diff --git a/py3.7/bin/activate b/py3.7/bin/activate deleted file mode 100644 index 1b1d7ee..0000000 --- a/py3.7/bin/activate +++ /dev/null @@ -1,76 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# you cannot run it directly - -deactivate () { - # 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 - 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="/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7" -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(py3.7) " != x ] ; then - PS1="(py3.7) ${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 - -# 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 -fi diff --git a/py3.7/bin/activate.csh b/py3.7/bin/activate.csh deleted file mode 100644 index 55e68a3..0000000 --- a/py3.7/bin/activate.csh +++ /dev/null @@ -1,37 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -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' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/bin:$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - if ("py3.7" != "") then - set env_name = "py3.7" - 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 - set prompt = "[$env_name] $prompt" - unset env_name -endif - -alias pydoc python -m pydoc - -rehash diff --git a/py3.7/bin/activate.fish b/py3.7/bin/activate.fish deleted file mode 100644 index 0e50e4e..0000000 --- a/py3.7/bin/activate.fish +++ /dev/null @@ -1,75 +0,0 @@ -# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org) -# 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" - functions -e fish_prompt - set -e _OLD_FISH_PROMPT_OVERRIDE - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - 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 "/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7" - -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. - - # save the current fish_prompt function as the function _old_fish_prompt - functions -c fish_prompt _old_fish_prompt - - # with the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command - set -l old_status $status - - # Prompt override? - if test -n "(py3.7) " - printf "%s%s" "(py3.7) " (set_color normal) - else - # ...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) - else - printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal) - end - end - - # Restore the return status of the previous command. - echo "exit $old_status" | . - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" -end diff --git a/py3.7/bin/easy_install b/py3.7/bin/easy_install deleted file mode 100755 index 074908b..0000000 --- a/py3.7/bin/easy_install +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- 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/py3.7/bin/easy_install-3.7 b/py3.7/bin/easy_install-3.7 deleted file mode 100755 index 074908b..0000000 --- a/py3.7/bin/easy_install-3.7 +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- 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/py3.7/bin/hypercorn b/py3.7/bin/hypercorn deleted file mode 100755 index b979803..0000000 --- a/py3.7/bin/hypercorn +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- coding: utf-8 -*- -import re -import sys - -from hypercorn.__main__ import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/py3.7/bin/pip b/py3.7/bin/pip deleted file mode 100755 index 04799ea..0000000 --- a/py3.7/bin/pip +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- 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/py3.7/bin/pip3 b/py3.7/bin/pip3 deleted file mode 100755 index 04799ea..0000000 --- a/py3.7/bin/pip3 +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- 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/py3.7/bin/pip3.7 b/py3.7/bin/pip3.7 deleted file mode 100755 index 04799ea..0000000 --- a/py3.7/bin/pip3.7 +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- 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/py3.7/bin/python b/py3.7/bin/python deleted file mode 120000 index 940bee3..0000000 --- a/py3.7/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3.7 \ No newline at end of file diff --git a/py3.7/bin/python3 b/py3.7/bin/python3 deleted file mode 120000 index 940bee3..0000000 --- a/py3.7/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -python3.7 \ No newline at end of file diff --git a/py3.7/bin/python3.7 b/py3.7/bin/python3.7 deleted file mode 120000 index f097b0e..0000000 --- a/py3.7/bin/python3.7 +++ /dev/null @@ -1 +0,0 @@ -/usr/bin/python3.7 \ No newline at end of file diff --git a/py3.7/bin/quart b/py3.7/bin/quart deleted file mode 100755 index a9f9037..0000000 --- a/py3.7/bin/quart +++ /dev/null @@ -1,11 +0,0 @@ -#!/home/vivek/Dev/RanchiMall/ranchimallflo-api/py3.7/bin/python3.7 - -# -*- coding: utf-8 -*- -import re -import sys - -from quart.cli import main - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/py3.7/lib/python3.7/site-packages/.libs_cffi_backend/libffi-d78936b1.so.6.0.4 b/py3.7/lib/python3.7/site-packages/.libs_cffi_backend/libffi-d78936b1.so.6.0.4 deleted file mode 100755 index 5f767a4..0000000 Binary files a/py3.7/lib/python3.7/site-packages/.libs_cffi_backend/libffi-d78936b1.so.6.0.4 and /dev/null differ diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/LICENSE.txt b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/LICENSE.txt deleted file mode 100644 index 87ce152..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,39 +0,0 @@ -Copyright © 2014 by the Pallets team. - -Some rights reserved. - -Redistribution and use in source and binary forms of the software as -well as documentation, with or without modification, are permitted -provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -- Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ----- - -Click uses parts of optparse written by Gregory P. Ward and maintained -by the Python Software Foundation. This is limited to code in parser.py. - -Copyright © 2001-2006 Gregory P. Ward. All rights reserved. -Copyright © 2002-2006 Python Software Foundation. All rights reserved. diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/METADATA deleted file mode 100644 index 625bdad..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/METADATA +++ /dev/null @@ -1,121 +0,0 @@ -Metadata-Version: 2.1 -Name: Click -Version: 7.0 -Summary: Composable command line interface toolkit -Home-page: https://palletsprojects.com/p/click/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: Pallets Team -Maintainer-email: contact@palletsprojects.com -License: BSD -Project-URL: Documentation, https://click.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/click -Project-URL: Issue tracker, https://github.com/pallets/click/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* - -\$ click\_ -========== - -Click is a Python package for creating beautiful command line interfaces -in a composable way with as little code as necessary. It's the "Command -Line Interface Creation Kit". It's highly configurable but comes with -sensible defaults out of the box. - -It aims to make the process of writing command line tools quick and fun -while also preventing any frustration caused by the inability to -implement an intended CLI API. - -Click in three points: - -- Arbitrary nesting of commands -- Automatic help page generation -- Supports lazy loading of subcommands at runtime - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - $ pip install click - -Click supports Python 3.4 and newer, Python 2.7, and PyPy. - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -A Simple Example ----------------- - -What does it look like? Here is an example of a simple Click program: - -.. code-block:: python - - import click - - @click.command() - @click.option("--count", default=1, help="Number of greetings.") - @click.option("--name", prompt="Your name", - help="The person to greet.") - def hello(count, name): - """Simple program that greets NAME for a total of COUNT times.""" - for _ in range(count): - click.echo("Hello, %s!" % name) - - if __name__ == '__main__': - hello() - -And what it looks like when run: - -.. code-block:: text - - $ python hello.py --count=3 - Your name: Click - Hello, Click! - Hello, Click! - Hello, Click! - - -Donate ------- - -The Pallets organization develops and supports Click and other popular -packages. In order to grow the community of contributors and users, and -allow the maintainers to devote more time to the projects, `please -donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -* Website: https://palletsprojects.com/p/click/ -* Documentation: https://click.palletsprojects.com/ -* License: `BSD `_ -* Releases: https://pypi.org/project/click/ -* Code: https://github.com/pallets/click -* Issue tracker: https://github.com/pallets/click/issues -* Test status: - - * Linux, Mac: https://travis-ci.org/pallets/click - * Windows: https://ci.appveyor.com/project/pallets/click - -* Test coverage: https://codecov.io/gh/pallets/click - - diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/RECORD deleted file mode 100644 index 027e7af..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/RECORD +++ /dev/null @@ -1,40 +0,0 @@ -Click-7.0.dist-info/LICENSE.txt,sha256=4hIxn676T0Wcisk3_chVcECjyrivKTZsoqSNI5AlIlw,1876 -Click-7.0.dist-info/METADATA,sha256=-r8jeke3Zer4diRvT1MjFZuiJ6yTT_qFP39svLqdaLI,3516 -Click-7.0.dist-info/RECORD,, -Click-7.0.dist-info/WHEEL,sha256=gduuPyBvFJQSQ0zdyxF7k0zynDXbIbvg5ZBHoXum5uk,110 -Click-7.0.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 -click/__init__.py,sha256=HjGThQ7tef9kkwCV371TBnrf0SAi6fKfU_jtEnbYTvQ,2789 -click/_bashcomplete.py,sha256=iaNUmtxag0YPfxba3TDYCNietiTMQIrvhRLj-H8okFU,11014 -click/_compat.py,sha256=vYmvoj4opPxo-c-2GMQQjYT_r_QkOKybkfGoeVrt0dA,23399 -click/_termui_impl.py,sha256=xHmLtOJhKUCVD6168yucJ9fknUJPAMs0eUTPgVUO-GQ,19611 -click/_textwrap.py,sha256=gwS4m7bdQiJnzaDG8osFcRb-5vn4t4l2qSCy-5csCEc,1198 -click/_unicodefun.py,sha256=QHy2_5jYlX-36O-JVrTHNnHOqg8tquUR0HmQFev7Ics,4364 -click/_winconsole.py,sha256=PPWVak8Iikm_gAPsxMrzwsVFCvHgaW3jPaDWZ1JBl3U,8965 -click/core.py,sha256=q8FLcDZsagBGSRe5Y9Hi_FGvAeZvusNfoO5EkhkSQ8Y,75305 -click/decorators.py,sha256=idKt6duLUUfAFftrHoREi8MJSd39XW36pUVHthdglwk,11226 -click/exceptions.py,sha256=CNpAjBAE7qjaV4WChxQeak95e5yUOau8AsvT-8m6wss,7663 -click/formatting.py,sha256=eh-cypTUAhpI3HD-K4ZpR3vCiURIO62xXvKkR3tNUTM,8889 -click/globals.py,sha256=oQkou3ZQ5DgrbVM6BwIBirwiqozbjfirzsLGAlLRRdg,1514 -click/parser.py,sha256=m-nGZz4VwprM42_qtFlWFGo7yRJQxkBlRcZodoH593Y,15510 -click/termui.py,sha256=o_ZXB2jyvL2Rce7P_bFGq452iyBq9ykJyRApIPMCZO0,23207 -click/testing.py,sha256=aYGqY_iWLu2p4k7lkuJ6t3fqpf6aPGqTsyLzNY_ngKg,13062 -click/types.py,sha256=2Q929p-aBP_ZYuMFJqJR-Ipucofv3fmDc5JzBDPmzJU,23287 -click/utils.py,sha256=6-D0WkAxvv9FkgHXSHwDIv0l9Gdx9Mm6Z5vuKNLIfZI,15763 -Click-7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click/__pycache__/_textwrap.cpython-37.pyc,, -click/__pycache__/_winconsole.cpython-37.pyc,, -click/__pycache__/__init__.cpython-37.pyc,, -click/__pycache__/_unicodefun.cpython-37.pyc,, -click/__pycache__/exceptions.cpython-37.pyc,, -click/__pycache__/termui.cpython-37.pyc,, -click/__pycache__/globals.cpython-37.pyc,, -click/__pycache__/_bashcomplete.cpython-37.pyc,, -click/__pycache__/_termui_impl.cpython-37.pyc,, -click/__pycache__/formatting.cpython-37.pyc,, -click/__pycache__/decorators.cpython-37.pyc,, -click/__pycache__/types.cpython-37.pyc,, -click/__pycache__/utils.cpython-37.pyc,, -click/__pycache__/_compat.cpython-37.pyc,, -click/__pycache__/parser.cpython-37.pyc,, -click/__pycache__/testing.cpython-37.pyc,, -click/__pycache__/core.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/WHEEL deleted file mode 100644 index 1316c41..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.31.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/top_level.txt deleted file mode 100644 index dca9a90..0000000 --- a/py3.7/lib/python3.7/site-packages/Click-7.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -click diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/LICENSE deleted file mode 100644 index 8a5dad9..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright P G Jones 2018. - -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. diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/METADATA deleted file mode 100644 index 93aadb1..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/METADATA +++ /dev/null @@ -1,121 +0,0 @@ -Metadata-Version: 2.1 -Name: Hypercorn -Version: 0.6.0 -Summary: A ASGI Server based on Hyper libraries and inspired by Gunicorn. -Home-page: https://gitlab.com/pgjones/hypercorn/ -Author: P G Jones -Author-email: philip.graham.jones@googlemail.com -License: MIT -Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=3.7 -Requires-Dist: h11 -Requires-Dist: h2 (>=3.1.0) -Requires-Dist: pytoml -Requires-Dist: typing-extensions -Requires-Dist: wsproto (>=0.14.0) -Provides-Extra: trio -Requires-Dist: trio (>=0.9.0) ; extra == 'trio' -Provides-Extra: uvloop -Requires-Dist: uvloop ; extra == 'uvloop' - -Hypercorn -========= - -.. image:: https://assets.gitlab-static.net/pgjones/hypercorn/raw/master/artwork/logo.png - :alt: Hypercorn logo - -|Build Status| |docs| |pypi| |http| |python| |license| - -Hypercorn is an `ASGI -`_ web -server based on the sans-io hyper, `h11 -`_, `h2 -`_, and `wsproto -`_ libraries and inspired by -Gunicorn. Hypercorn supports HTTP/1, HTTP/2, WebSockets (over HTTP/1 -and HTTP/2), ASGI/2, and ASGI/3 specifications. Hypercorn can utilise -asyncio, uvloop, or trio worker types. - -Hypercorn was initially part of `Quart -`_ before being separated out into a -standalone ASGI server. Hypercorn forked from version 0.5.0 of Quart. - -Quickstart ----------- - -Hypercorn can be installed via `pipenv -`_ or -`pip `_, - -.. code-block:: console - - $ pipenv install hypercorn - $ pip install hypercorn - -and requires Python 3.7.0 or higher. - -With hypercorn installed ASGI frameworks (or apps) can be served via -Hypercorn via the command line, - -.. code-block:: console - - $ hypercorn module:app - -Contributing ------------- - -Hypercorn is developed on `GitLab -`_. You are very welcome to open -`issues `_ or propose -`merge requests -`_. - -Testing -~~~~~~~ - -The best way to test Hypercorn is with Tox, - -.. code-block:: console - - $ pipenv install tox - $ tox - -this will check the code style and run the tests. - -Help ----- - -The Hypercorn `documentation `_ -is the best place to start, after that try opening an `issue -`_. - - -.. |Build Status| image:: https://gitlab.com/pgjones/hypercorn/badges/master/build.svg - :target: https://gitlab.com/pgjones/hypercorn/commits/master - -.. |docs| image:: https://img.shields.io/badge/docs-passing-brightgreen.svg - :target: https://pgjones.gitlab.io/hypercorn/ - -.. |pypi| image:: https://img.shields.io/pypi/v/hypercorn.svg - :target: https://pypi.python.org/pypi/Hypercorn/ - -.. |http| image:: https://img.shields.io/badge/http-1.0,1.1,2-orange.svg - :target: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol - -.. |python| image:: https://img.shields.io/pypi/pyversions/hypercorn.svg - :target: https://pypi.python.org/pypi/Hypercorn/ - -.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg - :target: https://gitlab.com/pgjones/hypercorn/blob/master/LICENSE - - diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/RECORD deleted file mode 100644 index 777895c..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/RECORD +++ /dev/null @@ -1,67 +0,0 @@ -hypercorn/__about__.py,sha256=cID1jLnC_vj48GgMN6Yb1FA3JsQ95zNmCHmRYE8TFhY,22 -hypercorn/__init__.py,sha256=ZBbFBwpZeEyk7_9xleLlt7KqM48wYv7kjY2we02gsqs,99 -hypercorn/__main__.py,sha256=MzspS5zwF0qZngY9HjZJ2oLlVE3lCWnj9CzH9L4WKxo,6633 -hypercorn/config.py,sha256=i5Fuz2LHpBjA-FVSCIOoZGCtG_9vLlvXVD1PFlIArpc,10379 -hypercorn/logging.py,sha256=Hav6-fjJNdoJPcA6X6_sC0JvOeKpdAWZOTG2UHBZmwY,3162 -hypercorn/middleware.py,sha256=z_JHBpe9Nr0UAqTcRhBgIByuo9S3ghJDWoVG-SE5qE8,2153 -hypercorn/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 -hypercorn/run.py,sha256=PUnAfyM_zw_rFNEWmnQDM1IIG_H9K4uwAheIvJTgefo,2247 -hypercorn/typing.py,sha256=shZHhDx96LCGUdIkSbytHgOwJXp6BNcwMUyXFncidAs,1740 -hypercorn/utils.py,sha256=H3c5HkFuMBnKZd97HhiLVluqBlQwjphihKFEvuy0SAM,5326 -hypercorn/asgi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -hypercorn/asgi/h11.py,sha256=jVYfPOQxrywiamZ4xJ9M-q2tRl7qTyPdCoADlipbGZ4,5968 -hypercorn/asgi/h2.py,sha256=jCxLwcu7kPaUfvOtkbGXx024-OYf3TLkNvEPGhGH0Yc,12201 -hypercorn/asgi/run.py,sha256=nnyM2FjSKgaYLoFGwBjZ_7A1MOYEapBuDlt1vLUCKSY,374 -hypercorn/asgi/utils.py,sha256=p458ox4XpvAeVCsEfj7y7qoA4BGOiGJVnGX2Mbe6_pg,2253 -hypercorn/asgi/wsproto.py,sha256=TYwXiDc8NwPYV-H_15Lrv-reoaYKHrXNqYdgMFIY66E,6757 -hypercorn/asyncio/__init__.py,sha256=Kn-AmsRLLz8QvvslwadnL0jRYPfAsNflGvh7NoVYGEE,962 -hypercorn/asyncio/base.py,sha256=mJ05MB4o-o-elKKwhJCzfQcHz1vVCSlggpChwtgJC7k,2624 -hypercorn/asyncio/h11.py,sha256=FFY8WzCheeVjBAwEROeEMer5WRQdjGVQrgULBNReKoM,4731 -hypercorn/asyncio/h2.py,sha256=9F1TvXyPVRuNJo1JE1GJnhiGFeGk8xNbvjXoeR3TlAs,13460 -hypercorn/asyncio/lifespan.py,sha256=_kcahg5zVMjoeH3xVV9z2fM5eW0rYDYycRuGWhVYaRo,2766 -hypercorn/asyncio/run.py,sha256=AtIs2ZWp5koRQ-TVANYwf_fxAAoJAS-6MTFqUPdxHmQ,7989 -hypercorn/asyncio/wsproto.py,sha256=R6xZXeUETpoMnhJUfBUJni1vKpekQwiQbLmyc1sSVxw,3871 -hypercorn/trio/__init__.py,sha256=ec0TRgtNXyQhG0zuW8RLGfe-FSD0H1777XBzFTYpf3s,1097 -hypercorn/trio/base.py,sha256=c1GifLedS9VD7Rxr-Sb2dV4iCGzp_R0S8i6yEiX2IMU,1008 -hypercorn/trio/h11.py,sha256=FGB-qp3KAAEg4aTbH5GJd-UFXBbfAKkZeAMhdhu78dc,5246 -hypercorn/trio/h2.py,sha256=GNOYS3XoO7GEAotlLPy-4LbHUV4o06lGdPWVEOGu_Qs,13869 -hypercorn/trio/lifespan.py,sha256=5J4JPeNv4AQUPmDh5r3VSWmlaF6QPVJut2SxL0soHk8,2770 -hypercorn/trio/run.py,sha256=29AbhZtT3bjQVqk7zd44WhN8SE6YZaan7CHZBKD7uJ0,4348 -hypercorn/trio/wsproto.py,sha256=il7x1MeedcUCEuNRKmcTbPdQcbgmfF79mhgaLQzewF0,3975 -Hypercorn-0.6.0.dist-info/LICENSE,sha256=HjGdhzPYNEZ3zQ7mwqjMBgHHRId5HViyayt-8GMMK38,1050 -Hypercorn-0.6.0.dist-info/METADATA,sha256=PF7MqztPVvNxMQylxtkonLI9dGbAAI21fOlPgB1AmO0,3850 -Hypercorn-0.6.0.dist-info/WHEEL,sha256=_NOXIqFgOaYmlm9RJLPQZ13BJuEIrp5jx5ptRD5uh3Y,92 -Hypercorn-0.6.0.dist-info/entry_points.txt,sha256=HV9e4tNKTeIJbe1PIswRWGn4jbCUQqfIbcAIV68Znuk,55 -Hypercorn-0.6.0.dist-info/top_level.txt,sha256=zSgQlh13xK80SFqsUPaG5-83qTJOzqYTBfP9XFcvB_Y,10 -Hypercorn-0.6.0.dist-info/RECORD,, -../../../bin/hypercorn,sha256=LFJdz3vcyldlmTu6u3n-R3aH1cs2Kpod6-1oXIbzTlc,269 -Hypercorn-0.6.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hypercorn/asyncio/__pycache__/base.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/run.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/__init__.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/h2.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/h11.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/wsproto.cpython-37.pyc,, -hypercorn/asyncio/__pycache__/lifespan.cpython-37.pyc,, -hypercorn/asgi/__pycache__/run.cpython-37.pyc,, -hypercorn/asgi/__pycache__/__init__.cpython-37.pyc,, -hypercorn/asgi/__pycache__/h2.cpython-37.pyc,, -hypercorn/asgi/__pycache__/utils.cpython-37.pyc,, -hypercorn/asgi/__pycache__/h11.cpython-37.pyc,, -hypercorn/asgi/__pycache__/wsproto.cpython-37.pyc,, -hypercorn/__pycache__/run.cpython-37.pyc,, -hypercorn/__pycache__/typing.cpython-37.pyc,, -hypercorn/__pycache__/__init__.cpython-37.pyc,, -hypercorn/__pycache__/__main__.cpython-37.pyc,, -hypercorn/__pycache__/utils.cpython-37.pyc,, -hypercorn/__pycache__/__about__.cpython-37.pyc,, -hypercorn/__pycache__/config.cpython-37.pyc,, -hypercorn/__pycache__/middleware.cpython-37.pyc,, -hypercorn/__pycache__/logging.cpython-37.pyc,, -hypercorn/trio/__pycache__/base.cpython-37.pyc,, -hypercorn/trio/__pycache__/run.cpython-37.pyc,, -hypercorn/trio/__pycache__/__init__.cpython-37.pyc,, -hypercorn/trio/__pycache__/h2.cpython-37.pyc,, -hypercorn/trio/__pycache__/h11.cpython-37.pyc,, -hypercorn/trio/__pycache__/wsproto.cpython-37.pyc,, -hypercorn/trio/__pycache__/lifespan.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/WHEEL deleted file mode 100644 index 4eeaea1..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.32.3) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/entry_points.txt b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/entry_points.txt deleted file mode 100644 index d9c53b5..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -hypercorn = hypercorn.__main__:main - diff --git a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/top_level.txt deleted file mode 100644 index 083a5e9..0000000 --- a/py3.7/lib/python3.7/site-packages/Hypercorn-0.6.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hypercorn diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/LICENSE deleted file mode 100644 index 10145a2..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Copyright (c) 2009 by the Jinja Team, see AUTHORS for more details. - -Some rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/METADATA deleted file mode 100644 index fb4a867..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/METADATA +++ /dev/null @@ -1,67 +0,0 @@ -Metadata-Version: 2.1 -Name: Jinja2 -Version: 2.10.1 -Summary: A small but fast and easy to use stand-alone template engine written in pure python. -Home-page: http://jinja.pocoo.org/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -License: BSD -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -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.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Requires-Dist: MarkupSafe (>=0.23) -Provides-Extra: i18n -Requires-Dist: Babel (>=0.8) ; extra == 'i18n' - - -Jinja2 -~~~~~~ - -Jinja2 is a template engine written in pure Python. It provides a -`Django`_ inspired non-XML syntax but supports inline expressions and -an optional `sandboxed`_ environment. - -Nutshell --------- - -Here a small example of a Jinja template:: - - {% extends 'base.html' %} - {% block title %}Memberlist{% endblock %} - {% block content %} - - {% endblock %} - -Philosophy ----------- - -Application logic is for the controller but don't try to make the life -for the template designer too hard by giving him too few functionality. - -For more informations visit the new `Jinja2 webpage`_ and `documentation`_. - -.. _sandboxed: https://en.wikipedia.org/wiki/Sandbox_(computer_security) -.. _Django: https://www.djangoproject.com/ -.. _Jinja2 webpage: http://jinja.pocoo.org/ -.. _documentation: http://jinja.pocoo.org/2/documentation/ - - diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/RECORD deleted file mode 100644 index 4e64a7e..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/RECORD +++ /dev/null @@ -1,61 +0,0 @@ -jinja2/__init__.py,sha256=V1D-JHQKklZseXOMA-uAW7-BeKe_TfPpOFi9-dV04ZA,2616 -jinja2/_compat.py,sha256=xP60CE5Qr8FTYcDE1f54tbZLKGvMwYml4-8T7Q4KG9k,2596 -jinja2/_identifier.py,sha256=W1QBSY-iJsyt6oR_nKSuNNCzV95vLIOYgUNPUI1d5gU,1726 -jinja2/asyncfilters.py,sha256=cTDPvrS8Hp_IkwsZ1m9af_lr5nHysw7uTa5gV0NmZVE,4144 -jinja2/asyncsupport.py,sha256=UErQ3YlTLaSjFb94P4MVn08-aVD9jJxty2JVfMRb-1M,7878 -jinja2/bccache.py,sha256=nQldx0ZRYANMyfvOihRoYFKSlUdd5vJkS7BjxNwlOZM,12794 -jinja2/compiler.py,sha256=BqC5U6JxObSRhblyT_a6Tp5GtEU5z3US1a4jLQaxxgo,65386 -jinja2/constants.py,sha256=uwwV8ZUhHhacAuz5PTwckfsbqBaqM7aKfyJL7kGX5YQ,1626 -jinja2/debug.py,sha256=WTVeUFGUa4v6ReCsYv-iVPa3pkNB75OinJt3PfxNdXs,12045 -jinja2/defaults.py,sha256=Em-95hmsJxIenDCZFB1YSvf9CNhe9rBmytN3yUrBcWA,1400 -jinja2/environment.py,sha256=VnkAkqw8JbjZct4tAyHlpBrka2vqB-Z58RAP-32P1ZY,50849 -jinja2/exceptions.py,sha256=_Rj-NVi98Q6AiEjYQOsP8dEIdu5AlmRHzcSNOPdWix4,4428 -jinja2/ext.py,sha256=atMQydEC86tN1zUsdQiHw5L5cF62nDbqGue25Yiu3N4,24500 -jinja2/filters.py,sha256=yOAJk0MsH-_gEC0i0U6NweVQhbtYaC-uE8xswHFLF4w,36528 -jinja2/idtracking.py,sha256=2GbDSzIvGArEBGLkovLkqEfmYxmWsEf8c3QZwM4uNsw,9197 -jinja2/lexer.py,sha256=ySEPoXd1g7wRjsuw23uimS6nkGN5aqrYwcOKxCaVMBQ,28559 -jinja2/loaders.py,sha256=xiTuURKAEObyym0nU8PCIXu_Qp8fn0AJ5oIADUUm-5Q,17382 -jinja2/meta.py,sha256=fmKHxkmZYAOm9QyWWy8EMd6eefAIh234rkBMW2X4ZR8,4340 -jinja2/nativetypes.py,sha256=_sJhS8f-8Q0QMIC0dm1YEdLyxEyoO-kch8qOL5xUDfE,7308 -jinja2/nodes.py,sha256=L10L_nQDfubLhO3XjpF9qz46FSh2clL-3e49ogVlMmA,30853 -jinja2/optimizer.py,sha256=MsdlFACJ0FRdPtjmCAdt7JQ9SGrXFaDNUaslsWQaG3M,1722 -jinja2/parser.py,sha256=lPzTEbcpTRBLw8ii6OYyExHeAhaZLMA05Hpv4ll3ULk,35875 -jinja2/runtime.py,sha256=DHdD38Pq8gj7uWQC5usJyWFoNWL317A9AvXOW_CLB34,27755 -jinja2/sandbox.py,sha256=UmX8hVjdaERCbA3RXBwrV1f-beA23KmijG5kzPJyU4A,17106 -jinja2/tests.py,sha256=iJQLwbapZr-EKquTG_fVOVdwHUUKf3SX9eNkjQDF8oU,4237 -jinja2/utils.py,sha256=q24VupGZotQ-uOyrJxCaXtDWhZC1RgsQG7kcdmjck2Q,20629 -jinja2/visitor.py,sha256=JD1H1cANA29JcntFfN5fPyqQxB4bI4wC00BzZa-XHks,3316 -Jinja2-2.10.1.dist-info/LICENSE,sha256=JvzUNv3Io51EiWrAPm8d_SXjhJnEjyDYvB3Tvwqqils,1554 -Jinja2-2.10.1.dist-info/METADATA,sha256=rx0eN8lX8iq8-YVppmCzV1Qx4y3Pj9IWi08mXUCrewI,2227 -Jinja2-2.10.1.dist-info/WHEEL,sha256=HX-v9-noUkyUoxyZ1PMSuS7auUxDAR4VBdoYLqD0xws,110 -Jinja2-2.10.1.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72 -Jinja2-2.10.1.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 -Jinja2-2.10.1.dist-info/RECORD,, -Jinja2-2.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -jinja2/__pycache__/tests.cpython-37.pyc,, -jinja2/__pycache__/optimizer.cpython-37.pyc,, -jinja2/__pycache__/filters.cpython-37.pyc,, -jinja2/__pycache__/asyncsupport.cpython-37.pyc,, -jinja2/__pycache__/defaults.cpython-37.pyc,, -jinja2/__pycache__/__init__.cpython-37.pyc,, -jinja2/__pycache__/_identifier.cpython-37.pyc,, -jinja2/__pycache__/exceptions.cpython-37.pyc,, -jinja2/__pycache__/sandbox.cpython-37.pyc,, -jinja2/__pycache__/ext.cpython-37.pyc,, -jinja2/__pycache__/environment.cpython-37.pyc,, -jinja2/__pycache__/loaders.cpython-37.pyc,, -jinja2/__pycache__/bccache.cpython-37.pyc,, -jinja2/__pycache__/nodes.cpython-37.pyc,, -jinja2/__pycache__/debug.cpython-37.pyc,, -jinja2/__pycache__/idtracking.cpython-37.pyc,, -jinja2/__pycache__/visitor.cpython-37.pyc,, -jinja2/__pycache__/utils.cpython-37.pyc,, -jinja2/__pycache__/lexer.cpython-37.pyc,, -jinja2/__pycache__/_compat.cpython-37.pyc,, -jinja2/__pycache__/nativetypes.cpython-37.pyc,, -jinja2/__pycache__/constants.cpython-37.pyc,, -jinja2/__pycache__/runtime.cpython-37.pyc,, -jinja2/__pycache__/meta.cpython-37.pyc,, -jinja2/__pycache__/parser.cpython-37.pyc,, -jinja2/__pycache__/asyncfilters.cpython-37.pyc,, -jinja2/__pycache__/compiler.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/WHEEL deleted file mode 100644 index c8240f0..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/entry_points.txt b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/entry_points.txt deleted file mode 100644 index 32e6b75..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/entry_points.txt +++ /dev/null @@ -1,4 +0,0 @@ - - [babel.extractors] - jinja2 = jinja2.ext:babel_extract[i18n] - \ No newline at end of file diff --git a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/top_level.txt deleted file mode 100644 index 7f7afbf..0000000 --- a/py3.7/lib/python3.7/site-packages/Jinja2-2.10.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -jinja2 diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt deleted file mode 100644 index 9d227a0..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.txt +++ /dev/null @@ -1,28 +0,0 @@ -Copyright 2010 Pallets - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA deleted file mode 100644 index b208d93..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/METADATA +++ /dev/null @@ -1,103 +0,0 @@ -Metadata-Version: 2.1 -Name: MarkupSafe -Version: 1.1.1 -Summary: Safely add untrusted strings to HTML/XML markup. -Home-page: https://palletsprojects.com/p/markupsafe/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: The Pallets Team -Maintainer-email: contact@palletsprojects.com -License: BSD-3-Clause -Project-URL: Documentation, https://markupsafe.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/markupsafe -Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* - -MarkupSafe -========== - -MarkupSafe implements a text object that escapes characters so it is -safe to use in HTML and XML. Characters that have special meanings are -replaced so that they display as the actual characters. This mitigates -injection attacks, meaning untrusted user input can safely be displayed -on a page. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U MarkupSafe - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -Examples --------- - -.. code-block:: pycon - - >>> from markupsafe import Markup, escape - >>> # escape replaces special characters and wraps in Markup - >>> escape('') - Markup(u'<script>alert(document.cookie);</script>') - >>> # wrap in Markup to mark text "safe" and prevent escaping - >>> Markup('Hello') - Markup('hello') - >>> escape(Markup('Hello')) - Markup('hello') - >>> # Markup is a text subclass (str on Python 3, unicode on Python 2) - >>> # methods and operators escape their arguments - >>> template = Markup("Hello %s") - >>> template % '"World"' - Markup('Hello "World"') - - -Donate ------- - -The Pallets organization develops and supports MarkupSafe and other -libraries that use it. In order to grow the community of contributors -and users, and allow the maintainers to devote more time to the -projects, `please donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -* Website: https://palletsprojects.com/p/markupsafe/ -* Documentation: https://markupsafe.palletsprojects.com/ -* License: `BSD-3-Clause `_ -* Releases: https://pypi.org/project/MarkupSafe/ -* Code: https://github.com/pallets/markupsafe -* Issue tracker: https://github.com/pallets/markupsafe/issues -* Test status: - - * Linux, Mac: https://travis-ci.org/pallets/markupsafe - * Windows: https://ci.appveyor.com/project/pallets/markupsafe - -* Test coverage: https://codecov.io/gh/pallets/markupsafe - - diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD deleted file mode 100644 index 84d0824..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/RECORD +++ /dev/null @@ -1,16 +0,0 @@ -MarkupSafe-1.1.1.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 -MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 -MarkupSafe-1.1.1.dist-info/RECORD,, -MarkupSafe-1.1.1.dist-info/METADATA,sha256=nJHwJ4_4ka-V39QH883jPrslj6inNdyyNASBXbYgHXQ,3570 -MarkupSafe-1.1.1.dist-info/WHEEL,sha256=AhV6RMqZ2IDfreRJKo44QWYxYeP-0Jr0bezzBLQ1eog,109 -markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690 -markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558 -markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873 -markupsafe/_speedups.cpython-37m-x86_64-linux-gnu.so,sha256=pz-ucGdAq6kJtq9lEY1kY2Ed6LQjbRrIicdu_i4HFqU,38875 -markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126 -markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884 -MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -markupsafe/__pycache__/_native.cpython-37.pyc,, -markupsafe/__pycache__/__init__.cpython-37.pyc,, -markupsafe/__pycache__/_constants.cpython-37.pyc,, -markupsafe/__pycache__/_compat.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL deleted file mode 100644 index 697e432..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.31.1) -Root-Is-Purelib: false -Tag: cp37-cp37m-manylinux1_x86_64 - diff --git a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt deleted file mode 100644 index 75bf729..0000000 --- a/py3.7/lib/python3.7/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -markupsafe diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/LICENSE deleted file mode 100644 index 6417781..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright P G Jones 2017. - -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. diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/METADATA deleted file mode 100644 index ba9ccbc..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/METADATA +++ /dev/null @@ -1,186 +0,0 @@ -Metadata-Version: 2.1 -Name: Quart -Version: 0.9.1 -Summary: A Python ASGI web microframework with the same API as Flask -Home-page: https://gitlab.com/pgjones/quart/ -Author: P G Jones -Author-email: philip.graham.jones@googlemail.com -License: MIT -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=3.7.0 -Requires-Dist: aiofiles -Requires-Dist: blinker -Requires-Dist: click -Requires-Dist: hypercorn (>=0.6.0) -Requires-Dist: itsdangerous -Requires-Dist: jinja2 -Requires-Dist: multidict -Requires-Dist: sortedcontainers -Provides-Extra: dotenv -Requires-Dist: python-dotenv ; extra == 'dotenv' - -Quart -===== - -.. image:: https://assets.gitlab-static.net/pgjones/quart/raw/master/artwork/logo.png - :alt: Quart logo - -|Build Status| |docs| |pypi| |http| |python| |license| |chat| - -Quart is a Python `ASGI -`_ web -microframework. It is intended to provide the easiest way to use -asyncio functionality in a web context, especially with existing Flask -apps. This is possible as the Quart API is a superset of the `Flask -`_ API. - -Quart aims to be a complete web microframework, as it supports -HTTP/1.1, HTTP/2 and websockets. Quart is very extendable and has a -number of known `extensions -`_ and works -with many of the `Flask extensions -`_. - -Quickstart ----------- - -Quart can be installed via `pipenv -`_ or -`pip `_, - -.. code-block:: console - - $ pipenv install quart - $ pip install quart - -and requires Python 3.7.0 or higher (see `python version support -`_ for -reasoning). - -A minimal Quart example is, - -.. code-block:: python - - from quart import Quart, websocket - - app = Quart(__name__) - - @app.route('/') - async def hello(): - return 'hello' - - @app.websocket('/ws') - async def ws(): - while True: - await websocket.send('hello') - - app.run() - -if the above is in a file called ``app.py`` it can be run as, - -.. code-block:: console - - $ python app.py - -To deploy in a production setting see the `deployment -`_ documentation. - -Features --------- - -Quart supports the full ASGI 3.0 specification as well as the -websocket response and HTTP/2 server push extensions. For those of you -familiar with Flask, Quart extends the Flask-API by adding support for, - -- HTTP/1.1 request streaming. -- Websockets. -- HTTP/2 server push. - -Note that not all ASGI servers support these features, for this reason -the recommended server is `Hypercorn -`_. - -Contributing ------------- - -Quart is developed on `GitLab `_. If -you come across an issue, or have a feature request please open an -`issue `_. If you want to -contribute a fix or the feature-implementation please do (typo fixes -welcome), by proposing a `merge request -`_. - -Testing -~~~~~~~ - -The best way to test Quart is with `Tox -`_, - -.. code-block:: console - - $ pipenv install tox - $ tox - -this will check the code style and run the tests. - -Help ----- - -The Quart `documentation `_ is the -best place to start, after that try searching `stack overflow -`_, if you still -can't find an answer please `open an issue -`_. - -API Compatibility with Flask ----------------------------- - -The Flask API can be described as consisting of the Flask public and -private APIs and Werkzeug upon which Flask is based. Quart is designed -to be fully compatible with the Flask public API (aside from async and -await keywords). Thereafter the aim is to be mostly compatible with -the Flask private API and to provide no guarantees about the Werkzeug -API. - -Migrating from Flask -~~~~~~~~~~~~~~~~~~~~ - -It should be possible to migrate to Quart from Flask by a find and -replace of ``flask`` to ``quart`` and then adding ``async`` and -``await`` keywords. See the `docs -`_ for full -details. - - -.. |Build Status| image:: https://gitlab.com/pgjones/quart/badges/master/build.svg - :target: https://gitlab.com/pgjones/quart/commits/master - -.. |docs| image:: https://img.shields.io/badge/docs-passing-brightgreen.svg - :target: https://pgjones.gitlab.io/quart/ - -.. |pypi| image:: https://img.shields.io/pypi/v/quart.svg - :target: https://pypi.python.org/pypi/Quart/ - -.. |http| image:: https://img.shields.io/badge/http-1.0,1.1,2-orange.svg - :target: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol - -.. |python| image:: https://img.shields.io/pypi/pyversions/quart.svg - :target: https://pypi.python.org/pypi/Quart/ - -.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg - :target: https://gitlab.com/pgjones/quart/blob/master/LICENSE - -.. |chat| image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg - :target: https://gitter.im/python-quart/lobby - - diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/RECORD deleted file mode 100644 index 62ea6c5..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/RECORD +++ /dev/null @@ -1,81 +0,0 @@ -quart/__about__.py,sha256=pF8TnH2QJF8nfDmcD7oPTrAOnioy05dV4YmYDzkT5Es,22 -quart/__init__.py,sha256=Gu4uRD6CcFFNIwRyNq8BhRurECW5rKZjlSx0iCZCdlI,2300 -quart/__main__.py,sha256=2wjJPPid_ntwG6Esmk2lxRLj3ABV1Nsdj3u1jB8jHlo,78 -quart/app.py,sha256=clYFulW16lUBkx1HA4XjdRy1sOH-RAqJJt9Ofisxm38,67485 -quart/asgi.py,sha256=s8NIepR1tWcI4EtRoQ7NxEp4-MzY3Lw-AyaWpDa6BpE,9155 -quart/blueprints.py,sha256=L84JZgJHRbEcGWyFh56GUoylfoJja3DMvG9syDYCcbk,27437 -quart/cli.py,sha256=UyTFFHV0s57sCLmP4SAMK-yODocQaMipSmDlTSM2PcY,7142 -quart/config.py,sha256=zD68vWwt0D6noT71HjOGSUfg49OFl9vJQcwROobaEv4,8934 -quart/ctx.py,sha256=oFlO2JOb-DSvRUf3gQ4NKRzZEuKKSCZN9Q053YCTTMg,12731 -quart/datastructures.py,sha256=DVGHRufsyfJ9kIXqz23SNzYjLAjssboaHceATAmVVm4,22533 -quart/debug.py,sha256=TyvwRVvRQo4n8V9PCqkJy7cDvfy3ng3jZqo5s2JtJ2c,2134 -quart/exceptions.py,sha256=G0VSvzwBg7vqodTPwJ9K0puNW3PrJd_bjazPzGKqxBg,4623 -quart/globals.py,sha256=-BVKmsWrv8oiGAvL6M8m4uskcHY6T-q8JzvfpdFqV9c,932 -quart/helpers.py,sha256=aLNikvOz957vHhPQl9A8EB9qvMYTWfh8xnxQDAJ_pRc,8267 -quart/local.py,sha256=SmntnfS5ddHPwdZJNhXvwAt6qZsizMlWsuuO4HIcAos,7575 -quart/logging.py,sha256=h8WqcY0MWkcqwdibHlpH88Ny8hPC2gq5RosUho8BatM,1119 -quart/py.typed,sha256=sow9soTwP9T_gEAQSVh7Gb8855h04Nwmhs2We-JRgZM,7 -quart/routing.py,sha256=qNqpsQQpoZSbdbv7ML3GVoU04Tx94d-H4RVVd8AjIq4,17723 -quart/sessions.py,sha256=paH1ghIFvOfo5wbdhWp9etcl0PgRga8NMTvKqjBP1K0,9338 -quart/signals.py,sha256=l8CdOTQ135Xgbua6ky3-TV9PXtkW26OWB1SNmgBvtDI,4287 -quart/static.py,sha256=kwnwbQHmHhaoZiFJXtj3xwTVNB2MvlCPgeYNGuS1GNk,7793 -quart/templating.py,sha256=xHs_dkOQFqJngeF0Jic222ikLzz1vJeMj4Dv2i7KpC8,4094 -quart/testing.py,sha256=QbxQ6-qCRU5mK8_FB4kOP-tapZIw42a1aYabNFQpzsA,12151 -quart/typing.py,sha256=bpWOAUeZex7egCqWFWqMwlN6gQcQkbzAbZ7fifgnML0,584 -quart/utils.py,sha256=d5GWS65NTSEqsGCuG-_ul1-MaIRBgbxTS7YVWr_opM8,2563 -quart/views.py,sha256=yxFzsQOOe0Qqwex-edvHIq82KL7DyPSPplxY_ZLJEQo,3607 -quart/flask_patch/__init__.py,sha256=EIoGwAjBtdf7zl7nsqiGmbrSv0DaIgYpOAIy-45Cbr8,2386 -quart/flask_patch/_patch.py,sha256=9Y1bMwhegppMAHmfzEzjECswCD_1uhpgUv1QAoB7NNY,4204 -quart/flask_patch/_synchronise.py,sha256=N92QngWDVmcjUzsLu9gpZRvmD6CkhDbdtPCDj6VdeCA,745 -quart/flask_patch/app.py,sha256=NiOxxNEWXUDJj3sZ_JoI1TFkQ_pjKC-tkuFt2yJ_OnI,1549 -quart/flask_patch/globals.py,sha256=nZg3s011InLpOieWsKHvnd6188W0Y0iD5w1TDCjPFfc,1094 -quart/json/__init__.py,sha256=V3J1xTzrZlR_dTIM3dim8yz_KeAN_7GqU56qkncwhPE,3175 -quart/json/tag.py,sha256=pl8NCClWogDVf11ml7mWFCFn_5onIz6xS-WPLG0LN58,4848 -quart/wrappers/__init__.py,sha256=_HbJz3YMG0hgCHSlQTH9Vh_R56CxOSDnWTD6H6ElM_8,222 -quart/wrappers/_base.py,sha256=QwqWEPOfxq0G9WBz-qUCFM6pLJriVM40Hr-22fa4RM4,11959 -quart/wrappers/request.py,sha256=GN6d1eo9jQsiOWH4tLNdRfwnqW9q-iO0UaAFzuPIoBc,12174 -quart/wrappers/response.py,sha256=hjN7y1Lw1vVgZkq0d5BnNJZr67AjilFYY-MO18YEy4w,21520 -Quart-0.9.1.dist-info/LICENSE,sha256=QtV1hUGogaFLFjgCXcQFOnFPxTkLUcwY43VJ6DXJKSg,1050 -Quart-0.9.1.dist-info/METADATA,sha256=mpxIYbztSHzDkMlpvkRD1qd8p4V0iQTKGYMkpMqYcqU,5807 -Quart-0.9.1.dist-info/WHEEL,sha256=S8S5VL-stOTSZDYxHyf0KP7eds0J72qrK0Evu3TfyAY,92 -Quart-0.9.1.dist-info/entry_points.txt,sha256=RqA0UUUkmZOtSvbyqsevnfBFUHUEcDpUCikcTO9czIw,42 -Quart-0.9.1.dist-info/top_level.txt,sha256=F_INWWD_HZA6avzVV_hQKfjEnZSlUUe6Y0XDjg3zABo,6 -Quart-0.9.1.dist-info/RECORD,, -../../../bin/quart,sha256=2HrcpGbLKyY9JxpSr9DpRMDx2Cp5fTK5Y-Xmub0Hfkg,260 -Quart-0.9.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -quart/json/__pycache__/__init__.cpython-37.pyc,, -quart/json/__pycache__/tag.cpython-37.pyc,, -quart/wrappers/__pycache__/_base.cpython-37.pyc,, -quart/wrappers/__pycache__/__init__.cpython-37.pyc,, -quart/wrappers/__pycache__/request.cpython-37.pyc,, -quart/wrappers/__pycache__/response.cpython-37.pyc,, -quart/__pycache__/templating.cpython-37.pyc,, -quart/__pycache__/blueprints.cpython-37.pyc,, -quart/__pycache__/app.cpython-37.pyc,, -quart/__pycache__/ctx.cpython-37.pyc,, -quart/__pycache__/typing.cpython-37.pyc,, -quart/__pycache__/__init__.cpython-37.pyc,, -quart/__pycache__/helpers.cpython-37.pyc,, -quart/__pycache__/exceptions.cpython-37.pyc,, -quart/__pycache__/globals.cpython-37.pyc,, -quart/__pycache__/views.cpython-37.pyc,, -quart/__pycache__/__main__.cpython-37.pyc,, -quart/__pycache__/datastructures.cpython-37.pyc,, -quart/__pycache__/debug.cpython-37.pyc,, -quart/__pycache__/local.cpython-37.pyc,, -quart/__pycache__/utils.cpython-37.pyc,, -quart/__pycache__/__about__.cpython-37.pyc,, -quart/__pycache__/sessions.cpython-37.pyc,, -quart/__pycache__/static.cpython-37.pyc,, -quart/__pycache__/signals.cpython-37.pyc,, -quart/__pycache__/asgi.cpython-37.pyc,, -quart/__pycache__/cli.cpython-37.pyc,, -quart/__pycache__/testing.cpython-37.pyc,, -quart/__pycache__/config.cpython-37.pyc,, -quart/__pycache__/routing.cpython-37.pyc,, -quart/__pycache__/logging.cpython-37.pyc,, -quart/flask_patch/__pycache__/_patch.cpython-37.pyc,, -quart/flask_patch/__pycache__/app.cpython-37.pyc,, -quart/flask_patch/__pycache__/__init__.cpython-37.pyc,, -quart/flask_patch/__pycache__/globals.cpython-37.pyc,, -quart/flask_patch/__pycache__/_synchronise.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/WHEEL deleted file mode 100644 index c57a597..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.4) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/entry_points.txt b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/entry_points.txt deleted file mode 100644 index 38fa811..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -quart = quart.cli:main - diff --git a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/top_level.txt deleted file mode 100644 index 60af440..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart-0.9.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -quart diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/LICENSE deleted file mode 100644 index 8a5dad9..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -Copyright P G Jones 2018. - -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. diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/METADATA deleted file mode 100644 index 4977c28..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/METADATA +++ /dev/null @@ -1,159 +0,0 @@ -Metadata-Version: 2.1 -Name: Quart-CORS -Version: 0.1.3 -Summary: A Quart extension to provide Cross Origin Resource Sharing, access control, support. -Home-page: https://gitlab.com/pgjones/quart-cors/ -Author: P G Jones -Author-email: philip.graham.jones@googlemail.com -License: MIT -Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha -Classifier: Environment :: Web Environment -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=3.6.1 -Requires-Dist: Quart (>=0.6.11) - -Quart-CORS -========== - -|Build Status| |pypi| |python| |license| - -Quart-CORS is an extension for `Quart -`_ to handle `Cross Origin Resource -Sharing `_, CORS (also known as access -control). - -CORS is required to share resources in browsers due to the `Same -Origin Policy `_ -which prevents resources being read and limits write actions from a -different origin. An origin in this case is defined as the scheme, -host and port combination. - -In practice the Same Origin Policy means that a browser visiting -``http://quart.com`` will prevent the response of ``GET -http://api.com`` being read. It will also prevent requests such as -``POST http://api.com``. Note that embedding is allowed e.g. ````. - -CORS allows the server to indicate to the browser that certain -resources can be used. It does so for GET requests by returning -headers that indicate the origins that can use the resource whereas -for other requests the browser will send a preflight OPTIONS request -and then inspect the headers in the response. - -Simple (GET) requests should return CORS headers specifying the -allowed origins (which can be any origin, ``*``) and whether -credentials should be shared. If credentials can be shared the origins -must be specific and not a wildcard. - -Preflight requests should return CORS headers specifying the allowed -origins, methods and headers in the request, whehter credentials -should be shared and what response headers should be exposed. - -Usage ------ - -To add CORS access control headers to all of the routes in the -application, simply apply the ``cors`` function to the application, - -.. code-block:: python - - app = Quart(__name__) - app = cors(app) - -alternatively if you wish to add CORS selectively either apply the -``cors`` function to a blueprint or the ``route_cors`` function to -a route, - -.. code-block:: python - - blueprint = Blueprint(__name__) - blueprint = cors(blueprint) - - @blueprint.route('/') - @route_cors() - async def handler(): - ... - -In addition defaults can be specified in the application -configuration, - -============================ ======== -Configuration key type ----------------------------- -------- -QUART_CORS_ALLOW_CREDENTIALS bool -QUART_CORS_ALLOW_HEADERS Set[str] -QUART_CORS_ALLOW_METHODS Set[str] -QUART_CORS_ALLOW_ORIGIN Set[str] -QUART_CORS_EXPOSE_HEADERS Set[str] -QUART_CORS_MAX_AGE float -============================ ======== - -Both the ``cors`` and ``route_cors`` functions take these arguments, - -================= =========================== -Argument type ------------------ --------------------------- -allow_credentials bool -allow_headers Union[Set[str], str] -allow_methods Union[Set[str], str] -allow_origin Union[Set[str], str] -expose_headers Union[Set[str], str] -max_age Union[int, flot, timedelta] -================= =========================== - -.. note:: - - The Same Origin Policy does not apply to websockets, and hence this - extension does not add CORS headers to websocket routes. In - addition the ``route_cors`` function should not be used on a - websocket route. - -Contributing ------------- - -Quart-CORS is developed on `GitLab -`_. You are very welcome to -open `issues `_ or -propose `merge requests -`_. - -Testing -~~~~~~~ - -The best way to test Quart-CORS is with Tox, - -.. code-block:: console - - $ pipenv install tox - $ tox - -this will check the code style and run the tests. - -Help ----- - -This README is the best place to start, after that try opening an -`issue `_. - - -.. |Build Status| image:: https://gitlab.com/pgjones/quart-cors/badges/master/build.svg - :target: https://gitlab.com/pgjones/quart-cors/commits/master - -.. |pypi| image:: https://img.shields.io/pypi/v/quart-cors.svg - :target: https://pypi.python.org/pypi/Quart-CORS/ - -.. |python| image:: https://img.shields.io/pypi/pyversions/quart-cors.svg - :target: https://pypi.python.org/pypi/Quart-CORS/ - -.. |license| image:: https://img.shields.io/badge/license-MIT-blue.svg - :target: https://gitlab.com/pgjones/quart-cors/blob/master/LICENSE - - diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/RECORD deleted file mode 100644 index 44ef129..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/RECORD +++ /dev/null @@ -1,8 +0,0 @@ -quart_cors.py,sha256=BHNBom_DXEWfI7QBUAqY1iEequOlrTL8bKdIHJCK7aI,10588 -Quart_CORS-0.1.3.dist-info/LICENSE,sha256=HjGdhzPYNEZ3zQ7mwqjMBgHHRId5HViyayt-8GMMK38,1050 -Quart_CORS-0.1.3.dist-info/METADATA,sha256=hib8lN1d5pvMwH-jqd8vsDneGNDFCTg9-QKHNj6w23I,5231 -Quart_CORS-0.1.3.dist-info/WHEEL,sha256=_NOXIqFgOaYmlm9RJLPQZ13BJuEIrp5jx5ptRD5uh3Y,92 -Quart_CORS-0.1.3.dist-info/top_level.txt,sha256=8rvyefjLRk14p42yU4avg7pG-4TIDyYwin-uh5KVW_4,11 -Quart_CORS-0.1.3.dist-info/RECORD,, -Quart_CORS-0.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -__pycache__/quart_cors.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/WHEEL deleted file mode 100644 index 4eeaea1..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.32.3) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/top_level.txt deleted file mode 100644 index 98a048a..0000000 --- a/py3.7/lib/python3.7/site-packages/Quart_CORS-0.1.3.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -quart_cors diff --git a/py3.7/lib/python3.7/site-packages/_cffi_backend.cpython-37m-x86_64-linux-gnu.so b/py3.7/lib/python3.7/site-packages/_cffi_backend.cpython-37m-x86_64-linux-gnu.so deleted file mode 100755 index 65b6778..0000000 Binary files a/py3.7/lib/python3.7/site-packages/_cffi_backend.cpython-37m-x86_64-linux-gnu.so and /dev/null differ diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/DESCRIPTION.rst b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/DESCRIPTION.rst deleted file mode 100644 index 5be2b5a..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,138 +0,0 @@ -aiofiles: file support for asyncio -================================== - -.. image:: https://img.shields.io/pypi/v/aiofiles.svg - :target: https://pypi.python.org/pypi/aiofiles - -.. image:: https://travis-ci.org/Tinche/aiofiles.svg?branch=master - :target: https://travis-ci.org/Tinche/aiofiles - -.. image:: https://codecov.io/gh/Tinche/aiofiles/branch/master/graph/badge.svg - :target: https://codecov.io/gh/Tinche/aiofiles - -**aiofiles** is an Apache2 licensed library, written in Python, for handling local -disk files in asyncio applications. - -Ordinary local file IO is blocking, and cannot easily and portably made -asynchronous. This means doing file IO may interfere with asyncio applications, -which shouldn't block the executing thread. aiofiles helps with this by -introducing asynchronous versions of files that support delegating operations to -a separate thread pool. - -.. code-block:: python - - async with aiofiles.open('filename', mode='r') as f: - contents = await f.read() - print(contents) - 'My file contents' - -Asynchronous iteration is also supported. - -.. code-block:: python - - async with aiofiles.open('filename') as f: - async for line in f: - ... - -Features --------- - -- a file API very similar to Python's standard, blocking API -- support for buffered and unbuffered binary files, and buffered text files -- support for ``async``/``await`` (:PEP:`492`) constructs - - -Installation ------------- - -To install aiofiles, simply: - -.. code-block:: bash - - $ pip install aiofiles - -Usage ------ - -Files are opened using the ``aiofiles.open()`` coroutine, which in addition to -mirroring the builtin ``open`` accepts optional ``loop`` and ``executor`` -arguments. If ``loop`` is absent, the default loop will be used, as per the -set asyncio policy. If ``executor`` is not specified, the default event loop -executor will be used. - -In case of success, an asynchronous file object is returned with an -API identical to an ordinary file, except the following methods are coroutines -and delegate to an executor: - -* ``close`` -* ``flush`` -* ``isatty`` -* ``read`` -* ``readall`` -* ``read1`` -* ``readinto`` -* ``readline`` -* ``readlines`` -* ``seek`` -* ``seekable`` -* ``tell`` -* ``truncate`` -* ``writable`` -* ``write`` -* ``writelines`` - -In case of failure, one of the usual exceptions will be raised. - -The ``aiofiles.os`` module contains executor-enabled coroutine versions of -several useful ``os`` functions that deal with files: - -* ``stat`` -* ``sendfile`` - -Writing tests for aiofiles -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Real file IO can be mocked by patching ``aiofiles.threadpool.sync_open`` -as desired. The return type also needs to be registered with the -``aiofiles.threadpool.wrap`` dispatcher: - -.. code-block:: python - - aiofiles.threadpool.wrap.register(mock.MagicMock)( - lambda *args, **kwargs: threadpool.AsyncBufferedIOBase(*args, **kwargs)) - - async def test_stuff(): - data = 'data' - mock_file = mock.MagicMock() - - with mock.patch('aiofiles.threadpool.sync_open', return_value=mock_file) as mock_open: - async with aiofiles.open('filename', 'w') as f: - await f.write(data) - - mock_file.write.assert_called_once_with(data) - -History -~~~~~~~ - -0.4.0 (2018-08-11) -`````````````````` -- Python 3.7 support. -- Removed Python 3.3/3.4 support. If you use these versions, stick to aiofiles 0.3.x. - -0.3.2 (2017-09-23) -`````````````````` -- The LICENSE is now included in the sdist. - `#31 `_ - -0.3.1 (2017-03-10) -`````````````````` - -- Introduced a changelog. -- ``aiofiles.os.sendfile`` will now work if the standard ``os`` module contains a ``sendfile`` function. - -Contributing -~~~~~~~~~~~~ -Contributions are very welcome. Tests can be run with ``tox``, please ensure -the coverage at least stays the same before you submit a pull request. - - diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/METADATA deleted file mode 100644 index 2e1c2f6..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/METADATA +++ /dev/null @@ -1,155 +0,0 @@ -Metadata-Version: 2.0 -Name: aiofiles -Version: 0.4.0 -Summary: File support for asyncio. -Home-page: https://github.com/Tinche/aiofiles -Author: Tin Tvrtkovic -Author-email: tinchester@gmail.com -License: Apache 2.0 -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Apache Software License -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: System :: Filesystems - -aiofiles: file support for asyncio -================================== - -.. image:: https://img.shields.io/pypi/v/aiofiles.svg - :target: https://pypi.python.org/pypi/aiofiles - -.. image:: https://travis-ci.org/Tinche/aiofiles.svg?branch=master - :target: https://travis-ci.org/Tinche/aiofiles - -.. image:: https://codecov.io/gh/Tinche/aiofiles/branch/master/graph/badge.svg - :target: https://codecov.io/gh/Tinche/aiofiles - -**aiofiles** is an Apache2 licensed library, written in Python, for handling local -disk files in asyncio applications. - -Ordinary local file IO is blocking, and cannot easily and portably made -asynchronous. This means doing file IO may interfere with asyncio applications, -which shouldn't block the executing thread. aiofiles helps with this by -introducing asynchronous versions of files that support delegating operations to -a separate thread pool. - -.. code-block:: python - - async with aiofiles.open('filename', mode='r') as f: - contents = await f.read() - print(contents) - 'My file contents' - -Asynchronous iteration is also supported. - -.. code-block:: python - - async with aiofiles.open('filename') as f: - async for line in f: - ... - -Features --------- - -- a file API very similar to Python's standard, blocking API -- support for buffered and unbuffered binary files, and buffered text files -- support for ``async``/``await`` (:PEP:`492`) constructs - - -Installation ------------- - -To install aiofiles, simply: - -.. code-block:: bash - - $ pip install aiofiles - -Usage ------ - -Files are opened using the ``aiofiles.open()`` coroutine, which in addition to -mirroring the builtin ``open`` accepts optional ``loop`` and ``executor`` -arguments. If ``loop`` is absent, the default loop will be used, as per the -set asyncio policy. If ``executor`` is not specified, the default event loop -executor will be used. - -In case of success, an asynchronous file object is returned with an -API identical to an ordinary file, except the following methods are coroutines -and delegate to an executor: - -* ``close`` -* ``flush`` -* ``isatty`` -* ``read`` -* ``readall`` -* ``read1`` -* ``readinto`` -* ``readline`` -* ``readlines`` -* ``seek`` -* ``seekable`` -* ``tell`` -* ``truncate`` -* ``writable`` -* ``write`` -* ``writelines`` - -In case of failure, one of the usual exceptions will be raised. - -The ``aiofiles.os`` module contains executor-enabled coroutine versions of -several useful ``os`` functions that deal with files: - -* ``stat`` -* ``sendfile`` - -Writing tests for aiofiles -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Real file IO can be mocked by patching ``aiofiles.threadpool.sync_open`` -as desired. The return type also needs to be registered with the -``aiofiles.threadpool.wrap`` dispatcher: - -.. code-block:: python - - aiofiles.threadpool.wrap.register(mock.MagicMock)( - lambda *args, **kwargs: threadpool.AsyncBufferedIOBase(*args, **kwargs)) - - async def test_stuff(): - data = 'data' - mock_file = mock.MagicMock() - - with mock.patch('aiofiles.threadpool.sync_open', return_value=mock_file) as mock_open: - async with aiofiles.open('filename', 'w') as f: - await f.write(data) - - mock_file.write.assert_called_once_with(data) - -History -~~~~~~~ - -0.4.0 (2018-08-11) -`````````````````` -- Python 3.7 support. -- Removed Python 3.3/3.4 support. If you use these versions, stick to aiofiles 0.3.x. - -0.3.2 (2017-09-23) -`````````````````` -- The LICENSE is now included in the sdist. - `#31 `_ - -0.3.1 (2017-03-10) -`````````````````` - -- Introduced a changelog. -- ``aiofiles.os.sendfile`` will now work if the standard ``os`` module contains a ``sendfile`` function. - -Contributing -~~~~~~~~~~~~ -Contributions are very welcome. Tests can be run with ``tox``, please ensure -the coverage at least stays the same before you submit a pull request. - - diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/RECORD deleted file mode 100644 index b914afd..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/RECORD +++ /dev/null @@ -1,23 +0,0 @@ -aiofiles/__init__.py,sha256=EqOSYq0u50pdIbUzDXqyeImxnHUmT9AtbRi_PtO5Hyw,123 -aiofiles/_compat.py,sha256=dk34urK9pKm1iqKNp2jKDWatAbn3Tt18eRn31G9BcAI,205 -aiofiles/base.py,sha256=OFBt0XoRATidR8UeVldUZmul6-jgRNTn6qebAgFoMys,2121 -aiofiles/os.py,sha256=zNYhMoGytKY994XPCqetbC4ScLgmZjJCjQfZNUm2NrU,514 -aiofiles/threadpool/__init__.py,sha256=io-WG10ohdQU6CdPZEV24oBssL_9T6NEf6AEAHA18Ao,2144 -aiofiles/threadpool/binary.py,sha256=Ds7je-noWGqtwBOd21OF7DNV1m9VFt3Z29ynS7hGf-k,1102 -aiofiles/threadpool/text.py,sha256=blq1hfMSQ_kEtDMuRwf-CtHNeOAwdgIOYYVDtFJi8CI,629 -aiofiles/threadpool/utils.py,sha256=8apQJirPwOgUeRUbT2ghDpqmiXaUq_ZJ5eQRklHgz3U,1266 -aiofiles-0.4.0.dist-info/DESCRIPTION.rst,sha256=H1Vj_rqfRMCdJcU1lW_sPSIWr185N97Kn594gYK_B1A,3873 -aiofiles-0.4.0.dist-info/METADATA,sha256=RqoqpyBnW1j0u1t3w9jQ_F-0vZWsepXvs0MA-GFoMsM,4445 -aiofiles-0.4.0.dist-info/RECORD,, -aiofiles-0.4.0.dist-info/WHEEL,sha256=8Lm45v9gcYRm70DrgFGVe4WsUtUMi1_0Tso1hqPGMjA,92 -aiofiles-0.4.0.dist-info/metadata.json,sha256=0eE-SIzvVCI2-nBAir1RKYLcPpxWa1uzpmAyD9Vye9M,712 -aiofiles-0.4.0.dist-info/top_level.txt,sha256=sskrEAT1Ocyj9qsJIoeIQNAijBFwY2L0nqayXghOSI0,9 -aiofiles-0.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -aiofiles/threadpool/__pycache__/__init__.cpython-37.pyc,, -aiofiles/threadpool/__pycache__/binary.cpython-37.pyc,, -aiofiles/threadpool/__pycache__/text.cpython-37.pyc,, -aiofiles/threadpool/__pycache__/utils.cpython-37.pyc,, -aiofiles/__pycache__/base.cpython-37.pyc,, -aiofiles/__pycache__/__init__.cpython-37.pyc,, -aiofiles/__pycache__/_compat.cpython-37.pyc,, -aiofiles/__pycache__/os.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/WHEEL deleted file mode 100644 index 6261a26..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.30.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/metadata.json b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/metadata.json deleted file mode 100644 index 8309a32..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: System :: Filesystems"], "extensions": {"python.details": {"contacts": [{"email": "tinchester@gmail.com", "name": "Tin Tvrtkovic", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/Tinche/aiofiles"}}}, "generator": "bdist_wheel (0.30.0)", "license": "Apache 2.0", "metadata_version": "2.0", "name": "aiofiles", "summary": "File support for asyncio.", "version": "0.4.0"} \ No newline at end of file diff --git a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/top_level.txt deleted file mode 100644 index 1ce9bba..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles-0.4.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -aiofiles diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/__init__.py b/py3.7/lib/python3.7/site-packages/aiofiles/__init__.py deleted file mode 100644 index 3c4d362..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""Utilities for asyncio-friendly file handling.""" -from .threadpool import open - -__version__ = "0.4.0" - -__all__ = (open,) diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/_compat.py b/py3.7/lib/python3.7/site-packages/aiofiles/_compat.py deleted file mode 100644 index 2921cc5..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/_compat.py +++ /dev/null @@ -1,8 +0,0 @@ -import sys - -try: - from functools import singledispatch -except ImportError: # pragma: nocover - from singledispatch import singledispatch - -PY_35 = sys.version_info >= (3, 5) diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/base.py b/py3.7/lib/python3.7/site-packages/aiofiles/base.py deleted file mode 100644 index 72a835e..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/base.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Various base classes.""" -import asyncio -from collections.abc import Coroutine - - -class AsyncBase: - def __init__(self, file, loop, executor): - self._file = file - self._loop = loop - self._executor = executor - - def __aiter__(self): - """We are our own iterator.""" - return self - - @asyncio.coroutine - def __anext__(self): - """Simulate normal file iteration.""" - line = yield from self.readline() - if line: - return line - else: - raise StopAsyncIteration - - -class _ContextManager(Coroutine): - __slots__ = ('_coro', '_obj') - - def __init__(self, coro): - self._coro = coro - self._obj = None - - def send(self, value): - return self._coro.send(value) - - def throw(self, typ, val=None, tb=None): - if val is None: - return self._coro.throw(typ) - elif tb is None: - return self._coro.throw(typ, val) - else: - return self._coro.throw(typ, val, tb) - - def close(self): - return self._coro.close() - - @property - def gi_frame(self): - return self._coro.gi_frame - - @property - def gi_running(self): - return self._coro.gi_running - - @property - def gi_code(self): - return self._coro.gi_code - - def __next__(self): - return self.send(None) - - @asyncio.coroutine - def __iter__(self): - resp = yield from self._coro - return resp - - def __await__(self): - resp = yield from self._coro - return resp - - @asyncio.coroutine - def __anext__(self): - resp = yield from self._coro - return resp - - @asyncio.coroutine - def __aenter__(self): - self._obj = yield from self._coro - return self._obj - - @asyncio.coroutine - def __aexit__(self, exc_type, exc, tb): - self._obj.close() - self._obj = None - - -class AiofilesContextManager(_ContextManager): - """An adjusted async context manager for aiofiles.""" - - @asyncio.coroutine - def __aexit__(self, exc_type, exc_val, exc_tb): - yield from self._obj.close() - self._obj = None diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/os.py b/py3.7/lib/python3.7/site-packages/aiofiles/os.py deleted file mode 100644 index 9b5c3ea..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/os.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Async executor versions of file functions from the os module.""" -import asyncio -from functools import partial, wraps -import os - - -def wrap(func): - @asyncio.coroutine - @wraps(func) - def run(*args, loop=None, executor=None, **kwargs): - if loop is None: - loop = asyncio.get_event_loop() - pfunc = partial(func, *args, **kwargs) - return loop.run_in_executor(executor, pfunc) - - return run - - -stat = wrap(os.stat) - -if hasattr(os, "sendfile"): - sendfile = wrap(os.sendfile) diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/__init__.py b/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/__init__.py deleted file mode 100644 index a8ea978..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -"""Handle files using a thread pool executor.""" -import asyncio - -from io import (FileIO, TextIOBase, BufferedReader, BufferedWriter, - BufferedRandom) -from functools import partial, singledispatch - -from .binary import AsyncBufferedIOBase, AsyncBufferedReader, AsyncFileIO -from .text import AsyncTextIOWrapper -from ..base import AiofilesContextManager - -sync_open = open - -__all__ = ('open', ) - - -def open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, - closefd=True, opener=None, *, loop=None, executor=None): - return AiofilesContextManager(_open(file, mode=mode, buffering=buffering, - encoding=encoding, errors=errors, - newline=newline, closefd=closefd, - opener=opener, loop=loop, - executor=executor)) - - -@asyncio.coroutine -def _open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, - closefd=True, opener=None, *, loop=None, executor=None): - """Open an asyncio file.""" - if loop is None: - loop = asyncio.get_event_loop() - cb = partial(sync_open, file, mode=mode, buffering=buffering, - encoding=encoding, errors=errors, newline=newline, - closefd=closefd, opener=opener) - f = yield from loop.run_in_executor(executor, cb) - - return wrap(f, loop=loop, executor=executor) - - -@singledispatch -def wrap(file, *, loop=None, executor=None): - raise TypeError('Unsupported io type: {}.'.format(file)) - - -@wrap.register(TextIOBase) -def _(file, *, loop=None, executor=None): - return AsyncTextIOWrapper(file, loop=loop, executor=executor) - - -@wrap.register(BufferedWriter) -def _(file, *, loop=None, executor=None): - return AsyncBufferedIOBase(file, loop=loop, executor=executor) - - -@wrap.register(BufferedReader) -@wrap.register(BufferedRandom) -def _(file, *, loop=None, executor=None): - return AsyncBufferedReader(file, loop=loop, executor=executor) - - -@wrap.register(FileIO) -def _(file, *, loop=None, executor=None): - return AsyncFileIO(file, loop, executor) diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/binary.py b/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/binary.py deleted file mode 100644 index 288b54b..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/binary.py +++ /dev/null @@ -1,26 +0,0 @@ -from ..base import AsyncBase -from .utils import (delegate_to_executor, proxy_property_directly, - proxy_method_directly) - - -@delegate_to_executor('close', 'flush', 'isatty', 'read', 'read1', 'readinto', - 'readline', 'readlines', 'seek', 'seekable', 'tell', - 'truncate', 'writable', 'write', 'writelines') -@proxy_method_directly('detach', 'fileno', 'readable') -@proxy_property_directly('closed', 'raw') -class AsyncBufferedIOBase(AsyncBase): - """The asyncio executor version of io.BufferedWriter.""" - - -@delegate_to_executor('peek') -class AsyncBufferedReader(AsyncBufferedIOBase): - """The asyncio executor version of io.BufferedReader and Random.""" - - -@delegate_to_executor('close', 'flush', 'isatty', 'read', 'readall', 'readinto', - 'readline', 'readlines', 'seek', 'seekable', 'tell', - 'truncate', 'writable', 'write', 'writelines') -@proxy_method_directly('fileno', 'readable') -@proxy_property_directly('closed') -class AsyncFileIO(AsyncBase): - """The asyncio executor version of io.FileIO.""" diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/text.py b/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/text.py deleted file mode 100644 index 7668c0a..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/text.py +++ /dev/null @@ -1,13 +0,0 @@ -from .utils import (delegate_to_executor, proxy_property_directly, - proxy_method_directly) -from ..base import AsyncBase - - -@delegate_to_executor('close', 'flush', 'isatty', 'read', 'readable', - 'readline', 'readlines', 'seek', 'seekable', 'tell', - 'truncate', 'write', 'writable', 'writelines') -@proxy_method_directly('detach', 'fileno', 'readable') -@proxy_property_directly('buffer', 'closed', 'encoding', 'errors', - 'line_buffering', 'newlines') -class AsyncTextIOWrapper(AsyncBase): - """The asyncio executor version of io.TextIOWrapper.""" diff --git a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/utils.py b/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/utils.py deleted file mode 100644 index 368b44b..0000000 --- a/py3.7/lib/python3.7/site-packages/aiofiles/threadpool/utils.py +++ /dev/null @@ -1,49 +0,0 @@ -import asyncio -import functools - - -def delegate_to_executor(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_delegate_method(attr_name)) - return cls - return cls_builder - - -def proxy_method_directly(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_proxy_method(attr_name)) - return cls - - return cls_builder - - -def proxy_property_directly(*attrs): - def cls_builder(cls): - for attr_name in attrs: - setattr(cls, attr_name, _make_proxy_property(attr_name)) - return cls - - return cls_builder - - -def _make_delegate_method(attr_name): - @asyncio.coroutine - def method(self, *args, **kwargs): - cb = functools.partial(getattr(self._file, attr_name), - *args, **kwargs) - return (yield from self._loop.run_in_executor(self._executor, cb)) - return method - - -def _make_proxy_method(attr_name): - def method(self, *args, **kwargs): - return getattr(self._file, attr_name)(*args, **kwargs) - return method - - -def _make_proxy_property(attr_name): - def proxy_property(self): - return getattr(self._file, attr_name) - return property(proxy_property) diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/DESCRIPTION.rst b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/DESCRIPTION.rst deleted file mode 100644 index 317e0e1..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,74 +0,0 @@ -[![Build Status](https://travis-ci.org/jek/blinker.svg?branch=master)](https://travis-ci.org/jek/blinker) - - -# Blinker - -Blinker provides a fast dispatching system that allows any number of -interested parties to subscribe to events, or "signals". - -Signal receivers can subscribe to specific senders or receive signals -sent by any sender. - - >>> from blinker import signal - >>> started = signal('round-started') - >>> def each(round): - ... print "Round %s!" % round - ... - >>> started.connect(each) - - >>> def round_two(round): - ... print "This is round two." - ... - >>> started.connect(round_two, sender=2) - - >>> for round in range(1, 4): - ... started.send(round) - ... - Round 1! - Round 2! - This is round two. - Round 3! - -See the [Blinker documentation](https://pythonhosted.org/blinker/) for more information. - -## Requirements - -Blinker requires Python 2.4 or higher, Python 3.0 or higher, or Jython 2.5 or higher. - -## Changelog Summary - -1.3 (July 3, 2013) - - - The global signal stash behind blinker.signal() is now backed by a - regular name-to-Signal dictionary. Previously, weak references were - held in the mapping and ephemeral usage in code like - ``signal('foo').connect(...)`` could have surprising program behavior - depending on import order of modules. - - blinker.Namespace is now built on a regular dict. Use - blinker.WeakNamespace for the older, weak-referencing behavior. - - Signal.connect('text-sender') uses an alternate hashing strategy to - avoid sharp edges in text identity. - -1.2 (October 26, 2011) - - - Added Signal.receiver_connected and Signal.receiver_disconnected - per-Signal signals. - - Deprecated the global 'receiver_connected' signal. - - Verified Python 3.2 support (no changes needed!) - -1.1 (July 21, 2010) - - - Added ``@signal.connect_via(sender)`` decorator - - Added ``signal.connected_to`` shorthand name for the - ``temporarily_connected_to`` context manager. - -1.0 (March 28, 2010) - - - Python 3.x compatibility - -0.9 (February 26, 2010) - - - Sphinx docs, project website - - Added ``with a_signal.temporarily_connected_to(receiver): ...`` support - - diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/METADATA deleted file mode 100644 index 2c4e7cb..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/METADATA +++ /dev/null @@ -1,103 +0,0 @@ -Metadata-Version: 2.0 -Name: blinker -Version: 1.4 -Summary: Fast, simple object-to-object and broadcast signaling -Home-page: http://pythonhosted.org/blinker/ -Author: Jason Kirtland -Author-email: jek@discorporate.us -License: MIT License -Keywords: signal emit events broadcast -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.4 -Classifier: Programming Language :: Python :: 2.5 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.0 -Classifier: Programming Language :: Python :: 3.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: Utilities - -[![Build Status](https://travis-ci.org/jek/blinker.svg?branch=master)](https://travis-ci.org/jek/blinker) - - -# Blinker - -Blinker provides a fast dispatching system that allows any number of -interested parties to subscribe to events, or "signals". - -Signal receivers can subscribe to specific senders or receive signals -sent by any sender. - - >>> from blinker import signal - >>> started = signal('round-started') - >>> def each(round): - ... print "Round %s!" % round - ... - >>> started.connect(each) - - >>> def round_two(round): - ... print "This is round two." - ... - >>> started.connect(round_two, sender=2) - - >>> for round in range(1, 4): - ... started.send(round) - ... - Round 1! - Round 2! - This is round two. - Round 3! - -See the [Blinker documentation](https://pythonhosted.org/blinker/) for more information. - -## Requirements - -Blinker requires Python 2.4 or higher, Python 3.0 or higher, or Jython 2.5 or higher. - -## Changelog Summary - -1.3 (July 3, 2013) - - - The global signal stash behind blinker.signal() is now backed by a - regular name-to-Signal dictionary. Previously, weak references were - held in the mapping and ephemeral usage in code like - ``signal('foo').connect(...)`` could have surprising program behavior - depending on import order of modules. - - blinker.Namespace is now built on a regular dict. Use - blinker.WeakNamespace for the older, weak-referencing behavior. - - Signal.connect('text-sender') uses an alternate hashing strategy to - avoid sharp edges in text identity. - -1.2 (October 26, 2011) - - - Added Signal.receiver_connected and Signal.receiver_disconnected - per-Signal signals. - - Deprecated the global 'receiver_connected' signal. - - Verified Python 3.2 support (no changes needed!) - -1.1 (July 21, 2010) - - - Added ``@signal.connect_via(sender)`` decorator - - Added ``signal.connected_to`` shorthand name for the - ``temporarily_connected_to`` context manager. - -1.0 (March 28, 2010) - - - Python 3.x compatibility - -0.9 (February 26, 2010) - - - Sphinx docs, project website - - Added ``with a_signal.temporarily_connected_to(receiver): ...`` support - - diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/RECORD deleted file mode 100644 index 5f7888c..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/RECORD +++ /dev/null @@ -1,15 +0,0 @@ -blinker/__init__.py,sha256=vgkMDX61C3h5jhFvxiGJ_FCkajPLZi-KzZr_AAfV-_0,300 -blinker/_saferef.py,sha256=OprBfoWWJd791Qm9OY5c-v1bIo2qLalHah8hqAA18Sw,9223 -blinker/_utilities.py,sha256=ev0IgdfH4wMSmLO-J3gVZSc-umhhmJiQJWdQNy6lyTY,4457 -blinker/base.py,sha256=MJ_qn4ladUGMAU2M1k2OIPfgUi_INhbqfLrvjdsmHVM,16319 -blinker-1.4.dist-info/DESCRIPTION.rst,sha256=3_4DJiX9bY8jfI5iy3cnv1RpTnnxn6H7hZU0XQcn654,2143 -blinker-1.4.dist-info/METADATA,sha256=05VH_-heiIxM9Ws-CV8oKgr_QyeTNAfHrlWXrY0shwE,3308 -blinker-1.4.dist-info/RECORD,, -blinker-1.4.dist-info/WHEEL,sha256=R7vZ7BN-uS956KbXldDh72QgjPXY8RJnlM4z4S73d8M,93 -blinker-1.4.dist-info/metadata.json,sha256=aKd8tj1U2KLWLRB75BhdINYrNQT4SP7HX6KQ6zjoFaU,1222 -blinker-1.4.dist-info/top_level.txt,sha256=2NmsENM0J2t9Z8mkjxHDmGMQj7Bm8f5ZTTYe1x1fZtM,8 -blinker-1.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -blinker/__pycache__/base.cpython-37.pyc,, -blinker/__pycache__/__init__.cpython-37.pyc,, -blinker/__pycache__/_utilities.cpython-37.pyc,, -blinker/__pycache__/_saferef.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/WHEEL deleted file mode 100644 index c694185..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.30.0) -Root-Is-Purelib: true -Tag: cp37-none-any - diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/metadata.json b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/metadata.json deleted file mode 100644 index 4a18217..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.4", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.0", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Topic :: Software Development :: Libraries", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "jek@discorporate.us", "name": "Jason Kirtland", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pythonhosted.org/blinker/"}}}, "generator": "bdist_wheel (0.30.0)", "keywords": ["signal", "emit", "events", "broadcast"], "license": "MIT License", "metadata_version": "2.0", "name": "blinker", "summary": "Fast, simple object-to-object and broadcast signaling", "version": "1.4"} \ No newline at end of file diff --git a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/top_level.txt deleted file mode 100644 index 1ff4ca5..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker-1.4.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -blinker diff --git a/py3.7/lib/python3.7/site-packages/blinker/__init__.py b/py3.7/lib/python3.7/site-packages/blinker/__init__.py deleted file mode 100644 index 3ea239c..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from blinker.base import ( - ANY, - NamedSignal, - Namespace, - Signal, - WeakNamespace, - receiver_connected, - signal, -) - -__all__ = [ - 'ANY', - 'NamedSignal', - 'Namespace', - 'Signal', - 'WeakNamespace', - 'receiver_connected', - 'signal', - ] - - -__version__ = '1.4' diff --git a/py3.7/lib/python3.7/site-packages/blinker/_saferef.py b/py3.7/lib/python3.7/site-packages/blinker/_saferef.py deleted file mode 100644 index 269e362..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker/_saferef.py +++ /dev/null @@ -1,234 +0,0 @@ -# extracted from Louie, http://pylouie.org/ -# updated for Python 3 -# -# Copyright (c) 2006 Patrick K. O'Brien, Mike C. Fletcher, -# Matthew R. Scott -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# * Neither the name of the nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -"""Refactored 'safe reference from dispatcher.py""" - -import operator -import sys -import traceback -import weakref - - -try: - callable -except NameError: - def callable(object): - return hasattr(object, '__call__') - - -if sys.version_info < (3,): - get_self = operator.attrgetter('im_self') - get_func = operator.attrgetter('im_func') -else: - get_self = operator.attrgetter('__self__') - get_func = operator.attrgetter('__func__') - - -def safe_ref(target, on_delete=None): - """Return a *safe* weak reference to a callable target. - - - ``target``: The object to be weakly referenced, if it's a bound - method reference, will create a BoundMethodWeakref, otherwise - creates a simple weakref. - - - ``on_delete``: If provided, will have a hard reference stored to - the callable to be called after the safe reference goes out of - scope with the reference object, (either a weakref or a - BoundMethodWeakref) as argument. - """ - try: - im_self = get_self(target) - except AttributeError: - if callable(on_delete): - return weakref.ref(target, on_delete) - else: - return weakref.ref(target) - else: - if im_self is not None: - # Turn a bound method into a BoundMethodWeakref instance. - # Keep track of these instances for lookup by disconnect(). - assert hasattr(target, 'im_func') or hasattr(target, '__func__'), ( - "safe_ref target %r has im_self, but no im_func, " - "don't know how to create reference" % target) - reference = BoundMethodWeakref(target=target, on_delete=on_delete) - return reference - - -class BoundMethodWeakref(object): - """'Safe' and reusable weak references to instance methods. - - BoundMethodWeakref objects provide a mechanism for referencing a - bound method without requiring that the method object itself - (which is normally a transient object) is kept alive. Instead, - the BoundMethodWeakref object keeps weak references to both the - object and the function which together define the instance method. - - Attributes: - - - ``key``: The identity key for the reference, calculated by the - class's calculate_key method applied to the target instance method. - - - ``deletion_methods``: Sequence of callable objects taking single - argument, a reference to this object which will be called when - *either* the target object or target function is garbage - collected (i.e. when this object becomes invalid). These are - specified as the on_delete parameters of safe_ref calls. - - - ``weak_self``: Weak reference to the target object. - - - ``weak_func``: Weak reference to the target function. - - Class Attributes: - - - ``_all_instances``: Class attribute pointing to all live - BoundMethodWeakref objects indexed by the class's - calculate_key(target) method applied to the target objects. - This weak value dictionary is used to short-circuit creation so - that multiple references to the same (object, function) pair - produce the same BoundMethodWeakref instance. - """ - - _all_instances = weakref.WeakValueDictionary() - - def __new__(cls, target, on_delete=None, *arguments, **named): - """Create new instance or return current instance. - - Basically this method of construction allows us to - short-circuit creation of references to already- referenced - instance methods. The key corresponding to the target is - calculated, and if there is already an existing reference, - that is returned, with its deletion_methods attribute updated. - Otherwise the new instance is created and registered in the - table of already-referenced methods. - """ - key = cls.calculate_key(target) - current = cls._all_instances.get(key) - if current is not None: - current.deletion_methods.append(on_delete) - return current - else: - base = super(BoundMethodWeakref, cls).__new__(cls) - cls._all_instances[key] = base - base.__init__(target, on_delete, *arguments, **named) - return base - - def __init__(self, target, on_delete=None): - """Return a weak-reference-like instance for a bound method. - - - ``target``: The instance-method target for the weak reference, - must have im_self and im_func attributes and be - reconstructable via the following, which is true of built-in - instance methods:: - - target.im_func.__get__( target.im_self ) - - - ``on_delete``: Optional callback which will be called when - this weak reference ceases to be valid (i.e. either the - object or the function is garbage collected). Should take a - single argument, which will be passed a pointer to this - object. - """ - def remove(weak, self=self): - """Set self.isDead to True when method or instance is destroyed.""" - methods = self.deletion_methods[:] - del self.deletion_methods[:] - try: - del self.__class__._all_instances[self.key] - except KeyError: - pass - for function in methods: - try: - if callable(function): - function(self) - except Exception: - try: - traceback.print_exc() - except AttributeError: - e = sys.exc_info()[1] - print ('Exception during saferef %s ' - 'cleanup function %s: %s' % (self, function, e)) - self.deletion_methods = [on_delete] - self.key = self.calculate_key(target) - im_self = get_self(target) - im_func = get_func(target) - self.weak_self = weakref.ref(im_self, remove) - self.weak_func = weakref.ref(im_func, remove) - self.self_name = str(im_self) - self.func_name = str(im_func.__name__) - - def calculate_key(cls, target): - """Calculate the reference key for this reference. - - Currently this is a two-tuple of the id()'s of the target - object and the target function respectively. - """ - return (id(get_self(target)), id(get_func(target))) - calculate_key = classmethod(calculate_key) - - def __str__(self): - """Give a friendly representation of the object.""" - return "%s(%s.%s)" % ( - self.__class__.__name__, - self.self_name, - self.func_name, - ) - - __repr__ = __str__ - - def __nonzero__(self): - """Whether we are still a valid reference.""" - return self() is not None - - def __cmp__(self, other): - """Compare with another reference.""" - if not isinstance(other, self.__class__): - return cmp(self.__class__, type(other)) - return cmp(self.key, other.key) - - def __call__(self): - """Return a strong reference to the bound method. - - If the target cannot be retrieved, then will return None, - otherwise returns a bound instance method for our object and - function. - - Note: You may call this method any number of times, as it does - not invalidate the reference. - """ - target = self.weak_self() - if target is not None: - function = self.weak_func() - if function is not None: - return function.__get__(target) - return None diff --git a/py3.7/lib/python3.7/site-packages/blinker/_utilities.py b/py3.7/lib/python3.7/site-packages/blinker/_utilities.py deleted file mode 100644 index 056270d..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker/_utilities.py +++ /dev/null @@ -1,163 +0,0 @@ -from weakref import ref - -from blinker._saferef import BoundMethodWeakref - - -try: - callable -except NameError: - def callable(object): - return hasattr(object, '__call__') - - -try: - from collections import defaultdict -except: - class defaultdict(dict): - - def __init__(self, default_factory=None, *a, **kw): - if (default_factory is not None and - not hasattr(default_factory, '__call__')): - raise TypeError('first argument must be callable') - dict.__init__(self, *a, **kw) - self.default_factory = default_factory - - def __getitem__(self, key): - try: - return dict.__getitem__(self, key) - except KeyError: - return self.__missing__(key) - - def __missing__(self, key): - if self.default_factory is None: - raise KeyError(key) - self[key] = value = self.default_factory() - return value - - def __reduce__(self): - if self.default_factory is None: - args = tuple() - else: - args = self.default_factory, - return type(self), args, None, None, self.items() - - def copy(self): - return self.__copy__() - - def __copy__(self): - return type(self)(self.default_factory, self) - - def __deepcopy__(self, memo): - import copy - return type(self)(self.default_factory, - copy.deepcopy(self.items())) - - def __repr__(self): - return 'defaultdict(%s, %s)' % (self.default_factory, - dict.__repr__(self)) - - -try: - from contextlib import contextmanager -except ImportError: - def contextmanager(fn): - def oops(*args, **kw): - raise RuntimeError("Python 2.5 or above is required to use " - "context managers.") - oops.__name__ = fn.__name__ - return oops - -class _symbol(object): - - def __init__(self, name): - """Construct a new named symbol.""" - self.__name__ = self.name = name - - def __reduce__(self): - return symbol, (self.name,) - - def __repr__(self): - return self.name -_symbol.__name__ = 'symbol' - - -class symbol(object): - """A constant symbol. - - >>> symbol('foo') is symbol('foo') - True - >>> symbol('foo') - foo - - A slight refinement of the MAGICCOOKIE=object() pattern. The primary - advantage of symbol() is its repr(). They are also singletons. - - Repeated calls of symbol('name') will all return the same instance. - - """ - symbols = {} - - def __new__(cls, name): - try: - return cls.symbols[name] - except KeyError: - return cls.symbols.setdefault(name, _symbol(name)) - - -try: - text = (str, unicode) -except NameError: - text = str - - -def hashable_identity(obj): - if hasattr(obj, '__func__'): - return (id(obj.__func__), id(obj.__self__)) - elif hasattr(obj, 'im_func'): - return (id(obj.im_func), id(obj.im_self)) - elif isinstance(obj, text): - return obj - else: - return id(obj) - - -WeakTypes = (ref, BoundMethodWeakref) - - -class annotatable_weakref(ref): - """A weakref.ref that supports custom instance attributes.""" - - -def reference(object, callback=None, **annotations): - """Return an annotated weak ref.""" - if callable(object): - weak = callable_reference(object, callback) - else: - weak = annotatable_weakref(object, callback) - for key, value in annotations.items(): - setattr(weak, key, value) - return weak - - -def callable_reference(object, callback=None): - """Return an annotated weak ref, supporting bound instance methods.""" - if hasattr(object, 'im_self') and object.im_self is not None: - return BoundMethodWeakref(target=object, on_delete=callback) - elif hasattr(object, '__self__') and object.__self__ is not None: - return BoundMethodWeakref(target=object, on_delete=callback) - return annotatable_weakref(object, callback) - - -class lazy_property(object): - """A @property that is only evaluated once.""" - - def __init__(self, deferred): - self._deferred = deferred - self.__doc__ = deferred.__doc__ - - def __get__(self, obj, cls): - if obj is None: - return self - value = self._deferred(obj) - setattr(obj, self._deferred.__name__, value) - return value diff --git a/py3.7/lib/python3.7/site-packages/blinker/base.py b/py3.7/lib/python3.7/site-packages/blinker/base.py deleted file mode 100644 index cc5880e..0000000 --- a/py3.7/lib/python3.7/site-packages/blinker/base.py +++ /dev/null @@ -1,455 +0,0 @@ -# -*- coding: utf-8; fill-column: 76 -*- -"""Signals and events. - -A small implementation of signals, inspired by a snippet of Django signal -API client code seen in a blog post. Signals are first-class objects and -each manages its own receivers and message emission. - -The :func:`signal` function provides singleton behavior for named signals. - -""" -from warnings import warn -from weakref import WeakValueDictionary - -from blinker._utilities import ( - WeakTypes, - contextmanager, - defaultdict, - hashable_identity, - lazy_property, - reference, - symbol, - ) - - -ANY = symbol('ANY') -ANY.__doc__ = 'Token for "any sender".' -ANY_ID = 0 - - -class Signal(object): - """A notification emitter.""" - - #: An :obj:`ANY` convenience synonym, allows ``Signal.ANY`` - #: without an additional import. - ANY = ANY - - @lazy_property - def receiver_connected(self): - """Emitted after each :meth:`connect`. - - The signal sender is the signal instance, and the :meth:`connect` - arguments are passed through: *receiver*, *sender*, and *weak*. - - .. versionadded:: 1.2 - - """ - return Signal(doc="Emitted after a receiver connects.") - - @lazy_property - def receiver_disconnected(self): - """Emitted after :meth:`disconnect`. - - The sender is the signal instance, and the :meth:`disconnect` arguments - are passed through: *receiver* and *sender*. - - Note, this signal is emitted **only** when :meth:`disconnect` is - called explicitly. - - The disconnect signal can not be emitted by an automatic disconnect - (due to a weakly referenced receiver or sender going out of scope), - as the receiver and/or sender instances are no longer available for - use at the time this signal would be emitted. - - An alternative approach is available by subscribing to - :attr:`receiver_connected` and setting up a custom weakref cleanup - callback on weak receivers and senders. - - .. versionadded:: 1.2 - - """ - return Signal(doc="Emitted after a receiver disconnects.") - - def __init__(self, doc=None): - """ - :param doc: optional. If provided, will be assigned to the signal's - __doc__ attribute. - - """ - if doc: - self.__doc__ = doc - #: A mapping of connected receivers. - #: - #: The values of this mapping are not meaningful outside of the - #: internal :class:`Signal` implementation, however the boolean value - #: of the mapping is useful as an extremely efficient check to see if - #: any receivers are connected to the signal. - self.receivers = {} - self._by_receiver = defaultdict(set) - self._by_sender = defaultdict(set) - self._weak_senders = {} - - def connect(self, receiver, sender=ANY, weak=True): - """Connect *receiver* to signal events sent by *sender*. - - :param receiver: A callable. Will be invoked by :meth:`send` with - `sender=` as a single positional argument and any \*\*kwargs that - were provided to a call to :meth:`send`. - - :param sender: Any object or :obj:`ANY`, defaults to ``ANY``. - Restricts notifications delivered to *receiver* to only those - :meth:`send` emissions sent by *sender*. If ``ANY``, the receiver - will always be notified. A *receiver* may be connected to - multiple *sender* values on the same Signal through multiple calls - to :meth:`connect`. - - :param weak: If true, the Signal will hold a weakref to *receiver* - and automatically disconnect when *receiver* goes out of scope or - is garbage collected. Defaults to True. - - """ - receiver_id = hashable_identity(receiver) - if weak: - receiver_ref = reference(receiver, self._cleanup_receiver) - receiver_ref.receiver_id = receiver_id - else: - receiver_ref = receiver - if sender is ANY: - sender_id = ANY_ID - else: - sender_id = hashable_identity(sender) - - self.receivers.setdefault(receiver_id, receiver_ref) - self._by_sender[sender_id].add(receiver_id) - self._by_receiver[receiver_id].add(sender_id) - del receiver_ref - - if sender is not ANY and sender_id not in self._weak_senders: - # wire together a cleanup for weakref-able senders - try: - sender_ref = reference(sender, self._cleanup_sender) - sender_ref.sender_id = sender_id - except TypeError: - pass - else: - self._weak_senders.setdefault(sender_id, sender_ref) - del sender_ref - - # broadcast this connection. if receivers raise, disconnect. - if ('receiver_connected' in self.__dict__ and - self.receiver_connected.receivers): - try: - self.receiver_connected.send(self, - receiver=receiver, - sender=sender, - weak=weak) - except: - self.disconnect(receiver, sender) - raise - if receiver_connected.receivers and self is not receiver_connected: - try: - receiver_connected.send(self, - receiver_arg=receiver, - sender_arg=sender, - weak_arg=weak) - except: - self.disconnect(receiver, sender) - raise - return receiver - - def connect_via(self, sender, weak=False): - """Connect the decorated function as a receiver for *sender*. - - :param sender: Any object or :obj:`ANY`. The decorated function - will only receive :meth:`send` emissions sent by *sender*. If - ``ANY``, the receiver will always be notified. A function may be - decorated multiple times with differing *sender* values. - - :param weak: If true, the Signal will hold a weakref to the - decorated function and automatically disconnect when *receiver* - goes out of scope or is garbage collected. Unlike - :meth:`connect`, this defaults to False. - - The decorated function will be invoked by :meth:`send` with - `sender=` as a single positional argument and any \*\*kwargs that - were provided to the call to :meth:`send`. - - - .. versionadded:: 1.1 - - """ - def decorator(fn): - self.connect(fn, sender, weak) - return fn - return decorator - - @contextmanager - def connected_to(self, receiver, sender=ANY): - """Execute a block with the signal temporarily connected to *receiver*. - - :param receiver: a receiver callable - :param sender: optional, a sender to filter on - - This is a context manager for use in the ``with`` statement. It can - be useful in unit tests. *receiver* is connected to the signal for - the duration of the ``with`` block, and will be disconnected - automatically when exiting the block: - - .. testsetup:: - - from __future__ import with_statement - from blinker import Signal - on_ready = Signal() - receiver = lambda sender: None - - .. testcode:: - - with on_ready.connected_to(receiver): - # do stuff - on_ready.send(123) - - .. versionadded:: 1.1 - - """ - self.connect(receiver, sender=sender, weak=False) - try: - yield None - except: - self.disconnect(receiver) - raise - else: - self.disconnect(receiver) - - def temporarily_connected_to(self, receiver, sender=ANY): - """An alias for :meth:`connected_to`. - - :param receiver: a receiver callable - :param sender: optional, a sender to filter on - - .. versionadded:: 0.9 - - .. versionchanged:: 1.1 - Renamed to :meth:`connected_to`. ``temporarily_connected_to`` was - deprecated in 1.2 and will be removed in a subsequent version. - - """ - warn("temporarily_connected_to is deprecated; " - "use connected_to instead.", - DeprecationWarning) - return self.connected_to(receiver, sender) - - def send(self, *sender, **kwargs): - """Emit this signal on behalf of *sender*, passing on \*\*kwargs. - - Returns a list of 2-tuples, pairing receivers with their return - value. The ordering of receiver notification is undefined. - - :param \*sender: Any object or ``None``. If omitted, synonymous - with ``None``. Only accepts one positional argument. - - :param \*\*kwargs: Data to be sent to receivers. - - """ - # Using '*sender' rather than 'sender=None' allows 'sender' to be - # used as a keyword argument- i.e. it's an invisible name in the - # function signature. - if len(sender) == 0: - sender = None - elif len(sender) > 1: - raise TypeError('send() accepts only one positional argument, ' - '%s given' % len(sender)) - else: - sender = sender[0] - if not self.receivers: - return [] - else: - return [(receiver, receiver(sender, **kwargs)) - for receiver in self.receivers_for(sender)] - - def has_receivers_for(self, sender): - """True if there is probably a receiver for *sender*. - - Performs an optimistic check only. Does not guarantee that all - weakly referenced receivers are still alive. See - :meth:`receivers_for` for a stronger search. - - """ - if not self.receivers: - return False - if self._by_sender[ANY_ID]: - return True - if sender is ANY: - return False - return hashable_identity(sender) in self._by_sender - - def receivers_for(self, sender): - """Iterate all live receivers listening for *sender*.""" - # TODO: test receivers_for(ANY) - if self.receivers: - sender_id = hashable_identity(sender) - if sender_id in self._by_sender: - ids = (self._by_sender[ANY_ID] | - self._by_sender[sender_id]) - else: - ids = self._by_sender[ANY_ID].copy() - for receiver_id in ids: - receiver = self.receivers.get(receiver_id) - if receiver is None: - continue - if isinstance(receiver, WeakTypes): - strong = receiver() - if strong is None: - self._disconnect(receiver_id, ANY_ID) - continue - receiver = strong - yield receiver - - def disconnect(self, receiver, sender=ANY): - """Disconnect *receiver* from this signal's events. - - :param receiver: a previously :meth:`connected` callable - - :param sender: a specific sender to disconnect from, or :obj:`ANY` - to disconnect from all senders. Defaults to ``ANY``. - - """ - if sender is ANY: - sender_id = ANY_ID - else: - sender_id = hashable_identity(sender) - receiver_id = hashable_identity(receiver) - self._disconnect(receiver_id, sender_id) - - if ('receiver_disconnected' in self.__dict__ and - self.receiver_disconnected.receivers): - self.receiver_disconnected.send(self, - receiver=receiver, - sender=sender) - - def _disconnect(self, receiver_id, sender_id): - if sender_id == ANY_ID: - if self._by_receiver.pop(receiver_id, False): - for bucket in self._by_sender.values(): - bucket.discard(receiver_id) - self.receivers.pop(receiver_id, None) - else: - self._by_sender[sender_id].discard(receiver_id) - self._by_receiver[receiver_id].discard(sender_id) - - def _cleanup_receiver(self, receiver_ref): - """Disconnect a receiver from all senders.""" - self._disconnect(receiver_ref.receiver_id, ANY_ID) - - def _cleanup_sender(self, sender_ref): - """Disconnect all receivers from a sender.""" - sender_id = sender_ref.sender_id - assert sender_id != ANY_ID - self._weak_senders.pop(sender_id, None) - for receiver_id in self._by_sender.pop(sender_id, ()): - self._by_receiver[receiver_id].discard(sender_id) - - def _cleanup_bookkeeping(self): - """Prune unused sender/receiver bookeeping. Not threadsafe. - - Connecting & disconnecting leave behind a small amount of bookeeping - for the receiver and sender values. Typical workloads using Blinker, - for example in most web apps, Flask, CLI scripts, etc., are not - adversely affected by this bookkeeping. - - With a long-running Python process performing dynamic signal routing - with high volume- e.g. connecting to function closures, "senders" are - all unique object instances, and doing all of this over and over- you - may see memory usage will grow due to extraneous bookeeping. (An empty - set() for each stale sender/receiver pair.) - - This method will prune that bookeeping away, with the caveat that such - pruning is not threadsafe. The risk is that cleanup of a fully - disconnected receiver/sender pair occurs while another thread is - connecting that same pair. If you are in the highly dynamic, unique - receiver/sender situation that has lead you to this method, that - failure mode is perhaps not a big deal for you. - """ - for mapping in (self._by_sender, self._by_receiver): - for _id, bucket in list(mapping.items()): - if not bucket: - mapping.pop(_id, None) - - def _clear_state(self): - """Throw away all signal state. Useful for unit tests.""" - self._weak_senders.clear() - self.receivers.clear() - self._by_sender.clear() - self._by_receiver.clear() - - -receiver_connected = Signal("""\ -Sent by a :class:`Signal` after a receiver connects. - -:argument: the Signal that was connected to -:keyword receiver_arg: the connected receiver -:keyword sender_arg: the sender to connect to -:keyword weak_arg: true if the connection to receiver_arg is a weak reference - -.. deprecated:: 1.2 - -As of 1.2, individual signals have their own private -:attr:`~Signal.receiver_connected` and -:attr:`~Signal.receiver_disconnected` signals with a slightly simplified -call signature. This global signal is planned to be removed in 1.6. - -""") - - -class NamedSignal(Signal): - """A named generic notification emitter.""" - - def __init__(self, name, doc=None): - Signal.__init__(self, doc) - - #: The name of this signal. - self.name = name - - def __repr__(self): - base = Signal.__repr__(self) - return "%s; %r>" % (base[:-1], self.name) - - -class Namespace(dict): - """A mapping of signal names to signals.""" - - def signal(self, name, doc=None): - """Return the :class:`NamedSignal` *name*, creating it if required. - - Repeated calls to this function will return the same signal object. - - """ - try: - return self[name] - except KeyError: - return self.setdefault(name, NamedSignal(name, doc)) - - -class WeakNamespace(WeakValueDictionary): - """A weak mapping of signal names to signals. - - Automatically cleans up unused Signals when the last reference goes out - of scope. This namespace implementation exists for a measure of legacy - compatibility with Blinker <= 1.2, and may be dropped in the future. - - .. versionadded:: 1.3 - - """ - - def signal(self, name, doc=None): - """Return the :class:`NamedSignal` *name*, creating it if required. - - Repeated calls to this function will return the same signal object. - - """ - try: - return self[name] - except KeyError: - return self.setdefault(name, NamedSignal(name, doc)) - - -signal = Namespace().signal diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/LICENSE.txt b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/LICENSE.txt deleted file mode 100644 index 29225ee..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ - -Except when otherwise stated (look for LICENSE files in directories or -information at the beginning of each file) all software and -documentation is licensed as follows: - - The MIT License - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or - sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/METADATA deleted file mode 100644 index b2284b3..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/METADATA +++ /dev/null @@ -1,36 +0,0 @@ -Metadata-Version: 2.1 -Name: cffi -Version: 1.12.3 -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 -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 :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Dist: pycparser - - -CFFI -==== - -Foreign Function Interface for Python calling C code. -Please see the `Documentation `_. - -Contact -------- - -`Mailing list `_ - - diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/RECORD deleted file mode 100644 index 703339a..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/RECORD +++ /dev/null @@ -1,45 +0,0 @@ -_cffi_backend.cpython-37m-x86_64-linux-gnu.so,sha256=-Tf27jBfpRwAJmc2u9lmzDNiE-2qW84YS5ehOLHzfrY,849744 -cffi/cffi_opcode.py,sha256=v9RdD_ovA8rCtqsC95Ivki5V667rAOhGgs3fb2q9xpM,5724 -cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 -cffi/vengine_gen.py,sha256=Zkq0-EdeZwn6qUvf_CI8iUEs2UxVIvDmKCH1j0-y0GI,26676 -cffi/cparser.py,sha256=dcVqrRob1zqrCO--RZ6e-TtobJ7VMDpCU85W6QJ-N-4,40874 -cffi/backend_ctypes.py,sha256=_WkpD1SJel5gJovV-0u8hw-XvD3Efapqm9pIAEHTHn4,42449 -cffi/vengine_cpy.py,sha256=hdyjjZNijLrg_uGMnnFyC-7GG_LxWtwB8BlS2vvVDQ0,41470 -cffi/verifier.py,sha256=J9Enz2rbJb9CHPqWlWQ5uQESoyr0uc7MNWugchjXBv4,11207 -cffi/pkgconfig.py,sha256=LP1w7vmWvmKwyqLaU1Z243FOWGNQMrgMUZrvgFuOlco,4374 -cffi/model.py,sha256=AYyjS26uiFKXtkm43qmStpy9zfGh5HVJF4UETYFBt6w,21682 -cffi/api.py,sha256=Q07iwDD0FRwWa2fx2ZzQft69iJs9aNR52fvrtUy3EY4,41800 -cffi/_cffi_include.h,sha256=JuFfmwpRE65vym3Nxr9vDMOIEuv21tXdarkL1l2WNms,12149 -cffi/commontypes.py,sha256=QS4uxCDI7JhtTyjh1hlnCA-gynmaszWxJaRRLGkJa1A,2689 -cffi/ffiplatform.py,sha256=HMXqR8ks2wtdsNxGaWpQ_PyqIvtiuos_vf1qKCy-cwg,4046 -cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 -cffi/_embedding.h,sha256=PuNkRzXjURiRh7tXzVdIn0RD9pTJx04ZokHbcEO_3OY,17226 -cffi/setuptools_ext.py,sha256=qc6arfrSzm4RNT5oJz6d5td7KJ-pHfI7bqYD0X4Q-08,8848 -cffi/__init__.py,sha256=XPx-ySmw7OmYmr-7iXd3YoXhXj1HQLHYviMKpmAuWLc,513 -cffi/error.py,sha256=v6xTiS4U0kvDcy4h_BDRo5v39ZQuj-IMRYLv5ETddZs,877 -cffi/_cffi_errors.h,sha256=6nFQ-4dRQI1bXRoSeqdvyKU33TmutQJB_2fAhWSzdl8,3856 -cffi/recompiler.py,sha256=LGqj7GPuq4KIG4axrN5G0Oy6YGmrLbBA0bHE-jCl6Oo,62711 -.libs_cffi_backend/libffi-d78936b1.so.6.0.4,sha256=pAI0ev0pF9Vb4xWg8P3tICWnZaYls8U8ku2NRiFLtIs,149064 -cffi-1.12.3.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76 -cffi-1.12.3.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 -cffi-1.12.3.dist-info/RECORD,, -cffi-1.12.3.dist-info/WHEEL,sha256=AhV6RMqZ2IDfreRJKo44QWYxYeP-0Jr0bezzBLQ1eog,109 -cffi-1.12.3.dist-info/LICENSE.txt,sha256=BLgPWwd7vtaICM_rreteNSPyqMmpZJXFh72W3x6sKjM,1294 -cffi-1.12.3.dist-info/METADATA,sha256=OA_DlKzbYB72gWWz0R2ds_RJzTIzvFx5cnHf5NXTRuo,1140 -cffi-1.12.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -cffi/__pycache__/verifier.cpython-37.pyc,, -cffi/__pycache__/commontypes.cpython-37.pyc,, -cffi/__pycache__/setuptools_ext.cpython-37.pyc,, -cffi/__pycache__/__init__.cpython-37.pyc,, -cffi/__pycache__/backend_ctypes.cpython-37.pyc,, -cffi/__pycache__/model.cpython-37.pyc,, -cffi/__pycache__/recompiler.cpython-37.pyc,, -cffi/__pycache__/cffi_opcode.cpython-37.pyc,, -cffi/__pycache__/error.cpython-37.pyc,, -cffi/__pycache__/api.cpython-37.pyc,, -cffi/__pycache__/lock.cpython-37.pyc,, -cffi/__pycache__/pkgconfig.cpython-37.pyc,, -cffi/__pycache__/cparser.cpython-37.pyc,, -cffi/__pycache__/vengine_gen.cpython-37.pyc,, -cffi/__pycache__/vengine_cpy.cpython-37.pyc,, -cffi/__pycache__/ffiplatform.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/WHEEL deleted file mode 100644 index 697e432..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.31.1) -Root-Is-Purelib: false -Tag: cp37-cp37m-manylinux1_x86_64 - diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/entry_points.txt b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/entry_points.txt deleted file mode 100644 index eee7e0f..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[distutils.setup_keywords] -cffi_modules = cffi.setuptools_ext:cffi_modules - diff --git a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/top_level.txt deleted file mode 100644 index f645779..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi-1.12.3.dist-info/top_level.txt +++ /dev/null @@ -1,2 +0,0 @@ -_cffi_backend -cffi diff --git a/py3.7/lib/python3.7/site-packages/cffi/__init__.py b/py3.7/lib/python3.7/site-packages/cffi/__init__.py deleted file mode 100644 index 0224a15..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -__all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError', - 'FFIError'] - -from .api import FFI -from .error import CDefError, FFIError, VerificationError, VerificationMissing -from .error import PkgConfigError - -__version__ = "1.12.3" -__version_info__ = (1, 12, 3) - -# 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/py3.7/lib/python3.7/site-packages/cffi/_cffi_errors.h b/py3.7/lib/python3.7/site-packages/cffi/_cffi_errors.h deleted file mode 100644 index 83cdad0..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/_cffi_errors.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef CFFI_MESSAGEBOX -# ifdef _MSC_VER -# define CFFI_MESSAGEBOX 1 -# else -# define CFFI_MESSAGEBOX 0 -# endif -#endif - - -#if CFFI_MESSAGEBOX -/* Windows only: logic to take the Python-CFFI embedding logic - initialization errors and display them in a background thread - with MessageBox. The idea is that if the whole program closes - as a result of this problem, then likely it is already a console - program and you can read the stderr output in the console too. - If it is not a console program, then it will likely show its own - dialog to complain, or generally not abruptly close, and for this - case the background thread should stay alive. -*/ -static void *volatile _cffi_bootstrap_text; - -static PyObject *_cffi_start_error_capture(void) -{ - PyObject *result = NULL; - PyObject *x, *m, *bi; - - if (InterlockedCompareExchangePointer(&_cffi_bootstrap_text, - (void *)1, NULL) != NULL) - return (PyObject *)1; - - m = PyImport_AddModule("_cffi_error_capture"); - if (m == NULL) - goto error; - - result = PyModule_GetDict(m); - if (result == NULL) - goto error; - -#if PY_MAJOR_VERSION >= 3 - bi = PyImport_ImportModule("builtins"); -#else - bi = PyImport_ImportModule("__builtin__"); -#endif - if (bi == NULL) - goto error; - PyDict_SetItemString(result, "__builtins__", bi); - Py_DECREF(bi); - - x = PyRun_String( - "import sys\n" - "class FileLike:\n" - " def write(self, x):\n" - " try:\n" - " of.write(x)\n" - " except: pass\n" - " self.buf += x\n" - "fl = FileLike()\n" - "fl.buf = ''\n" - "of = sys.stderr\n" - "sys.stderr = fl\n" - "def done():\n" - " sys.stderr = of\n" - " return fl.buf\n", /* make sure the returned value stays alive */ - Py_file_input, - result, result); - Py_XDECREF(x); - - error: - if (PyErr_Occurred()) - { - PyErr_WriteUnraisable(Py_None); - PyErr_Clear(); - } - return result; -} - -#pragma comment(lib, "user32.lib") - -static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) -{ - Sleep(666); /* may be interrupted if the whole process is closing */ -#if PY_MAJOR_VERSION >= 3 - MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, - L"Python-CFFI error", - MB_OK | MB_ICONERROR); -#else - MessageBoxA(NULL, (char *)_cffi_bootstrap_text, - "Python-CFFI error", - MB_OK | MB_ICONERROR); -#endif - _cffi_bootstrap_text = NULL; - return 0; -} - -static void _cffi_stop_error_capture(PyObject *ecap) -{ - PyObject *s; - void *text; - - if (ecap == (PyObject *)1) - return; - - if (ecap == NULL) - goto error; - - s = PyRun_String("done()", Py_eval_input, ecap, ecap); - if (s == NULL) - goto error; - - /* Show a dialog box, but in a background thread, and - never show multiple dialog boxes at once. */ -#if PY_MAJOR_VERSION >= 3 - text = PyUnicode_AsWideCharString(s, NULL); -#else - text = PyString_AsString(s); -#endif - - _cffi_bootstrap_text = text; - - if (text != NULL) - { - HANDLE h; - h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, - NULL, 0, NULL); - if (h != NULL) - CloseHandle(h); - } - /* decref the string, but it should stay alive as 'fl.buf' - in the small module above. It will really be freed only if - we later get another similar error. So it's a leak of at - most one copy of the small module. That's fine for this - situation which is usually a "fatal error" anyway. */ - Py_DECREF(s); - PyErr_Clear(); - return; - - error: - _cffi_bootstrap_text = NULL; - PyErr_Clear(); -} - -#else - -static PyObject *_cffi_start_error_capture(void) { return NULL; } -static void _cffi_stop_error_capture(PyObject *ecap) { } - -#endif diff --git a/py3.7/lib/python3.7/site-packages/cffi/_cffi_include.h b/py3.7/lib/python3.7/site-packages/cffi/_cffi_include.h deleted file mode 100644 index 37ea74f..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/_cffi_include.h +++ /dev/null @@ -1,308 +0,0 @@ -#define _CFFI_ - -/* We try to define Py_LIMITED_API before including Python.h. - - Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and - Py_REF_DEBUG are not defined. This is a best-effort approximation: - we can learn about Py_DEBUG from pyconfig.h, but it is unclear if - the same works for the other two macros. Py_DEBUG implies them, - but not the other way around. - - Issue #350 is still open: on Windows, the code here causes it to link - with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was - attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv - does not make PYTHON3.DLL available, and so the "correctly" compiled - version would not run inside a virtualenv. We will re-apply the fix - after virtualenv has been fixed for some time. For explanation, see - issue #355. For a workaround if you want PYTHON3.DLL and don't worry - about virtualenv, see issue #350. See also 'py_limited_api' in - setuptools_ext.py. -*/ -#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) -# include -# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) -# define Py_LIMITED_API -# endif -#endif - -#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 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# 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 - -#ifdef __cplusplus -# ifndef _Bool - typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ -# endif -#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_from_c__Bool PyBool_FromLong - -#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 *, struct _cffi_ctypedescr *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_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 *, struct _cffi_ctypedescr *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(_cffi_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(*)(struct _cffi_ctypedescr *, \ - PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) -#define _CFFI_CPIDX 25 -#define _cffi_call_python \ - ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) -#define _cffi_to_c_wchar3216_t \ - ((int(*)(PyObject *))_cffi_exports[26]) -#define _cffi_from_c_wchar3216_t \ - ((PyObject *(*)(int))_cffi_exports[27]) -#define _CFFI_NUM_EXPORTS 28 - -struct _cffi_ctypedescr; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (struct _cffi_ctypedescr *)_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; -} - - -#ifdef HAVE_WCHAR_H -typedef wchar_t _cffi_wchar_t; -#else -typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ -#endif - -_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 2) - return (uint16_t)_cffi_to_c_wchar_t(o); - else - return (uint16_t)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) -{ - if (sizeof(_cffi_wchar_t) == 2) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t((int)x); -} - -_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) -{ - if (sizeof(_cffi_wchar_t) == 4) - return (int)_cffi_to_c_wchar_t(o); - else - return (int)_cffi_to_c_wchar3216_t(o); -} - -_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) -{ - if (sizeof(_cffi_wchar_t) == 4) - return _cffi_from_c_wchar_t((_cffi_wchar_t)x); - else - return _cffi_from_c_wchar3216_t(x); -} - - -/********** end CPython-specific section **********/ -#else -_CFFI_UNUSED_FN -static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); -# define _cffi_call_python _cffi_call_python_org -#endif - - -#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 MS_WIN32 -# define _cffi_stdcall __stdcall -#else -# define _cffi_stdcall /* nothing */ -#endif - -#ifdef __cplusplus -} -#endif diff --git a/py3.7/lib/python3.7/site-packages/cffi/_embedding.h b/py3.7/lib/python3.7/site-packages/cffi/_embedding.h deleted file mode 100644 index 30842c1..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/_embedding.h +++ /dev/null @@ -1,518 +0,0 @@ - -/***** Support code for embedding *****/ - -#ifdef __cplusplus -extern "C" { -#endif - - -#if defined(_WIN32) -# define CFFI_DLLEXPORT __declspec(dllexport) -#elif defined(__GNUC__) -# define CFFI_DLLEXPORT __attribute__((visibility("default"))) -#else -# define CFFI_DLLEXPORT /* nothing */ -#endif - - -/* There are two global variables of type _cffi_call_python_fnptr: - - * _cffi_call_python, which we declare just below, is the one called - by ``extern "Python"`` implementations. - - * _cffi_call_python_org, which on CPython is actually part of the - _cffi_exports[] array, is the function pointer copied from - _cffi_backend. - - After initialization is complete, both are equal. However, the - first one remains equal to &_cffi_start_and_call_python until the - very end of initialization, when we are (or should be) sure that - concurrent threads also see a completely initialized world, and - only then is it changed. -*/ -#undef _cffi_call_python -typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); -static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); -static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; - - -#ifndef _MSC_VER - /* --- Assuming a GCC not infinitely old --- */ -# define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) -# define cffi_write_barrier() __sync_synchronize() -# if !defined(__amd64__) && !defined(__x86_64__) && \ - !defined(__i386__) && !defined(__i386) -# define cffi_read_barrier() __sync_synchronize() -# else -# define cffi_read_barrier() (void)0 -# endif -#else - /* --- Windows threads version --- */ -# include -# define cffi_compare_and_swap(l,o,n) \ - (InterlockedCompareExchangePointer(l,n,o) == (o)) -# define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) -# define cffi_read_barrier() (void)0 -static volatile LONG _cffi_dummy; -#endif - -#ifdef WITH_THREAD -# ifndef _MSC_VER -# include - static pthread_mutex_t _cffi_embed_startup_lock; -# else - static CRITICAL_SECTION _cffi_embed_startup_lock; -# endif - static char _cffi_embed_startup_lock_ready = 0; -#endif - -static void _cffi_acquire_reentrant_mutex(void) -{ - static void *volatile lock = NULL; - - while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: pthread_mutex_init() should be very fast, and - this is only run at start-up anyway. */ - } - -#ifdef WITH_THREAD - if (!_cffi_embed_startup_lock_ready) { -# ifndef _MSC_VER - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&_cffi_embed_startup_lock, &attr); -# else - InitializeCriticalSection(&_cffi_embed_startup_lock); -# endif - _cffi_embed_startup_lock_ready = 1; - } -#endif - - while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) - ; - -#ifndef _MSC_VER - pthread_mutex_lock(&_cffi_embed_startup_lock); -#else - EnterCriticalSection(&_cffi_embed_startup_lock); -#endif -} - -static void _cffi_release_reentrant_mutex(void) -{ -#ifndef _MSC_VER - pthread_mutex_unlock(&_cffi_embed_startup_lock); -#else - LeaveCriticalSection(&_cffi_embed_startup_lock); -#endif -} - - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - -#include "_cffi_errors.h" - - -#define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] - -PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */ - -static void _cffi_py_initialize(void) -{ - /* XXX use initsigs=0, which "skips initialization registration of - signal handlers, which might be useful when Python is - embedded" according to the Python docs. But review and think - if it should be a user-controllable setting. - - XXX we should also give a way to write errors to a buffer - instead of to stderr. - - XXX if importing 'site' fails, CPython (any version) calls - exit(). Should we try to work around this behavior here? - */ - Py_InitializeEx(0); -} - -static int _cffi_initialize_python(void) -{ - /* This initializes Python, imports _cffi_backend, and then the - present .dll/.so is set up as a CPython C extension module. - */ - int result; - PyGILState_STATE state; - PyObject *pycode=NULL, *global_dict=NULL, *x; - PyObject *builtins; - - state = PyGILState_Ensure(); - - /* Call the initxxx() function from the present module. It will - create and initialize us as a CPython extension module, instead - of letting the startup Python code do it---it might reimport - the same .dll/.so and get maybe confused on some platforms. - It might also have troubles locating the .dll/.so again for all - I know. - */ - (void)_CFFI_PYTHON_STARTUP_FUNC(); - if (PyErr_Occurred()) - goto error; - - /* Now run the Python code provided to ffi.embedding_init_code(). - */ - pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, - "", - Py_file_input); - if (pycode == NULL) - goto error; - global_dict = PyDict_New(); - if (global_dict == NULL) - goto error; - builtins = PyEval_GetBuiltins(); - if (builtins == NULL) - goto error; - if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) - goto error; - x = PyEval_EvalCode( -#if PY_MAJOR_VERSION < 3 - (PyCodeObject *) -#endif - pycode, global_dict, global_dict); - if (x == NULL) - goto error; - Py_DECREF(x); - - /* Done! Now if we've been called from - _cffi_start_and_call_python() in an ``extern "Python"``, we can - only hope that the Python code did correctly set up the - corresponding @ffi.def_extern() function. Otherwise, the - general logic of ``extern "Python"`` functions (inside the - _cffi_backend module) will find that the reference is still - missing and print an error. - */ - result = 0; - done: - Py_XDECREF(pycode); - Py_XDECREF(global_dict); - PyGILState_Release(state); - return result; - - error:; - { - /* Print as much information as potentially useful. - Debugging load-time failures with embedding is not fun - */ - PyObject *ecap; - PyObject *exception, *v, *tb, *f, *modules, *mod; - PyErr_Fetch(&exception, &v, &tb); - ecap = _cffi_start_error_capture(); - f = PySys_GetObject((char *)"stderr"); - if (f != NULL && f != Py_None) { - PyFile_WriteString( - "Failed to initialize the Python-CFFI embedding logic:\n\n", f); - } - - if (exception != NULL) { - PyErr_NormalizeException(&exception, &v, &tb); - PyErr_Display(exception, v, tb); - } - Py_XDECREF(exception); - Py_XDECREF(v); - Py_XDECREF(tb); - - if (f != NULL && f != Py_None) { - PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.12.3" - "\n_cffi_backend module: ", f); - modules = PyImport_GetModuleDict(); - mod = PyDict_GetItemString(modules, "_cffi_backend"); - if (mod == NULL) { - PyFile_WriteString("not loaded", f); - } - else { - v = PyObject_GetAttrString(mod, "__file__"); - PyFile_WriteObject(v, f, 0); - Py_XDECREF(v); - } - PyFile_WriteString("\nsys.path: ", f); - PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); - PyFile_WriteString("\n\n", f); - } - _cffi_stop_error_capture(ecap); - } - result = -1; - goto done; -} - -PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ - -static int _cffi_carefully_make_gil(void) -{ - /* This does the basic initialization of Python. It can be called - completely concurrently from unrelated threads. It assumes - that we don't hold the GIL before (if it exists), and we don't - hold it afterwards. - - (What it really does used to be completely different in Python 2 - and Python 3, with the Python 2 solution avoiding the spin-lock - around the Py_InitializeEx() call. However, after recent changes - to CPython 2.7 (issue #358) it no longer works. So we use the - Python 3 solution everywhere.) - - This initializes Python by calling Py_InitializeEx(). - Important: this must not be called concurrently at all. - So we use a global variable as a simple spin lock. This global - variable must be from 'libpythonX.Y.so', not from this - cffi-based extension module, because it must be shared from - different cffi-based extension modules. - - In Python < 3.8, we choose - _PyParser_TokenNames[0] as a completely arbitrary pointer value - that is never written to. The default is to point to the - string "ENDMARKER". We change it temporarily to point to the - next character in that string. (Yes, I know it's REALLY - obscure.) - - In Python >= 3.8, this string array is no longer writable, so - instead we pick PyCapsuleType.tp_version_tag. We can't change - Python < 3.8 because someone might use a mixture of cffi - embedded modules, some of which were compiled before this file - changed. - */ - -#ifdef WITH_THREAD -# if PY_VERSION_HEX < 0x03080000 - char *volatile *lock = (char *volatile *)_PyParser_TokenNames; - char *old_value, *locked_value; - - while (1) { /* spin loop */ - old_value = *lock; - locked_value = old_value + 1; - if (old_value[0] == 'E') { - assert(old_value[1] == 'N'); - if (cffi_compare_and_swap(lock, old_value, locked_value)) - break; - } - else { - assert(old_value[0] == 'N'); - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: PyEval_InitThreads() should be very fast, and - this is only run at start-up anyway. */ - } - } -# else - int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; - int old_value, locked_value; - assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); - - while (1) { /* spin loop */ - old_value = *lock; - locked_value = -42; - if (old_value == 0) { - if (cffi_compare_and_swap(lock, old_value, locked_value)) - break; - } - else { - assert(old_value == locked_value); - /* should ideally do a spin loop instruction here, but - hard to do it portably and doesn't really matter I - think: PyEval_InitThreads() should be very fast, and - this is only run at start-up anyway. */ - } - } -# endif -#endif - - /* call Py_InitializeEx() */ - { - PyGILState_STATE state = PyGILState_UNLOCKED; - if (!Py_IsInitialized()) - _cffi_py_initialize(); - else - state = PyGILState_Ensure(); - - PyEval_InitThreads(); - PyGILState_Release(state); - } - -#ifdef WITH_THREAD - /* release the lock */ - while (!cffi_compare_and_swap(lock, locked_value, old_value)) - ; -#endif - - return 0; -} - -/********** end CPython-specific section **********/ - - -#else - - -/********** PyPy-specific section **********/ - -PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */ - -static struct _cffi_pypy_init_s { - const char *name; - void (*func)(const void *[]); - const char *code; -} _cffi_pypy_init = { - _CFFI_MODULE_NAME, - (void(*)(const void *[]))_CFFI_PYTHON_STARTUP_FUNC, - _CFFI_PYTHON_STARTUP_CODE, -}; - -extern int pypy_carefully_make_gil(const char *); -extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); - -static int _cffi_carefully_make_gil(void) -{ - return pypy_carefully_make_gil(_CFFI_MODULE_NAME); -} - -static int _cffi_initialize_python(void) -{ - return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); -} - -/********** end PyPy-specific section **********/ - - -#endif - - -#ifdef __GNUC__ -__attribute__((noinline)) -#endif -static _cffi_call_python_fnptr _cffi_start_python(void) -{ - /* Delicate logic to initialize Python. This function can be - called multiple times concurrently, e.g. when the process calls - its first ``extern "Python"`` functions in multiple threads at - once. It can also be called recursively, in which case we must - ignore it. We also have to consider what occurs if several - different cffi-based extensions reach this code in parallel - threads---it is a different copy of the code, then, and we - can't have any shared global variable unless it comes from - 'libpythonX.Y.so'. - - Idea: - - * _cffi_carefully_make_gil(): "carefully" call - PyEval_InitThreads() (possibly with Py_InitializeEx() first). - - * then we use a (local) custom lock to make sure that a call to this - cffi-based extension will wait if another call to the *same* - extension is running the initialization in another thread. - It is reentrant, so that a recursive call will not block, but - only one from a different thread. - - * then we grab the GIL and (Python 2) we call Py_InitializeEx(). - At this point, concurrent calls to Py_InitializeEx() are not - possible: we have the GIL. - - * do the rest of the specific initialization, which may - temporarily release the GIL but not the custom lock. - Only release the custom lock when we are done. - */ - static char called = 0; - - if (_cffi_carefully_make_gil() != 0) - return NULL; - - _cffi_acquire_reentrant_mutex(); - - /* Here the GIL exists, but we don't have it. We're only protected - from concurrency by the reentrant mutex. */ - - /* This file only initializes the embedded module once, the first - time this is called, even if there are subinterpreters. */ - if (!called) { - called = 1; /* invoke _cffi_initialize_python() only once, - but don't set '_cffi_call_python' right now, - otherwise concurrent threads won't call - this function at all (we need them to wait) */ - if (_cffi_initialize_python() == 0) { - /* now initialization is finished. Switch to the fast-path. */ - - /* We would like nobody to see the new value of - '_cffi_call_python' without also seeing the rest of the - data initialized. However, this is not possible. But - the new value of '_cffi_call_python' is the function - 'cffi_call_python()' from _cffi_backend. So: */ - cffi_write_barrier(); - /* ^^^ we put a write barrier here, and a corresponding - read barrier at the start of cffi_call_python(). This - ensures that after that read barrier, we see everything - done here before the write barrier. - */ - - assert(_cffi_call_python_org != NULL); - _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; - } - else { - /* initialization failed. Reset this to NULL, even if it was - already set to some other value. Future calls to - _cffi_start_python() are still forced to occur, and will - always return NULL from now on. */ - _cffi_call_python_org = NULL; - } - } - - _cffi_release_reentrant_mutex(); - - return (_cffi_call_python_fnptr)_cffi_call_python_org; -} - -static -void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) -{ - _cffi_call_python_fnptr fnptr; - int current_err = errno; -#ifdef _MSC_VER - int current_lasterr = GetLastError(); -#endif - fnptr = _cffi_start_python(); - if (fnptr == NULL) { - fprintf(stderr, "function %s() called, but initialization code " - "failed. Returning 0.\n", externpy->name); - memset(args, 0, externpy->size_of_result); - } -#ifdef _MSC_VER - SetLastError(current_lasterr); -#endif - errno = current_err; - - if (fnptr != NULL) - fnptr(externpy, args); -} - - -/* The cffi_start_python() function makes sure Python is initialized - and our cffi module is set up. It can be called manually from the - user C code. The same effect is obtained automatically from any - dll-exported ``extern "Python"`` function. This function returns - -1 if initialization failed, 0 if all is OK. */ -_CFFI_UNUSED_FN -static int cffi_start_python(void) -{ - if (_cffi_call_python == &_cffi_start_and_call_python) { - if (_cffi_start_python() == NULL) - return -1; - } - cffi_read_barrier(); - return 0; -} - -#undef cffi_compare_and_swap -#undef cffi_write_barrier -#undef cffi_read_barrier - -#ifdef __cplusplus -} -#endif diff --git a/py3.7/lib/python3.7/site-packages/cffi/api.py b/py3.7/lib/python3.7/site-packages/cffi/api.py deleted file mode 100644 index 32fe620..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/api.py +++ /dev/null @@ -1,961 +0,0 @@ -import sys, types -from .lock import allocate_lock -from .error import CDefError -from . import model - -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 - -_unspecified = object() - - - -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. - """ - 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__ - if backend.__version__ != __version__: - # bad version! Try to be as explicit as possible. - if hasattr(backend, '__file__'): - # CPython - raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( - __version__, __file__, - backend.__version__, backend.__file__)) - else: - # PyPy - raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( - __version__, __file__, backend.__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.) - - from . import cparser - 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 - self._init_once_cache = {} - self._cdef_version = None - self._embedding = None - self._typecache = model.get_typecache(backend) - if hasattr(backend, 'set_ffi'): - backend.set_ffi(self) - for name in list(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() - self.buffer = backend.buffer - - def cdef(self, csource, override=False, packed=False, pack=None): - """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. - Alternatively, 'pack' can be a small integer, and requests for - alignment greater than that are ignored (pack=1 is equivalent to - packed=True). - """ - self._cdef(csource, override=override, packed=packed, pack=pack) - - def embedding_api(self, csource, packed=False, pack=None): - self._cdef(csource, packed=packed, pack=pack, dllexport=True) - if self._embedding is None: - self._embedding = '' - - def _cdef(self, csource, override=False, **options): - 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._cdef_version = object() - self._parser.parse(csource, override=override, **options) - 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 dlclose(self, lib): - """Close a library obtained with ffi.dlopen(). After this call, - access to functions or variables from the library will fail - (possibly with a segmentation fault). - """ - type(lib).__cffi_close__(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 unpack(self, cdata, length): - """Unpack an array of C data of the given length, - returning a Python string/unicode/list. - - If 'cdata' is a pointer to 'char', returns a byte string. - It does not stop at the first null. This is equivalent to: - ffi.buffer(cdata, length)[:] - - If 'cdata' is a pointer to 'wchar_t', returns a unicode string. - 'length' is measured in wchar_t's; it is not the size in bytes. - - If 'cdata' is a pointer to anything else, returns a list of - 'length' items. This is a faster equivalent to: - [cdata[i] for i in range(length)] - """ - return self._backend.unpack(cdata, length) - - #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 - # """ - # note that 'buffer' is a type, set on this instance by __init__ - - def from_buffer(self, cdecl, python_buffer=_unspecified, - require_writable=False): - """Return a cdata of the given type pointing 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 or unicode (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. - - The first argument is optional and default to 'char[]'. - """ - if python_buffer is _unspecified: - cdecl, python_buffer = self.BCharA, cdecl - elif isinstance(cdecl, basestring): - cdecl = self._typeof(cdecl) - return self._backend.from_buffer(cdecl, python_buffer, - require_writable) - - 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, size=0): - """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. - - The optional 'size' gives an estimate of the size, used to - trigger the garbage collection more eagerly. So far only used - on PyPy. It tells the GC that the returned object keeps alive - roughly 'size' bytes of external memory. - """ - return self._backend.gcp(cdata, destructor, size) - - 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): - 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. - """ - try: - ctype = self._backend.typeof(cdata) - except TypeError: - if '__addressof__' in type(cdata).__dict__: - return type(cdata).__addressof__(cdata, *fields_or_indexes) - raise - 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 release(self, x): - self._backend.release(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 _apply_embedding_fix(self, kwds): - # must include an argument like "-lpython2.7" for the compiler - def ensure(key, value): - lst = kwds.setdefault(key, []) - if value not in lst: - lst.append(value) - # - if '__pypy__' in sys.builtin_module_names: - import os - if sys.platform == "win32": - # we need 'libpypy-c.lib'. Current distributions of - # pypy (>= 4.1) contain it as 'libs/python27.lib'. - pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'libs')) - else: - # we need 'libpypy-c.{so,dylib}', which should be by - # default located in 'sys.prefix/bin' for installed - # systems. - if sys.version_info < (3,): - pythonlib = "pypy-c" - else: - pythonlib = "pypy3-c" - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'bin')) - # On uninstalled pypy's, the libpypy-c is typically found in - # .../pypy/goal/. - if hasattr(sys, 'prefix'): - ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) - else: - if sys.platform == "win32": - template = "python%d%d" - if hasattr(sys, 'gettotalrefcount'): - template += '_d' - else: - try: - import sysconfig - except ImportError: # 2.6 - from distutils import sysconfig - template = "python%d.%d" - if sysconfig.get_config_var('DEBUG_EXT'): - template += sysconfig.get_config_var('DEBUG_EXT') - pythonlib = (template % - (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) - if hasattr(sys, 'abiflags'): - pythonlib += sys.abiflags - ensure('libraries', pythonlib) - if sys.platform == "win32": - ensure('extra_link_args', '/MANIFEST') - - def set_source(self, module_name, source, source_extension='.c', **kwds): - import os - 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") - if os.sep in module_name or (os.altsep and os.altsep in module_name): - raise ValueError("'module_name' must not contain '/': use a dotted " - "name to make a 'package.module' location") - self._assigned_source = (str(module_name), source, - source_extension, kwds) - - def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, - source_extension='.c', **kwds): - from . import pkgconfig - if not isinstance(pkgconfig_libs, list): - raise TypeError("the pkgconfig_libs argument must be a list " - "of package names") - kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) - pkgconfig.merge_flags(kwds, kwds2) - self.set_source(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='.', verbose=0, target=None, debug=None): - """The 'target' argument gives the final file name of the - compiled DLL. Use '*' to force distutils' choice, suitable for - regular CPython C API modules. Use a file name ending in '.*' - to ask for the system's default extension for dynamic libraries - (.so/.dll/.dylib). - - The default is '*' when building a non-embedded C API extension, - and (module_name + '.*') when building an embedded library. - """ - 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, - target=target, source_extension=source_extension, - compiler_verbose=verbose, debug=debug, **kwds) - - def init_once(self, func, tag): - # Read _init_once_cache[tag], which is either (False, lock) if - # we're calling the function now in some thread, or (True, result). - # Don't call setdefault() in most cases, to avoid allocating and - # immediately freeing a lock; but still use setdefaut() to avoid - # races. - try: - x = self._init_once_cache[tag] - except KeyError: - x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) - # Common case: we got (True, result), so we return the result. - if x[0]: - return x[1] - # Else, it's a lock. Acquire it to serialize the following tests. - with x[1]: - # Read again from _init_once_cache the current status. - x = self._init_once_cache[tag] - if x[0]: - return x[1] - # Call the function and store the result back. - result = func() - self._init_once_cache[tag] = (True, result) - return result - - def embedding_init_code(self, pysource): - if self._embedding: - raise ValueError("embedding_init_code() can only be called once") - # fix 'pysource' before it gets dumped into the C file: - # - remove empty lines at the beginning, so it starts at "line 1" - # - dedent, if all non-empty lines are indented - # - check for SyntaxErrors - import re - match = re.match(r'\s*\n', pysource) - if match: - pysource = pysource[match.end():] - lines = pysource.splitlines() or [''] - prefix = re.match(r'\s*', lines[0]).group() - for i in range(1, len(lines)): - line = lines[i] - if line.rstrip(): - while not line.startswith(prefix): - prefix = prefix[:-1] - i = len(prefix) - lines = [line[i:]+'\n' for line in lines] - pysource = ''.join(lines) - # - compile(pysource, "cffi_init", "exec") - # - self._embedding = pysource - - def def_extern(self, *args, **kwds): - raise ValueError("ffi.def_extern() is only available on API-mode FFI " - "objects") - - def list_types(self): - """Returns the user type names known to this FFI instance. - This returns a tuple containing three lists of names: - (typedef_names, names_of_structs, names_of_unions) - """ - typedefs = [] - structs = [] - unions = [] - for key in self._parser._declarations: - if key.startswith('typedef '): - typedefs.append(key[8:]) - elif key.startswith('struct '): - structs.append(key[7:]) - elif key.startswith('union '): - unions.append(key[6:]) - typedefs.sort() - structs.sort() - unions.sort() - return (typedefs, structs, unions) - - -def _load_backend_lib(backend, name, flags): - import os - if name is None: - if sys.platform != "win32": - return backend.load_library(None, flags) - name = "c" # Windows: load_library(None) fails, but this works - # on Python 2 (backward compatibility hack only) - first_error = None - if '.' in name or '/' in name or os.sep in name: - try: - return backend.load_library(name, flags) - except OSError as e: - first_error = e - import ctypes.util - path = ctypes.util.find_library(name) - if path is None: - if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): - raise OSError("dlopen(None) cannot work on Windows for Python 3 " - "(see http://bugs.python.org/issue23606)") - msg = ("ctypes.util.find_library() did not manage " - "to locate a library called %r" % (name,)) - if first_error is not None: - msg = "%s. Additionally, %s" % (first_error, msg) - raise OSError(msg) - return backend.load_library(path, flags) - -def _make_ffi_library(ffi, libname, flags): - backend = ffi._backend - backendlib = _load_backend_lib(backend, libname, flags) - # - def accessor_function(name): - key = 'function ' + name - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - value = backendlib.load_function(BType, name) - library.__dict__[name] = value - # - def accessor_variable(name): - key = 'variable ' + name - 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))) - # - def addressof_var(name): - try: - return addr_variables[name] - except KeyError: - with ffi._lock: - if name not in addr_variables: - key = 'variable ' + name - tp, _ = ffi._parser._declarations[key] - BType = ffi._get_cached_btype(tp) - if BType.kind != 'array': - BType = model.pointer_cache(ffi, BType) - p = backendlib.load_function(BType, name) - addr_variables[name] = p - return addr_variables[name] - # - def accessor_constant(name): - raise NotImplementedError("non-integer constant '%s' cannot be " - "accessed from a dlopen() library" % (name,)) - # - def accessor_int_constant(name): - library.__dict__[name] = ffi._parser._int_constants[name] - # - accessors = {} - accessors_version = [False] - addr_variables = {} - # - def update_accessors(): - if accessors_version[0] is ffi._cdef_version: - return - # - for key, (tp, _) in ffi._parser._declarations.items(): - if not isinstance(tp, model.EnumType): - tag, name = key.split(' ', 1) - if tag == 'function': - accessors[name] = accessor_function - elif tag == 'variable': - accessors[name] = accessor_variable - elif tag == 'constant': - accessors[name] = accessor_constant - else: - for i, enumname in enumerate(tp.enumerators): - def accessor_enum(name, tp=tp, i=i): - tp.check_not_partial() - library.__dict__[name] = tp.enumvalues[i] - accessors[enumname] = accessor_enum - for name in ffi._parser._int_constants: - accessors.setdefault(name, accessor_int_constant) - accessors_version[0] = ffi._cdef_version - # - 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 - if name not in accessors: - update_accessors() - if name not in accessors: - raise AttributeError(name) - accessors[name](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) - def __dir__(self): - with ffi._lock: - update_accessors() - return accessors.keys() - def __addressof__(self, name): - if name in library.__dict__: - return library.__dict__[name] - if name in FFILibrary.__dict__: - return addressof_var(name) - make_accessor(name) - if name in library.__dict__: - return library.__dict__[name] - if name in FFILibrary.__dict__: - return addressof_var(name) - raise AttributeError("cffi library has no function or " - "global variable named '%s'" % (name,)) - def __cffi_close__(self): - backendlib.close_lib() - self.__dict__.clear() - # - 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/py3.7/lib/python3.7/site-packages/cffi/backend_ctypes.py b/py3.7/lib/python3.7/site-packages/cffi/backend_ctypes.py deleted file mode 100644 index 679ae05..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/backend_ctypes.py +++ /dev/null @@ -1,1121 +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): - v_is_ptr = not isinstance(self, CTypesGenericPrimitive) - w_is_ptr = (isinstance(other, CTypesData) and - not isinstance(other, CTypesGenericPrimitive)) - if v_is_ptr and w_is_ptr: - return cmpfunc(self._convert_to_address(None), - other._convert_to_address(None)) - elif v_is_ptr or w_is_ptr: - return NotImplemented - else: - if isinstance(self, CTypesGenericPrimitive): - self = self._value - if isinstance(other, CTypesGenericPrimitive): - other = other._value - return cmpfunc(self, other) - 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(self._convert_to_address(None)) - - def _to_string(self, maxlen): - raise TypeError("string(): %r" % (self,)) - - -class CTypesGenericPrimitive(CTypesData): - __slots__ = [] - - def __hash__(self): - return hash(self._value) - - 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) - __bool__ = __nonzero__ - - @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__) - def __nonzero__(self): - return ord(self._value) != 0 - else: - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - 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: - if isinstance(init, CTypesGenericArray): - if (len(init) != len(blob) or - not isinstance(init, CTypesArray)): - raise TypeError("length/type mismatch: %s" % (init,)) - 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, - pack=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 - elif pack: - struct_or_union._pack_ = pack - 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) - - _weakref_cache_ref = None - - def gcp(self, cdata, destructor, size=0): - if self._weakref_cache_ref is None: - import weakref - class MyRef(weakref.ref): - def __eq__(self, other): - myref = self() - return self is other or ( - myref is not None and myref is other()) - def __ne__(self, other): - return not (self == other) - def __hash__(self): - try: - return self._hash - except AttributeError: - self._hash = hash(self()) - return self._hash - self._weakref_cache_ref = {}, MyRef - weak_cache, MyRef = self._weakref_cache_ref - - if destructor is None: - try: - del weak_cache[MyRef(cdata)] - except KeyError: - raise TypeError("Can remove destructor only on a object " - "previously returned by ffi.gc()") - return None - - def remove(k): - cdata, destructor = weak_cache.pop(k, (None, None)) - if destructor is not None: - destructor(cdata) - - new_cdata = self.cast(self.typeof(cdata), cdata) - assert new_cdata is not cdata - weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor) - return new_cdata - - 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/py3.7/lib/python3.7/site-packages/cffi/cffi_opcode.py b/py3.7/lib/python3.7/site-packages/cffi/cffi_opcode.py deleted file mode 100644 index a0df98d..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/cffi_opcode.py +++ /dev/null @@ -1,187 +0,0 @@ -from .error import VerificationError - -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): - 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 -OP_EXTERN_PYTHON = 41 - -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 -PRIM_FLOATCOMPLEX = 48 -PRIM_DOUBLECOMPLEX = 49 -PRIM_CHAR16 = 50 -PRIM_CHAR32 = 51 - -_NUM_PRIM = 52 -_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, - 'float _Complex': PRIM_FLOATCOMPLEX, - 'double _Complex': PRIM_DOUBLECOMPLEX, - '_Bool': PRIM_BOOL, - 'wchar_t': PRIM_WCHAR, - 'char16_t': PRIM_CHAR16, - 'char32_t': PRIM_CHAR32, - '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/py3.7/lib/python3.7/site-packages/cffi/commontypes.py b/py3.7/lib/python3.7/site-packages/cffi/commontypes.py deleted file mode 100644 index 8ec97c7..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/commontypes.py +++ /dev/null @@ -1,80 +0,0 @@ -import sys -from . import model -from .error import FFIError - - -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 FFIError("The Windows type %r is only available after " - "you call ffi.set_unicode()" % (commontype,)) - else: - if commontype == cdecl: - raise FFIError( - "Unsupported type: %r. Please look at " - "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " - "and file an issue if you think this type should really " - "be supported." % (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/py3.7/lib/python3.7/site-packages/cffi/cparser.py b/py3.7/lib/python3.7/site-packages/cffi/cparser.py deleted file mode 100644 index 262fd76..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/cparser.py +++ /dev/null @@ -1,931 +0,0 @@ -from . import model -from .commontypes import COMMON_TYPES, resolve_common_type -from .error import FFIError, CDefError -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 - -def _workaround_for_static_import_finders(): - # Issue #392: packaging tools like cx_Freeze can not find these - # because pycparser uses exec dynamic import. This is an obscure - # workaround. This function is never called. - import pycparser.yacctab - import pycparser.lextab - -CDEF_SOURCE_STRING = "" -_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_extern_python = re.compile(r'\bextern\s*"' - r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.') -_r_star_const_space = re.compile( # matches "* const " - r"[*]\s*((const|volatile|restrict)\b\s*)+") -_r_int_dotdotdot = re.compile(r"(\b(int|long|short|signed|unsigned|char)\s*)+" - r"\.\.\.") -_r_float_dotdotdot = re.compile(r"\b(double|float)\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_extern_python(csource): - # input: `extern "Python" int foo(int);` or - # `extern "Python" { int foo(int); }` - # output: - # void __cffi_extern_python_start; - # int foo(int); - # void __cffi_extern_python_stop; - # - # input: `extern "Python+C" int foo(int);` - # output: - # void __cffi_extern_python_plus_c_start; - # int foo(int); - # void __cffi_extern_python_stop; - parts = [] - while True: - match = _r_extern_python.search(csource) - if not match: - break - endpos = match.end() - 1 - #print - #print ''.join(parts)+csource - #print '=>' - parts.append(csource[:match.start()]) - if 'C' in match.group(1): - parts.append('void __cffi_extern_python_plus_c_start; ') - else: - parts.append('void __cffi_extern_python_start; ') - if csource[endpos] == '{': - # grouping variant - closing = csource.find('}', endpos) - if closing < 0: - raise CDefError("'extern \"Python\" {': no '}' found") - if csource.find('{', endpos + 1, closing) >= 0: - raise NotImplementedError("cannot use { } inside a block " - "'extern \"Python\" { ... }'") - parts.append(csource[endpos+1:closing]) - csource = csource[closing+1:] - else: - # non-grouping variant - semicolon = csource.find(';', endpos) - if semicolon < 0: - raise CDefError("'extern \"Python\": no ';' found") - parts.append(csource[endpos:semicolon+1]) - csource = csource[semicolon+1:] - parts.append(' void __cffi_extern_python_stop;') - #print ''.join(parts)+csource - #print - parts.append(csource) - return ''.join(parts) - -def _warn_for_string_literal(csource): - if '"' in csource: - import warnings - warnings.warn("String literal found in cdef() or type source. " - "String literals are ignored here, but you should " - "remove them anyway because some character sequences " - "confuse pre-parsing.") - -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 `extern "Python"` with start/end markers - csource = _preprocess_extern_python(csource) - # - # Now there should not be any string literal left; warn if we get one - _warn_for_string_literal(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 "int ..." or "unsigned long int..." with "__dotdotdotint__" - csource = _r_int_dotdotdot.sub(' __dotdotdotint__ ', csource) - # Replace "float ..." or "double..." with "__dotdotdotfloat__" - csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource) - # 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._options = {} - 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 = [] - csourcelines.append('# 1 ""') - for typename in typenames: - csourcelines.append('typedef int %s;' % typename) - csourcelines.append('typedef int __dotdotdotint__, __dotdotdotfloat__,' - ' __dotdotdot__;') - # this forces pycparser to consider the following in the file - # called from line 1 - csourcelines.append('# 1 "%s"' % (CDEF_SOURCE_STRING,)) - csourcelines.append(csource) - fullcsource = '\n'.join(csourcelines) - if lock is not None: - lock.acquire() # pycparser is not thread-safe... - try: - ast = _get_parser().parse(fullcsource) - 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 interpret that as a line number. This will not work if - # the user gives explicit ``# NUM "FILE"`` directives. - line = None - msg = str(e) - match = re.match(r"%s:(\d+):" % (CDEF_SOURCE_STRING,), msg) - if match: - linenum = int(match.group(1), 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 CDefError(msg) - - def parse(self, csource, override=False, packed=False, pack=None, - dllexport=False): - if packed: - if packed != True: - raise ValueError("'packed' should be False or True; use " - "'pack' to give another value") - if pack: - raise ValueError("cannot give both 'pack' and 'packed'") - pack = 1 - elif pack: - if pack & (pack - 1): - raise ValueError("'pack' must be a power of two, not %r" % - (pack,)) - else: - pack = 0 - prev_options = self._options - try: - self._options = {'override': override, - 'packed': pack, - 'dllexport': dllexport} - self._internal_parse(csource) - finally: - self._options = prev_options - - 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 - else: - assert 0 - current_decl = None - # - try: - self._inside_extern_python = '__cffi_extern_python_stop' - for decl in iterator: - current_decl = decl - if isinstance(decl, pycparser.c_ast.Decl): - self._parse_decl(decl) - elif isinstance(decl, pycparser.c_ast.Typedef): - if not decl.name: - raise 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].startswith('__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[-1].startswith('__dotdotdot')): - realtype = self._get_unknown_ptr_type(decl) - else: - realtype, quals = self._get_type_and_quals( - decl.type, name=decl.name, partial_length_ok=True) - self._declare('typedef ' + decl.name, realtype, quals=quals) - elif decl.__class__.__name__ == 'Pragma': - pass # skip pragma, only in pycparser 2.15 - else: - raise CDefError("unexpected <%s>: this construct is valid " - "C but not valid in cdef()" % - decl.__class__.__name__, decl) - except CDefError as e: - if len(e.args) == 1: - e.args = e.args + (current_decl,) - raise - except 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 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 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 _declare_function(self, tp, quals, decl): - tp = self._get_type_pointer(tp, quals) - if self._options.get('dllexport'): - tag = 'dllexport_python ' - elif self._inside_extern_python == '__cffi_extern_python_start': - tag = 'extern_python ' - elif self._inside_extern_python == '__cffi_extern_python_plus_c_start': - tag = 'extern_python_plus_c ' - else: - tag = 'function ' - self._declare(tag + decl.name, tp) - - 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) - self._declare_function(tp, quals, decl) - 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 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: - self._declare_function(tp, quals, decl) - 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 (tp is model.void_type and - decl.name.startswith('__cffi_extern_python_')): - # hack: `extern "Python"` in the C source is replaced - # with "void __cffi_extern_python_start;" and - # "void __cffi_extern_python_stop;" - self._inside_extern_python = decl.name - else: - if self._inside_extern_python !='__cffi_extern_python_stop': - raise CDefError( - "cannot declare constants or " - "variables with 'extern \"Python\"'") - if (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 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._options.get('override'): - raise 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 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 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 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 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 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._options.get('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 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 '0' <= s[0] <= '9': - s = s.rstrip('uUlL') - try: - if s.startswith('0'): - return int(s, 8) - else: - return int(s, 10) - except ValueError: - if len(s) > 1: - if s.lower()[0:2] == '0x': - return int(s, 16) - elif s.lower()[0:2] == '0b': - return int(s, 2) - raise CDefError("invalid constant %r" % (s,)) - elif s[0] == "'" and s[-1] == "'" and ( - len(s) == 3 or (len(s) == 4 and s[1] == "\\")): - return ord(s[-2]) - else: - raise 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 (isinstance(exprnode, pycparser.c_ast.ID) and - exprnode.name == '__dotdotdotarray__'): - if partial_length_ok: - self._partial_length = True - return '...' - raise FFIError(":%d: unsupported '[...]' here, cannot derive " - "the actual array length in this context" - % exprnode.coord.line) - # - if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and - exprnode.op == '+'): - return (self._parse_constant(exprnode.left) + - self._parse_constant(exprnode.right)) - # - if (isinstance(exprnode, pycparser.c_ast.BinaryOp) and - exprnode.op == '-'): - return (self._parse_constant(exprnode.left) - - self._parse_constant(exprnode.right)) - # - raise 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 - if typenames == ['__dotdotdot__']: - return model.unknown_type(decl.name) - - if typenames == ['__dotdotdotint__']: - if self._uses_new_feature is None: - self._uses_new_feature = "'typedef int... %s'" % decl.name - return model.UnknownIntegerType(decl.name) - - if typenames == ['__dotdotdotfloat__']: - # note: not for 'long double' so far - if self._uses_new_feature is None: - self._uses_new_feature = "'typedef float... %s'" % decl.name - return model.UnknownFloatType(decl.name) - - raise FFIError(':%d: unsupported usage of "..." in typedef' - % decl.coord.line) - - def _get_unknown_ptr_type(self, decl): - if decl.type.type.type.names == ['__dotdotdot__']: - return model.unknown_ptr_type(decl.name) - raise FFIError(':%d: unsupported usage of "..." in typedef' - % decl.coord.line) diff --git a/py3.7/lib/python3.7/site-packages/cffi/error.py b/py3.7/lib/python3.7/site-packages/cffi/error.py deleted file mode 100644 index 0a27247..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/error.py +++ /dev/null @@ -1,31 +0,0 @@ - -class FFIError(Exception): - __module__ = 'cffi' - -class CDefError(Exception): - __module__ = 'cffi' - def __str__(self): - try: - current_decl = self.args[1] - filename = current_decl.coord.file - linenum = current_decl.coord.line - prefix = '%s:%d: ' % (filename, linenum) - except (AttributeError, TypeError, IndexError): - prefix = '' - return '%s%s' % (prefix, self.args[0]) - -class VerificationError(Exception): - """ An error raised when verification fails - """ - __module__ = 'cffi' - -class VerificationMissing(Exception): - """ An error raised when incomplete structures are passed into - cdef, but no verification has been done - """ - __module__ = 'cffi' - -class PkgConfigError(Exception): - """ An error raised for missing modules in pkg-config - """ - __module__ = 'cffi' diff --git a/py3.7/lib/python3.7/site-packages/cffi/ffiplatform.py b/py3.7/lib/python3.7/site-packages/cffi/ffiplatform.py deleted file mode 100644 index 8531346..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/ffiplatform.py +++ /dev/null @@ -1,127 +0,0 @@ -import sys, os -from .error import VerificationError - - -LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', - 'extra_objects', 'depends'] - -def get_extension(srcfilename, modname, sources=(), **kwds): - _hack_at_distutils() - from distutils.core import Extension - allsources = [srcfilename] - for src in sources: - allsources.append(os.path.normpath(src)) - return Extension(name=modname, sources=allsources, **kwds) - -def compile(tmpdir, ext, compiler_verbose=0, debug=None): - """Compile a C extension module using distutils.""" - - _hack_at_distutils() - saved_environ = os.environ.copy() - try: - outputfilename = _build(tmpdir, ext, compiler_verbose, debug) - 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, compiler_verbose=0, debug=None): - # XXX compact but horrible :-( - from distutils.core import Distribution - import distutils.errors, distutils.log - # - dist = Distribution({'ext_modules': [ext]}) - dist.parse_config_files() - options = dist.get_option_dict('build_ext') - if debug is None: - debug = sys.flags.debug - options['debug'] = ('ffiplatform', debug) - options['force'] = ('ffiplatform', True) - options['build_lib'] = ('ffiplatform', tmpdir) - options['build_temp'] = ('ffiplatform', tmpdir) - # - try: - old_level = distutils.log.set_threshold(0) or 0 - try: - distutils.log.set_verbosity(compiler_verbose) - dist.run_command('build_ext') - cmd_obj = dist.get_command_obj('build_ext') - [soname] = cmd_obj.get_outputs() - finally: - distutils.log.set_threshold(old_level) - except (distutils.errors.CompileError, - distutils.errors.LinkError) as e: - raise VerificationError('%s: %s' % (e.__class__.__name__, e)) - # - 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() - -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 diff --git a/py3.7/lib/python3.7/site-packages/cffi/lock.py b/py3.7/lib/python3.7/site-packages/cffi/lock.py deleted file mode 100644 index db91b71..0000000 --- a/py3.7/lib/python3.7/site-packages/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/py3.7/lib/python3.7/site-packages/cffi/model.py b/py3.7/lib/python3.7/site-packages/cffi/model.py deleted file mode 100644 index 5f1b0d2..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/model.py +++ /dev/null @@ -1,614 +0,0 @@ -import types -import weakref - -from .lock import allocate_lock -from .error import CDefError, VerificationError, VerificationMissing - -# 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: - 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): - def is_complex_type(self): - return False - - -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', - 'float _Complex': 'j', - 'double _Complex': 'j', - '_Bool': 'i', - # the following types are not primitive in the C sense - 'wchar_t': 'c', - 'char16_t': 'c', - 'char32_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 is_complex_type(self): - return self.ALL_PRIMITIVE_TYPES[self.name] == 'j' - - 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): - raise 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 == '...': - raise 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 = 0 - - 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 anonymous_struct_fields(self): - if self.fldtypes is not None: - for name, type in zip(self.fldnames, self.fldtypes): - if name == '' and isinstance(type, StructOrUnion): - yield type - - def enumfields(self, expand_anonymous_struct_union=True): - 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) - and expand_anonymous_struct_union): - # 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)) - extra_flags = () - if self.packed: - if self.packed == 1: - extra_flags = (8,) # SF_PACKED - else: - extra_flags = (0, self.packed) - ffi._backend.complete_struct_or_union(BType, lst, self, - -1, -1, *extra_flags) - # - 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): - raise VerificationError(msg) - - def check_not_partial(self): - if self.partial and self.fixedlayout is None: - raise 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: - raise 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) - # - if self.enumvalues: - smallest_value = min(self.enumvalues) - largest_value = max(self.enumvalues) - else: - import warnings - try: - # XXX! The goal is to ensure that the warnings.warn() - # will not suppress the warning. We want to get it - # several times if we reach this point several times. - __warningregistry__.clear() - except NameError: - pass - warnings.warn("%r has no values explicitly defined; " - "guessing that it is equivalent to 'unsigned int'" - % 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 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() -_typecache_cffi_backend = weakref.WeakValueDictionary() - -def get_typecache(backend): - # returns _typecache_cffi_backend if backend is the _cffi_backend - # module, or type(backend).__typecache if backend is an instance of - # CTypesBackend (or some FakeBackend class during tests) - if isinstance(backend, types.ModuleType): - return _typecache_cffi_backend - with global_lock: - if not hasattr(type(backend), '__typecache'): - type(backend).__typecache = weakref.WeakValueDictionary() - return type(backend).__typecache - -def global_cache(srctype, ffi, funcname, *args, **kwds): - key = kwds.pop('key', (funcname, args)) - assert not kwds - try: - return ffi._typecache[key] - except KeyError: - pass - 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._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/py3.7/lib/python3.7/site-packages/cffi/parse_c_type.h b/py3.7/lib/python3.7/site-packages/cffi/parse_c_type.h deleted file mode 100644 index 84e4ef8..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/parse_c_type.h +++ /dev/null @@ -1,181 +0,0 @@ - -/* This part is from file 'cffi/parse_c_type.h'. It is copied at the - beginning of C sources generated by CFFI's ffi.set_source(). */ - -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_OP_EXTERN_PYTHON 41 - -#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_PRIM_FLOATCOMPLEX 48 -#define _CFFI_PRIM_DOUBLECOMPLEX 49 -#define _CFFI_PRIM_CHAR16 50 -#define _CFFI_PRIM_CHAR32 51 - -#define _CFFI__NUM_PRIM 52 -#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; -}; - -struct _cffi_externpy_s { - const char *name; - size_t size_of_result; - void *reserved1, *reserved2; -}; - -#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/py3.7/lib/python3.7/site-packages/cffi/pkgconfig.py b/py3.7/lib/python3.7/site-packages/cffi/pkgconfig.py deleted file mode 100644 index 5c93f15..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/pkgconfig.py +++ /dev/null @@ -1,121 +0,0 @@ -# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi -import sys, os, subprocess - -from .error import PkgConfigError - - -def merge_flags(cfg1, cfg2): - """Merge values from cffi config flags cfg2 to cf1 - - Example: - merge_flags({"libraries": ["one"]}, {"libraries": ["two"]}) - {"libraries": ["one", "two"]} - """ - for key, value in cfg2.items(): - if key not in cfg1: - cfg1[key] = value - else: - if not isinstance(cfg1[key], list): - raise TypeError("cfg1[%r] should be a list of strings" % (key,)) - if not isinstance(value, list): - raise TypeError("cfg2[%r] should be a list of strings" % (key,)) - cfg1[key].extend(value) - return cfg1 - - -def call(libname, flag, encoding=sys.getfilesystemencoding()): - """Calls pkg-config and returns the output if found - """ - a = ["pkg-config", "--print-errors"] - a.append(flag) - a.append(libname) - try: - pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except EnvironmentError as e: - raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),)) - - bout, berr = pc.communicate() - if pc.returncode != 0: - try: - berr = berr.decode(encoding) - except Exception: - pass - raise PkgConfigError(berr.strip()) - - if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x - try: - bout = bout.decode(encoding) - except UnicodeDecodeError: - raise PkgConfigError("pkg-config %s %s returned bytes that cannot " - "be decoded with encoding %r:\n%r" % - (flag, libname, encoding, bout)) - - if os.altsep != '\\' and '\\' in bout: - raise PkgConfigError("pkg-config %s %s returned an unsupported " - "backslash-escaped output:\n%r" % - (flag, libname, bout)) - return bout - - -def flags_from_pkgconfig(libs): - r"""Return compiler line flags for FFI.set_source based on pkg-config output - - Usage - ... - ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"]) - - If pkg-config is installed on build machine, then arguments include_dirs, - library_dirs, libraries, define_macros, extra_compile_args and - extra_link_args are extended with an output of pkg-config for libfoo and - libbar. - - Raises PkgConfigError in case the pkg-config call fails. - """ - - def get_include_dirs(string): - return [x[2:] for x in string.split() if x.startswith("-I")] - - def get_library_dirs(string): - return [x[2:] for x in string.split() if x.startswith("-L")] - - def get_libraries(string): - return [x[2:] for x in string.split() if x.startswith("-l")] - - # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils - def get_macros(string): - def _macro(x): - x = x[2:] # drop "-D" - if '=' in x: - return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar") - else: - return (x, None) # "-Dfoo" => ("foo", None) - return [_macro(x) for x in string.split() if x.startswith("-D")] - - def get_other_cflags(string): - return [x for x in string.split() if not x.startswith("-I") and - not x.startswith("-D")] - - def get_other_libs(string): - return [x for x in string.split() if not x.startswith("-L") and - not x.startswith("-l")] - - # return kwargs for given libname - def kwargs(libname): - fse = sys.getfilesystemencoding() - all_cflags = call(libname, "--cflags") - all_libs = call(libname, "--libs") - return { - "include_dirs": get_include_dirs(all_cflags), - "library_dirs": get_library_dirs(all_libs), - "libraries": get_libraries(all_libs), - "define_macros": get_macros(all_cflags), - "extra_compile_args": get_other_cflags(all_cflags), - "extra_link_args": get_other_libs(all_libs), - } - - # merge all arguments together - ret = {} - for libname in libs: - lib_flags = kwargs(libname) - merge_flags(ret, lib_flags) - return ret diff --git a/py3.7/lib/python3.7/site-packages/cffi/recompiler.py b/py3.7/lib/python3.7/site-packages/cffi/recompiler.py deleted file mode 100644 index 20e912b..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/recompiler.py +++ /dev/null @@ -1,1542 +0,0 @@ -import os, sys, io -from . import ffiplatform, model -from .error import VerificationError -from .cffi_opcode import * - -VERSION_BASE = 0x2601 -VERSION_EMBEDDED = 0x2701 -VERSION_CHAR16CHAR32 = 0x2801 - - -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: - _num_externpy = 0 - - 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 - self._version = VERSION_BASE - - def needs_version(self, ver): - self._version = max(self._version, ver) - - 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 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 - if self.ffi._embedding is not None: - prnt('#define _CFFI_USE_EMBEDDING') - # - # 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)) - # - # if we have ffi._embedding != None, we give it here as a macro - # and include an extra file - base_module_name = self.module_name.split('.')[-1] - if self.ffi._embedding is not None: - prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,)) - prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {') - self._print_string_literal_in_array(self.ffi._embedding) - prnt('0 };') - prnt('#ifdef PYPY_VERSION') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( - base_module_name,)) - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( - base_module_name,)) - prnt('#else') - prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( - base_module_name,)) - prnt('#endif') - lines = self._rel_readlines('_embedding.h') - i = lines.index('#include "_cffi_errors.h"\n') - lines[i:i+1] = self._rel_readlines('_cffi_errors.h') - prnt(''.join(lines)) - self.needs_version(VERSION_EMBEDDED) - # - # 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 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 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),)) - flags = 0 - if self._num_externpy: - flags |= 1 # set to mean that we use extern "Python" - prnt(' %d, /* flags */' % flags) - prnt('};') - prnt() - # - # the init function - prnt('#ifdef __GNUC__') - prnt('# pragma GCC visibility push(default) /* for -fvisibility= */') - prnt('#endif') - prnt() - prnt('#ifdef PYPY_VERSION') - prnt('PyMODINIT_FUNC') - prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) - prnt('{') - if self._num_externpy: - prnt(' if (((intptr_t)p[0]) >= 0x0A03) {') - prnt(' _cffi_call_python_org = ' - '(void(*)(struct _cffi_externpy_s *, char *))p[1];') - prnt(' }') - prnt(' p[0] = (const void *)0x%x;' % self._version) - prnt(' p[1] = &_cffi_type_context;') - prnt('#if PY_MAJOR_VERSION >= 3') - prnt(' return NULL;') - prnt('#endif') - 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", 0x%x, &_cffi_type_context);' % ( - self.module_name, self._version)) - prnt('}') - prnt('#else') - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % (base_module_name,)) - prnt('{') - prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( - self.module_name, self._version)) - prnt('}') - prnt('#endif') - prnt() - prnt('#ifdef __GNUC__') - prnt('# pragma GCC visibility pop') - prnt('#endif') - self._version = None - - 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 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 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 = 0x%x," % (self._version,)) - self._version = None - # - # 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) and not tp.is_complex_type(): - 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: - cname = tp.get_c_name('') - converter = '(%s)_cffi_to_c_%s' % (cname, - tp.name.replace(' ', '_')) - if cname in ('char16_t', 'char32_t'): - self.needs_version(VERSION_CHAR16CHAR32) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif (isinstance(tp, model.StructOrUnionOrEnum) or - isinstance(tp, model.BasePrimitiveType)): - # a struct (not a struct pointer) as a function argument; - # or, a complex (the same code works) - 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() and tp.name != '_Bool': - 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' and not tp.is_complex_type(): - cname = tp.name.replace(' ', '_') - if cname in ('char16_t', 'char32_t'): - self.needs_version(VERSION_CHAR16CHAR32) - return '_cffi_from_c_%s(%s)' % (cname, 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.StructOrUnion): - 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 _typedef_type(self, tp, name): - return self._global_type(tp, "(*(%s *)0)" % (name,)) - - def _generate_cpy_typedef_collecttype(self, tp, name): - self._do_collect_type(self._typedef_type(tp, name)) - - 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): - tp = self._typedef_type(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() - prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % ( - name, len(rng), len(rng), - ', '.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();') - 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. We also do that for - # complex args and return type. - def need_indirection(type): - return (isinstance(type, model.StructOrUnion) or - (isinstance(type, model.PrimitiveType) and - type.is_complex_type())) - difference = False - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - indirection = '' - if need_indirection(type): - 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 need_indirection(tp_result): - 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) - if self.target_is_python: - # also requires nested anon struct/unions in ABI mode, recursively - for fldtype in tp.anonymous_struct_fields(): - self._struct_collecttype(fldtype) - - 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) | 0); /* 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 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 any(tp.anonymous_struct_fields()): - pass # field layout obtained silently from the C compiler - else: - flags.append("_CFFI_F_CHECK_FIELDS") - if tp.packed: - if tp.packed > 1: - raise NotImplementedError( - "%r is declared with 'pack=%r'; only 0 or 1 are " - "supported in API mode (try to use \"...;\", which " - "does not require a 'pack' declaration)" % - (tp, 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: - expand_anonymous_struct_union = not self.target_is_python - enumfields = list(tp.enumfields(expand_anonymous_struct_union)) - for fldname, fldtype, fbitsize, fqual in enumfields: - fldtype = self._field_type(tp, fldname, fldtype) - self._check_not_opaque(fldtype, - "field '%s.%s'" % (tp.name, fldname)) - # 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 _check_not_opaque(self, tp, location): - while isinstance(tp, model.ArrayType): - tp = tp.item - if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: - raise TypeError( - "%s is of an opaque type (not declared in cdef())" % location) - - 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 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 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))) - - # ---------- - # extern "Python" - - def _generate_cpy_extern_python_collecttype(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - self._do_collect_type(tp) - _generate_cpy_dllexport_python_collecttype = \ - _generate_cpy_extern_python_plus_c_collecttype = \ - _generate_cpy_extern_python_collecttype - - def _extern_python_decl(self, tp, name, tag_and_space): - prnt = self._prnt - if isinstance(tp.result, model.VoidType): - size_of_result = '0' - else: - context = 'result of %s' % name - size_of_result = '(int)sizeof(%s)' % ( - tp.result.get_c_name('', context),) - prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name) - prnt(' { "%s.%s", %s };' % (self.module_name, name, size_of_result)) - prnt() - # - arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arg = type.get_c_name(' a%d' % i, context) - arguments.append(arg) - # - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - name_and_arguments = '%s(%s)' % (name, repr_arguments) - if tp.abi == "__stdcall": - name_and_arguments = '_cffi_stdcall ' + name_and_arguments - # - def may_need_128_bits(tp): - return (isinstance(tp, model.PrimitiveType) and - tp.name == 'long double') - # - size_of_a = max(len(tp.args)*8, 8) - if may_need_128_bits(tp.result): - size_of_a = max(size_of_a, 16) - if isinstance(tp.result, model.StructOrUnion): - size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % ( - tp.result.get_c_name(''), size_of_a, - tp.result.get_c_name(''), size_of_a) - prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments))) - prnt('{') - prnt(' char a[%s];' % size_of_a) - prnt(' char *p = a;') - for i, type in enumerate(tp.args): - arg = 'a%d' % i - if (isinstance(type, model.StructOrUnion) or - may_need_128_bits(type)): - arg = '&' + arg - type = model.PointerType(type) - prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg)) - prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name) - if not isinstance(tp.result, model.VoidType): - prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),)) - prnt('}') - prnt() - self._num_externpy += 1 - - def _generate_cpy_extern_python_decl(self, tp, name): - self._extern_python_decl(tp, name, 'static ') - - def _generate_cpy_dllexport_python_decl(self, tp, name): - self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ') - - def _generate_cpy_extern_python_plus_c_decl(self, tp, name): - self._extern_python_decl(tp, name, '') - - def _generate_cpy_extern_python_ctx(self, tp, name): - if self.target_is_python: - raise VerificationError( - "cannot use 'extern \"Python\"' in the ABI mode") - if tp.ellipsis: - raise NotImplementedError("a vararg function is extern \"Python\"") - type_index = self._typesdict[tp] - type_op = CffiOp(OP_EXTERN_PYTHON, type_index) - self._lsts["global"].append( - GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name)) - - _generate_cpy_dllexport_python_ctx = \ - _generate_cpy_extern_python_plus_c_ctx = \ - _generate_cpy_extern_python_ctx - - def _print_string_literal_in_array(self, s): - prnt = self._prnt - prnt('// # NB. this is not a string because of a size limit in MSVC') - for line in s.splitlines(True): - prnt(('// ' + line).rstrip()) - printed_line = '' - for c in line: - if len(printed_line) >= 76: - prnt(printed_line) - printed_line = '' - printed_line += '%d,' % (ord(c),) - prnt(printed_line) - - # ---------- - # 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 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, verbose): - if verbose: - print("generating %s" % (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 - if verbose: - print("(already up-to-date)") - 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, verbose=False): - assert preamble is not None - return _make_c_or_py_source(ffi, module_name, preamble, target_c_file, - verbose) - -def make_py_source(ffi, module_name, target_py_file, verbose=False): - return _make_c_or_py_source(ffi, module_name, None, target_py_file, - verbose) - -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 - - -# Aaargh. Distutils is not tested at all for the purpose of compiling -# DLLs that are not extension modules. Here are some hacks to work -# around that, in the _patch_for_*() functions... - -def _patch_meth(patchlist, cls, name, new_meth): - old = getattr(cls, name) - patchlist.append((cls, name, old)) - setattr(cls, name, new_meth) - return old - -def _unpatch_meths(patchlist): - for cls, name, old_meth in reversed(patchlist): - setattr(cls, name, old_meth) - -def _patch_for_embedding(patchlist): - if sys.platform == 'win32': - # we must not remove the manifest when building for embedding! - from distutils.msvc9compiler import MSVCCompiler - _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref', - lambda self, manifest_file: manifest_file) - - if sys.platform == 'darwin': - # we must not make a '-bundle', but a '-dynamiclib' instead - from distutils.ccompiler import CCompiler - def my_link_shared_object(self, *args, **kwds): - if '-bundle' in self.linker_so: - self.linker_so = list(self.linker_so) - i = self.linker_so.index('-bundle') - self.linker_so[i] = '-dynamiclib' - return old_link_shared_object(self, *args, **kwds) - old_link_shared_object = _patch_meth(patchlist, CCompiler, - 'link_shared_object', - my_link_shared_object) - -def _patch_for_target(patchlist, target): - from distutils.command.build_ext import build_ext - # if 'target' is different from '*', we need to patch some internal - # method to just return this 'target' value, instead of having it - # built from module_name - if target.endswith('.*'): - target = target[:-2] - if sys.platform == 'win32': - target += '.dll' - elif sys.platform == 'darwin': - target += '.dylib' - else: - target += '.so' - _patch_meth(patchlist, build_ext, 'get_ext_filename', - lambda self, ext_name: target) - - -def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, - c_file=None, source_extension='.c', extradir=None, - compiler_verbose=1, target=None, debug=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: - embedding = (ffi._embedding is not None) - if embedding: - ffi._apply_embedding_fix(kwds) - 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 - # - if target is None: - if embedding: - target = '%s.*' % module_name - else: - target = '*' - # - ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) - updated = make_c_source(ffi, module_name, preamble, c_file, - verbose=compiler_verbose) - if call_c_compiler: - patchlist = [] - cwd = os.getcwd() - try: - if embedding: - _patch_for_embedding(patchlist) - if target != '*': - _patch_for_target(patchlist, target) - if compiler_verbose: - if tmpdir == '.': - msg = 'the current directory is' - else: - msg = 'setting the current directory to' - print('%s %r' % (msg, os.path.abspath(tmpdir))) - os.chdir(tmpdir) - outputfilename = ffiplatform.compile('.', ext, - compiler_verbose, debug) - finally: - os.chdir(cwd) - _unpatch_meths(patchlist) - 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, - verbose=compiler_verbose) - if call_c_compiler: - return c_file - else: - return None, updated - diff --git a/py3.7/lib/python3.7/site-packages/cffi/setuptools_ext.py b/py3.7/lib/python3.7/site-packages/cffi/setuptools_ext.py deleted file mode 100644 index df5a518..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/setuptools_ext.py +++ /dev/null @@ -1,217 +0,0 @@ -import os -import sys - -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 _set_py_limited_api(Extension, kwds): - """ - Add py_limited_api to kwds if setuptools >= 26 is in use. - Do not alter the setting if it already exists. - Setuptools takes care of ignoring the flag on Python 2 and PyPy. - - CPython itself should ignore the flag in a debugging version - (by not listing .abi3.so in the extensions it supports), but - it doesn't so far, creating troubles. That's why we check - for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent - of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) - - On Windows, with CPython <= 3.4, it's better not to use py_limited_api - because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. - For now we'll skip py_limited_api on all Windows versions to avoid an - inconsistent mess. - """ - if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') - and sys.platform != 'win32'): - import setuptools - try: - setuptools_major_version = int(setuptools.__version__.partition('.')[0]) - if setuptools_major_version >= 26: - kwds['py_limited_api'] = True - except ValueError: # certain development versions of setuptools - # If we don't know the version number of setuptools, we - # try to set 'py_limited_api' anyway. At worst, we get a - # warning. - kwds['py_limited_api'] = True - return kwds - -def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): - from distutils.core import Extension - # We are a setuptools extension. Need this build_ext for py_limited_api. - from setuptools.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', [])) - kwds = _set_py_limited_api(Extension, kwds) - 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 setuptools.command.build_py import build_py - from setuptools.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)) - def get_source_files(self): - # This is called from 'setup.py sdist' only. Exclude - # the generate .py module in this case. - saved_py_modules = self.py_modules - try: - if saved_py_modules: - self.py_modules = [m for m in saved_py_modules - if m != module_name] - return base_class.get_source_files(self) - finally: - self.py_modules = saved_py_modules - dist.cmdclass['build_py'] = build_py_make_mod - - # distutils and setuptools have no notion I could find of a - # generated python module. If we don't add module_name to - # dist.py_modules, then things mostly work but there are some - # combination of options (--root and --record) that will miss - # the module. So we add it here, which gives a few apparently - # harmless warnings about not finding the file outside the - # build directory. - # Then we need to hack more in get_source_files(); see above. - if dist.py_modules is None: - dist.py_modules = [] - dist.py_modules.append(module_name) - - # 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/py3.7/lib/python3.7/site-packages/cffi/vengine_cpy.py b/py3.7/lib/python3.7/site-packages/cffi/vengine_cpy.py deleted file mode 100644 index 536f11f..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/vengine_cpy.py +++ /dev/null @@ -1,1015 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys, imp -from . import model -from .error import VerificationError - - -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 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, 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 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() and tp.name != '_Bool': - 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.StructOrUnion): - 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 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 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 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 - 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 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# 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_from_c__Bool PyBool_FromLong - -#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/py3.7/lib/python3.7/site-packages/cffi/vengine_gen.py b/py3.7/lib/python3.7/site-packages/cffi/vengine_gen.py deleted file mode 100644 index a64ff64..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/vengine_gen.py +++ /dev/null @@ -1,675 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys, os -import types - -from . import model -from .error import VerificationError - - -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 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 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 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 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 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 - 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 */ -# ifndef __cplusplus - typedef unsigned char _Bool; -# endif -# endif -#else -# include -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) -# include -# endif -#endif -''' diff --git a/py3.7/lib/python3.7/site-packages/cffi/verifier.py b/py3.7/lib/python3.7/site-packages/cffi/verifier.py deleted file mode 100644 index 59b78c2..0000000 --- a/py3.7/lib/python3.7/site-packages/cffi/verifier.py +++ /dev/null @@ -1,306 +0,0 @@ -# -# DEPRECATED: implementation for ffi.verify() -# -import sys, os, binascii, shutil, io -from . import __version_verifier_modules__ -from . import ffiplatform -from .error import VerificationError - -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) - - -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 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 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 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): - ffiplatform._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): - dirname = os.path.dirname(filename) - if dirname and not os.path.isdir(dirname): - os.makedirs(dirname) diff --git a/py3.7/lib/python3.7/site-packages/click/__init__.py b/py3.7/lib/python3.7/site-packages/click/__init__.py deleted file mode 100644 index d3c3366..0000000 --- a/py3.7/lib/python3.7/site-packages/click/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -""" -click -~~~~~ - -Click is a simple Python module inspired by the stdlib optparse to make -writing command line scripts fun. Unlike other modules, it's based -around a simple API that does not come with too much magic and is -composable. - -:copyright: © 2014 by the Pallets team. -:license: BSD, see LICENSE.rst for more details. -""" - -# Core classes -from .core import Context, BaseCommand, Command, MultiCommand, Group, \ - CommandCollection, Parameter, Option, Argument - -# Globals -from .globals import get_current_context - -# Decorators -from .decorators import pass_context, pass_obj, make_pass_decorator, \ - command, group, argument, option, confirmation_option, \ - password_option, version_option, help_option - -# Types -from .types import ParamType, File, Path, Choice, IntRange, Tuple, \ - DateTime, STRING, INT, FLOAT, BOOL, UUID, UNPROCESSED, FloatRange - -# Utilities -from .utils import echo, get_binary_stream, get_text_stream, open_file, \ - format_filename, get_app_dir, get_os_args - -# Terminal functions -from .termui import prompt, confirm, get_terminal_size, echo_via_pager, \ - progressbar, clear, style, unstyle, secho, edit, launch, getchar, \ - pause - -# Exceptions -from .exceptions import ClickException, UsageError, BadParameter, \ - FileError, Abort, NoSuchOption, BadOptionUsage, BadArgumentUsage, \ - MissingParameter - -# Formatting -from .formatting import HelpFormatter, wrap_text - -# Parsing -from .parser import OptionParser - - -__all__ = [ - # Core classes - 'Context', 'BaseCommand', 'Command', 'MultiCommand', 'Group', - 'CommandCollection', 'Parameter', 'Option', 'Argument', - - # Globals - 'get_current_context', - - # Decorators - 'pass_context', 'pass_obj', 'make_pass_decorator', 'command', 'group', - 'argument', 'option', 'confirmation_option', 'password_option', - 'version_option', 'help_option', - - # Types - 'ParamType', 'File', 'Path', 'Choice', 'IntRange', 'Tuple', - 'DateTime', 'STRING', 'INT', 'FLOAT', 'BOOL', 'UUID', 'UNPROCESSED', - 'FloatRange', - - # Utilities - 'echo', 'get_binary_stream', 'get_text_stream', 'open_file', - 'format_filename', 'get_app_dir', 'get_os_args', - - # Terminal functions - 'prompt', 'confirm', 'get_terminal_size', 'echo_via_pager', - 'progressbar', 'clear', 'style', 'unstyle', 'secho', 'edit', 'launch', - 'getchar', 'pause', - - # Exceptions - 'ClickException', 'UsageError', 'BadParameter', 'FileError', - 'Abort', 'NoSuchOption', 'BadOptionUsage', 'BadArgumentUsage', - 'MissingParameter', - - # Formatting - 'HelpFormatter', 'wrap_text', - - # Parsing - 'OptionParser', -] - - -# Controls if click should emit the warning about the use of unicode -# literals. -disable_unicode_literals_warning = False - - -__version__ = '7.0' diff --git a/py3.7/lib/python3.7/site-packages/click/_bashcomplete.py b/py3.7/lib/python3.7/site-packages/click/_bashcomplete.py deleted file mode 100644 index a5f1084..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_bashcomplete.py +++ /dev/null @@ -1,293 +0,0 @@ -import copy -import os -import re - -from .utils import echo -from .parser import split_arg_string -from .core import MultiCommand, Option, Argument -from .types import Choice - -try: - from collections import abc -except ImportError: - import collections as abc - -WORDBREAK = '=' - -# Note, only BASH version 4.4 and later have the nosort option. -COMPLETION_SCRIPT_BASH = ''' -%(complete_func)s() { - local IFS=$'\n' - COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \\ - COMP_CWORD=$COMP_CWORD \\ - %(autocomplete_var)s=complete $1 ) ) - return 0 -} - -%(complete_func)setup() { - local COMPLETION_OPTIONS="" - local BASH_VERSION_ARR=(${BASH_VERSION//./ }) - # Only BASH version 4.4 and later have the nosort option. - if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] && [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then - COMPLETION_OPTIONS="-o nosort" - fi - - complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s -} - -%(complete_func)setup -''' - -COMPLETION_SCRIPT_ZSH = ''' -%(complete_func)s() { - local -a completions - local -a completions_with_descriptions - local -a response - response=("${(@f)$( env COMP_WORDS=\"${words[*]}\" \\ - COMP_CWORD=$((CURRENT-1)) \\ - %(autocomplete_var)s=\"complete_zsh\" \\ - %(script_names)s )}") - - for key descr in ${(kv)response}; do - if [[ "$descr" == "_" ]]; then - completions+=("$key") - else - completions_with_descriptions+=("$key":"$descr") - fi - done - - if [ -n "$completions_with_descriptions" ]; then - _describe -V unsorted completions_with_descriptions -U -Q - fi - - if [ -n "$completions" ]; then - compadd -U -V unsorted -Q -a completions - fi - compstate[insert]="automenu" -} - -compdef %(complete_func)s %(script_names)s -''' - -_invalid_ident_char_re = re.compile(r'[^a-zA-Z0-9_]') - - -def get_completion_script(prog_name, complete_var, shell): - cf_name = _invalid_ident_char_re.sub('', prog_name.replace('-', '_')) - script = COMPLETION_SCRIPT_ZSH if shell == 'zsh' else COMPLETION_SCRIPT_BASH - return (script % { - 'complete_func': '_%s_completion' % cf_name, - 'script_names': prog_name, - 'autocomplete_var': complete_var, - }).strip() + ';' - - -def resolve_ctx(cli, prog_name, args): - """ - Parse into a hierarchy of contexts. Contexts are connected through the parent variable. - :param cli: command definition - :param prog_name: the program that is running - :param args: full list of args - :return: the final context/command parsed - """ - ctx = cli.make_context(prog_name, args, resilient_parsing=True) - args = ctx.protected_args + ctx.args - while args: - if isinstance(ctx.command, MultiCommand): - if not ctx.command.chain: - cmd_name, cmd, args = ctx.command.resolve_command(ctx, args) - if cmd is None: - return ctx - ctx = cmd.make_context(cmd_name, args, parent=ctx, - resilient_parsing=True) - args = ctx.protected_args + ctx.args - else: - # Walk chained subcommand contexts saving the last one. - while args: - cmd_name, cmd, args = ctx.command.resolve_command(ctx, args) - if cmd is None: - return ctx - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - resilient_parsing=True) - args = sub_ctx.args - ctx = sub_ctx - args = sub_ctx.protected_args + sub_ctx.args - else: - break - return ctx - - -def start_of_option(param_str): - """ - :param param_str: param_str to check - :return: whether or not this is the start of an option declaration (i.e. starts "-" or "--") - """ - return param_str and param_str[:1] == '-' - - -def is_incomplete_option(all_args, cmd_param): - """ - :param all_args: the full original list of args supplied - :param cmd_param: the current command paramter - :return: whether or not the last option declaration (i.e. starts "-" or "--") is incomplete and - corresponds to this cmd_param. In other words whether this cmd_param option can still accept - values - """ - if not isinstance(cmd_param, Option): - return False - if cmd_param.is_flag: - return False - last_option = None - for index, arg_str in enumerate(reversed([arg for arg in all_args if arg != WORDBREAK])): - if index + 1 > cmd_param.nargs: - break - if start_of_option(arg_str): - last_option = arg_str - - return True if last_option and last_option in cmd_param.opts else False - - -def is_incomplete_argument(current_params, cmd_param): - """ - :param current_params: the current params and values for this argument as already entered - :param cmd_param: the current command parameter - :return: whether or not the last argument is incomplete and corresponds to this cmd_param. In - other words whether or not the this cmd_param argument can still accept values - """ - if not isinstance(cmd_param, Argument): - return False - current_param_values = current_params[cmd_param.name] - if current_param_values is None: - return True - if cmd_param.nargs == -1: - return True - if isinstance(current_param_values, abc.Iterable) \ - and cmd_param.nargs > 1 and len(current_param_values) < cmd_param.nargs: - return True - return False - - -def get_user_autocompletions(ctx, args, incomplete, cmd_param): - """ - :param ctx: context associated with the parsed command - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :param cmd_param: command definition - :return: all the possible user-specified completions for the param - """ - results = [] - if isinstance(cmd_param.type, Choice): - # Choices don't support descriptions. - results = [(c, None) - for c in cmd_param.type.choices if str(c).startswith(incomplete)] - elif cmd_param.autocompletion is not None: - dynamic_completions = cmd_param.autocompletion(ctx=ctx, - args=args, - incomplete=incomplete) - results = [c if isinstance(c, tuple) else (c, None) - for c in dynamic_completions] - return results - - -def get_visible_commands_starting_with(ctx, starts_with): - """ - :param ctx: context associated with the parsed command - :starts_with: string that visible commands must start with. - :return: all visible (not hidden) commands that start with starts_with. - """ - for c in ctx.command.list_commands(ctx): - if c.startswith(starts_with): - command = ctx.command.get_command(ctx, c) - if not command.hidden: - yield command - - -def add_subcommand_completions(ctx, incomplete, completions_out): - # Add subcommand completions. - if isinstance(ctx.command, MultiCommand): - completions_out.extend( - [(c.name, c.get_short_help_str()) for c in get_visible_commands_starting_with(ctx, incomplete)]) - - # Walk up the context list and add any other completion possibilities from chained commands - while ctx.parent is not None: - ctx = ctx.parent - if isinstance(ctx.command, MultiCommand) and ctx.command.chain: - remaining_commands = [c for c in get_visible_commands_starting_with(ctx, incomplete) - if c.name not in ctx.protected_args] - completions_out.extend([(c.name, c.get_short_help_str()) for c in remaining_commands]) - - -def get_choices(cli, prog_name, args, incomplete): - """ - :param cli: command definition - :param prog_name: the program that is running - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :return: all the possible completions for the incomplete - """ - all_args = copy.deepcopy(args) - - ctx = resolve_ctx(cli, prog_name, args) - if ctx is None: - return [] - - # In newer versions of bash long opts with '='s are partitioned, but it's easier to parse - # without the '=' - if start_of_option(incomplete) and WORDBREAK in incomplete: - partition_incomplete = incomplete.partition(WORDBREAK) - all_args.append(partition_incomplete[0]) - incomplete = partition_incomplete[2] - elif incomplete == WORDBREAK: - incomplete = '' - - completions = [] - if start_of_option(incomplete): - # completions for partial options - for param in ctx.command.params: - if isinstance(param, Option) and not param.hidden: - param_opts = [param_opt for param_opt in param.opts + - param.secondary_opts if param_opt not in all_args or param.multiple] - completions.extend([(o, param.help) for o in param_opts if o.startswith(incomplete)]) - return completions - # completion for option values from user supplied values - for param in ctx.command.params: - if is_incomplete_option(all_args, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - # completion for argument values from user supplied values - for param in ctx.command.params: - if is_incomplete_argument(ctx.params, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - - add_subcommand_completions(ctx, incomplete, completions) - # Sort before returning so that proper ordering can be enforced in custom types. - return sorted(completions) - - -def do_complete(cli, prog_name, include_descriptions): - cwords = split_arg_string(os.environ['COMP_WORDS']) - cword = int(os.environ['COMP_CWORD']) - args = cwords[1:cword] - try: - incomplete = cwords[cword] - except IndexError: - incomplete = '' - - for item in get_choices(cli, prog_name, args, incomplete): - echo(item[0]) - if include_descriptions: - # ZSH has trouble dealing with empty array parameters when returned from commands, so use a well defined character '_' to indicate no description is present. - echo(item[1] if item[1] else '_') - - return True - - -def bashcomplete(cli, prog_name, complete_var, complete_instr): - if complete_instr.startswith('source'): - shell = 'zsh' if complete_instr == 'source_zsh' else 'bash' - echo(get_completion_script(prog_name, complete_var, shell)) - return True - elif complete_instr == 'complete' or complete_instr == 'complete_zsh': - return do_complete(cli, prog_name, complete_instr == 'complete_zsh') - return False diff --git a/py3.7/lib/python3.7/site-packages/click/_compat.py b/py3.7/lib/python3.7/site-packages/click/_compat.py deleted file mode 100644 index 937e230..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_compat.py +++ /dev/null @@ -1,703 +0,0 @@ -import re -import io -import os -import sys -import codecs -from weakref import WeakKeyDictionary - - -PY2 = sys.version_info[0] == 2 -CYGWIN = sys.platform.startswith('cygwin') -# Determine local App Engine environment, per Google's own suggestion -APP_ENGINE = ('APPENGINE_RUNTIME' in os.environ and - 'Development/' in os.environ['SERVER_SOFTWARE']) -WIN = sys.platform.startswith('win') and not APP_ENGINE -DEFAULT_COLUMNS = 80 - - -_ansi_re = re.compile(r'\033\[((?:\d|;)*)([a-zA-Z])') - - -def get_filesystem_encoding(): - return sys.getfilesystemencoding() or sys.getdefaultencoding() - - -def _make_text_stream(stream, encoding, errors, - force_readable=False, force_writable=False): - if encoding is None: - encoding = get_best_encoding(stream) - if errors is None: - errors = 'replace' - return _NonClosingTextIOWrapper(stream, encoding, errors, - line_buffering=True, - force_readable=force_readable, - force_writable=force_writable) - - -def is_ascii_encoding(encoding): - """Checks if a given encoding is ascii.""" - try: - return codecs.lookup(encoding).name == 'ascii' - except LookupError: - return False - - -def get_best_encoding(stream): - """Returns the default stream encoding if not found.""" - rv = getattr(stream, 'encoding', None) or sys.getdefaultencoding() - if is_ascii_encoding(rv): - return 'utf-8' - return rv - - -class _NonClosingTextIOWrapper(io.TextIOWrapper): - - def __init__(self, stream, encoding, errors, - force_readable=False, force_writable=False, **extra): - self._stream = stream = _FixupStream(stream, force_readable, - force_writable) - io.TextIOWrapper.__init__(self, stream, encoding, errors, **extra) - - # The io module is a place where the Python 3 text behavior - # was forced upon Python 2, so we need to unbreak - # it to look like Python 2. - if PY2: - def write(self, x): - if isinstance(x, str) or is_bytes(x): - try: - self.flush() - except Exception: - pass - return self.buffer.write(str(x)) - return io.TextIOWrapper.write(self, x) - - def writelines(self, lines): - for line in lines: - self.write(line) - - def __del__(self): - try: - self.detach() - except Exception: - pass - - def isatty(self): - # https://bitbucket.org/pypy/pypy/issue/1803 - return self._stream.isatty() - - -class _FixupStream(object): - """The new io interface needs more from streams than streams - traditionally implement. As such, this fix-up code is necessary in - some circumstances. - - The forcing of readable and writable flags are there because some tools - put badly patched objects on sys (one such offender are certain version - of jupyter notebook). - """ - - def __init__(self, stream, force_readable=False, force_writable=False): - self._stream = stream - self._force_readable = force_readable - self._force_writable = force_writable - - def __getattr__(self, name): - return getattr(self._stream, name) - - def read1(self, size): - f = getattr(self._stream, 'read1', None) - if f is not None: - return f(size) - # We only dispatch to readline instead of read in Python 2 as we - # do not want cause problems with the different implementation - # of line buffering. - if PY2: - return self._stream.readline(size) - return self._stream.read(size) - - def readable(self): - if self._force_readable: - return True - x = getattr(self._stream, 'readable', None) - if x is not None: - return x() - try: - self._stream.read(0) - except Exception: - return False - return True - - def writable(self): - if self._force_writable: - return True - x = getattr(self._stream, 'writable', None) - if x is not None: - return x() - try: - self._stream.write('') - except Exception: - try: - self._stream.write(b'') - except Exception: - return False - return True - - def seekable(self): - x = getattr(self._stream, 'seekable', None) - if x is not None: - return x() - try: - self._stream.seek(self._stream.tell()) - except Exception: - return False - return True - - -if PY2: - text_type = unicode - bytes = str - raw_input = raw_input - string_types = (str, unicode) - int_types = (int, long) - iteritems = lambda x: x.iteritems() - range_type = xrange - - def is_bytes(x): - return isinstance(x, (buffer, bytearray)) - - _identifier_re = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*$') - - # For Windows, we need to force stdout/stdin/stderr to binary if it's - # fetched for that. This obviously is not the most correct way to do - # it as it changes global state. Unfortunately, there does not seem to - # be a clear better way to do it as just reopening the file in binary - # mode does not change anything. - # - # An option would be to do what Python 3 does and to open the file as - # binary only, patch it back to the system, and then use a wrapper - # stream that converts newlines. It's not quite clear what's the - # correct option here. - # - # This code also lives in _winconsole for the fallback to the console - # emulation stream. - # - # There are also Windows environments where the `msvcrt` module is not - # available (which is why we use try-catch instead of the WIN variable - # here), such as the Google App Engine development server on Windows. In - # those cases there is just nothing we can do. - def set_binary_mode(f): - return f - - try: - import msvcrt - except ImportError: - pass - else: - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - msvcrt.setmode(fileno, os.O_BINARY) - return f - - try: - import fcntl - except ImportError: - pass - else: - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - flags = fcntl.fcntl(fileno, fcntl.F_GETFL) - fcntl.fcntl(fileno, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) - return f - - def isidentifier(x): - return _identifier_re.search(x) is not None - - def get_binary_stdin(): - return set_binary_mode(sys.stdin) - - def get_binary_stdout(): - _wrap_std_stream('stdout') - return set_binary_mode(sys.stdout) - - def get_binary_stderr(): - _wrap_std_stream('stderr') - return set_binary_mode(sys.stderr) - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdin, encoding, errors, - force_readable=True) - - def get_text_stdout(encoding=None, errors=None): - _wrap_std_stream('stdout') - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdout, encoding, errors, - force_writable=True) - - def get_text_stderr(encoding=None, errors=None): - _wrap_std_stream('stderr') - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stderr, encoding, errors, - force_writable=True) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), 'replace') - return value -else: - import io - text_type = str - raw_input = input - string_types = (str,) - int_types = (int,) - range_type = range - isidentifier = lambda x: x.isidentifier() - iteritems = lambda x: iter(x.items()) - - def is_bytes(x): - return isinstance(x, (bytes, memoryview, bytearray)) - - def _is_binary_reader(stream, default=False): - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - def _is_binary_writer(stream, default=False): - try: - stream.write(b'') - except Exception: - try: - stream.write('') - return False - except Exception: - pass - return default - return True - - def _find_binary_reader(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_reader(stream, False): - return stream - - buf = getattr(stream, 'buffer', None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_reader(buf, True): - return buf - - def _find_binary_writer(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detatching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_writer(stream, False): - return stream - - buf = getattr(stream, 'buffer', None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_writer(buf, True): - return buf - - def _stream_is_misconfigured(stream): - """A stream is misconfigured if its encoding is ASCII.""" - # If the stream does not have an encoding set, we assume it's set - # to ASCII. This appears to happen in certain unittest - # environments. It's not quite clear what the correct behavior is - # but this at least will force Click to recover somehow. - return is_ascii_encoding(getattr(stream, 'encoding', None) or 'ascii') - - def _is_compatible_text_stream(stream, encoding, errors): - stream_encoding = getattr(stream, 'encoding', None) - stream_errors = getattr(stream, 'errors', None) - - # Perfect match. - if stream_encoding == encoding and stream_errors == errors: - return True - - # Otherwise, it's only a compatible stream if we did not ask for - # an encoding. - if encoding is None: - return stream_encoding is not None - - return False - - def _force_correct_text_reader(text_reader, encoding, errors, - force_readable=False): - if _is_binary_reader(text_reader, False): - binary_reader = text_reader - else: - # If there is no target encoding set, we need to verify that the - # reader is not actually misconfigured. - if encoding is None and not _stream_is_misconfigured(text_reader): - return text_reader - - if _is_compatible_text_stream(text_reader, encoding, errors): - return text_reader - - # If the reader has no encoding, we try to find the underlying - # binary reader for it. If that fails because the environment is - # misconfigured, we silently go with the same reader because this - # is too common to happen. In that case, mojibake is better than - # exceptions. - binary_reader = _find_binary_reader(text_reader) - if binary_reader is None: - return text_reader - - # At this point, we default the errors to replace instead of strict - # because nobody handles those errors anyways and at this point - # we're so fundamentally fucked that nothing can repair it. - if errors is None: - errors = 'replace' - return _make_text_stream(binary_reader, encoding, errors, - force_readable=force_readable) - - def _force_correct_text_writer(text_writer, encoding, errors, - force_writable=False): - if _is_binary_writer(text_writer, False): - binary_writer = text_writer - else: - # If there is no target encoding set, we need to verify that the - # writer is not actually misconfigured. - if encoding is None and not _stream_is_misconfigured(text_writer): - return text_writer - - if _is_compatible_text_stream(text_writer, encoding, errors): - return text_writer - - # If the writer has no encoding, we try to find the underlying - # binary writer for it. If that fails because the environment is - # misconfigured, we silently go with the same writer because this - # is too common to happen. In that case, mojibake is better than - # exceptions. - binary_writer = _find_binary_writer(text_writer) - if binary_writer is None: - return text_writer - - # At this point, we default the errors to replace instead of strict - # because nobody handles those errors anyways and at this point - # we're so fundamentally fucked that nothing can repair it. - if errors is None: - errors = 'replace' - return _make_text_stream(binary_writer, encoding, errors, - force_writable=force_writable) - - def get_binary_stdin(): - reader = _find_binary_reader(sys.stdin) - if reader is None: - raise RuntimeError('Was not able to determine binary ' - 'stream for sys.stdin.') - return reader - - def get_binary_stdout(): - writer = _find_binary_writer(sys.stdout) - if writer is None: - raise RuntimeError('Was not able to determine binary ' - 'stream for sys.stdout.') - return writer - - def get_binary_stderr(): - writer = _find_binary_writer(sys.stderr) - if writer is None: - raise RuntimeError('Was not able to determine binary ' - 'stream for sys.stderr.') - return writer - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_reader(sys.stdin, encoding, errors, - force_readable=True) - - def get_text_stdout(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stdout, encoding, errors, - force_writable=True) - - def get_text_stderr(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stderr, encoding, errors, - force_writable=True) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), 'replace') - else: - value = value.encode('utf-8', 'surrogateescape') \ - .decode('utf-8', 'replace') - return value - - -def get_streerror(e, default=None): - if hasattr(e, 'strerror'): - msg = e.strerror - else: - if default is not None: - msg = default - else: - msg = str(e) - if isinstance(msg, bytes): - msg = msg.decode('utf-8', 'replace') - return msg - - -def open_stream(filename, mode='r', encoding=None, errors='strict', - atomic=False): - # Standard streams first. These are simple because they don't need - # special handling for the atomic flag. It's entirely ignored. - if filename == '-': - if any(m in mode for m in ['w', 'a', 'x']): - if 'b' in mode: - return get_binary_stdout(), False - return get_text_stdout(encoding=encoding, errors=errors), False - if 'b' in mode: - return get_binary_stdin(), False - return get_text_stdin(encoding=encoding, errors=errors), False - - # Non-atomic writes directly go out through the regular open functions. - if not atomic: - if encoding is None: - return open(filename, mode), True - return io.open(filename, mode, encoding=encoding, errors=errors), True - - # Some usability stuff for atomic writes - if 'a' in mode: - raise ValueError( - 'Appending to an existing file is not supported, because that ' - 'would involve an expensive `copy`-operation to a temporary ' - 'file. Open the file in normal `w`-mode and copy explicitly ' - 'if that\'s what you\'re after.' - ) - if 'x' in mode: - raise ValueError('Use the `overwrite`-parameter instead.') - if 'w' not in mode: - raise ValueError('Atomic writes only make sense with `w`-mode.') - - # Atomic writes are more complicated. They work by opening a file - # as a proxy in the same folder and then using the fdopen - # functionality to wrap it in a Python file. Then we wrap it in an - # atomic file that moves the file over on close. - import tempfile - fd, tmp_filename = tempfile.mkstemp(dir=os.path.dirname(filename), - prefix='.__atomic-write') - - if encoding is not None: - f = io.open(fd, mode, encoding=encoding, errors=errors) - else: - f = os.fdopen(fd, mode) - - return _AtomicFile(f, tmp_filename, os.path.realpath(filename)), True - - -# Used in a destructor call, needs extra protection from interpreter cleanup. -if hasattr(os, 'replace'): - _replace = os.replace - _can_replace = True -else: - _replace = os.rename - _can_replace = not WIN - - -class _AtomicFile(object): - - def __init__(self, f, tmp_filename, real_filename): - self._f = f - self._tmp_filename = tmp_filename - self._real_filename = real_filename - self.closed = False - - @property - def name(self): - return self._real_filename - - def close(self, delete=False): - if self.closed: - return - self._f.close() - if not _can_replace: - try: - os.remove(self._real_filename) - except OSError: - pass - _replace(self._tmp_filename, self._real_filename) - self.closed = True - - def __getattr__(self, name): - return getattr(self._f, name) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close(delete=exc_type is not None) - - def __repr__(self): - return repr(self._f) - - -auto_wrap_for_ansi = None -colorama = None -get_winterm_size = None - - -def strip_ansi(value): - return _ansi_re.sub('', value) - - -def should_strip_ansi(stream=None, color=None): - if color is None: - if stream is None: - stream = sys.stdin - return not isatty(stream) - return not color - - -# If we're on Windows, we provide transparent integration through -# colorama. This will make ANSI colors through the echo function -# work automatically. -if WIN: - # Windows has a smaller terminal - DEFAULT_COLUMNS = 79 - - from ._winconsole import _get_windows_console_stream, _wrap_std_stream - - def _get_argv_encoding(): - import locale - return locale.getpreferredencoding() - - if PY2: - def raw_input(prompt=''): - sys.stderr.flush() - if prompt: - stdout = _default_text_stdout() - stdout.write(prompt) - stdin = _default_text_stdin() - return stdin.readline().rstrip('\r\n') - - try: - import colorama - except ImportError: - pass - else: - _ansi_stream_wrappers = WeakKeyDictionary() - - def auto_wrap_for_ansi(stream, color=None): - """This function wraps a stream so that calls through colorama - are issued to the win32 console API to recolor on demand. It - also ensures to reset the colors if a write call is interrupted - to not destroy the console afterwards. - """ - try: - cached = _ansi_stream_wrappers.get(stream) - except Exception: - cached = None - if cached is not None: - return cached - strip = should_strip_ansi(stream, color) - ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) - rv = ansi_wrapper.stream - _write = rv.write - - def _safe_write(s): - try: - return _write(s) - except: - ansi_wrapper.reset_all() - raise - - rv.write = _safe_write - try: - _ansi_stream_wrappers[stream] = rv - except Exception: - pass - return rv - - def get_winterm_size(): - win = colorama.win32.GetConsoleScreenBufferInfo( - colorama.win32.STDOUT).srWindow - return win.Right - win.Left, win.Bottom - win.Top -else: - def _get_argv_encoding(): - return getattr(sys.stdin, 'encoding', None) or get_filesystem_encoding() - - _get_windows_console_stream = lambda *x: None - _wrap_std_stream = lambda *x: None - - -def term_len(x): - return len(strip_ansi(x)) - - -def isatty(stream): - try: - return stream.isatty() - except Exception: - return False - - -def _make_cached_stream_func(src_func, wrapper_func): - cache = WeakKeyDictionary() - def func(): - stream = src_func() - try: - rv = cache.get(stream) - except Exception: - rv = None - if rv is not None: - return rv - rv = wrapper_func() - try: - stream = src_func() # In case wrapper_func() modified the stream - cache[stream] = rv - except Exception: - pass - return rv - return func - - -_default_text_stdin = _make_cached_stream_func( - lambda: sys.stdin, get_text_stdin) -_default_text_stdout = _make_cached_stream_func( - lambda: sys.stdout, get_text_stdout) -_default_text_stderr = _make_cached_stream_func( - lambda: sys.stderr, get_text_stderr) - - -binary_streams = { - 'stdin': get_binary_stdin, - 'stdout': get_binary_stdout, - 'stderr': get_binary_stderr, -} - -text_streams = { - 'stdin': get_text_stdin, - 'stdout': get_text_stdout, - 'stderr': get_text_stderr, -} diff --git a/py3.7/lib/python3.7/site-packages/click/_termui_impl.py b/py3.7/lib/python3.7/site-packages/click/_termui_impl.py deleted file mode 100644 index 00a8e5e..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_termui_impl.py +++ /dev/null @@ -1,621 +0,0 @@ -# -*- coding: utf-8 -*- -""" -click._termui_impl -~~~~~~~~~~~~~~~~~~ - -This module contains implementations for the termui module. To keep the -import time of Click down, some infrequently used functionality is -placed in this module and only imported as needed. - -:copyright: © 2014 by the Pallets team. -:license: BSD, see LICENSE.rst for more details. -""" - -import os -import sys -import time -import math -import contextlib -from ._compat import _default_text_stdout, range_type, PY2, isatty, \ - open_stream, strip_ansi, term_len, get_best_encoding, WIN, int_types, \ - CYGWIN -from .utils import echo -from .exceptions import ClickException - - -if os.name == 'nt': - BEFORE_BAR = '\r' - AFTER_BAR = '\n' -else: - BEFORE_BAR = '\r\033[?25l' - AFTER_BAR = '\033[?25h\n' - - -def _length_hint(obj): - """Returns the length hint of an object.""" - try: - return len(obj) - except (AttributeError, TypeError): - try: - get_hint = type(obj).__length_hint__ - except AttributeError: - return None - try: - hint = get_hint(obj) - except TypeError: - return None - if hint is NotImplemented or \ - not isinstance(hint, int_types) or \ - hint < 0: - return None - return hint - - -class ProgressBar(object): - - def __init__(self, iterable, length=None, fill_char='#', empty_char=' ', - bar_template='%(bar)s', info_sep=' ', show_eta=True, - show_percent=None, show_pos=False, item_show_func=None, - label=None, file=None, color=None, width=30): - self.fill_char = fill_char - self.empty_char = empty_char - self.bar_template = bar_template - self.info_sep = info_sep - self.show_eta = show_eta - self.show_percent = show_percent - self.show_pos = show_pos - self.item_show_func = item_show_func - self.label = label or '' - if file is None: - file = _default_text_stdout() - self.file = file - self.color = color - self.width = width - self.autowidth = width == 0 - - if length is None: - length = _length_hint(iterable) - if iterable is None: - if length is None: - raise TypeError('iterable or length is required') - iterable = range_type(length) - self.iter = iter(iterable) - self.length = length - self.length_known = length is not None - self.pos = 0 - self.avg = [] - self.start = self.last_eta = time.time() - self.eta_known = False - self.finished = False - self.max_width = None - self.entered = False - self.current_item = None - self.is_hidden = not isatty(self.file) - self._last_line = None - self.short_limit = 0.5 - - def __enter__(self): - self.entered = True - self.render_progress() - return self - - def __exit__(self, exc_type, exc_value, tb): - self.render_finish() - - def __iter__(self): - if not self.entered: - raise RuntimeError('You need to use progress bars in a with block.') - self.render_progress() - return self.generator() - - def is_fast(self): - return time.time() - self.start <= self.short_limit - - def render_finish(self): - if self.is_hidden or self.is_fast(): - return - self.file.write(AFTER_BAR) - self.file.flush() - - @property - def pct(self): - if self.finished: - return 1.0 - return min(self.pos / (float(self.length) or 1), 1.0) - - @property - def time_per_iteration(self): - if not self.avg: - return 0.0 - return sum(self.avg) / float(len(self.avg)) - - @property - def eta(self): - if self.length_known and not self.finished: - return self.time_per_iteration * (self.length - self.pos) - return 0.0 - - def format_eta(self): - if self.eta_known: - t = int(self.eta) - seconds = t % 60 - t //= 60 - minutes = t % 60 - t //= 60 - hours = t % 24 - t //= 24 - if t > 0: - days = t - return '%dd %02d:%02d:%02d' % (days, hours, minutes, seconds) - else: - return '%02d:%02d:%02d' % (hours, minutes, seconds) - return '' - - def format_pos(self): - pos = str(self.pos) - if self.length_known: - pos += '/%s' % self.length - return pos - - def format_pct(self): - return ('% 4d%%' % int(self.pct * 100))[1:] - - def format_bar(self): - if self.length_known: - bar_length = int(self.pct * self.width) - bar = self.fill_char * bar_length - bar += self.empty_char * (self.width - bar_length) - elif self.finished: - bar = self.fill_char * self.width - else: - bar = list(self.empty_char * (self.width or 1)) - if self.time_per_iteration != 0: - bar[int((math.cos(self.pos * self.time_per_iteration) - / 2.0 + 0.5) * self.width)] = self.fill_char - bar = ''.join(bar) - return bar - - def format_progress_line(self): - show_percent = self.show_percent - - info_bits = [] - if self.length_known and show_percent is None: - show_percent = not self.show_pos - - if self.show_pos: - info_bits.append(self.format_pos()) - if show_percent: - info_bits.append(self.format_pct()) - if self.show_eta and self.eta_known and not self.finished: - info_bits.append(self.format_eta()) - if self.item_show_func is not None: - item_info = self.item_show_func(self.current_item) - if item_info is not None: - info_bits.append(item_info) - - return (self.bar_template % { - 'label': self.label, - 'bar': self.format_bar(), - 'info': self.info_sep.join(info_bits) - }).rstrip() - - def render_progress(self): - from .termui import get_terminal_size - - if self.is_hidden: - return - - buf = [] - # Update width in case the terminal has been resized - if self.autowidth: - old_width = self.width - self.width = 0 - clutter_length = term_len(self.format_progress_line()) - new_width = max(0, get_terminal_size()[0] - clutter_length) - if new_width < old_width: - buf.append(BEFORE_BAR) - buf.append(' ' * self.max_width) - self.max_width = new_width - self.width = new_width - - clear_width = self.width - if self.max_width is not None: - clear_width = self.max_width - - buf.append(BEFORE_BAR) - line = self.format_progress_line() - line_len = term_len(line) - if self.max_width is None or self.max_width < line_len: - self.max_width = line_len - - buf.append(line) - buf.append(' ' * (clear_width - line_len)) - line = ''.join(buf) - # Render the line only if it changed. - - if line != self._last_line and not self.is_fast(): - self._last_line = line - echo(line, file=self.file, color=self.color, nl=False) - self.file.flush() - - def make_step(self, n_steps): - self.pos += n_steps - if self.length_known and self.pos >= self.length: - self.finished = True - - if (time.time() - self.last_eta) < 1.0: - return - - self.last_eta = time.time() - - # self.avg is a rolling list of length <= 7 of steps where steps are - # defined as time elapsed divided by the total progress through - # self.length. - if self.pos: - step = (time.time() - self.start) / self.pos - else: - step = time.time() - self.start - - self.avg = self.avg[-6:] + [step] - - self.eta_known = self.length_known - - def update(self, n_steps): - self.make_step(n_steps) - self.render_progress() - - def finish(self): - self.eta_known = 0 - self.current_item = None - self.finished = True - - def generator(self): - """ - Returns a generator which yields the items added to the bar during - construction, and updates the progress bar *after* the yielded block - returns. - """ - if not self.entered: - raise RuntimeError('You need to use progress bars in a with block.') - - if self.is_hidden: - for rv in self.iter: - yield rv - else: - for rv in self.iter: - self.current_item = rv - yield rv - self.update(1) - self.finish() - self.render_progress() - - -def pager(generator, color=None): - """Decide what method to use for paging through text.""" - stdout = _default_text_stdout() - if not isatty(sys.stdin) or not isatty(stdout): - return _nullpager(stdout, generator, color) - pager_cmd = (os.environ.get('PAGER', None) or '').strip() - if pager_cmd: - if WIN: - return _tempfilepager(generator, pager_cmd, color) - return _pipepager(generator, pager_cmd, color) - if os.environ.get('TERM') in ('dumb', 'emacs'): - return _nullpager(stdout, generator, color) - if WIN or sys.platform.startswith('os2'): - return _tempfilepager(generator, 'more <', color) - if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0: - return _pipepager(generator, 'less', color) - - import tempfile - fd, filename = tempfile.mkstemp() - os.close(fd) - try: - if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0: - return _pipepager(generator, 'more', color) - return _nullpager(stdout, generator, color) - finally: - os.unlink(filename) - - -def _pipepager(generator, cmd, color): - """Page through text by feeding it to another program. Invoking a - pager through this might support colors. - """ - import subprocess - env = dict(os.environ) - - # If we're piping to less we might support colors under the - # condition that - cmd_detail = cmd.rsplit('/', 1)[-1].split() - if color is None and cmd_detail[0] == 'less': - less_flags = os.environ.get('LESS', '') + ' '.join(cmd_detail[1:]) - if not less_flags: - env['LESS'] = '-R' - color = True - elif 'r' in less_flags or 'R' in less_flags: - color = True - - c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, - env=env) - encoding = get_best_encoding(c.stdin) - try: - for text in generator: - if not color: - text = strip_ansi(text) - - c.stdin.write(text.encode(encoding, 'replace')) - except (IOError, KeyboardInterrupt): - pass - else: - c.stdin.close() - - # Less doesn't respect ^C, but catches it for its own UI purposes (aborting - # search or other commands inside less). - # - # That means when the user hits ^C, the parent process (click) terminates, - # but less is still alive, paging the output and messing up the terminal. - # - # If the user wants to make the pager exit on ^C, they should set - # `LESS='-K'`. It's not our decision to make. - while True: - try: - c.wait() - except KeyboardInterrupt: - pass - else: - break - - -def _tempfilepager(generator, cmd, color): - """Page through text by invoking a program on a temporary file.""" - import tempfile - filename = tempfile.mktemp() - # TODO: This never terminates if the passed generator never terminates. - text = "".join(generator) - if not color: - text = strip_ansi(text) - encoding = get_best_encoding(sys.stdout) - with open_stream(filename, 'wb')[0] as f: - f.write(text.encode(encoding)) - try: - os.system(cmd + ' "' + filename + '"') - finally: - os.unlink(filename) - - -def _nullpager(stream, generator, color): - """Simply print unformatted text. This is the ultimate fallback.""" - for text in generator: - if not color: - text = strip_ansi(text) - stream.write(text) - - -class Editor(object): - - def __init__(self, editor=None, env=None, require_save=True, - extension='.txt'): - self.editor = editor - self.env = env - self.require_save = require_save - self.extension = extension - - def get_editor(self): - if self.editor is not None: - return self.editor - for key in 'VISUAL', 'EDITOR': - rv = os.environ.get(key) - if rv: - return rv - if WIN: - return 'notepad' - for editor in 'vim', 'nano': - if os.system('which %s >/dev/null 2>&1' % editor) == 0: - return editor - return 'vi' - - def edit_file(self, filename): - import subprocess - editor = self.get_editor() - if self.env: - environ = os.environ.copy() - environ.update(self.env) - else: - environ = None - try: - c = subprocess.Popen('%s "%s"' % (editor, filename), - env=environ, shell=True) - exit_code = c.wait() - if exit_code != 0: - raise ClickException('%s: Editing failed!' % editor) - except OSError as e: - raise ClickException('%s: Editing failed: %s' % (editor, e)) - - def edit(self, text): - import tempfile - - text = text or '' - if text and not text.endswith('\n'): - text += '\n' - - fd, name = tempfile.mkstemp(prefix='editor-', suffix=self.extension) - try: - if WIN: - encoding = 'utf-8-sig' - text = text.replace('\n', '\r\n') - else: - encoding = 'utf-8' - text = text.encode(encoding) - - f = os.fdopen(fd, 'wb') - f.write(text) - f.close() - timestamp = os.path.getmtime(name) - - self.edit_file(name) - - if self.require_save \ - and os.path.getmtime(name) == timestamp: - return None - - f = open(name, 'rb') - try: - rv = f.read() - finally: - f.close() - return rv.decode('utf-8-sig').replace('\r\n', '\n') - finally: - os.unlink(name) - - -def open_url(url, wait=False, locate=False): - import subprocess - - def _unquote_file(url): - try: - import urllib - except ImportError: - import urllib - if url.startswith('file://'): - url = urllib.unquote(url[7:]) - return url - - if sys.platform == 'darwin': - args = ['open'] - if wait: - args.append('-W') - if locate: - args.append('-R') - args.append(_unquote_file(url)) - null = open('/dev/null', 'w') - try: - return subprocess.Popen(args, stderr=null).wait() - finally: - null.close() - elif WIN: - if locate: - url = _unquote_file(url) - args = 'explorer /select,"%s"' % _unquote_file( - url.replace('"', '')) - else: - args = 'start %s "" "%s"' % ( - wait and '/WAIT' or '', url.replace('"', '')) - return os.system(args) - elif CYGWIN: - if locate: - url = _unquote_file(url) - args = 'cygstart "%s"' % (os.path.dirname(url).replace('"', '')) - else: - args = 'cygstart %s "%s"' % ( - wait and '-w' or '', url.replace('"', '')) - return os.system(args) - - try: - if locate: - url = os.path.dirname(_unquote_file(url)) or '.' - else: - url = _unquote_file(url) - c = subprocess.Popen(['xdg-open', url]) - if wait: - return c.wait() - return 0 - except OSError: - if url.startswith(('http://', 'https://')) and not locate and not wait: - import webbrowser - webbrowser.open(url) - return 0 - return 1 - - -def _translate_ch_to_exc(ch): - if ch == u'\x03': - raise KeyboardInterrupt() - if ch == u'\x04' and not WIN: # Unix-like, Ctrl+D - raise EOFError() - if ch == u'\x1a' and WIN: # Windows, Ctrl+Z - raise EOFError() - - -if WIN: - import msvcrt - - @contextlib.contextmanager - def raw_terminal(): - yield - - def getchar(echo): - # The function `getch` will return a bytes object corresponding to - # the pressed character. Since Windows 10 build 1803, it will also - # return \x00 when called a second time after pressing a regular key. - # - # `getwch` does not share this probably-bugged behavior. Moreover, it - # returns a Unicode object by default, which is what we want. - # - # Either of these functions will return \x00 or \xe0 to indicate - # a special key, and you need to call the same function again to get - # the "rest" of the code. The fun part is that \u00e0 is - # "latin small letter a with grave", so if you type that on a French - # keyboard, you _also_ get a \xe0. - # E.g., consider the Up arrow. This returns \xe0 and then \x48. The - # resulting Unicode string reads as "a with grave" + "capital H". - # This is indistinguishable from when the user actually types - # "a with grave" and then "capital H". - # - # When \xe0 is returned, we assume it's part of a special-key sequence - # and call `getwch` again, but that means that when the user types - # the \u00e0 character, `getchar` doesn't return until a second - # character is typed. - # The alternative is returning immediately, but that would mess up - # cross-platform handling of arrow keys and others that start with - # \xe0. Another option is using `getch`, but then we can't reliably - # read non-ASCII characters, because return values of `getch` are - # limited to the current 8-bit codepage. - # - # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` - # is doing the right thing in more situations than with `getch`. - if echo: - func = msvcrt.getwche - else: - func = msvcrt.getwch - - rv = func() - if rv in (u'\x00', u'\xe0'): - # \x00 and \xe0 are control characters that indicate special key, - # see above. - rv += func() - _translate_ch_to_exc(rv) - return rv -else: - import tty - import termios - - @contextlib.contextmanager - def raw_terminal(): - if not isatty(sys.stdin): - f = open('/dev/tty') - fd = f.fileno() - else: - fd = sys.stdin.fileno() - f = None - try: - old_settings = termios.tcgetattr(fd) - try: - tty.setraw(fd) - yield fd - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stdout.flush() - if f is not None: - f.close() - except termios.error: - pass - - def getchar(echo): - with raw_terminal() as fd: - ch = os.read(fd, 32) - ch = ch.decode(get_best_encoding(sys.stdin), 'replace') - if echo and isatty(sys.stdout): - sys.stdout.write(ch) - _translate_ch_to_exc(ch) - return ch diff --git a/py3.7/lib/python3.7/site-packages/click/_textwrap.py b/py3.7/lib/python3.7/site-packages/click/_textwrap.py deleted file mode 100644 index 7e77603..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_textwrap.py +++ /dev/null @@ -1,38 +0,0 @@ -import textwrap -from contextlib import contextmanager - - -class TextWrapper(textwrap.TextWrapper): - - def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): - space_left = max(width - cur_len, 1) - - if self.break_long_words: - last = reversed_chunks[-1] - cut = last[:space_left] - res = last[space_left:] - cur_line.append(cut) - reversed_chunks[-1] = res - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - @contextmanager - def extra_indent(self, indent): - old_initial_indent = self.initial_indent - old_subsequent_indent = self.subsequent_indent - self.initial_indent += indent - self.subsequent_indent += indent - try: - yield - finally: - self.initial_indent = old_initial_indent - self.subsequent_indent = old_subsequent_indent - - def indent_only(self, text): - rv = [] - for idx, line in enumerate(text.splitlines()): - indent = self.initial_indent - if idx > 0: - indent = self.subsequent_indent - rv.append(indent + line) - return '\n'.join(rv) diff --git a/py3.7/lib/python3.7/site-packages/click/_unicodefun.py b/py3.7/lib/python3.7/site-packages/click/_unicodefun.py deleted file mode 100644 index 620edff..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_unicodefun.py +++ /dev/null @@ -1,125 +0,0 @@ -import os -import sys -import codecs - -from ._compat import PY2 - - -# If someone wants to vendor click, we want to ensure the -# correct package is discovered. Ideally we could use a -# relative import here but unfortunately Python does not -# support that. -click = sys.modules[__name__.rsplit('.', 1)[0]] - - -def _find_unicode_literals_frame(): - import __future__ - if not hasattr(sys, '_getframe'): # not all Python implementations have it - return 0 - frm = sys._getframe(1) - idx = 1 - while frm is not None: - if frm.f_globals.get('__name__', '').startswith('click.'): - frm = frm.f_back - idx += 1 - elif frm.f_code.co_flags & __future__.unicode_literals.compiler_flag: - return idx - else: - break - return 0 - - -def _check_for_unicode_literals(): - if not __debug__: - return - if not PY2 or click.disable_unicode_literals_warning: - return - bad_frame = _find_unicode_literals_frame() - if bad_frame <= 0: - return - from warnings import warn - warn(Warning('Click detected the use of the unicode_literals ' - '__future__ import. This is heavily discouraged ' - 'because it can introduce subtle bugs in your ' - 'code. You should instead use explicit u"" literals ' - 'for your unicode strings. For more information see ' - 'https://click.palletsprojects.com/python3/'), - stacklevel=bad_frame) - - -def _verify_python3_env(): - """Ensures that the environment is good for unicode on Python 3.""" - if PY2: - return - try: - import locale - fs_enc = codecs.lookup(locale.getpreferredencoding()).name - except Exception: - fs_enc = 'ascii' - if fs_enc != 'ascii': - return - - extra = '' - if os.name == 'posix': - import subprocess - try: - rv = subprocess.Popen(['locale', '-a'], stdout=subprocess.PIPE, - stderr=subprocess.PIPE).communicate()[0] - except OSError: - rv = b'' - good_locales = set() - has_c_utf8 = False - - # Make sure we're operating on text here. - if isinstance(rv, bytes): - rv = rv.decode('ascii', 'replace') - - for line in rv.splitlines(): - locale = line.strip() - if locale.lower().endswith(('.utf-8', '.utf8')): - good_locales.add(locale) - if locale.lower() in ('c.utf8', 'c.utf-8'): - has_c_utf8 = True - - extra += '\n\n' - if not good_locales: - extra += ( - 'Additional information: on this system no suitable UTF-8\n' - 'locales were discovered. This most likely requires resolving\n' - 'by reconfiguring the locale system.' - ) - elif has_c_utf8: - extra += ( - 'This system supports the C.UTF-8 locale which is recommended.\n' - 'You might be able to resolve your issue by exporting the\n' - 'following environment variables:\n\n' - ' export LC_ALL=C.UTF-8\n' - ' export LANG=C.UTF-8' - ) - else: - extra += ( - 'This system lists a couple of UTF-8 supporting locales that\n' - 'you can pick from. The following suitable locales were\n' - 'discovered: %s' - ) % ', '.join(sorted(good_locales)) - - bad_locale = None - for locale in os.environ.get('LC_ALL'), os.environ.get('LANG'): - if locale and locale.lower().endswith(('.utf-8', '.utf8')): - bad_locale = locale - if locale is not None: - break - if bad_locale is not None: - extra += ( - '\n\nClick discovered that you exported a UTF-8 locale\n' - 'but the locale system could not pick up from it because\n' - 'it does not exist. The exported locale is "%s" but it\n' - 'is not supported' - ) % bad_locale - - raise RuntimeError( - 'Click will abort further execution because Python 3 was' - ' configured to use ASCII as encoding for the environment.' - ' Consult https://click.palletsprojects.com/en/7.x/python3/ for' - ' mitigation steps.' + extra - ) diff --git a/py3.7/lib/python3.7/site-packages/click/_winconsole.py b/py3.7/lib/python3.7/site-packages/click/_winconsole.py deleted file mode 100644 index bbb080d..0000000 --- a/py3.7/lib/python3.7/site-packages/click/_winconsole.py +++ /dev/null @@ -1,307 +0,0 @@ -# -*- coding: utf-8 -*- -# This module is based on the excellent work by Adam Bartoš who -# provided a lot of what went into the implementation here in -# the discussion to issue1602 in the Python bug tracker. -# -# There are some general differences in regards to how this works -# compared to the original patches as we do not need to patch -# the entire interpreter but just work in our little world of -# echo and prmopt. - -import io -import os -import sys -import zlib -import time -import ctypes -import msvcrt -from ._compat import _NonClosingTextIOWrapper, text_type, PY2 -from ctypes import byref, POINTER, c_int, c_char, c_char_p, \ - c_void_p, py_object, c_ssize_t, c_ulong, windll, WINFUNCTYPE -try: - from ctypes import pythonapi - PyObject_GetBuffer = pythonapi.PyObject_GetBuffer - PyBuffer_Release = pythonapi.PyBuffer_Release -except ImportError: - pythonapi = None -from ctypes.wintypes import LPWSTR, LPCWSTR - - -c_ssize_p = POINTER(c_ssize_t) - -kernel32 = windll.kernel32 -GetStdHandle = kernel32.GetStdHandle -ReadConsoleW = kernel32.ReadConsoleW -WriteConsoleW = kernel32.WriteConsoleW -GetLastError = kernel32.GetLastError -GetCommandLineW = WINFUNCTYPE(LPWSTR)( - ('GetCommandLineW', windll.kernel32)) -CommandLineToArgvW = WINFUNCTYPE( - POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( - ('CommandLineToArgvW', windll.shell32)) - - -STDIN_HANDLE = GetStdHandle(-10) -STDOUT_HANDLE = GetStdHandle(-11) -STDERR_HANDLE = GetStdHandle(-12) - - -PyBUF_SIMPLE = 0 -PyBUF_WRITABLE = 1 - -ERROR_SUCCESS = 0 -ERROR_NOT_ENOUGH_MEMORY = 8 -ERROR_OPERATION_ABORTED = 995 - -STDIN_FILENO = 0 -STDOUT_FILENO = 1 -STDERR_FILENO = 2 - -EOF = b'\x1a' -MAX_BYTES_WRITTEN = 32767 - - -class Py_buffer(ctypes.Structure): - _fields_ = [ - ('buf', c_void_p), - ('obj', py_object), - ('len', c_ssize_t), - ('itemsize', c_ssize_t), - ('readonly', c_int), - ('ndim', c_int), - ('format', c_char_p), - ('shape', c_ssize_p), - ('strides', c_ssize_p), - ('suboffsets', c_ssize_p), - ('internal', c_void_p) - ] - - if PY2: - _fields_.insert(-1, ('smalltable', c_ssize_t * 2)) - - -# On PyPy we cannot get buffers so our ability to operate here is -# serverly limited. -if pythonapi is None: - get_buffer = None -else: - def get_buffer(obj, writable=False): - buf = Py_buffer() - flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE - PyObject_GetBuffer(py_object(obj), byref(buf), flags) - try: - buffer_type = c_char * buf.len - return buffer_type.from_address(buf.buf) - finally: - PyBuffer_Release(byref(buf)) - - -class _WindowsConsoleRawIOBase(io.RawIOBase): - - def __init__(self, handle): - self.handle = handle - - def isatty(self): - io.RawIOBase.isatty(self) - return True - - -class _WindowsConsoleReader(_WindowsConsoleRawIOBase): - - def readable(self): - return True - - def readinto(self, b): - bytes_to_be_read = len(b) - if not bytes_to_be_read: - return 0 - elif bytes_to_be_read % 2: - raise ValueError('cannot read odd number of bytes from ' - 'UTF-16-LE encoded console') - - buffer = get_buffer(b, writable=True) - code_units_to_be_read = bytes_to_be_read // 2 - code_units_read = c_ulong() - - rv = ReadConsoleW(self.handle, buffer, code_units_to_be_read, - byref(code_units_read), None) - if GetLastError() == ERROR_OPERATION_ABORTED: - # wait for KeyboardInterrupt - time.sleep(0.1) - if not rv: - raise OSError('Windows error: %s' % GetLastError()) - - if buffer[0] == EOF: - return 0 - return 2 * code_units_read.value - - -class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): - - def writable(self): - return True - - @staticmethod - def _get_error_message(errno): - if errno == ERROR_SUCCESS: - return 'ERROR_SUCCESS' - elif errno == ERROR_NOT_ENOUGH_MEMORY: - return 'ERROR_NOT_ENOUGH_MEMORY' - return 'Windows error %s' % errno - - def write(self, b): - bytes_to_be_written = len(b) - buf = get_buffer(b) - code_units_to_be_written = min(bytes_to_be_written, - MAX_BYTES_WRITTEN) // 2 - code_units_written = c_ulong() - - WriteConsoleW(self.handle, buf, code_units_to_be_written, - byref(code_units_written), None) - bytes_written = 2 * code_units_written.value - - if bytes_written == 0 and bytes_to_be_written > 0: - raise OSError(self._get_error_message(GetLastError())) - return bytes_written - - -class ConsoleStream(object): - - def __init__(self, text_stream, byte_stream): - self._text_stream = text_stream - self.buffer = byte_stream - - @property - def name(self): - return self.buffer.name - - def write(self, x): - if isinstance(x, text_type): - return self._text_stream.write(x) - try: - self.flush() - except Exception: - pass - return self.buffer.write(x) - - def writelines(self, lines): - for line in lines: - self.write(line) - - def __getattr__(self, name): - return getattr(self._text_stream, name) - - def isatty(self): - return self.buffer.isatty() - - def __repr__(self): - return '' % ( - self.name, - self.encoding, - ) - - -class WindowsChunkedWriter(object): - """ - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()' which we wrap to write in - limited chunks due to a Windows limitation on binary console streams. - """ - def __init__(self, wrapped): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def write(self, text): - total_to_write = len(text) - written = 0 - - while written < total_to_write: - to_write = min(total_to_write - written, MAX_BYTES_WRITTEN) - self.__wrapped.write(text[written:written+to_write]) - written += to_write - - -_wrapped_std_streams = set() - - -def _wrap_std_stream(name): - # Python 2 & Windows 7 and below - if PY2 and sys.getwindowsversion()[:2] <= (6, 1) and name not in _wrapped_std_streams: - setattr(sys, name, WindowsChunkedWriter(getattr(sys, name))) - _wrapped_std_streams.add(name) - - -def _get_text_stdin(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), - 'utf-16-le', 'strict', line_buffering=True) - return ConsoleStream(text_stream, buffer_stream) - - -def _get_text_stdout(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), - 'utf-16-le', 'strict', line_buffering=True) - return ConsoleStream(text_stream, buffer_stream) - - -def _get_text_stderr(buffer_stream): - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), - 'utf-16-le', 'strict', line_buffering=True) - return ConsoleStream(text_stream, buffer_stream) - - -if PY2: - def _hash_py_argv(): - return zlib.crc32('\x00'.join(sys.argv[1:])) - - _initial_argv_hash = _hash_py_argv() - - def _get_windows_argv(): - argc = c_int(0) - argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) - argv = [argv_unicode[i] for i in range(0, argc.value)] - - if not hasattr(sys, 'frozen'): - argv = argv[1:] - while len(argv) > 0: - arg = argv[0] - if not arg.startswith('-') or arg == '-': - break - argv = argv[1:] - if arg.startswith(('-c', '-m')): - break - - return argv[1:] - - -_stream_factories = { - 0: _get_text_stdin, - 1: _get_text_stdout, - 2: _get_text_stderr, -} - - -def _get_windows_console_stream(f, encoding, errors): - if get_buffer is not None and \ - encoding in ('utf-16-le', None) \ - and errors in ('strict', None) and \ - hasattr(f, 'isatty') and f.isatty(): - func = _stream_factories.get(f.fileno()) - if func is not None: - if not PY2: - f = getattr(f, 'buffer', None) - if f is None: - return None - else: - # If we are on Python 2 we need to set the stream that we - # deal with to binary mode as otherwise the exercise if a - # bit moot. The same problems apply as for - # get_binary_stdin and friends from _compat. - msvcrt.setmode(f.fileno(), os.O_BINARY) - return func(f) diff --git a/py3.7/lib/python3.7/site-packages/click/core.py b/py3.7/lib/python3.7/site-packages/click/core.py deleted file mode 100644 index 7a1e342..0000000 --- a/py3.7/lib/python3.7/site-packages/click/core.py +++ /dev/null @@ -1,1856 +0,0 @@ -import errno -import inspect -import os -import sys -from contextlib import contextmanager -from itertools import repeat -from functools import update_wrapper - -from .types import convert_type, IntRange, BOOL -from .utils import PacifyFlushWrapper, make_str, make_default_short_help, \ - echo, get_os_args -from .exceptions import ClickException, UsageError, BadParameter, Abort, \ - MissingParameter, Exit -from .termui import prompt, confirm, style -from .formatting import HelpFormatter, join_options -from .parser import OptionParser, split_opt -from .globals import push_context, pop_context - -from ._compat import PY2, isidentifier, iteritems, string_types -from ._unicodefun import _check_for_unicode_literals, _verify_python3_env - - -_missing = object() - - -SUBCOMMAND_METAVAR = 'COMMAND [ARGS]...' -SUBCOMMANDS_METAVAR = 'COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...' - -DEPRECATED_HELP_NOTICE = ' (DEPRECATED)' -DEPRECATED_INVOKE_NOTICE = 'DeprecationWarning: ' + \ - 'The command %(name)s is deprecated.' - - -def _maybe_show_deprecated_notice(cmd): - if cmd.deprecated: - echo(style(DEPRECATED_INVOKE_NOTICE % {'name': cmd.name}, fg='red'), err=True) - - -def fast_exit(code): - """Exit without garbage collection, this speeds up exit by about 10ms for - things like bash completion. - """ - sys.stdout.flush() - sys.stderr.flush() - os._exit(code) - - -def _bashcomplete(cmd, prog_name, complete_var=None): - """Internal handler for the bash completion support.""" - if complete_var is None: - complete_var = '_%s_COMPLETE' % (prog_name.replace('-', '_')).upper() - complete_instr = os.environ.get(complete_var) - if not complete_instr: - return - - from ._bashcomplete import bashcomplete - if bashcomplete(cmd, prog_name, complete_var, complete_instr): - fast_exit(1) - - -def _check_multicommand(base_command, cmd_name, cmd, register=False): - if not base_command.chain or not isinstance(cmd, MultiCommand): - return - if register: - hint = 'It is not possible to add multi commands as children to ' \ - 'another multi command that is in chain mode' - else: - hint = 'Found a multi command as subcommand to a multi command ' \ - 'that is in chain mode. This is not supported' - raise RuntimeError('%s. Command "%s" is set to chain and "%s" was ' - 'added as subcommand but it in itself is a ' - 'multi command. ("%s" is a %s within a chained ' - '%s named "%s").' % ( - hint, base_command.name, cmd_name, - cmd_name, cmd.__class__.__name__, - base_command.__class__.__name__, - base_command.name)) - - -def batch(iterable, batch_size): - return list(zip(*repeat(iter(iterable), batch_size))) - - -def invoke_param_callback(callback, ctx, param, value): - code = getattr(callback, '__code__', None) - args = getattr(code, 'co_argcount', 3) - - if args < 3: - # This will become a warning in Click 3.0: - from warnings import warn - warn(Warning('Invoked legacy parameter callback "%s". The new ' - 'signature for such callbacks starting with ' - 'click 2.0 is (ctx, param, value).' - % callback), stacklevel=3) - return callback(ctx, value) - return callback(ctx, param, value) - - -@contextmanager -def augment_usage_errors(ctx, param=None): - """Context manager that attaches extra information to exceptions that - fly. - """ - try: - yield - except BadParameter as e: - if e.ctx is None: - e.ctx = ctx - if param is not None and e.param is None: - e.param = param - raise - except UsageError as e: - if e.ctx is None: - e.ctx = ctx - raise - - -def iter_params_for_processing(invocation_order, declaration_order): - """Given a sequence of parameters in the order as should be considered - for processing and an iterable of parameters that exist, this returns - a list in the correct order as they should be processed. - """ - def sort_key(item): - try: - idx = invocation_order.index(item) - except ValueError: - idx = float('inf') - return (not item.is_eager, idx) - - return sorted(declaration_order, key=sort_key) - - -class Context(object): - """The context is a special internal object that holds state relevant - for the script execution at every single level. It's normally invisible - to commands unless they opt-in to getting access to it. - - The context is useful as it can pass internal objects around and can - control special execution features such as reading data from - environment variables. - - A context can be used as context manager in which case it will call - :meth:`close` on teardown. - - .. versionadded:: 2.0 - Added the `resilient_parsing`, `help_option_names`, - `token_normalize_func` parameters. - - .. versionadded:: 3.0 - Added the `allow_extra_args` and `allow_interspersed_args` - parameters. - - .. versionadded:: 4.0 - Added the `color`, `ignore_unknown_options`, and - `max_content_width` parameters. - - :param command: the command class for this context. - :param parent: the parent context. - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it is usually - the name of the script, for commands below it it's - the name of the script. - :param obj: an arbitrary object of user data. - :param auto_envvar_prefix: the prefix to use for automatic environment - variables. If this is `None` then reading - from environment variables is disabled. This - does not affect manually set environment - variables which are always read. - :param default_map: a dictionary (like object) with default values - for parameters. - :param terminal_width: the width of the terminal. The default is - inherit from parent context. If no context - defines the terminal width then auto - detection will be applied. - :param max_content_width: the maximum width for content rendered by - Click (this currently only affects help - pages). This defaults to 80 characters if - not overridden. In other words: even if the - terminal is larger than that, Click will not - format things wider than 80 characters by - default. In addition to that, formatters might - add some safety mapping on the right. - :param resilient_parsing: if this flag is enabled then Click will - parse without any interactivity or callback - invocation. Default values will also be - ignored. This is useful for implementing - things such as completion support. - :param allow_extra_args: if this is set to `True` then extra arguments - at the end will not raise an error and will be - kept on the context. The default is to inherit - from the command. - :param allow_interspersed_args: if this is set to `False` then options - and arguments cannot be mixed. The - default is to inherit from the command. - :param ignore_unknown_options: instructs click to ignore options it does - not know and keeps them for later - processing. - :param help_option_names: optionally a list of strings that define how - the default help parameter is named. The - default is ``['--help']``. - :param token_normalize_func: an optional function that is used to - normalize tokens (options, choices, - etc.). This for instance can be used to - implement case insensitive behavior. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are used in texts that Click prints which is by - default not the case. This for instance would affect - help output. - """ - - def __init__(self, command, parent=None, info_name=None, obj=None, - auto_envvar_prefix=None, default_map=None, - terminal_width=None, max_content_width=None, - resilient_parsing=False, allow_extra_args=None, - allow_interspersed_args=None, - ignore_unknown_options=None, help_option_names=None, - token_normalize_func=None, color=None): - #: the parent context or `None` if none exists. - self.parent = parent - #: the :class:`Command` for this context. - self.command = command - #: the descriptive information name - self.info_name = info_name - #: the parsed parameters except if the value is hidden in which - #: case it's not remembered. - self.params = {} - #: the leftover arguments. - self.args = [] - #: protected arguments. These are arguments that are prepended - #: to `args` when certain parsing scenarios are encountered but - #: must be never propagated to another arguments. This is used - #: to implement nested parsing. - self.protected_args = [] - if obj is None and parent is not None: - obj = parent.obj - #: the user object stored. - self.obj = obj - self._meta = getattr(parent, 'meta', {}) - - #: A dictionary (-like object) with defaults for parameters. - if default_map is None \ - and parent is not None \ - and parent.default_map is not None: - default_map = parent.default_map.get(info_name) - self.default_map = default_map - - #: This flag indicates if a subcommand is going to be executed. A - #: group callback can use this information to figure out if it's - #: being executed directly or because the execution flow passes - #: onwards to a subcommand. By default it's None, but it can be - #: the name of the subcommand to execute. - #: - #: If chaining is enabled this will be set to ``'*'`` in case - #: any commands are executed. It is however not possible to - #: figure out which ones. If you require this knowledge you - #: should use a :func:`resultcallback`. - self.invoked_subcommand = None - - if terminal_width is None and parent is not None: - terminal_width = parent.terminal_width - #: The width of the terminal (None is autodetection). - self.terminal_width = terminal_width - - if max_content_width is None and parent is not None: - max_content_width = parent.max_content_width - #: The maximum width of formatted content (None implies a sensible - #: default which is 80 for most things). - self.max_content_width = max_content_width - - if allow_extra_args is None: - allow_extra_args = command.allow_extra_args - #: Indicates if the context allows extra args or if it should - #: fail on parsing. - #: - #: .. versionadded:: 3.0 - self.allow_extra_args = allow_extra_args - - if allow_interspersed_args is None: - allow_interspersed_args = command.allow_interspersed_args - #: Indicates if the context allows mixing of arguments and - #: options or not. - #: - #: .. versionadded:: 3.0 - self.allow_interspersed_args = allow_interspersed_args - - if ignore_unknown_options is None: - ignore_unknown_options = command.ignore_unknown_options - #: Instructs click to ignore options that a command does not - #: understand and will store it on the context for later - #: processing. This is primarily useful for situations where you - #: want to call into external programs. Generally this pattern is - #: strongly discouraged because it's not possibly to losslessly - #: forward all arguments. - #: - #: .. versionadded:: 4.0 - self.ignore_unknown_options = ignore_unknown_options - - if help_option_names is None: - if parent is not None: - help_option_names = parent.help_option_names - else: - help_option_names = ['--help'] - - #: The names for the help options. - self.help_option_names = help_option_names - - if token_normalize_func is None and parent is not None: - token_normalize_func = parent.token_normalize_func - - #: An optional normalization function for tokens. This is - #: options, choices, commands etc. - self.token_normalize_func = token_normalize_func - - #: Indicates if resilient parsing is enabled. In that case Click - #: will do its best to not cause any failures and default values - #: will be ignored. Useful for completion. - self.resilient_parsing = resilient_parsing - - # If there is no envvar prefix yet, but the parent has one and - # the command on this level has a name, we can expand the envvar - # prefix automatically. - if auto_envvar_prefix is None: - if parent is not None \ - and parent.auto_envvar_prefix is not None and \ - self.info_name is not None: - auto_envvar_prefix = '%s_%s' % (parent.auto_envvar_prefix, - self.info_name.upper()) - else: - auto_envvar_prefix = auto_envvar_prefix.upper() - self.auto_envvar_prefix = auto_envvar_prefix - - if color is None and parent is not None: - color = parent.color - - #: Controls if styling output is wanted or not. - self.color = color - - self._close_callbacks = [] - self._depth = 0 - - def __enter__(self): - self._depth += 1 - push_context(self) - return self - - def __exit__(self, exc_type, exc_value, tb): - self._depth -= 1 - if self._depth == 0: - self.close() - pop_context() - - @contextmanager - def scope(self, cleanup=True): - """This helper method can be used with the context object to promote - it to the current thread local (see :func:`get_current_context`). - The default behavior of this is to invoke the cleanup functions which - can be disabled by setting `cleanup` to `False`. The cleanup - functions are typically used for things such as closing file handles. - - If the cleanup is intended the context object can also be directly - used as a context manager. - - Example usage:: - - with ctx.scope(): - assert get_current_context() is ctx - - This is equivalent:: - - with ctx: - assert get_current_context() is ctx - - .. versionadded:: 5.0 - - :param cleanup: controls if the cleanup functions should be run or - not. The default is to run these functions. In - some situations the context only wants to be - temporarily pushed in which case this can be disabled. - Nested pushes automatically defer the cleanup. - """ - if not cleanup: - self._depth += 1 - try: - with self as rv: - yield rv - finally: - if not cleanup: - self._depth -= 1 - - @property - def meta(self): - """This is a dictionary which is shared with all the contexts - that are nested. It exists so that click utilities can store some - state here if they need to. It is however the responsibility of - that code to manage this dictionary well. - - The keys are supposed to be unique dotted strings. For instance - module paths are a good choice for it. What is stored in there is - irrelevant for the operation of click. However what is important is - that code that places data here adheres to the general semantics of - the system. - - Example usage:: - - LANG_KEY = __name__ + '.lang' - - def set_language(value): - ctx = get_current_context() - ctx.meta[LANG_KEY] = value - - def get_language(): - return get_current_context().meta.get(LANG_KEY, 'en_US') - - .. versionadded:: 5.0 - """ - return self._meta - - def make_formatter(self): - """Creates the formatter for the help and usage output.""" - return HelpFormatter(width=self.terminal_width, - max_width=self.max_content_width) - - def call_on_close(self, f): - """This decorator remembers a function as callback that should be - executed when the context tears down. This is most useful to bind - resource handling to the script execution. For instance, file objects - opened by the :class:`File` type will register their close callbacks - here. - - :param f: the function to execute on teardown. - """ - self._close_callbacks.append(f) - return f - - def close(self): - """Invokes all close callbacks.""" - for cb in self._close_callbacks: - cb() - self._close_callbacks = [] - - @property - def command_path(self): - """The computed command path. This is used for the ``usage`` - information on the help page. It's automatically created by - combining the info names of the chain of contexts to the root. - """ - rv = '' - if self.info_name is not None: - rv = self.info_name - if self.parent is not None: - rv = self.parent.command_path + ' ' + rv - return rv.lstrip() - - def find_root(self): - """Finds the outermost context.""" - node = self - while node.parent is not None: - node = node.parent - return node - - def find_object(self, object_type): - """Finds the closest object of a given type.""" - node = self - while node is not None: - if isinstance(node.obj, object_type): - return node.obj - node = node.parent - - def ensure_object(self, object_type): - """Like :meth:`find_object` but sets the innermost object to a - new instance of `object_type` if it does not exist. - """ - rv = self.find_object(object_type) - if rv is None: - self.obj = rv = object_type() - return rv - - def lookup_default(self, name): - """Looks up the default for a parameter name. This by default - looks into the :attr:`default_map` if available. - """ - if self.default_map is not None: - rv = self.default_map.get(name) - if callable(rv): - rv = rv() - return rv - - def fail(self, message): - """Aborts the execution of the program with a specific error - message. - - :param message: the error message to fail with. - """ - raise UsageError(message, self) - - def abort(self): - """Aborts the script.""" - raise Abort() - - def exit(self, code=0): - """Exits the application with a given exit code.""" - raise Exit(code) - - def get_usage(self): - """Helper method to get formatted usage string for the current - context and command. - """ - return self.command.get_usage(self) - - def get_help(self): - """Helper method to get formatted help page for the current - context and command. - """ - return self.command.get_help(self) - - def invoke(*args, **kwargs): - """Invokes a command callback in exactly the way it expects. There - are two ways to invoke this method: - - 1. the first argument can be a callback and all other arguments and - keyword arguments are forwarded directly to the function. - 2. the first argument is a click command object. In that case all - arguments are forwarded as well but proper click parameters - (options and click arguments) must be keyword arguments and Click - will fill in defaults. - - Note that before Click 3.2 keyword arguments were not properly filled - in against the intention of this code and no context was created. For - more information about this change and why it was done in a bugfix - release see :ref:`upgrade-to-3.2`. - """ - self, callback = args[:2] - ctx = self - - # It's also possible to invoke another command which might or - # might not have a callback. In that case we also fill - # in defaults and make a new context for this command. - if isinstance(callback, Command): - other_cmd = callback - callback = other_cmd.callback - ctx = Context(other_cmd, info_name=other_cmd.name, parent=self) - if callback is None: - raise TypeError('The given command does not have a ' - 'callback that can be invoked.') - - for param in other_cmd.params: - if param.name not in kwargs and param.expose_value: - kwargs[param.name] = param.get_default(ctx) - - args = args[2:] - with augment_usage_errors(self): - with ctx: - return callback(*args, **kwargs) - - def forward(*args, **kwargs): - """Similar to :meth:`invoke` but fills in default keyword - arguments from the current context if the other command expects - it. This cannot invoke callbacks directly, only other commands. - """ - self, cmd = args[:2] - - # It's also possible to invoke another command which might or - # might not have a callback. - if not isinstance(cmd, Command): - raise TypeError('Callback is not a command.') - - for param in self.params: - if param not in kwargs: - kwargs[param] = self.params[param] - - return self.invoke(cmd, **kwargs) - - -class BaseCommand(object): - """The base command implements the minimal API contract of commands. - Most code will never use this as it does not implement a lot of useful - functionality but it can act as the direct subclass of alternative - parsing methods that do not depend on the Click parser. - - For instance, this can be used to bridge Click and other systems like - argparse or docopt. - - Because base commands do not implement a lot of the API that other - parts of Click take for granted, they are not supported for all - operations. For instance, they cannot be used with the decorators - usually and they have no built-in callback system. - - .. versionchanged:: 2.0 - Added the `context_settings` parameter. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - """ - #: the default for the :attr:`Context.allow_extra_args` flag. - allow_extra_args = False - #: the default for the :attr:`Context.allow_interspersed_args` flag. - allow_interspersed_args = True - #: the default for the :attr:`Context.ignore_unknown_options` flag. - ignore_unknown_options = False - - def __init__(self, name, context_settings=None): - #: the name the command thinks it has. Upon registering a command - #: on a :class:`Group` the group will default the command name - #: with this information. You should instead use the - #: :class:`Context`\'s :attr:`~Context.info_name` attribute. - self.name = name - if context_settings is None: - context_settings = {} - #: an optional dictionary with defaults passed to the context. - self.context_settings = context_settings - - def get_usage(self, ctx): - raise NotImplementedError('Base commands cannot get usage') - - def get_help(self, ctx): - raise NotImplementedError('Base commands cannot get help') - - def make_context(self, info_name, args, parent=None, **extra): - """This function when given an info name and arguments will kick - off the parsing and create a new :class:`Context`. It does not - invoke the actual command callback though. - - :param info_name: the info name for this invokation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it's usually - the name of the script, for commands below it it's - the name of the script. - :param args: the arguments to parse as list of strings. - :param parent: the parent context if available. - :param extra: extra keyword arguments forwarded to the context - constructor. - """ - for key, value in iteritems(self.context_settings): - if key not in extra: - extra[key] = value - ctx = Context(self, info_name=info_name, parent=parent, **extra) - with ctx.scope(cleanup=False): - self.parse_args(ctx, args) - return ctx - - def parse_args(self, ctx, args): - """Given a context and a list of arguments this creates the parser - and parses the arguments, then modifies the context as necessary. - This is automatically invoked by :meth:`make_context`. - """ - raise NotImplementedError('Base commands do not know how to parse ' - 'arguments.') - - def invoke(self, ctx): - """Given a context, this invokes the command. The default - implementation is raising a not implemented error. - """ - raise NotImplementedError('Base commands are not invokable by default') - - def main(self, args=None, prog_name=None, complete_var=None, - standalone_mode=True, **extra): - """This is the way to invoke a script with all the bells and - whistles as a command line application. This will always terminate - the application after a call. If this is not wanted, ``SystemExit`` - needs to be caught. - - This method is also available by directly calling the instance of - a :class:`Command`. - - .. versionadded:: 3.0 - Added the `standalone_mode` flag to control the standalone mode. - - :param args: the arguments that should be used for parsing. If not - provided, ``sys.argv[1:]`` is used. - :param prog_name: the program name that should be used. By default - the program name is constructed by taking the file - name from ``sys.argv[0]``. - :param complete_var: the environment variable that controls the - bash completion support. The default is - ``"__COMPLETE"`` with prog_name in - uppercase. - :param standalone_mode: the default behavior is to invoke the script - in standalone mode. Click will then - handle exceptions and convert them into - error messages and the function will never - return but shut down the interpreter. If - this is set to `False` they will be - propagated to the caller and the return - value of this function is the return value - of :meth:`invoke`. - :param extra: extra keyword arguments are forwarded to the context - constructor. See :class:`Context` for more information. - """ - # If we are in Python 3, we will verify that the environment is - # sane at this point or reject further execution to avoid a - # broken script. - if not PY2: - _verify_python3_env() - else: - _check_for_unicode_literals() - - if args is None: - args = get_os_args() - else: - args = list(args) - - if prog_name is None: - prog_name = make_str(os.path.basename( - sys.argv and sys.argv[0] or __file__)) - - # Hook for the Bash completion. This only activates if the Bash - # completion is actually enabled, otherwise this is quite a fast - # noop. - _bashcomplete(self, prog_name, complete_var) - - try: - try: - with self.make_context(prog_name, args, **extra) as ctx: - rv = self.invoke(ctx) - if not standalone_mode: - return rv - # it's not safe to `ctx.exit(rv)` here! - # note that `rv` may actually contain data like "1" which - # has obvious effects - # more subtle case: `rv=[None, None]` can come out of - # chained commands which all returned `None` -- so it's not - # even always obvious that `rv` indicates success/failure - # by its truthiness/falsiness - ctx.exit() - except (EOFError, KeyboardInterrupt): - echo(file=sys.stderr) - raise Abort() - except ClickException as e: - if not standalone_mode: - raise - e.show() - sys.exit(e.exit_code) - except IOError as e: - if e.errno == errno.EPIPE: - sys.stdout = PacifyFlushWrapper(sys.stdout) - sys.stderr = PacifyFlushWrapper(sys.stderr) - sys.exit(1) - else: - raise - except Exit as e: - if standalone_mode: - sys.exit(e.exit_code) - else: - # in non-standalone mode, return the exit code - # note that this is only reached if `self.invoke` above raises - # an Exit explicitly -- thus bypassing the check there which - # would return its result - # the results of non-standalone execution may therefore be - # somewhat ambiguous: if there are codepaths which lead to - # `ctx.exit(1)` and to `return 1`, the caller won't be able to - # tell the difference between the two - return e.exit_code - except Abort: - if not standalone_mode: - raise - echo('Aborted!', file=sys.stderr) - sys.exit(1) - - def __call__(self, *args, **kwargs): - """Alias for :meth:`main`.""" - return self.main(*args, **kwargs) - - -class Command(BaseCommand): - """Commands are the basic building block of command line interfaces in - Click. A basic command handles command line parsing and might dispatch - more parsing to commands nested below it. - - .. versionchanged:: 2.0 - Added the `context_settings` parameter. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - :param callback: the callback to invoke. This is optional. - :param params: the parameters to register with this command. This can - be either :class:`Option` or :class:`Argument` objects. - :param help: the help string to use for this command. - :param epilog: like the help string but it's printed at the end of the - help page after everything else. - :param short_help: the short help to use for this command. This is - shown on the command listing of the parent command. - :param add_help_option: by default each command registers a ``--help`` - option. This can be disabled by this parameter. - :param hidden: hide this command from help outputs. - - :param deprecated: issues a message indicating that - the command is deprecated. - """ - - def __init__(self, name, context_settings=None, callback=None, - params=None, help=None, epilog=None, short_help=None, - options_metavar='[OPTIONS]', add_help_option=True, - hidden=False, deprecated=False): - BaseCommand.__init__(self, name, context_settings) - #: the callback to execute when the command fires. This might be - #: `None` in which case nothing happens. - self.callback = callback - #: the list of parameters for this command in the order they - #: should show up in the help page and execute. Eager parameters - #: will automatically be handled before non eager ones. - self.params = params or [] - # if a form feed (page break) is found in the help text, truncate help - # text to the content preceding the first form feed - if help and '\f' in help: - help = help.split('\f', 1)[0] - self.help = help - self.epilog = epilog - self.options_metavar = options_metavar - self.short_help = short_help - self.add_help_option = add_help_option - self.hidden = hidden - self.deprecated = deprecated - - def get_usage(self, ctx): - formatter = ctx.make_formatter() - self.format_usage(ctx, formatter) - return formatter.getvalue().rstrip('\n') - - def get_params(self, ctx): - rv = self.params - help_option = self.get_help_option(ctx) - if help_option is not None: - rv = rv + [help_option] - return rv - - def format_usage(self, ctx, formatter): - """Writes the usage line into the formatter.""" - pieces = self.collect_usage_pieces(ctx) - formatter.write_usage(ctx.command_path, ' '.join(pieces)) - - def collect_usage_pieces(self, ctx): - """Returns all the pieces that go into the usage line and returns - it as a list of strings. - """ - rv = [self.options_metavar] - for param in self.get_params(ctx): - rv.extend(param.get_usage_pieces(ctx)) - return rv - - def get_help_option_names(self, ctx): - """Returns the names for the help option.""" - all_names = set(ctx.help_option_names) - for param in self.params: - all_names.difference_update(param.opts) - all_names.difference_update(param.secondary_opts) - return all_names - - def get_help_option(self, ctx): - """Returns the help option object.""" - help_options = self.get_help_option_names(ctx) - if not help_options or not self.add_help_option: - return - - def show_help(ctx, param, value): - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - return Option(help_options, is_flag=True, - is_eager=True, expose_value=False, - callback=show_help, - help='Show this message and exit.') - - def make_parser(self, ctx): - """Creates the underlying option parser for this command.""" - parser = OptionParser(ctx) - for param in self.get_params(ctx): - param.add_to_parser(parser, ctx) - return parser - - def get_help(self, ctx): - """Formats the help into a string and returns it. This creates a - formatter and will call into the following formatting methods: - """ - formatter = ctx.make_formatter() - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip('\n') - - def get_short_help_str(self, limit=45): - """Gets short help for the command or makes it by shortening the long help string.""" - return self.short_help or self.help and make_default_short_help(self.help, limit) or '' - - def format_help(self, ctx, formatter): - """Writes the help into the formatter if it exists. - - This calls into the following methods: - - - :meth:`format_usage` - - :meth:`format_help_text` - - :meth:`format_options` - - :meth:`format_epilog` - """ - self.format_usage(ctx, formatter) - self.format_help_text(ctx, formatter) - self.format_options(ctx, formatter) - self.format_epilog(ctx, formatter) - - def format_help_text(self, ctx, formatter): - """Writes the help text to the formatter if it exists.""" - if self.help: - formatter.write_paragraph() - with formatter.indentation(): - help_text = self.help - if self.deprecated: - help_text += DEPRECATED_HELP_NOTICE - formatter.write_text(help_text) - elif self.deprecated: - formatter.write_paragraph() - with formatter.indentation(): - formatter.write_text(DEPRECATED_HELP_NOTICE) - - def format_options(self, ctx, formatter): - """Writes all the options into the formatter if they exist.""" - opts = [] - for param in self.get_params(ctx): - rv = param.get_help_record(ctx) - if rv is not None: - opts.append(rv) - - if opts: - with formatter.section('Options'): - formatter.write_dl(opts) - - def format_epilog(self, ctx, formatter): - """Writes the epilog into the formatter if it exists.""" - if self.epilog: - formatter.write_paragraph() - with formatter.indentation(): - formatter.write_text(self.epilog) - - def parse_args(self, ctx, args): - parser = self.make_parser(ctx) - opts, args, param_order = parser.parse_args(args=args) - - for param in iter_params_for_processing( - param_order, self.get_params(ctx)): - value, args = param.handle_parse_result(ctx, opts, args) - - if args and not ctx.allow_extra_args and not ctx.resilient_parsing: - ctx.fail('Got unexpected extra argument%s (%s)' - % (len(args) != 1 and 's' or '', - ' '.join(map(make_str, args)))) - - ctx.args = args - return args - - def invoke(self, ctx): - """Given a context, this invokes the attached callback (if it exists) - in the right way. - """ - _maybe_show_deprecated_notice(self) - if self.callback is not None: - return ctx.invoke(self.callback, **ctx.params) - - -class MultiCommand(Command): - """A multi command is the basic implementation of a command that - dispatches to subcommands. The most common version is the - :class:`Group`. - - :param invoke_without_command: this controls how the multi command itself - is invoked. By default it's only invoked - if a subcommand is provided. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is enabled by default if - `invoke_without_command` is disabled or disabled - if it's enabled. If enabled this will add - ``--help`` as argument if no arguments are - passed. - :param subcommand_metavar: the string that is used in the documentation - to indicate the subcommand place. - :param chain: if this is set to `True` chaining of multiple subcommands - is enabled. This restricts the form of commands in that - they cannot have optional arguments but it allows - multiple commands to be chained together. - :param result_callback: the result callback to attach to this multi - command. - """ - allow_extra_args = True - allow_interspersed_args = False - - def __init__(self, name=None, invoke_without_command=False, - no_args_is_help=None, subcommand_metavar=None, - chain=False, result_callback=None, **attrs): - Command.__init__(self, name, **attrs) - if no_args_is_help is None: - no_args_is_help = not invoke_without_command - self.no_args_is_help = no_args_is_help - self.invoke_without_command = invoke_without_command - if subcommand_metavar is None: - if chain: - subcommand_metavar = SUBCOMMANDS_METAVAR - else: - subcommand_metavar = SUBCOMMAND_METAVAR - self.subcommand_metavar = subcommand_metavar - self.chain = chain - #: The result callback that is stored. This can be set or - #: overridden with the :func:`resultcallback` decorator. - self.result_callback = result_callback - - if self.chain: - for param in self.params: - if isinstance(param, Argument) and not param.required: - raise RuntimeError('Multi commands in chain mode cannot ' - 'have optional arguments.') - - def collect_usage_pieces(self, ctx): - rv = Command.collect_usage_pieces(self, ctx) - rv.append(self.subcommand_metavar) - return rv - - def format_options(self, ctx, formatter): - Command.format_options(self, ctx, formatter) - self.format_commands(ctx, formatter) - - def resultcallback(self, replace=False): - """Adds a result callback to the chain command. By default if a - result callback is already registered this will chain them but - this can be disabled with the `replace` parameter. The result - callback is invoked with the return value of the subcommand - (or the list of return values from all subcommands if chaining - is enabled) as well as the parameters as they would be passed - to the main callback. - - Example:: - - @click.group() - @click.option('-i', '--input', default=23) - def cli(input): - return 42 - - @cli.resultcallback() - def process_result(result, input): - return result + input - - .. versionadded:: 3.0 - - :param replace: if set to `True` an already existing result - callback will be removed. - """ - def decorator(f): - old_callback = self.result_callback - if old_callback is None or replace: - self.result_callback = f - return f - def function(__value, *args, **kwargs): - return f(old_callback(__value, *args, **kwargs), - *args, **kwargs) - self.result_callback = rv = update_wrapper(function, f) - return rv - return decorator - - def format_commands(self, ctx, formatter): - """Extra format methods for multi methods that adds all the commands - after the options. - """ - commands = [] - for subcommand in self.list_commands(ctx): - cmd = self.get_command(ctx, subcommand) - # What is this, the tool lied about a command. Ignore it - if cmd is None: - continue - if cmd.hidden: - continue - - commands.append((subcommand, cmd)) - - # allow for 3 times the default spacing - if len(commands): - limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) - - rows = [] - for subcommand, cmd in commands: - help = cmd.get_short_help_str(limit) - rows.append((subcommand, help)) - - if rows: - with formatter.section('Commands'): - formatter.write_dl(rows) - - def parse_args(self, ctx, args): - if not args and self.no_args_is_help and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - rest = Command.parse_args(self, ctx, args) - if self.chain: - ctx.protected_args = rest - ctx.args = [] - elif rest: - ctx.protected_args, ctx.args = rest[:1], rest[1:] - - return ctx.args - - def invoke(self, ctx): - def _process_result(value): - if self.result_callback is not None: - value = ctx.invoke(self.result_callback, value, - **ctx.params) - return value - - if not ctx.protected_args: - # If we are invoked without command the chain flag controls - # how this happens. If we are not in chain mode, the return - # value here is the return value of the command. - # If however we are in chain mode, the return value is the - # return value of the result processor invoked with an empty - # list (which means that no subcommand actually was executed). - if self.invoke_without_command: - if not self.chain: - return Command.invoke(self, ctx) - with ctx: - Command.invoke(self, ctx) - return _process_result([]) - ctx.fail('Missing command.') - - # Fetch args back out - args = ctx.protected_args + ctx.args - ctx.args = [] - ctx.protected_args = [] - - # If we're not in chain mode, we only allow the invocation of a - # single command but we also inform the current context about the - # name of the command to invoke. - if not self.chain: - # Make sure the context is entered so we do not clean up - # resources until the result processor has worked. - with ctx: - cmd_name, cmd, args = self.resolve_command(ctx, args) - ctx.invoked_subcommand = cmd_name - Command.invoke(self, ctx) - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) - with sub_ctx: - return _process_result(sub_ctx.command.invoke(sub_ctx)) - - # In chain mode we create the contexts step by step, but after the - # base command has been invoked. Because at that point we do not - # know the subcommands yet, the invoked subcommand attribute is - # set to ``*`` to inform the command that subcommands are executed - # but nothing else. - with ctx: - ctx.invoked_subcommand = args and '*' or None - Command.invoke(self, ctx) - - # Otherwise we make every single context and invoke them in a - # chain. In that case the return value to the result processor - # is the list of all invoked subcommand's results. - contexts = [] - while args: - cmd_name, cmd, args = self.resolve_command(ctx, args) - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False) - contexts.append(sub_ctx) - args, sub_ctx.args = sub_ctx.args, [] - - rv = [] - for sub_ctx in contexts: - with sub_ctx: - rv.append(sub_ctx.command.invoke(sub_ctx)) - return _process_result(rv) - - def resolve_command(self, ctx, args): - cmd_name = make_str(args[0]) - original_cmd_name = cmd_name - - # Get the command - cmd = self.get_command(ctx, cmd_name) - - # If we can't find the command but there is a normalization - # function available, we try with that one. - if cmd is None and ctx.token_normalize_func is not None: - cmd_name = ctx.token_normalize_func(cmd_name) - cmd = self.get_command(ctx, cmd_name) - - # If we don't find the command we want to show an error message - # to the user that it was not provided. However, there is - # something else we should do: if the first argument looks like - # an option we want to kick off parsing again for arguments to - # resolve things like --help which now should go to the main - # place. - if cmd is None and not ctx.resilient_parsing: - if split_opt(cmd_name)[0]: - self.parse_args(ctx, ctx.args) - ctx.fail('No such command "%s".' % original_cmd_name) - - return cmd_name, cmd, args[1:] - - def get_command(self, ctx, cmd_name): - """Given a context and a command name, this returns a - :class:`Command` object if it exists or returns `None`. - """ - raise NotImplementedError() - - def list_commands(self, ctx): - """Returns a list of subcommand names in the order they should - appear. - """ - return [] - - -class Group(MultiCommand): - """A group allows a command to have subcommands attached. This is the - most common way to implement nesting in Click. - - :param commands: a dictionary of commands. - """ - - def __init__(self, name=None, commands=None, **attrs): - MultiCommand.__init__(self, name, **attrs) - #: the registered subcommands by their exported names. - self.commands = commands or {} - - def add_command(self, cmd, name=None): - """Registers another :class:`Command` with this group. If the name - is not provided, the name of the command is used. - """ - name = name or cmd.name - if name is None: - raise TypeError('Command has no name.') - _check_multicommand(self, name, cmd, register=True) - self.commands[name] = cmd - - def command(self, *args, **kwargs): - """A shortcut decorator for declaring and attaching a command to - the group. This takes the same arguments as :func:`command` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. - """ - def decorator(f): - cmd = command(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - return decorator - - def group(self, *args, **kwargs): - """A shortcut decorator for declaring and attaching a group to - the group. This takes the same arguments as :func:`group` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. - """ - def decorator(f): - cmd = group(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - return decorator - - def get_command(self, ctx, cmd_name): - return self.commands.get(cmd_name) - - def list_commands(self, ctx): - return sorted(self.commands) - - -class CommandCollection(MultiCommand): - """A command collection is a multi command that merges multiple multi - commands together into one. This is a straightforward implementation - that accepts a list of different multi commands as sources and - provides all the commands for each of them. - """ - - def __init__(self, name=None, sources=None, **attrs): - MultiCommand.__init__(self, name, **attrs) - #: The list of registered multi commands. - self.sources = sources or [] - - def add_source(self, multi_cmd): - """Adds a new multi command to the chain dispatcher.""" - self.sources.append(multi_cmd) - - def get_command(self, ctx, cmd_name): - for source in self.sources: - rv = source.get_command(ctx, cmd_name) - if rv is not None: - if self.chain: - _check_multicommand(self, cmd_name, rv) - return rv - - def list_commands(self, ctx): - rv = set() - for source in self.sources: - rv.update(source.list_commands(ctx)) - return sorted(rv) - - -class Parameter(object): - r"""A parameter to a command comes in two versions: they are either - :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently - not supported by design as some of the internals for parsing are - intentionally not finalized. - - Some settings are supported by both options and arguments. - - .. versionchanged:: 2.0 - Changed signature for parameter callback to also be passed the - parameter. In Click 2.0, the old callback format will still work, - but it will raise a warning to give you change to migrate the - code easier. - - :param param_decls: the parameter declarations for this option or - argument. This is a list of flags or argument - names. - :param type: the type that should be used. Either a :class:`ParamType` - or a Python type. The later is converted into the former - automatically if supported. - :param required: controls if this is optional or not. - :param default: the default value if omitted. This can also be a callable, - in which case it's invoked when the default is needed - without any arguments. - :param callback: a callback that should be executed after the parameter - was matched. This is called as ``fn(ctx, param, - value)`` and needs to return the value. Before Click - 2.0, the signature was ``(ctx, value)``. - :param nargs: the number of arguments to match. If not ``1`` the return - value is a tuple instead of single value. The default for - nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). - :param metavar: how the value is represented in the help page. - :param expose_value: if this is `True` then the value is passed onwards - to the command callback and stored on the context, - otherwise it's skipped. - :param is_eager: eager values are processed before non eager ones. This - should not be set for arguments or it will inverse the - order of processing. - :param envvar: a string or list of strings that are environment variables - that should be checked. - """ - param_type_name = 'parameter' - - def __init__(self, param_decls=None, type=None, required=False, - default=None, callback=None, nargs=None, metavar=None, - expose_value=True, is_eager=False, envvar=None, - autocompletion=None): - self.name, self.opts, self.secondary_opts = \ - self._parse_decls(param_decls or (), expose_value) - - self.type = convert_type(type, default) - - # Default nargs to what the type tells us if we have that - # information available. - if nargs is None: - if self.type.is_composite: - nargs = self.type.arity - else: - nargs = 1 - - self.required = required - self.callback = callback - self.nargs = nargs - self.multiple = False - self.expose_value = expose_value - self.default = default - self.is_eager = is_eager - self.metavar = metavar - self.envvar = envvar - self.autocompletion = autocompletion - - @property - def human_readable_name(self): - """Returns the human readable name of this parameter. This is the - same as the name for options, but the metavar for arguments. - """ - return self.name - - def make_metavar(self): - if self.metavar is not None: - return self.metavar - metavar = self.type.get_metavar(self) - if metavar is None: - metavar = self.type.name.upper() - if self.nargs != 1: - metavar += '...' - return metavar - - def get_default(self, ctx): - """Given a context variable this calculates the default value.""" - # Otherwise go with the regular default. - if callable(self.default): - rv = self.default() - else: - rv = self.default - return self.type_cast_value(ctx, rv) - - def add_to_parser(self, parser, ctx): - pass - - def consume_value(self, ctx, opts): - value = opts.get(self.name) - if value is None: - value = self.value_from_envvar(ctx) - if value is None: - value = ctx.lookup_default(self.name) - return value - - def type_cast_value(self, ctx, value): - """Given a value this runs it properly through the type system. - This automatically handles things like `nargs` and `multiple` as - well as composite types. - """ - if self.type.is_composite: - if self.nargs <= 1: - raise TypeError('Attempted to invoke composite type ' - 'but nargs has been set to %s. This is ' - 'not supported; nargs needs to be set to ' - 'a fixed value > 1.' % self.nargs) - if self.multiple: - return tuple(self.type(x or (), self, ctx) for x in value or ()) - return self.type(value or (), self, ctx) - - def _convert(value, level): - if level == 0: - return self.type(value, self, ctx) - return tuple(_convert(x, level - 1) for x in value or ()) - return _convert(value, (self.nargs != 1) + bool(self.multiple)) - - def process_value(self, ctx, value): - """Given a value and context this runs the logic to convert the - value as necessary. - """ - # If the value we were given is None we do nothing. This way - # code that calls this can easily figure out if something was - # not provided. Otherwise it would be converted into an empty - # tuple for multiple invocations which is inconvenient. - if value is not None: - return self.type_cast_value(ctx, value) - - def value_is_missing(self, value): - if value is None: - return True - if (self.nargs != 1 or self.multiple) and value == (): - return True - return False - - def full_process_value(self, ctx, value): - value = self.process_value(ctx, value) - - if value is None and not ctx.resilient_parsing: - value = self.get_default(ctx) - - if self.required and self.value_is_missing(value): - raise MissingParameter(ctx=ctx, param=self) - - return value - - def resolve_envvar_value(self, ctx): - if self.envvar is None: - return - if isinstance(self.envvar, (tuple, list)): - for envvar in self.envvar: - rv = os.environ.get(envvar) - if rv is not None: - return rv - else: - return os.environ.get(self.envvar) - - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) - if rv is not None and self.nargs != 1: - rv = self.type.split_envvar_value(rv) - return rv - - def handle_parse_result(self, ctx, opts, args): - with augment_usage_errors(ctx, param=self): - value = self.consume_value(ctx, opts) - try: - value = self.full_process_value(ctx, value) - except Exception: - if not ctx.resilient_parsing: - raise - value = None - if self.callback is not None: - try: - value = invoke_param_callback( - self.callback, ctx, self, value) - except Exception: - if not ctx.resilient_parsing: - raise - - if self.expose_value: - ctx.params[self.name] = value - return value, args - - def get_help_record(self, ctx): - pass - - def get_usage_pieces(self, ctx): - return [] - - def get_error_hint(self, ctx): - """Get a stringified version of the param for use in error messages to - indicate which param caused the error. - """ - hint_list = self.opts or [self.human_readable_name] - return ' / '.join('"%s"' % x for x in hint_list) - - -class Option(Parameter): - """Options are usually optional values on the command line and - have some extra features that arguments don't have. - - All other parameters are passed onwards to the parameter constructor. - - :param show_default: controls if the default value should be shown on the - help page. Normally, defaults are not shown. If this - value is a string, it shows the string instead of the - value. This is particularly useful for dynamic options. - :param show_envvar: controls if an environment variable should be shown on - the help page. Normally, environment variables - are not shown. - :param prompt: if set to `True` or a non empty string then the user will be - prompted for input. If set to `True` the prompt will be the - option name capitalized. - :param confirmation_prompt: if set then the value will need to be confirmed - if it was prompted for. - :param hide_input: if this is `True` then the input on the prompt will be - hidden from the user. This is useful for password - input. - :param is_flag: forces this option to act as a flag. The default is - auto detection. - :param flag_value: which value should be used for this flag if it's - enabled. This is set to a boolean automatically if - the option string contains a slash to mark two options. - :param multiple: if this is set to `True` then the argument is accepted - multiple times and recorded. This is similar to ``nargs`` - in how it works but supports arbitrary number of - arguments. - :param count: this flag makes an option increment an integer. - :param allow_from_autoenv: if this is enabled then the value of this - parameter will be pulled from an environment - variable in case a prefix is defined on the - context. - :param help: the help string. - :param hidden: hide this option from help outputs. - """ - param_type_name = 'option' - - def __init__(self, param_decls=None, show_default=False, - prompt=False, confirmation_prompt=False, - hide_input=False, is_flag=None, flag_value=None, - multiple=False, count=False, allow_from_autoenv=True, - type=None, help=None, hidden=False, show_choices=True, - show_envvar=False, **attrs): - default_is_missing = attrs.get('default', _missing) is _missing - Parameter.__init__(self, param_decls, type=type, **attrs) - - if prompt is True: - prompt_text = self.name.replace('_', ' ').capitalize() - elif prompt is False: - prompt_text = None - else: - prompt_text = prompt - self.prompt = prompt_text - self.confirmation_prompt = confirmation_prompt - self.hide_input = hide_input - self.hidden = hidden - - # Flags - if is_flag is None: - if flag_value is not None: - is_flag = True - else: - is_flag = bool(self.secondary_opts) - if is_flag and default_is_missing: - self.default = False - if flag_value is None: - flag_value = not self.default - self.is_flag = is_flag - self.flag_value = flag_value - if self.is_flag and isinstance(self.flag_value, bool) \ - and type is None: - self.type = BOOL - self.is_bool_flag = True - else: - self.is_bool_flag = False - - # Counting - self.count = count - if count: - if type is None: - self.type = IntRange(min=0) - if default_is_missing: - self.default = 0 - - self.multiple = multiple - self.allow_from_autoenv = allow_from_autoenv - self.help = help - self.show_default = show_default - self.show_choices = show_choices - self.show_envvar = show_envvar - - # Sanity check for stuff we don't support - if __debug__: - if self.nargs < 0: - raise TypeError('Options cannot have nargs < 0') - if self.prompt and self.is_flag and not self.is_bool_flag: - raise TypeError('Cannot prompt for flags that are not bools.') - if not self.is_bool_flag and self.secondary_opts: - raise TypeError('Got secondary option for non boolean flag.') - if self.is_bool_flag and self.hide_input \ - and self.prompt is not None: - raise TypeError('Hidden input does not work with boolean ' - 'flag prompts.') - if self.count: - if self.multiple: - raise TypeError('Options cannot be multiple and count ' - 'at the same time.') - elif self.is_flag: - raise TypeError('Options cannot be count and flags at ' - 'the same time.') - - def _parse_decls(self, decls, expose_value): - opts = [] - secondary_opts = [] - name = None - possible_names = [] - - for decl in decls: - if isidentifier(decl): - if name is not None: - raise TypeError('Name defined twice') - name = decl - else: - split_char = decl[:1] == '/' and ';' or '/' - if split_char in decl: - first, second = decl.split(split_char, 1) - first = first.rstrip() - if first: - possible_names.append(split_opt(first)) - opts.append(first) - second = second.lstrip() - if second: - secondary_opts.append(second.lstrip()) - else: - possible_names.append(split_opt(decl)) - opts.append(decl) - - if name is None and possible_names: - possible_names.sort(key=lambda x: -len(x[0])) # group long options first - name = possible_names[0][1].replace('-', '_').lower() - if not isidentifier(name): - name = None - - if name is None: - if not expose_value: - return None, opts, secondary_opts - raise TypeError('Could not determine name for option') - - if not opts and not secondary_opts: - raise TypeError('No options defined but a name was passed (%s). ' - 'Did you mean to declare an argument instead ' - 'of an option?' % name) - - return name, opts, secondary_opts - - def add_to_parser(self, parser, ctx): - kwargs = { - 'dest': self.name, - 'nargs': self.nargs, - 'obj': self, - } - - if self.multiple: - action = 'append' - elif self.count: - action = 'count' - else: - action = 'store' - - if self.is_flag: - kwargs.pop('nargs', None) - if self.is_bool_flag and self.secondary_opts: - parser.add_option(self.opts, action=action + '_const', - const=True, **kwargs) - parser.add_option(self.secondary_opts, action=action + - '_const', const=False, **kwargs) - else: - parser.add_option(self.opts, action=action + '_const', - const=self.flag_value, - **kwargs) - else: - kwargs['action'] = action - parser.add_option(self.opts, **kwargs) - - def get_help_record(self, ctx): - if self.hidden: - return - any_prefix_is_slash = [] - - def _write_opts(opts): - rv, any_slashes = join_options(opts) - if any_slashes: - any_prefix_is_slash[:] = [True] - if not self.is_flag and not self.count: - rv += ' ' + self.make_metavar() - return rv - - rv = [_write_opts(self.opts)] - if self.secondary_opts: - rv.append(_write_opts(self.secondary_opts)) - - help = self.help or '' - extra = [] - if self.show_envvar: - envvar = self.envvar - if envvar is None: - if self.allow_from_autoenv and \ - ctx.auto_envvar_prefix is not None: - envvar = '%s_%s' % (ctx.auto_envvar_prefix, self.name.upper()) - if envvar is not None: - extra.append('env var: %s' % ( - ', '.join('%s' % d for d in envvar) - if isinstance(envvar, (list, tuple)) - else envvar, )) - if self.default is not None and self.show_default: - if isinstance(self.show_default, string_types): - default_string = '({})'.format(self.show_default) - elif isinstance(self.default, (list, tuple)): - default_string = ', '.join('%s' % d for d in self.default) - elif inspect.isfunction(self.default): - default_string = "(dynamic)" - else: - default_string = self.default - extra.append('default: {}'.format(default_string)) - - if self.required: - extra.append('required') - if extra: - help = '%s[%s]' % (help and help + ' ' or '', '; '.join(extra)) - - return ((any_prefix_is_slash and '; ' or ' / ').join(rv), help) - - def get_default(self, ctx): - # If we're a non boolean flag out default is more complex because - # we need to look at all flags in the same group to figure out - # if we're the the default one in which case we return the flag - # value as default. - if self.is_flag and not self.is_bool_flag: - for param in ctx.command.params: - if param.name == self.name and param.default: - return param.flag_value - return None - return Parameter.get_default(self, ctx) - - def prompt_for_value(self, ctx): - """This is an alternative flow that can be activated in the full - value processing if a value does not exist. It will prompt the - user until a valid value exists and then returns the processed - value as result. - """ - # Calculate the default before prompting anything to be stable. - default = self.get_default(ctx) - - # If this is a prompt for a flag we need to handle this - # differently. - if self.is_bool_flag: - return confirm(self.prompt, default) - - return prompt(self.prompt, default=default, type=self.type, - hide_input=self.hide_input, show_choices=self.show_choices, - confirmation_prompt=self.confirmation_prompt, - value_proc=lambda x: self.process_value(ctx, x)) - - def resolve_envvar_value(self, ctx): - rv = Parameter.resolve_envvar_value(self, ctx) - if rv is not None: - return rv - if self.allow_from_autoenv and \ - ctx.auto_envvar_prefix is not None: - envvar = '%s_%s' % (ctx.auto_envvar_prefix, self.name.upper()) - return os.environ.get(envvar) - - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) - if rv is None: - return None - value_depth = (self.nargs != 1) + bool(self.multiple) - if value_depth > 0 and rv is not None: - rv = self.type.split_envvar_value(rv) - if self.multiple and self.nargs != 1: - rv = batch(rv, self.nargs) - return rv - - def full_process_value(self, ctx, value): - if value is None and self.prompt is not None \ - and not ctx.resilient_parsing: - return self.prompt_for_value(ctx) - return Parameter.full_process_value(self, ctx, value) - - -class Argument(Parameter): - """Arguments are positional parameters to a command. They generally - provide fewer features than options but can have infinite ``nargs`` - and are required by default. - - All parameters are passed onwards to the parameter constructor. - """ - param_type_name = 'argument' - - def __init__(self, param_decls, required=None, **attrs): - if required is None: - if attrs.get('default') is not None: - required = False - else: - required = attrs.get('nargs', 1) > 0 - Parameter.__init__(self, param_decls, required=required, **attrs) - if self.default is not None and self.nargs < 0: - raise TypeError('nargs=-1 in combination with a default value ' - 'is not supported.') - - @property - def human_readable_name(self): - if self.metavar is not None: - return self.metavar - return self.name.upper() - - def make_metavar(self): - if self.metavar is not None: - return self.metavar - var = self.type.get_metavar(self) - if not var: - var = self.name.upper() - if not self.required: - var = '[%s]' % var - if self.nargs != 1: - var += '...' - return var - - def _parse_decls(self, decls, expose_value): - if not decls: - if not expose_value: - return None, [], [] - raise TypeError('Could not determine name for argument') - if len(decls) == 1: - name = arg = decls[0] - name = name.replace('-', '_').lower() - else: - raise TypeError('Arguments take exactly one ' - 'parameter declaration, got %d' % len(decls)) - return name, [arg], [] - - def get_usage_pieces(self, ctx): - return [self.make_metavar()] - - def get_error_hint(self, ctx): - return '"%s"' % self.make_metavar() - - def add_to_parser(self, parser, ctx): - parser.add_argument(dest=self.name, nargs=self.nargs, - obj=self) - - -# Circular dependency between decorators and core -from .decorators import command, group diff --git a/py3.7/lib/python3.7/site-packages/click/decorators.py b/py3.7/lib/python3.7/site-packages/click/decorators.py deleted file mode 100644 index c57c530..0000000 --- a/py3.7/lib/python3.7/site-packages/click/decorators.py +++ /dev/null @@ -1,311 +0,0 @@ -import sys -import inspect - -from functools import update_wrapper - -from ._compat import iteritems -from ._unicodefun import _check_for_unicode_literals -from .utils import echo -from .globals import get_current_context - - -def pass_context(f): - """Marks a callback as wanting to receive the current context - object as first argument. - """ - def new_func(*args, **kwargs): - return f(get_current_context(), *args, **kwargs) - return update_wrapper(new_func, f) - - -def pass_obj(f): - """Similar to :func:`pass_context`, but only pass the object on the - context onwards (:attr:`Context.obj`). This is useful if that object - represents the state of a nested system. - """ - def new_func(*args, **kwargs): - return f(get_current_context().obj, *args, **kwargs) - return update_wrapper(new_func, f) - - -def make_pass_decorator(object_type, ensure=False): - """Given an object type this creates a decorator that will work - similar to :func:`pass_obj` but instead of passing the object of the - current context, it will find the innermost context of type - :func:`object_type`. - - This generates a decorator that works roughly like this:: - - from functools import update_wrapper - - def decorator(f): - @pass_context - def new_func(ctx, *args, **kwargs): - obj = ctx.find_object(object_type) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - :param object_type: the type of the object to pass. - :param ensure: if set to `True`, a new object will be created and - remembered on the context if it's not there yet. - """ - def decorator(f): - def new_func(*args, **kwargs): - ctx = get_current_context() - if ensure: - obj = ctx.ensure_object(object_type) - else: - obj = ctx.find_object(object_type) - if obj is None: - raise RuntimeError('Managed to invoke callback without a ' - 'context object of type %r existing' - % object_type.__name__) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - -def _make_command(f, name, attrs, cls): - if isinstance(f, Command): - raise TypeError('Attempted to convert a callback into a ' - 'command twice.') - try: - params = f.__click_params__ - params.reverse() - del f.__click_params__ - except AttributeError: - params = [] - help = attrs.get('help') - if help is None: - help = inspect.getdoc(f) - if isinstance(help, bytes): - help = help.decode('utf-8') - else: - help = inspect.cleandoc(help) - attrs['help'] = help - _check_for_unicode_literals() - return cls(name=name or f.__name__.lower().replace('_', '-'), - callback=f, params=params, **attrs) - - -def command(name=None, cls=None, **attrs): - r"""Creates a new :class:`Command` and uses the decorated function as - callback. This will also automatically attach all decorated - :func:`option`\s and :func:`argument`\s as parameters to the command. - - The name of the command defaults to the name of the function. If you - want to change that, you can pass the intended name as the first - argument. - - All keyword arguments are forwarded to the underlying command class. - - Once decorated the function turns into a :class:`Command` instance - that can be invoked as a command line utility or be attached to a - command :class:`Group`. - - :param name: the name of the command. This defaults to the function - name with underscores replaced by dashes. - :param cls: the command class to instantiate. This defaults to - :class:`Command`. - """ - if cls is None: - cls = Command - def decorator(f): - cmd = _make_command(f, name, attrs, cls) - cmd.__doc__ = f.__doc__ - return cmd - return decorator - - -def group(name=None, **attrs): - """Creates a new :class:`Group` with a function as callback. This - works otherwise the same as :func:`command` just that the `cls` - parameter is set to :class:`Group`. - """ - attrs.setdefault('cls', Group) - return command(name, **attrs) - - -def _param_memo(f, param): - if isinstance(f, Command): - f.params.append(param) - else: - if not hasattr(f, '__click_params__'): - f.__click_params__ = [] - f.__click_params__.append(param) - - -def argument(*param_decls, **attrs): - """Attaches an argument to the command. All positional arguments are - passed as parameter declarations to :class:`Argument`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Argument` instance manually - and attaching it to the :attr:`Command.params` list. - - :param cls: the argument class to instantiate. This defaults to - :class:`Argument`. - """ - def decorator(f): - ArgumentClass = attrs.pop('cls', Argument) - _param_memo(f, ArgumentClass(param_decls, **attrs)) - return f - return decorator - - -def option(*param_decls, **attrs): - """Attaches an option to the command. All positional arguments are - passed as parameter declarations to :class:`Option`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Option` instance manually - and attaching it to the :attr:`Command.params` list. - - :param cls: the option class to instantiate. This defaults to - :class:`Option`. - """ - def decorator(f): - # Issue 926, copy attrs, so pre-defined options can re-use the same cls= - option_attrs = attrs.copy() - - if 'help' in option_attrs: - option_attrs['help'] = inspect.cleandoc(option_attrs['help']) - OptionClass = option_attrs.pop('cls', Option) - _param_memo(f, OptionClass(param_decls, **option_attrs)) - return f - return decorator - - -def confirmation_option(*param_decls, **attrs): - """Shortcut for confirmation prompts that can be ignored by passing - ``--yes`` as parameter. - - This is equivalent to decorating a function with :func:`option` with - the following parameters:: - - def callback(ctx, param, value): - if not value: - ctx.abort() - - @click.command() - @click.option('--yes', is_flag=True, callback=callback, - expose_value=False, prompt='Do you want to continue?') - def dropdb(): - pass - """ - def decorator(f): - def callback(ctx, param, value): - if not value: - ctx.abort() - attrs.setdefault('is_flag', True) - attrs.setdefault('callback', callback) - attrs.setdefault('expose_value', False) - attrs.setdefault('prompt', 'Do you want to continue?') - attrs.setdefault('help', 'Confirm the action without prompting.') - return option(*(param_decls or ('--yes',)), **attrs)(f) - return decorator - - -def password_option(*param_decls, **attrs): - """Shortcut for password prompts. - - This is equivalent to decorating a function with :func:`option` with - the following parameters:: - - @click.command() - @click.option('--password', prompt=True, confirmation_prompt=True, - hide_input=True) - def changeadmin(password): - pass - """ - def decorator(f): - attrs.setdefault('prompt', True) - attrs.setdefault('confirmation_prompt', True) - attrs.setdefault('hide_input', True) - return option(*(param_decls or ('--password',)), **attrs)(f) - return decorator - - -def version_option(version=None, *param_decls, **attrs): - """Adds a ``--version`` option which immediately ends the program - printing out the version number. This is implemented as an eager - option that prints the version and exits the program in the callback. - - :param version: the version number to show. If not provided Click - attempts an auto discovery via setuptools. - :param prog_name: the name of the program (defaults to autodetection) - :param message: custom message to show instead of the default - (``'%(prog)s, version %(version)s'``) - :param others: everything else is forwarded to :func:`option`. - """ - if version is None: - if hasattr(sys, '_getframe'): - module = sys._getframe(1).f_globals.get('__name__') - else: - module = '' - - def decorator(f): - prog_name = attrs.pop('prog_name', None) - message = attrs.pop('message', '%(prog)s, version %(version)s') - - def callback(ctx, param, value): - if not value or ctx.resilient_parsing: - return - prog = prog_name - if prog is None: - prog = ctx.find_root().info_name - ver = version - if ver is None: - try: - import pkg_resources - except ImportError: - pass - else: - for dist in pkg_resources.working_set: - scripts = dist.get_entry_map().get('console_scripts') or {} - for script_name, entry_point in iteritems(scripts): - if entry_point.module_name == module: - ver = dist.version - break - if ver is None: - raise RuntimeError('Could not determine version') - echo(message % { - 'prog': prog, - 'version': ver, - }, color=ctx.color) - ctx.exit() - - attrs.setdefault('is_flag', True) - attrs.setdefault('expose_value', False) - attrs.setdefault('is_eager', True) - attrs.setdefault('help', 'Show the version and exit.') - attrs['callback'] = callback - return option(*(param_decls or ('--version',)), **attrs)(f) - return decorator - - -def help_option(*param_decls, **attrs): - """Adds a ``--help`` option which immediately ends the program - printing out the help page. This is usually unnecessary to add as - this is added by default to all commands unless suppressed. - - Like :func:`version_option`, this is implemented as eager option that - prints in the callback and exits. - - All arguments are forwarded to :func:`option`. - """ - def decorator(f): - def callback(ctx, param, value): - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - attrs.setdefault('is_flag', True) - attrs.setdefault('expose_value', False) - attrs.setdefault('help', 'Show this message and exit.') - attrs.setdefault('is_eager', True) - attrs['callback'] = callback - return option(*(param_decls or ('--help',)), **attrs)(f) - return decorator - - -# Circular dependencies between core and decorators -from .core import Command, Group, Argument, Option diff --git a/py3.7/lib/python3.7/site-packages/click/exceptions.py b/py3.7/lib/python3.7/site-packages/click/exceptions.py deleted file mode 100644 index 6fa1765..0000000 --- a/py3.7/lib/python3.7/site-packages/click/exceptions.py +++ /dev/null @@ -1,235 +0,0 @@ -from ._compat import PY2, filename_to_ui, get_text_stderr -from .utils import echo - - -def _join_param_hints(param_hint): - if isinstance(param_hint, (tuple, list)): - return ' / '.join('"%s"' % x for x in param_hint) - return param_hint - - -class ClickException(Exception): - """An exception that Click can handle and show to the user.""" - - #: The exit code for this exception - exit_code = 1 - - def __init__(self, message): - ctor_msg = message - if PY2: - if ctor_msg is not None: - ctor_msg = ctor_msg.encode('utf-8') - Exception.__init__(self, ctor_msg) - self.message = message - - def format_message(self): - return self.message - - def __str__(self): - return self.message - - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.message.encode('utf-8') - - def show(self, file=None): - if file is None: - file = get_text_stderr() - echo('Error: %s' % self.format_message(), file=file) - - -class UsageError(ClickException): - """An internal exception that signals a usage error. This typically - aborts any further handling. - - :param message: the error message to display. - :param ctx: optionally the context that caused this error. Click will - fill in the context automatically in some situations. - """ - exit_code = 2 - - def __init__(self, message, ctx=None): - ClickException.__init__(self, message) - self.ctx = ctx - self.cmd = self.ctx and self.ctx.command or None - - def show(self, file=None): - if file is None: - file = get_text_stderr() - color = None - hint = '' - if (self.cmd is not None and - self.cmd.get_help_option(self.ctx) is not None): - hint = ('Try "%s %s" for help.\n' - % (self.ctx.command_path, self.ctx.help_option_names[0])) - if self.ctx is not None: - color = self.ctx.color - echo(self.ctx.get_usage() + '\n%s' % hint, file=file, color=color) - echo('Error: %s' % self.format_message(), file=file, color=color) - - -class BadParameter(UsageError): - """An exception that formats out a standardized error message for a - bad parameter. This is useful when thrown from a callback or type as - Click will attach contextual information to it (for instance, which - parameter it is). - - .. versionadded:: 2.0 - - :param param: the parameter object that caused this error. This can - be left out, and Click will attach this info itself - if possible. - :param param_hint: a string that shows up as parameter name. This - can be used as alternative to `param` in cases - where custom validation should happen. If it is - a string it's used as such, if it's a list then - each item is quoted and separated. - """ - - def __init__(self, message, ctx=None, param=None, - param_hint=None): - UsageError.__init__(self, message, ctx) - self.param = param - self.param_hint = param_hint - - def format_message(self): - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - return 'Invalid value: %s' % self.message - param_hint = _join_param_hints(param_hint) - - return 'Invalid value for %s: %s' % (param_hint, self.message) - - -class MissingParameter(BadParameter): - """Raised if click required an option or argument but it was not - provided when invoking the script. - - .. versionadded:: 4.0 - - :param param_type: a string that indicates the type of the parameter. - The default is to inherit the parameter type from - the given `param`. Valid values are ``'parameter'``, - ``'option'`` or ``'argument'``. - """ - - def __init__(self, message=None, ctx=None, param=None, - param_hint=None, param_type=None): - BadParameter.__init__(self, message, ctx, param, param_hint) - self.param_type = param_type - - def format_message(self): - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) - else: - param_hint = None - param_hint = _join_param_hints(param_hint) - - param_type = self.param_type - if param_type is None and self.param is not None: - param_type = self.param.param_type_name - - msg = self.message - if self.param is not None: - msg_extra = self.param.type.get_missing_message(self.param) - if msg_extra: - if msg: - msg += '. ' + msg_extra - else: - msg = msg_extra - - return 'Missing %s%s%s%s' % ( - param_type, - param_hint and ' %s' % param_hint or '', - msg and '. ' or '.', - msg or '', - ) - - -class NoSuchOption(UsageError): - """Raised if click attempted to handle an option that does not - exist. - - .. versionadded:: 4.0 - """ - - def __init__(self, option_name, message=None, possibilities=None, - ctx=None): - if message is None: - message = 'no such option: %s' % option_name - UsageError.__init__(self, message, ctx) - self.option_name = option_name - self.possibilities = possibilities - - def format_message(self): - bits = [self.message] - if self.possibilities: - if len(self.possibilities) == 1: - bits.append('Did you mean %s?' % self.possibilities[0]) - else: - possibilities = sorted(self.possibilities) - bits.append('(Possible options: %s)' % ', '.join(possibilities)) - return ' '.join(bits) - - -class BadOptionUsage(UsageError): - """Raised if an option is generally supplied but the use of the option - was incorrect. This is for instance raised if the number of arguments - for an option is not correct. - - .. versionadded:: 4.0 - - :param option_name: the name of the option being used incorrectly. - """ - - def __init__(self, option_name, message, ctx=None): - UsageError.__init__(self, message, ctx) - self.option_name = option_name - - -class BadArgumentUsage(UsageError): - """Raised if an argument is generally supplied but the use of the argument - was incorrect. This is for instance raised if the number of values - for an argument is not correct. - - .. versionadded:: 6.0 - """ - - def __init__(self, message, ctx=None): - UsageError.__init__(self, message, ctx) - - -class FileError(ClickException): - """Raised if a file cannot be opened.""" - - def __init__(self, filename, hint=None): - ui_filename = filename_to_ui(filename) - if hint is None: - hint = 'unknown error' - ClickException.__init__(self, hint) - self.ui_filename = ui_filename - self.filename = filename - - def format_message(self): - return 'Could not open file %s: %s' % (self.ui_filename, self.message) - - -class Abort(RuntimeError): - """An internal signalling exception that signals Click to abort.""" - - -class Exit(RuntimeError): - """An exception that indicates that the application should exit with some - status code. - - :param code: the status code to exit with. - """ - def __init__(self, code=0): - self.exit_code = code diff --git a/py3.7/lib/python3.7/site-packages/click/formatting.py b/py3.7/lib/python3.7/site-packages/click/formatting.py deleted file mode 100644 index a3d6a4d..0000000 --- a/py3.7/lib/python3.7/site-packages/click/formatting.py +++ /dev/null @@ -1,256 +0,0 @@ -from contextlib import contextmanager -from .termui import get_terminal_size -from .parser import split_opt -from ._compat import term_len - - -# Can force a width. This is used by the test system -FORCED_WIDTH = None - - -def measure_table(rows): - widths = {} - for row in rows: - for idx, col in enumerate(row): - widths[idx] = max(widths.get(idx, 0), term_len(col)) - return tuple(y for x, y in sorted(widths.items())) - - -def iter_rows(rows, col_count): - for row in rows: - row = tuple(row) - yield row + ('',) * (col_count - len(row)) - - -def wrap_text(text, width=78, initial_indent='', subsequent_indent='', - preserve_paragraphs=False): - """A helper function that intelligently wraps text. By default, it - assumes that it operates on a single paragraph of text but if the - `preserve_paragraphs` parameter is provided it will intelligently - handle paragraphs (defined by two empty lines). - - If paragraphs are handled, a paragraph can be prefixed with an empty - line containing the ``\\b`` character (``\\x08``) to indicate that - no rewrapping should happen in that block. - - :param text: the text that should be rewrapped. - :param width: the maximum width for the text. - :param initial_indent: the initial indent that should be placed on the - first line as a string. - :param subsequent_indent: the indent string that should be placed on - each consecutive line. - :param preserve_paragraphs: if this flag is set then the wrapping will - intelligently handle paragraphs. - """ - from ._textwrap import TextWrapper - text = text.expandtabs() - wrapper = TextWrapper(width, initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - replace_whitespace=False) - if not preserve_paragraphs: - return wrapper.fill(text) - - p = [] - buf = [] - indent = None - - def _flush_par(): - if not buf: - return - if buf[0].strip() == '\b': - p.append((indent or 0, True, '\n'.join(buf[1:]))) - else: - p.append((indent or 0, False, ' '.join(buf))) - del buf[:] - - for line in text.splitlines(): - if not line: - _flush_par() - indent = None - else: - if indent is None: - orig_len = term_len(line) - line = line.lstrip() - indent = orig_len - term_len(line) - buf.append(line) - _flush_par() - - rv = [] - for indent, raw, text in p: - with wrapper.extra_indent(' ' * indent): - if raw: - rv.append(wrapper.indent_only(text)) - else: - rv.append(wrapper.fill(text)) - - return '\n\n'.join(rv) - - -class HelpFormatter(object): - """This class helps with formatting text-based help pages. It's - usually just needed for very special internal cases, but it's also - exposed so that developers can write their own fancy outputs. - - At present, it always writes into memory. - - :param indent_increment: the additional increment for each level. - :param width: the width for the text. This defaults to the terminal - width clamped to a maximum of 78. - """ - - def __init__(self, indent_increment=2, width=None, max_width=None): - self.indent_increment = indent_increment - if max_width is None: - max_width = 80 - if width is None: - width = FORCED_WIDTH - if width is None: - width = max(min(get_terminal_size()[0], max_width) - 2, 50) - self.width = width - self.current_indent = 0 - self.buffer = [] - - def write(self, string): - """Writes a unicode string into the internal buffer.""" - self.buffer.append(string) - - def indent(self): - """Increases the indentation.""" - self.current_indent += self.indent_increment - - def dedent(self): - """Decreases the indentation.""" - self.current_indent -= self.indent_increment - - def write_usage(self, prog, args='', prefix='Usage: '): - """Writes a usage line into the buffer. - - :param prog: the program name. - :param args: whitespace separated list of arguments. - :param prefix: the prefix for the first line. - """ - usage_prefix = '%*s%s ' % (self.current_indent, prefix, prog) - text_width = self.width - self.current_indent - - if text_width >= (term_len(usage_prefix) + 20): - # The arguments will fit to the right of the prefix. - indent = ' ' * term_len(usage_prefix) - self.write(wrap_text(args, text_width, - initial_indent=usage_prefix, - subsequent_indent=indent)) - else: - # The prefix is too long, put the arguments on the next line. - self.write(usage_prefix) - self.write('\n') - indent = ' ' * (max(self.current_indent, term_len(prefix)) + 4) - self.write(wrap_text(args, text_width, - initial_indent=indent, - subsequent_indent=indent)) - - self.write('\n') - - def write_heading(self, heading): - """Writes a heading into the buffer.""" - self.write('%*s%s:\n' % (self.current_indent, '', heading)) - - def write_paragraph(self): - """Writes a paragraph into the buffer.""" - if self.buffer: - self.write('\n') - - def write_text(self, text): - """Writes re-indented text into the buffer. This rewraps and - preserves paragraphs. - """ - text_width = max(self.width - self.current_indent, 11) - indent = ' ' * self.current_indent - self.write(wrap_text(text, text_width, - initial_indent=indent, - subsequent_indent=indent, - preserve_paragraphs=True)) - self.write('\n') - - def write_dl(self, rows, col_max=30, col_spacing=2): - """Writes a definition list into the buffer. This is how options - and commands are usually formatted. - - :param rows: a list of two item tuples for the terms and values. - :param col_max: the maximum width of the first column. - :param col_spacing: the number of spaces between the first and - second column. - """ - rows = list(rows) - widths = measure_table(rows) - if len(widths) != 2: - raise TypeError('Expected two columns for definition list') - - first_col = min(widths[0], col_max) + col_spacing - - for first, second in iter_rows(rows, len(widths)): - self.write('%*s%s' % (self.current_indent, '', first)) - if not second: - self.write('\n') - continue - if term_len(first) <= first_col - col_spacing: - self.write(' ' * (first_col - term_len(first))) - else: - self.write('\n') - self.write(' ' * (first_col + self.current_indent)) - - text_width = max(self.width - first_col - 2, 10) - lines = iter(wrap_text(second, text_width).splitlines()) - if lines: - self.write(next(lines) + '\n') - for line in lines: - self.write('%*s%s\n' % ( - first_col + self.current_indent, '', line)) - else: - self.write('\n') - - @contextmanager - def section(self, name): - """Helpful context manager that writes a paragraph, a heading, - and the indents. - - :param name: the section name that is written as heading. - """ - self.write_paragraph() - self.write_heading(name) - self.indent() - try: - yield - finally: - self.dedent() - - @contextmanager - def indentation(self): - """A context manager that increases the indentation.""" - self.indent() - try: - yield - finally: - self.dedent() - - def getvalue(self): - """Returns the buffer contents.""" - return ''.join(self.buffer) - - -def join_options(options): - """Given a list of option strings this joins them in the most appropriate - way and returns them in the form ``(formatted_string, - any_prefix_is_slash)`` where the second item in the tuple is a flag that - indicates if any of the option prefixes was a slash. - """ - rv = [] - any_prefix_is_slash = False - for opt in options: - prefix = split_opt(opt)[0] - if prefix == '/': - any_prefix_is_slash = True - rv.append((len(prefix), opt)) - - rv.sort(key=lambda x: x[0]) - - rv = ', '.join(x[1] for x in rv) - return rv, any_prefix_is_slash diff --git a/py3.7/lib/python3.7/site-packages/click/globals.py b/py3.7/lib/python3.7/site-packages/click/globals.py deleted file mode 100644 index 843b594..0000000 --- a/py3.7/lib/python3.7/site-packages/click/globals.py +++ /dev/null @@ -1,48 +0,0 @@ -from threading import local - - -_local = local() - - -def get_current_context(silent=False): - """Returns the current click context. This can be used as a way to - access the current context object from anywhere. This is a more implicit - alternative to the :func:`pass_context` decorator. This function is - primarily useful for helpers such as :func:`echo` which might be - interested in changing its behavior based on the current context. - - To push the current context, :meth:`Context.scope` can be used. - - .. versionadded:: 5.0 - - :param silent: is set to `True` the return value is `None` if no context - is available. The default behavior is to raise a - :exc:`RuntimeError`. - """ - try: - return getattr(_local, 'stack')[-1] - except (AttributeError, IndexError): - if not silent: - raise RuntimeError('There is no active click context.') - - -def push_context(ctx): - """Pushes a new context to the current stack.""" - _local.__dict__.setdefault('stack', []).append(ctx) - - -def pop_context(): - """Removes the top level from the stack.""" - _local.stack.pop() - - -def resolve_color_default(color=None): - """"Internal helper to get the default value of the color flag. If a - value is passed it's returned unchanged, otherwise it's looked up from - the current context. - """ - if color is not None: - return color - ctx = get_current_context(silent=True) - if ctx is not None: - return ctx.color diff --git a/py3.7/lib/python3.7/site-packages/click/parser.py b/py3.7/lib/python3.7/site-packages/click/parser.py deleted file mode 100644 index 1c3ae9c..0000000 --- a/py3.7/lib/python3.7/site-packages/click/parser.py +++ /dev/null @@ -1,427 +0,0 @@ -# -*- coding: utf-8 -*- -""" -click.parser -~~~~~~~~~~~~ - -This module started out as largely a copy paste from the stdlib's -optparse module with the features removed that we do not need from -optparse because we implement them in Click on a higher level (for -instance type handling, help formatting and a lot more). - -The plan is to remove more and more from here over time. - -The reason this is a different module and not optparse from the stdlib -is that there are differences in 2.x and 3.x about the error messages -generated and optparse in the stdlib uses gettext for no good reason -and might cause us issues. -""" - -import re -from collections import deque -from .exceptions import UsageError, NoSuchOption, BadOptionUsage, \ - BadArgumentUsage - - -def _unpack_args(args, nargs_spec): - """Given an iterable of arguments and an iterable of nargs specifications, - it returns a tuple with all the unpacked arguments at the first index - and all remaining arguments as the second. - - The nargs specification is the number of arguments that should be consumed - or `-1` to indicate that this position should eat up all the remainders. - - Missing items are filled with `None`. - """ - args = deque(args) - nargs_spec = deque(nargs_spec) - rv = [] - spos = None - - def _fetch(c): - try: - if spos is None: - return c.popleft() - else: - return c.pop() - except IndexError: - return None - - while nargs_spec: - nargs = _fetch(nargs_spec) - if nargs == 1: - rv.append(_fetch(args)) - elif nargs > 1: - x = [_fetch(args) for _ in range(nargs)] - # If we're reversed, we're pulling in the arguments in reverse, - # so we need to turn them around. - if spos is not None: - x.reverse() - rv.append(tuple(x)) - elif nargs < 0: - if spos is not None: - raise TypeError('Cannot have two nargs < 0') - spos = len(rv) - rv.append(None) - - # spos is the position of the wildcard (star). If it's not `None`, - # we fill it with the remainder. - if spos is not None: - rv[spos] = tuple(args) - args = [] - rv[spos + 1:] = reversed(rv[spos + 1:]) - - return tuple(rv), list(args) - - -def _error_opt_args(nargs, opt): - if nargs == 1: - raise BadOptionUsage(opt, '%s option requires an argument' % opt) - raise BadOptionUsage(opt, '%s option requires %d arguments' % (opt, nargs)) - - -def split_opt(opt): - first = opt[:1] - if first.isalnum(): - return '', opt - if opt[1:2] == first: - return opt[:2], opt[2:] - return first, opt[1:] - - -def normalize_opt(opt, ctx): - if ctx is None or ctx.token_normalize_func is None: - return opt - prefix, opt = split_opt(opt) - return prefix + ctx.token_normalize_func(opt) - - -def split_arg_string(string): - """Given an argument string this attempts to split it into small parts.""" - rv = [] - for match in re.finditer(r"('([^'\\]*(?:\\.[^'\\]*)*)'" - r'|"([^"\\]*(?:\\.[^"\\]*)*)"' - r'|\S+)\s*', string, re.S): - arg = match.group().strip() - if arg[:1] == arg[-1:] and arg[:1] in '"\'': - arg = arg[1:-1].encode('ascii', 'backslashreplace') \ - .decode('unicode-escape') - try: - arg = type(string)(arg) - except UnicodeError: - pass - rv.append(arg) - return rv - - -class Option(object): - - def __init__(self, opts, dest, action=None, nargs=1, const=None, obj=None): - self._short_opts = [] - self._long_opts = [] - self.prefixes = set() - - for opt in opts: - prefix, value = split_opt(opt) - if not prefix: - raise ValueError('Invalid start character for option (%s)' - % opt) - self.prefixes.add(prefix[0]) - if len(prefix) == 1 and len(value) == 1: - self._short_opts.append(opt) - else: - self._long_opts.append(opt) - self.prefixes.add(prefix) - - if action is None: - action = 'store' - - self.dest = dest - self.action = action - self.nargs = nargs - self.const = const - self.obj = obj - - @property - def takes_value(self): - return self.action in ('store', 'append') - - def process(self, value, state): - if self.action == 'store': - state.opts[self.dest] = value - elif self.action == 'store_const': - state.opts[self.dest] = self.const - elif self.action == 'append': - state.opts.setdefault(self.dest, []).append(value) - elif self.action == 'append_const': - state.opts.setdefault(self.dest, []).append(self.const) - elif self.action == 'count': - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 - else: - raise ValueError('unknown action %r' % self.action) - state.order.append(self.obj) - - -class Argument(object): - - def __init__(self, dest, nargs=1, obj=None): - self.dest = dest - self.nargs = nargs - self.obj = obj - - def process(self, value, state): - if self.nargs > 1: - holes = sum(1 for x in value if x is None) - if holes == len(value): - value = None - elif holes != 0: - raise BadArgumentUsage('argument %s takes %d values' - % (self.dest, self.nargs)) - state.opts[self.dest] = value - state.order.append(self.obj) - - -class ParsingState(object): - - def __init__(self, rargs): - self.opts = {} - self.largs = [] - self.rargs = rargs - self.order = [] - - -class OptionParser(object): - """The option parser is an internal class that is ultimately used to - parse options and arguments. It's modelled after optparse and brings - a similar but vastly simplified API. It should generally not be used - directly as the high level Click classes wrap it for you. - - It's not nearly as extensible as optparse or argparse as it does not - implement features that are implemented on a higher level (such as - types or defaults). - - :param ctx: optionally the :class:`~click.Context` where this parser - should go with. - """ - - def __init__(self, ctx=None): - #: The :class:`~click.Context` for this parser. This might be - #: `None` for some advanced use cases. - self.ctx = ctx - #: This controls how the parser deals with interspersed arguments. - #: If this is set to `False`, the parser will stop on the first - #: non-option. Click uses this to implement nested subcommands - #: safely. - self.allow_interspersed_args = True - #: This tells the parser how to deal with unknown options. By - #: default it will error out (which is sensible), but there is a - #: second mode where it will ignore it and continue processing - #: after shifting all the unknown options into the resulting args. - self.ignore_unknown_options = False - if ctx is not None: - self.allow_interspersed_args = ctx.allow_interspersed_args - self.ignore_unknown_options = ctx.ignore_unknown_options - self._short_opt = {} - self._long_opt = {} - self._opt_prefixes = set(['-', '--']) - self._args = [] - - def add_option(self, opts, dest, action=None, nargs=1, const=None, - obj=None): - """Adds a new option named `dest` to the parser. The destination - is not inferred (unlike with optparse) and needs to be explicitly - provided. Action can be any of ``store``, ``store_const``, - ``append``, ``appnd_const`` or ``count``. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - if obj is None: - obj = dest - opts = [normalize_opt(opt, self.ctx) for opt in opts] - option = Option(opts, dest, action=action, nargs=nargs, - const=const, obj=obj) - self._opt_prefixes.update(option.prefixes) - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - def add_argument(self, dest, nargs=1, obj=None): - """Adds a positional argument named `dest` to the parser. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - if obj is None: - obj = dest - self._args.append(Argument(dest=dest, nargs=nargs, obj=obj)) - - def parse_args(self, args): - """Parses positional arguments and returns ``(values, args, order)`` - for the parsed options and arguments as well as the leftover - arguments if there are any. The order is a list of objects as they - appear on the command line. If arguments appear multiple times they - will be memorized multiple times as well. - """ - state = ParsingState(args) - try: - self._process_args_for_options(state) - self._process_args_for_args(state) - except UsageError: - if self.ctx is None or not self.ctx.resilient_parsing: - raise - return state.opts, state.largs, state.order - - def _process_args_for_args(self, state): - pargs, args = _unpack_args(state.largs + state.rargs, - [x.nargs for x in self._args]) - - for idx, arg in enumerate(self._args): - arg.process(pargs[idx], state) - - state.largs = args - state.rargs = [] - - def _process_args_for_options(self, state): - while state.rargs: - arg = state.rargs.pop(0) - arglen = len(arg) - # Double dashes always handled explicitly regardless of what - # prefixes are valid. - if arg == '--': - return - elif arg[:1] in self._opt_prefixes and arglen > 1: - self._process_opts(arg, state) - elif self.allow_interspersed_args: - state.largs.append(arg) - else: - state.rargs.insert(0, arg) - return - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt(self, opt, explicit_value, state): - if opt not in self._long_opt: - possibilities = [word for word in self._long_opt - if word.startswith(opt)] - raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) - - option = self._long_opt[opt] - if option.takes_value: - # At this point it's safe to modify rargs by injecting the - # explicit value, because no exception is raised in this - # branch. This means that the inserted value will be fully - # consumed. - if explicit_value is not None: - state.rargs.insert(0, explicit_value) - - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - elif explicit_value is not None: - raise BadOptionUsage(opt, '%s option does not take a value' % opt) - - else: - value = None - - option.process(value, state) - - def _match_short_opt(self, arg, state): - stop = False - i = 1 - prefix = arg[0] - unknown_options = [] - - for ch in arg[1:]: - opt = normalize_opt(prefix + ch, self.ctx) - option = self._short_opt.get(opt) - i += 1 - - if not option: - if self.ignore_unknown_options: - unknown_options.append(ch) - continue - raise NoSuchOption(opt, ctx=self.ctx) - if option.takes_value: - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - state.rargs.insert(0, arg[i:]) - stop = True - - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - else: - value = None - - option.process(value, state) - - if stop: - break - - # If we got any unknown options we re-combinate the string of the - # remaining options and re-attach the prefix, then report that - # to the state as new larg. This way there is basic combinatorics - # that can be achieved while still ignoring unknown arguments. - if self.ignore_unknown_options and unknown_options: - state.largs.append(prefix + ''.join(unknown_options)) - - def _process_opts(self, arg, state): - explicit_value = None - # Long option handling happens in two parts. The first part is - # supporting explicitly attached values. In any case, we will try - # to long match the option first. - if '=' in arg: - long_opt, explicit_value = arg.split('=', 1) - else: - long_opt = arg - norm_long_opt = normalize_opt(long_opt, self.ctx) - - # At this point we will match the (assumed) long option through - # the long option matching code. Note that this allows options - # like "-foo" to be matched as long options. - try: - self._match_long_opt(norm_long_opt, explicit_value, state) - except NoSuchOption: - # At this point the long option matching failed, and we need - # to try with short options. However there is a special rule - # which says, that if we have a two character options prefix - # (applies to "--foo" for instance), we do not dispatch to the - # short option code and will instead raise the no option - # error. - if arg[:2] not in self._opt_prefixes: - return self._match_short_opt(arg, state) - if not self.ignore_unknown_options: - raise - state.largs.append(arg) diff --git a/py3.7/lib/python3.7/site-packages/click/termui.py b/py3.7/lib/python3.7/site-packages/click/termui.py deleted file mode 100644 index bf9a3aa..0000000 --- a/py3.7/lib/python3.7/site-packages/click/termui.py +++ /dev/null @@ -1,606 +0,0 @@ -import os -import sys -import struct -import inspect -import itertools - -from ._compat import raw_input, text_type, string_types, \ - isatty, strip_ansi, get_winterm_size, DEFAULT_COLUMNS, WIN -from .utils import echo -from .exceptions import Abort, UsageError -from .types import convert_type, Choice, Path -from .globals import resolve_color_default - - -# The prompt functions to use. The doc tools currently override these -# functions to customize how they work. -visible_prompt_func = raw_input - -_ansi_colors = { - 'black': 30, - 'red': 31, - 'green': 32, - 'yellow': 33, - 'blue': 34, - 'magenta': 35, - 'cyan': 36, - 'white': 37, - 'reset': 39, - 'bright_black': 90, - 'bright_red': 91, - 'bright_green': 92, - 'bright_yellow': 93, - 'bright_blue': 94, - 'bright_magenta': 95, - 'bright_cyan': 96, - 'bright_white': 97, -} -_ansi_reset_all = '\033[0m' - - -def hidden_prompt_func(prompt): - import getpass - return getpass.getpass(prompt) - - -def _build_prompt(text, suffix, show_default=False, default=None, show_choices=True, type=None): - prompt = text - if type is not None and show_choices and isinstance(type, Choice): - prompt += ' (' + ", ".join(map(str, type.choices)) + ')' - if default is not None and show_default: - prompt = '%s [%s]' % (prompt, default) - return prompt + suffix - - -def prompt(text, default=None, hide_input=False, confirmation_prompt=False, - type=None, value_proc=None, prompt_suffix=': ', show_default=True, - err=False, show_choices=True): - """Prompts a user for input. This is a convenience function that can - be used to prompt a user for input later. - - If the user aborts the input by sending a interrupt signal, this - function will catch it and raise a :exc:`Abort` exception. - - .. versionadded:: 7.0 - Added the show_choices parameter. - - .. versionadded:: 6.0 - Added unicode support for cmd.exe on Windows. - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param text: the text to show for the prompt. - :param default: the default value to use if no input happens. If this - is not given it will prompt until it's aborted. - :param hide_input: if this is set to true then the input value will - be hidden. - :param confirmation_prompt: asks for confirmation for the value. - :param type: the type to use to check the value against. - :param value_proc: if this parameter is provided it's a function that - is invoked instead of the type conversion to - convert a value. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - :param show_choices: Show or hide choices if the passed type is a Choice. - For example if type is a Choice of either day or week, - show_choices is true and text is "Group by" then the - prompt will be "Group by (day, week): ". - """ - result = None - - def prompt_func(text): - f = hide_input and hidden_prompt_func or visible_prompt_func - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(text, nl=False, err=err) - return f('') - except (KeyboardInterrupt, EOFError): - # getpass doesn't print a newline if the user aborts input with ^C. - # Allegedly this behavior is inherited from getpass(3). - # A doc bug has been filed at https://bugs.python.org/issue24711 - if hide_input: - echo(None, err=err) - raise Abort() - - if value_proc is None: - value_proc = convert_type(type, default) - - prompt = _build_prompt(text, prompt_suffix, show_default, default, show_choices, type) - - while 1: - while 1: - value = prompt_func(prompt) - if value: - break - elif default is not None: - if isinstance(value_proc, Path): - # validate Path default value(exists, dir_okay etc.) - value = default - break - return default - try: - result = value_proc(value) - except UsageError as e: - echo('Error: %s' % e.message, err=err) - continue - if not confirmation_prompt: - return result - while 1: - value2 = prompt_func('Repeat for confirmation: ') - if value2: - break - if value == value2: - return result - echo('Error: the two entered values do not match', err=err) - - -def confirm(text, default=False, abort=False, prompt_suffix=': ', - show_default=True, err=False): - """Prompts for confirmation (yes/no question). - - If the user aborts the input by sending a interrupt signal this - function will catch it and raise a :exc:`Abort` exception. - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param text: the question to ask. - :param default: the default for the prompt. - :param abort: if this is set to `True` a negative answer aborts the - exception by raising :exc:`Abort`. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - prompt = _build_prompt(text, prompt_suffix, show_default, - default and 'Y/n' or 'y/N') - while 1: - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(prompt, nl=False, err=err) - value = visible_prompt_func('').lower().strip() - except (KeyboardInterrupt, EOFError): - raise Abort() - if value in ('y', 'yes'): - rv = True - elif value in ('n', 'no'): - rv = False - elif value == '': - rv = default - else: - echo('Error: invalid input', err=err) - continue - break - if abort and not rv: - raise Abort() - return rv - - -def get_terminal_size(): - """Returns the current size of the terminal as tuple in the form - ``(width, height)`` in columns and rows. - """ - # If shutil has get_terminal_size() (Python 3.3 and later) use that - if sys.version_info >= (3, 3): - import shutil - shutil_get_terminal_size = getattr(shutil, 'get_terminal_size', None) - if shutil_get_terminal_size: - sz = shutil_get_terminal_size() - return sz.columns, sz.lines - - # We provide a sensible default for get_winterm_size() when being invoked - # inside a subprocess. Without this, it would not provide a useful input. - if get_winterm_size is not None: - size = get_winterm_size() - if size == (0, 0): - return (79, 24) - else: - return size - - def ioctl_gwinsz(fd): - try: - import fcntl - import termios - cr = struct.unpack( - 'hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234')) - except Exception: - return - return cr - - cr = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - try: - cr = ioctl_gwinsz(fd) - finally: - os.close(fd) - except Exception: - pass - if not cr or not cr[0] or not cr[1]: - cr = (os.environ.get('LINES', 25), - os.environ.get('COLUMNS', DEFAULT_COLUMNS)) - return int(cr[1]), int(cr[0]) - - -def echo_via_pager(text_or_generator, color=None): - """This function takes a text and shows it via an environment specific - pager on stdout. - - .. versionchanged:: 3.0 - Added the `color` flag. - - :param text_or_generator: the text to page, or alternatively, a - generator emitting the text to page. - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - color = resolve_color_default(color) - - if inspect.isgeneratorfunction(text_or_generator): - i = text_or_generator() - elif isinstance(text_or_generator, string_types): - i = [text_or_generator] - else: - i = iter(text_or_generator) - - # convert every element of i to a text type if necessary - text_generator = (el if isinstance(el, string_types) else text_type(el) - for el in i) - - from ._termui_impl import pager - return pager(itertools.chain(text_generator, "\n"), color) - - -def progressbar(iterable=None, length=None, label=None, show_eta=True, - show_percent=None, show_pos=False, - item_show_func=None, fill_char='#', empty_char='-', - bar_template='%(label)s [%(bar)s] %(info)s', - info_sep=' ', width=36, file=None, color=None): - """This function creates an iterable context manager that can be used - to iterate over something while showing a progress bar. It will - either iterate over the `iterable` or `length` items (that are counted - up). While iteration happens, this function will print a rendered - progress bar to the given `file` (defaults to stdout) and will attempt - to calculate remaining time and more. By default, this progress bar - will not be rendered if the file is not a terminal. - - The context manager creates the progress bar. When the context - manager is entered the progress bar is already displayed. With every - iteration over the progress bar, the iterable passed to the bar is - advanced and the bar is updated. When the context manager exits, - a newline is printed and the progress bar is finalized on screen. - - No printing must happen or the progress bar will be unintentionally - destroyed. - - Example usage:: - - with progressbar(items) as bar: - for item in bar: - do_something_with(item) - - Alternatively, if no iterable is specified, one can manually update the - progress bar through the `update()` method instead of directly - iterating over the progress bar. The update method accepts the number - of steps to increment the bar with:: - - with progressbar(length=chunks.total_bytes) as bar: - for chunk in chunks: - process_chunk(chunk) - bar.update(chunks.bytes) - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `color` parameter. Added a `update` method to the - progressbar object. - - :param iterable: an iterable to iterate over. If not provided the length - is required. - :param length: the number of items to iterate over. By default the - progressbar will attempt to ask the iterator about its - length, which might or might not work. If an iterable is - also provided this parameter can be used to override the - length. If an iterable is not provided the progress bar - will iterate over a range of that length. - :param label: the label to show next to the progress bar. - :param show_eta: enables or disables the estimated time display. This is - automatically disabled if the length cannot be - determined. - :param show_percent: enables or disables the percentage display. The - default is `True` if the iterable has a length or - `False` if not. - :param show_pos: enables or disables the absolute position display. The - default is `False`. - :param item_show_func: a function called with the current item which - can return a string to show the current item - next to the progress bar. Note that the current - item can be `None`! - :param fill_char: the character to use to show the filled part of the - progress bar. - :param empty_char: the character to use to show the non-filled part of - the progress bar. - :param bar_template: the format string to use as template for the bar. - The parameters in it are ``label`` for the label, - ``bar`` for the progress bar and ``info`` for the - info section. - :param info_sep: the separator between multiple info items (eta etc.) - :param width: the width of the progress bar in characters, 0 means full - terminal width - :param file: the file to write to. If this is not a terminal then - only the label is printed. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are included anywhere in the progress bar output - which is not the case by default. - """ - from ._termui_impl import ProgressBar - color = resolve_color_default(color) - return ProgressBar(iterable=iterable, length=length, show_eta=show_eta, - show_percent=show_percent, show_pos=show_pos, - item_show_func=item_show_func, fill_char=fill_char, - empty_char=empty_char, bar_template=bar_template, - info_sep=info_sep, file=file, label=label, - width=width, color=color) - - -def clear(): - """Clears the terminal screen. This will have the effect of clearing - the whole visible space of the terminal and moving the cursor to the - top left. This does not do anything if not connected to a terminal. - - .. versionadded:: 2.0 - """ - if not isatty(sys.stdout): - return - # If we're on Windows and we don't have colorama available, then we - # clear the screen by shelling out. Otherwise we can use an escape - # sequence. - if WIN: - os.system('cls') - else: - sys.stdout.write('\033[2J\033[1;1H') - - -def style(text, fg=None, bg=None, bold=None, dim=None, underline=None, - blink=None, reverse=None, reset=True): - """Styles a text with ANSI styles and returns the new string. By - default the styling is self contained which means that at the end - of the string a reset code is issued. This can be prevented by - passing ``reset=False``. - - Examples:: - - click.echo(click.style('Hello World!', fg='green')) - click.echo(click.style('ATTENTION!', blink=True)) - click.echo(click.style('Some things', reverse=True, fg='cyan')) - - Supported color names: - - * ``black`` (might be a gray) - * ``red`` - * ``green`` - * ``yellow`` (might be an orange) - * ``blue`` - * ``magenta`` - * ``cyan`` - * ``white`` (might be light gray) - * ``bright_black`` - * ``bright_red`` - * ``bright_green`` - * ``bright_yellow`` - * ``bright_blue`` - * ``bright_magenta`` - * ``bright_cyan`` - * ``bright_white`` - * ``reset`` (reset the color code only) - - .. versionadded:: 2.0 - - .. versionadded:: 7.0 - Added support for bright colors. - - :param text: the string to style with ansi codes. - :param fg: if provided this will become the foreground color. - :param bg: if provided this will become the background color. - :param bold: if provided this will enable or disable bold mode. - :param dim: if provided this will enable or disable dim mode. This is - badly supported. - :param underline: if provided this will enable or disable underline. - :param blink: if provided this will enable or disable blinking. - :param reverse: if provided this will enable or disable inverse - rendering (foreground becomes background and the - other way round). - :param reset: by default a reset-all code is added at the end of the - string which means that styles do not carry over. This - can be disabled to compose styles. - """ - bits = [] - if fg: - try: - bits.append('\033[%dm' % (_ansi_colors[fg])) - except KeyError: - raise TypeError('Unknown color %r' % fg) - if bg: - try: - bits.append('\033[%dm' % (_ansi_colors[bg] + 10)) - except KeyError: - raise TypeError('Unknown color %r' % bg) - if bold is not None: - bits.append('\033[%dm' % (1 if bold else 22)) - if dim is not None: - bits.append('\033[%dm' % (2 if dim else 22)) - if underline is not None: - bits.append('\033[%dm' % (4 if underline else 24)) - if blink is not None: - bits.append('\033[%dm' % (5 if blink else 25)) - if reverse is not None: - bits.append('\033[%dm' % (7 if reverse else 27)) - bits.append(text) - if reset: - bits.append(_ansi_reset_all) - return ''.join(bits) - - -def unstyle(text): - """Removes ANSI styling information from a string. Usually it's not - necessary to use this function as Click's echo function will - automatically remove styling if necessary. - - .. versionadded:: 2.0 - - :param text: the text to remove style information from. - """ - return strip_ansi(text) - - -def secho(message=None, file=None, nl=True, err=False, color=None, **styles): - """This function combines :func:`echo` and :func:`style` into one - call. As such the following two calls are the same:: - - click.secho('Hello World!', fg='green') - click.echo(click.style('Hello World!', fg='green')) - - All keyword arguments are forwarded to the underlying functions - depending on which one they go with. - - .. versionadded:: 2.0 - """ - if message is not None: - message = style(message, **styles) - return echo(message, file=file, nl=nl, err=err, color=color) - - -def edit(text=None, editor=None, env=None, require_save=True, - extension='.txt', filename=None): - r"""Edits the given text in the defined editor. If an editor is given - (should be the full path to the executable but the regular operating - system search path is used for finding the executable) it overrides - the detected editor. Optionally, some environment variables can be - used. If the editor is closed without changes, `None` is returned. In - case a file is edited directly the return value is always `None` and - `require_save` and `extension` are ignored. - - If the editor cannot be opened a :exc:`UsageError` is raised. - - Note for Windows: to simplify cross-platform usage, the newlines are - automatically converted from POSIX to Windows and vice versa. As such, - the message here will have ``\n`` as newline markers. - - :param text: the text to edit. - :param editor: optionally the editor to use. Defaults to automatic - detection. - :param env: environment variables to forward to the editor. - :param require_save: if this is true, then not saving in the editor - will make the return value become `None`. - :param extension: the extension to tell the editor about. This defaults - to `.txt` but changing this might change syntax - highlighting. - :param filename: if provided it will edit this file instead of the - provided text contents. It will not use a temporary - file as an indirection in that case. - """ - from ._termui_impl import Editor - editor = Editor(editor=editor, env=env, require_save=require_save, - extension=extension) - if filename is None: - return editor.edit(text) - editor.edit_file(filename) - - -def launch(url, wait=False, locate=False): - """This function launches the given URL (or filename) in the default - viewer application for this file type. If this is an executable, it - might launch the executable in a new session. The return value is - the exit code of the launched application. Usually, ``0`` indicates - success. - - Examples:: - - click.launch('https://click.palletsprojects.com/') - click.launch('/my/downloaded/file', locate=True) - - .. versionadded:: 2.0 - - :param url: URL or filename of the thing to launch. - :param wait: waits for the program to stop. - :param locate: if this is set to `True` then instead of launching the - application associated with the URL it will attempt to - launch a file manager with the file located. This - might have weird effects if the URL does not point to - the filesystem. - """ - from ._termui_impl import open_url - return open_url(url, wait=wait, locate=locate) - - -# If this is provided, getchar() calls into this instead. This is used -# for unittesting purposes. -_getchar = None - - -def getchar(echo=False): - """Fetches a single character from the terminal and returns it. This - will always return a unicode character and under certain rare - circumstances this might return more than one character. The - situations which more than one character is returned is when for - whatever reason multiple characters end up in the terminal buffer or - standard input was not actually a terminal. - - Note that this will always read from the terminal, even if something - is piped into the standard input. - - Note for Windows: in rare cases when typing non-ASCII characters, this - function might wait for a second character and then return both at once. - This is because certain Unicode characters look like special-key markers. - - .. versionadded:: 2.0 - - :param echo: if set to `True`, the character read will also show up on - the terminal. The default is to not show it. - """ - f = _getchar - if f is None: - from ._termui_impl import getchar as f - return f(echo) - - -def raw_terminal(): - from ._termui_impl import raw_terminal as f - return f() - - -def pause(info='Press any key to continue ...', err=False): - """This command stops execution and waits for the user to press any - key to continue. This is similar to the Windows batch "pause" - command. If the program is not run through a terminal, this command - will instead do nothing. - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param info: the info string to print before pausing. - :param err: if set to message goes to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - if not isatty(sys.stdin) or not isatty(sys.stdout): - return - try: - if info: - echo(info, nl=False, err=err) - try: - getchar() - except (KeyboardInterrupt, EOFError): - pass - finally: - if info: - echo(err=err) diff --git a/py3.7/lib/python3.7/site-packages/click/testing.py b/py3.7/lib/python3.7/site-packages/click/testing.py deleted file mode 100644 index 1b2924e..0000000 --- a/py3.7/lib/python3.7/site-packages/click/testing.py +++ /dev/null @@ -1,374 +0,0 @@ -import os -import sys -import shutil -import tempfile -import contextlib -import shlex - -from ._compat import iteritems, PY2, string_types - - -# If someone wants to vendor click, we want to ensure the -# correct package is discovered. Ideally we could use a -# relative import here but unfortunately Python does not -# support that. -clickpkg = sys.modules[__name__.rsplit('.', 1)[0]] - - -if PY2: - from cStringIO import StringIO -else: - import io - from ._compat import _find_binary_reader - - -class EchoingStdin(object): - - def __init__(self, input, output): - self._input = input - self._output = output - - def __getattr__(self, x): - return getattr(self._input, x) - - def _echo(self, rv): - self._output.write(rv) - return rv - - def read(self, n=-1): - return self._echo(self._input.read(n)) - - def readline(self, n=-1): - return self._echo(self._input.readline(n)) - - def readlines(self): - return [self._echo(x) for x in self._input.readlines()] - - def __iter__(self): - return iter(self._echo(x) for x in self._input) - - def __repr__(self): - return repr(self._input) - - -def make_input_stream(input, charset): - # Is already an input stream. - if hasattr(input, 'read'): - if PY2: - return input - rv = _find_binary_reader(input) - if rv is not None: - return rv - raise TypeError('Could not find binary reader for input stream.') - - if input is None: - input = b'' - elif not isinstance(input, bytes): - input = input.encode(charset) - if PY2: - return StringIO(input) - return io.BytesIO(input) - - -class Result(object): - """Holds the captured result of an invoked CLI script.""" - - def __init__(self, runner, stdout_bytes, stderr_bytes, exit_code, - exception, exc_info=None): - #: The runner that created the result - self.runner = runner - #: The standard output as bytes. - self.stdout_bytes = stdout_bytes - #: The standard error as bytes, or False(y) if not available - self.stderr_bytes = stderr_bytes - #: The exit code as integer. - self.exit_code = exit_code - #: The exception that happened if one did. - self.exception = exception - #: The traceback - self.exc_info = exc_info - - @property - def output(self): - """The (standard) output as unicode string.""" - return self.stdout - - @property - def stdout(self): - """The standard output as unicode string.""" - return self.stdout_bytes.decode(self.runner.charset, 'replace') \ - .replace('\r\n', '\n') - - @property - def stderr(self): - """The standard error as unicode string.""" - if not self.stderr_bytes: - raise ValueError("stderr not separately captured") - return self.stderr_bytes.decode(self.runner.charset, 'replace') \ - .replace('\r\n', '\n') - - - def __repr__(self): - return '<%s %s>' % ( - type(self).__name__, - self.exception and repr(self.exception) or 'okay', - ) - - -class CliRunner(object): - """The CLI runner provides functionality to invoke a Click command line - script for unittesting purposes in a isolated environment. This only - works in single-threaded systems without any concurrency as it changes the - global interpreter state. - - :param charset: the character set for the input and output data. This is - UTF-8 by default and should not be changed currently as - the reporting to Click only works in Python 2 properly. - :param env: a dictionary with environment variables for overriding. - :param echo_stdin: if this is set to `True`, then reading from stdin writes - to stdout. This is useful for showing examples in - some circumstances. Note that regular prompts - will automatically echo the input. - :param mix_stderr: if this is set to `False`, then stdout and stderr are - preserved as independent streams. This is useful for - Unix-philosophy apps that have predictable stdout and - noisy stderr, such that each may be measured - independently - """ - - def __init__(self, charset=None, env=None, echo_stdin=False, - mix_stderr=True): - if charset is None: - charset = 'utf-8' - self.charset = charset - self.env = env or {} - self.echo_stdin = echo_stdin - self.mix_stderr = mix_stderr - - def get_default_prog_name(self, cli): - """Given a command object it will return the default program name - for it. The default is the `name` attribute or ``"root"`` if not - set. - """ - return cli.name or 'root' - - def make_env(self, overrides=None): - """Returns the environment overrides for invoking a script.""" - rv = dict(self.env) - if overrides: - rv.update(overrides) - return rv - - @contextlib.contextmanager - def isolation(self, input=None, env=None, color=False): - """A context manager that sets up the isolation for invoking of a - command line tool. This sets up stdin with the given input data - and `os.environ` with the overrides from the given dictionary. - This also rebinds some internals in Click to be mocked (like the - prompt functionality). - - This is automatically done in the :meth:`invoke` method. - - .. versionadded:: 4.0 - The ``color`` parameter was added. - - :param input: the input stream to put into sys.stdin. - :param env: the environment overrides as dictionary. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - """ - input = make_input_stream(input, self.charset) - - old_stdin = sys.stdin - old_stdout = sys.stdout - old_stderr = sys.stderr - old_forced_width = clickpkg.formatting.FORCED_WIDTH - clickpkg.formatting.FORCED_WIDTH = 80 - - env = self.make_env(env) - - if PY2: - bytes_output = StringIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - sys.stdout = bytes_output - if not self.mix_stderr: - bytes_error = StringIO() - sys.stderr = bytes_error - else: - bytes_output = io.BytesIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - input = io.TextIOWrapper(input, encoding=self.charset) - sys.stdout = io.TextIOWrapper( - bytes_output, encoding=self.charset) - if not self.mix_stderr: - bytes_error = io.BytesIO() - sys.stderr = io.TextIOWrapper( - bytes_error, encoding=self.charset) - - if self.mix_stderr: - sys.stderr = sys.stdout - - sys.stdin = input - - def visible_input(prompt=None): - sys.stdout.write(prompt or '') - val = input.readline().rstrip('\r\n') - sys.stdout.write(val + '\n') - sys.stdout.flush() - return val - - def hidden_input(prompt=None): - sys.stdout.write((prompt or '') + '\n') - sys.stdout.flush() - return input.readline().rstrip('\r\n') - - def _getchar(echo): - char = sys.stdin.read(1) - if echo: - sys.stdout.write(char) - sys.stdout.flush() - return char - - default_color = color - - def should_strip_ansi(stream=None, color=None): - if color is None: - return not default_color - return not color - - old_visible_prompt_func = clickpkg.termui.visible_prompt_func - old_hidden_prompt_func = clickpkg.termui.hidden_prompt_func - old__getchar_func = clickpkg.termui._getchar - old_should_strip_ansi = clickpkg.utils.should_strip_ansi - clickpkg.termui.visible_prompt_func = visible_input - clickpkg.termui.hidden_prompt_func = hidden_input - clickpkg.termui._getchar = _getchar - clickpkg.utils.should_strip_ansi = should_strip_ansi - - old_env = {} - try: - for key, value in iteritems(env): - old_env[key] = os.environ.get(key) - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - yield (bytes_output, not self.mix_stderr and bytes_error) - finally: - for key, value in iteritems(old_env): - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - sys.stdout = old_stdout - sys.stderr = old_stderr - sys.stdin = old_stdin - clickpkg.termui.visible_prompt_func = old_visible_prompt_func - clickpkg.termui.hidden_prompt_func = old_hidden_prompt_func - clickpkg.termui._getchar = old__getchar_func - clickpkg.utils.should_strip_ansi = old_should_strip_ansi - clickpkg.formatting.FORCED_WIDTH = old_forced_width - - def invoke(self, cli, args=None, input=None, env=None, - catch_exceptions=True, color=False, mix_stderr=False, **extra): - """Invokes a command in an isolated environment. The arguments are - forwarded directly to the command line script, the `extra` keyword - arguments are passed to the :meth:`~clickpkg.Command.main` function of - the command. - - This returns a :class:`Result` object. - - .. versionadded:: 3.0 - The ``catch_exceptions`` parameter was added. - - .. versionchanged:: 3.0 - The result object now has an `exc_info` attribute with the - traceback if available. - - .. versionadded:: 4.0 - The ``color`` parameter was added. - - :param cli: the command to invoke - :param args: the arguments to invoke. It may be given as an iterable - or a string. When given as string it will be interpreted - as a Unix shell command. More details at - :func:`shlex.split`. - :param input: the input data for `sys.stdin`. - :param env: the environment overrides. - :param catch_exceptions: Whether to catch any other exceptions than - ``SystemExit``. - :param extra: the keyword arguments to pass to :meth:`main`. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - """ - exc_info = None - with self.isolation(input=input, env=env, color=color) as outstreams: - exception = None - exit_code = 0 - - if isinstance(args, string_types): - args = shlex.split(args) - - try: - prog_name = extra.pop("prog_name") - except KeyError: - prog_name = self.get_default_prog_name(cli) - - try: - cli.main(args=args or (), prog_name=prog_name, **extra) - except SystemExit as e: - exc_info = sys.exc_info() - exit_code = e.code - if exit_code is None: - exit_code = 0 - - if exit_code != 0: - exception = e - - if not isinstance(exit_code, int): - sys.stdout.write(str(exit_code)) - sys.stdout.write('\n') - exit_code = 1 - - except Exception as e: - if not catch_exceptions: - raise - exception = e - exit_code = 1 - exc_info = sys.exc_info() - finally: - sys.stdout.flush() - stdout = outstreams[0].getvalue() - stderr = outstreams[1] and outstreams[1].getvalue() - - return Result(runner=self, - stdout_bytes=stdout, - stderr_bytes=stderr, - exit_code=exit_code, - exception=exception, - exc_info=exc_info) - - @contextlib.contextmanager - def isolated_filesystem(self): - """A context manager that creates a temporary folder and changes - the current working directory to it for isolated filesystem tests. - """ - cwd = os.getcwd() - t = tempfile.mkdtemp() - os.chdir(t) - try: - yield t - finally: - os.chdir(cwd) - try: - shutil.rmtree(t) - except (OSError, IOError): - pass diff --git a/py3.7/lib/python3.7/site-packages/click/types.py b/py3.7/lib/python3.7/site-packages/click/types.py deleted file mode 100644 index 1f88032..0000000 --- a/py3.7/lib/python3.7/site-packages/click/types.py +++ /dev/null @@ -1,668 +0,0 @@ -import os -import stat -from datetime import datetime - -from ._compat import open_stream, text_type, filename_to_ui, \ - get_filesystem_encoding, get_streerror, _get_argv_encoding, PY2 -from .exceptions import BadParameter -from .utils import safecall, LazyFile - - -class ParamType(object): - """Helper for converting values through types. The following is - necessary for a valid type: - - * it needs a name - * it needs to pass through None unchanged - * it needs to convert from a string - * it needs to convert its result type through unchanged - (eg: needs to be idempotent) - * it needs to be able to deal with param and context being `None`. - This can be the case when the object is used with prompt - inputs. - """ - is_composite = False - - #: the descriptive name of this type - name = None - - #: if a list of this type is expected and the value is pulled from a - #: string environment variable, this is what splits it up. `None` - #: means any whitespace. For all parameters the general rule is that - #: whitespace splits them up. The exception are paths and files which - #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on - #: Windows). - envvar_list_splitter = None - - def __call__(self, value, param=None, ctx=None): - if value is not None: - return self.convert(value, param, ctx) - - def get_metavar(self, param): - """Returns the metavar default for this param if it provides one.""" - - def get_missing_message(self, param): - """Optionally might return extra information about a missing - parameter. - - .. versionadded:: 2.0 - """ - - def convert(self, value, param, ctx): - """Converts the value. This is not invoked for values that are - `None` (the missing value). - """ - return value - - def split_envvar_value(self, rv): - """Given a value from an environment variable this splits it up - into small chunks depending on the defined envvar list splitter. - - If the splitter is set to `None`, which means that whitespace splits, - then leading and trailing whitespace is ignored. Otherwise, leading - and trailing splitters usually lead to empty items being included. - """ - return (rv or '').split(self.envvar_list_splitter) - - def fail(self, message, param=None, ctx=None): - """Helper method to fail with an invalid value message.""" - raise BadParameter(message, ctx=ctx, param=param) - - -class CompositeParamType(ParamType): - is_composite = True - - @property - def arity(self): - raise NotImplementedError() - - -class FuncParamType(ParamType): - - def __init__(self, func): - self.name = func.__name__ - self.func = func - - def convert(self, value, param, ctx): - try: - return self.func(value) - except ValueError: - try: - value = text_type(value) - except UnicodeError: - value = str(value).decode('utf-8', 'replace') - self.fail(value, param, ctx) - - -class UnprocessedParamType(ParamType): - name = 'text' - - def convert(self, value, param, ctx): - return value - - def __repr__(self): - return 'UNPROCESSED' - - -class StringParamType(ParamType): - name = 'text' - - def convert(self, value, param, ctx): - if isinstance(value, bytes): - enc = _get_argv_encoding() - try: - value = value.decode(enc) - except UnicodeError: - fs_enc = get_filesystem_encoding() - if fs_enc != enc: - try: - value = value.decode(fs_enc) - except UnicodeError: - value = value.decode('utf-8', 'replace') - return value - return value - - def __repr__(self): - return 'STRING' - - -class Choice(ParamType): - """The choice type allows a value to be checked against a fixed set - of supported values. All of these values have to be strings. - - You should only pass a list or tuple of choices. Other iterables - (like generators) may lead to surprising results. - - See :ref:`choice-opts` for an example. - - :param case_sensitive: Set to false to make choices case - insensitive. Defaults to true. - """ - - name = 'choice' - - def __init__(self, choices, case_sensitive=True): - self.choices = choices - self.case_sensitive = case_sensitive - - def get_metavar(self, param): - return '[%s]' % '|'.join(self.choices) - - def get_missing_message(self, param): - return 'Choose from:\n\t%s.' % ',\n\t'.join(self.choices) - - def convert(self, value, param, ctx): - # Exact match - if value in self.choices: - return value - - # Match through normalization and case sensitivity - # first do token_normalize_func, then lowercase - # preserve original `value` to produce an accurate message in - # `self.fail` - normed_value = value - normed_choices = self.choices - - if ctx is not None and \ - ctx.token_normalize_func is not None: - normed_value = ctx.token_normalize_func(value) - normed_choices = [ctx.token_normalize_func(choice) for choice in - self.choices] - - if not self.case_sensitive: - normed_value = normed_value.lower() - normed_choices = [choice.lower() for choice in normed_choices] - - if normed_value in normed_choices: - return normed_value - - self.fail('invalid choice: %s. (choose from %s)' % - (value, ', '.join(self.choices)), param, ctx) - - def __repr__(self): - return 'Choice(%r)' % list(self.choices) - - -class DateTime(ParamType): - """The DateTime type converts date strings into `datetime` objects. - - The format strings which are checked are configurable, but default to some - common (non-timezone aware) ISO 8601 formats. - - When specifying *DateTime* formats, you should only pass a list or a tuple. - Other iterables, like generators, may lead to surprising results. - - The format strings are processed using ``datetime.strptime``, and this - consequently defines the format strings which are allowed. - - Parsing is tried using each format, in order, and the first format which - parses successfully is used. - - :param formats: A list or tuple of date format strings, in the order in - which they should be tried. Defaults to - ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, - ``'%Y-%m-%d %H:%M:%S'``. - """ - name = 'datetime' - - def __init__(self, formats=None): - self.formats = formats or [ - '%Y-%m-%d', - '%Y-%m-%dT%H:%M:%S', - '%Y-%m-%d %H:%M:%S' - ] - - def get_metavar(self, param): - return '[{}]'.format('|'.join(self.formats)) - - def _try_to_convert_date(self, value, format): - try: - return datetime.strptime(value, format) - except ValueError: - return None - - def convert(self, value, param, ctx): - # Exact match - for format in self.formats: - dtime = self._try_to_convert_date(value, format) - if dtime: - return dtime - - self.fail( - 'invalid datetime format: {}. (choose from {})'.format( - value, ', '.join(self.formats))) - - def __repr__(self): - return 'DateTime' - - -class IntParamType(ParamType): - name = 'integer' - - def convert(self, value, param, ctx): - try: - return int(value) - except (ValueError, UnicodeError): - self.fail('%s is not a valid integer' % value, param, ctx) - - def __repr__(self): - return 'INT' - - -class IntRange(IntParamType): - """A parameter that works similar to :data:`click.INT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. - - See :ref:`ranges` for an example. - """ - name = 'integer range' - - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp - - def convert(self, value, param, ctx): - rv = IntParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if self.min is not None and rv < self.min or \ - self.max is not None and rv > self.max: - if self.min is None: - self.fail('%s is bigger than the maximum valid value ' - '%s.' % (rv, self.max), param, ctx) - elif self.max is None: - self.fail('%s is smaller than the minimum valid value ' - '%s.' % (rv, self.min), param, ctx) - else: - self.fail('%s is not in the valid range of %s to %s.' - % (rv, self.min, self.max), param, ctx) - return rv - - def __repr__(self): - return 'IntRange(%r, %r)' % (self.min, self.max) - - -class FloatParamType(ParamType): - name = 'float' - - def convert(self, value, param, ctx): - try: - return float(value) - except (UnicodeError, ValueError): - self.fail('%s is not a valid floating point value' % - value, param, ctx) - - def __repr__(self): - return 'FLOAT' - - -class FloatRange(FloatParamType): - """A parameter that works similar to :data:`click.FLOAT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. - - See :ref:`ranges` for an example. - """ - name = 'float range' - - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp - - def convert(self, value, param, ctx): - rv = FloatParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if self.min is not None and rv < self.min or \ - self.max is not None and rv > self.max: - if self.min is None: - self.fail('%s is bigger than the maximum valid value ' - '%s.' % (rv, self.max), param, ctx) - elif self.max is None: - self.fail('%s is smaller than the minimum valid value ' - '%s.' % (rv, self.min), param, ctx) - else: - self.fail('%s is not in the valid range of %s to %s.' - % (rv, self.min, self.max), param, ctx) - return rv - - def __repr__(self): - return 'FloatRange(%r, %r)' % (self.min, self.max) - - -class BoolParamType(ParamType): - name = 'boolean' - - def convert(self, value, param, ctx): - if isinstance(value, bool): - return bool(value) - value = value.lower() - if value in ('true', 't', '1', 'yes', 'y'): - return True - elif value in ('false', 'f', '0', 'no', 'n'): - return False - self.fail('%s is not a valid boolean' % value, param, ctx) - - def __repr__(self): - return 'BOOL' - - -class UUIDParameterType(ParamType): - name = 'uuid' - - def convert(self, value, param, ctx): - import uuid - try: - if PY2 and isinstance(value, text_type): - value = value.encode('ascii') - return uuid.UUID(value) - except (UnicodeError, ValueError): - self.fail('%s is not a valid UUID value' % value, param, ctx) - - def __repr__(self): - return 'UUID' - - -class File(ParamType): - """Declares a parameter to be a file for reading or writing. The file - is automatically closed once the context tears down (after the command - finished working). - - Files can be opened for reading or writing. The special value ``-`` - indicates stdin or stdout depending on the mode. - - By default, the file is opened for reading text data, but it can also be - opened in binary mode or for writing. The encoding parameter can be used - to force a specific encoding. - - The `lazy` flag controls if the file should be opened immediately or upon - first IO. The default is to be non-lazy for standard input and output - streams as well as files opened for reading, `lazy` otherwise. When opening a - file lazily for reading, it is still opened temporarily for validation, but - will not be held open until first IO. lazy is mainly useful when opening - for writing to avoid creating the file until it is needed. - - Starting with Click 2.0, files can also be opened atomically in which - case all writes go into a separate file in the same folder and upon - completion the file will be moved over to the original location. This - is useful if a file regularly read by other users is modified. - - See :ref:`file-args` for more information. - """ - name = 'filename' - envvar_list_splitter = os.path.pathsep - - def __init__(self, mode='r', encoding=None, errors='strict', lazy=None, - atomic=False): - self.mode = mode - self.encoding = encoding - self.errors = errors - self.lazy = lazy - self.atomic = atomic - - def resolve_lazy_flag(self, value): - if self.lazy is not None: - return self.lazy - if value == '-': - return False - elif 'w' in self.mode: - return True - return False - - def convert(self, value, param, ctx): - try: - if hasattr(value, 'read') or hasattr(value, 'write'): - return value - - lazy = self.resolve_lazy_flag(value) - - if lazy: - f = LazyFile(value, self.mode, self.encoding, self.errors, - atomic=self.atomic) - if ctx is not None: - ctx.call_on_close(f.close_intelligently) - return f - - f, should_close = open_stream(value, self.mode, - self.encoding, self.errors, - atomic=self.atomic) - # If a context is provided, we automatically close the file - # at the end of the context execution (or flush out). If a - # context does not exist, it's the caller's responsibility to - # properly close the file. This for instance happens when the - # type is used with prompts. - if ctx is not None: - if should_close: - ctx.call_on_close(safecall(f.close)) - else: - ctx.call_on_close(safecall(f.flush)) - return f - except (IOError, OSError) as e: - self.fail('Could not open file: %s: %s' % ( - filename_to_ui(value), - get_streerror(e), - ), param, ctx) - - -class Path(ParamType): - """The path type is similar to the :class:`File` type but it performs - different checks. First of all, instead of returning an open file - handle it returns just the filename. Secondly, it can perform various - basic checks about what the file or directory should be. - - .. versionchanged:: 6.0 - `allow_dash` was added. - - :param exists: if set to true, the file or directory needs to exist for - this value to be valid. If this is not required and a - file does indeed not exist, then all further checks are - silently skipped. - :param file_okay: controls if a file is a possible value. - :param dir_okay: controls if a directory is a possible value. - :param writable: if true, a writable check is performed. - :param readable: if true, a readable check is performed. - :param resolve_path: if this is true, then the path is fully resolved - before the value is passed onwards. This means - that it's absolute and symlinks are resolved. It - will not expand a tilde-prefix, as this is - supposed to be done by the shell only. - :param allow_dash: If this is set to `True`, a single dash to indicate - standard streams is permitted. - :param path_type: optionally a string type that should be used to - represent the path. The default is `None` which - means the return value will be either bytes or - unicode depending on what makes most sense given the - input data Click deals with. - """ - envvar_list_splitter = os.path.pathsep - - def __init__(self, exists=False, file_okay=True, dir_okay=True, - writable=False, readable=True, resolve_path=False, - allow_dash=False, path_type=None): - self.exists = exists - self.file_okay = file_okay - self.dir_okay = dir_okay - self.writable = writable - self.readable = readable - self.resolve_path = resolve_path - self.allow_dash = allow_dash - self.type = path_type - - if self.file_okay and not self.dir_okay: - self.name = 'file' - self.path_type = 'File' - elif self.dir_okay and not self.file_okay: - self.name = 'directory' - self.path_type = 'Directory' - else: - self.name = 'path' - self.path_type = 'Path' - - def coerce_path_result(self, rv): - if self.type is not None and not isinstance(rv, self.type): - if self.type is text_type: - rv = rv.decode(get_filesystem_encoding()) - else: - rv = rv.encode(get_filesystem_encoding()) - return rv - - def convert(self, value, param, ctx): - rv = value - - is_dash = self.file_okay and self.allow_dash and rv in (b'-', '-') - - if not is_dash: - if self.resolve_path: - rv = os.path.realpath(rv) - - try: - st = os.stat(rv) - except OSError: - if not self.exists: - return self.coerce_path_result(rv) - self.fail('%s "%s" does not exist.' % ( - self.path_type, - filename_to_ui(value) - ), param, ctx) - - if not self.file_okay and stat.S_ISREG(st.st_mode): - self.fail('%s "%s" is a file.' % ( - self.path_type, - filename_to_ui(value) - ), param, ctx) - if not self.dir_okay and stat.S_ISDIR(st.st_mode): - self.fail('%s "%s" is a directory.' % ( - self.path_type, - filename_to_ui(value) - ), param, ctx) - if self.writable and not os.access(value, os.W_OK): - self.fail('%s "%s" is not writable.' % ( - self.path_type, - filename_to_ui(value) - ), param, ctx) - if self.readable and not os.access(value, os.R_OK): - self.fail('%s "%s" is not readable.' % ( - self.path_type, - filename_to_ui(value) - ), param, ctx) - - return self.coerce_path_result(rv) - - -class Tuple(CompositeParamType): - """The default behavior of Click is to apply a type on a value directly. - This works well in most cases, except for when `nargs` is set to a fixed - count and different types should be used for different items. In this - case the :class:`Tuple` type can be used. This type can only be used - if `nargs` is set to a fixed number. - - For more information see :ref:`tuple-type`. - - This can be selected by using a Python tuple literal as a type. - - :param types: a list of types that should be used for the tuple items. - """ - - def __init__(self, types): - self.types = [convert_type(ty) for ty in types] - - @property - def name(self): - return "<" + " ".join(ty.name for ty in self.types) + ">" - - @property - def arity(self): - return len(self.types) - - def convert(self, value, param, ctx): - if len(value) != len(self.types): - raise TypeError('It would appear that nargs is set to conflict ' - 'with the composite type arity.') - return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) - - -def convert_type(ty, default=None): - """Converts a callable or python ty into the most appropriate param - ty. - """ - guessed_type = False - if ty is None and default is not None: - if isinstance(default, tuple): - ty = tuple(map(type, default)) - else: - ty = type(default) - guessed_type = True - - if isinstance(ty, tuple): - return Tuple(ty) - if isinstance(ty, ParamType): - return ty - if ty is text_type or ty is str or ty is None: - return STRING - if ty is int: - return INT - # Booleans are only okay if not guessed. This is done because for - # flags the default value is actually a bit of a lie in that it - # indicates which of the flags is the one we want. See get_default() - # for more information. - if ty is bool and not guessed_type: - return BOOL - if ty is float: - return FLOAT - if guessed_type: - return STRING - - # Catch a common mistake - if __debug__: - try: - if issubclass(ty, ParamType): - raise AssertionError('Attempted to use an uninstantiated ' - 'parameter type (%s).' % ty) - except TypeError: - pass - return FuncParamType(ty) - - -#: A dummy parameter type that just does nothing. From a user's -#: perspective this appears to just be the same as `STRING` but internally -#: no string conversion takes place. This is necessary to achieve the -#: same bytes/unicode behavior on Python 2/3 in situations where you want -#: to not convert argument types. This is usually useful when working -#: with file paths as they can appear in bytes and unicode. -#: -#: For path related uses the :class:`Path` type is a better choice but -#: there are situations where an unprocessed type is useful which is why -#: it is is provided. -#: -#: .. versionadded:: 4.0 -UNPROCESSED = UnprocessedParamType() - -#: A unicode string parameter type which is the implicit default. This -#: can also be selected by using ``str`` as type. -STRING = StringParamType() - -#: An integer parameter. This can also be selected by using ``int`` as -#: type. -INT = IntParamType() - -#: A floating point value parameter. This can also be selected by using -#: ``float`` as type. -FLOAT = FloatParamType() - -#: A boolean parameter. This is the default for boolean flags. This can -#: also be selected by using ``bool`` as a type. -BOOL = BoolParamType() - -#: A UUID parameter. -UUID = UUIDParameterType() diff --git a/py3.7/lib/python3.7/site-packages/click/utils.py b/py3.7/lib/python3.7/site-packages/click/utils.py deleted file mode 100644 index fc84369..0000000 --- a/py3.7/lib/python3.7/site-packages/click/utils.py +++ /dev/null @@ -1,440 +0,0 @@ -import os -import sys - -from .globals import resolve_color_default - -from ._compat import text_type, open_stream, get_filesystem_encoding, \ - get_streerror, string_types, PY2, binary_streams, text_streams, \ - filename_to_ui, auto_wrap_for_ansi, strip_ansi, should_strip_ansi, \ - _default_text_stdout, _default_text_stderr, is_bytes, WIN - -if not PY2: - from ._compat import _find_binary_writer -elif WIN: - from ._winconsole import _get_windows_argv, \ - _hash_py_argv, _initial_argv_hash - - -echo_native_types = string_types + (bytes, bytearray) - - -def _posixify(name): - return '-'.join(name.split()).lower() - - -def safecall(func): - """Wraps a function so that it swallows exceptions.""" - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except Exception: - pass - return wrapper - - -def make_str(value): - """Converts a value into a valid string.""" - if isinstance(value, bytes): - try: - return value.decode(get_filesystem_encoding()) - except UnicodeError: - return value.decode('utf-8', 'replace') - return text_type(value) - - -def make_default_short_help(help, max_length=45): - """Return a condensed version of help string.""" - words = help.split() - total_length = 0 - result = [] - done = False - - for word in words: - if word[-1:] == '.': - done = True - new_length = result and 1 + len(word) or len(word) - if total_length + new_length > max_length: - result.append('...') - done = True - else: - if result: - result.append(' ') - result.append(word) - if done: - break - total_length += new_length - - return ''.join(result) - - -class LazyFile(object): - """A lazy file works like a regular file but it does not fully open - the file but it does perform some basic checks early to see if the - filename parameter does make sense. This is useful for safely opening - files for writing. - """ - - def __init__(self, filename, mode='r', encoding=None, errors='strict', - atomic=False): - self.name = filename - self.mode = mode - self.encoding = encoding - self.errors = errors - self.atomic = atomic - - if filename == '-': - self._f, self.should_close = open_stream(filename, mode, - encoding, errors) - else: - if 'r' in mode: - # Open and close the file in case we're opening it for - # reading so that we can catch at least some errors in - # some cases early. - open(filename, mode).close() - self._f = None - self.should_close = True - - def __getattr__(self, name): - return getattr(self.open(), name) - - def __repr__(self): - if self._f is not None: - return repr(self._f) - return '' % (self.name, self.mode) - - def open(self): - """Opens the file if it's not yet open. This call might fail with - a :exc:`FileError`. Not handling this error will produce an error - that Click shows. - """ - if self._f is not None: - return self._f - try: - rv, self.should_close = open_stream(self.name, self.mode, - self.encoding, - self.errors, - atomic=self.atomic) - except (IOError, OSError) as e: - from .exceptions import FileError - raise FileError(self.name, hint=get_streerror(e)) - self._f = rv - return rv - - def close(self): - """Closes the underlying file, no matter what.""" - if self._f is not None: - self._f.close() - - def close_intelligently(self): - """This function only closes the file if it was opened by the lazy - file wrapper. For instance this will never close stdin. - """ - if self.should_close: - self.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - self.close_intelligently() - - def __iter__(self): - self.open() - return iter(self._f) - - -class KeepOpenFile(object): - - def __init__(self, file): - self._file = file - - def __getattr__(self, name): - return getattr(self._file, name) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - pass - - def __repr__(self): - return repr(self._file) - - def __iter__(self): - return iter(self._file) - - -def echo(message=None, file=None, nl=True, err=False, color=None): - """Prints a message plus a newline to the given file or stdout. On - first sight, this looks like the print function, but it has improved - support for handling Unicode and binary data that does not fail no - matter how badly configured the system is. - - Primarily it means that you can print binary data as well as Unicode - data on both 2.x and 3.x to the given file in the most appropriate way - possible. This is a very carefree function in that it will try its - best to not fail. As of Click 6.0 this includes support for unicode - output on the Windows console. - - In addition to that, if `colorama`_ is installed, the echo function will - also support clever handling of ANSI codes. Essentially it will then - do the following: - - - add transparent handling of ANSI color codes on Windows. - - hide ANSI codes automatically if the destination file is not a - terminal. - - .. _colorama: https://pypi.org/project/colorama/ - - .. versionchanged:: 6.0 - As of Click 6.0 the echo function will properly support unicode - output on the windows console. Not that click does not modify - the interpreter in any way which means that `sys.stdout` or the - print statement or function will still not provide unicode support. - - .. versionchanged:: 2.0 - Starting with version 2.0 of Click, the echo function will work - with colorama if it's installed. - - .. versionadded:: 3.0 - The `err` parameter was added. - - .. versionchanged:: 4.0 - Added the `color` flag. - - :param message: the message to print - :param file: the file to write to (defaults to ``stdout``) - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``. This is faster and easier than calling - :func:`get_text_stderr` yourself. - :param nl: if set to `True` (the default) a newline is printed afterwards. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. - """ - if file is None: - if err: - file = _default_text_stderr() - else: - file = _default_text_stdout() - - # Convert non bytes/text into the native string type. - if message is not None and not isinstance(message, echo_native_types): - message = text_type(message) - - if nl: - message = message or u'' - if isinstance(message, text_type): - message += u'\n' - else: - message += b'\n' - - # If there is a message, and we're in Python 3, and the value looks - # like bytes, we manually need to find the binary stream and write the - # message in there. This is done separately so that most stream - # types will work as you would expect. Eg: you can write to StringIO - # for other cases. - if message and not PY2 and is_bytes(message): - binary_file = _find_binary_writer(file) - if binary_file is not None: - file.flush() - binary_file.write(message) - binary_file.flush() - return - - # ANSI-style support. If there is no message or we are dealing with - # bytes nothing is happening. If we are connected to a file we want - # to strip colors. If we are on windows we either wrap the stream - # to strip the color or we use the colorama support to translate the - # ansi codes to API calls. - if message and not is_bytes(message): - color = resolve_color_default(color) - if should_strip_ansi(file, color): - message = strip_ansi(message) - elif WIN: - if auto_wrap_for_ansi is not None: - file = auto_wrap_for_ansi(file) - elif not color: - message = strip_ansi(message) - - if message: - file.write(message) - file.flush() - - -def get_binary_stream(name): - """Returns a system stream for byte processing. This essentially - returns the stream from the sys module with the given name but it - solves some compatibility issues between different Python versions. - Primarily this function is necessary for getting binary streams on - Python 3. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - """ - opener = binary_streams.get(name) - if opener is None: - raise TypeError('Unknown standard stream %r' % name) - return opener() - - -def get_text_stream(name, encoding=None, errors='strict'): - """Returns a system stream for text processing. This usually returns - a wrapped stream around a binary stream returned from - :func:`get_binary_stream` but it also can take shortcuts on Python 3 - for already correctly configured streams. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - :param encoding: overrides the detected default encoding. - :param errors: overrides the default error mode. - """ - opener = text_streams.get(name) - if opener is None: - raise TypeError('Unknown standard stream %r' % name) - return opener(encoding, errors) - - -def open_file(filename, mode='r', encoding=None, errors='strict', - lazy=False, atomic=False): - """This is similar to how the :class:`File` works but for manual - usage. Files are opened non lazy by default. This can open regular - files as well as stdin/stdout if ``'-'`` is passed. - - If stdin/stdout is returned the stream is wrapped so that the context - manager will not close the stream accidentally. This makes it possible - to always use the function like this without having to worry to - accidentally close a standard stream:: - - with open_file(filename) as f: - ... - - .. versionadded:: 3.0 - - :param filename: the name of the file to open (or ``'-'`` for stdin/stdout). - :param mode: the mode in which to open the file. - :param encoding: the encoding to use. - :param errors: the error handling for this file. - :param lazy: can be flipped to true to open the file lazily. - :param atomic: in atomic mode writes go into a temporary file and it's - moved on close. - """ - if lazy: - return LazyFile(filename, mode, encoding, errors, atomic=atomic) - f, should_close = open_stream(filename, mode, encoding, errors, - atomic=atomic) - if not should_close: - f = KeepOpenFile(f) - return f - - -def get_os_args(): - """This returns the argument part of sys.argv in the most appropriate - form for processing. What this means is that this return value is in - a format that works for Click to process but does not necessarily - correspond well to what's actually standard for the interpreter. - - On most environments the return value is ``sys.argv[:1]`` unchanged. - However if you are on Windows and running Python 2 the return value - will actually be a list of unicode strings instead because the - default behavior on that platform otherwise will not be able to - carry all possible values that sys.argv can have. - - .. versionadded:: 6.0 - """ - # We can only extract the unicode argv if sys.argv has not been - # changed since the startup of the application. - if PY2 and WIN and _initial_argv_hash == _hash_py_argv(): - return _get_windows_argv() - return sys.argv[1:] - - -def format_filename(filename, shorten=False): - """Formats a filename for user display. The main purpose of this - function is to ensure that the filename can be displayed at all. This - will decode the filename to unicode if necessary in a way that it will - not fail. Optionally, it can shorten the filename to not include the - full path to the filename. - - :param filename: formats a filename for UI display. This will also convert - the filename into unicode without failing. - :param shorten: this optionally shortens the filename to strip of the - path that leads up to it. - """ - if shorten: - filename = os.path.basename(filename) - return filename_to_ui(filename) - - -def get_app_dir(app_name, roaming=True, force_posix=False): - r"""Returns the config folder for the application. The default behavior - is to return whatever is most appropriate for the operating system. - - To give you an idea, for an app called ``"Foo Bar"``, something like - the following folders could be returned: - - Mac OS X: - ``~/Library/Application Support/Foo Bar`` - Mac OS X (POSIX): - ``~/.foo-bar`` - Unix: - ``~/.config/foo-bar`` - Unix (POSIX): - ``~/.foo-bar`` - Win XP (roaming): - ``C:\Documents and Settings\\Local Settings\Application Data\Foo Bar`` - Win XP (not roaming): - ``C:\Documents and Settings\\Application Data\Foo Bar`` - Win 7 (roaming): - ``C:\Users\\AppData\Roaming\Foo Bar`` - Win 7 (not roaming): - ``C:\Users\\AppData\Local\Foo Bar`` - - .. versionadded:: 2.0 - - :param app_name: the application name. This should be properly capitalized - and can contain whitespace. - :param roaming: controls if the folder should be roaming or not on Windows. - Has no affect otherwise. - :param force_posix: if this is set to `True` then on any POSIX system the - folder will be stored in the home folder with a leading - dot instead of the XDG config home or darwin's - application support folder. - """ - if WIN: - key = roaming and 'APPDATA' or 'LOCALAPPDATA' - folder = os.environ.get(key) - if folder is None: - folder = os.path.expanduser('~') - return os.path.join(folder, app_name) - if force_posix: - return os.path.join(os.path.expanduser('~/.' + _posixify(app_name))) - if sys.platform == 'darwin': - return os.path.join(os.path.expanduser( - '~/Library/Application Support'), app_name) - return os.path.join( - os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), - _posixify(app_name)) - - -class PacifyFlushWrapper(object): - """This wrapper is used to catch and suppress BrokenPipeErrors resulting - from ``.flush()`` being called on broken pipe during the shutdown/final-GC - of the Python interpreter. Notably ``.flush()`` is always called on - ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any - other cleanup code, and the case where the underlying file is not a broken - pipe, all calls and attributes are proxied. - """ - - def __init__(self, wrapped): - self.wrapped = wrapped - - def flush(self): - try: - self.wrapped.flush() - except IOError as e: - import errno - if e.errno != errno.EPIPE: - raise - - def __getattr__(self, attr): - return getattr(self.wrapped, attr) diff --git a/py3.7/lib/python3.7/site-packages/easy-install.pth b/py3.7/lib/python3.7/site-packages/easy-install.pth deleted file mode 100644 index 48ec255..0000000 --- a/py3.7/lib/python3.7/site-packages/easy-install.pth +++ /dev/null @@ -1 +0,0 @@ -./pybtc-2.0.9-py3.7.egg diff --git a/py3.7/lib/python3.7/site-packages/easy_install.py b/py3.7/lib/python3.7/site-packages/easy_install.py deleted file mode 100644 index d87e984..0000000 --- a/py3.7/lib/python3.7/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/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/LICENSE.txt b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/LICENSE.txt deleted file mode 100644 index 8f080ea..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Nathaniel J. Smith and other contributors - -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. diff --git a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/METADATA deleted file mode 100644 index c370bee..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/METADATA +++ /dev/null @@ -1,193 +0,0 @@ -Metadata-Version: 2.1 -Name: h11 -Version: 0.9.0 -Summary: A pure-Python, bring-your-own-I/O implementation of HTTP/1.1 -Home-page: https://github.com/python-hyper/h11 -Author: Nathaniel J. Smith -Author-email: njs@pobox.com -License: MIT -Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Topic :: Internet :: WWW/HTTP -Classifier: Topic :: System :: Networking - -h11 -=== - -.. image:: https://travis-ci.org/python-hyper/h11.svg?branch=master - :target: https://travis-ci.org/python-hyper/h11 - :alt: Automated test status - -.. image:: https://codecov.io/gh/python-hyper/h11/branch/master/graph/badge.svg - :target: https://codecov.io/gh/python-hyper/h11 - :alt: Test coverage - -.. image:: https://readthedocs.org/projects/h11/badge/?version=latest - :target: http://h11.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - -This is a little HTTP/1.1 library written from scratch in Python, -heavily inspired by `hyper-h2 `_. - -It's a "bring-your-own-I/O" library; h11 contains no IO code -whatsoever. This means you can hook h11 up to your favorite network -API, and that could be anything you want: synchronous, threaded, -asynchronous, or your own implementation of `RFC 6214 -`_ -- h11 won't judge you. -(Compare this to the current state of the art, where every time a `new -network API `_ comes along then someone -gets to start over reimplementing the entire HTTP protocol from -scratch.) Cory Benfield made an `excellent blog post describing the -benefits of this approach -`_, or if you like video -then here's his `PyCon 2016 talk on the same theme -`_. - -This also means that h11 is not immediately useful out of the box: -it's a toolkit for building programs that speak HTTP, not something -that could directly replace ``requests`` or ``twisted.web`` or -whatever. But h11 makes it much easier to implement something like -``requests`` or ``twisted.web``. - -At a high level, working with h11 goes like this: - -1) First, create an ``h11.Connection`` object to track the state of a - single HTTP/1.1 connection. - -2) When you read data off the network, pass it to - ``conn.receive_data(...)``; you'll get back a list of objects - representing high-level HTTP "events". - -3) When you want to send a high-level HTTP event, create the - corresponding "event" object and pass it to ``conn.send(...)``; - this will give you back some bytes that you can then push out - through the network. - -For example, a client might instantiate and then send a -``h11.Request`` object, then zero or more ``h11.Data`` objects for the -request body (e.g., if this is a POST), and then a -``h11.EndOfMessage`` to indicate the end of the message. Then the -server would then send back a ``h11.Response``, some ``h11.Data``, and -its own ``h11.EndOfMessage``. If either side violates the protocol, -you'll get a ``h11.ProtocolError`` exception. - -h11 is suitable for implementing both servers and clients, and has a -pleasantly symmetric API: the events you send as a client are exactly -the ones that you receive as a server and vice-versa. - -`Here's an example of a tiny HTTP client -`_ - -It also has `a fine manual `_. - -FAQ ---- - -*Whyyyyy?* - -I wanted to play with HTTP in `Curio -`__ and `Trio -`__, which at the time didn't have any -HTTP libraries. So I thought, no big deal, Python has, like, a dozen -different implementations of HTTP, surely I can find one that's -reusable. I didn't find one, but I did find Cory's call-to-arms -blog-post. So I figured, well, fine, if I have to implement HTTP from -scratch, at least I can make sure no-one *else* has to ever again. - -*Should I use it?* - -Maybe. You should be aware that it's a very young project. But, it's -feature complete and has an exhaustive test-suite and complete docs, -so the next step is for people to try using it and see how it goes -:-). If you do then please let us know -- if nothing else we'll want -to talk to you before making any incompatible changes! - -*What are the features/limitations?* - -Roughly speaking, it's trying to be a robust, complete, and non-hacky -implementation of the first "chapter" of the HTTP/1.1 spec: `RFC 7230: -HTTP/1.1 Message Syntax and Routing -`_. That is, it mostly focuses on -implementing HTTP at the level of taking bytes on and off the wire, -and the headers related to that, and tries to be anal about spec -conformance. It doesn't know about higher-level concerns like URL -routing, conditional GETs, cross-origin cookie policies, or content -negotiation. But it does know how to take care of framing, -cross-version differences in keep-alive handling, and the "obsolete -line folding" rule, so you can focus your energies on the hard / -interesting parts for your application, and it tries to support the -full specification in the sense that any useful HTTP/1.1 conformant -application should be able to use h11. - -It's pure Python, and has no dependencies outside of the standard -library. - -It has a test suite with 100.0% coverage for both statements and -branches. - -Currently it supports Python 3 (testing on 3.4-3.7), Python 2.7, and PyPy. -(Originally it had a Cython wrapper for `http-parser -`_ and a beautiful nested state -machine implemented with ``yield from`` to postprocess the output. But -I had to take these out -- the new *parser* needs fewer lines-of-code -than the old *parser wrapper*, is written in pure Python, uses no -exotic language syntax, and has more features. It's sad, really; that -old state machine was really slick. I just need a few sentences here -to mourn that.) - -I don't know how fast it is. I haven't benchmarked or profiled it yet, -so it's probably got a few pointless hot spots, and I've been trying -to err on the side of simplicity and robustness instead of -micro-optimization. But at the architectural level I tried hard to -avoid fundamentally bad decisions, e.g., I believe that all the -parsing algorithms remain linear-time even in the face of pathological -input like slowloris, and there are no byte-by-byte loops. (I also -believe that it maintains bounded memory usage in the face of -arbitrary/pathological input.) - -The whole library is ~800 lines-of-code. You can read and understand -the whole thing in less than an hour. Most of the energy invested in -this so far has been spent on trying to keep things simple by -minimizing special-cases and ad hoc state manipulation; even though it -is now quite small and simple, I'm still annoyed that I haven't -figured out how to make it even smaller and simpler. (Unfortunately, -HTTP does not lend itself to simplicity.) - -The API is ~feature complete and I don't expect the general outlines -to change much, but you can't judge an API's ergonomics until you -actually document and use it, so I'd expect some changes in the -details. - -*How do I try it?* - -.. code-block:: sh - - $ pip install h11 - $ git clone git@github.com:python-hyper/h11 - $ cd h11/examples - $ python basic-client.py - -and go from there. - -*License?* - -MIT - -*Code of conduct?* - -Contributors are requested to follow our `code of conduct -`_ in -all project spaces. - - diff --git a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/RECORD deleted file mode 100644 index 700ff46..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/RECORD +++ /dev/null @@ -1,51 +0,0 @@ -h11/__init__.py,sha256=3gYpvQiX8_6-dyXaAxQt_sIYREVTz1T-zB5Lf4hjKt0,909 -h11/_abnf.py,sha256=tMKqgOEkTHHp8sPd_gmU9Qowe_yXXrihct63RX2zJsg,4637 -h11/_connection.py,sha256=igtLgTM-3tpiDvJA9R5toMQUiJw9o4m2wFD8izlelI0,24986 -h11/_events.py,sha256=BjWc_btWJW_N-CRUPRo68fKF8vv6hlcMs19b9oNBymc,9910 -h11/_headers.py,sha256=4LGuElGbwCdMT3pHiTc3ghUN3f7uPMLoYnkoR86YXXs,6823 -h11/_readers.py,sha256=_lYHBTdXFjF3V8z8mn9-TGW5XrskWVggq3pL8yUIgGA,7214 -h11/_receivebuffer.py,sha256=hxloIiW5b5g_cdbFAzPw-tv6YpKnDIsN4z1FUWlopcg,3911 -h11/_state.py,sha256=7YG1pJzTbwx46U_HIqKViJvf62nqGJd0g9KZ3TRR5i4,12175 -h11/_util.py,sha256=D6Pfn5Jc1TIdMjrUEpg1J_KcMvBIbCXHA9Aac5GTedM,4994 -h11/_version.py,sha256=8QshbQupywjssaujkSQCtTpWC_MRedlwIOO5IPhkeIA,685 -h11/_writers.py,sha256=k2j07RoKw6dsW_soJ6RIutPt6QddOJlZv-gP7t_I9OY,4683 -h11/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -h11/tests/helpers.py,sha256=nKheRzldPf278C81d_9_Mb9yWsYJ5udwKg_oq-fAz-U,2528 -h11/tests/test_against_stdlib_http.py,sha256=es30cmRVSTcrkNqoH5AGe_uT3ljR0OaLf2tID_17Owo,4010 -h11/tests/test_connection.py,sha256=24pNvHl9DV8rz0urlPBiAJeGNnODzWD2AiyfDu7AHmc,35578 -h11/tests/test_events.py,sha256=VUmiZfqBs0OM3Zxiwh6QviP1kZGbBqoMjBpz0OgwepE,4780 -h11/tests/test_headers.py,sha256=VH1T4kYh3B_PMU8PCmNwIS3YwXWsPvc-QZR2i79G6Vw,4847 -h11/tests/test_helpers.py,sha256=mPOAiv4HtyG0_T23K_ihh1JUs0y71ykD47c9r3iVtz0,573 -h11/tests/test_io.py,sha256=X2K26_1-yUPgv9KH52pNdiw7h-j33thu69MRmUEiVz4,14432 -h11/tests/test_receivebuffer.py,sha256=FId-lVBL3gBKmKD8gmmuZW_vdPYDtywxC3HozHI4Im0,2099 -h11/tests/test_state.py,sha256=JMKqA2d2wtskf7FbsAr1s9qsIul4WtwdXVAOCUJgalk,8551 -h11/tests/test_util.py,sha256=nlyS9b0KaP4rpsyRae0KmJ0ANNnrUjDmYaKFzz-l2RM,2711 -h11/tests/data/test-file,sha256=ZJ03Rqs98oJw29OHzJg7LlMzyGQaRAY0r3AqBeM2wVU,65 -h11-0.9.0.dist-info/LICENSE.txt,sha256=N9tbuFkm2yikJ6JYZ_ELEjIAOuob5pzLhRE4rbjm82E,1124 -h11-0.9.0.dist-info/METADATA,sha256=H9b57xIB1kDea2qMZQnzwatUmGadiuw-jU30EmALToY,8085 -h11-0.9.0.dist-info/WHEEL,sha256=h_aVn5OB2IERUjMbi2pucmR_zzWJtk303YXvhh60NJ8,110 -h11-0.9.0.dist-info/top_level.txt,sha256=F7dC4jl3zeh8TGHEPaWJrMbeuoWbS379Gwdi-Yvdcis,4 -h11-0.9.0.dist-info/RECORD,, -h11-0.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -h11/tests/__pycache__/test_connection.cpython-37.pyc,, -h11/tests/__pycache__/test_io.cpython-37.pyc,, -h11/tests/__pycache__/test_against_stdlib_http.cpython-37.pyc,, -h11/tests/__pycache__/__init__.cpython-37.pyc,, -h11/tests/__pycache__/helpers.cpython-37.pyc,, -h11/tests/__pycache__/test_events.cpython-37.pyc,, -h11/tests/__pycache__/test_state.cpython-37.pyc,, -h11/tests/__pycache__/test_helpers.cpython-37.pyc,, -h11/tests/__pycache__/test_receivebuffer.cpython-37.pyc,, -h11/tests/__pycache__/test_headers.cpython-37.pyc,, -h11/tests/__pycache__/test_util.cpython-37.pyc,, -h11/__pycache__/_headers.cpython-37.pyc,, -h11/__pycache__/_readers.cpython-37.pyc,, -h11/__pycache__/_version.cpython-37.pyc,, -h11/__pycache__/_connection.cpython-37.pyc,, -h11/__pycache__/__init__.cpython-37.pyc,, -h11/__pycache__/_writers.cpython-37.pyc,, -h11/__pycache__/_util.cpython-37.pyc,, -h11/__pycache__/_state.cpython-37.pyc,, -h11/__pycache__/_abnf.cpython-37.pyc,, -h11/__pycache__/_events.cpython-37.pyc,, -h11/__pycache__/_receivebuffer.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/WHEEL deleted file mode 100644 index 78e6f69..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.33.4) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/top_level.txt deleted file mode 100644 index 0d24def..0000000 --- a/py3.7/lib/python3.7/site-packages/h11-0.9.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -h11 diff --git a/py3.7/lib/python3.7/site-packages/h11/__init__.py b/py3.7/lib/python3.7/site-packages/h11/__init__.py deleted file mode 100644 index ae39e01..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# A highish-level implementation of the HTTP/1.1 wire protocol (RFC 7230), -# containing no networking code at all, loosely modelled on hyper-h2's generic -# implementation of HTTP/2 (and in particular the h2.connection.H2Connection -# class). There's still a bunch of subtle details you need to get right if you -# want to make this actually useful, because it doesn't implement all the -# semantics to check that what you're asking to write to the wire is sensible, -# but at least it gets you out of dealing with the wire itself. - -from ._connection import * -from ._events import * -from ._state import * -from ._util import LocalProtocolError, ProtocolError, RemoteProtocolError -from ._version import __version__ - -PRODUCT_ID = "python-h11/" + __version__ - - -__all__ = ["ProtocolError", "LocalProtocolError", "RemoteProtocolError"] -__all__ += _events.__all__ -__all__ += _connection.__all__ -__all__ += _state.__all__ diff --git a/py3.7/lib/python3.7/site-packages/h11/_abnf.py b/py3.7/lib/python3.7/site-packages/h11/_abnf.py deleted file mode 100644 index e6d49e1..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_abnf.py +++ /dev/null @@ -1,129 +0,0 @@ -# We use native strings for all the re patterns, to take advantage of string -# formatting, and then convert to bytestrings when compiling the final re -# objects. - -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#whitespace -# OWS = *( SP / HTAB ) -# ; optional whitespace -OWS = r"[ \t]*" - -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.token.separators -# token = 1*tchar -# -# tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" -# / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" -# / DIGIT / ALPHA -# ; any VCHAR, except delimiters -token = r"[-!#$%&'*+.^_`|~0-9a-zA-Z]+" - -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#header.fields -# field-name = token -field_name = token - -# The standard says: -# -# field-value = *( field-content / obs-fold ) -# field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] -# field-vchar = VCHAR / obs-text -# obs-fold = CRLF 1*( SP / HTAB ) -# ; obsolete line folding -# ; see Section 3.2.4 -# -# https://tools.ietf.org/html/rfc5234#appendix-B.1 -# -# VCHAR = %x21-7E -# ; visible (printing) characters -# -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#rule.quoted-string -# obs-text = %x80-FF -# -# However, the standard definition of field-content is WRONG! It disallows -# fields containing a single visible character surrounded by whitespace, -# e.g. "foo a bar". -# -# See: https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4189 -# -# So our definition of field_content attempts to fix it up... -# -# Also, we allow lots of control characters, because apparently people assume -# that they're legal in practice (e.g., google analytics makes cookies with -# \x01 in them!): -# https://github.com/python-hyper/h11/issues/57 -# We still don't allow NUL or whitespace, because those are often treated as -# meta-characters and letting them through can lead to nasty issues like SSRF. -vchar = r"[\x21-\x7e]" -vchar_or_obs_text = r"[^\x00\s]" -field_vchar = vchar_or_obs_text -field_content = r"{field_vchar}+(?:[ \t]+{field_vchar}+)*".format(**globals()) - -# We handle obs-fold at a different level, and our fixed-up field_content -# already grows to swallow the whole value, so ? instead of * -field_value = r"({field_content})?".format(**globals()) - -# header-field = field-name ":" OWS field-value OWS -header_field = ( - r"(?P{field_name})" - r":" - r"{OWS}" - r"(?P{field_value})" - r"{OWS}".format(**globals()) -) - -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#request.line -# -# request-line = method SP request-target SP HTTP-version CRLF -# method = token -# HTTP-version = HTTP-name "/" DIGIT "." DIGIT -# HTTP-name = %x48.54.54.50 ; "HTTP", case-sensitive -# -# request-target is complicated (see RFC 7230 sec 5.3) -- could be path, full -# URL, host+port (for connect), or even "*", but in any case we are guaranteed -# that it contists of the visible printing characters. -method = token -request_target = r"{vchar}+".format(**globals()) -http_version = r"HTTP/(?P[0-9]\.[0-9])" -request_line = ( - r"(?P{method})" - r" " - r"(?P{request_target})" - r" " - r"{http_version}".format(**globals()) -) - -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#status.line -# -# status-line = HTTP-version SP status-code SP reason-phrase CRLF -# status-code = 3DIGIT -# reason-phrase = *( HTAB / SP / VCHAR / obs-text ) -status_code = r"[0-9]{3}" -reason_phrase = r"([ \t]|{vchar_or_obs_text})*".format(**globals()) -status_line = ( - r"{http_version}" - r" " - r"(?P{status_code})" - # However, there are apparently a few too many servers out there that just - # leave out the reason phrase: - # https://github.com/scrapy/scrapy/issues/345#issuecomment-281756036 - # https://github.com/seanmonstar/httparse/issues/29 - # so make it optional. ?: is a non-capturing group. - r"(?: (?P{reason_phrase}))?".format(**globals()) -) - -HEXDIG = r"[0-9A-Fa-f]" -# Actually -# -# chunk-size = 1*HEXDIG -# -# but we impose an upper-limit to avoid ridiculosity. len(str(2**64)) == 20 -chunk_size = r"({HEXDIG}){{1,20}}".format(**globals()) -# Actually -# -# chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) -# -# but we aren't parsing the things so we don't really care. -chunk_ext = r";.*" -chunk_header = ( - r"(?P{chunk_size})" - r"(?P{chunk_ext})?" - r"\r\n".format(**globals()) -) diff --git a/py3.7/lib/python3.7/site-packages/h11/_connection.py b/py3.7/lib/python3.7/site-packages/h11/_connection.py deleted file mode 100644 index 4fc629a..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_connection.py +++ /dev/null @@ -1,586 +0,0 @@ -# This contains the main Connection class. Everything in h11 revolves around -# this. - -from ._events import * # Import all event types -from ._headers import get_comma_header, has_expect_100_continue, set_comma_header -from ._readers import READERS -from ._receivebuffer import ReceiveBuffer -from ._state import * # Import all state sentinels -from ._state import _SWITCH_CONNECT, _SWITCH_UPGRADE, ConnectionState -from ._util import ( # Import the internal things we need - LocalProtocolError, - make_sentinel, - RemoteProtocolError, -) -from ._writers import WRITERS - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = ["Connection", "NEED_DATA", "PAUSED"] - -NEED_DATA = make_sentinel("NEED_DATA") -PAUSED = make_sentinel("PAUSED") - -# If we ever have this much buffered without it making a complete parseable -# event, we error out. The only time we really buffer is when reading the -# request/reponse line + headers together, so this is effectively the limit on -# the size of that. -# -# Some precedents for defaults: -# - node.js: 80 * 1024 -# - tomcat: 8 * 1024 -# - IIS: 16 * 1024 -# - Apache: <8 KiB per line> -DEFAULT_MAX_INCOMPLETE_EVENT_SIZE = 16 * 1024 - -# RFC 7230's rules for connection lifecycles: -# - If either side says they want to close the connection, then the connection -# must close. -# - HTTP/1.1 defaults to keep-alive unless someone says Connection: close -# - HTTP/1.0 defaults to close unless both sides say Connection: keep-alive -# (and even this is a mess -- e.g. if you're implementing a proxy then -# sending Connection: keep-alive is forbidden). -# -# We simplify life by simply not supporting keep-alive with HTTP/1.0 peers. So -# our rule is: -# - If someone says Connection: close, we will close -# - If someone uses HTTP/1.0, we will close. -def _keep_alive(event): - connection = get_comma_header(event.headers, b"connection") - if b"close" in connection: - return False - if getattr(event, "http_version", b"1.1") < b"1.1": - return False - return True - - -def _body_framing(request_method, event): - # Called when we enter SEND_BODY to figure out framing information for - # this body. - # - # These are the only two events that can trigger a SEND_BODY state: - assert type(event) in (Request, Response) - # Returns one of: - # - # ("content-length", count) - # ("chunked", ()) - # ("http/1.0", ()) - # - # which are (lookup key, *args) for constructing body reader/writer - # objects. - # - # Reference: https://tools.ietf.org/html/rfc7230#section-3.3.3 - # - # Step 1: some responses always have an empty body, regardless of what the - # headers say. - if type(event) is Response: - if ( - event.status_code in (204, 304) - or request_method == b"HEAD" - or (request_method == b"CONNECT" and 200 <= event.status_code < 300) - ): - return ("content-length", (0,)) - # Section 3.3.3 also lists another case -- responses with status_code - # < 200. For us these are InformationalResponses, not Responses, so - # they can't get into this function in the first place. - assert event.status_code >= 200 - - # Step 2: check for Transfer-Encoding (T-E beats C-L): - transfer_encodings = get_comma_header(event.headers, b"transfer-encoding") - if transfer_encodings: - assert transfer_encodings == [b"chunked"] - return ("chunked", ()) - - # Step 3: check for Content-Length - content_lengths = get_comma_header(event.headers, b"content-length") - if content_lengths: - return ("content-length", (int(content_lengths[0]),)) - - # Step 4: no applicable headers; fallback/default depends on type - if type(event) is Request: - return ("content-length", (0,)) - else: - return ("http/1.0", ()) - - -################################################################ -# -# The main Connection class -# -################################################################ - - -class Connection(object): - """An object encapsulating the state of an HTTP connection. - - Args: - our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If - you're implementing a server, pass :data:`h11.SERVER`. - - max_incomplete_event_size (int): - The maximum number of bytes we're willing to buffer of an - incomplete event. In practice this mostly sets a limit on the - maximum size of the request/response line + headers. If this is - exceeded, then :meth:`next_event` will raise - :exc:`RemoteProtocolError`. - - """ - - def __init__( - self, our_role, max_incomplete_event_size=DEFAULT_MAX_INCOMPLETE_EVENT_SIZE - ): - self._max_incomplete_event_size = max_incomplete_event_size - # State and role tracking - if our_role not in (CLIENT, SERVER): - raise ValueError("expected CLIENT or SERVER, not {!r}".format(our_role)) - self.our_role = our_role - if our_role is CLIENT: - self.their_role = SERVER - else: - self.their_role = CLIENT - self._cstate = ConnectionState() - - # Callables for converting data->events or vice-versa given the - # current state - self._writer = self._get_io_object(self.our_role, None, WRITERS) - self._reader = self._get_io_object(self.their_role, None, READERS) - - # Holds any unprocessed received data - self._receive_buffer = ReceiveBuffer() - # If this is true, then it indicates that the incoming connection was - # closed *after* the end of whatever's in self._receive_buffer: - self._receive_buffer_closed = False - - # Extra bits of state that don't fit into the state machine. - # - # These two are only used to interpret framing headers for figuring - # out how to read/write response bodies. their_http_version is also - # made available as a convenient public API. - self.their_http_version = None - self._request_method = None - # This is pure flow-control and doesn't at all affect the set of legal - # transitions, so no need to bother ConnectionState with it: - self.client_is_waiting_for_100_continue = False - - @property - def states(self): - """A dictionary like:: - - {CLIENT: , SERVER: } - - See :ref:`state-machine` for details. - - """ - return dict(self._cstate.states) - - @property - def our_state(self): - """The current state of whichever role we are playing. See - :ref:`state-machine` for details. - """ - return self._cstate.states[self.our_role] - - @property - def their_state(self): - """The current state of whichever role we are NOT playing. See - :ref:`state-machine` for details. - """ - return self._cstate.states[self.their_role] - - @property - def they_are_waiting_for_100_continue(self): - return self.their_role is CLIENT and self.client_is_waiting_for_100_continue - - def start_next_cycle(self): - """Attempt to reset our connection state for a new request/response - cycle. - - If both client and server are in :data:`DONE` state, then resets them - both to :data:`IDLE` state in preparation for a new request/response - cycle on this same connection. Otherwise, raises a - :exc:`LocalProtocolError`. - - See :ref:`keepalive-and-pipelining`. - - """ - old_states = dict(self._cstate.states) - self._cstate.start_next_cycle() - self._request_method = None - # self.their_http_version gets left alone, since it presumably lasts - # beyond a single request/response cycle - assert not self.client_is_waiting_for_100_continue - self._respond_to_state_changes(old_states) - - def _process_error(self, role): - old_states = dict(self._cstate.states) - self._cstate.process_error(role) - self._respond_to_state_changes(old_states) - - def _server_switch_event(self, event): - if type(event) is InformationalResponse and event.status_code == 101: - return _SWITCH_UPGRADE - if type(event) is Response: - if ( - _SWITCH_CONNECT in self._cstate.pending_switch_proposals - and 200 <= event.status_code < 300 - ): - return _SWITCH_CONNECT - return None - - # All events go through here - def _process_event(self, role, event): - # First, pass the event through the state machine to make sure it - # succeeds. - old_states = dict(self._cstate.states) - if role is CLIENT and type(event) is Request: - if event.method == b"CONNECT": - self._cstate.process_client_switch_proposal(_SWITCH_CONNECT) - if get_comma_header(event.headers, b"upgrade"): - self._cstate.process_client_switch_proposal(_SWITCH_UPGRADE) - server_switch_event = None - if role is SERVER: - server_switch_event = self._server_switch_event(event) - self._cstate.process_event(role, type(event), server_switch_event) - - # Then perform the updates triggered by it. - - # self._request_method - if type(event) is Request: - self._request_method = event.method - - # self.their_http_version - if role is self.their_role and type(event) in ( - Request, - Response, - InformationalResponse, - ): - self.their_http_version = event.http_version - - # Keep alive handling - # - # RFC 7230 doesn't really say what one should do if Connection: close - # shows up on a 1xx InformationalResponse. I think the idea is that - # this is not supposed to happen. In any case, if it does happen, we - # ignore it. - if type(event) in (Request, Response) and not _keep_alive(event): - self._cstate.process_keep_alive_disabled() - - # 100-continue - if type(event) is Request and has_expect_100_continue(event): - self.client_is_waiting_for_100_continue = True - if type(event) in (InformationalResponse, Response): - self.client_is_waiting_for_100_continue = False - if role is CLIENT and type(event) in (Data, EndOfMessage): - self.client_is_waiting_for_100_continue = False - - self._respond_to_state_changes(old_states, event) - - def _get_io_object(self, role, event, io_dict): - # event may be None; it's only used when entering SEND_BODY - state = self._cstate.states[role] - if state is SEND_BODY: - # Special case: the io_dict has a dict of reader/writer factories - # that depend on the request/response framing. - framing_type, args = _body_framing(self._request_method, event) - return io_dict[SEND_BODY][framing_type](*args) - else: - # General case: the io_dict just has the appropriate reader/writer - # for this state - return io_dict.get((role, state)) - - # This must be called after any action that might have caused - # self._cstate.states to change. - def _respond_to_state_changes(self, old_states, event=None): - # Update reader/writer - if self.our_state != old_states[self.our_role]: - self._writer = self._get_io_object(self.our_role, event, WRITERS) - if self.their_state != old_states[self.their_role]: - self._reader = self._get_io_object(self.their_role, event, READERS) - - @property - def trailing_data(self): - """Data that has been received, but not yet processed, represented as - a tuple with two elements, where the first is a byte-string containing - the unprocessed data itself, and the second is a bool that is True if - the receive connection was closed. - - See :ref:`switching-protocols` for discussion of why you'd want this. - """ - return (bytes(self._receive_buffer), self._receive_buffer_closed) - - def receive_data(self, data): - """Add data to our internal recieve buffer. - - This does not actually do any processing on the data, just stores - it. To trigger processing, you have to call :meth:`next_event`. - - Args: - data (:term:`bytes-like object`): - The new data that was just received. - - Special case: If *data* is an empty byte-string like ``b""``, - then this indicates that the remote side has closed the - connection (end of file). Normally this is convenient, because - standard Python APIs like :meth:`file.read` or - :meth:`socket.recv` use ``b""`` to indicate end-of-file, while - other failures to read are indicated using other mechanisms - like raising :exc:`TimeoutError`. When using such an API you - can just blindly pass through whatever you get from ``read`` - to :meth:`receive_data`, and everything will work. - - But, if you have an API where reading an empty string is a - valid non-EOF condition, then you need to be aware of this and - make sure to check for such strings and avoid passing them to - :meth:`receive_data`. - - Returns: - Nothing, but after calling this you should call :meth:`next_event` - to parse the newly received data. - - Raises: - RuntimeError: - Raised if you pass an empty *data*, indicating EOF, and then - pass a non-empty *data*, indicating more data that somehow - arrived after the EOF. - - (Calling ``receive_data(b"")`` multiple times is fine, - and equivalent to calling it once.) - - """ - if data: - if self._receive_buffer_closed: - raise RuntimeError("received close, then received more data?") - self._receive_buffer += data - else: - self._receive_buffer_closed = True - - def _extract_next_receive_event(self): - state = self.their_state - # We don't pause immediately when they enter DONE, because even in - # DONE state we can still process a ConnectionClosed() event. But - # if we have data in our buffer, then we definitely aren't getting - # a ConnectionClosed() immediately and we need to pause. - if state is DONE and self._receive_buffer: - return PAUSED - if state is MIGHT_SWITCH_PROTOCOL or state is SWITCHED_PROTOCOL: - return PAUSED - assert self._reader is not None - event = self._reader(self._receive_buffer) - if event is None: - if not self._receive_buffer and self._receive_buffer_closed: - # In some unusual cases (basically just HTTP/1.0 bodies), EOF - # triggers an actual protocol event; in that case, we want to - # return that event, and then the state will change and we'll - # get called again to generate the actual ConnectionClosed(). - if hasattr(self._reader, "read_eof"): - event = self._reader.read_eof() - else: - event = ConnectionClosed() - if event is None: - event = NEED_DATA - return event - - def next_event(self): - """Parse the next event out of our receive buffer, update our internal - state, and return it. - - This is a mutating operation -- think of it like calling :func:`next` - on an iterator. - - Returns: - : One of three things: - - 1) An event object -- see :ref:`events`. - - 2) The special constant :data:`NEED_DATA`, which indicates that - you need to read more data from your socket and pass it to - :meth:`receive_data` before this method will be able to return - any more events. - - 3) The special constant :data:`PAUSED`, which indicates that we - are not in a state where we can process incoming data (usually - because the peer has finished their part of the current - request/response cycle, and you have not yet called - :meth:`start_next_cycle`). See :ref:`flow-control` for details. - - Raises: - RemoteProtocolError: - The peer has misbehaved. You should close the connection - (possibly after sending some kind of 4xx response). - - Once this method returns :class:`ConnectionClosed` once, then all - subsequent calls will also return :class:`ConnectionClosed`. - - If this method raises any exception besides :exc:`RemoteProtocolError` - then that's a bug -- if it happens please file a bug report! - - If this method raises any exception then it also sets - :attr:`Connection.their_state` to :data:`ERROR` -- see - :ref:`error-handling` for discussion. - - """ - - if self.their_state is ERROR: - raise RemoteProtocolError("Can't receive data when peer state is ERROR") - try: - event = self._extract_next_receive_event() - if event not in [NEED_DATA, PAUSED]: - self._process_event(self.their_role, event) - self._receive_buffer.compress() - if event is NEED_DATA: - if len(self._receive_buffer) > self._max_incomplete_event_size: - # 431 is "Request header fields too large" which is pretty - # much the only situation where we can get here - raise RemoteProtocolError( - "Receive buffer too long", error_status_hint=431 - ) - if self._receive_buffer_closed: - # We're still trying to complete some event, but that's - # never going to happen because no more data is coming - raise RemoteProtocolError("peer unexpectedly closed connection") - return event - except BaseException as exc: - self._process_error(self.their_role) - if isinstance(exc, LocalProtocolError): - exc._reraise_as_remote_protocol_error() - else: - raise - - def send(self, event): - """Convert a high-level event into bytes that can be sent to the peer, - while updating our internal state machine. - - Args: - event: The :ref:`event ` to send. - - Returns: - If ``type(event) is ConnectionClosed``, then returns - ``None``. Otherwise, returns a :term:`bytes-like object`. - - Raises: - LocalProtocolError: - Sending this event at this time would violate our - understanding of the HTTP/1.1 protocol. - - If this method raises any exception then it also sets - :attr:`Connection.our_state` to :data:`ERROR` -- see - :ref:`error-handling` for discussion. - - """ - data_list = self.send_with_data_passthrough(event) - if data_list is None: - return None - else: - return b"".join(data_list) - - def send_with_data_passthrough(self, event): - """Identical to :meth:`send`, except that in situations where - :meth:`send` returns a single :term:`bytes-like object`, this instead - returns a list of them -- and when sending a :class:`Data` event, this - list is guaranteed to contain the exact object you passed in as - :attr:`Data.data`. See :ref:`sendfile` for discussion. - - """ - if self.our_state is ERROR: - raise LocalProtocolError("Can't send data when our state is ERROR") - try: - if type(event) is Response: - self._clean_up_response_headers_for_sending(event) - # We want to call _process_event before calling the writer, - # because if someone tries to do something invalid then this will - # give a sensible error message, while our writers all just assume - # they will only receive valid events. But, _process_event might - # change self._writer. So we have to do a little dance: - writer = self._writer - self._process_event(self.our_role, event) - if type(event) is ConnectionClosed: - return None - else: - # In any situation where writer is None, process_event should - # have raised ProtocolError - assert writer is not None - data_list = [] - writer(event, data_list.append) - return data_list - except: - self._process_error(self.our_role) - raise - - def send_failed(self): - """Notify the state machine that we failed to send the data it gave - us. - - This causes :attr:`Connection.our_state` to immediately become - :data:`ERROR` -- see :ref:`error-handling` for discussion. - - """ - self._process_error(self.our_role) - - # When sending a Response, we take responsibility for a few things: - # - # - Sometimes you MUST set Connection: close. We take care of those - # times. (You can also set it yourself if you want, and if you do then - # we'll respect that and close the connection at the right time. But you - # don't have to worry about that unless you want to.) - # - # - The user has to set Content-Length if they want it. Otherwise, for - # responses that have bodies (e.g. not HEAD), then we will automatically - # select the right mechanism for streaming a body of unknown length, - # which depends on depending on the peer's HTTP version. - # - # This function's *only* responsibility is making sure headers are set up - # right -- everything downstream just looks at the headers. There are no - # side channels. It mutates the response event in-place (but not the - # response.headers list object). - def _clean_up_response_headers_for_sending(self, response): - assert type(response) is Response - - headers = list(response.headers) - need_close = False - - # HEAD requests need some special handling: they always act like they - # have Content-Length: 0, and that's how _body_framing treats - # them. But their headers are supposed to match what we would send if - # the request was a GET. (Technically there is one deviation allowed: - # we're allowed to leave out the framing headers -- see - # https://tools.ietf.org/html/rfc7231#section-4.3.2 . But it's just as - # easy to get them right.) - method_for_choosing_headers = self._request_method - if method_for_choosing_headers == b"HEAD": - method_for_choosing_headers = b"GET" - framing_type, _ = _body_framing(method_for_choosing_headers, response) - if framing_type in ("chunked", "http/1.0"): - # This response has a body of unknown length. - # If our peer is HTTP/1.1, we use Transfer-Encoding: chunked - # If our peer is HTTP/1.0, we use no framing headers, and close the - # connection afterwards. - # - # Make sure to clear Content-Length (in principle user could have - # set both and then we ignored Content-Length b/c - # Transfer-Encoding overwrote it -- this would be naughty of them, - # but the HTTP spec says that if our peer does this then we have - # to fix it instead of erroring out, so we'll accord the user the - # same respect). - set_comma_header(headers, b"content-length", []) - if self.their_http_version is None or self.their_http_version < b"1.1": - # Either we never got a valid request and are sending back an - # error (their_http_version is None), so we assume the worst; - # or else we did get a valid HTTP/1.0 request, so we know that - # they don't understand chunked encoding. - set_comma_header(headers, b"transfer-encoding", []) - # This is actually redundant ATM, since currently we - # unconditionally disable keep-alive when talking to HTTP/1.0 - # peers. But let's be defensive just in case we add - # Connection: keep-alive support later: - if self._request_method != b"HEAD": - need_close = True - else: - set_comma_header(headers, b"transfer-encoding", ["chunked"]) - - if not self._cstate.keep_alive or need_close: - # Make sure Connection: close is set - connection = set(get_comma_header(headers, b"connection")) - connection.discard(b"keep-alive") - connection.add(b"close") - set_comma_header(headers, b"connection", sorted(connection)) - - response.headers = headers diff --git a/py3.7/lib/python3.7/site-packages/h11/_events.py b/py3.7/lib/python3.7/site-packages/h11/_events.py deleted file mode 100644 index c11d838..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_events.py +++ /dev/null @@ -1,305 +0,0 @@ -# High level events that make up HTTP/1.1 conversations. Loosely inspired by -# the corresponding events in hyper-h2: -# -# http://python-hyper.org/h2/en/stable/api.html#events -# -# Don't subclass these. Stuff will break. - -import re - -from . import _headers -from ._abnf import request_target -from ._util import bytesify, LocalProtocolError, validate - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = [ - "Request", - "InformationalResponse", - "Response", - "Data", - "EndOfMessage", - "ConnectionClosed", -] - -request_target_re = re.compile(request_target.encode("ascii")) - - -class _EventBundle(object): - _fields = [] - _defaults = {} - - def __init__(self, **kwargs): - _parsed = kwargs.pop("_parsed", False) - allowed = set(self._fields) - for kwarg in kwargs: - if kwarg not in allowed: - raise TypeError( - "unrecognized kwarg {} for {}".format( - kwarg, self.__class__.__name__ - ) - ) - required = allowed.difference(self._defaults) - for field in required: - if field not in kwargs: - raise TypeError( - "missing required kwarg {} for {}".format( - field, self.__class__.__name__ - ) - ) - self.__dict__.update(self._defaults) - self.__dict__.update(kwargs) - - # Special handling for some fields - - if "headers" in self.__dict__: - self.headers = _headers.normalize_and_validate( - self.headers, _parsed=_parsed - ) - - if not _parsed: - for field in ["method", "target", "http_version", "reason"]: - if field in self.__dict__: - self.__dict__[field] = bytesify(self.__dict__[field]) - - if "status_code" in self.__dict__: - if not isinstance(self.status_code, int): - raise LocalProtocolError("status code must be integer") - # Because IntEnum objects are instances of int, but aren't - # duck-compatible (sigh), see gh-72. - self.status_code = int(self.status_code) - - self._validate() - - def _validate(self): - pass - - def __repr__(self): - name = self.__class__.__name__ - kwarg_strs = [ - "{}={}".format(field, self.__dict__[field]) for field in self._fields - ] - kwarg_str = ", ".join(kwarg_strs) - return "{}({})".format(name, kwarg_str) - - # Useful for tests - def __eq__(self, other): - return self.__class__ == other.__class__ and self.__dict__ == other.__dict__ - - def __ne__(self, other): - return not self.__eq__(other) - - # This is an unhashable type. - __hash__ = None - - -class Request(_EventBundle): - """The beginning of an HTTP request. - - Fields: - - .. attribute:: method - - An HTTP method, e.g. ``b"GET"`` or ``b"POST"``. Always a byte - string. :term:`Bytes-like objects ` and native - strings containing only ascii characters will be automatically - converted to byte strings. - - .. attribute:: target - - The target of an HTTP request, e.g. ``b"/index.html"``, or one of the - more exotic formats described in `RFC 7320, section 5.3 - `_. Always a byte - string. :term:`Bytes-like objects ` and native - strings containing only ascii characters will be automatically - converted to byte strings. - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - """ - - _fields = ["method", "target", "headers", "http_version"] - _defaults = {"http_version": b"1.1"} - - def _validate(self): - # "A server MUST respond with a 400 (Bad Request) status code to any - # HTTP/1.1 request message that lacks a Host header field and to any - # request message that contains more than one Host header field or a - # Host header field with an invalid field-value." - # -- https://tools.ietf.org/html/rfc7230#section-5.4 - host_count = 0 - for name, value in self.headers: - if name == b"host": - host_count += 1 - if self.http_version == b"1.1" and host_count == 0: - raise LocalProtocolError("Missing mandatory Host: header") - if host_count > 1: - raise LocalProtocolError("Found multiple Host: headers") - - validate(request_target_re, self.target, "Illegal target characters") - - -class _ResponseBase(_EventBundle): - _fields = ["status_code", "headers", "http_version", "reason"] - _defaults = {"http_version": b"1.1", "reason": b""} - - -class InformationalResponse(_ResponseBase): - """An HTTP informational response. - - Fields: - - .. attribute:: status_code - - The status code of this response, as an integer. For an - :class:`InformationalResponse`, this is always in the range [100, - 200). - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for - details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - .. attribute:: reason - - The reason phrase of this response, as a byte string. For example: - ``b"OK"``, or ``b"Not Found"``. - - """ - - def _validate(self): - if not (100 <= self.status_code < 200): - raise LocalProtocolError( - "InformationalResponse status_code should be in range " - "[100, 200), not {}".format(self.status_code) - ) - - -class Response(_ResponseBase): - """The beginning of an HTTP response. - - Fields: - - .. attribute:: status_code - - The status code of this response, as an integer. For an - :class:`Response`, this is always in the range [200, - 600). - - .. attribute:: headers - - Request headers, represented as a list of (name, value) pairs. See - :ref:`the header normalization rules ` for details. - - .. attribute:: http_version - - The HTTP protocol version, represented as a byte string like - ``b"1.1"``. See :ref:`the HTTP version normalization rules - ` for details. - - .. attribute:: reason - - The reason phrase of this response, as a byte string. For example: - ``b"OK"``, or ``b"Not Found"``. - - """ - - def _validate(self): - if not (200 <= self.status_code < 600): - raise LocalProtocolError( - "Response status_code should be in range [200, 600), not {}".format( - self.status_code - ) - ) - - -class Data(_EventBundle): - """Part of an HTTP message body. - - Fields: - - .. attribute:: data - - A :term:`bytes-like object` containing part of a message body. Or, if - using the ``combine=False`` argument to :meth:`Connection.send`, then - any object that your socket writing code knows what to do with, and for - which calling :func:`len` returns the number of bytes that will be - written -- see :ref:`sendfile` for details. - - .. attribute:: chunk_start - - A marker that indicates whether this data object is from the start of a - chunked transfer encoding chunk. This field is ignored when when a Data - event is provided to :meth:`Connection.send`: it is only valid on - events emitted from :meth:`Connection.next_event`. You probably - shouldn't use this attribute at all; see - :ref:`chunk-delimiters-are-bad` for details. - - .. attribute:: chunk_end - - A marker that indicates whether this data object is the last for a - given chunked transfer encoding chunk. This field is ignored when when - a Data event is provided to :meth:`Connection.send`: it is only valid - on events emitted from :meth:`Connection.next_event`. You probably - shouldn't use this attribute at all; see - :ref:`chunk-delimiters-are-bad` for details. - - """ - - _fields = ["data", "chunk_start", "chunk_end"] - _defaults = {"chunk_start": False, "chunk_end": False} - - -# XX FIXME: "A recipient MUST ignore (or consider as an error) any fields that -# are forbidden to be sent in a trailer, since processing them as if they were -# present in the header section might bypass external security filters." -# https://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7230.html#chunked.trailer.part -# Unfortunately, the list of forbidden fields is long and vague :-/ -class EndOfMessage(_EventBundle): - """The end of an HTTP message. - - Fields: - - .. attribute:: headers - - Default value: ``[]`` - - Any trailing headers attached to this message, represented as a list of - (name, value) pairs. See :ref:`the header normalization rules - ` for details. - - Must be empty unless ``Transfer-Encoding: chunked`` is in use. - - """ - - _fields = ["headers"] - _defaults = {"headers": []} - - -class ConnectionClosed(_EventBundle): - """This event indicates that the sender has closed their outgoing - connection. - - Note that this does not necessarily mean that they can't *receive* further - data, because TCP connections are composed to two one-way channels which - can be closed independently. See :ref:`closing` for details. - - No fields. - """ - - pass diff --git a/py3.7/lib/python3.7/site-packages/h11/_headers.py b/py3.7/lib/python3.7/site-packages/h11/_headers.py deleted file mode 100644 index 878f63c..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_headers.py +++ /dev/null @@ -1,171 +0,0 @@ -import re - -from ._abnf import field_name, field_value -from ._util import bytesify, LocalProtocolError, validate - -# Facts -# ----- -# -# Headers are: -# keys: case-insensitive ascii -# values: mixture of ascii and raw bytes -# -# "Historically, HTTP has allowed field content with text in the ISO-8859-1 -# charset [ISO-8859-1], supporting other charsets only through use of -# [RFC2047] encoding. In practice, most HTTP header field values use only a -# subset of the US-ASCII charset [USASCII]. Newly defined header fields SHOULD -# limit their field values to US-ASCII octets. A recipient SHOULD treat other -# octets in field content (obs-text) as opaque data." -# And it deprecates all non-ascii values -# -# Leading/trailing whitespace in header names is forbidden -# -# Values get leading/trailing whitespace stripped -# -# Content-Disposition actually needs to contain unicode semantically; to -# accomplish this it has a terrifically weird way of encoding the filename -# itself as ascii (and even this still has lots of cross-browser -# incompatibilities) -# -# Order is important: -# "a proxy MUST NOT change the order of these field values when forwarding a -# message" -# (and there are several headers where the order indicates a preference) -# -# Multiple occurences of the same header: -# "A sender MUST NOT generate multiple header fields with the same field name -# in a message unless either the entire field value for that header field is -# defined as a comma-separated list [or the header is Set-Cookie which gets a -# special exception]" - RFC 7230. (cookies are in RFC 6265) -# -# So every header aside from Set-Cookie can be merged by b", ".join if it -# occurs repeatedly. But, of course, they can't necessarily be split by -# .split(b","), because quoting. -# -# Given all this mess (case insensitive, duplicates allowed, order is -# important, ...), there doesn't appear to be any standard way to handle -# headers in Python -- they're almost like dicts, but... actually just -# aren't. For now we punt and just use a super simple representation: headers -# are a list of pairs -# -# [(name1, value1), (name2, value2), ...] -# -# where all entries are bytestrings, names are lowercase and have no -# leading/trailing whitespace, and values are bytestrings with no -# leading/trailing whitespace. Searching and updating are done via naive O(n) -# methods. -# -# Maybe a dict-of-lists would be better? - -_content_length_re = re.compile(br"[0-9]+") -_field_name_re = re.compile(field_name.encode("ascii")) -_field_value_re = re.compile(field_value.encode("ascii")) - - -def normalize_and_validate(headers, _parsed=False): - new_headers = [] - saw_content_length = False - saw_transfer_encoding = False - for name, value in headers: - # For headers coming out of the parser, we can safely skip some steps, - # because it always returns bytes and has already run these regexes - # over the data: - if not _parsed: - name = bytesify(name) - value = bytesify(value) - validate(_field_name_re, name, "Illegal header name {!r}", name) - validate(_field_value_re, value, "Illegal header value {!r}", value) - name = name.lower() - if name == b"content-length": - if saw_content_length: - raise LocalProtocolError("multiple Content-Length headers") - validate(_content_length_re, value, "bad Content-Length") - saw_content_length = True - if name == b"transfer-encoding": - # "A server that receives a request message with a transfer coding - # it does not understand SHOULD respond with 501 (Not - # Implemented)." - # https://tools.ietf.org/html/rfc7230#section-3.3.1 - if saw_transfer_encoding: - raise LocalProtocolError( - "multiple Transfer-Encoding headers", error_status_hint=501 - ) - # "All transfer-coding names are case-insensitive" - # -- https://tools.ietf.org/html/rfc7230#section-4 - value = value.lower() - if value != b"chunked": - raise LocalProtocolError( - "Only Transfer-Encoding: chunked is supported", - error_status_hint=501, - ) - saw_transfer_encoding = True - new_headers.append((name, value)) - return new_headers - - -def get_comma_header(headers, name): - # Should only be used for headers whose value is a list of - # comma-separated, case-insensitive values. - # - # The header name `name` is expected to be lower-case bytes. - # - # Connection: meets these criteria (including cast insensitivity). - # - # Content-Length: technically is just a single value (1*DIGIT), but the - # standard makes reference to implementations that do multiple values, and - # using this doesn't hurt. Ditto, case insensitivity doesn't things either - # way. - # - # Transfer-Encoding: is more complex (allows for quoted strings), so - # splitting on , is actually wrong. For example, this is legal: - # - # Transfer-Encoding: foo; options="1,2", chunked - # - # and should be parsed as - # - # foo; options="1,2" - # chunked - # - # but this naive function will parse it as - # - # foo; options="1 - # 2" - # chunked - # - # However, this is okay because the only thing we are going to do with - # any Transfer-Encoding is reject ones that aren't just "chunked", so - # both of these will be treated the same anyway. - # - # Expect: the only legal value is the literal string - # "100-continue". Splitting on commas is harmless. Case insensitive. - # - out = [] - for found_name, found_raw_value in headers: - if found_name == name: - found_raw_value = found_raw_value.lower() - for found_split_value in found_raw_value.split(b","): - found_split_value = found_split_value.strip() - if found_split_value: - out.append(found_split_value) - return out - - -def set_comma_header(headers, name, new_values): - # The header name `name` is expected to be lower-case bytes. - new_headers = [] - for found_name, found_raw_value in headers: - if found_name != name: - new_headers.append((found_name, found_raw_value)) - for new_value in new_values: - new_headers.append((name, new_value)) - headers[:] = normalize_and_validate(new_headers) - - -def has_expect_100_continue(request): - # https://tools.ietf.org/html/rfc7231#section-5.1.1 - # "A server that receives a 100-continue expectation in an HTTP/1.0 request - # MUST ignore that expectation." - if request.http_version < b"1.1": - return False - expect = get_comma_header(request.headers, b"expect") - return b"100-continue" in expect diff --git a/py3.7/lib/python3.7/site-packages/h11/_readers.py b/py3.7/lib/python3.7/site-packages/h11/_readers.py deleted file mode 100644 index 752cac0..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_readers.py +++ /dev/null @@ -1,217 +0,0 @@ -# Code to read HTTP data -# -# Strategy: each reader is a callable which takes a ReceiveBuffer object, and -# either: -# 1) consumes some of it and returns an Event -# 2) raises a LocalProtocolError (for consistency -- e.g. we call validate() -# and it might raise a LocalProtocolError, so simpler just to always use -# this) -# 3) returns None, meaning "I need more data" -# -# If they have a .read_eof attribute, then this will be called if an EOF is -# received -- but this is optional. Either way, the actual ConnectionClosed -# event will be generated afterwards. -# -# READERS is a dict describing how to pick a reader. It maps states to either: -# - a reader -# - or, for body readers, a dict of per-framing reader factories - -import re - -from ._abnf import chunk_header, header_field, request_line, status_line -from ._events import * -from ._state import * -from ._util import LocalProtocolError, RemoteProtocolError, validate - -__all__ = ["READERS"] - -header_field_re = re.compile(header_field.encode("ascii")) - -# Remember that this has to run in O(n) time -- so e.g. the bytearray cast is -# critical. -obs_fold_re = re.compile(br"[ \t]+") - - -def _obsolete_line_fold(lines): - it = iter(lines) - last = None - for line in it: - match = obs_fold_re.match(line) - if match: - if last is None: - raise LocalProtocolError("continuation line at start of headers") - if not isinstance(last, bytearray): - last = bytearray(last) - last += b" " - last += line[match.end() :] - else: - if last is not None: - yield last - last = line - if last is not None: - yield last - - -def _decode_header_lines(lines): - for line in _obsolete_line_fold(lines): - # _obsolete_line_fold yields either bytearray or bytes objects. On - # Python 3, validate() takes either and returns matches as bytes. But - # on Python 2, validate can return matches as bytearrays, so we have - # to explicitly cast back. - matches = validate(header_field_re, bytes(line)) - yield (matches["field_name"], matches["field_value"]) - - -request_line_re = re.compile(request_line.encode("ascii")) - - -def maybe_read_from_IDLE_client(buf): - lines = buf.maybe_extract_lines() - if lines is None: - return None - if not lines: - raise LocalProtocolError("no request line received") - matches = validate(request_line_re, lines[0]) - return Request( - headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches - ) - - -status_line_re = re.compile(status_line.encode("ascii")) - - -def maybe_read_from_SEND_RESPONSE_server(buf): - lines = buf.maybe_extract_lines() - if lines is None: - return None - if not lines: - raise LocalProtocolError("no response line received") - matches = validate(status_line_re, lines[0]) - # Tolerate missing reason phrases - if matches["reason"] is None: - matches["reason"] = b"" - status_code = matches["status_code"] = int(matches["status_code"]) - class_ = InformationalResponse if status_code < 200 else Response - return class_( - headers=list(_decode_header_lines(lines[1:])), _parsed=True, **matches - ) - - -class ContentLengthReader: - def __init__(self, length): - self._length = length - self._remaining = length - - def __call__(self, buf): - if self._remaining == 0: - return EndOfMessage() - data = buf.maybe_extract_at_most(self._remaining) - if data is None: - return None - self._remaining -= len(data) - return Data(data=data) - - def read_eof(self): - raise RemoteProtocolError( - "peer closed connection without sending complete message body " - "(received {} bytes, expected {})".format( - self._length - self._remaining, self._length - ) - ) - - -chunk_header_re = re.compile(chunk_header.encode("ascii")) - - -class ChunkedReader(object): - def __init__(self): - self._bytes_in_chunk = 0 - # After reading a chunk, we have to throw away the trailing \r\n; if - # this is >0 then we discard that many bytes before resuming regular - # de-chunkification. - self._bytes_to_discard = 0 - self._reading_trailer = False - - def __call__(self, buf): - if self._reading_trailer: - lines = buf.maybe_extract_lines() - if lines is None: - return None - return EndOfMessage(headers=list(_decode_header_lines(lines))) - if self._bytes_to_discard > 0: - data = buf.maybe_extract_at_most(self._bytes_to_discard) - if data is None: - return None - self._bytes_to_discard -= len(data) - if self._bytes_to_discard > 0: - return None - # else, fall through and read some more - assert self._bytes_to_discard == 0 - if self._bytes_in_chunk == 0: - # We need to refill our chunk count - chunk_header = buf.maybe_extract_until_next(b"\r\n") - if chunk_header is None: - return None - matches = validate(chunk_header_re, chunk_header) - # XX FIXME: we discard chunk extensions. Does anyone care? - # We convert to bytes because Python 2's `int()` function doesn't - # work properly on bytearray objects. - self._bytes_in_chunk = int(bytes(matches["chunk_size"]), base=16) - if self._bytes_in_chunk == 0: - self._reading_trailer = True - return self(buf) - chunk_start = True - else: - chunk_start = False - assert self._bytes_in_chunk > 0 - data = buf.maybe_extract_at_most(self._bytes_in_chunk) - if data is None: - return None - self._bytes_in_chunk -= len(data) - if self._bytes_in_chunk == 0: - self._bytes_to_discard = 2 - chunk_end = True - else: - chunk_end = False - return Data(data=data, chunk_start=chunk_start, chunk_end=chunk_end) - - def read_eof(self): - raise RemoteProtocolError( - "peer closed connection without sending complete message body " - "(incomplete chunked read)" - ) - - -class Http10Reader(object): - def __call__(self, buf): - data = buf.maybe_extract_at_most(999999999) - if data is None: - return None - return Data(data=data) - - def read_eof(self): - return EndOfMessage() - - -def expect_nothing(buf): - if buf: - raise LocalProtocolError("Got data when expecting EOF") - return None - - -READERS = { - (CLIENT, IDLE): maybe_read_from_IDLE_client, - (SERVER, IDLE): maybe_read_from_SEND_RESPONSE_server, - (SERVER, SEND_RESPONSE): maybe_read_from_SEND_RESPONSE_server, - (CLIENT, DONE): expect_nothing, - (CLIENT, MUST_CLOSE): expect_nothing, - (CLIENT, CLOSED): expect_nothing, - (SERVER, DONE): expect_nothing, - (SERVER, MUST_CLOSE): expect_nothing, - (SERVER, CLOSED): expect_nothing, - SEND_BODY: { - "chunked": ChunkedReader, - "content-length": ContentLengthReader, - "http/1.0": Http10Reader, - }, -} diff --git a/py3.7/lib/python3.7/site-packages/h11/_receivebuffer.py b/py3.7/lib/python3.7/site-packages/h11/_receivebuffer.py deleted file mode 100644 index c56749a..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_receivebuffer.py +++ /dev/null @@ -1,112 +0,0 @@ -import sys - -__all__ = ["ReceiveBuffer"] - - -# Operations we want to support: -# - find next \r\n or \r\n\r\n, or wait until there is one -# - read at-most-N bytes -# Goals: -# - on average, do this fast -# - worst case, do this in O(n) where n is the number of bytes processed -# Plan: -# - store bytearray, offset, how far we've searched for a separator token -# - use the how-far-we've-searched data to avoid rescanning -# - while doing a stream of uninterrupted processing, advance offset instead -# of constantly copying -# WARNING: -# - I haven't benchmarked or profiled any of this yet. -# -# Note that starting in Python 3.4, deleting the initial n bytes from a -# bytearray is amortized O(n), thanks to some excellent work by Antoine -# Martin: -# -# https://bugs.python.org/issue19087 -# -# This means that if we only supported 3.4+, we could get rid of the code here -# involving self._start and self.compress, because it's doing exactly the same -# thing that bytearray now does internally. -# -# BUT unfortunately, we still support 2.7, and reading short segments out of a -# long buffer MUST be O(bytes read) to avoid DoS issues, so we can't actually -# delete this code. Yet: -# -# https://pythonclock.org/ -# -# (Two things to double-check first though: make sure PyPy also has the -# optimization, and benchmark to make sure it's a win, since we do have a -# slightly clever thing where we delay calling compress() until we've -# processed a whole event, which could in theory be slightly more efficient -# than the internal bytearray support.) -class ReceiveBuffer(object): - def __init__(self): - self._data = bytearray() - # These are both absolute offsets into self._data: - self._start = 0 - self._looked_at = 0 - self._looked_for = b"" - - def __bool__(self): - return bool(len(self)) - - # for @property unprocessed_data - def __bytes__(self): - return bytes(self._data[self._start :]) - - if sys.version_info[0] < 3: # version specific: Python 2 - __str__ = __bytes__ - __nonzero__ = __bool__ - - def __len__(self): - return len(self._data) - self._start - - def compress(self): - # Heuristic: only compress if it lets us reduce size by a factor - # of 2 - if self._start > len(self._data) // 2: - del self._data[: self._start] - self._looked_at -= self._start - self._start -= self._start - - def __iadd__(self, byteslike): - self._data += byteslike - return self - - def maybe_extract_at_most(self, count): - out = self._data[self._start : self._start + count] - if not out: - return None - self._start += len(out) - return out - - def maybe_extract_until_next(self, needle): - # Returns extracted bytes on success (advancing offset), or None on - # failure - if self._looked_for == needle: - search_start = max(self._start, self._looked_at - len(needle) + 1) - else: - search_start = self._start - offset = self._data.find(needle, search_start) - if offset == -1: - self._looked_at = len(self._data) - self._looked_for = needle - return None - new_start = offset + len(needle) - out = self._data[self._start : new_start] - self._start = new_start - return out - - # HTTP/1.1 has a number of constructs where you keep reading lines until - # you see a blank one. This does that, and then returns the lines. - def maybe_extract_lines(self): - if self._data[self._start : self._start + 2] == b"\r\n": - self._start += 2 - return [] - else: - data = self.maybe_extract_until_next(b"\r\n\r\n") - if data is None: - return None - lines = data.split(b"\r\n") - assert lines[-2] == lines[-1] == b"" - del lines[-2:] - return lines diff --git a/py3.7/lib/python3.7/site-packages/h11/_state.py b/py3.7/lib/python3.7/site-packages/h11/_state.py deleted file mode 100644 index 70a5e04..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_state.py +++ /dev/null @@ -1,307 +0,0 @@ -################################################################ -# The core state machine -################################################################ -# -# Rule 1: everything that affects the state machine and state transitions must -# live here in this file. As much as possible goes into the table-based -# representation, but for the bits that don't quite fit, the actual code and -# state must nonetheless live here. -# -# Rule 2: this file does not know about what role we're playing; it only knows -# about HTTP request/response cycles in the abstract. This ensures that we -# don't cheat and apply different rules to local and remote parties. -# -# -# Theory of operation -# =================== -# -# Possibly the simplest way to think about this is that we actually have 5 -# different state machines here. Yes, 5. These are: -# -# 1) The client state, with its complicated automaton (see the docs) -# 2) The server state, with its complicated automaton (see the docs) -# 3) The keep-alive state, with possible states {True, False} -# 4) The SWITCH_CONNECT state, with possible states {False, True} -# 5) The SWITCH_UPGRADE state, with possible states {False, True} -# -# For (3)-(5), the first state listed is the initial state. -# -# (1)-(3) are stored explicitly in member variables. The last -# two are stored implicitly in the pending_switch_proposals set as: -# (state of 4) == (_SWITCH_CONNECT in pending_switch_proposals) -# (state of 5) == (_SWITCH_UPGRADE in pending_switch_proposals) -# -# And each of these machines has two different kinds of transitions: -# -# a) Event-triggered -# b) State-triggered -# -# Event triggered is the obvious thing that you'd think it is: some event -# happens, and if it's the right event at the right time then a transition -# happens. But there are somewhat complicated rules for which machines can -# "see" which events. (As a rule of thumb, if a machine "sees" an event, this -# means two things: the event can affect the machine, and if the machine is -# not in a state where it expects that event then it's an error.) These rules -# are: -# -# 1) The client machine sees all h11.events objects emitted by the client. -# -# 2) The server machine sees all h11.events objects emitted by the server. -# -# It also sees the client's Request event. -# -# And sometimes, server events are annotated with a _SWITCH_* event. For -# example, we can have a (Response, _SWITCH_CONNECT) event, which is -# different from a regular Response event. -# -# 3) The keep-alive machine sees the process_keep_alive_disabled() event -# (which is derived from Request/Response events), and this event -# transitions it from True -> False, or from False -> False. There's no way -# to transition back. -# -# 4&5) The _SWITCH_* machines transition from False->True when we get a -# Request that proposes the relevant type of switch (via -# process_client_switch_proposals), and they go from True->False when we -# get a Response that has no _SWITCH_* annotation. -# -# So that's event-triggered transitions. -# -# State-triggered transitions are less standard. What they do here is couple -# the machines together. The way this works is, when certain *joint* -# configurations of states are achieved, then we automatically transition to a -# new *joint* state. So, for example, if we're ever in a joint state with -# -# client: DONE -# keep-alive: False -# -# then the client state immediately transitions to: -# -# client: MUST_CLOSE -# -# This is fundamentally different from an event-based transition, because it -# doesn't matter how we arrived at the {client: DONE, keep-alive: False} state -# -- maybe the client transitioned SEND_BODY -> DONE, or keep-alive -# transitioned True -> False. Either way, once this precondition is satisfied, -# this transition is immediately triggered. -# -# What if two conflicting state-based transitions get enabled at the same -# time? In practice there's only one case where this arises (client DONE -> -# MIGHT_SWITCH_PROTOCOL versus DONE -> MUST_CLOSE), and we resolve it by -# explicitly prioritizing the DONE -> MIGHT_SWITCH_PROTOCOL transition. -# -# Implementation -# -------------- -# -# The event-triggered transitions for the server and client machines are all -# stored explicitly in a table. Ditto for the state-triggered transitions that -# involve just the server and client state. -# -# The transitions for the other machines, and the state-triggered transitions -# that involve the other machines, are written out as explicit Python code. -# -# It'd be nice if there were some cleaner way to do all this. This isn't -# *too* terrible, but I feel like it could probably be better. -# -# WARNING -# ------- -# -# The script that generates the state machine diagrams for the docs knows how -# to read out the EVENT_TRIGGERED_TRANSITIONS and STATE_TRIGGERED_TRANSITIONS -# tables. But it can't automatically read the transitions that are written -# directly in Python code. So if you touch those, you need to also update the -# script to keep it in sync! - -from ._events import * -from ._util import LocalProtocolError, make_sentinel - -# Everything in __all__ gets re-exported as part of the h11 public API. -__all__ = [ - "CLIENT", - "SERVER", - "IDLE", - "SEND_RESPONSE", - "SEND_BODY", - "DONE", - "MUST_CLOSE", - "CLOSED", - "MIGHT_SWITCH_PROTOCOL", - "SWITCHED_PROTOCOL", - "ERROR", -] - -CLIENT = make_sentinel("CLIENT") -SERVER = make_sentinel("SERVER") - -# States -IDLE = make_sentinel("IDLE") -SEND_RESPONSE = make_sentinel("SEND_RESPONSE") -SEND_BODY = make_sentinel("SEND_BODY") -DONE = make_sentinel("DONE") -MUST_CLOSE = make_sentinel("MUST_CLOSE") -CLOSED = make_sentinel("CLOSED") -ERROR = make_sentinel("ERROR") - -# Switch types -MIGHT_SWITCH_PROTOCOL = make_sentinel("MIGHT_SWITCH_PROTOCOL") -SWITCHED_PROTOCOL = make_sentinel("SWITCHED_PROTOCOL") - -_SWITCH_UPGRADE = make_sentinel("_SWITCH_UPGRADE") -_SWITCH_CONNECT = make_sentinel("_SWITCH_CONNECT") - -EVENT_TRIGGERED_TRANSITIONS = { - CLIENT: { - IDLE: {Request: SEND_BODY, ConnectionClosed: CLOSED}, - SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, - DONE: {ConnectionClosed: CLOSED}, - MUST_CLOSE: {ConnectionClosed: CLOSED}, - CLOSED: {ConnectionClosed: CLOSED}, - MIGHT_SWITCH_PROTOCOL: {}, - SWITCHED_PROTOCOL: {}, - ERROR: {}, - }, - SERVER: { - IDLE: { - ConnectionClosed: CLOSED, - Response: SEND_BODY, - # Special case: server sees client Request events, in this form - (Request, CLIENT): SEND_RESPONSE, - }, - SEND_RESPONSE: { - InformationalResponse: SEND_RESPONSE, - Response: SEND_BODY, - (InformationalResponse, _SWITCH_UPGRADE): SWITCHED_PROTOCOL, - (Response, _SWITCH_CONNECT): SWITCHED_PROTOCOL, - }, - SEND_BODY: {Data: SEND_BODY, EndOfMessage: DONE}, - DONE: {ConnectionClosed: CLOSED}, - MUST_CLOSE: {ConnectionClosed: CLOSED}, - CLOSED: {ConnectionClosed: CLOSED}, - SWITCHED_PROTOCOL: {}, - ERROR: {}, - }, -} - -# NB: there are also some special-case state-triggered transitions hard-coded -# into _fire_state_triggered_transitions below. -STATE_TRIGGERED_TRANSITIONS = { - # (Client state, Server state) -> new states - # Protocol negotiation - (MIGHT_SWITCH_PROTOCOL, SWITCHED_PROTOCOL): {CLIENT: SWITCHED_PROTOCOL}, - # Socket shutdown - (CLOSED, DONE): {SERVER: MUST_CLOSE}, - (CLOSED, IDLE): {SERVER: MUST_CLOSE}, - (ERROR, DONE): {SERVER: MUST_CLOSE}, - (DONE, CLOSED): {CLIENT: MUST_CLOSE}, - (IDLE, CLOSED): {CLIENT: MUST_CLOSE}, - (DONE, ERROR): {CLIENT: MUST_CLOSE}, -} - - -class ConnectionState(object): - def __init__(self): - # Extra bits of state that don't quite fit into the state model. - - # If this is False then it enables the automatic DONE -> MUST_CLOSE - # transition. Don't set this directly; call .keep_alive_disabled() - self.keep_alive = True - - # This is a subset of {UPGRADE, CONNECT}, containing the proposals - # made by the client for switching protocols. - self.pending_switch_proposals = set() - - self.states = {CLIENT: IDLE, SERVER: IDLE} - - def process_error(self, role): - self.states[role] = ERROR - self._fire_state_triggered_transitions() - - def process_keep_alive_disabled(self): - self.keep_alive = False - self._fire_state_triggered_transitions() - - def process_client_switch_proposal(self, switch_event): - self.pending_switch_proposals.add(switch_event) - self._fire_state_triggered_transitions() - - def process_event(self, role, event_type, server_switch_event=None): - if server_switch_event is not None: - assert role is SERVER - if server_switch_event not in self.pending_switch_proposals: - raise LocalProtocolError( - "Received server {} event without a pending proposal".format( - server_switch_event - ) - ) - event_type = (event_type, server_switch_event) - if server_switch_event is None and event_type is Response: - self.pending_switch_proposals = set() - self._fire_event_triggered_transitions(role, event_type) - # Special case: the server state does get to see Request - # events. - if event_type is Request: - assert role is CLIENT - self._fire_event_triggered_transitions(SERVER, (Request, CLIENT)) - self._fire_state_triggered_transitions() - - def _fire_event_triggered_transitions(self, role, event_type): - state = self.states[role] - try: - new_state = EVENT_TRIGGERED_TRANSITIONS[role][state][event_type] - except KeyError: - raise LocalProtocolError( - "can't handle event type {} when role={} and state={}".format( - event_type.__name__, role, self.states[role] - ) - ) - self.states[role] = new_state - - def _fire_state_triggered_transitions(self): - # We apply these rules repeatedly until converging on a fixed point - while True: - start_states = dict(self.states) - - # It could happen that both these special-case transitions are - # enabled at the same time: - # - # DONE -> MIGHT_SWITCH_PROTOCOL - # DONE -> MUST_CLOSE - # - # For example, this will always be true of a HTTP/1.0 client - # requesting CONNECT. If this happens, the protocol switch takes - # priority. From there the client will either go to - # SWITCHED_PROTOCOL, in which case it's none of our business when - # they close the connection, or else the server will deny the - # request, in which case the client will go back to DONE and then - # from there to MUST_CLOSE. - if self.pending_switch_proposals: - if self.states[CLIENT] is DONE: - self.states[CLIENT] = MIGHT_SWITCH_PROTOCOL - - if not self.pending_switch_proposals: - if self.states[CLIENT] is MIGHT_SWITCH_PROTOCOL: - self.states[CLIENT] = DONE - - if not self.keep_alive: - for role in (CLIENT, SERVER): - if self.states[role] is DONE: - self.states[role] = MUST_CLOSE - - # Tabular state-triggered transitions - joint_state = (self.states[CLIENT], self.states[SERVER]) - changes = STATE_TRIGGERED_TRANSITIONS.get(joint_state, {}) - self.states.update(changes) - - if self.states == start_states: - # Fixed point reached - return - - def start_next_cycle(self): - if self.states != {CLIENT: DONE, SERVER: DONE}: - raise LocalProtocolError( - "not in a reusable state. self.states={}".format(self.states) - ) - # Can't reach DONE/DONE with any of these active, but still, let's be - # sure. - assert self.keep_alive - assert not self.pending_switch_proposals - self.states = {CLIENT: IDLE, SERVER: IDLE} diff --git a/py3.7/lib/python3.7/site-packages/h11/_util.py b/py3.7/lib/python3.7/site-packages/h11/_util.py deleted file mode 100644 index 0a2c28e..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_util.py +++ /dev/null @@ -1,142 +0,0 @@ -import re -import sys - -__all__ = [ - "ProtocolError", - "LocalProtocolError", - "RemoteProtocolError", - "validate", - "make_sentinel", - "bytesify", -] - - -class ProtocolError(Exception): - """Exception indicating a violation of the HTTP/1.1 protocol. - - This as an abstract base class, with two concrete base classes: - :exc:`LocalProtocolError`, which indicates that you tried to do something - that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which - indicates that the remote peer tried to do something that HTTP/1.1 says is - illegal. See :ref:`error-handling` for details. - - In addition to the normal :exc:`Exception` features, it has one attribute: - - .. attribute:: error_status_hint - - This gives a suggestion as to what status code a server might use if - this error occurred as part of a request. - - For a :exc:`RemoteProtocolError`, this is useful as a suggestion for - how you might want to respond to a misbehaving peer, if you're - implementing a server. - - For a :exc:`LocalProtocolError`, this can be taken as a suggestion for - how your peer might have responded to *you* if h11 had allowed you to - continue. - - The default is 400 Bad Request, a generic catch-all for protocol - violations. - - """ - - def __init__(self, msg, error_status_hint=400): - if type(self) is ProtocolError: - raise TypeError("tried to directly instantiate ProtocolError") - Exception.__init__(self, msg) - self.error_status_hint = error_status_hint - - -# Strategy: there are a number of public APIs where a LocalProtocolError can -# be raised (send(), all the different event constructors, ...), and only one -# public API where RemoteProtocolError can be raised -# (receive_data()). Therefore we always raise LocalProtocolError internally, -# and then receive_data will translate this into a RemoteProtocolError. -# -# Internally: -# LocalProtocolError is the generic "ProtocolError". -# Externally: -# LocalProtocolError is for local errors and RemoteProtocolError is for -# remote errors. -class LocalProtocolError(ProtocolError): - def _reraise_as_remote_protocol_error(self): - # After catching a LocalProtocolError, use this method to re-raise it - # as a RemoteProtocolError. This method must be called from inside an - # except: block. - # - # An easy way to get an equivalent RemoteProtocolError is just to - # modify 'self' in place. - self.__class__ = RemoteProtocolError - # But the re-raising is somewhat non-trivial -- you might think that - # now that we've modified the in-flight exception object, that just - # doing 'raise' to re-raise it would be enough. But it turns out that - # this doesn't work, because Python tracks the exception type - # (exc_info[0]) separately from the exception object (exc_info[1]), - # and we only modified the latter. So we really do need to re-raise - # the new type explicitly. - if sys.version_info[0] >= 3: - # On py3, the traceback is part of the exception object, so our - # in-place modification preserved it and we can just re-raise: - raise self - else: - # On py2, preserving the traceback requires 3-argument - # raise... but on py3 this is a syntax error, so we have to hide - # it inside an exec - exec("raise RemoteProtocolError, self, sys.exc_info()[2]") - - -class RemoteProtocolError(ProtocolError): - pass - - -try: - _fullmatch = type(re.compile("")).fullmatch -except AttributeError: - - def _fullmatch(regex, data): # version specific: Python < 3.4 - match = regex.match(data) - if match and match.end() != len(data): - match = None - return match - - -def validate(regex, data, msg="malformed data", *format_args): - match = _fullmatch(regex, data) - if not match: - if format_args: - msg = msg.format(*format_args) - raise LocalProtocolError(msg) - return match.groupdict() - - -# Sentinel values -# -# - Inherit identity-based comparison and hashing from object -# - Have a nice repr -# - Have a *bonus property*: type(sentinel) is sentinel -# -# The bonus property is useful if you want to take the return value from -# next_event() and do some sort of dispatch based on type(event). -class _SentinelBase(type): - def __repr__(self): - return self.__name__ - - -def make_sentinel(name): - cls = _SentinelBase(name, (_SentinelBase,), {}) - cls.__class__ = cls - return cls - - -# Used for methods, request targets, HTTP versions, header names, and header -# values. Accepts ascii-strings, or bytes/bytearray/memoryview/..., and always -# returns bytes. -def bytesify(s): - # Fast-path: - if type(s) is bytes: - return s - if isinstance(s, str): - s = s.encode("ascii") - if isinstance(s, int): - raise TypeError("expected bytes-like object, not int") - return bytes(s) diff --git a/py3.7/lib/python3.7/site-packages/h11/_version.py b/py3.7/lib/python3.7/site-packages/h11/_version.py deleted file mode 100644 index 2944df8..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_version.py +++ /dev/null @@ -1,16 +0,0 @@ -# This file must be kept very simple, because it is consumed from several -# places -- it is imported by h11/__init__.py, execfile'd by setup.py, etc. - -# We use a simple scheme: -# 1.0.0 -> 1.0.0+dev -> 1.1.0 -> 1.1.0+dev -# where the +dev versions are never released into the wild, they're just what -# we stick into the VCS in between releases. -# -# This is compatible with PEP 440: -# http://legacy.python.org/dev/peps/pep-0440/ -# via the use of the "local suffix" "+dev", which is disallowed on index -# servers and causes 1.0.0+dev to sort after plain 1.0.0, which is what we -# want. (Contrast with the special suffix 1.0.0.dev, which sorts *before* -# 1.0.0.) - -__version__ = "0.9.0" diff --git a/py3.7/lib/python3.7/site-packages/h11/_writers.py b/py3.7/lib/python3.7/site-packages/h11/_writers.py deleted file mode 100644 index 6a41100..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/_writers.py +++ /dev/null @@ -1,142 +0,0 @@ -# Code to read HTTP data -# -# Strategy: each writer takes an event + a write-some-bytes function, which is -# calls. -# -# WRITERS is a dict describing how to pick a reader. It maps states to either: -# - a writer -# - or, for body writers, a dict of framin-dependent writer factories - -import sys - -from ._events import Data, EndOfMessage -from ._state import CLIENT, IDLE, SEND_BODY, SEND_RESPONSE, SERVER -from ._util import LocalProtocolError - -__all__ = ["WRITERS"] - -# Equivalent of bstr % values, that works on python 3.x for x < 5 -if (3, 0) <= sys.version_info < (3, 5): - - def bytesmod(bstr, values): - decoded_values = [] - for value in values: - if isinstance(value, bytes): - decoded_values.append(value.decode("ascii")) - else: - decoded_values.append(value) - return (bstr.decode("ascii") % tuple(decoded_values)).encode("ascii") - - -else: - - def bytesmod(bstr, values): - return bstr % values - - -def write_headers(headers, write): - # "Since the Host field-value is critical information for handling a - # request, a user agent SHOULD generate Host as the first header field - # following the request-line." - RFC 7230 - for name, value in headers: - if name == b"host": - write(bytesmod(b"%s: %s\r\n", (name, value))) - for name, value in headers: - if name != b"host": - write(bytesmod(b"%s: %s\r\n", (name, value))) - write(b"\r\n") - - -def write_request(request, write): - if request.http_version != b"1.1": - raise LocalProtocolError("I only send HTTP/1.1") - write(bytesmod(b"%s %s HTTP/1.1\r\n", (request.method, request.target))) - write_headers(request.headers, write) - - -# Shared between InformationalResponse and Response -def write_any_response(response, write): - if response.http_version != b"1.1": - raise LocalProtocolError("I only send HTTP/1.1") - status_bytes = str(response.status_code).encode("ascii") - # We don't bother sending ascii status messages like "OK"; they're - # optional and ignored by the protocol. (But the space after the numeric - # status code is mandatory.) - # - # XX FIXME: could at least make an effort to pull out the status message - # from stdlib's http.HTTPStatus table. Or maybe just steal their enums - # (either by import or copy/paste). We already accept them as status codes - # since they're of type IntEnum < int. - write(bytesmod(b"HTTP/1.1 %s %s\r\n", (status_bytes, response.reason))) - write_headers(response.headers, write) - - -class BodyWriter(object): - def __call__(self, event, write): - if type(event) is Data: - self.send_data(event.data, write) - elif type(event) is EndOfMessage: - self.send_eom(event.headers, write) - else: # pragma: no cover - assert False - - -# -# These are all careful not to do anything to 'data' except call len(data) and -# write(data). This allows us to transparently pass-through funny objects, -# like placeholder objects referring to files on disk that will be sent via -# sendfile(2). -# -class ContentLengthWriter(BodyWriter): - def __init__(self, length): - self._length = length - - def send_data(self, data, write): - self._length -= len(data) - if self._length < 0: - raise LocalProtocolError("Too much data for declared Content-Length") - write(data) - - def send_eom(self, headers, write): - if self._length != 0: - raise LocalProtocolError("Too little data for declared Content-Length") - if headers: - raise LocalProtocolError("Content-Length and trailers don't mix") - - -class ChunkedWriter(BodyWriter): - def send_data(self, data, write): - # if we encoded 0-length data in the naive way, it would look like an - # end-of-message. - if not data: - return - write(bytesmod(b"%x\r\n", (len(data),))) - write(data) - write(b"\r\n") - - def send_eom(self, headers, write): - write(b"0\r\n") - write_headers(headers, write) - - -class Http10Writer(BodyWriter): - def send_data(self, data, write): - write(data) - - def send_eom(self, headers, write): - if headers: - raise LocalProtocolError("can't send trailers to HTTP/1.0 client") - # no need to close the socket ourselves, that will be taken care of by - # Connection: close machinery - - -WRITERS = { - (CLIENT, IDLE): write_request, - (SERVER, IDLE): write_any_response, - (SERVER, SEND_RESPONSE): write_any_response, - SEND_BODY: { - "chunked": ChunkedWriter, - "content-length": ContentLengthWriter, - "http/1.0": Http10Writer, - }, -} diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/__init__.py b/py3.7/lib/python3.7/site-packages/h11/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/data/test-file b/py3.7/lib/python3.7/site-packages/h11/tests/data/test-file deleted file mode 100644 index d0be0a6..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/data/test-file +++ /dev/null @@ -1 +0,0 @@ -92b12bc045050b55b848d37167a1a63947c364579889ce1d39788e45e9fac9e5 diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/helpers.py b/py3.7/lib/python3.7/site-packages/h11/tests/helpers.py deleted file mode 100644 index 9d2cf38..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/helpers.py +++ /dev/null @@ -1,77 +0,0 @@ -from .._connection import * -from .._events import * -from .._state import * - - -def get_all_events(conn): - got_events = [] - while True: - event = conn.next_event() - if event in (NEED_DATA, PAUSED): - break - got_events.append(event) - if type(event) is ConnectionClosed: - break - return got_events - - -def receive_and_get(conn, data): - conn.receive_data(data) - return get_all_events(conn) - - -# Merges adjacent Data events, converts payloads to bytestrings, and removes -# chunk boundaries. -def normalize_data_events(in_events): - out_events = [] - for event in in_events: - if type(event) is Data: - event.data = bytes(event.data) - event.chunk_start = False - event.chunk_end = False - if out_events and type(out_events[-1]) is type(event) is Data: - out_events[-1].data += event.data - else: - out_events.append(event) - return out_events - - -# Given that we want to write tests that push some events through a Connection -# and check that its state updates appropriately... we might as make a habit -# of pushing them through two Connections with a fake network link in -# between. -class ConnectionPair: - def __init__(self): - self.conn = {CLIENT: Connection(CLIENT), SERVER: Connection(SERVER)} - self.other = {CLIENT: SERVER, SERVER: CLIENT} - - @property - def conns(self): - return self.conn.values() - - # expect="match" if expect=send_events; expect=[...] to say what expected - def send(self, role, send_events, expect="match"): - if not isinstance(send_events, list): - send_events = [send_events] - data = b"" - closed = False - for send_event in send_events: - new_data = self.conn[role].send(send_event) - if new_data is None: - closed = True - else: - data += new_data - # send uses b"" to mean b"", and None to mean closed - # receive uses b"" to mean closed, and None to mean "try again" - # so we have to translate between the two conventions - if data: - self.conn[self.other[role]].receive_data(data) - if closed: - self.conn[self.other[role]].receive_data(b"") - got_events = get_all_events(self.conn[self.other[role]]) - if expect == "match": - expect = send_events - if not isinstance(expect, list): - expect = [expect] - assert got_events == expect - return data diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_against_stdlib_http.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_against_stdlib_http.py deleted file mode 100644 index b4219ff..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_against_stdlib_http.py +++ /dev/null @@ -1,123 +0,0 @@ -import json -import os.path -import socket -import threading -from contextlib import closing, contextmanager - -import h11 - -try: - from urllib.request import urlopen -except ImportError: # version specific: Python 2 - from urllib2 import urlopen - -try: - import socketserver -except ImportError: # version specific: Python 2 - import SocketServer as socketserver - -try: - from http.server import SimpleHTTPRequestHandler -except ImportError: # version specific: Python 2 - from SimpleHTTPServer import SimpleHTTPRequestHandler - - -@contextmanager -def socket_server(handler): - httpd = socketserver.TCPServer(("127.0.0.1", 0), handler) - thread = threading.Thread( - target=httpd.serve_forever, kwargs={"poll_interval": 0.01} - ) - thread.daemon = True - try: - thread.start() - yield httpd - finally: - httpd.shutdown() - - -test_file_path = os.path.join(os.path.dirname(__file__), "data/test-file") -with open(test_file_path, "rb") as f: - test_file_data = f.read() - - -class SingleMindedRequestHandler(SimpleHTTPRequestHandler): - def translate_path(self, path): - return test_file_path - - -def test_h11_as_client(): - with socket_server(SingleMindedRequestHandler) as httpd: - with closing(socket.create_connection(httpd.server_address)) as s: - c = h11.Connection(h11.CLIENT) - - s.sendall( - c.send( - h11.Request( - method="GET", target="/foo", headers=[("Host", "localhost")] - ) - ) - ) - s.sendall(c.send(h11.EndOfMessage())) - - data = bytearray() - while True: - event = c.next_event() - print(event) - if event is h11.NEED_DATA: - # Use a small read buffer to make things more challenging - # and exercise more paths :-) - c.receive_data(s.recv(10)) - continue - if type(event) is h11.Response: - assert event.status_code == 200 - if type(event) is h11.Data: - data += event.data - if type(event) is h11.EndOfMessage: - break - assert bytes(data) == test_file_data - - -class H11RequestHandler(socketserver.BaseRequestHandler): - def handle(self): - with closing(self.request) as s: - c = h11.Connection(h11.SERVER) - request = None - while True: - event = c.next_event() - if event is h11.NEED_DATA: - # Use a small read buffer to make things more challenging - # and exercise more paths :-) - c.receive_data(s.recv(10)) - continue - if type(event) is h11.Request: - request = event - if type(event) is h11.EndOfMessage: - break - info = json.dumps( - { - "method": request.method.decode("ascii"), - "target": request.target.decode("ascii"), - "headers": { - name.decode("ascii"): value.decode("ascii") - for (name, value) in request.headers - }, - } - ) - s.sendall(c.send(h11.Response(status_code=200, headers=[]))) - s.sendall(c.send(h11.Data(data=info.encode("ascii")))) - s.sendall(c.send(h11.EndOfMessage())) - - -def test_h11_as_server(): - with socket_server(H11RequestHandler) as httpd: - host, port = httpd.server_address - url = "http://{}:{}/some-path".format(host, port) - with closing(urlopen(url)) as f: - assert f.getcode() == 200 - data = f.read() - info = json.loads(data.decode("ascii")) - print(info) - assert info["method"] == "GET" - assert info["target"] == "/some-path" - assert "urllib" in info["headers"]["user-agent"] diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_connection.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_connection.py deleted file mode 100644 index 13e6e2d..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_connection.py +++ /dev/null @@ -1,1046 +0,0 @@ -import pytest - -from .._connection import _body_framing, _keep_alive, Connection, NEED_DATA, PAUSED -from .._events import * -from .._state import * -from .._util import LocalProtocolError, RemoteProtocolError -from .helpers import ConnectionPair, get_all_events, receive_and_get - - -def test__keep_alive(): - assert _keep_alive( - Request(method="GET", target="/", headers=[("Host", "Example.com")]) - ) - assert not _keep_alive( - Request( - method="GET", - target="/", - headers=[("Host", "Example.com"), ("Connection", "close")], - ) - ) - assert not _keep_alive( - Request( - method="GET", - target="/", - headers=[("Host", "Example.com"), ("Connection", "a, b, cLOse, foo")], - ) - ) - assert not _keep_alive( - Request(method="GET", target="/", headers=[], http_version="1.0") - ) - - assert _keep_alive(Response(status_code=200, headers=[])) - assert not _keep_alive(Response(status_code=200, headers=[("Connection", "close")])) - assert not _keep_alive( - Response(status_code=200, headers=[("Connection", "a, b, cLOse, foo")]) - ) - assert not _keep_alive(Response(status_code=200, headers=[], http_version="1.0")) - - -def test__body_framing(): - def headers(cl, te): - headers = [] - if cl is not None: - headers.append(("Content-Length", str(cl))) - if te: - headers.append(("Transfer-Encoding", "chunked")) - return headers - - def resp(status_code=200, cl=None, te=False): - return Response(status_code=status_code, headers=headers(cl, te)) - - def req(cl=None, te=False): - h = headers(cl, te) - h += [("Host", "example.com")] - return Request(method="GET", target="/", headers=h) - - # Special cases where the headers are ignored: - for kwargs in [{}, {"cl": 100}, {"te": True}, {"cl": 100, "te": True}]: - for meth, r in [ - (b"HEAD", resp(**kwargs)), - (b"GET", resp(status_code=204, **kwargs)), - (b"GET", resp(status_code=304, **kwargs)), - ]: - assert _body_framing(meth, r) == ("content-length", (0,)) - - # Transfer-encoding - for kwargs in [{"te": True}, {"cl": 100, "te": True}]: - for meth, r in [(None, req(**kwargs)), (b"GET", resp(**kwargs))]: - assert _body_framing(meth, r) == ("chunked", ()) - - # Content-Length - for meth, r in [(None, req(cl=100)), (b"GET", resp(cl=100))]: - assert _body_framing(meth, r) == ("content-length", (100,)) - - # No headers - assert _body_framing(None, req()) == ("content-length", (0,)) - assert _body_framing(b"GET", resp()) == ("http/1.0", ()) - - -def test_Connection_basics_and_content_length(): - with pytest.raises(ValueError): - Connection("CLIENT") - - p = ConnectionPair() - assert p.conn[CLIENT].our_role is CLIENT - assert p.conn[CLIENT].their_role is SERVER - assert p.conn[SERVER].our_role is SERVER - assert p.conn[SERVER].their_role is CLIENT - - data = p.send( - CLIENT, - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Content-Length", "10")], - ), - ) - assert data == ( - b"GET / HTTP/1.1\r\n" b"host: example.com\r\n" b"content-length: 10\r\n\r\n" - ) - - for conn in p.conns: - assert conn.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - assert p.conn[CLIENT].our_state is SEND_BODY - assert p.conn[CLIENT].their_state is SEND_RESPONSE - assert p.conn[SERVER].our_state is SEND_RESPONSE - assert p.conn[SERVER].their_state is SEND_BODY - - assert p.conn[CLIENT].their_http_version is None - assert p.conn[SERVER].their_http_version == b"1.1" - - data = p.send(SERVER, InformationalResponse(status_code=100, headers=[])) - assert data == b"HTTP/1.1 100 \r\n\r\n" - - data = p.send(SERVER, Response(status_code=200, headers=[("Content-Length", "11")])) - assert data == b"HTTP/1.1 200 \r\ncontent-length: 11\r\n\r\n" - - for conn in p.conns: - assert conn.states == {CLIENT: SEND_BODY, SERVER: SEND_BODY} - - assert p.conn[CLIENT].their_http_version == b"1.1" - assert p.conn[SERVER].their_http_version == b"1.1" - - data = p.send(CLIENT, Data(data=b"12345")) - assert data == b"12345" - data = p.send( - CLIENT, Data(data=b"67890"), expect=[Data(data=b"67890"), EndOfMessage()] - ) - assert data == b"67890" - data = p.send(CLIENT, EndOfMessage(), expect=[]) - assert data == b"" - - for conn in p.conns: - assert conn.states == {CLIENT: DONE, SERVER: SEND_BODY} - - data = p.send(SERVER, Data(data=b"1234567890")) - assert data == b"1234567890" - data = p.send(SERVER, Data(data=b"1"), expect=[Data(data=b"1"), EndOfMessage()]) - assert data == b"1" - data = p.send(SERVER, EndOfMessage(), expect=[]) - assert data == b"" - - for conn in p.conns: - assert conn.states == {CLIENT: DONE, SERVER: DONE} - - -def test_chunked(): - p = ConnectionPair() - - p.send( - CLIENT, - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Transfer-Encoding", "chunked")], - ), - ) - data = p.send(CLIENT, Data(data=b"1234567890", chunk_start=True, chunk_end=True)) - assert data == b"a\r\n1234567890\r\n" - data = p.send(CLIENT, Data(data=b"abcde", chunk_start=True, chunk_end=True)) - assert data == b"5\r\nabcde\r\n" - data = p.send(CLIENT, Data(data=b""), expect=[]) - assert data == b"" - data = p.send(CLIENT, EndOfMessage(headers=[("hello", "there")])) - assert data == b"0\r\nhello: there\r\n\r\n" - - p.send( - SERVER, Response(status_code=200, headers=[("Transfer-Encoding", "chunked")]) - ) - p.send(SERVER, Data(data=b"54321", chunk_start=True, chunk_end=True)) - p.send(SERVER, Data(data=b"12345", chunk_start=True, chunk_end=True)) - p.send(SERVER, EndOfMessage()) - - for conn in p.conns: - assert conn.states == {CLIENT: DONE, SERVER: DONE} - - -def test_chunk_boundaries(): - conn = Connection(our_role=SERVER) - - request = ( - b"POST / HTTP/1.1\r\n" - b"Host: example.com\r\n" - b"Transfer-Encoding: chunked\r\n" - b"\r\n" - ) - conn.receive_data(request) - assert conn.next_event() == Request( - method="POST", - target="/", - headers=[("Host", "example.com"), ("Transfer-Encoding", "chunked")], - ) - assert conn.next_event() is NEED_DATA - - conn.receive_data(b"5\r\nhello\r\n") - assert conn.next_event() == Data(data=b"hello", chunk_start=True, chunk_end=True) - - conn.receive_data(b"5\r\nhel") - assert conn.next_event() == Data(data=b"hel", chunk_start=True, chunk_end=False) - - conn.receive_data(b"l") - assert conn.next_event() == Data(data=b"l", chunk_start=False, chunk_end=False) - - conn.receive_data(b"o\r\n") - assert conn.next_event() == Data(data=b"o", chunk_start=False, chunk_end=True) - - conn.receive_data(b"5\r\nhello") - assert conn.next_event() == Data(data=b"hello", chunk_start=True, chunk_end=True) - - conn.receive_data(b"\r\n") - assert conn.next_event() == NEED_DATA - - conn.receive_data(b"0\r\n\r\n") - assert conn.next_event() == EndOfMessage() - - -def test_client_talking_to_http10_server(): - c = Connection(CLIENT) - c.send(Request(method="GET", target="/", headers=[("Host", "example.com")])) - c.send(EndOfMessage()) - assert c.our_state is DONE - # No content-length, so Http10 framing for body - assert receive_and_get(c, b"HTTP/1.0 200 OK\r\n\r\n") == [ - Response(status_code=200, headers=[], http_version="1.0", reason=b"OK") - ] - assert c.our_state is MUST_CLOSE - assert receive_and_get(c, b"12345") == [Data(data=b"12345")] - assert receive_and_get(c, b"67890") == [Data(data=b"67890")] - assert receive_and_get(c, b"") == [EndOfMessage(), ConnectionClosed()] - assert c.their_state is CLOSED - - -def test_server_talking_to_http10_client(): - c = Connection(SERVER) - # No content-length, so no body - # NB: no host header - assert receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") == [ - Request(method="GET", target="/", headers=[], http_version="1.0"), - EndOfMessage(), - ] - assert c.their_state is MUST_CLOSE - - # We automatically Connection: close back at them - assert ( - c.send(Response(status_code=200, headers=[])) - == b"HTTP/1.1 200 \r\nconnection: close\r\n\r\n" - ) - - assert c.send(Data(data=b"12345")) == b"12345" - assert c.send(EndOfMessage()) == b"" - assert c.our_state is MUST_CLOSE - - # Check that it works if they do send Content-Length - c = Connection(SERVER) - # NB: no host header - assert receive_and_get(c, b"POST / HTTP/1.0\r\nContent-Length: 10\r\n\r\n1") == [ - Request( - method="POST", - target="/", - headers=[("Content-Length", "10")], - http_version="1.0", - ), - Data(data=b"1"), - ] - assert receive_and_get(c, b"234567890") == [Data(data=b"234567890"), EndOfMessage()] - assert c.their_state is MUST_CLOSE - assert receive_and_get(c, b"") == [ConnectionClosed()] - - -def test_automatic_transfer_encoding_in_response(): - # Check that in responses, the user can specify either Transfer-Encoding: - # chunked or no framing at all, and in both cases we automatically select - # the right option depending on whether the peer speaks HTTP/1.0 or - # HTTP/1.1 - for user_headers in [ - [("Transfer-Encoding", "chunked")], - [], - # In fact, this even works if Content-Length is set, - # because if both are set then Transfer-Encoding wins - [("Transfer-Encoding", "chunked"), ("Content-Length", "100")], - ]: - p = ConnectionPair() - p.send( - CLIENT, - [ - Request(method="GET", target="/", headers=[("Host", "example.com")]), - EndOfMessage(), - ], - ) - # When speaking to HTTP/1.1 client, all of the above cases get - # normalized to Transfer-Encoding: chunked - p.send( - SERVER, - Response(status_code=200, headers=user_headers), - expect=Response( - status_code=200, headers=[("Transfer-Encoding", "chunked")] - ), - ) - - # When speaking to HTTP/1.0 client, all of the above cases get - # normalized to no-framing-headers - c = Connection(SERVER) - receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") - assert ( - c.send(Response(status_code=200, headers=user_headers)) - == b"HTTP/1.1 200 \r\nconnection: close\r\n\r\n" - ) - assert c.send(Data(data=b"12345")) == b"12345" - - -def test_automagic_connection_close_handling(): - p = ConnectionPair() - # If the user explicitly sets Connection: close, then we notice and - # respect it - p.send( - CLIENT, - [ - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Connection", "close")], - ), - EndOfMessage(), - ], - ) - for conn in p.conns: - assert conn.states[CLIENT] is MUST_CLOSE - # And if the client sets it, the server automatically echoes it back - p.send( - SERVER, - # no header here... - [Response(status_code=204, headers=[]), EndOfMessage()], - # ...but oh look, it arrived anyway - expect=[ - Response(status_code=204, headers=[("connection", "close")]), - EndOfMessage(), - ], - ) - for conn in p.conns: - assert conn.states == {CLIENT: MUST_CLOSE, SERVER: MUST_CLOSE} - - -def test_100_continue(): - def setup(): - p = ConnectionPair() - p.send( - CLIENT, - Request( - method="GET", - target="/", - headers=[ - ("Host", "example.com"), - ("Content-Length", "100"), - ("Expect", "100-continue"), - ], - ), - ) - for conn in p.conns: - assert conn.client_is_waiting_for_100_continue - assert not p.conn[CLIENT].they_are_waiting_for_100_continue - assert p.conn[SERVER].they_are_waiting_for_100_continue - return p - - # Disabled by 100 Continue - p = setup() - p.send(SERVER, InformationalResponse(status_code=100, headers=[])) - for conn in p.conns: - assert not conn.client_is_waiting_for_100_continue - assert not conn.they_are_waiting_for_100_continue - - # Disabled by a real response - p = setup() - p.send( - SERVER, Response(status_code=200, headers=[("Transfer-Encoding", "chunked")]) - ) - for conn in p.conns: - assert not conn.client_is_waiting_for_100_continue - assert not conn.they_are_waiting_for_100_continue - - # Disabled by the client going ahead and sending stuff anyway - p = setup() - p.send(CLIENT, Data(data=b"12345")) - for conn in p.conns: - assert not conn.client_is_waiting_for_100_continue - assert not conn.they_are_waiting_for_100_continue - - -def test_max_incomplete_event_size_countermeasure(): - # Infinitely long headers are definitely not okay - c = Connection(SERVER) - c.receive_data(b"GET / HTTP/1.0\r\nEndless: ") - assert c.next_event() is NEED_DATA - with pytest.raises(RemoteProtocolError): - while True: - c.receive_data(b"a" * 1024) - c.next_event() - - # Checking that the same header is accepted / rejected depending on the - # max_incomplete_event_size setting: - c = Connection(SERVER, max_incomplete_event_size=5000) - c.receive_data(b"GET / HTTP/1.0\r\nBig: ") - c.receive_data(b"a" * 4000) - c.receive_data(b"\r\n\r\n") - assert get_all_events(c) == [ - Request( - method="GET", target="/", http_version="1.0", headers=[("big", "a" * 4000)] - ), - EndOfMessage(), - ] - - c = Connection(SERVER, max_incomplete_event_size=4000) - c.receive_data(b"GET / HTTP/1.0\r\nBig: ") - c.receive_data(b"a" * 4000) - with pytest.raises(RemoteProtocolError): - c.next_event() - - # Temporarily exceeding the size limit is fine, as long as its done with - # complete events: - c = Connection(SERVER, max_incomplete_event_size=5000) - c.receive_data(b"GET / HTTP/1.0\r\nContent-Length: 10000") - c.receive_data(b"\r\n\r\n" + b"a" * 10000) - assert get_all_events(c) == [ - Request( - method="GET", - target="/", - http_version="1.0", - headers=[("Content-Length", "10000")], - ), - Data(data=b"a" * 10000), - EndOfMessage(), - ] - - c = Connection(SERVER, max_incomplete_event_size=100) - # Two pipelined requests to create a way-too-big receive buffer... but - # it's fine because we're not checking - c.receive_data( - b"GET /1 HTTP/1.1\r\nHost: a\r\n\r\n" - b"GET /2 HTTP/1.1\r\nHost: b\r\n\r\n" + b"X" * 1000 - ) - assert get_all_events(c) == [ - Request(method="GET", target="/1", headers=[("host", "a")]), - EndOfMessage(), - ] - # Even more data comes in, still no problem - c.receive_data(b"X" * 1000) - # We can respond and reuse to get the second pipelined request - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - c.start_next_cycle() - assert get_all_events(c) == [ - Request(method="GET", target="/2", headers=[("host", "b")]), - EndOfMessage(), - ] - # But once we unpause and try to read the next message, and find that it's - # incomplete and the buffer is *still* way too large, then *that's* a - # problem: - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - c.start_next_cycle() - with pytest.raises(RemoteProtocolError): - c.next_event() - - -def test_reuse_simple(): - p = ConnectionPair() - p.send( - CLIENT, - [Request(method="GET", target="/", headers=[("Host", "a")]), EndOfMessage()], - ) - p.send(SERVER, [Response(status_code=200, headers=[]), EndOfMessage()]) - for conn in p.conns: - assert conn.states == {CLIENT: DONE, SERVER: DONE} - conn.start_next_cycle() - - p.send( - CLIENT, - [ - Request(method="DELETE", target="/foo", headers=[("Host", "a")]), - EndOfMessage(), - ], - ) - p.send(SERVER, [Response(status_code=404, headers=[]), EndOfMessage()]) - - -def test_pipelining(): - # Client doesn't support pipelining, so we have to do this by hand - c = Connection(SERVER) - assert c.next_event() is NEED_DATA - # 3 requests all bunched up - c.receive_data( - b"GET /1 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" - b"12345" - b"GET /2 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" - b"67890" - b"GET /3 HTTP/1.1\r\nHost: a.com\r\n\r\n" - ) - assert get_all_events(c) == [ - Request( - method="GET", - target="/1", - headers=[("Host", "a.com"), ("Content-Length", "5")], - ), - Data(data=b"12345"), - EndOfMessage(), - ] - assert c.their_state is DONE - assert c.our_state is SEND_RESPONSE - - assert c.next_event() is PAUSED - - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - assert c.their_state is DONE - assert c.our_state is DONE - - c.start_next_cycle() - - assert get_all_events(c) == [ - Request( - method="GET", - target="/2", - headers=[("Host", "a.com"), ("Content-Length", "5")], - ), - Data(data=b"67890"), - EndOfMessage(), - ] - assert c.next_event() is PAUSED - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - c.start_next_cycle() - - assert get_all_events(c) == [ - Request(method="GET", target="/3", headers=[("Host", "a.com")]), - EndOfMessage(), - ] - # Doesn't pause this time, no trailing data - assert c.next_event() is NEED_DATA - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - - # Arrival of more data triggers pause - assert c.next_event() is NEED_DATA - c.receive_data(b"SADF") - assert c.next_event() is PAUSED - assert c.trailing_data == (b"SADF", False) - # If EOF arrives while paused, we don't see that either: - c.receive_data(b"") - assert c.trailing_data == (b"SADF", True) - assert c.next_event() is PAUSED - c.receive_data(b"") - assert c.next_event() is PAUSED - # Can't call receive_data with non-empty buf after closing it - with pytest.raises(RuntimeError): - c.receive_data(b"FDSA") - - -def test_protocol_switch(): - for (req, deny, accept) in [ - ( - Request( - method="CONNECT", - target="example.com:443", - headers=[("Host", "foo"), ("Content-Length", "1")], - ), - Response(status_code=404, headers=[]), - Response(status_code=200, headers=[]), - ), - ( - Request( - method="GET", - target="/", - headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], - ), - Response(status_code=200, headers=[]), - InformationalResponse(status_code=101, headers=[("Upgrade", "a")]), - ), - ( - Request( - method="CONNECT", - target="example.com:443", - headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], - ), - Response(status_code=404, headers=[]), - # Accept CONNECT, not upgrade - Response(status_code=200, headers=[]), - ), - ( - Request( - method="CONNECT", - target="example.com:443", - headers=[("Host", "foo"), ("Content-Length", "1"), ("Upgrade", "a, b")], - ), - Response(status_code=404, headers=[]), - # Accept Upgrade, not CONNECT - InformationalResponse(status_code=101, headers=[("Upgrade", "b")]), - ), - ]: - - def setup(): - p = ConnectionPair() - p.send(CLIENT, req) - # No switch-related state change stuff yet; the client has to - # finish the request before that kicks in - for conn in p.conns: - assert conn.states[CLIENT] is SEND_BODY - p.send(CLIENT, [Data(data=b"1"), EndOfMessage()]) - for conn in p.conns: - assert conn.states[CLIENT] is MIGHT_SWITCH_PROTOCOL - assert p.conn[SERVER].next_event() is PAUSED - return p - - # Test deny case - p = setup() - p.send(SERVER, deny) - for conn in p.conns: - assert conn.states == {CLIENT: DONE, SERVER: SEND_BODY} - p.send(SERVER, EndOfMessage()) - # Check that re-use is still allowed after a denial - for conn in p.conns: - conn.start_next_cycle() - - # Test accept case - p = setup() - p.send(SERVER, accept) - for conn in p.conns: - assert conn.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} - conn.receive_data(b"123") - assert conn.next_event() is PAUSED - conn.receive_data(b"456") - assert conn.next_event() is PAUSED - assert conn.trailing_data == (b"123456", False) - - # Pausing in might-switch, then recovery - # (weird artificial case where the trailing data actually is valid - # HTTP for some reason, because this makes it easier to test the state - # logic) - p = setup() - sc = p.conn[SERVER] - sc.receive_data(b"GET / HTTP/1.0\r\n\r\n") - assert sc.next_event() is PAUSED - assert sc.trailing_data == (b"GET / HTTP/1.0\r\n\r\n", False) - sc.send(deny) - assert sc.next_event() is PAUSED - sc.send(EndOfMessage()) - sc.start_next_cycle() - assert get_all_events(sc) == [ - Request(method="GET", target="/", headers=[], http_version="1.0"), - EndOfMessage(), - ] - - # When we're DONE, have no trailing data, and the connection gets - # closed, we report ConnectionClosed(). When we're in might-switch or - # switched, we don't. - p = setup() - sc = p.conn[SERVER] - sc.receive_data(b"") - assert sc.next_event() is PAUSED - assert sc.trailing_data == (b"", True) - p.send(SERVER, accept) - assert sc.next_event() is PAUSED - - p = setup() - sc = p.conn[SERVER] - sc.receive_data(b"") == [] - assert sc.next_event() is PAUSED - sc.send(deny) - assert sc.next_event() == ConnectionClosed() - - # You can't send after switching protocols, or while waiting for a - # protocol switch - p = setup() - with pytest.raises(LocalProtocolError): - p.conn[CLIENT].send( - Request(method="GET", target="/", headers=[("Host", "a")]) - ) - p = setup() - p.send(SERVER, accept) - with pytest.raises(LocalProtocolError): - p.conn[SERVER].send(Data(data=b"123")) - - -def test_close_simple(): - # Just immediately closing a new connection without anything having - # happened yet. - for (who_shot_first, who_shot_second) in [(CLIENT, SERVER), (SERVER, CLIENT)]: - - def setup(): - p = ConnectionPair() - p.send(who_shot_first, ConnectionClosed()) - for conn in p.conns: - assert conn.states == { - who_shot_first: CLOSED, - who_shot_second: MUST_CLOSE, - } - return p - - # You can keep putting b"" into a closed connection, and you keep - # getting ConnectionClosed() out: - p = setup() - assert p.conn[who_shot_second].next_event() == ConnectionClosed() - assert p.conn[who_shot_second].next_event() == ConnectionClosed() - p.conn[who_shot_second].receive_data(b"") - assert p.conn[who_shot_second].next_event() == ConnectionClosed() - # Second party can close... - p = setup() - p.send(who_shot_second, ConnectionClosed()) - for conn in p.conns: - assert conn.our_state is CLOSED - assert conn.their_state is CLOSED - # But trying to receive new data on a closed connection is a - # RuntimeError (not ProtocolError, because the problem here isn't - # violation of HTTP, it's violation of physics) - p = setup() - with pytest.raises(RuntimeError): - p.conn[who_shot_second].receive_data(b"123") - # And receiving new data on a MUST_CLOSE connection is a ProtocolError - p = setup() - p.conn[who_shot_first].receive_data(b"GET") - with pytest.raises(RemoteProtocolError): - p.conn[who_shot_first].next_event() - - -def test_close_different_states(): - req = [ - Request(method="GET", target="/foo", headers=[("Host", "a")]), - EndOfMessage(), - ] - resp = [Response(status_code=200, headers=[]), EndOfMessage()] - - # Client before request - p = ConnectionPair() - p.send(CLIENT, ConnectionClosed()) - for conn in p.conns: - assert conn.states == {CLIENT: CLOSED, SERVER: MUST_CLOSE} - - # Client after request - p = ConnectionPair() - p.send(CLIENT, req) - p.send(CLIENT, ConnectionClosed()) - for conn in p.conns: - assert conn.states == {CLIENT: CLOSED, SERVER: SEND_RESPONSE} - - # Server after request -> not allowed - p = ConnectionPair() - p.send(CLIENT, req) - with pytest.raises(LocalProtocolError): - p.conn[SERVER].send(ConnectionClosed()) - p.conn[CLIENT].receive_data(b"") - with pytest.raises(RemoteProtocolError): - p.conn[CLIENT].next_event() - - # Server after response - p = ConnectionPair() - p.send(CLIENT, req) - p.send(SERVER, resp) - p.send(SERVER, ConnectionClosed()) - for conn in p.conns: - assert conn.states == {CLIENT: MUST_CLOSE, SERVER: CLOSED} - - # Both after closing (ConnectionClosed() is idempotent) - p = ConnectionPair() - p.send(CLIENT, req) - p.send(SERVER, resp) - p.send(CLIENT, ConnectionClosed()) - p.send(SERVER, ConnectionClosed()) - p.send(CLIENT, ConnectionClosed()) - p.send(SERVER, ConnectionClosed()) - - # In the middle of sending -> not allowed - p = ConnectionPair() - p.send( - CLIENT, - Request( - method="GET", target="/", headers=[("Host", "a"), ("Content-Length", "10")] - ), - ) - with pytest.raises(LocalProtocolError): - p.conn[CLIENT].send(ConnectionClosed()) - p.conn[SERVER].receive_data(b"") - with pytest.raises(RemoteProtocolError): - p.conn[SERVER].next_event() - - -# Receive several requests and then client shuts down their side of the -# connection; we can respond to each -def test_pipelined_close(): - c = Connection(SERVER) - # 2 requests then a close - c.receive_data( - b"GET /1 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" - b"12345" - b"GET /2 HTTP/1.1\r\nHost: a.com\r\nContent-Length: 5\r\n\r\n" - b"67890" - ) - c.receive_data(b"") - assert get_all_events(c) == [ - Request( - method="GET", - target="/1", - headers=[("host", "a.com"), ("content-length", "5")], - ), - Data(data=b"12345"), - EndOfMessage(), - ] - assert c.states[CLIENT] is DONE - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - assert c.states[SERVER] is DONE - c.start_next_cycle() - assert get_all_events(c) == [ - Request( - method="GET", - target="/2", - headers=[("host", "a.com"), ("content-length", "5")], - ), - Data(data=b"67890"), - EndOfMessage(), - ConnectionClosed(), - ] - assert c.states == {CLIENT: CLOSED, SERVER: SEND_RESPONSE} - c.send(Response(status_code=200, headers=[])) - c.send(EndOfMessage()) - assert c.states == {CLIENT: CLOSED, SERVER: MUST_CLOSE} - c.send(ConnectionClosed()) - assert c.states == {CLIENT: CLOSED, SERVER: CLOSED} - - -def test_sendfile(): - class SendfilePlaceholder: - def __len__(self): - return 10 - - placeholder = SendfilePlaceholder() - - def setup(header, http_version): - c = Connection(SERVER) - receive_and_get( - c, "GET / HTTP/{}\r\nHost: a\r\n\r\n".format(http_version).encode("ascii") - ) - headers = [] - if header: - headers.append(header) - c.send(Response(status_code=200, headers=headers)) - return c, c.send_with_data_passthrough(Data(data=placeholder)) - - c, data = setup(("Content-Length", "10"), "1.1") - assert data == [placeholder] - # Raises an error if the connection object doesn't think we've sent - # exactly 10 bytes - c.send(EndOfMessage()) - - _, data = setup(("Transfer-Encoding", "chunked"), "1.1") - assert placeholder in data - data[data.index(placeholder)] = b"x" * 10 - assert b"".join(data) == b"a\r\nxxxxxxxxxx\r\n" - - c, data = setup(None, "1.0") - assert data == [placeholder] - assert c.our_state is SEND_BODY - - -def test_errors(): - # After a receive error, you can't receive - for role in [CLIENT, SERVER]: - c = Connection(our_role=role) - c.receive_data(b"gibberish\r\n\r\n") - with pytest.raises(RemoteProtocolError): - c.next_event() - # Now any attempt to receive continues to raise - assert c.their_state is ERROR - assert c.our_state is not ERROR - print(c._cstate.states) - with pytest.raises(RemoteProtocolError): - c.next_event() - # But we can still yell at the client for sending us gibberish - if role is SERVER: - assert ( - c.send(Response(status_code=400, headers=[])) - == b"HTTP/1.1 400 \r\nconnection: close\r\n\r\n" - ) - - # After an error sending, you can no longer send - # (This is especially important for things like content-length errors, - # where there's complex internal state being modified) - def conn(role): - c = Connection(our_role=role) - if role is SERVER: - # Put it into the state where it *could* send a response... - receive_and_get(c, b"GET / HTTP/1.0\r\n\r\n") - assert c.our_state is SEND_RESPONSE - return c - - for role in [CLIENT, SERVER]: - if role is CLIENT: - # This HTTP/1.0 request won't be detected as bad until after we go - # through the state machine and hit the writing code - good = Request(method="GET", target="/", headers=[("Host", "example.com")]) - bad = Request( - method="GET", - target="/", - headers=[("Host", "example.com")], - http_version="1.0", - ) - elif role is SERVER: - good = Response(status_code=200, headers=[]) - bad = Response(status_code=200, headers=[], http_version="1.0") - # Make sure 'good' actually is good - c = conn(role) - c.send(good) - assert c.our_state is not ERROR - # Do that again, but this time sending 'bad' first - c = conn(role) - with pytest.raises(LocalProtocolError): - c.send(bad) - assert c.our_state is ERROR - assert c.their_state is not ERROR - # Now 'good' is not so good - with pytest.raises(LocalProtocolError): - c.send(good) - - # And check send_failed() too - c = conn(role) - c.send_failed() - assert c.our_state is ERROR - assert c.their_state is not ERROR - # This is idempotent - c.send_failed() - assert c.our_state is ERROR - assert c.their_state is not ERROR - - -def test_idle_receive_nothing(): - # At one point this incorrectly raised an error - for role in [CLIENT, SERVER]: - c = Connection(role) - assert c.next_event() is NEED_DATA - - -def test_connection_drop(): - c = Connection(SERVER) - c.receive_data(b"GET /") - assert c.next_event() is NEED_DATA - c.receive_data(b"") - with pytest.raises(RemoteProtocolError): - c.next_event() - - -def test_408_request_timeout(): - # Should be able to send this spontaneously as a server without seeing - # anything from client - p = ConnectionPair() - p.send(SERVER, Response(status_code=408, headers=[])) - - -# This used to raise IndexError -def test_empty_request(): - c = Connection(SERVER) - c.receive_data(b"\r\n") - with pytest.raises(RemoteProtocolError): - c.next_event() - - -# This used to raise IndexError -def test_empty_response(): - c = Connection(CLIENT) - c.send(Request(method="GET", target="/", headers=[("Host", "a")])) - c.receive_data(b"\r\n") - with pytest.raises(RemoteProtocolError): - c.next_event() - - -# This used to give different headers for HEAD and GET. -# The correct way to handle HEAD is to put whatever headers we *would* have -# put if it were a GET -- even though we know that for HEAD, those headers -# will be ignored. -def test_HEAD_framing_headers(): - def setup(method, http_version): - c = Connection(SERVER) - c.receive_data( - method + b" / HTTP/" + http_version + b"\r\n" + b"Host: example.com\r\n\r\n" - ) - assert type(c.next_event()) is Request - assert type(c.next_event()) is EndOfMessage - return c - - for method in [b"GET", b"HEAD"]: - # No Content-Length, HTTP/1.1 peer, should use chunked - c = setup(method, b"1.1") - assert ( - c.send(Response(status_code=200, headers=[])) == b"HTTP/1.1 200 \r\n" - b"transfer-encoding: chunked\r\n\r\n" - ) - - # No Content-Length, HTTP/1.0 peer, frame with connection: close - c = setup(method, b"1.0") - assert ( - c.send(Response(status_code=200, headers=[])) == b"HTTP/1.1 200 \r\n" - b"connection: close\r\n\r\n" - ) - - # Content-Length + Transfer-Encoding, TE wins - c = setup(method, b"1.1") - assert ( - c.send( - Response( - status_code=200, - headers=[ - ("Content-Length", "100"), - ("Transfer-Encoding", "chunked"), - ], - ) - ) - == b"HTTP/1.1 200 \r\n" - b"transfer-encoding: chunked\r\n\r\n" - ) - - -def test_special_exceptions_for_lost_connection_in_message_body(): - c = Connection(SERVER) - c.receive_data( - b"POST / HTTP/1.1\r\n" b"Host: example.com\r\n" b"Content-Length: 100\r\n\r\n" - ) - assert type(c.next_event()) is Request - assert c.next_event() is NEED_DATA - c.receive_data(b"12345") - assert c.next_event() == Data(data=b"12345") - c.receive_data(b"") - with pytest.raises(RemoteProtocolError) as excinfo: - c.next_event() - assert "received 5 bytes" in str(excinfo.value) - assert "expected 100" in str(excinfo.value) - - c = Connection(SERVER) - c.receive_data( - b"POST / HTTP/1.1\r\n" - b"Host: example.com\r\n" - b"Transfer-Encoding: chunked\r\n\r\n" - ) - assert type(c.next_event()) is Request - assert c.next_event() is NEED_DATA - c.receive_data(b"8\r\n012345") - assert c.next_event().data == b"012345" - c.receive_data(b"") - with pytest.raises(RemoteProtocolError) as excinfo: - c.next_event() - assert "incomplete chunked read" in str(excinfo.value) diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_events.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_events.py deleted file mode 100644 index 4c2a912..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_events.py +++ /dev/null @@ -1,165 +0,0 @@ -import pytest - -from .. import _events -from .._events import * -from .._util import LocalProtocolError - - -def test_event_bundle(): - class T(_events._EventBundle): - _fields = ["a", "b"] - _defaults = {"b": 1} - - def _validate(self): - if self.a == 0: - raise ValueError - - # basic construction and methods - t = T(a=1, b=0) - assert repr(t) == "T(a=1, b=0)" - assert t == T(a=1, b=0) - assert not (t == T(a=2, b=0)) - assert not (t != T(a=1, b=0)) - assert t != T(a=2, b=0) - with pytest.raises(TypeError): - hash(t) - - # check defaults - t = T(a=10) - assert t.a == 10 - assert t.b == 1 - - # no positional args - with pytest.raises(TypeError): - T(1) - - with pytest.raises(TypeError): - T(1, a=1, b=0) - - # unknown field - with pytest.raises(TypeError): - T(a=1, b=0, c=10) - - # missing required field - with pytest.raises(TypeError) as exc: - T(b=0) - # make sure we error on the right missing kwarg - assert "kwarg a" in str(exc) - - # _validate is called - with pytest.raises(ValueError): - T(a=0, b=0) - - -def test_events(): - with pytest.raises(LocalProtocolError): - # Missing Host: - req = Request( - method="GET", target="/", headers=[("a", "b")], http_version="1.1" - ) - # But this is okay (HTTP/1.0) - req = Request(method="GET", target="/", headers=[("a", "b")], http_version="1.0") - # fields are normalized - assert req.method == b"GET" - assert req.target == b"/" - assert req.headers == [(b"a", b"b")] - assert req.http_version == b"1.0" - - # This is also okay -- has a Host (with weird capitalization, which is ok) - req = Request( - method="GET", - target="/", - headers=[("a", "b"), ("hOSt", "example.com")], - http_version="1.1", - ) - # we normalize header capitalization - assert req.headers == [(b"a", b"b"), (b"host", b"example.com")] - - # Multiple host is bad too - with pytest.raises(LocalProtocolError): - req = Request( - method="GET", - target="/", - headers=[("Host", "a"), ("Host", "a")], - http_version="1.1", - ) - # Even for HTTP/1.0 - with pytest.raises(LocalProtocolError): - req = Request( - method="GET", - target="/", - headers=[("Host", "a"), ("Host", "a")], - http_version="1.0", - ) - - # Header values are validated - for bad_char in "\x00\r\n\f\v": - with pytest.raises(LocalProtocolError): - req = Request( - method="GET", - target="/", - headers=[("Host", "a"), ("Foo", "asd" + bad_char)], - http_version="1.0", - ) - - # But for compatibility we allow non-whitespace control characters, even - # though they're forbidden by the spec. - Request( - method="GET", - target="/", - headers=[("Host", "a"), ("Foo", "asd\x01\x02\x7f")], - http_version="1.0", - ) - - # Request target is validated - for bad_char in b"\x00\x20\x7f\xee": - target = bytearray(b"/") - target.append(bad_char) - with pytest.raises(LocalProtocolError): - Request( - method="GET", target=target, headers=[("Host", "a")], http_version="1.1" - ) - - ir = InformationalResponse(status_code=100, headers=[("Host", "a")]) - assert ir.status_code == 100 - assert ir.headers == [(b"host", b"a")] - assert ir.http_version == b"1.1" - - with pytest.raises(LocalProtocolError): - InformationalResponse(status_code=200, headers=[("Host", "a")]) - - resp = Response(status_code=204, headers=[], http_version="1.0") - assert resp.status_code == 204 - assert resp.headers == [] - assert resp.http_version == b"1.0" - - with pytest.raises(LocalProtocolError): - resp = Response(status_code=100, headers=[], http_version="1.0") - - with pytest.raises(LocalProtocolError): - Response(status_code="100", headers=[], http_version="1.0") - - with pytest.raises(LocalProtocolError): - InformationalResponse(status_code=b"100", headers=[], http_version="1.0") - - d = Data(data=b"asdf") - assert d.data == b"asdf" - - eom = EndOfMessage() - assert eom.headers == [] - - cc = ConnectionClosed() - assert repr(cc) == "ConnectionClosed()" - - -def test_intenum_status_code(): - # https://github.com/python-hyper/h11/issues/72 - try: - from http import HTTPStatus - except ImportError: - pytest.skip("Only affects Python 3") - - r = Response(status_code=HTTPStatus.OK, headers=[], http_version="1.0") - assert r.status_code == HTTPStatus.OK - assert type(r.status_code) is not type(HTTPStatus.OK) - assert type(r.status_code) is int diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_headers.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_headers.py deleted file mode 100644 index 67bcd7b..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_headers.py +++ /dev/null @@ -1,139 +0,0 @@ -import pytest - -from .._headers import * - - -def test_normalize_and_validate(): - assert normalize_and_validate([("foo", "bar")]) == [(b"foo", b"bar")] - assert normalize_and_validate([(b"foo", b"bar")]) == [(b"foo", b"bar")] - - # no leading/trailing whitespace in names - with pytest.raises(LocalProtocolError): - normalize_and_validate([(b"foo ", "bar")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([(b" foo", "bar")]) - - # no weird characters in names - with pytest.raises(LocalProtocolError) as excinfo: - normalize_and_validate([(b"foo bar", b"baz")]) - assert "foo bar" in str(excinfo.value) - with pytest.raises(LocalProtocolError): - normalize_and_validate([(b"foo\x00bar", b"baz")]) - # Not even 8-bit characters: - with pytest.raises(LocalProtocolError): - normalize_and_validate([(b"foo\xffbar", b"baz")]) - # And not even the control characters we allow in values: - with pytest.raises(LocalProtocolError): - normalize_and_validate([(b"foo\x01bar", b"baz")]) - - # no return or NUL characters in values - with pytest.raises(LocalProtocolError) as excinfo: - normalize_and_validate([("foo", "bar\rbaz")]) - assert "bar\\rbaz" in str(excinfo.value) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", "bar\nbaz")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", "bar\x00baz")]) - # no leading/trailing whitespace - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", "barbaz ")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", " barbaz")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", "barbaz\t")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("foo", "\tbarbaz")]) - - # content-length - assert normalize_and_validate([("Content-Length", "1")]) == [ - (b"content-length", b"1") - ] - with pytest.raises(LocalProtocolError): - normalize_and_validate([("Content-Length", "asdf")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("Content-Length", "1x")]) - with pytest.raises(LocalProtocolError): - normalize_and_validate([("Content-Length", "1"), ("Content-Length", "2")]) - - # transfer-encoding - assert normalize_and_validate([("Transfer-Encoding", "chunked")]) == [ - (b"transfer-encoding", b"chunked") - ] - assert normalize_and_validate([("Transfer-Encoding", "cHuNkEd")]) == [ - (b"transfer-encoding", b"chunked") - ] - with pytest.raises(LocalProtocolError) as excinfo: - normalize_and_validate([("Transfer-Encoding", "gzip")]) - assert excinfo.value.error_status_hint == 501 # Not Implemented - with pytest.raises(LocalProtocolError) as excinfo: - normalize_and_validate( - [("Transfer-Encoding", "chunked"), ("Transfer-Encoding", "gzip")] - ) - assert excinfo.value.error_status_hint == 501 # Not Implemented - - -def test_get_set_comma_header(): - headers = normalize_and_validate( - [ - ("Connection", "close"), - ("whatever", "something"), - ("connectiON", "fOo,, , BAR"), - ] - ) - - assert get_comma_header(headers, b"connection") == [b"close", b"foo", b"bar"] - - set_comma_header(headers, b"newthing", ["a", "b"]) - - with pytest.raises(LocalProtocolError): - set_comma_header(headers, b"newthing", [" a", "b"]) - - assert headers == [ - (b"connection", b"close"), - (b"whatever", b"something"), - (b"connection", b"fOo,, , BAR"), - (b"newthing", b"a"), - (b"newthing", b"b"), - ] - - set_comma_header(headers, b"whatever", ["different thing"]) - - assert headers == [ - (b"connection", b"close"), - (b"connection", b"fOo,, , BAR"), - (b"newthing", b"a"), - (b"newthing", b"b"), - (b"whatever", b"different thing"), - ] - - -def test_has_100_continue(): - from .._events import Request - - assert has_expect_100_continue( - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Expect", "100-continue")], - ) - ) - assert not has_expect_100_continue( - Request(method="GET", target="/", headers=[("Host", "example.com")]) - ) - # Case insensitive - assert has_expect_100_continue( - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Expect", "100-Continue")], - ) - ) - # Doesn't work in HTTP/1.0 - assert not has_expect_100_continue( - Request( - method="GET", - target="/", - headers=[("Host", "example.com"), ("Expect", "100-continue")], - http_version="1.0", - ) - ) diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_helpers.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_helpers.py deleted file mode 100644 index 1477947..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_helpers.py +++ /dev/null @@ -1,23 +0,0 @@ -from .helpers import * - - -def test_normalize_data_events(): - assert normalize_data_events( - [ - Data(data=bytearray(b"1")), - Data(data=b"2"), - Response(status_code=200, headers=[]), - Data(data=b"3"), - Data(data=b"4"), - EndOfMessage(), - Data(data=b"5"), - Data(data=b"6"), - Data(data=b"7"), - ] - ) == [ - Data(data=b"12"), - Response(status_code=200, headers=[]), - Data(data=b"34"), - EndOfMessage(), - Data(data=b"567"), - ] diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_io.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_io.py deleted file mode 100644 index ef5e31b..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_io.py +++ /dev/null @@ -1,507 +0,0 @@ -import pytest - -from .._events import * -from .._headers import normalize_and_validate -from .._readers import ( - _obsolete_line_fold, - ChunkedReader, - ContentLengthReader, - Http10Reader, - READERS, -) -from .._receivebuffer import ReceiveBuffer -from .._state import * -from .._util import LocalProtocolError -from .._writers import ( - ChunkedWriter, - ContentLengthWriter, - Http10Writer, - write_any_response, - write_headers, - write_request, - WRITERS, -) -from .helpers import normalize_data_events - -SIMPLE_CASES = [ - ( - (CLIENT, IDLE), - Request( - method="GET", - target="/a", - headers=[("Host", "foo"), ("Connection", "close")], - ), - b"GET /a HTTP/1.1\r\nhost: foo\r\nconnection: close\r\n\r\n", - ), - ( - (SERVER, SEND_RESPONSE), - Response(status_code=200, headers=[("Connection", "close")], reason=b"OK"), - b"HTTP/1.1 200 OK\r\nconnection: close\r\n\r\n", - ), - ( - (SERVER, SEND_RESPONSE), - Response(status_code=200, headers=[], reason=b"OK"), - b"HTTP/1.1 200 OK\r\n\r\n", - ), - ( - (SERVER, SEND_RESPONSE), - InformationalResponse( - status_code=101, headers=[("Upgrade", "websocket")], reason=b"Upgrade" - ), - b"HTTP/1.1 101 Upgrade\r\nupgrade: websocket\r\n\r\n", - ), - ( - (SERVER, SEND_RESPONSE), - InformationalResponse(status_code=101, headers=[], reason=b"Upgrade"), - b"HTTP/1.1 101 Upgrade\r\n\r\n", - ), -] - - -def dowrite(writer, obj): - got_list = [] - writer(obj, got_list.append) - return b"".join(got_list) - - -def tw(writer, obj, expected): - got = dowrite(writer, obj) - assert got == expected - - -def makebuf(data): - buf = ReceiveBuffer() - buf += data - return buf - - -def tr(reader, data, expected): - def check(got): - assert got == expected - # Headers should always be returned as bytes, not e.g. bytearray - # https://github.com/python-hyper/wsproto/pull/54#issuecomment-377709478 - for name, value in getattr(got, "headers", []): - print(name, value) - assert type(name) is bytes - assert type(value) is bytes - - # Simple: consume whole thing - buf = makebuf(data) - check(reader(buf)) - assert not buf - - # Incrementally growing buffer - buf = ReceiveBuffer() - for i in range(len(data)): - assert reader(buf) is None - buf += data[i : i + 1] - check(reader(buf)) - - # Trailing data - buf = makebuf(data) - buf += b"trailing" - check(reader(buf)) - assert bytes(buf) == b"trailing" - - -def test_writers_simple(): - for ((role, state), event, binary) in SIMPLE_CASES: - tw(WRITERS[role, state], event, binary) - - -def test_readers_simple(): - for ((role, state), event, binary) in SIMPLE_CASES: - tr(READERS[role, state], binary, event) - - -def test_writers_unusual(): - # Simple test of the write_headers utility routine - tw( - write_headers, - normalize_and_validate([("foo", "bar"), ("baz", "quux")]), - b"foo: bar\r\nbaz: quux\r\n\r\n", - ) - tw(write_headers, [], b"\r\n") - - # We understand HTTP/1.0, but we don't speak it - with pytest.raises(LocalProtocolError): - tw( - write_request, - Request( - method="GET", - target="/", - headers=[("Host", "foo"), ("Connection", "close")], - http_version="1.0", - ), - None, - ) - with pytest.raises(LocalProtocolError): - tw( - write_any_response, - Response( - status_code=200, headers=[("Connection", "close")], http_version="1.0" - ), - None, - ) - - -def test_readers_unusual(): - # Reading HTTP/1.0 - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.0\r\nSome: header\r\n\r\n", - Request( - method="HEAD", - target="/foo", - headers=[("Some", "header")], - http_version="1.0", - ), - ) - - # check no-headers, since it's only legal with HTTP/1.0 - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.0\r\n\r\n", - Request(method="HEAD", target="/foo", headers=[], http_version="1.0"), - ) - - tr( - READERS[SERVER, SEND_RESPONSE], - b"HTTP/1.0 200 OK\r\nSome: header\r\n\r\n", - Response( - status_code=200, - headers=[("Some", "header")], - http_version="1.0", - reason=b"OK", - ), - ) - - # single-character header values (actually disallowed by the ABNF in RFC - # 7230 -- this is a bug in the standard that we originally copied...) - tr( - READERS[SERVER, SEND_RESPONSE], - b"HTTP/1.0 200 OK\r\n" b"Foo: a a a a a \r\n\r\n", - Response( - status_code=200, - headers=[("Foo", "a a a a a")], - http_version="1.0", - reason=b"OK", - ), - ) - - # Empty headers -- also legal - tr( - READERS[SERVER, SEND_RESPONSE], - b"HTTP/1.0 200 OK\r\n" b"Foo:\r\n\r\n", - Response( - status_code=200, headers=[("Foo", "")], http_version="1.0", reason=b"OK" - ), - ) - - tr( - READERS[SERVER, SEND_RESPONSE], - b"HTTP/1.0 200 OK\r\n" b"Foo: \t \t \r\n\r\n", - Response( - status_code=200, headers=[("Foo", "")], http_version="1.0", reason=b"OK" - ), - ) - - # Tolerate broken servers that leave off the response code - tr( - READERS[SERVER, SEND_RESPONSE], - b"HTTP/1.0 200\r\n" b"Foo: bar\r\n\r\n", - Response( - status_code=200, headers=[("Foo", "bar")], http_version="1.0", reason=b"" - ), - ) - - # obsolete line folding - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" - b"Host: example.com\r\n" - b"Some: multi-line\r\n" - b" header\r\n" - b"\tnonsense\r\n" - b" \t \t\tI guess\r\n" - b"Connection: close\r\n" - b"More-nonsense: in the\r\n" - b" last header \r\n\r\n", - Request( - method="HEAD", - target="/foo", - headers=[ - ("Host", "example.com"), - ("Some", "multi-line header nonsense I guess"), - ("Connection", "close"), - ("More-nonsense", "in the last header"), - ], - ), - ) - - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" b" folded: line\r\n\r\n", - None, - ) - - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" b"foo : line\r\n\r\n", - None, - ) - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" b"foo\t: line\r\n\r\n", - None, - ) - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" b"foo\t: line\r\n\r\n", - None, - ) - with pytest.raises(LocalProtocolError): - tr(READERS[CLIENT, IDLE], b"HEAD /foo HTTP/1.1\r\n" b": line\r\n\r\n", None) - - -def test__obsolete_line_fold_bytes(): - # _obsolete_line_fold has a defensive cast to bytearray, which is - # necessary to protect against O(n^2) behavior in case anyone ever passes - # in regular bytestrings... but right now we never pass in regular - # bytestrings. so this test just exists to get some coverage on that - # defensive cast. - assert list(_obsolete_line_fold([b"aaa", b"bbb", b" ccc", b"ddd"])) == [ - b"aaa", - bytearray(b"bbb ccc"), - b"ddd", - ] - - -def _run_reader_iter(reader, buf, do_eof): - while True: - event = reader(buf) - if event is None: - break - yield event - # body readers have undefined behavior after returning EndOfMessage, - # because this changes the state so they don't get called again - if type(event) is EndOfMessage: - break - if do_eof: - assert not buf - yield reader.read_eof() - - -def _run_reader(*args): - events = list(_run_reader_iter(*args)) - return normalize_data_events(events) - - -def t_body_reader(thunk, data, expected, do_eof=False): - # Simple: consume whole thing - print("Test 1") - buf = makebuf(data) - assert _run_reader(thunk(), buf, do_eof) == expected - - # Incrementally growing buffer - print("Test 2") - reader = thunk() - buf = ReceiveBuffer() - events = [] - for i in range(len(data)): - events += _run_reader(reader, buf, False) - buf += data[i : i + 1] - events += _run_reader(reader, buf, do_eof) - assert normalize_data_events(events) == expected - - is_complete = any(type(event) is EndOfMessage for event in expected) - if is_complete and not do_eof: - buf = makebuf(data + b"trailing") - assert _run_reader(thunk(), buf, False) == expected - - -def test_ContentLengthReader(): - t_body_reader(lambda: ContentLengthReader(0), b"", [EndOfMessage()]) - - t_body_reader( - lambda: ContentLengthReader(10), - b"0123456789", - [Data(data=b"0123456789"), EndOfMessage()], - ) - - -def test_Http10Reader(): - t_body_reader(Http10Reader, b"", [EndOfMessage()], do_eof=True) - t_body_reader(Http10Reader, b"asdf", [Data(data=b"asdf")], do_eof=False) - t_body_reader( - Http10Reader, b"asdf", [Data(data=b"asdf"), EndOfMessage()], do_eof=True - ) - - -def test_ChunkedReader(): - t_body_reader(ChunkedReader, b"0\r\n\r\n", [EndOfMessage()]) - - t_body_reader( - ChunkedReader, - b"0\r\nSome: header\r\n\r\n", - [EndOfMessage(headers=[("Some", "header")])], - ) - - t_body_reader( - ChunkedReader, - b"5\r\n01234\r\n" - + b"10\r\n0123456789abcdef\r\n" - + b"0\r\n" - + b"Some: header\r\n\r\n", - [ - Data(data=b"012340123456789abcdef"), - EndOfMessage(headers=[("Some", "header")]), - ], - ) - - t_body_reader( - ChunkedReader, - b"5\r\n01234\r\n" + b"10\r\n0123456789abcdef\r\n" + b"0\r\n\r\n", - [Data(data=b"012340123456789abcdef"), EndOfMessage()], - ) - - # handles upper and lowercase hex - t_body_reader( - ChunkedReader, - b"aA\r\n" + b"x" * 0xAA + b"\r\n" + b"0\r\n\r\n", - [Data(data=b"x" * 0xAA), EndOfMessage()], - ) - - # refuses arbitrarily long chunk integers - with pytest.raises(LocalProtocolError): - # Technically this is legal HTTP/1.1, but we refuse to process chunk - # sizes that don't fit into 20 characters of hex - t_body_reader(ChunkedReader, b"9" * 100 + b"\r\nxxx", [Data(data=b"xxx")]) - - # refuses garbage in the chunk count - with pytest.raises(LocalProtocolError): - t_body_reader(ChunkedReader, b"10\x00\r\nxxx", None) - - # handles (and discards) "chunk extensions" omg wtf - t_body_reader( - ChunkedReader, - b"5; hello=there\r\n" - + b"xxxxx" - + b"\r\n" - + b'0; random="junk"; some=more; canbe=lonnnnngg\r\n\r\n', - [Data(data=b"xxxxx"), EndOfMessage()], - ) - - -def test_ContentLengthWriter(): - w = ContentLengthWriter(5) - assert dowrite(w, Data(data=b"123")) == b"123" - assert dowrite(w, Data(data=b"45")) == b"45" - assert dowrite(w, EndOfMessage()) == b"" - - w = ContentLengthWriter(5) - with pytest.raises(LocalProtocolError): - dowrite(w, Data(data=b"123456")) - - w = ContentLengthWriter(5) - dowrite(w, Data(data=b"123")) - with pytest.raises(LocalProtocolError): - dowrite(w, Data(data=b"456")) - - w = ContentLengthWriter(5) - dowrite(w, Data(data=b"123")) - with pytest.raises(LocalProtocolError): - dowrite(w, EndOfMessage()) - - w = ContentLengthWriter(5) - dowrite(w, Data(data=b"123")) == b"123" - dowrite(w, Data(data=b"45")) == b"45" - with pytest.raises(LocalProtocolError): - dowrite(w, EndOfMessage(headers=[("Etag", "asdf")])) - - -def test_ChunkedWriter(): - w = ChunkedWriter() - assert dowrite(w, Data(data=b"aaa")) == b"3\r\naaa\r\n" - assert dowrite(w, Data(data=b"a" * 20)) == b"14\r\n" + b"a" * 20 + b"\r\n" - - assert dowrite(w, Data(data=b"")) == b"" - - assert dowrite(w, EndOfMessage()) == b"0\r\n\r\n" - - assert ( - dowrite(w, EndOfMessage(headers=[("Etag", "asdf"), ("a", "b")])) - == b"0\r\netag: asdf\r\na: b\r\n\r\n" - ) - - -def test_Http10Writer(): - w = Http10Writer() - assert dowrite(w, Data(data=b"1234")) == b"1234" - assert dowrite(w, EndOfMessage()) == b"" - - with pytest.raises(LocalProtocolError): - dowrite(w, EndOfMessage(headers=[("Etag", "asdf")])) - - -def test_reject_garbage_after_request_line(): - with pytest.raises(LocalProtocolError): - tr(READERS[SERVER, SEND_RESPONSE], b"HTTP/1.0 200 OK\x00xxxx\r\n\r\n", None) - - -def test_reject_garbage_after_response_line(): - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1 xxxxxx\r\n" b"Host: a\r\n\r\n", - None, - ) - - -def test_reject_garbage_in_header_line(): - with pytest.raises(LocalProtocolError): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" b"Host: foo\x00bar\r\n\r\n", - None, - ) - - -def test_reject_non_vchar_in_path(): - for bad_char in b"\x00\x20\x7f\xee": - message = bytearray(b"HEAD /") - message.append(bad_char) - message.extend(b" HTTP/1.1\r\nHost: foobar\r\n\r\n") - with pytest.raises(LocalProtocolError): - tr(READERS[CLIENT, IDLE], message, None) - - -# https://github.com/python-hyper/h11/issues/57 -def test_allow_some_garbage_in_cookies(): - tr( - READERS[CLIENT, IDLE], - b"HEAD /foo HTTP/1.1\r\n" - b"Host: foo\r\n" - b"Set-Cookie: ___utmvafIumyLc=kUd\x01UpAt; path=/; Max-Age=900\r\n" - b"\r\n", - Request( - method="HEAD", - target="/foo", - headers=[ - ("Host", "foo"), - ("Set-Cookie", "___utmvafIumyLc=kUd\x01UpAt; path=/; Max-Age=900"), - ], - ), - ) - - -def test_host_comes_first(): - tw( - write_headers, - normalize_and_validate([("foo", "bar"), ("Host", "example.com")]), - b"host: example.com\r\nfoo: bar\r\n\r\n", - ) diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_receivebuffer.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_receivebuffer.py deleted file mode 100644 index 2be220b..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_receivebuffer.py +++ /dev/null @@ -1,78 +0,0 @@ -from .._receivebuffer import ReceiveBuffer - - -def test_receivebuffer(): - b = ReceiveBuffer() - assert not b - assert len(b) == 0 - assert bytes(b) == b"" - - b += b"123" - assert b - assert len(b) == 3 - assert bytes(b) == b"123" - - b.compress() - assert bytes(b) == b"123" - - assert b.maybe_extract_at_most(2) == b"12" - assert b - assert len(b) == 1 - assert bytes(b) == b"3" - - b.compress() - assert bytes(b) == b"3" - - assert b.maybe_extract_at_most(10) == b"3" - assert bytes(b) == b"" - - assert b.maybe_extract_at_most(10) is None - assert not b - - ################################################################ - # maybe_extract_until_next - ################################################################ - - b += b"12345a6789aa" - - assert b.maybe_extract_until_next(b"a") == b"12345a" - assert bytes(b) == b"6789aa" - - assert b.maybe_extract_until_next(b"aaa") is None - assert bytes(b) == b"6789aa" - - b += b"a12" - assert b.maybe_extract_until_next(b"aaa") == b"6789aaa" - assert bytes(b) == b"12" - - # check repeated searches for the same needle, triggering the - # pickup-where-we-left-off logic - b += b"345" - assert b.maybe_extract_until_next(b"aaa") is None - - b += b"6789aaa123" - assert b.maybe_extract_until_next(b"aaa") == b"123456789aaa" - assert bytes(b) == b"123" - - ################################################################ - # maybe_extract_lines - ################################################################ - - b += b"\r\na: b\r\nfoo:bar\r\n\r\ntrailing" - lines = b.maybe_extract_lines() - assert lines == [b"123", b"a: b", b"foo:bar"] - assert bytes(b) == b"trailing" - - assert b.maybe_extract_lines() is None - - b += b"\r\n\r" - assert b.maybe_extract_lines() is None - - assert b.maybe_extract_at_most(100) == b"trailing\r\n\r" - assert not b - - # Empty body case (as happens at the end of chunked encoding if there are - # no trailing headers, e.g.) - b += b"\r\ntrailing" - assert b.maybe_extract_lines() == [] - assert bytes(b) == b"trailing" diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_state.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_state.py deleted file mode 100644 index efe83f0..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_state.py +++ /dev/null @@ -1,250 +0,0 @@ -import pytest - -from .._events import * -from .._state import * -from .._state import _SWITCH_CONNECT, _SWITCH_UPGRADE, ConnectionState -from .._util import LocalProtocolError - - -def test_ConnectionState(): - cs = ConnectionState() - - # Basic event-triggered transitions - - assert cs.states == {CLIENT: IDLE, SERVER: IDLE} - - cs.process_event(CLIENT, Request) - # The SERVER-Request special case: - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - # Illegal transitions raise an error and nothing happens - with pytest.raises(LocalProtocolError): - cs.process_event(CLIENT, Request) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - cs.process_event(SERVER, InformationalResponse) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - cs.process_event(SERVER, Response) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_BODY} - - cs.process_event(CLIENT, EndOfMessage) - cs.process_event(SERVER, EndOfMessage) - assert cs.states == {CLIENT: DONE, SERVER: DONE} - - # State-triggered transition - - cs.process_event(SERVER, ConnectionClosed) - assert cs.states == {CLIENT: MUST_CLOSE, SERVER: CLOSED} - - -def test_ConnectionState_keep_alive(): - # keep_alive = False - cs = ConnectionState() - cs.process_event(CLIENT, Request) - cs.process_keep_alive_disabled() - cs.process_event(CLIENT, EndOfMessage) - assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_RESPONSE} - - cs.process_event(SERVER, Response) - cs.process_event(SERVER, EndOfMessage) - assert cs.states == {CLIENT: MUST_CLOSE, SERVER: MUST_CLOSE} - - -def test_ConnectionState_keep_alive_in_DONE(): - # Check that if keep_alive is disabled when the CLIENT is already in DONE, - # then this is sufficient to immediately trigger the DONE -> MUST_CLOSE - # transition - cs = ConnectionState() - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - assert cs.states[CLIENT] is DONE - cs.process_keep_alive_disabled() - assert cs.states[CLIENT] is MUST_CLOSE - - -def test_ConnectionState_switch_denied(): - for switch_type in (_SWITCH_CONNECT, _SWITCH_UPGRADE): - for deny_early in (True, False): - cs = ConnectionState() - cs.process_client_switch_proposal(switch_type) - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, Data) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - assert switch_type in cs.pending_switch_proposals - - if deny_early: - # before client reaches DONE - cs.process_event(SERVER, Response) - assert not cs.pending_switch_proposals - - cs.process_event(CLIENT, EndOfMessage) - - if deny_early: - assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} - else: - assert cs.states == { - CLIENT: MIGHT_SWITCH_PROTOCOL, - SERVER: SEND_RESPONSE, - } - - cs.process_event(SERVER, InformationalResponse) - assert cs.states == { - CLIENT: MIGHT_SWITCH_PROTOCOL, - SERVER: SEND_RESPONSE, - } - - cs.process_event(SERVER, Response) - assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} - assert not cs.pending_switch_proposals - - -_response_type_for_switch = { - _SWITCH_UPGRADE: InformationalResponse, - _SWITCH_CONNECT: Response, - None: Response, -} - - -def test_ConnectionState_protocol_switch_accepted(): - for switch_event in [_SWITCH_UPGRADE, _SWITCH_CONNECT]: - cs = ConnectionState() - cs.process_client_switch_proposal(switch_event) - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, Data) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - cs.process_event(CLIENT, EndOfMessage) - assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} - - cs.process_event(SERVER, InformationalResponse) - assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} - - cs.process_event(SERVER, _response_type_for_switch[switch_event], switch_event) - assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} - - -def test_ConnectionState_double_protocol_switch(): - # CONNECT + Upgrade is legal! Very silly, but legal. So we support - # it. Because sometimes doing the silly thing is easier than not. - for server_switch in [None, _SWITCH_UPGRADE, _SWITCH_CONNECT]: - cs = ConnectionState() - cs.process_client_switch_proposal(_SWITCH_UPGRADE) - cs.process_client_switch_proposal(_SWITCH_CONNECT) - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} - cs.process_event( - SERVER, _response_type_for_switch[server_switch], server_switch - ) - if server_switch is None: - assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} - else: - assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} - - -def test_ConnectionState_inconsistent_protocol_switch(): - for client_switches, server_switch in [ - ([], _SWITCH_CONNECT), - ([], _SWITCH_UPGRADE), - ([_SWITCH_UPGRADE], _SWITCH_CONNECT), - ([_SWITCH_CONNECT], _SWITCH_UPGRADE), - ]: - cs = ConnectionState() - for client_switch in client_switches: - cs.process_client_switch_proposal(client_switch) - cs.process_event(CLIENT, Request) - with pytest.raises(LocalProtocolError): - cs.process_event(SERVER, Response, server_switch) - - -def test_ConnectionState_keepalive_protocol_switch_interaction(): - # keep_alive=False + pending_switch_proposals - cs = ConnectionState() - cs.process_client_switch_proposal(_SWITCH_UPGRADE) - cs.process_event(CLIENT, Request) - cs.process_keep_alive_disabled() - cs.process_event(CLIENT, Data) - assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} - - # the protocol switch "wins" - cs.process_event(CLIENT, EndOfMessage) - assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} - - # but when the server denies the request, keep_alive comes back into play - cs.process_event(SERVER, Response) - assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_BODY} - - -def test_ConnectionState_reuse(): - cs = ConnectionState() - - with pytest.raises(LocalProtocolError): - cs.start_next_cycle() - - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - - with pytest.raises(LocalProtocolError): - cs.start_next_cycle() - - cs.process_event(SERVER, Response) - cs.process_event(SERVER, EndOfMessage) - - cs.start_next_cycle() - assert cs.states == {CLIENT: IDLE, SERVER: IDLE} - - # No keepalive - - cs.process_event(CLIENT, Request) - cs.process_keep_alive_disabled() - cs.process_event(CLIENT, EndOfMessage) - cs.process_event(SERVER, Response) - cs.process_event(SERVER, EndOfMessage) - - with pytest.raises(LocalProtocolError): - cs.start_next_cycle() - - # One side closed - - cs = ConnectionState() - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - cs.process_event(CLIENT, ConnectionClosed) - cs.process_event(SERVER, Response) - cs.process_event(SERVER, EndOfMessage) - - with pytest.raises(LocalProtocolError): - cs.start_next_cycle() - - # Succesful protocol switch - - cs = ConnectionState() - cs.process_client_switch_proposal(_SWITCH_UPGRADE) - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - cs.process_event(SERVER, InformationalResponse, _SWITCH_UPGRADE) - - with pytest.raises(LocalProtocolError): - cs.start_next_cycle() - - # Failed protocol switch - - cs = ConnectionState() - cs.process_client_switch_proposal(_SWITCH_UPGRADE) - cs.process_event(CLIENT, Request) - cs.process_event(CLIENT, EndOfMessage) - cs.process_event(SERVER, Response) - cs.process_event(SERVER, EndOfMessage) - - cs.start_next_cycle() - assert cs.states == {CLIENT: IDLE, SERVER: IDLE} - - -def test_server_request_is_illegal(): - # There used to be a bug in how we handled the Request special case that - # made this allowed... - cs = ConnectionState() - with pytest.raises(LocalProtocolError): - cs.process_event(SERVER, Request) diff --git a/py3.7/lib/python3.7/site-packages/h11/tests/test_util.py b/py3.7/lib/python3.7/site-packages/h11/tests/test_util.py deleted file mode 100644 index 74ab33b..0000000 --- a/py3.7/lib/python3.7/site-packages/h11/tests/test_util.py +++ /dev/null @@ -1,99 +0,0 @@ -import re -import sys -import traceback - -import pytest - -from .._util import * - - -def test_ProtocolError(): - with pytest.raises(TypeError): - ProtocolError("abstract base class") - - -def test_LocalProtocolError(): - try: - raise LocalProtocolError("foo") - except LocalProtocolError as e: - assert str(e) == "foo" - assert e.error_status_hint == 400 - - try: - raise LocalProtocolError("foo", error_status_hint=418) - except LocalProtocolError as e: - assert str(e) == "foo" - assert e.error_status_hint == 418 - - def thunk(): - raise LocalProtocolError("a", error_status_hint=420) - - try: - try: - thunk() - except LocalProtocolError as exc1: - orig_traceback = "".join(traceback.format_tb(sys.exc_info()[2])) - exc1._reraise_as_remote_protocol_error() - except RemoteProtocolError as exc2: - assert type(exc2) is RemoteProtocolError - assert exc2.args == ("a",) - assert exc2.error_status_hint == 420 - new_traceback = "".join(traceback.format_tb(sys.exc_info()[2])) - assert new_traceback.endswith(orig_traceback) - - -def test_validate(): - my_re = re.compile(br"(?P[0-9]+)\.(?P[0-9]+)") - with pytest.raises(LocalProtocolError): - validate(my_re, b"0.") - - groups = validate(my_re, b"0.1") - assert groups == {"group1": b"0", "group2": b"1"} - - # successful partial matches are an error - must match whole string - with pytest.raises(LocalProtocolError): - validate(my_re, b"0.1xx") - with pytest.raises(LocalProtocolError): - validate(my_re, b"0.1\n") - - -def test_validate_formatting(): - my_re = re.compile(br"foo") - - with pytest.raises(LocalProtocolError) as excinfo: - validate(my_re, b"", "oops") - assert "oops" in str(excinfo.value) - - with pytest.raises(LocalProtocolError) as excinfo: - validate(my_re, b"", "oops {}") - assert "oops {}" in str(excinfo.value) - - with pytest.raises(LocalProtocolError) as excinfo: - validate(my_re, b"", "oops {} xx", 10) - assert "oops 10 xx" in str(excinfo.value) - - -def test_make_sentinel(): - S = make_sentinel("S") - assert repr(S) == "S" - assert S == S - assert type(S).__name__ == "S" - assert S in {S} - assert type(S) is S - S2 = make_sentinel("S2") - assert repr(S2) == "S2" - assert S != S2 - assert S not in {S2} - assert type(S) is not type(S2) - - -def test_bytesify(): - assert bytesify(b"123") == b"123" - assert bytesify(bytearray(b"123")) == b"123" - assert bytesify("123") == b"123" - - with pytest.raises(UnicodeEncodeError): - bytesify(u"\u1234") - - with pytest.raises(TypeError): - bytesify(10) diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/LICENSE deleted file mode 100644 index 7bb76c5..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015-2016 Cory Benfield and contributors - -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. diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/METADATA deleted file mode 100644 index aebc479..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/METADATA +++ /dev/null @@ -1,828 +0,0 @@ -Metadata-Version: 2.1 -Name: h2 -Version: 3.1.0 -Summary: HTTP/2 State-Machine based protocol implementation -Home-page: http://hyper.rtfd.org -Author: Cory Benfield -Author-email: cory@lukasa.co.uk -License: MIT License -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Dist: hyperframe (<6,>=5.2.0) -Requires-Dist: hpack (<4,>=2.3) -Requires-Dist: enum34 (<2,>=1.1.6) ; python_version == "2.7" or python_version == "3.3" - -=============================== -hyper-h2: HTTP/2 Protocol Stack -=============================== - -.. image:: https://raw.github.com/Lukasa/hyper/development/docs/source/images/hyper.png - -.. image:: https://travis-ci.org/python-hyper/hyper-h2.svg?branch=master - :target: https://travis-ci.org/python-hyper/hyper-h2 - -This repository contains a pure-Python implementation of a HTTP/2 protocol -stack. It's written from the ground up to be embeddable in whatever program you -choose to use, ensuring that you can speak HTTP/2 regardless of your -programming paradigm. - -You use it like this: - -.. code-block:: python - - import h2.connection - - conn = h2.connection.H2Connection() - conn.send_headers(stream_id=stream_id, headers=headers) - conn.send_data(stream_id, data) - socket.sendall(conn.data_to_send()) - events = conn.receive_data(socket_data) - -This repository does not provide a parsing layer, a network layer, or any rules -about concurrency. Instead, it's a purely in-memory solution, defined in terms -of data actions and HTTP/2 frames. This is one building block of a full Python -HTTP implementation. - -To install it, just run: - -.. code-block:: console - - $ pip install h2 - -Documentation -============= - -Documentation is available at http://python-hyper.org/h2/. - -Contributing -============ - -``hyper-h2`` welcomes contributions from anyone! Unlike many other projects we -are happy to accept cosmetic contributions and small contributions, in addition -to large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://python-hyper.org/en/latest/contributing.html - -License -======= - -``hyper-h2`` is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -``hyper-h2`` is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. - - -Release History -=============== - -3.1.0 (2019-01-22) ------------------- - -API Changes (Backward-Incompatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- ``h2.connection.H2Connection.data_to_send`` first and only argument ``amt`` - was renamed to ``amount``. -- Support for Python 3.3 has been removed. - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- ``h2.connection.H2Connection.send_data`` now supports ``data`` parameter - being a ``memoryview`` object. -- Refactor ping-related events: a ``h2.events.PingReceived`` event is fired - when a PING frame is received and a ``h2.events.PingAckReceived`` event is - fired when a PING frame with an ACK flag is received. - ``h2.events.PingAcknowledged`` is deprecated in favour of the identical - ``h2.events.PingAckReceived``. -- Added ``ENABLE_CONNECT_PROTOCOL`` to ``h2.settings.SettingCodes``. -- Support ``CONNECT`` requests with a ``:protocol`` pseudo header - thereby supporting RFC 8441. -- A limit to the number of closed streams kept in memory by the - connection is applied. It can be configured by - ``h2.connection.H2Connection.MAX_CLOSED_STREAMS``. - -Bugfixes -~~~~~~~~ - -- Debug logging when stream_id is None is now fixed and no longer errors. - -3.0.1 (2017-04-03) ------------------- - -Bugfixes -~~~~~~~~ - -- CONTINUATION frames sent on closed streams previously caused stream errors - of type STREAM_CLOSED. RFC 7540 § 6.10 requires that these be connection - errors of type PROTOCOL_ERROR, and so this release changes to match that - behaviour. -- Remote peers incrementing their inbound connection window beyond the maximum - allowed value now cause stream-level errors, rather than connection-level - errors, allowing connections to stay up longer. -- h2 now rejects receiving and sending request header blocks that are missing - any of the mandatory pseudo-header fields (:path, :scheme, and :method). -- h2 now rejects receiving and sending request header blocks that have an empty - :path pseudo-header value. -- h2 now rejects receiving and sending request header blocks that contain - response-only pseudo-headers, and vice versa. -- h2 now correct respects user-initiated changes to the HEADER_TABLE_SIZE - local setting, and ensures that if users shrink or increase the header - table size it is policed appropriately. - - -2.6.2 (2017-04-03) ------------------- - -Bugfixes -~~~~~~~~ - -- CONTINUATION frames sent on closed streams previously caused stream errors - of type STREAM_CLOSED. RFC 7540 § 6.10 requires that these be connection - errors of type PROTOCOL_ERROR, and so this release changes to match that - behaviour. -- Remote peers incrementing their inbound connection window beyond the maximum - allowed value now cause stream-level errors, rather than connection-level - errors, allowing connections to stay up longer. -- h2 now rejects receiving and sending request header blocks that are missing - any of the mandatory pseudo-header fields (:path, :scheme, and :method). -- h2 now rejects receiving and sending request header blocks that have an empty - :path pseudo-header value. -- h2 now rejects receiving and sending request header blocks that contain - response-only pseudo-headers, and vice versa. -- h2 now correct respects user-initiated changes to the HEADER_TABLE_SIZE - local setting, and ensures that if users shrink or increase the header - table size it is policed appropriately. - - -2.5.4 (2017-04-03) ------------------- - -Bugfixes -~~~~~~~~ - -- CONTINUATION frames sent on closed streams previously caused stream errors - of type STREAM_CLOSED. RFC 7540 § 6.10 requires that these be connection - errors of type PROTOCOL_ERROR, and so this release changes to match that - behaviour. -- Remote peers incrementing their inbound connection window beyond the maximum - allowed value now cause stream-level errors, rather than connection-level - errors, allowing connections to stay up longer. -- h2 now correct respects user-initiated changes to the HEADER_TABLE_SIZE - local setting, and ensures that if users shrink or increase the header - table size it is policed appropriately. - - -3.0.0 (2017-03-24) ------------------- - -API Changes (Backward-Incompatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- By default, hyper-h2 now joins together received cookie header fields, per - RFC 7540 Section 8.1.2.5. -- Added a ``normalize_inbound_headers`` flag to the ``H2Configuration`` object - that defaults to ``True``. Setting this to ``False`` changes the behaviour - from the previous point back to the v2 behaviour. -- Removed deprecated fields from ``h2.errors`` module. -- Removed deprecated fields from ``h2.settings`` module. -- Removed deprecated ``client_side`` and ``header_encoding`` arguments from - ``H2Connection``. -- Removed deprecated ``client_side`` and ``header_encoding`` properties from - ``H2Connection``. -- ``dict`` objects are no longer allowed for user-supplied headers. -- The default header encoding is now ``None``, not ``utf-8``: this means that - all events that carry headers now return those headers as byte strings by - default. The header encoding can be set back to ``utf-8`` to restore the old - behaviour. - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added new ``UnknownFrameReceived`` event that fires when unknown extension - frames have been received. This only fires when using hyperframe 5.0 or - later: earlier versions of hyperframe cause us to silently ignore extension - frames. - -Bugfixes -~~~~~~~~ - -None - - -2.6.1 (2017-03-16) ------------------- - -Bugfixes -~~~~~~~~ - -- Allowed hyperframe v5 support while continuing to ignore unexpected frames. - - -2.5.3 (2017-03-16) ------------------- - -Bugfixes -~~~~~~~~ - -- Allowed hyperframe v5 support while continuing to ignore unexpected frames. - - -2.4.4 (2017-03-16) ------------------- - -Bugfixes -~~~~~~~~ - -- Allowed hyperframe v5 support while continuing to ignore unexpected frames. - - -2.6.0 (2017-02-28) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added a new ``h2.events.Event`` class that acts as a base class for all - events. -- Rather than reject outbound Connection-specific headers, h2 will now - normalize the header block by removing them. -- Implement equality for the ``h2.settings.Settings`` class. -- Added ``h2.settings.SettingCodes``, an enum that is used to store all the - HTTP/2 setting codes. This allows us to use a better printed representation of - the setting code in most places that it is used. -- The ``setting`` field in ``ChangedSetting`` for the ``RemoteSettingsChanged`` - and ``SettingsAcknowledged`` events has been updated to be instances of - ``SettingCodes`` whenever they correspond to a known setting code. When they - are an unknown setting code, they are instead ``int``. As ``SettingCodes`` is - a subclass of ``int``, this is non-breaking. -- Deprecated the other fields in ``h2.settings``. These will be removed in - 3.0.0. -- Added an optional ``pad_length`` parameter to ``H2Connection.send_data`` - to allow the user to include padding on a data frame. -- Added a new parameter to the ``h2.config.H2Configuration`` initializer which - takes a logger. This allows us to log by providing a logger that conforms - to the requirements of this module so that it can be used in different - environments. - -Bugfixes -~~~~~~~~ - -- Correctly reject pushed request header blocks whenever they have malformed - request header blocks. -- Correctly normalize pushed request header blocks whenever they have - normalizable header fields. -- Remote peers are now allowed to send zero or any positive number as a value - for ``SETTINGS_MAX_HEADER_LIST_SIZE``, where previously sending zero would - raise a ``InvalidSettingsValueError``. -- Resolved issue where the ``HTTP2-Settings`` header value for plaintext - upgrade that was emitted by ``initiate_upgrade_connection`` included the - *entire* ``SETTINGS`` frame, instead of just the payload. -- Resolved issue where the ``HTTP2-Settings`` header value sent by a client for - plaintext upgrade would be ignored by ``initiate_upgrade_connection``, rather - than have those settings applied appropriately. -- Resolved an issue whereby certain frames received from a peer in the CLOSED - state would trigger connection errors when RFC 7540 says they should have - triggered stream errors instead. Added more detailed stream closure tracking - to ensure we don't throw away connections unnecessarily. - - -2.5.2 (2017-01-27) ------------------- - -- Resolved issue where the ``HTTP2-Settings`` header value for plaintext - upgrade that was emitted by ``initiate_upgrade_connection`` included the - *entire* ``SETTINGS`` frame, instead of just the payload. -- Resolved issue where the ``HTTP2-Settings`` header value sent by a client for - plaintext upgrade would be ignored by ``initiate_upgrade_connection``, rather - than have those settings applied appropriately. - - -2.4.3 (2017-01-27) ------------------- - -- Resolved issue where the ``HTTP2-Settings`` header value for plaintext - upgrade that was emitted by ``initiate_upgrade_connection`` included the - *entire* ``SETTINGS`` frame, instead of just the payload. -- Resolved issue where the ``HTTP2-Settings`` header value sent by a client for - plaintext upgrade would be ignored by ``initiate_upgrade_connection``, rather - than have those settings applied appropriately. - - -2.3.4 (2017-01-27) ------------------- - -- Resolved issue where the ``HTTP2-Settings`` header value for plaintext - upgrade that was emitted by ``initiate_upgrade_connection`` included the - *entire* ``SETTINGS`` frame, instead of just the payload. -- Resolved issue where the ``HTTP2-Settings`` header value sent by a client for - plaintext upgrade would be ignored by ``initiate_upgrade_connection``, rather - than have those settings applied appropriately. - - -2.5.1 (2016-12-17) ------------------- - -Bugfixes -~~~~~~~~ - -- Remote peers are now allowed to send zero or any positive number as a value - for ``SETTINGS_MAX_HEADER_LIST_SIZE``, where previously sending zero would - raise a ``InvalidSettingsValueError``. - - -2.5.0 (2016-10-25) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added a new ``H2Configuration`` object that allows rich configuration of - a ``H2Connection``. This object supersedes the prior keyword arguments to the - ``H2Connection`` object, which are now deprecated and will be removed in 3.0. -- Added support for automated window management via the - ``acknowledge_received_data`` method. See the documentation for more details. -- Added a ``DenialOfServiceError`` that is raised whenever a behaviour that - looks like a DoS attempt is encountered: for example, an overly large - decompressed header list. This is a subclass of ``ProtocolError``. -- Added support for setting and managing ``SETTINGS_MAX_HEADER_LIST_SIZE``. - This setting is now defaulted to 64kB. -- Added ``h2.errors.ErrorCodes``, an enum that is used to store all the HTTP/2 - error codes. This allows us to use a better printed representation of the - error code in most places that it is used. -- The ``error_code`` fields on ``ConnectionTerminated`` and ``StreamReset`` - events have been updated to be instances of ``ErrorCodes`` whenever they - correspond to a known error code. When they are an unknown error code, they - are instead ``int``. As ``ErrorCodes`` is a subclass of ``int``, this is - non-breaking. -- Deprecated the other fields in ``h2.errors``. These will be removed in 3.0.0. - -Bugfixes -~~~~~~~~ - -- Correctly reject request header blocks with neither :authority nor Host - headers, or header blocks which contain mismatched :authority and Host - headers, per RFC 7540 Section 8.1.2.3. -- Correctly expect that responses to HEAD requests will have no body regardless - of the value of the Content-Length header, and reject those that do. -- Correctly refuse to send header blocks that contain neither :authority nor - Host headers, or header blocks which contain mismatched :authority and Host - headers, per RFC 7540 Section 8.1.2.3. -- Hyper-h2 will now reject header field names and values that contain leading - or trailing whitespace. -- Correctly strip leading/trailing whitespace from header field names and - values. -- Correctly refuse to send header blocks with a TE header whose value is not - ``trailers``, per RFC 7540 Section 8.1.2.2. -- Correctly refuse to send header blocks with connection-specific headers, - per RFC 7540 Section 8.1.2.2. -- Correctly refuse to send header blocks that contain duplicate pseudo-header - fields, or with pseudo-header fields that appear after ordinary header fields, - per RFC 7540 Section 8.1.2.1. - - This may cause passing a dictionary as the header block to ``send_headers`` - to throw a ``ProtocolError``, because dictionaries are unordered and so they - may trip this check. Passing dictionaries here is deprecated, and callers - should change to using a sequence of 2-tuples as their header blocks. -- Correctly reject trailers that contain HTTP/2 pseudo-header fields, per RFC - 7540 Section 8.1.2.1. -- Correctly refuse to send trailers that contain HTTP/2 pseudo-header fields, - per RFC 7540 Section 8.1.2.1. -- Correctly reject responses that do not contain the ``:status`` header field, - per RFC 7540 Section 8.1.2.4. -- Correctly refuse to send responses that do not contain the ``:status`` header - field, per RFC 7540 Section 8.1.2.4. -- Correctly update the maximum frame size when the user updates the value of - that setting. Prior to this release, if the user updated the maximum frame - size hyper-h2 would ignore the update, preventing the remote peer from using - the higher frame sizes. - -2.4.2 (2016-10-25) ------------------- - -Bugfixes -~~~~~~~~ - -- Correctly update the maximum frame size when the user updates the value of - that setting. Prior to this release, if the user updated the maximum frame - size hyper-h2 would ignore the update, preventing the remote peer from using - the higher frame sizes. - -2.3.3 (2016-10-25) ------------------- - -Bugfixes -~~~~~~~~ - -- Correctly update the maximum frame size when the user updates the value of - that setting. Prior to this release, if the user updated the maximum frame - size hyper-h2 would ignore the update, preventing the remote peer from using - the higher frame sizes. - -2.2.7 (2016-10-25) ------------------- - -*Final 2.2.X release* - -Bugfixes -~~~~~~~~ - -- Correctly update the maximum frame size when the user updates the value of - that setting. Prior to this release, if the user updated the maximum frame - size hyper-h2 would ignore the update, preventing the remote peer from using - the higher frame sizes. - -2.4.1 (2016-08-23) ------------------- - -Bugfixes -~~~~~~~~ - -- Correctly expect that responses to HEAD requests will have no body regardless - of the value of the Content-Length header, and reject those that do. - -2.3.2 (2016-08-23) ------------------- - -Bugfixes -~~~~~~~~ - -- Correctly expect that responses to HEAD requests will have no body regardless - of the value of the Content-Length header, and reject those that do. - -2.4.0 (2016-07-01) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Adds ``additional_data`` to ``H2Connection.close_connection``, allowing the - user to send additional debug data on the GOAWAY frame. -- Adds ``last_stream_id`` to ``H2Connection.close_connection``, allowing the - user to manually control what the reported last stream ID is. -- Add new method: ``prioritize``. -- Add support for emitting stream priority information when sending headers - frames using three new keyword arguments: ``priority_weight``, - ``priority_depends_on``, and ``priority_exclusive``. -- Add support for "related events": events that fire simultaneously on a single - frame. - - -2.3.1 (2016-05-12) ------------------- - -Bugfixes -~~~~~~~~ - -- Resolved ``AttributeError`` encountered when receiving more than one sequence - of CONTINUATION frames on a given connection. - - -2.2.5 (2016-05-12) ------------------- - -Bugfixes -~~~~~~~~ - -- Resolved ``AttributeError`` encountered when receiving more than one sequence - of CONTINUATION frames on a given connection. - - -2.3.0 (2016-04-26) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added a new flag to the ``H2Connection`` constructor: ``header_encoding``, - that controls what encoding is used (if any) to decode the headers from bytes - to unicode. This defaults to UTF-8 for backward compatibility. To disable the - decode and use bytes exclusively, set the field to False, None, or the empty - string. This affects all headers, including those pushed by servers. -- Bumped the minimum version of HPACK allowed from 2.0 to 2.2. -- Added support for advertising RFC 7838 Alternative services. -- Allowed users to provide ``hpack.HeaderTuple`` and - ``hpack.NeverIndexedHeaderTuple`` objects to all methods that send headers. -- Changed all events that carry headers to emit ``hpack.HeaderTuple`` and - ``hpack.NeverIndexedHeaderTuple`` instead of plain tuples. This allows users - to maintain header indexing state. -- Added support for plaintext upgrade with the ``initiate_upgrade_connection`` - method. - -Bugfixes -~~~~~~~~ - -- Automatically ensure that all ``Authorization`` and ``Proxy-Authorization`` - headers, as well as short ``Cookie`` headers, are prevented from being added - to encoding contexts. - -2.2.4 (2016-04-25) ------------------- - -Bugfixes -~~~~~~~~ - -- Correctly forbid pseudo-headers that were not defined in RFC 7540. -- Ignore AltSvc frames, rather than exploding when receiving them. - -2.1.5 (2016-04-25) ------------------- - -*Final 2.1.X release* - -Bugfixes -~~~~~~~~ - -- Correctly forbid pseudo-headers that were not defined in RFC 7540. -- Ignore AltSvc frames, rather than exploding when receiving them. - -2.2.3 (2016-04-13) ------------------- - -Bugfixes -~~~~~~~~ - -- Allowed the 4.X series of hyperframe releases as dependencies. - -2.1.4 (2016-04-13) ------------------- - -Bugfixes -~~~~~~~~ - -- Allowed the 4.X series of hyperframe releases as dependencies. - - -2.2.2 (2016-04-05) ------------------- - -Bugfixes -~~~~~~~~ - -- Fixed issue where informational responses were erroneously not allowed to be - sent in the ``HALF_CLOSED_REMOTE`` state. -- Fixed issue where informational responses were erroneously not allowed to be - received in the ``HALF_CLOSED_LOCAL`` state. -- Fixed issue where we allowed information responses to be sent or received - after final responses. - -2.2.1 (2016-03-23) ------------------- - -Bugfixes -~~~~~~~~ - -- Fixed issue where users using locales that did not default to UTF-8 were - unable to install source distributions of the package. - -2.2.0 (2016-03-23) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added support for sending informational responses (responses with 1XX status) - codes as part of the standard flow. HTTP/2 allows zero or more informational - responses with no upper limit: hyper-h2 does too. -- Added support for receiving informational responses (responses with 1XX - status) codes as part of the standard flow. HTTP/2 allows zero or more - informational responses with no upper limit: hyper-h2 does too. -- Added a new event: ``ReceivedInformationalResponse``. This response is fired - when informational responses (those with 1XX status codes). -- Added an ``additional_data`` field to the ``ConnectionTerminated`` event that - carries any additional data sent on the GOAWAY frame. May be ``None`` if no - such data was sent. -- Added the ``initial_values`` optional argument to the ``Settings`` object. - -Bugfixes -~~~~~~~~ - -- Correctly reject all of the connection-specific headers mentioned in RFC 7540 - § 8.1.2.2, not just the ``Connection:`` header. -- Defaulted the value of ``SETTINGS_MAX_CONCURRENT_STREAMS`` to 100, unless - explicitly overridden. This is a safe defensive initial value for this - setting. - -2.1.3 (2016-03-16) ------------------- - -Deprecations -~~~~~~~~~~~~ - -- Passing dictionaries to ``send_headers`` as the header block is deprecated, - and will be removed in 3.0. - -2.1.2 (2016-02-17) ------------------- - -Bugfixes -~~~~~~~~ - -- Reject attempts to push streams on streams that were themselves pushed: - streams can only be pushed on streams that were initiated by the client. -- Correctly allow CONTINUATION frames to extend the header block started by a - PUSH_PROMISE frame. -- Changed our handling of frames received on streams that were reset by the - user. - - Previously these would, at best, cause ProtocolErrors to be raised and the - connection to be torn down (rather defeating the point of resetting streams - at all) and, at worst, would cause subtle inconsistencies in state between - hyper-h2 and the remote peer that could lead to header block decoding errors - or flow control blockages. - - Now when the user resets a stream all further frames received on that stream - are ignored except where they affect some form of connection-level state, - where they have their effect and are then ignored. -- Fixed a bug whereby receiving a PUSH_PROMISE frame on a stream that was - closed would cause a RST_STREAM frame to be emitted on the closed-stream, - but not the newly-pushed one. Now this causes a ``ProtocolError``. - -2.1.1 (2016-02-05) ------------------- - -Bugfixes -~~~~~~~~ - -- Added debug representations for all events. -- Fixed problems with setup.py that caused trouble on older setuptools/pip - installs. - -2.1.0 (2016-02-02) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added new field to ``DataReceived``: ``flow_controlled_length``. This is the - length of the frame including padded data, allowing users to correctly track - changes to the flow control window. -- Defined new ``UnsupportedFrameError``, thrown when frames that are known to - hyperframe but not supported by hyper-h2 are received. For - backward-compatibility reasons, this is a ``ProtocolError`` *and* a - ``KeyError``. - -Bugfixes -~~~~~~~~ - -- Hyper-h2 now correctly accounts for padding when maintaining flow control - windows. -- Resolved a bug where hyper-h2 would mistakenly apply - SETTINGS_INITIAL_WINDOW_SIZE to the connection flow control window in - addition to the stream-level flow control windows. -- Invalid Content-Length headers now throw ``ProtocolError`` exceptions and - correctly tear the connection down, instead of leaving the connection in an - indeterminate state. -- Invalid header blocks now throw ``ProtocolError``, rather than a grab bag of - possible other exceptions. - -2.0.0 (2016-01-25) ------------------- - -API Changes (Breaking) -~~~~~~~~~~~~~~~~~~~~~~ - -- Attempts to open streams with invalid stream IDs, either by the remote peer - or by the user, are now rejected as a ``ProtocolError``. Previously these - were allowed, and would cause remote peers to error. -- Receiving frames that have invalid padding now causes the connection to be - terminated with a ``ProtocolError`` being raised. Previously these passed - undetected. -- Settings values set by both the user and the remote peer are now validated - when they're set. If they're invalid, a new ``InvalidSettingsValueError`` is - raised and, if set by the remote peer, a connection error is signaled. - Previously, it was possible to set invalid values. These would either be - caught when building frames, or would be allowed to stand. -- Settings changes no longer require user action to be acknowledged: hyper-h2 - acknowledges them automatically. This moves the location where some - exceptions may be thrown, and also causes the ``acknowledge_settings`` method - to be removed from the public API. -- Removed a number of methods on the ``H2Connection`` object from the public, - semantically versioned API, by renaming them to have leading underscores. - Specifically, removed: - - - ``get_stream_by_id`` - - ``get_or_create_stream`` - - ``begin_new_stream`` - - ``receive_frame`` - - ``acknowledge_settings`` - -- Added full support for receiving CONTINUATION frames, including policing - logic about when and how they are received. Previously, receiving - CONTINUATION frames was not supported and would throw exceptions. -- All public API functions on ``H2Connection`` except for ``receive_data`` no - longer return lists of events, because these lists were always empty. Events - are now only raised by ``receive_data``. -- Calls to ``increment_flow_control_window`` with out of range values now raise - ``ValueError`` exceptions. Previously they would be allowed, or would cause - errors when serializing frames. - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added ``PriorityUpdated`` event for signaling priority changes. -- Added ``get_next_available_stream_id`` function. -- Receiving DATA frames on streams not in the OPEN or HALF_CLOSED_LOCAL states - now causes a stream reset, rather than a connection reset. The error is now - also classified as a ``StreamClosedError``, rather than a more generic - ``ProtocolError``. -- Receiving HEADERS or PUSH_PROMISE frames in the HALF_CLOSED_REMOTE state now - causes a stream reset, rather than a connection reset. -- Receiving frames that violate the max frame size now causes connection errors - with error code FRAME_SIZE_ERROR, not a generic PROTOCOL_ERROR. This - condition now also raises a ``FrameTooLargeError``, a new subclass of - ``ProtocolError``. -- Made ``NoSuchStreamError`` a subclass of ``ProtocolError``. -- The ``StreamReset`` event is now also fired whenever a protocol error from - the remote peer forces a stream to close early. This is only fired once. -- The ``StreamReset`` event now carries a flag, ``remote_reset``, that is set - to ``True`` in all cases where ``StreamReset`` would previously have fired - (e.g. when the remote peer sent a RST_STREAM), and is set to ``False`` when - it fires because the remote peer made a protocol error. -- Hyper-h2 now rejects attempts by peers to increment a flow control window by - zero bytes. -- Hyper-h2 now rejects peers sending header blocks that are ill-formed for a - number of reasons as set out in RFC 7540 Section 8.1.2. -- Attempting to send non-PRIORITY frames on closed streams now raises - ``StreamClosedError``. -- Remote peers attempting to increase the flow control window beyond - ``2**31 - 1``, either by window increment or by settings frame, are now - rejected as ``ProtocolError``. -- Local attempts to increase the flow control window beyond ``2**31 - 1`` by - window increment are now rejected as ``ProtocolError``. -- The bytes that represent individual settings are now available in - ``h2.settings``, instead of needing users to import them from hyperframe. - -Bugfixes -~~~~~~~~ - -- RFC 7540 requires that a separate minimum stream ID be used for inbound and - outbound streams. Hyper-h2 now obeys this requirement. -- Hyper-h2 now does a better job of reporting the last stream ID it has - partially handled when terminating connections. -- Fixed an error in the arguments of ``StreamIDTooLowError``. -- Prevent ``ValueError`` leaking from Hyperframe. -- Prevent ``struct.error`` and ``InvalidFrameError`` leaking from Hyperframe. - -1.1.1 (2015-11-17) ------------------- - -Bugfixes -~~~~~~~~ - -- Forcibly lowercase all header names to improve compatibility with - implementations that demand lower-case header names. - -1.1.0 (2015-10-28) ------------------- - -API Changes (Backward-Compatible) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Added a new ``ConnectionTerminated`` event, which fires when GOAWAY frames - are received. -- Added a subclass of ``NoSuchStreamError``, called ``StreamClosedError``, that - fires when actions are taken on a stream that is closed and has had its state - flushed from the system. -- Added ``StreamIDTooLowError``, raised when the user or the remote peer - attempts to create a stream with an ID lower than one previously used in the - dialog. Inherits from ``ValueError`` for backward-compatibility reasons. - -Bugfixes -~~~~~~~~ - -- Do not throw ``ProtocolError`` when attempting to send multiple GOAWAY - frames on one connection. -- We no longer forcefully change the decoder table size when settings changes - are ACKed, instead waiting for remote acknowledgement of the change. -- Improve the performance of checking whether a stream is open. -- We now attempt to lazily garbage collect closed streams, to avoid having the - state hang around indefinitely, leaking memory. -- Avoid further per-stream allocations, leading to substantial performance - improvements when many short-lived streams are used. - -1.0.0 (2015-10-15) ------------------- - -- First production release! - - diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/RECORD deleted file mode 100644 index bb43f13..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/RECORD +++ /dev/null @@ -1,28 +0,0 @@ -h2/__init__.py,sha256=5JeiMynVO_BNdkPwJG87HocuejIIZTlopM0fP0xO0Cc,86 -h2/config.py,sha256=yUt4qqDqe7wtpsWUmsScDhWCoJC7pV5DIrIjkHbPoY0,6498 -h2/connection.py,sha256=PVFYoKAQ2cBfw0M3xkkpkdG3E0QsckvlY7PVxEreDvk,81507 -h2/errors.py,sha256=zVc5DO6IBAv1EkJxdb-mpRdqxUBfb5W0gwdqBLpqy80,1553 -h2/events.py,sha256=_zttawGqPVmEVeZN1S3kGREQ-VSt1xP07SebUxLqAF4,21962 -h2/exceptions.py,sha256=rdeQYMyQ46s6gkRkkb02YXsKZnc1VFuPqpPKr8Q-8a8,5379 -h2/frame_buffer.py,sha256=NBeQ94joXLE9XkGpfGFeB_VIOBNq_9fINy90YUG0qD4,6771 -h2/settings.py,sha256=hUohNoWHMouGhOWiDc2r5sceqMGTuVsDpi9KmsPCDMY,11814 -h2/stream.py,sha256=M0I2tfRI2CK2diFht167-5N6x5YkpR70PS8_dG4dfbw,55948 -h2/utilities.py,sha256=JI6DcBWD0rXiAafbCfnXmroYK1Q28g4bqHLqeqA29_4,22818 -h2/windows.py,sha256=XRuu1Y2WlTq6TuEpuhfvl5R6TIGysoU9s0mpFVgjIUA,5603 -h2-3.1.0.dist-info/LICENSE,sha256=Zj-SU-E1GbgqtKaxyqtr7QWq2nBRfyjNAlS-ip-hntY,1102 -h2-3.1.0.dist-info/METADATA,sha256=a6TvzsCeijPksW0FIUepj1JozPMbEIy6yxYrdiQ7B_8,31598 -h2-3.1.0.dist-info/WHEEL,sha256=_wJFdOYk7i3xxT8ElOkUJvOdOvfNGbR9g-bf6UQT6sU,110 -h2-3.1.0.dist-info/top_level.txt,sha256=Hiulx8KxI2jFUM1dG7-CZeRkO3j50MBwCLG36Vrq-kI,3 -h2-3.1.0.dist-info/RECORD,, -h2-3.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -h2/__pycache__/errors.cpython-37.pyc,, -h2/__pycache__/__init__.cpython-37.pyc,, -h2/__pycache__/exceptions.cpython-37.pyc,, -h2/__pycache__/windows.cpython-37.pyc,, -h2/__pycache__/events.cpython-37.pyc,, -h2/__pycache__/stream.cpython-37.pyc,, -h2/__pycache__/frame_buffer.cpython-37.pyc,, -h2/__pycache__/connection.cpython-37.pyc,, -h2/__pycache__/settings.cpython-37.pyc,, -h2/__pycache__/utilities.cpython-37.pyc,, -h2/__pycache__/config.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/WHEEL deleted file mode 100644 index c4bde30..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.32.3) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/top_level.txt deleted file mode 100644 index c48b563..0000000 --- a/py3.7/lib/python3.7/site-packages/h2-3.1.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -h2 diff --git a/py3.7/lib/python3.7/site-packages/h2/__init__.py b/py3.7/lib/python3.7/site-packages/h2/__init__.py deleted file mode 100644 index 2e7e7ee..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2 -~~ - -A HTTP/2 implementation. -""" -__version__ = '3.1.0' diff --git a/py3.7/lib/python3.7/site-packages/h2/config.py b/py3.7/lib/python3.7/site-packages/h2/config.py deleted file mode 100644 index 08129a4..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/config.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/config -~~~~~~~~~ - -Objects for controlling the configuration of the HTTP/2 stack. -""" - - -class _BooleanConfigOption(object): - """ - Descriptor for handling a boolean config option. This will block - attempts to set boolean config options to non-bools. - """ - def __init__(self, name): - self.name = name - self.attr_name = '_%s' % self.name - - def __get__(self, instance, owner): - return getattr(instance, self.attr_name) - - def __set__(self, instance, value): - if not isinstance(value, bool): - raise ValueError("%s must be a bool" % self.name) - setattr(instance, self.attr_name, value) - - -class DummyLogger(object): - """ - An Logger object that does not actual logging, hence a DummyLogger. - - For the class the log operation is merely a no-op. The intent is to avoid - conditionals being sprinkled throughout the hyper-h2 code for calls to - logging functions when no logger is passed into the corresponding object. - """ - def __init__(self, *vargs): - pass - - def debug(self, *vargs, **kwargs): - """ - No-op logging. Only level needed for now. - """ - pass - - -class H2Configuration(object): - """ - An object that controls the way a single HTTP/2 connection behaves. - - This object allows the users to customize behaviour. In particular, it - allows users to enable or disable optional features, or to otherwise handle - various unusual behaviours. - - This object has very little behaviour of its own: it mostly just ensures - that configuration is self-consistent. - - :param client_side: Whether this object is to be used on the client side of - a connection, or on the server side. Affects the logic used by the - state machine, the default settings values, the allowable stream IDs, - and several other properties. Defaults to ``True``. - :type client_side: ``bool`` - - :param header_encoding: Controls whether the headers emitted by this object - in events are transparently decoded to ``unicode`` strings, and what - encoding is used to do that decoding. This defaults to ``None``, - meaning that headers will be returned as bytes. To automatically - decode headers (that is, to return them as unicode strings), this can - be set to the string name of any encoding, e.g. ``'utf-8'``. - - .. versionchanged:: 3.0.0 - Changed default value from ``'utf-8'`` to ``None`` - - :type header_encoding: ``str``, ``False``, or ``None`` - - :param validate_outbound_headers: Controls whether the headers emitted - by this object are validated against the rules in RFC 7540. - Disabling this setting will cause outbound header validation to - be skipped, and allow the object to emit headers that may be illegal - according to RFC 7540. Defaults to ``True``. - :type validate_outbound_headers: ``bool`` - - :param normalize_outbound_headers: Controls whether the headers emitted - by this object are normalized before sending. Disabling this setting - will cause outbound header normalization to be skipped, and allow - the object to emit headers that may be illegal according to - RFC 7540. Defaults to ``True``. - :type normalize_outbound_headers: ``bool`` - - :param validate_inbound_headers: Controls whether the headers received - by this object are validated against the rules in RFC 7540. - Disabling this setting will cause inbound header validation to - be skipped, and allow the object to receive headers that may be illegal - according to RFC 7540. Defaults to ``True``. - :type validate_inbound_headers: ``bool`` - - :param normalize_inbound_headers: Controls whether the headers received by - this object are normalized according to the rules of RFC 7540. - Disabling this setting may lead to hyper-h2 emitting header blocks that - some RFCs forbid, e.g. with multiple cookie fields. - - .. versionadded:: 3.0.0 - - :type normalize_inbound_headers: ``bool`` - - :param logger: A logger that conforms to the requirements for this module, - those being no I/O and no context switches, which is needed in order - to run in asynchronous operation. - - .. versionadded:: 2.6.0 - - :type logger: ``logging.Logger`` - """ - client_side = _BooleanConfigOption('client_side') - validate_outbound_headers = _BooleanConfigOption( - 'validate_outbound_headers' - ) - normalize_outbound_headers = _BooleanConfigOption( - 'normalize_outbound_headers' - ) - validate_inbound_headers = _BooleanConfigOption( - 'validate_inbound_headers' - ) - normalize_inbound_headers = _BooleanConfigOption( - 'normalize_inbound_headers' - ) - - def __init__(self, - client_side=True, - header_encoding=None, - validate_outbound_headers=True, - normalize_outbound_headers=True, - validate_inbound_headers=True, - normalize_inbound_headers=True, - logger=None): - self.client_side = client_side - self.header_encoding = header_encoding - self.validate_outbound_headers = validate_outbound_headers - self.normalize_outbound_headers = normalize_outbound_headers - self.validate_inbound_headers = validate_inbound_headers - self.normalize_inbound_headers = normalize_inbound_headers - self.logger = logger or DummyLogger(__name__) - - @property - def header_encoding(self): - """ - Controls whether the headers emitted by this object in events are - transparently decoded to ``unicode`` strings, and what encoding is used - to do that decoding. This defaults to ``None``, meaning that headers - will be returned as bytes. To automatically decode headers (that is, to - return them as unicode strings), this can be set to the string name of - any encoding, e.g. ``'utf-8'``. - """ - return self._header_encoding - - @header_encoding.setter - def header_encoding(self, value): - """ - Enforces constraints on the value of header encoding. - """ - if not isinstance(value, (bool, str, type(None))): - raise ValueError("header_encoding must be bool, string, or None") - if value is True: - raise ValueError("header_encoding cannot be True") - self._header_encoding = value diff --git a/py3.7/lib/python3.7/site-packages/h2/connection.py b/py3.7/lib/python3.7/site-packages/h2/connection.py deleted file mode 100644 index 20975e3..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/connection.py +++ /dev/null @@ -1,2012 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/connection -~~~~~~~~~~~~~ - -An implementation of a HTTP/2 connection. -""" -import base64 - -from enum import Enum, IntEnum - -from hyperframe.exceptions import InvalidPaddingError -from hyperframe.frame import ( - GoAwayFrame, WindowUpdateFrame, HeadersFrame, DataFrame, PingFrame, - PushPromiseFrame, SettingsFrame, RstStreamFrame, PriorityFrame, - ContinuationFrame, AltSvcFrame, ExtensionFrame -) -from hpack.hpack import Encoder, Decoder -from hpack.exceptions import HPACKError, OversizedHeaderListError - -from .config import H2Configuration -from .errors import ErrorCodes, _error_code_from_int -from .events import ( - WindowUpdated, RemoteSettingsChanged, PingReceived, PingAckReceived, - SettingsAcknowledged, ConnectionTerminated, PriorityUpdated, - AlternativeServiceAvailable, UnknownFrameReceived -) -from .exceptions import ( - ProtocolError, NoSuchStreamError, FlowControlError, FrameTooLargeError, - TooManyStreamsError, StreamClosedError, StreamIDTooLowError, - NoAvailableStreamIDError, RFC1122Error, DenialOfServiceError -) -from .frame_buffer import FrameBuffer -from .settings import Settings, SettingCodes -from .stream import H2Stream, StreamClosedBy -from .utilities import SizeLimitDict, guard_increment_window -from .windows import WindowManager - - -class ConnectionState(Enum): - IDLE = 0 - CLIENT_OPEN = 1 - SERVER_OPEN = 2 - CLOSED = 3 - - -class ConnectionInputs(Enum): - SEND_HEADERS = 0 - SEND_PUSH_PROMISE = 1 - SEND_DATA = 2 - SEND_GOAWAY = 3 - SEND_WINDOW_UPDATE = 4 - SEND_PING = 5 - SEND_SETTINGS = 6 - SEND_RST_STREAM = 7 - SEND_PRIORITY = 8 - RECV_HEADERS = 9 - RECV_PUSH_PROMISE = 10 - RECV_DATA = 11 - RECV_GOAWAY = 12 - RECV_WINDOW_UPDATE = 13 - RECV_PING = 14 - RECV_SETTINGS = 15 - RECV_RST_STREAM = 16 - RECV_PRIORITY = 17 - SEND_ALTERNATIVE_SERVICE = 18 # Added in 2.3.0 - RECV_ALTERNATIVE_SERVICE = 19 # Added in 2.3.0 - - -class AllowedStreamIDs(IntEnum): - EVEN = 0 - ODD = 1 - - -class H2ConnectionStateMachine(object): - """ - A single HTTP/2 connection state machine. - - This state machine, while defined in its own class, is logically part of - the H2Connection class also defined in this file. The state machine itself - maintains very little state directly, instead focusing entirely on managing - state transitions. - """ - # For the purposes of this state machine we treat HEADERS and their - # associated CONTINUATION frames as a single jumbo frame. The protocol - # allows/requires this by preventing other frames from being interleved in - # between HEADERS/CONTINUATION frames. - # - # The _transitions dictionary contains a mapping of tuples of - # (state, input) to tuples of (side_effect_function, end_state). This map - # contains all allowed transitions: anything not in this map is invalid - # and immediately causes a transition to ``closed``. - - _transitions = { - # State: idle - (ConnectionState.IDLE, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.IDLE, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.IDLE, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_PING): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_PING): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.IDLE, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.IDLE, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.IDLE), - (ConnectionState.IDLE, ConnectionInputs.SEND_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.IDLE, ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.CLIENT_OPEN), - - # State: open, client side. - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_DATA): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_PING): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PUSH_PROMISE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_DATA): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PING): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.SEND_RST_STREAM): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_RST_STREAM): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.CLIENT_OPEN), - (ConnectionState.CLIENT_OPEN, - ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.CLIENT_OPEN), - - # State: open, server side. - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PUSH_PROMISE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_DATA): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_WINDOW_UPDATE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PING): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_SETTINGS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_PRIORITY): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_HEADERS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_DATA): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_WINDOW_UPDATE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_PING): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_SETTINGS): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_PRIORITY): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.SEND_RST_STREAM): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, ConnectionInputs.RECV_RST_STREAM): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, - ConnectionInputs.SEND_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - (ConnectionState.SERVER_OPEN, - ConnectionInputs.RECV_ALTERNATIVE_SERVICE): - (None, ConnectionState.SERVER_OPEN), - - # State: closed - (ConnectionState.CLOSED, ConnectionInputs.SEND_GOAWAY): - (None, ConnectionState.CLOSED), - (ConnectionState.CLOSED, ConnectionInputs.RECV_GOAWAY): - (None, ConnectionState.CLOSED), - } - - def __init__(self): - self.state = ConnectionState.IDLE - - def process_input(self, input_): - """ - Process a specific input in the state machine. - """ - if not isinstance(input_, ConnectionInputs): - raise ValueError("Input must be an instance of ConnectionInputs") - - try: - func, target_state = self._transitions[(self.state, input_)] - except KeyError: - old_state = self.state - self.state = ConnectionState.CLOSED - raise ProtocolError( - "Invalid input %s in state %s" % (input_, old_state) - ) - else: - self.state = target_state - if func is not None: # pragma: no cover - return func() - - return [] - - -class H2Connection(object): - """ - A low-level HTTP/2 connection object. This handles building and receiving - frames and maintains both connection and per-stream state for all streams - on this connection. - - This wraps a HTTP/2 Connection state machine implementation, ensuring that - frames can only be sent/received when the connection is in a valid state. - It also builds stream state machines on demand to ensure that the - constraints of those state machines are met as well. Attempts to create - frames that cannot be sent will raise a ``ProtocolError``. - - .. versionchanged:: 2.3.0 - Added the ``header_encoding`` keyword argument. - - .. versionchanged:: 2.5.0 - Added the ``config`` keyword argument. Deprecated the ``client_side`` - and ``header_encoding`` parameters. - - .. versionchanged:: 3.0.0 - Removed deprecated parameters and properties. - - :param config: The configuration for the HTTP/2 connection. - - .. versionadded:: 2.5.0 - - :type config: :class:`H2Configuration ` - """ - # The initial maximum outbound frame size. This can be changed by receiving - # a settings frame. - DEFAULT_MAX_OUTBOUND_FRAME_SIZE = 65535 - - # The initial maximum inbound frame size. This is somewhat arbitrarily - # chosen. - DEFAULT_MAX_INBOUND_FRAME_SIZE = 2**24 - - # The highest acceptable stream ID. - HIGHEST_ALLOWED_STREAM_ID = 2**31 - 1 - - # The largest acceptable window increment. - MAX_WINDOW_INCREMENT = 2**31 - 1 - - # The initial default value of SETTINGS_MAX_HEADER_LIST_SIZE. - DEFAULT_MAX_HEADER_LIST_SIZE = 2**16 - - # Keep in memory limited amount of results for streams closes - MAX_CLOSED_STREAMS = 2**16 - - def __init__(self, config=None): - self.state_machine = H2ConnectionStateMachine() - self.streams = {} - self.highest_inbound_stream_id = 0 - self.highest_outbound_stream_id = 0 - self.encoder = Encoder() - self.decoder = Decoder() - - # This won't always actually do anything: for versions of HPACK older - # than 2.3.0 it does nothing. However, we have to try! - self.decoder.max_header_list_size = self.DEFAULT_MAX_HEADER_LIST_SIZE - - #: The configuration for this HTTP/2 connection object. - #: - #: .. versionadded:: 2.5.0 - self.config = config - if self.config is None: - self.config = H2Configuration( - client_side=True, - ) - - # Objects that store settings, including defaults. - # - # We set the MAX_CONCURRENT_STREAMS value to 100 because its default is - # unbounded, and that's a dangerous default because it allows - # essentially unbounded resources to be allocated regardless of how - # they will be used. 100 should be suitable for the average - # application. This default obviously does not apply to the remote - # peer's settings: the remote peer controls them! - # - # We also set MAX_HEADER_LIST_SIZE to a reasonable value. This is to - # advertise our defence against CVE-2016-6581. However, not all - # versions of HPACK will let us do it. That's ok: we should at least - # suggest that we're not vulnerable. - self.local_settings = Settings( - client=self.config.client_side, - initial_values={ - SettingCodes.MAX_CONCURRENT_STREAMS: 100, - SettingCodes.MAX_HEADER_LIST_SIZE: - self.DEFAULT_MAX_HEADER_LIST_SIZE, - } - ) - self.remote_settings = Settings(client=not self.config.client_side) - - # The current value of the connection flow control windows on the - # connection. - self.outbound_flow_control_window = ( - self.remote_settings.initial_window_size - ) - - #: The maximum size of a frame that can be emitted by this peer, in - #: bytes. - self.max_outbound_frame_size = self.remote_settings.max_frame_size - - #: The maximum size of a frame that can be received by this peer, in - #: bytes. - self.max_inbound_frame_size = self.local_settings.max_frame_size - - # Buffer for incoming data. - self.incoming_buffer = FrameBuffer(server=not self.config.client_side) - - # A private variable to store a sequence of received header frames - # until completion. - self._header_frames = [] - - # Data that needs to be sent. - self._data_to_send = b'' - - # Keeps track of how streams are closed. - # Used to ensure that we don't blow up in the face of frames that were - # in flight when a RST_STREAM was sent. - # Also used to determine whether we should consider a frame received - # while a stream is closed as either a stream error or a connection - # error. - self._closed_streams = SizeLimitDict( - size_limit=self.MAX_CLOSED_STREAMS - ) - - # The flow control window manager for the connection. - self._inbound_flow_control_window_manager = WindowManager( - max_window_size=self.local_settings.initial_window_size - ) - - # When in doubt use dict-dispatch. - self._frame_dispatch_table = { - HeadersFrame: self._receive_headers_frame, - PushPromiseFrame: self._receive_push_promise_frame, - SettingsFrame: self._receive_settings_frame, - DataFrame: self._receive_data_frame, - WindowUpdateFrame: self._receive_window_update_frame, - PingFrame: self._receive_ping_frame, - RstStreamFrame: self._receive_rst_stream_frame, - PriorityFrame: self._receive_priority_frame, - GoAwayFrame: self._receive_goaway_frame, - ContinuationFrame: self._receive_naked_continuation, - AltSvcFrame: self._receive_alt_svc_frame, - ExtensionFrame: self._receive_unknown_frame - } - - def _prepare_for_sending(self, frames): - if not frames: - return - self._data_to_send += b''.join(f.serialize() for f in frames) - assert all(f.body_len <= self.max_outbound_frame_size for f in frames) - - def _open_streams(self, remainder): - """ - A common method of counting number of open streams. Returns the number - of streams that are open *and* that have (stream ID % 2) == remainder. - While it iterates, also deletes any closed streams. - """ - count = 0 - to_delete = [] - - for stream_id, stream in self.streams.items(): - if stream.open and (stream_id % 2 == remainder): - count += 1 - elif stream.closed: - to_delete.append(stream_id) - - for stream_id in to_delete: - stream = self.streams.pop(stream_id) - self._closed_streams[stream_id] = stream.closed_by - - return count - - @property - def open_outbound_streams(self): - """ - The current number of open outbound streams. - """ - outbound_numbers = int(self.config.client_side) - return self._open_streams(outbound_numbers) - - @property - def open_inbound_streams(self): - """ - The current number of open inbound streams. - """ - inbound_numbers = int(not self.config.client_side) - return self._open_streams(inbound_numbers) - - @property - def inbound_flow_control_window(self): - """ - The size of the inbound flow control window for the connection. This is - rarely publicly useful: instead, use :meth:`remote_flow_control_window - `. This - shortcut is largely present to provide a shortcut to this data. - """ - return self._inbound_flow_control_window_manager.current_window_size - - def _begin_new_stream(self, stream_id, allowed_ids): - """ - Initiate a new stream. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - - :param stream_id: The ID of the stream to open. - :param allowed_ids: What kind of stream ID is allowed. - """ - self.config.logger.debug( - "Attempting to initiate stream ID %d", stream_id - ) - outbound = self._stream_id_is_outbound(stream_id) - highest_stream_id = ( - self.highest_outbound_stream_id if outbound else - self.highest_inbound_stream_id - ) - - if stream_id <= highest_stream_id: - raise StreamIDTooLowError(stream_id, highest_stream_id) - - if (stream_id % 2) != int(allowed_ids): - raise ProtocolError( - "Invalid stream ID for peer." - ) - - s = H2Stream( - stream_id, - config=self.config, - inbound_window_size=self.local_settings.initial_window_size, - outbound_window_size=self.remote_settings.initial_window_size - ) - self.config.logger.debug("Stream ID %d created", stream_id) - s.max_inbound_frame_size = self.max_inbound_frame_size - s.max_outbound_frame_size = self.max_outbound_frame_size - - self.streams[stream_id] = s - self.config.logger.debug("Current streams: %s", self.streams.keys()) - - if outbound: - self.highest_outbound_stream_id = stream_id - else: - self.highest_inbound_stream_id = stream_id - - return s - - def initiate_connection(self): - """ - Provides any data that needs to be sent at the start of the connection. - Must be called for both clients and servers. - """ - self.config.logger.debug("Initializing connection") - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - if self.config.client_side: - preamble = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' - else: - preamble = b'' - - f = SettingsFrame(0) - for setting, value in self.local_settings.items(): - f.settings[setting] = value - self.config.logger.debug( - "Send Settings frame: %s", self.local_settings - ) - - self._data_to_send += preamble + f.serialize() - - def initiate_upgrade_connection(self, settings_header=None): - """ - Call to initialise the connection object for use with an upgraded - HTTP/2 connection (i.e. a connection negotiated using the - ``Upgrade: h2c`` HTTP header). - - This method differs from :meth:`initiate_connection - ` in several ways. - Firstly, it handles the additional SETTINGS frame that is sent in the - ``HTTP2-Settings`` header field. When called on a client connection, - this method will return a bytestring that the caller can put in the - ``HTTP2-Settings`` field they send on their initial request. When - called on a server connection, the user **must** provide the value they - received from the client in the ``HTTP2-Settings`` header field to the - ``settings_header`` argument, which will be used appropriately. - - Additionally, this method sets up stream 1 in a half-closed state - appropriate for this side of the connection, to reflect the fact that - the request is already complete. - - Finally, this method also prepares the appropriate preamble to be sent - after the upgrade. - - .. versionadded:: 2.3.0 - - :param settings_header: (optional, server-only): The value of the - ``HTTP2-Settings`` header field received from the client. - :type settings_header: ``bytes`` - - :returns: For clients, a bytestring to put in the ``HTTP2-Settings``. - For servers, returns nothing. - :rtype: ``bytes`` or ``None`` - """ - self.config.logger.debug( - "Upgrade connection. Current settings: %s", self.local_settings - ) - - frame_data = None - # Begin by getting the preamble in place. - self.initiate_connection() - - if self.config.client_side: - f = SettingsFrame(0) - for setting, value in self.local_settings.items(): - f.settings[setting] = value - - frame_data = f.serialize_body() - frame_data = base64.urlsafe_b64encode(frame_data) - elif settings_header: - # We have a settings header from the client. This needs to be - # applied, but we want to throw away the ACK. We do this by - # inserting the data into a Settings frame and then passing it to - # the state machine, but ignoring the return value. - settings_header = base64.urlsafe_b64decode(settings_header) - f = SettingsFrame(0) - f.parse_body(settings_header) - self._receive_settings_frame(f) - - # Set up appropriate state. Stream 1 in a half-closed state: - # half-closed(local) for clients, half-closed(remote) for servers. - # Additionally, we need to set up the Connection state machine. - connection_input = ( - ConnectionInputs.SEND_HEADERS if self.config.client_side - else ConnectionInputs.RECV_HEADERS - ) - self.config.logger.debug("Process input %s", connection_input) - self.state_machine.process_input(connection_input) - - # Set up stream 1. - self._begin_new_stream(stream_id=1, allowed_ids=AllowedStreamIDs.ODD) - self.streams[1].upgrade(self.config.client_side) - return frame_data - - def _get_or_create_stream(self, stream_id, allowed_ids): - """ - Gets a stream by its stream ID. Will create one if one does not already - exist. Use allowed_ids to circumvent the usual stream ID rules for - clients and servers. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - """ - try: - return self.streams[stream_id] - except KeyError: - return self._begin_new_stream(stream_id, allowed_ids) - - def _get_stream_by_id(self, stream_id): - """ - Gets a stream by its stream ID. Raises NoSuchStreamError if the stream - ID does not correspond to a known stream and is higher than the current - maximum: raises if it is lower than the current maximum. - - .. versionchanged:: 2.0.0 - Removed this function from the public API. - """ - try: - return self.streams[stream_id] - except KeyError: - outbound = self._stream_id_is_outbound(stream_id) - highest_stream_id = ( - self.highest_outbound_stream_id if outbound else - self.highest_inbound_stream_id - ) - - if stream_id > highest_stream_id: - raise NoSuchStreamError(stream_id) - else: - raise StreamClosedError(stream_id) - - def get_next_available_stream_id(self): - """ - Returns an integer suitable for use as the stream ID for the next - stream created by this endpoint. For server endpoints, this stream ID - will be even. For client endpoints, this stream ID will be odd. If no - stream IDs are available, raises :class:`NoAvailableStreamIDError - `. - - .. warning:: The return value from this function does not change until - the stream ID has actually been used by sending or pushing - headers on that stream. For that reason, it should be - called as close as possible to the actual use of the - stream ID. - - .. versionadded:: 2.0.0 - - :raises: :class:`NoAvailableStreamIDError - ` - :returns: The next free stream ID this peer can use to initiate a - stream. - :rtype: ``int`` - """ - # No streams have been opened yet, so return the lowest allowed stream - # ID. - if not self.highest_outbound_stream_id: - next_stream_id = 1 if self.config.client_side else 2 - else: - next_stream_id = self.highest_outbound_stream_id + 2 - self.config.logger.debug( - "Next available stream ID %d", next_stream_id - ) - if next_stream_id > self.HIGHEST_ALLOWED_STREAM_ID: - raise NoAvailableStreamIDError("Exhausted allowed stream IDs") - - return next_stream_id - - def send_headers(self, stream_id, headers, end_stream=False, - priority_weight=None, priority_depends_on=None, - priority_exclusive=None): - """ - Send headers on a given stream. - - This function can be used to send request or response headers: the kind - that are sent depends on whether this connection has been opened as a - client or server connection, and whether the stream was opened by the - remote peer or not. - - If this is a client connection, calling ``send_headers`` will send the - headers as a request. It will also implicitly open the stream being - used. If this is a client connection and ``send_headers`` has *already* - been called, this will send trailers instead. - - If this is a server connection, calling ``send_headers`` will send the - headers as a response. It is a protocol error for a server to open a - stream by sending headers. If this is a server connection and - ``send_headers`` has *already* been called, this will send trailers - instead. - - When acting as a server, you may call ``send_headers`` any number of - times allowed by the following rules, in this order: - - - zero or more times with ``(':status', '1XX')`` (where ``1XX`` is a - placeholder for any 100-level status code). - - once with any other status header. - - zero or one time for trailers. - - That is, you are allowed to send as many informational responses as you - like, followed by one complete response and zero or one HTTP trailer - blocks. - - Clients may send one or two header blocks: one request block, and - optionally one trailer block. - - If it is important to send HPACK "never indexed" header fields (as - defined in `RFC 7451 Section 7.1.3 - `_), the user may - instead provide headers using the HPACK library's :class:`HeaderTuple - ` and :class:`NeverIndexedHeaderTuple - ` objects. - - This method also allows users to prioritize the stream immediately, - by sending priority information on the HEADERS frame directly. To do - this, any one of ``priority_weight``, ``priority_depends_on``, or - ``priority_exclusive`` must be set to a value that is not ``None``. For - more information on the priority fields, see :meth:`prioritize - `. - - .. warning:: In HTTP/2, it is mandatory that all the HTTP/2 special - headers (that is, ones whose header keys begin with ``:``) appear - at the start of the header block, before any normal headers. - - .. versionchanged:: 2.3.0 - Added support for using :class:`HeaderTuple - ` objects to store headers. - - .. versionchanged:: 2.4.0 - Added the ability to provide priority keyword arguments: - ``priority_weight``, ``priority_depends_on``, and - ``priority_exclusive``. - - :param stream_id: The stream ID to send the headers on. If this stream - does not currently exist, it will be created. - :type stream_id: ``int`` - - :param headers: The request/response headers to send. - :type headers: An iterable of two tuples of bytestrings or - :class:`HeaderTuple ` objects. - - :param end_stream: Whether this headers frame should end the stream - immediately (that is, whether no more data will be sent after this - frame). Defaults to ``False``. - :type end_stream: ``bool`` - - :param priority_weight: Sets the priority weight of the stream. See - :meth:`prioritize ` for more - about how this field works. Defaults to ``None``, which means that - no priority information will be sent. - :type priority_weight: ``int`` or ``None`` - - :param priority_depends_on: Sets which stream this one depends on for - priority purposes. See :meth:`prioritize - ` for more about how this - field works. Defaults to ``None``, which means that no priority - information will be sent. - :type priority_depends_on: ``int`` or ``None`` - - :param priority_exclusive: Sets whether this stream exclusively depends - on the stream given in ``priority_depends_on`` for priority - purposes. See :meth:`prioritize - ` for more about how this - field workds. Defaults to ``None``, which means that no priority - information will be sent. - :type priority_depends_on: ``bool`` or ``None`` - - :returns: Nothing - """ - self.config.logger.debug( - "Send headers on stream ID %d", stream_id - ) - - # Check we can open the stream. - if stream_id not in self.streams: - max_open_streams = self.remote_settings.max_concurrent_streams - if (self.open_outbound_streams + 1) > max_open_streams: - raise TooManyStreamsError( - "Max outbound streams is %d, %d open" % - (max_open_streams, self.open_outbound_streams) - ) - - self.state_machine.process_input(ConnectionInputs.SEND_HEADERS) - stream = self._get_or_create_stream( - stream_id, AllowedStreamIDs(self.config.client_side) - ) - frames = stream.send_headers( - headers, self.encoder, end_stream - ) - - # We may need to send priority information. - priority_present = ( - (priority_weight is not None) or - (priority_depends_on is not None) or - (priority_exclusive is not None) - ) - - if priority_present: - if not self.config.client_side: - raise RFC1122Error("Servers SHOULD NOT prioritize streams.") - - headers_frame = frames[0] - headers_frame.flags.add('PRIORITY') - frames[0] = _add_frame_priority( - headers_frame, - priority_weight, - priority_depends_on, - priority_exclusive - ) - - self._prepare_for_sending(frames) - - def send_data(self, stream_id, data, end_stream=False, pad_length=None): - """ - Send data on a given stream. - - This method does no breaking up of data: if the data is larger than the - value returned by :meth:`local_flow_control_window - ` for this stream - then a :class:`FlowControlError ` will - be raised. If the data is larger than :data:`max_outbound_frame_size - ` then a - :class:`FrameTooLargeError ` will be - raised. - - Hyper-h2 does this to avoid buffering the data internally. If the user - has more data to send than hyper-h2 will allow, consider breaking it up - and buffering it externally. - - :param stream_id: The ID of the stream on which to send the data. - :type stream_id: ``int`` - :param data: The data to send on the stream. - :type data: ``bytes`` - :param end_stream: (optional) Whether this is the last data to be sent - on the stream. Defaults to ``False``. - :type end_stream: ``bool`` - :param pad_length: (optional) Length of the padding to apply to the - data frame. Defaults to ``None`` for no use of padding. Note that - a value of ``0`` results in padding of length ``0`` - (with the "padding" flag set on the frame). - - .. versionadded:: 2.6.0 - - :type pad_length: ``int`` - :returns: Nothing - """ - self.config.logger.debug( - "Send data on stream ID %d with len %d", stream_id, len(data) - ) - frame_size = len(data) - if pad_length is not None: - if not isinstance(pad_length, int): - raise TypeError("pad_length must be an int") - if pad_length < 0 or pad_length > 255: - raise ValueError("pad_length must be within range: [0, 255]") - # Account for padding bytes plus the 1-byte padding length field. - frame_size += pad_length + 1 - self.config.logger.debug( - "Frame size on stream ID %d is %d", stream_id, frame_size - ) - - if frame_size > self.local_flow_control_window(stream_id): - raise FlowControlError( - "Cannot send %d bytes, flow control window is %d." % - (frame_size, self.local_flow_control_window(stream_id)) - ) - elif frame_size > self.max_outbound_frame_size: - raise FrameTooLargeError( - "Cannot send frame size %d, max frame size is %d" % - (frame_size, self.max_outbound_frame_size) - ) - - self.state_machine.process_input(ConnectionInputs.SEND_DATA) - frames = self.streams[stream_id].send_data( - data, end_stream, pad_length=pad_length - ) - - self._prepare_for_sending(frames) - - self.outbound_flow_control_window -= frame_size - self.config.logger.debug( - "Outbound flow control window size is %d", - self.outbound_flow_control_window - ) - assert self.outbound_flow_control_window >= 0 - - def end_stream(self, stream_id): - """ - Cleanly end a given stream. - - This method ends a stream by sending an empty DATA frame on that stream - with the ``END_STREAM`` flag set. - - :param stream_id: The ID of the stream to end. - :type stream_id: ``int`` - :returns: Nothing - """ - self.config.logger.debug("End stream ID %d", stream_id) - self.state_machine.process_input(ConnectionInputs.SEND_DATA) - frames = self.streams[stream_id].end_stream() - self._prepare_for_sending(frames) - - def increment_flow_control_window(self, increment, stream_id=None): - """ - Increment a flow control window, optionally for a single stream. Allows - the remote peer to send more data. - - .. versionchanged:: 2.0.0 - Rejects attempts to increment the flow control window by out of - range values with a ``ValueError``. - - :param increment: The amount to increment the flow control window by. - :type increment: ``int`` - :param stream_id: (optional) The ID of the stream that should have its - flow control window opened. If not present or ``None``, the - connection flow control window will be opened instead. - :type stream_id: ``int`` or ``None`` - :returns: Nothing - :raises: ``ValueError`` - """ - if not (1 <= increment <= self.MAX_WINDOW_INCREMENT): - raise ValueError( - "Flow control increment must be between 1 and %d" % - self.MAX_WINDOW_INCREMENT - ) - - self.state_machine.process_input(ConnectionInputs.SEND_WINDOW_UPDATE) - - if stream_id is not None: - stream = self.streams[stream_id] - frames = stream.increase_flow_control_window( - increment - ) - - self.config.logger.debug( - "Increase stream ID %d flow control window by %d", - stream_id, increment - ) - else: - self._inbound_flow_control_window_manager.window_opened(increment) - f = WindowUpdateFrame(0) - f.window_increment = increment - frames = [f] - - self.config.logger.debug( - "Increase connection flow control window by %d", increment - ) - - self._prepare_for_sending(frames) - - def push_stream(self, stream_id, promised_stream_id, request_headers): - """ - Push a response to the client by sending a PUSH_PROMISE frame. - - If it is important to send HPACK "never indexed" header fields (as - defined in `RFC 7451 Section 7.1.3 - `_), the user may - instead provide headers using the HPACK library's :class:`HeaderTuple - ` and :class:`NeverIndexedHeaderTuple - ` objects. - - :param stream_id: The ID of the stream that this push is a response to. - :type stream_id: ``int`` - :param promised_stream_id: The ID of the stream that the pushed - response will be sent on. - :type promised_stream_id: ``int`` - :param request_headers: The headers of the request that the pushed - response will be responding to. - :type request_headers: An iterable of two tuples of bytestrings or - :class:`HeaderTuple ` objects. - :returns: Nothing - """ - self.config.logger.debug( - "Send Push Promise frame on stream ID %d", stream_id - ) - - if not self.remote_settings.enable_push: - raise ProtocolError("Remote peer has disabled stream push") - - self.state_machine.process_input(ConnectionInputs.SEND_PUSH_PROMISE) - stream = self._get_stream_by_id(stream_id) - - # We need to prevent users pushing streams in response to streams that - # they themselves have already pushed: see #163 and RFC 7540 § 6.6. The - # easiest way to do that is to assert that the stream_id is not even: - # this shortcut works because only servers can push and the state - # machine will enforce this. - if (stream_id % 2) == 0: - raise ProtocolError("Cannot recursively push streams.") - - new_stream = self._begin_new_stream( - promised_stream_id, AllowedStreamIDs.EVEN - ) - self.streams[promised_stream_id] = new_stream - - frames = stream.push_stream_in_band( - promised_stream_id, request_headers, self.encoder - ) - new_frames = new_stream.locally_pushed() - self._prepare_for_sending(frames + new_frames) - - def ping(self, opaque_data): - """ - Send a PING frame. - - :param opaque_data: A bytestring of length 8 that will be sent in the - PING frame. - :returns: Nothing - """ - self.config.logger.debug("Send Ping frame") - - if not isinstance(opaque_data, bytes) or len(opaque_data) != 8: - raise ValueError("Invalid value for ping data: %r" % opaque_data) - - self.state_machine.process_input(ConnectionInputs.SEND_PING) - f = PingFrame(0) - f.opaque_data = opaque_data - self._prepare_for_sending([f]) - - def reset_stream(self, stream_id, error_code=0): - """ - Reset a stream. - - This method forcibly closes a stream by sending a RST_STREAM frame for - a given stream. This is not a graceful closure. To gracefully end a - stream, try the :meth:`end_stream - ` method. - - :param stream_id: The ID of the stream to reset. - :type stream_id: ``int`` - :param error_code: (optional) The error code to use to reset the - stream. Defaults to :data:`ErrorCodes.NO_ERROR - `. - :type error_code: ``int`` - :returns: Nothing - """ - self.config.logger.debug("Reset stream ID %d", stream_id) - self.state_machine.process_input(ConnectionInputs.SEND_RST_STREAM) - stream = self._get_stream_by_id(stream_id) - frames = stream.reset_stream(error_code) - self._prepare_for_sending(frames) - - def close_connection(self, error_code=0, additional_data=None, - last_stream_id=None): - - """ - Close a connection, emitting a GOAWAY frame. - - .. versionchanged:: 2.4.0 - Added ``additional_data`` and ``last_stream_id`` arguments. - - :param error_code: (optional) The error code to send in the GOAWAY - frame. - :param additional_data: (optional) Additional debug data indicating - a reason for closing the connection. Must be a bytestring. - :param last_stream_id: (optional) The last stream which was processed - by the sender. Defaults to ``highest_inbound_stream_id``. - :returns: Nothing - """ - self.config.logger.debug("Close connection") - self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY) - - # Additional_data must be bytes - if additional_data is not None: - assert isinstance(additional_data, bytes) - - if last_stream_id is None: - last_stream_id = self.highest_inbound_stream_id - - f = GoAwayFrame( - stream_id=0, - last_stream_id=last_stream_id, - error_code=error_code, - additional_data=(additional_data or b'') - ) - self._prepare_for_sending([f]) - - def update_settings(self, new_settings): - """ - Update the local settings. This will prepare and emit the appropriate - SETTINGS frame. - - :param new_settings: A dictionary of {setting: new value} - """ - self.config.logger.debug( - "Update connection settings to %s", new_settings - ) - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - self.local_settings.update(new_settings) - s = SettingsFrame(0) - s.settings = new_settings - self._prepare_for_sending([s]) - - def advertise_alternative_service(self, - field_value, - origin=None, - stream_id=None): - """ - Notify a client about an available Alternative Service. - - An Alternative Service is defined in `RFC 7838 - `_. An Alternative Service - notification informs a client that a given origin is also available - elsewhere. - - Alternative Services can be advertised in two ways. Firstly, they can - be advertised explicitly: that is, a server can say "origin X is also - available at Y". To advertise like this, set the ``origin`` argument - and not the ``stream_id`` argument. Alternatively, they can be - advertised implicitly: that is, a server can say "the origin you're - contacting on stream X is also available at Y". To advertise like this, - set the ``stream_id`` argument and not the ``origin`` argument. - - The explicit method of advertising can be done as long as the - connection is active. The implicit method can only be done after the - client has sent the request headers and before the server has sent the - response headers: outside of those points, Hyper-h2 will forbid sending - the Alternative Service advertisement by raising a ProtocolError. - - The ``field_value`` parameter is specified in RFC 7838. Hyper-h2 does - not validate or introspect this argument: the user is required to - ensure that it's well-formed. ``field_value`` corresponds to RFC 7838's - "Alternative Service Field Value". - - .. note:: It is strongly preferred to use the explicit method of - advertising Alternative Services. The implicit method of - advertising Alternative Services has a number of subtleties - and can lead to inconsistencies between the server and - client. Hyper-h2 allows both mechanisms, but caution is - strongly advised. - - .. versionadded:: 2.3.0 - - :param field_value: The RFC 7838 Alternative Service Field Value. This - argument is not introspected by Hyper-h2: the user is responsible - for ensuring that it is well-formed. - :type field_value: ``bytes`` - - :param origin: The origin/authority to which the Alternative Service - being advertised applies. Must not be provided at the same time as - ``stream_id``. - :type origin: ``bytes`` or ``None`` - - :param stream_id: The ID of the stream which was sent to the authority - for which this Alternative Service advertisement applies. Must not - be provided at the same time as ``origin``. - :type stream_id: ``int`` or ``None`` - - :returns: Nothing. - """ - if not isinstance(field_value, bytes): - raise ValueError("Field must be bytestring.") - - if origin is not None and stream_id is not None: - raise ValueError("Must not provide both origin and stream_id") - - self.state_machine.process_input( - ConnectionInputs.SEND_ALTERNATIVE_SERVICE - ) - - if origin is not None: - # This ALTSVC is sent on stream zero. - f = AltSvcFrame(stream_id=0) - f.origin = origin - f.field = field_value - frames = [f] - else: - stream = self._get_stream_by_id(stream_id) - frames = stream.advertise_alternative_service(field_value) - - self._prepare_for_sending(frames) - - def prioritize(self, stream_id, weight=None, depends_on=None, - exclusive=None): - """ - Notify a server about the priority of a stream. - - Stream priorities are a form of guidance to a remote server: they - inform the server about how important a given response is, so that the - server may allocate its resources (e.g. bandwidth, CPU time, etc.) - accordingly. This exists to allow clients to ensure that the most - important data arrives earlier, while less important data does not - starve out the more important data. - - Stream priorities are explained in depth in `RFC 7540 Section 5.3 - `_. - - This method updates the priority information of a single stream. It may - be called well before a stream is actively in use, or well after a - stream is closed. - - .. warning:: RFC 7540 allows for servers to change the priority of - streams. However, hyper-h2 **does not** allow server - stacks to do this. This is because most clients do not - adequately know how to respond when provided conflicting - priority information, and relatively little utility is - provided by making that functionality available. - - .. note:: hyper-h2 **does not** maintain any information about the - RFC 7540 priority tree. That means that hyper-h2 does not - prevent incautious users from creating invalid priority - trees, particularly by creating priority loops. While some - basic error checking is provided by hyper-h2, users are - strongly recommended to understand their prioritisation - strategies before using the priority tools here. - - .. note:: Priority information is strictly advisory. Servers are - allowed to disregard it entirely. Avoid relying on the idea - that your priority signaling will definitely be obeyed. - - .. versionadded:: 2.4.0 - - :param stream_id: The ID of the stream to prioritize. - :type stream_id: ``int`` - - :param weight: The weight to give the stream. Defaults to ``16``, the - default weight of any stream. May be any value between ``1`` and - ``256`` inclusive. The relative weight of a stream indicates what - proportion of available resources will be allocated to that - stream. - :type weight: ``int`` - - :param depends_on: The ID of the stream on which this stream depends. - This stream will only be progressed if it is impossible to - progress the parent stream (the one on which this one depends). - Passing the value ``0`` means that this stream does not depend on - any other. Defaults to ``0``. - :type depends_on: ``int`` - - :param exclusive: Whether this stream is an exclusive dependency of its - "parent" stream (i.e. the stream given by ``depends_on``). If a - stream is an exclusive dependency of another, that means that all - previously-set children of the parent are moved to become children - of the new exclusively-dependent stream. Defaults to ``False``. - :type exclusive: ``bool`` - """ - if not self.config.client_side: - raise RFC1122Error("Servers SHOULD NOT prioritize streams.") - - self.state_machine.process_input( - ConnectionInputs.SEND_PRIORITY - ) - - frame = PriorityFrame(stream_id) - frame = _add_frame_priority(frame, weight, depends_on, exclusive) - - self._prepare_for_sending([frame]) - - def local_flow_control_window(self, stream_id): - """ - Returns the maximum amount of data that can be sent on stream - ``stream_id``. - - This value will never be larger than the total data that can be sent on - the connection: even if the given stream allows more data, the - connection window provides a logical maximum to the amount of data that - can be sent. - - The maximum data that can be sent in a single data frame on a stream - is either this value, or the maximum frame size, whichever is - *smaller*. - - :param stream_id: The ID of the stream whose flow control window is - being queried. - :type stream_id: ``int`` - :returns: The amount of data in bytes that can be sent on the stream - before the flow control window is exhausted. - :rtype: ``int`` - """ - stream = self._get_stream_by_id(stream_id) - return min( - self.outbound_flow_control_window, - stream.outbound_flow_control_window - ) - - def remote_flow_control_window(self, stream_id): - """ - Returns the maximum amount of data the remote peer can send on stream - ``stream_id``. - - This value will never be larger than the total data that can be sent on - the connection: even if the given stream allows more data, the - connection window provides a logical maximum to the amount of data that - can be sent. - - The maximum data that can be sent in a single data frame on a stream - is either this value, or the maximum frame size, whichever is - *smaller*. - - :param stream_id: The ID of the stream whose flow control window is - being queried. - :type stream_id: ``int`` - :returns: The amount of data in bytes that can be received on the - stream before the flow control window is exhausted. - :rtype: ``int`` - """ - stream = self._get_stream_by_id(stream_id) - return min( - self.inbound_flow_control_window, - stream.inbound_flow_control_window - ) - - def acknowledge_received_data(self, acknowledged_size, stream_id): - """ - Inform the :class:`H2Connection ` that a - certain number of flow-controlled bytes have been processed, and that - the space should be handed back to the remote peer at an opportune - time. - - .. versionadded:: 2.5.0 - - :param acknowledged_size: The total *flow-controlled size* of the data - that has been processed. Note that this must include the amount of - padding that was sent with that data. - :type acknowledged_size: ``int`` - :param stream_id: The ID of the stream on which this data was received. - :type stream_id: ``int`` - :returns: Nothing - :rtype: ``None`` - """ - self.config.logger.debug( - "Ack received data on stream ID %d with size %d", - stream_id, acknowledged_size - ) - if stream_id <= 0: - raise ValueError( - "Stream ID %d is not valid for acknowledge_received_data" % - stream_id - ) - if acknowledged_size < 0: - raise ValueError("Cannot acknowledge negative data") - - frames = [] - - conn_manager = self._inbound_flow_control_window_manager - conn_increment = conn_manager.process_bytes(acknowledged_size) - if conn_increment: - f = WindowUpdateFrame(0) - f.window_increment = conn_increment - frames.append(f) - - try: - stream = self._get_stream_by_id(stream_id) - except StreamClosedError: - # The stream is already gone. We're not worried about incrementing - # the window in this case. - pass - else: - # No point incrementing the windows of closed streams. - if stream.open: - frames.extend( - stream.acknowledge_received_data(acknowledged_size) - ) - - self._prepare_for_sending(frames) - - def data_to_send(self, amount=None): - """ - Returns some data for sending out of the internal data buffer. - - This method is analogous to ``read`` on a file-like object, but it - doesn't block. Instead, it returns as much data as the user asks for, - or less if that much data is not available. It does not perform any - I/O, and so uses a different name. - - :param amount: (optional) The maximum amount of data to return. If not - set, or set to ``None``, will return as much data as possible. - :type amount: ``int`` - :returns: A bytestring containing the data to send on the wire. - :rtype: ``bytes`` - """ - if amount is None: - data = self._data_to_send - self._data_to_send = b'' - return data - else: - data = self._data_to_send[:amount] - self._data_to_send = self._data_to_send[amount:] - return data - - def clear_outbound_data_buffer(self): - """ - Clears the outbound data buffer, such that if this call was immediately - followed by a call to - :meth:`data_to_send `, that - call would return no data. - - This method should not normally be used, but is made available to avoid - exposing implementation details. - """ - self._data_to_send = b'' - - def _acknowledge_settings(self): - """ - Acknowledge settings that have been received. - - .. versionchanged:: 2.0.0 - Removed from public API, removed useless ``event`` parameter, made - automatic. - - :returns: Nothing - """ - self.state_machine.process_input(ConnectionInputs.SEND_SETTINGS) - - changes = self.remote_settings.acknowledge() - - if SettingCodes.INITIAL_WINDOW_SIZE in changes: - setting = changes[SettingCodes.INITIAL_WINDOW_SIZE] - self._flow_control_change_from_settings( - setting.original_value, - setting.new_value, - ) - - # HEADER_TABLE_SIZE changes by the remote part affect our encoder: cf. - # RFC 7540 Section 6.5.2. - if SettingCodes.HEADER_TABLE_SIZE in changes: - setting = changes[SettingCodes.HEADER_TABLE_SIZE] - self.encoder.header_table_size = setting.new_value - - if SettingCodes.MAX_FRAME_SIZE in changes: - setting = changes[SettingCodes.MAX_FRAME_SIZE] - self.max_outbound_frame_size = setting.new_value - for stream in self.streams.values(): - stream.max_outbound_frame_size = setting.new_value - - f = SettingsFrame(0) - f.flags.add('ACK') - return [f] - - def _flow_control_change_from_settings(self, old_value, new_value): - """ - Update flow control windows in response to a change in the value of - SETTINGS_INITIAL_WINDOW_SIZE. - - When this setting is changed, it automatically updates all flow control - windows by the delta in the settings values. Note that it does not - increment the *connection* flow control window, per section 6.9.2 of - RFC 7540. - """ - delta = new_value - old_value - - for stream in self.streams.values(): - stream.outbound_flow_control_window = guard_increment_window( - stream.outbound_flow_control_window, - delta - ) - - def _inbound_flow_control_change_from_settings(self, old_value, new_value): - """ - Update remote flow control windows in response to a change in the value - of SETTINGS_INITIAL_WINDOW_SIZE. - - When this setting is changed, it automatically updates all remote flow - control windows by the delta in the settings values. - """ - delta = new_value - old_value - - for stream in self.streams.values(): - stream._inbound_flow_control_change_from_settings(delta) - - def receive_data(self, data): - """ - Pass some received HTTP/2 data to the connection for handling. - - :param data: The data received from the remote peer on the network. - :type data: ``bytes`` - :returns: A list of events that the remote peer triggered by sending - this data. - """ - self.config.logger.debug( - "Process received data on connection. Received data: %r", data - ) - - events = [] - self.incoming_buffer.add_data(data) - self.incoming_buffer.max_frame_size = self.max_inbound_frame_size - - try: - for frame in self.incoming_buffer: - events.extend(self._receive_frame(frame)) - except InvalidPaddingError: - self._terminate_connection(ErrorCodes.PROTOCOL_ERROR) - raise ProtocolError("Received frame with invalid padding.") - except ProtocolError as e: - # For whatever reason, receiving the frame caused a protocol error. - # We should prepare to emit a GoAway frame before throwing the - # exception up further. No need for an event: the exception will - # do fine. - self._terminate_connection(e.error_code) - raise - - return events - - def _receive_frame(self, frame): - """ - Handle a frame received on the connection. - - .. versionchanged:: 2.0.0 - Removed from the public API. - """ - try: - # I don't love using __class__ here, maybe reconsider it. - frames, events = self._frame_dispatch_table[frame.__class__](frame) - except StreamClosedError as e: - # If the stream was closed by RST_STREAM, we just send a RST_STREAM - # to the remote peer. Otherwise, this is a connection error, and so - # we will re-raise to trigger one. - if self._stream_is_closed_by_reset(e.stream_id): - f = RstStreamFrame(e.stream_id) - f.error_code = e.error_code - self._prepare_for_sending([f]) - events = e._events - else: - raise - except StreamIDTooLowError as e: - # The stream ID seems invalid. This may happen when the closed - # stream has been cleaned up, or when the remote peer has opened a - # new stream with a higher stream ID than this one, forcing it - # closed implicitly. - # - # Check how the stream was closed: depending on the mechanism, it - # is either a stream error or a connection error. - if self._stream_is_closed_by_reset(e.stream_id): - # Closed by RST_STREAM is a stream error. - f = RstStreamFrame(e.stream_id) - f.error_code = ErrorCodes.STREAM_CLOSED - self._prepare_for_sending([f]) - events = [] - elif self._stream_is_closed_by_end(e.stream_id): - # Closed by END_STREAM is a connection error. - raise StreamClosedError(e.stream_id) - else: - # Closed implicitly, also a connection error, but of type - # PROTOCOL_ERROR. - raise - else: - self._prepare_for_sending(frames) - - return events - - def _terminate_connection(self, error_code): - """ - Terminate the connection early. Used in error handling blocks to send - GOAWAY frames. - """ - f = GoAwayFrame(0) - f.last_stream_id = self.highest_inbound_stream_id - f.error_code = error_code - self.state_machine.process_input(ConnectionInputs.SEND_GOAWAY) - self._prepare_for_sending([f]) - - def _receive_headers_frame(self, frame): - """ - Receive a headers frame on the connection. - """ - # If necessary, check we can open the stream. Also validate that the - # stream ID is valid. - if frame.stream_id not in self.streams: - max_open_streams = self.local_settings.max_concurrent_streams - if (self.open_inbound_streams + 1) > max_open_streams: - raise TooManyStreamsError( - "Max outbound streams is %d, %d open" % - (max_open_streams, self.open_outbound_streams) - ) - - # Let's decode the headers. We handle headers as bytes internally up - # until we hang them off the event, at which point we may optionally - # convert them to unicode. - headers = _decode_headers(self.decoder, frame.data) - - events = self.state_machine.process_input( - ConnectionInputs.RECV_HEADERS - ) - stream = self._get_or_create_stream( - frame.stream_id, AllowedStreamIDs(not self.config.client_side) - ) - frames, stream_events = stream.receive_headers( - headers, - 'END_STREAM' in frame.flags, - self.config.header_encoding - ) - - if 'PRIORITY' in frame.flags: - p_frames, p_events = self._receive_priority_frame(frame) - stream_events[0].priority_updated = p_events[0] - stream_events.extend(p_events) - assert not p_frames - - return frames, events + stream_events - - def _receive_push_promise_frame(self, frame): - """ - Receive a push-promise frame on the connection. - """ - if not self.local_settings.enable_push: - raise ProtocolError("Received pushed stream") - - pushed_headers = _decode_headers(self.decoder, frame.data) - - events = self.state_machine.process_input( - ConnectionInputs.RECV_PUSH_PROMISE - ) - - try: - stream = self._get_stream_by_id(frame.stream_id) - except NoSuchStreamError: - # We need to check if the parent stream was reset by us. If it was - # then we presume that the PUSH_PROMISE was in flight when we reset - # the parent stream. Rather than accept the new stream, just reset - # it. - # - # If this was closed naturally, however, we should call this a - # PROTOCOL_ERROR: pushing a stream on a naturally closed stream is - # a real problem because it creates a brand new stream that the - # remote peer now believes exists. - if (self._stream_closed_by(frame.stream_id) == - StreamClosedBy.SEND_RST_STREAM): - f = RstStreamFrame(frame.promised_stream_id) - f.error_code = ErrorCodes.REFUSED_STREAM - return [f], events - - raise ProtocolError("Attempted to push on closed stream.") - - # We need to prevent peers pushing streams in response to streams that - # they themselves have already pushed: see #163 and RFC 7540 § 6.6. The - # easiest way to do that is to assert that the stream_id is not even: - # this shortcut works because only servers can push and the state - # machine will enforce this. - if (frame.stream_id % 2) == 0: - raise ProtocolError("Cannot recursively push streams.") - - try: - frames, stream_events = stream.receive_push_promise_in_band( - frame.promised_stream_id, - pushed_headers, - self.config.header_encoding, - ) - except StreamClosedError: - # The parent stream was reset by us, so we presume that - # PUSH_PROMISE was in flight when we reset the parent stream. - # So we just reset the new stream. - f = RstStreamFrame(frame.promised_stream_id) - f.error_code = ErrorCodes.REFUSED_STREAM - return [f], events - - new_stream = self._begin_new_stream( - frame.promised_stream_id, AllowedStreamIDs.EVEN - ) - self.streams[frame.promised_stream_id] = new_stream - new_stream.remotely_pushed(pushed_headers) - - return frames, events + stream_events - - def _receive_data_frame(self, frame): - """ - Receive a data frame on the connection. - """ - flow_controlled_length = frame.flow_controlled_length - - events = self.state_machine.process_input( - ConnectionInputs.RECV_DATA - ) - self._inbound_flow_control_window_manager.window_consumed( - flow_controlled_length - ) - stream = self._get_stream_by_id(frame.stream_id) - frames, stream_events = stream.receive_data( - frame.data, - 'END_STREAM' in frame.flags, - flow_controlled_length - ) - return frames, events + stream_events - - def _receive_settings_frame(self, frame): - """ - Receive a SETTINGS frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_SETTINGS - ) - - # This is an ack of the local settings. - if 'ACK' in frame.flags: - changed_settings = self._local_settings_acked() - ack_event = SettingsAcknowledged() - ack_event.changed_settings = changed_settings - events.append(ack_event) - return [], events - - # Add the new settings. - self.remote_settings.update(frame.settings) - events.append( - RemoteSettingsChanged.from_settings( - self.remote_settings, frame.settings - ) - ) - frames = self._acknowledge_settings() - - return frames, events - - def _receive_window_update_frame(self, frame): - """ - Receive a WINDOW_UPDATE frame on the connection. - """ - # Validate the frame. - if not (1 <= frame.window_increment <= self.MAX_WINDOW_INCREMENT): - raise ProtocolError( - "Flow control increment must be between 1 and %d, received %d" - % (self.MAX_WINDOW_INCREMENT, frame.window_increment) - ) - - events = self.state_machine.process_input( - ConnectionInputs.RECV_WINDOW_UPDATE - ) - - if frame.stream_id: - stream = self._get_stream_by_id(frame.stream_id) - frames, stream_events = stream.receive_window_update( - frame.window_increment - ) - else: - # Increment our local flow control window. - self.outbound_flow_control_window = guard_increment_window( - self.outbound_flow_control_window, - frame.window_increment - ) - - # FIXME: Should we split this into one event per active stream? - window_updated_event = WindowUpdated() - window_updated_event.stream_id = 0 - window_updated_event.delta = frame.window_increment - stream_events = [window_updated_event] - frames = [] - - return frames, events + stream_events - - def _receive_ping_frame(self, frame): - """ - Receive a PING frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_PING - ) - flags = [] - - if 'ACK' in frame.flags: - evt = PingAckReceived() - else: - evt = PingReceived() - - # automatically ACK the PING with the same 'opaque data' - f = PingFrame(0) - f.flags = {'ACK'} - f.opaque_data = frame.opaque_data - flags.append(f) - - evt.ping_data = frame.opaque_data - events.append(evt) - - return flags, events - - def _receive_rst_stream_frame(self, frame): - """ - Receive a RST_STREAM frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_RST_STREAM - ) - try: - stream = self._get_stream_by_id(frame.stream_id) - except NoSuchStreamError: - # The stream is missing. That's ok, we just do nothing here. - stream_frames = [] - stream_events = [] - else: - stream_frames, stream_events = stream.stream_reset(frame) - - return stream_frames, events + stream_events - - def _receive_priority_frame(self, frame): - """ - Receive a PRIORITY frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_PRIORITY - ) - - event = PriorityUpdated() - event.stream_id = frame.stream_id - event.depends_on = frame.depends_on - event.exclusive = frame.exclusive - - # Weight is an integer between 1 and 256, but the byte only allows - # 0 to 255: add one. - event.weight = frame.stream_weight + 1 - - # A stream may not depend on itself. - if event.depends_on == frame.stream_id: - raise ProtocolError( - "Stream %d may not depend on itself" % frame.stream_id - ) - events.append(event) - - return [], events - - def _receive_goaway_frame(self, frame): - """ - Receive a GOAWAY frame on the connection. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_GOAWAY - ) - - # Clear the outbound data buffer: we cannot send further data now. - self.clear_outbound_data_buffer() - - # Fire an appropriate ConnectionTerminated event. - new_event = ConnectionTerminated() - new_event.error_code = _error_code_from_int(frame.error_code) - new_event.last_stream_id = frame.last_stream_id - new_event.additional_data = (frame.additional_data - if frame.additional_data else None) - events.append(new_event) - - return [], events - - def _receive_naked_continuation(self, frame): - """ - A naked CONTINUATION frame has been received. This is always an error, - but the type of error it is depends on the state of the stream and must - transition the state of the stream, so we need to pass it to the - appropriate stream. - """ - stream = self._get_stream_by_id(frame.stream_id) - stream.receive_continuation() - assert False, "Should not be reachable" - - def _receive_alt_svc_frame(self, frame): - """ - An ALTSVC frame has been received. This frame, specified in RFC 7838, - is used to advertise alternative places where the same service can be - reached. - - This frame can optionally be received either on a stream or on stream - 0, and its semantics are different in each case. - """ - events = self.state_machine.process_input( - ConnectionInputs.RECV_ALTERNATIVE_SERVICE - ) - frames = [] - - if frame.stream_id: - # Given that it makes no sense to receive ALTSVC on a stream - # before that stream has been opened with a HEADERS frame, the - # ALTSVC frame cannot create a stream. If the stream is not - # present, we simply ignore the frame. - try: - stream = self._get_stream_by_id(frame.stream_id) - except (NoSuchStreamError, StreamClosedError): - pass - else: - stream_frames, stream_events = stream.receive_alt_svc(frame) - frames.extend(stream_frames) - events.extend(stream_events) - else: - # This frame is sent on stream 0. The origin field on the frame - # must be present, though if it isn't it's not a ProtocolError - # (annoyingly), we just need to ignore it. - if not frame.origin: - return frames, events - - # If we're a server, we want to ignore this (RFC 7838 says so). - if not self.config.client_side: - return frames, events - - event = AlternativeServiceAvailable() - event.origin = frame.origin - event.field_value = frame.field - events.append(event) - - return frames, events - - def _receive_unknown_frame(self, frame): - """ - We have received a frame that we do not understand. This is almost - certainly an extension frame, though it's impossible to be entirely - sure. - - RFC 7540 § 5.5 says that we MUST ignore unknown frame types: so we - do. We do notify the user that we received one, however. - """ - # All we do here is log. - self.config.logger.debug( - "Received unknown extension frame (ID %d)", frame.stream_id - ) - event = UnknownFrameReceived() - event.frame = frame - return [], [event] - - def _local_settings_acked(self): - """ - Handle the local settings being ACKed, update internal state. - """ - changes = self.local_settings.acknowledge() - - if SettingCodes.INITIAL_WINDOW_SIZE in changes: - setting = changes[SettingCodes.INITIAL_WINDOW_SIZE] - self._inbound_flow_control_change_from_settings( - setting.original_value, - setting.new_value, - ) - - if SettingCodes.MAX_HEADER_LIST_SIZE in changes: - setting = changes[SettingCodes.MAX_HEADER_LIST_SIZE] - self.decoder.max_header_list_size = setting.new_value - - if SettingCodes.MAX_FRAME_SIZE in changes: - setting = changes[SettingCodes.MAX_FRAME_SIZE] - self.max_inbound_frame_size = setting.new_value - - if SettingCodes.HEADER_TABLE_SIZE in changes: - setting = changes[SettingCodes.HEADER_TABLE_SIZE] - # This is safe across all hpack versions: some versions just won't - # respect it. - self.decoder.max_allowed_table_size = setting.new_value - - return changes - - def _stream_id_is_outbound(self, stream_id): - """ - Returns ``True`` if the stream ID corresponds to an outbound stream - (one initiated by this peer), returns ``False`` otherwise. - """ - return (stream_id % 2 == int(self.config.client_side)) - - def _stream_closed_by(self, stream_id): - """ - Returns how the stream was closed. - - The return value will be either a member of - ``h2.stream.StreamClosedBy`` or ``None``. If ``None``, the stream was - closed implicitly by the peer opening a stream with a higher stream ID - before opening this one. - """ - if stream_id in self.streams: - return self.streams[stream_id].closed_by - if stream_id in self._closed_streams: - return self._closed_streams[stream_id] - return None - - def _stream_is_closed_by_reset(self, stream_id): - """ - Returns ``True`` if the stream was closed by sending or receiving a - RST_STREAM frame. Returns ``False`` otherwise. - """ - return self._stream_closed_by(stream_id) in ( - StreamClosedBy.RECV_RST_STREAM, StreamClosedBy.SEND_RST_STREAM - ) - - def _stream_is_closed_by_end(self, stream_id): - """ - Returns ``True`` if the stream was closed by sending or receiving an - END_STREAM flag in a HEADERS or DATA frame. Returns ``False`` - otherwise. - """ - return self._stream_closed_by(stream_id) in ( - StreamClosedBy.RECV_END_STREAM, StreamClosedBy.SEND_END_STREAM - ) - - -def _add_frame_priority(frame, weight=None, depends_on=None, exclusive=None): - """ - Adds priority data to a given frame. Does not change any flags set on that - frame: if the caller is adding priority information to a HEADERS frame they - must set that themselves. - - This method also deliberately sets defaults for anything missing. - - This method validates the input values. - """ - # A stream may not depend on itself. - if depends_on == frame.stream_id: - raise ProtocolError( - "Stream %d may not depend on itself" % frame.stream_id - ) - - # Weight must be between 1 and 256. - if weight is not None: - if weight > 256 or weight < 1: - raise ProtocolError( - "Weight must be between 1 and 256, not %d" % weight - ) - else: - # Weight is an integer between 1 and 256, but the byte only allows - # 0 to 255: subtract one. - weight -= 1 - - # Set defaults for anything not provided. - weight = weight if weight is not None else 15 - depends_on = depends_on if depends_on is not None else 0 - exclusive = exclusive if exclusive is not None else False - - frame.stream_weight = weight - frame.depends_on = depends_on - frame.exclusive = exclusive - - return frame - - -def _decode_headers(decoder, encoded_header_block): - """ - Decode a HPACK-encoded header block, translating HPACK exceptions into - sensible hyper-h2 errors. - - This only ever returns bytestring headers: hyper-h2 may emit them as - unicode later, but internally it processes them as bytestrings only. - """ - try: - return decoder.decode(encoded_header_block, raw=True) - except OversizedHeaderListError as e: - # This is a symptom of a HPACK bomb attack: the user has - # disregarded our requirements on how large a header block we'll - # accept. - raise DenialOfServiceError("Oversized header block: %s" % e) - except (HPACKError, IndexError, TypeError, UnicodeDecodeError) as e: - # We should only need HPACKError here, but versions of HPACK older - # than 2.1.0 throw all three others as well. For maximum - # compatibility, catch all of them. - raise ProtocolError("Error decoding header block: %s" % e) diff --git a/py3.7/lib/python3.7/site-packages/h2/errors.py b/py3.7/lib/python3.7/site-packages/h2/errors.py deleted file mode 100644 index baef200..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/errors.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/errors -~~~~~~~~~~~~~~~~~~~ - -Global error code registry containing the established HTTP/2 error codes. - -The current registry is available at: -https://tools.ietf.org/html/rfc7540#section-11.4 -""" -import enum - - -class ErrorCodes(enum.IntEnum): - """ - All known HTTP/2 error codes. - - .. versionadded:: 2.5.0 - """ - #: Graceful shutdown. - NO_ERROR = 0x0 - - #: Protocol error detected. - PROTOCOL_ERROR = 0x1 - - #: Implementation fault. - INTERNAL_ERROR = 0x2 - - #: Flow-control limits exceeded. - FLOW_CONTROL_ERROR = 0x3 - - #: Settings not acknowledged. - SETTINGS_TIMEOUT = 0x4 - - #: Frame received for closed stream. - STREAM_CLOSED = 0x5 - - #: Frame size incorrect. - FRAME_SIZE_ERROR = 0x6 - - #: Stream not processed. - REFUSED_STREAM = 0x7 - - #: Stream cancelled. - CANCEL = 0x8 - - #: Compression state not updated. - COMPRESSION_ERROR = 0x9 - - #: TCP connection error for CONNECT method. - CONNECT_ERROR = 0xa - - #: Processing capacity exceeded. - ENHANCE_YOUR_CALM = 0xb - - #: Negotiated TLS parameters not acceptable. - INADEQUATE_SECURITY = 0xc - - #: Use HTTP/1.1 for the request. - HTTP_1_1_REQUIRED = 0xd - - -def _error_code_from_int(code): - """ - Given an integer error code, returns either one of :class:`ErrorCodes - ` or, if not present in the known set of codes, - returns the integer directly. - """ - try: - return ErrorCodes(code) - except ValueError: - return code - - -__all__ = ['ErrorCodes'] diff --git a/py3.7/lib/python3.7/site-packages/h2/events.py b/py3.7/lib/python3.7/site-packages/h2/events.py deleted file mode 100644 index a06c990..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/events.py +++ /dev/null @@ -1,648 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/events -~~~~~~~~~ - -Defines Event types for HTTP/2. - -Events are returned by the H2 state machine to allow implementations to keep -track of events triggered by receiving data. Each time data is provided to the -H2 state machine it processes the data and returns a list of Event objects. -""" -import binascii - -from .settings import ChangedSetting, _setting_code_from_int - - -class Event(object): - """ - Base class for h2 events. - """ - pass - - -class RequestReceived(Event): - """ - The RequestReceived event is fired whenever request headers are received. - This event carries the HTTP headers for the given request and the stream ID - of the new stream. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - def __init__(self): - #: The Stream ID for the stream this request was made on. - self.stream_id = None - - #: The request headers. - self.headers = None - - #: If this request also ended the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended = None - - #: If this request also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated = None - - def __repr__(self): - return "" % ( - self.stream_id, self.headers - ) - - -class ResponseReceived(Event): - """ - The ResponseReceived event is fired whenever response headers are received. - This event carries the HTTP headers for the given response and the stream - ID of the new stream. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - def __init__(self): - #: The Stream ID for the stream this response was made on. - self.stream_id = None - - #: The response headers. - self.headers = None - - #: If this response also ended the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended = None - - #: If this response also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated = None - - def __repr__(self): - return "" % ( - self.stream_id, self.headers - ) - - -class TrailersReceived(Event): - """ - The TrailersReceived event is fired whenever trailers are received on a - stream. Trailers are a set of headers sent after the body of the - request/response, and are used to provide information that wasn't known - ahead of time (e.g. content-length). This event carries the HTTP header - fields that form the trailers and the stream ID of the stream on which they - were received. - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` and ``priority_updated`` properties. - """ - def __init__(self): - #: The Stream ID for the stream on which these trailers were received. - self.stream_id = None - - #: The trailers themselves. - self.headers = None - - #: Trailers always end streams. This property has the associated - #: :class:`StreamEnded ` in it. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended = None - - #: If the trailers also set associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated = None - - def __repr__(self): - return "" % ( - self.stream_id, self.headers - ) - - -class _HeadersSent(Event): - """ - The _HeadersSent event is fired whenever headers are sent. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - pass - - -class _ResponseSent(_HeadersSent): - """ - The _ResponseSent event is fired whenever response headers are sent - on a stream. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - pass - - -class _RequestSent(_HeadersSent): - """ - The _RequestSent event is fired whenever request headers are sent - on a stream. - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - pass - - -class _TrailersSent(_HeadersSent): - """ - The _TrailersSent event is fired whenever trailers are sent on a - stream. Trailers are a set of headers sent after the body of the - request/response, and are used to provide information that wasn't known - ahead of time (e.g. content-length). - - This is an internal event, used to determine validation steps on - outgoing header blocks. - """ - pass - - -class _PushedRequestSent(_HeadersSent): - """ - The _PushedRequestSent event is fired whenever pushed request headers are - sent. - - This is an internal event, used to determine validation steps on outgoing - header blocks. - """ - pass - - -class InformationalResponseReceived(Event): - """ - The InformationalResponseReceived event is fired when an informational - response (that is, one whose status code is a 1XX code) is received from - the remote peer. - - The remote peer may send any number of these, from zero upwards. These - responses are most commonly sent in response to requests that have the - ``expect: 100-continue`` header field present. Most users can safely - ignore this event unless you are intending to use the - ``expect: 100-continue`` flow, or are for any reason expecting a different - 1XX status code. - - .. versionadded:: 2.2.0 - - .. versionchanged:: 2.3.0 - Changed the type of ``headers`` to :class:`HeaderTuple - `. This has no effect on current users. - - .. versionchanged:: 2.4.0 - Added ``priority_updated`` property. - """ - def __init__(self): - #: The Stream ID for the stream this informational response was made - #: on. - self.stream_id = None - - #: The headers for this informational response. - self.headers = None - - #: If this response also had associated priority information, the - #: associated :class:`PriorityUpdated ` - #: event will be available here. - #: - #: .. versionadded:: 2.4.0 - self.priority_updated = None - - def __repr__(self): - return "" % ( - self.stream_id, self.headers - ) - - -class DataReceived(Event): - """ - The DataReceived event is fired whenever data is received on a stream from - the remote peer. The event carries the data itself, and the stream ID on - which the data was received. - - .. versionchanged:: 2.4.0 - Added ``stream_ended`` property. - """ - def __init__(self): - #: The Stream ID for the stream this data was received on. - self.stream_id = None - - #: The data itself. - self.data = None - - #: The amount of data received that counts against the flow control - #: window. Note that padding counts against the flow control window, so - #: when adjusting flow control you should always use this field rather - #: than ``len(data)``. - self.flow_controlled_length = None - - #: If this data chunk also completed the stream, the associated - #: :class:`StreamEnded ` event will be available - #: here. - #: - #: .. versionadded:: 2.4.0 - self.stream_ended = None - - def __repr__(self): - return ( - "" % ( - self.stream_id, - self.flow_controlled_length, - _bytes_representation(self.data[:20]), - ) - ) - - -class WindowUpdated(Event): - """ - The WindowUpdated event is fired whenever a flow control window changes - size. HTTP/2 defines flow control windows for connections and streams: this - event fires for both connections and streams. The event carries the ID of - the stream to which it applies (set to zero if the window update applies to - the connection), and the delta in the window size. - """ - def __init__(self): - #: The Stream ID of the stream whose flow control window was changed. - #: May be ``0`` if the connection window was changed. - self.stream_id = None - - #: The window delta. - self.delta = None - - def __repr__(self): - return "" % ( - self.stream_id, self.delta - ) - - -class RemoteSettingsChanged(Event): - """ - The RemoteSettingsChanged event is fired whenever the remote peer changes - its settings. It contains a complete inventory of changed settings, - including their previous values. - - In HTTP/2, settings changes need to be acknowledged. hyper-h2 automatically - acknowledges settings changes for efficiency. However, it is possible that - the caller may not be happy with the changed setting. - - When this event is received, the caller should confirm that the new - settings are acceptable. If they are not acceptable, the user should close - the connection with the error code :data:`PROTOCOL_ERROR - `. - - .. versionchanged:: 2.0.0 - Prior to this version the user needed to acknowledge settings changes. - This is no longer the case: hyper-h2 now automatically acknowledges - them. - """ - def __init__(self): - #: A dictionary of setting byte to - #: :class:`ChangedSetting `, representing - #: the changed settings. - self.changed_settings = {} - - @classmethod - def from_settings(cls, old_settings, new_settings): - """ - Build a RemoteSettingsChanged event from a set of changed settings. - - :param old_settings: A complete collection of old settings, in the form - of a dictionary of ``{setting: value}``. - :param new_settings: All the changed settings and their new values, in - the form of a dictionary of ``{setting: value}``. - """ - e = cls() - for setting, new_value in new_settings.items(): - setting = _setting_code_from_int(setting) - original_value = old_settings.get(setting) - change = ChangedSetting(setting, original_value, new_value) - e.changed_settings[setting] = change - - return e - - def __repr__(self): - return "" % ( - ", ".join(repr(cs) for cs in self.changed_settings.values()), - ) - - -class PingReceived(Event): - """ - The PingReceived event is fired whenever a PING is received. It contains - the 'opaque data' of the PING frame. A ping acknowledgment with the same - 'opaque data' is automatically emitted after receiving a ping. - - .. versionadded:: 3.1.0 - """ - def __init__(self): - #: The data included on the ping. - self.ping_data = None - - def __repr__(self): - return "" % ( - _bytes_representation(self.ping_data), - ) - - -class PingAcknowledged(Event): - """ - Same as PingAckReceived. - - .. deprecated:: 3.1.0 - """ - def __init__(self): - #: The data included on the ping. - self.ping_data = None - - def __repr__(self): - return "" % ( - _bytes_representation(self.ping_data), - ) - - -class PingAckReceived(PingAcknowledged): - """ - The PingAckReceived event is fired whenever a PING acknowledgment is - received. It contains the 'opaque data' of the PING+ACK frame, allowing the - user to correlate PINGs and calculate RTT. - - .. versionadded:: 3.1.0 - """ - pass - - -class StreamEnded(Event): - """ - The StreamEnded event is fired whenever a stream is ended by a remote - party. The stream may not be fully closed if it has not been closed - locally, but no further data or headers should be expected on that stream. - """ - def __init__(self): - #: The Stream ID of the stream that was closed. - self.stream_id = None - - def __repr__(self): - return "" % self.stream_id - - -class StreamReset(Event): - """ - The StreamReset event is fired in two situations. The first is when the - remote party forcefully resets the stream. The second is when the remote - party has made a protocol error which only affects a single stream. In this - case, Hyper-h2 will terminate the stream early and return this event. - - .. versionchanged:: 2.0.0 - This event is now fired when Hyper-h2 automatically resets a stream. - """ - def __init__(self): - #: The Stream ID of the stream that was reset. - self.stream_id = None - - #: The error code given. Either one of :class:`ErrorCodes - #: ` or ``int`` - self.error_code = None - - #: Whether the remote peer sent a RST_STREAM or we did. - self.remote_reset = True - - def __repr__(self): - return "" % ( - self.stream_id, self.error_code, self.remote_reset - ) - - -class PushedStreamReceived(Event): - """ - The PushedStreamReceived event is fired whenever a pushed stream has been - received from a remote peer. The event carries on it the new stream ID, the - ID of the parent stream, and the request headers pushed by the remote peer. - """ - def __init__(self): - #: The Stream ID of the stream created by the push. - self.pushed_stream_id = None - - #: The Stream ID of the stream that the push is related to. - self.parent_stream_id = None - - #: The request headers, sent by the remote party in the push. - self.headers = None - - def __repr__(self): - return ( - "" % ( - self.pushed_stream_id, - self.parent_stream_id, - self.headers, - ) - ) - - -class SettingsAcknowledged(Event): - """ - The SettingsAcknowledged event is fired whenever a settings ACK is received - from the remote peer. The event carries on it the settings that were - acknowedged, in the same format as - :class:`h2.events.RemoteSettingsChanged`. - """ - def __init__(self): - #: A dictionary of setting byte to - #: :class:`ChangedSetting `, representing - #: the changed settings. - self.changed_settings = {} - - def __repr__(self): - return "" % ( - ", ".join(repr(cs) for cs in self.changed_settings.values()), - ) - - -class PriorityUpdated(Event): - """ - The PriorityUpdated event is fired whenever a stream sends updated priority - information. This can occur when the stream is opened, or at any time - during the stream lifetime. - - This event is purely advisory, and does not need to be acted on. - - .. versionadded:: 2.0.0 - """ - def __init__(self): - #: The ID of the stream whose priority information is being updated. - self.stream_id = None - - #: The new stream weight. May be the same as the original stream - #: weight. An integer between 1 and 256. - self.weight = None - - #: The stream ID this stream now depends on. May be ``0``. - self.depends_on = None - - #: Whether the stream *exclusively* depends on the parent stream. If it - #: does, this stream should inherit the current children of its new - #: parent. - self.exclusive = None - - def __repr__(self): - return ( - "" % ( - self.stream_id, - self.weight, - self.depends_on, - self.exclusive - ) - ) - - -class ConnectionTerminated(Event): - """ - The ConnectionTerminated event is fired when a connection is torn down by - the remote peer using a GOAWAY frame. Once received, no further action may - be taken on the connection: a new connection must be established. - """ - def __init__(self): - #: The error code cited when tearing down the connection. Should be - #: one of :class:`ErrorCodes `, but may not be if - #: unknown HTTP/2 extensions are being used. - self.error_code = None - - #: The stream ID of the last stream the remote peer saw. This can - #: provide an indication of what data, if any, never reached the remote - #: peer and so can safely be resent. - self.last_stream_id = None - - #: Additional debug data that can be appended to GOAWAY frame. - self.additional_data = None - - def __repr__(self): - return ( - "" % ( - self.error_code, - self.last_stream_id, - _bytes_representation( - self.additional_data[:20] - if self.additional_data else None) - ) - ) - - -class AlternativeServiceAvailable(Event): - """ - The AlternativeServiceAvailable event is fired when the remote peer - advertises an `RFC 7838 `_ Alternative - Service using an ALTSVC frame. - - This event always carries the origin to which the ALTSVC information - applies. That origin is either supplied by the server directly, or inferred - by hyper-h2 from the ``:authority`` pseudo-header field that was sent by - the user when initiating a given stream. - - This event also carries what RFC 7838 calls the "Alternative Service Field - Value", which is formatted like a HTTP header field and contains the - relevant alternative service information. Hyper-h2 does not parse or in any - way modify that information: the user is required to do that. - - This event can only be fired on the client end of a connection. - - .. versionadded:: 2.3.0 - """ - def __init__(self): - #: The origin to which the alternative service field value applies. - #: This field is either supplied by the server directly, or inferred by - #: hyper-h2 from the ``:authority`` pseudo-header field that was sent - #: by the user when initiating the stream on which the frame was - #: received. - self.origin = None - - #: The ALTSVC field value. This contains information about the HTTP - #: alternative service being advertised by the server. Hyper-h2 does - #: not parse this field: it is left exactly as sent by the server. The - #: structure of the data in this field is given by `RFC 7838 Section 3 - #: `_. - self.field_value = None - - def __repr__(self): - return ( - "" % ( - self.origin.decode('utf-8', 'ignore'), - self.field_value.decode('utf-8', 'ignore'), - ) - ) - - -class UnknownFrameReceived(Event): - """ - The UnknownFrameReceived event is fired when the remote peer sends a frame - that hyper-h2 does not understand. This occurs primarily when the remote - peer is employing HTTP/2 extensions that hyper-h2 doesn't know anything - about. - - RFC 7540 requires that HTTP/2 implementations ignore these frames. hyper-h2 - does so. However, this event is fired to allow implementations to perform - special processing on those frames if needed (e.g. if the implementation - is capable of handling the frame itself). - - .. versionadded:: 2.7.0 - """ - def __init__(self): - #: The hyperframe Frame object that encapsulates the received frame. - self.frame = None - - def __repr__(self): - return "" - - -def _bytes_representation(data): - """ - Converts a bytestring into something that is safe to print on all Python - platforms. - - This function is relatively expensive, so it should not be called on the - mainline of the code. It's safe to use in things like object repr methods - though. - """ - if data is None: - return None - - hex = binascii.hexlify(data) - - # This is moderately clever: on all Python versions hexlify returns a byte - # string. On Python 3 we want an actual string, so we just check whether - # that's what we have. - if not isinstance(hex, str): # pragma: no cover - hex = hex.decode('ascii') - - return hex diff --git a/py3.7/lib/python3.7/site-packages/h2/exceptions.py b/py3.7/lib/python3.7/site-packages/h2/exceptions.py deleted file mode 100644 index 388f9e9..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/exceptions.py +++ /dev/null @@ -1,186 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/exceptions -~~~~~~~~~~~~~ - -Exceptions for the HTTP/2 module. -""" -import h2.errors - - -class H2Error(Exception): - """ - The base class for all exceptions for the HTTP/2 module. - """ - - -class ProtocolError(H2Error): - """ - An action was attempted in violation of the HTTP/2 protocol. - """ - #: The error code corresponds to this kind of Protocol Error. - error_code = h2.errors.ErrorCodes.PROTOCOL_ERROR - - -class FrameTooLargeError(ProtocolError): - """ - The frame that we tried to send or that we received was too large. - """ - #: This error code that corresponds to this kind of Protocol Error. - error_code = h2.errors.ErrorCodes.FRAME_SIZE_ERROR - - -class FrameDataMissingError(ProtocolError): - """ - The frame that we received is missing some data. - - .. versionadded:: 2.0.0 - """ - #: The error code that corresponds to this kind of Protocol Error - error_code = h2.errors.ErrorCodes.FRAME_SIZE_ERROR - - -class TooManyStreamsError(ProtocolError): - """ - An attempt was made to open a stream that would lead to too many concurrent - streams. - """ - pass - - -class FlowControlError(ProtocolError): - """ - An attempted action violates flow control constraints. - """ - #: The error code that corresponds to this kind of - #: :class:`ProtocolError ` - error_code = h2.errors.ErrorCodes.FLOW_CONTROL_ERROR - - -class StreamIDTooLowError(ProtocolError): - """ - An attempt was made to open a stream that had an ID that is lower than the - highest ID we have seen on this connection. - """ - def __init__(self, stream_id, max_stream_id): - #: The ID of the stream that we attempted to open. - self.stream_id = stream_id - - #: The current highest-seen stream ID. - self.max_stream_id = max_stream_id - - def __str__(self): - return "StreamIDTooLowError: %d is lower than %d" % ( - self.stream_id, self.max_stream_id - ) - - -class NoAvailableStreamIDError(ProtocolError): - """ - There are no available stream IDs left to the connection. All stream IDs - have been exhausted. - - .. versionadded:: 2.0.0 - """ - pass - - -class NoSuchStreamError(ProtocolError): - """ - A stream-specific action referenced a stream that does not exist. - - .. versionchanged:: 2.0.0 - Became a subclass of :class:`ProtocolError - ` - """ - def __init__(self, stream_id): - #: The stream ID that corresponds to the non-existent stream. - self.stream_id = stream_id - - -class StreamClosedError(NoSuchStreamError): - """ - A more specific form of - :class:`NoSuchStreamError `. Indicates - that the stream has since been closed, and that all state relating to that - stream has been removed. - """ - def __init__(self, stream_id): - #: The stream ID that corresponds to the nonexistent stream. - self.stream_id = stream_id - - #: The relevant HTTP/2 error code. - self.error_code = h2.errors.ErrorCodes.STREAM_CLOSED - - # Any events that internal code may need to fire. Not relevant to - # external users that may receive a StreamClosedError. - self._events = [] - - -class InvalidSettingsValueError(ProtocolError, ValueError): - """ - An attempt was made to set an invalid Settings value. - - .. versionadded:: 2.0.0 - """ - def __init__(self, msg, error_code): - super(InvalidSettingsValueError, self).__init__(msg) - self.error_code = error_code - - -class InvalidBodyLengthError(ProtocolError): - """ - The remote peer sent more or less data that the Content-Length header - indicated. - - .. versionadded:: 2.0.0 - """ - def __init__(self, expected, actual): - self.expected_length = expected - self.actual_length = actual - - def __str__(self): - return "InvalidBodyLengthError: Expected %d bytes, received %d" % ( - self.expected_length, self.actual_length - ) - - -class UnsupportedFrameError(ProtocolError, KeyError): - """ - The remote peer sent a frame that is unsupported in this context. - - .. versionadded:: 2.1.0 - """ - # TODO: Remove the KeyError in 3.0.0 - pass - - -class RFC1122Error(H2Error): - """ - Emitted when users attempt to do something that is literally allowed by the - relevant RFC, but is sufficiently ill-defined that it's unwise to allow - users to actually do it. - - While there is some disagreement about whether or not we should be liberal - in what accept, it is a truth universally acknowledged that we should be - conservative in what emit. - - .. versionadded:: 2.4.0 - """ - # shazow says I'm going to regret naming the exception this way. If that - # turns out to be true, TELL HIM NOTHING. - pass - - -class DenialOfServiceError(ProtocolError): - """ - Emitted when the remote peer exhibits a behaviour that is likely to be an - attempt to perform a Denial of Service attack on the implementation. This - is a form of ProtocolError that carries a different error code, and allows - more easy detection of this kind of behaviour. - - .. versionadded:: 2.5.0 - """ - #: The error code that corresponds to this kind of - #: :class:`ProtocolError ` - error_code = h2.errors.ErrorCodes.ENHANCE_YOUR_CALM diff --git a/py3.7/lib/python3.7/site-packages/h2/frame_buffer.py b/py3.7/lib/python3.7/site-packages/h2/frame_buffer.py deleted file mode 100644 index e79f6ec..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/frame_buffer.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/frame_buffer -~~~~~~~~~~~~~~~ - -A data structure that provides a way to iterate over a byte buffer in terms of -frames. -""" -from hyperframe.exceptions import InvalidFrameError -from hyperframe.frame import ( - Frame, HeadersFrame, ContinuationFrame, PushPromiseFrame -) - -from .exceptions import ( - ProtocolError, FrameTooLargeError, FrameDataMissingError -) - -# To avoid a DOS attack based on sending loads of continuation frames, we limit -# the maximum number we're perpared to receive. In this case, we'll set the -# limit to 64, which means the largest encoded header block we can receive by -# default is 262144 bytes long, and the largest possible *at all* is 1073741760 -# bytes long. -# -# This value seems reasonable for now, but in future we may want to evaluate -# making it configurable. -CONTINUATION_BACKLOG = 64 - - -class FrameBuffer(object): - """ - This is a data structure that expects to act as a buffer for HTTP/2 data - that allows iteraton in terms of H2 frames. - """ - def __init__(self, server=False): - self.data = b'' - self.max_frame_size = 0 - self._preamble = b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n' if server else b'' - self._preamble_len = len(self._preamble) - self._headers_buffer = [] - - def add_data(self, data): - """ - Add more data to the frame buffer. - - :param data: A bytestring containing the byte buffer. - """ - if self._preamble_len: - data_len = len(data) - of_which_preamble = min(self._preamble_len, data_len) - - if self._preamble[:of_which_preamble] != data[:of_which_preamble]: - raise ProtocolError("Invalid HTTP/2 preamble.") - - data = data[of_which_preamble:] - self._preamble_len -= of_which_preamble - self._preamble = self._preamble[of_which_preamble:] - - self.data += data - - def _parse_frame_header(self, data): - """ - Parses the frame header from the data. Either returns a tuple of - (frame, length), or throws an exception. The returned frame may be None - if the frame is of unknown type. - """ - try: - frame, length = Frame.parse_frame_header(data[:9]) - except ValueError as e: - # The frame header is invalid. This is a ProtocolError - raise ProtocolError("Invalid frame header received: %s" % str(e)) - - return frame, length - - def _validate_frame_length(self, length): - """ - Confirm that the frame is an appropriate length. - """ - if length > self.max_frame_size: - raise FrameTooLargeError( - "Received overlong frame: length %d, max %d" % - (length, self.max_frame_size) - ) - - def _update_header_buffer(self, f): - """ - Updates the internal header buffer. Returns a frame that should replace - the current one. May throw exceptions if this frame is invalid. - """ - # Check if we're in the middle of a headers block. If we are, this - # frame *must* be a CONTINUATION frame with the same stream ID as the - # leading HEADERS or PUSH_PROMISE frame. Anything else is a - # ProtocolError. If the frame *is* valid, append it to the header - # buffer. - if self._headers_buffer: - stream_id = self._headers_buffer[0].stream_id - valid_frame = ( - f is not None and - isinstance(f, ContinuationFrame) and - f.stream_id == stream_id - ) - if not valid_frame: - raise ProtocolError("Invalid frame during header block.") - - # Append the frame to the buffer. - self._headers_buffer.append(f) - if len(self._headers_buffer) > CONTINUATION_BACKLOG: - raise ProtocolError("Too many continuation frames received.") - - # If this is the end of the header block, then we want to build a - # mutant HEADERS frame that's massive. Use the original one we got, - # then set END_HEADERS and set its data appopriately. If it's not - # the end of the block, lose the current frame: we can't yield it. - if 'END_HEADERS' in f.flags: - f = self._headers_buffer[0] - f.flags.add('END_HEADERS') - f.data = b''.join(x.data for x in self._headers_buffer) - self._headers_buffer = [] - else: - f = None - elif (isinstance(f, (HeadersFrame, PushPromiseFrame)) and - 'END_HEADERS' not in f.flags): - # This is the start of a headers block! Save the frame off and then - # act like we didn't receive one. - self._headers_buffer.append(f) - f = None - - return f - - # The methods below support the iterator protocol. - def __iter__(self): - return self - - def next(self): # Python 2 - # First, check that we have enough data to successfully parse the - # next frame header. If not, bail. Otherwise, parse it. - if len(self.data) < 9: - raise StopIteration() - - try: - f, length = self._parse_frame_header(self.data) - except InvalidFrameError: # pragma: no cover - raise ProtocolError("Received frame with invalid frame header.") - - # Next, check that we have enough length to parse the frame body. If - # not, bail, leaving the frame header data in the buffer for next time. - if len(self.data) < length + 9: - raise StopIteration() - - # Confirm the frame has an appropriate length. - self._validate_frame_length(length) - - # Don't try to parse the body if we didn't get a frame we know about: - # there's nothing we can do with it anyway. - if f is not None: - try: - f.parse_body(memoryview(self.data[9:9+length])) - except InvalidFrameError: - raise FrameDataMissingError("Frame data missing or invalid") - - # At this point, as we know we'll use or discard the entire frame, we - # can update the data. - self.data = self.data[9+length:] - - # Pass the frame through the header buffer. - f = self._update_header_buffer(f) - - # If we got a frame we didn't understand or shouldn't yield, rather - # than return None it'd be better if we just tried to get the next - # frame in the sequence instead. Recurse back into ourselves to do - # that. This is safe because the amount of work we have to do here is - # strictly bounded by the length of the buffer. - return f if f is not None else self.next() - - def __next__(self): # Python 3 - return self.next() diff --git a/py3.7/lib/python3.7/site-packages/h2/settings.py b/py3.7/lib/python3.7/site-packages/h2/settings.py deleted file mode 100644 index bf87c94..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/settings.py +++ /dev/null @@ -1,339 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/settings -~~~~~~~~~~~ - -This module contains a HTTP/2 settings object. This object provides a simple -API for manipulating HTTP/2 settings, keeping track of both the current active -state of the settings and the unacknowledged future values of the settings. -""" -import collections -import enum - -from hyperframe.frame import SettingsFrame - -from h2.errors import ErrorCodes -from h2.exceptions import InvalidSettingsValueError - -try: - from collections.abc import MutableMapping -except ImportError: # pragma: no cover - # Python 2.7 compatibility - from collections import MutableMapping - - -class SettingCodes(enum.IntEnum): - """ - All known HTTP/2 setting codes. - - .. versionadded:: 2.6.0 - """ - - #: Allows the sender to inform the remote endpoint of the maximum size of - #: the header compression table used to decode header blocks, in octets. - HEADER_TABLE_SIZE = SettingsFrame.HEADER_TABLE_SIZE - - #: This setting can be used to disable server push. To disable server push - #: on a client, set this to 0. - ENABLE_PUSH = SettingsFrame.ENABLE_PUSH - - #: Indicates the maximum number of concurrent streams that the sender will - #: allow. - MAX_CONCURRENT_STREAMS = SettingsFrame.MAX_CONCURRENT_STREAMS - - #: Indicates the sender's initial window size (in octets) for stream-level - #: flow control. - INITIAL_WINDOW_SIZE = SettingsFrame.INITIAL_WINDOW_SIZE - - #: Indicates the size of the largest frame payload that the sender is - #: willing to receive, in octets. - MAX_FRAME_SIZE = SettingsFrame.MAX_FRAME_SIZE - - #: This advisory setting informs a peer of the maximum size of header list - #: that the sender is prepared to accept, in octets. The value is based on - #: the uncompressed size of header fields, including the length of the name - #: and value in octets plus an overhead of 32 octets for each header field. - MAX_HEADER_LIST_SIZE = SettingsFrame.MAX_HEADER_LIST_SIZE - - #: This setting can be used to enable the connect protocol. To enable on a - #: client set this to 1. - ENABLE_CONNECT_PROTOCOL = SettingsFrame.ENABLE_CONNECT_PROTOCOL - - -def _setting_code_from_int(code): - """ - Given an integer setting code, returns either one of :class:`SettingCodes - ` or, if not present in the known set of codes, - returns the integer directly. - """ - try: - return SettingCodes(code) - except ValueError: - return code - - -class ChangedSetting: - - def __init__(self, setting, original_value, new_value): - #: The setting code given. Either one of :class:`SettingCodes - #: ` or ``int`` - #: - #: .. versionchanged:: 2.6.0 - self.setting = setting - - #: The original value before being changed. - self.original_value = original_value - - #: The new value after being changed. - self.new_value = new_value - - def __repr__(self): - return ( - "ChangedSetting(setting=%s, original_value=%s, " - "new_value=%s)" - ) % ( - self.setting, - self.original_value, - self.new_value - ) - - -class Settings(MutableMapping): - """ - An object that encapsulates HTTP/2 settings state. - - HTTP/2 Settings are a complex beast. Each party, remote and local, has its - own settings and a view of the other party's settings. When a settings - frame is emitted by a peer it cannot assume that the new settings values - are in place until the remote peer acknowledges the setting. In principle, - multiple settings changes can be "in flight" at the same time, all with - different values. - - This object encapsulates this mess. It provides a dict-like interface to - settings, which return the *current* values of the settings in question. - Additionally, it keeps track of the stack of proposed values: each time an - acknowledgement is sent/received, it updates the current values with the - stack of proposed values. On top of all that, it validates the values to - make sure they're allowed, and raises :class:`InvalidSettingsValueError - ` if they are not. - - Finally, this object understands what the default values of the HTTP/2 - settings are, and sets those defaults appropriately. - - .. versionchanged:: 2.2.0 - Added the ``initial_values`` parameter. - - .. versionchanged:: 2.5.0 - Added the ``max_header_list_size`` property. - - :param client: (optional) Whether these settings should be defaulted for a - client implementation or a server implementation. Defaults to ``True``. - :type client: ``bool`` - :param initial_values: (optional) Any initial values the user would like - set, rather than RFC 7540's defaults. - :type initial_vales: ``MutableMapping`` - """ - def __init__(self, client=True, initial_values=None): - # Backing object for the settings. This is a dictionary of - # (setting: [list of values]), where the first value in the list is the - # current value of the setting. Strictly this doesn't use lists but - # instead uses collections.deque to avoid repeated memory allocations. - # - # This contains the default values for HTTP/2. - self._settings = { - SettingCodes.HEADER_TABLE_SIZE: collections.deque([4096]), - SettingCodes.ENABLE_PUSH: collections.deque([int(client)]), - SettingCodes.INITIAL_WINDOW_SIZE: collections.deque([65535]), - SettingCodes.MAX_FRAME_SIZE: collections.deque([16384]), - SettingCodes.ENABLE_CONNECT_PROTOCOL: collections.deque([0]), - } - if initial_values is not None: - for key, value in initial_values.items(): - invalid = _validate_setting(key, value) - if invalid: - raise InvalidSettingsValueError( - "Setting %d has invalid value %d" % (key, value), - error_code=invalid - ) - self._settings[key] = collections.deque([value]) - - def acknowledge(self): - """ - The settings have been acknowledged, either by the user (remote - settings) or by the remote peer (local settings). - - :returns: A dict of {setting: ChangedSetting} that were applied. - """ - changed_settings = {} - - # If there is more than one setting in the list, we have a setting - # value outstanding. Update them. - for k, v in self._settings.items(): - if len(v) > 1: - old_setting = v.popleft() - new_setting = v[0] - changed_settings[k] = ChangedSetting( - k, old_setting, new_setting - ) - - return changed_settings - - # Provide easy-access to well known settings. - @property - def header_table_size(self): - """ - The current value of the :data:`HEADER_TABLE_SIZE - ` setting. - """ - return self[SettingCodes.HEADER_TABLE_SIZE] - - @header_table_size.setter - def header_table_size(self, value): - self[SettingCodes.HEADER_TABLE_SIZE] = value - - @property - def enable_push(self): - """ - The current value of the :data:`ENABLE_PUSH - ` setting. - """ - return self[SettingCodes.ENABLE_PUSH] - - @enable_push.setter - def enable_push(self, value): - self[SettingCodes.ENABLE_PUSH] = value - - @property - def initial_window_size(self): - """ - The current value of the :data:`INITIAL_WINDOW_SIZE - ` setting. - """ - return self[SettingCodes.INITIAL_WINDOW_SIZE] - - @initial_window_size.setter - def initial_window_size(self, value): - self[SettingCodes.INITIAL_WINDOW_SIZE] = value - - @property - def max_frame_size(self): - """ - The current value of the :data:`MAX_FRAME_SIZE - ` setting. - """ - return self[SettingCodes.MAX_FRAME_SIZE] - - @max_frame_size.setter - def max_frame_size(self, value): - self[SettingCodes.MAX_FRAME_SIZE] = value - - @property - def max_concurrent_streams(self): - """ - The current value of the :data:`MAX_CONCURRENT_STREAMS - ` setting. - """ - return self.get(SettingCodes.MAX_CONCURRENT_STREAMS, 2**32+1) - - @max_concurrent_streams.setter - def max_concurrent_streams(self, value): - self[SettingCodes.MAX_CONCURRENT_STREAMS] = value - - @property - def max_header_list_size(self): - """ - The current value of the :data:`MAX_HEADER_LIST_SIZE - ` setting. If not set, - returns ``None``, which means unlimited. - - .. versionadded:: 2.5.0 - """ - return self.get(SettingCodes.MAX_HEADER_LIST_SIZE, None) - - @max_header_list_size.setter - def max_header_list_size(self, value): - self[SettingCodes.MAX_HEADER_LIST_SIZE] = value - - @property - def enable_connect_protocol(self): - """ - The current value of the :data:`ENABLE_CONNECT_PROTOCOL - ` setting. - """ - return self[SettingCodes.ENABLE_CONNECT_PROTOCOL] - - @enable_connect_protocol.setter - def enable_connect_protocol(self, value): - self[SettingCodes.ENABLE_CONNECT_PROTOCOL] = value - - # Implement the MutableMapping API. - def __getitem__(self, key): - val = self._settings[key][0] - - # Things that were created when a setting was received should stay - # KeyError'd. - if val is None: - raise KeyError - - return val - - def __setitem__(self, key, value): - invalid = _validate_setting(key, value) - if invalid: - raise InvalidSettingsValueError( - "Setting %d has invalid value %d" % (key, value), - error_code=invalid - ) - - try: - items = self._settings[key] - except KeyError: - items = collections.deque([None]) - self._settings[key] = items - - items.append(value) - - def __delitem__(self, key): - del self._settings[key] - - def __iter__(self): - return self._settings.__iter__() - - def __len__(self): - return len(self._settings) - - def __eq__(self, other): - if isinstance(other, Settings): - return self._settings == other._settings - else: - return NotImplemented - - def __ne__(self, other): - if isinstance(other, Settings): - return not self == other - else: - return NotImplemented - - -def _validate_setting(setting, value): # noqa: C901 - """ - Confirms that a specific setting has a well-formed value. If the setting is - invalid, returns an error code. Otherwise, returns 0 (NO_ERROR). - """ - if setting == SettingCodes.ENABLE_PUSH: - if value not in (0, 1): - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.INITIAL_WINDOW_SIZE: - if not 0 <= value <= 2147483647: # 2^31 - 1 - return ErrorCodes.FLOW_CONTROL_ERROR - elif setting == SettingCodes.MAX_FRAME_SIZE: - if not 16384 <= value <= 16777215: # 2^14 and 2^24 - 1 - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.MAX_HEADER_LIST_SIZE: - if value < 0: - return ErrorCodes.PROTOCOL_ERROR - elif setting == SettingCodes.ENABLE_CONNECT_PROTOCOL: - if value not in (0, 1): - return ErrorCodes.PROTOCOL_ERROR - - return 0 diff --git a/py3.7/lib/python3.7/site-packages/h2/stream.py b/py3.7/lib/python3.7/site-packages/h2/stream.py deleted file mode 100644 index 827e65a..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/stream.py +++ /dev/null @@ -1,1403 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/stream -~~~~~~~~~ - -An implementation of a HTTP/2 stream. -""" -from enum import Enum, IntEnum -from hpack import HeaderTuple -from hyperframe.frame import ( - HeadersFrame, ContinuationFrame, DataFrame, WindowUpdateFrame, - RstStreamFrame, PushPromiseFrame, AltSvcFrame -) - -from .errors import ErrorCodes, _error_code_from_int -from .events import ( - RequestReceived, ResponseReceived, DataReceived, WindowUpdated, - StreamEnded, PushedStreamReceived, StreamReset, TrailersReceived, - InformationalResponseReceived, AlternativeServiceAvailable, - _ResponseSent, _RequestSent, _TrailersSent, _PushedRequestSent -) -from .exceptions import ( - ProtocolError, StreamClosedError, InvalidBodyLengthError, FlowControlError -) -from .utilities import ( - guard_increment_window, is_informational_response, authority_from_headers, - validate_headers, validate_outbound_headers, normalize_outbound_headers, - HeaderValidationFlags, extract_method_header, normalize_inbound_headers -) -from .windows import WindowManager - - -class StreamState(IntEnum): - IDLE = 0 - RESERVED_REMOTE = 1 - RESERVED_LOCAL = 2 - OPEN = 3 - HALF_CLOSED_REMOTE = 4 - HALF_CLOSED_LOCAL = 5 - CLOSED = 6 - - -class StreamInputs(Enum): - SEND_HEADERS = 0 - SEND_PUSH_PROMISE = 1 - SEND_RST_STREAM = 2 - SEND_DATA = 3 - SEND_WINDOW_UPDATE = 4 - SEND_END_STREAM = 5 - RECV_HEADERS = 6 - RECV_PUSH_PROMISE = 7 - RECV_RST_STREAM = 8 - RECV_DATA = 9 - RECV_WINDOW_UPDATE = 10 - RECV_END_STREAM = 11 - RECV_CONTINUATION = 12 # Added in 2.0.0 - SEND_INFORMATIONAL_HEADERS = 13 # Added in 2.2.0 - RECV_INFORMATIONAL_HEADERS = 14 # Added in 2.2.0 - SEND_ALTERNATIVE_SERVICE = 15 # Added in 2.3.0 - RECV_ALTERNATIVE_SERVICE = 16 # Added in 2.3.0 - UPGRADE_CLIENT = 17 # Added 2.3.0 - UPGRADE_SERVER = 18 # Added 2.3.0 - - -class StreamClosedBy(Enum): - SEND_END_STREAM = 0 - RECV_END_STREAM = 1 - SEND_RST_STREAM = 2 - RECV_RST_STREAM = 3 - - -# This array is initialized once, and is indexed by the stream states above. -# It indicates whether a stream in the given state is open. The reason we do -# this is that we potentially check whether a stream in a given state is open -# quite frequently: given that we check so often, we should do so in the -# fastest and most performant way possible. -STREAM_OPEN = [False for _ in range(0, len(StreamState))] -STREAM_OPEN[StreamState.OPEN] = True -STREAM_OPEN[StreamState.HALF_CLOSED_LOCAL] = True -STREAM_OPEN[StreamState.HALF_CLOSED_REMOTE] = True - - -class H2StreamStateMachine(object): - """ - A single HTTP/2 stream state machine. - - This stream object implements basically the state machine described in - RFC 7540 section 5.1. - - :param stream_id: The stream ID of this stream. This is stored primarily - for logging purposes. - """ - def __init__(self, stream_id): - self.state = StreamState.IDLE - self.stream_id = stream_id - - #: Whether this peer is the client side of this stream. - self.client = None - - # Whether trailers have been sent/received on this stream or not. - self.headers_sent = None - self.trailers_sent = None - self.headers_received = None - self.trailers_received = None - - # How the stream was closed. One of StreamClosedBy. - self.stream_closed_by = None - - def process_input(self, input_): - """ - Process a specific input in the state machine. - """ - if not isinstance(input_, StreamInputs): - raise ValueError("Input must be an instance of StreamInputs") - - try: - func, target_state = _transitions[(self.state, input_)] - except KeyError: - old_state = self.state - self.state = StreamState.CLOSED - raise ProtocolError( - "Invalid input %s in state %s" % (input_, old_state) - ) - else: - previous_state = self.state - self.state = target_state - if func is not None: - try: - return func(self, previous_state) - except ProtocolError: - self.state = StreamState.CLOSED - raise - except AssertionError as e: # pragma: no cover - self.state = StreamState.CLOSED - raise ProtocolError(e) - - return [] - - def request_sent(self, previous_state): - """ - Fires when a request is sent. - """ - self.client = True - self.headers_sent = True - event = _RequestSent() - - return [event] - - def response_sent(self, previous_state): - """ - Fires when something that should be a response is sent. This 'response' - may actually be trailers. - """ - if not self.headers_sent: - if self.client is True or self.client is None: - raise ProtocolError("Client cannot send responses.") - self.headers_sent = True - event = _ResponseSent() - else: - assert not self.trailers_sent - self.trailers_sent = True - event = _TrailersSent() - - return [event] - - def request_received(self, previous_state): - """ - Fires when a request is received. - """ - assert not self.headers_received - assert not self.trailers_received - - self.client = False - self.headers_received = True - event = RequestReceived() - - event.stream_id = self.stream_id - return [event] - - def response_received(self, previous_state): - """ - Fires when a response is received. Also disambiguates between responses - and trailers. - """ - if not self.headers_received: - assert self.client is True - self.headers_received = True - event = ResponseReceived() - else: - assert not self.trailers_received - self.trailers_received = True - event = TrailersReceived() - - event.stream_id = self.stream_id - return [event] - - def data_received(self, previous_state): - """ - Fires when data is received. - """ - event = DataReceived() - event.stream_id = self.stream_id - return [event] - - def window_updated(self, previous_state): - """ - Fires when a window update frame is received. - """ - event = WindowUpdated() - event.stream_id = self.stream_id - return [event] - - def stream_half_closed(self, previous_state): - """ - Fires when an END_STREAM flag is received in the OPEN state, - transitioning this stream to a HALF_CLOSED_REMOTE state. - """ - event = StreamEnded() - event.stream_id = self.stream_id - return [event] - - def stream_ended(self, previous_state): - """ - Fires when a stream is cleanly ended. - """ - self.stream_closed_by = StreamClosedBy.RECV_END_STREAM - event = StreamEnded() - event.stream_id = self.stream_id - return [event] - - def stream_reset(self, previous_state): - """ - Fired when a stream is forcefully reset. - """ - self.stream_closed_by = StreamClosedBy.RECV_RST_STREAM - event = StreamReset() - event.stream_id = self.stream_id - return [event] - - def send_new_pushed_stream(self, previous_state): - """ - Fires on the newly pushed stream, when pushed by the local peer. - - No event here, but definitionally this peer must be a server. - """ - assert self.client is None - self.client = False - self.headers_received = True - return [] - - def recv_new_pushed_stream(self, previous_state): - """ - Fires on the newly pushed stream, when pushed by the remote peer. - - No event here, but definitionally this peer must be a client. - """ - assert self.client is None - self.client = True - self.headers_sent = True - return [] - - def send_push_promise(self, previous_state): - """ - Fires on the already-existing stream when a PUSH_PROMISE frame is sent. - We may only send PUSH_PROMISE frames if we're a server. - """ - if self.client is True: - raise ProtocolError("Cannot push streams from client peers.") - - event = _PushedRequestSent() - return [event] - - def recv_push_promise(self, previous_state): - """ - Fires on the already-existing stream when a PUSH_PROMISE frame is - received. We may only receive PUSH_PROMISE frames if we're a client. - - Fires a PushedStreamReceived event. - """ - if not self.client: - if self.client is None: # pragma: no cover - msg = "Idle streams cannot receive pushes" - else: # pragma: no cover - msg = "Cannot receive pushed streams as a server" - raise ProtocolError(msg) - - event = PushedStreamReceived() - event.parent_stream_id = self.stream_id - return [event] - - def send_end_stream(self, previous_state): - """ - Called when an attempt is made to send END_STREAM in the - HALF_CLOSED_REMOTE state. - """ - self.stream_closed_by = StreamClosedBy.SEND_END_STREAM - - def send_reset_stream(self, previous_state): - """ - Called when an attempt is made to send RST_STREAM in a non-closed - stream state. - """ - self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM - - def reset_stream_on_error(self, previous_state): - """ - Called when we need to forcefully emit another RST_STREAM frame on - behalf of the state machine. - - If this is the first time we've done this, we should also hang an event - off the StreamClosedError so that the user can be informed. We know - it's the first time we've done this if the stream is currently in a - state other than CLOSED. - """ - self.stream_closed_by = StreamClosedBy.SEND_RST_STREAM - - error = StreamClosedError(self.stream_id) - - event = StreamReset() - event.stream_id = self.stream_id - event.error_code = ErrorCodes.STREAM_CLOSED - event.remote_reset = False - error._events = [event] - raise error - - def recv_on_closed_stream(self, previous_state): - """ - Called when an unexpected frame is received on an already-closed - stream. - - An endpoint that receives an unexpected frame should treat it as - a stream error or connection error with type STREAM_CLOSED, depending - on the specific frame. The error handling is done at a higher level: - this just raises the appropriate error. - """ - raise StreamClosedError(self.stream_id) - - def send_on_closed_stream(self, previous_state): - """ - Called when an attempt is made to send data on an already-closed - stream. - - This essentially overrides the standard logic by throwing a - more-specific error: StreamClosedError. This is a ProtocolError, so it - matches the standard API of the state machine, but provides more detail - to the user. - """ - raise StreamClosedError(self.stream_id) - - def recv_push_on_closed_stream(self, previous_state): - """ - Called when a PUSH_PROMISE frame is received on a full stop - stream. - - If the stream was closed by us sending a RST_STREAM frame, then we - presume that the PUSH_PROMISE was in flight when we reset the parent - stream. Rathen than accept the new stream, we just reset it. - Otherwise, we should call this a PROTOCOL_ERROR: pushing a stream on a - naturally closed stream is a real problem because it creates a brand - new stream that the remote peer now believes exists. - """ - assert self.stream_closed_by is not None - - if self.stream_closed_by == StreamClosedBy.SEND_RST_STREAM: - raise StreamClosedError(self.stream_id) - else: - raise ProtocolError("Attempted to push on closed stream.") - - def send_push_on_closed_stream(self, previous_state): - """ - Called when an attempt is made to push on an already-closed stream. - - This essentially overrides the standard logic by providing a more - useful error message. It's necessary because simply indicating that the - stream is closed is not enough: there is now a new stream that is not - allowed to be there. The only recourse is to tear the whole connection - down. - """ - raise ProtocolError("Attempted to push on closed stream.") - - def window_on_closed_stream(self, previous_state): - """ - Called when a WINDOW_UPDATE frame is received on an already-closed - stream. - - If we sent an END_STREAM frame, we just ignore the frame, as instructed - in RFC 7540 Section 5.1. Technically we should eventually consider - WINDOW_UPDATE in this state an error, but we don't have access to a - clock so we just always allow it. If we closed the stream for any other - reason, we behave as we do for receiving any other frame on a closed - stream. - """ - assert self.stream_closed_by is not None - - if self.stream_closed_by == StreamClosedBy.SEND_END_STREAM: - return [] - return self.recv_on_closed_stream(previous_state) - - def reset_on_closed_stream(self, previous_state): - """ - Called when a RST_STREAM frame is received on an already-closed stream. - - If we sent an END_STREAM frame, we just ignore the frame, as instructed - in RFC 7540 Section 5.1. Technically we should eventually consider - RST_STREAM in this state an error, but we don't have access to a clock - so we just always allow it. If we closed the stream for any other - reason, we behave as we do for receiving any other frame on a closed - stream. - """ - assert self.stream_closed_by is not None - - if self.stream_closed_by is StreamClosedBy.SEND_END_STREAM: - return [] - return self.recv_on_closed_stream(previous_state) - - def send_informational_response(self, previous_state): - """ - Called when an informational header block is sent (that is, a block - where the :status header has a 1XX value). - - Only enforces that these are sent *before* final headers are sent. - """ - if self.headers_sent: - raise ProtocolError("Information response after final response") - - event = _ResponseSent() - return [event] - - def recv_informational_response(self, previous_state): - """ - Called when an informational header block is received (that is, a block - where the :status header has a 1XX value). - """ - if self.headers_received: - raise ProtocolError("Informational response after final response") - - event = InformationalResponseReceived() - event.stream_id = self.stream_id - return [event] - - def recv_alt_svc(self, previous_state): - """ - Called when receiving an ALTSVC frame. - - RFC 7838 allows us to receive ALTSVC frames at any stream state, which - is really absurdly overzealous. For that reason, we want to limit the - states in which we can actually receive it. It's really only sensible - to receive it after we've sent our own headers and before the server - has sent its header block: the server can't guarantee that we have any - state around after it completes its header block, and the server - doesn't know what origin we're talking about before we've sent ours. - - For that reason, this function applies a few extra checks on both state - and some of the little state variables we keep around. If those suggest - an unreasonable situation for the ALTSVC frame to have been sent in, - we quietly ignore it (as RFC 7838 suggests). - - This function is also *not* always called by the state machine. In some - states (IDLE, RESERVED_LOCAL, CLOSED) we don't bother to call it, - because we know the frame cannot be valid in that state (IDLE because - the server cannot know what origin the stream applies to, CLOSED - because the server cannot assume we still have state around, - RESERVED_LOCAL because by definition if we're in the RESERVED_LOCAL - state then *we* are the server). - """ - # Servers can't receive ALTSVC frames, but RFC 7838 tells us to ignore - # them. - if self.client is False: - return [] - - # If we've received the response headers from the server they can't - # guarantee we still have any state around. Other implementations - # (like nghttp2) ignore ALTSVC in this state, so we will too. - if self.headers_received: - return [] - - # Otherwise, this is a sensible enough frame to have received. Return - # the event and let it get populated. - return [AlternativeServiceAvailable()] - - def send_alt_svc(self, previous_state): - """ - Called when sending an ALTSVC frame on this stream. - - For consistency with the restrictions we apply on receiving ALTSVC - frames in ``recv_alt_svc``, we want to restrict when users can send - ALTSVC frames to the situations when we ourselves would accept them. - - That means: when we are a server, when we have received the request - headers, and when we have not yet sent our own response headers. - """ - # We should not send ALTSVC after we've sent response headers, as the - # client may have disposed of its state. - if self.headers_sent: - raise ProtocolError( - "Cannot send ALTSVC after sending response headers." - ) - - return - - -# STATE MACHINE -# -# The stream state machine is defined here to avoid the need to allocate it -# repeatedly for each stream. It cannot be defined in the stream class because -# it needs to be able to reference the callbacks defined on the class, but -# because Python's scoping rules are weird the class object is not actually in -# scope during the body of the class object. -# -# For the sake of clarity, we reproduce the RFC 7540 state machine here: -# -# +--------+ -# send PP | | recv PP -# ,--------| idle |--------. -# / | | \ -# v +--------+ v -# +----------+ | +----------+ -# | | | send H / | | -# ,------| reserved | | recv H | reserved |------. -# | | (local) | | | (remote) | | -# | +----------+ v +----------+ | -# | | +--------+ | | -# | | recv ES | | send ES | | -# | send H | ,-------| open |-------. | recv H | -# | | / | | \ | | -# | v v +--------+ v v | -# | +----------+ | +----------+ | -# | | half | | | half | | -# | | closed | | send R / | closed | | -# | | (remote) | | recv R | (local) | | -# | +----------+ | +----------+ | -# | | | | | -# | | send ES / | recv ES / | | -# | | send R / v send R / | | -# | | recv R +--------+ recv R | | -# | send R / `----------->| |<-----------' send R / | -# | recv R | closed | recv R | -# `----------------------->| |<----------------------' -# +--------+ -# -# send: endpoint sends this frame -# recv: endpoint receives this frame -# -# H: HEADERS frame (with implied CONTINUATIONs) -# PP: PUSH_PROMISE frame (with implied CONTINUATIONs) -# ES: END_STREAM flag -# R: RST_STREAM frame -# -# For the purposes of this state machine we treat HEADERS and their -# associated CONTINUATION frames as a single jumbo frame. The protocol -# allows/requires this by preventing other frames from being interleved in -# between HEADERS/CONTINUATION frames. However, if a CONTINUATION frame is -# received without a prior HEADERS frame, it *will* be passed to this state -# machine. The state machine should always reject that frame, either as an -# invalid transition or because the stream is closed. -# -# There is a confusing relationship around PUSH_PROMISE frames. The state -# machine above considers them to be frames belonging to the new stream, -# which is *somewhat* true. However, they are sent with the stream ID of -# their related stream, and are only sendable in some cases. -# For this reason, our state machine implementation below allows for -# PUSH_PROMISE frames both in the IDLE state (as in the diagram), but also -# in the OPEN, HALF_CLOSED_LOCAL, and HALF_CLOSED_REMOTE states. -# Essentially, for hyper-h2, PUSH_PROMISE frames are effectively sent on -# two streams. -# -# The _transitions dictionary contains a mapping of tuples of -# (state, input) to tuples of (side_effect_function, end_state). This -# map contains all allowed transitions: anything not in this map is -# invalid and immediately causes a transition to ``closed``. -_transitions = { - # State: idle - (StreamState.IDLE, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.request_sent, StreamState.OPEN), - (StreamState.IDLE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.request_received, StreamState.OPEN), - (StreamState.IDLE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.IDLE, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_new_pushed_stream, - StreamState.RESERVED_LOCAL), - (StreamState.IDLE, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_new_pushed_stream, - StreamState.RESERVED_REMOTE), - (StreamState.IDLE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.IDLE), - (StreamState.IDLE, StreamInputs.UPGRADE_CLIENT): - (H2StreamStateMachine.request_sent, StreamState.HALF_CLOSED_LOCAL), - (StreamState.IDLE, StreamInputs.UPGRADE_SERVER): - (H2StreamStateMachine.request_received, - StreamState.HALF_CLOSED_REMOTE), - - # State: reserved local - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.HALF_CLOSED_REMOTE), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.RESERVED_LOCAL, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.RESERVED_LOCAL), - (StreamState.RESERVED_LOCAL, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.RESERVED_LOCAL), - - # State: reserved remote - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.RESERVED_REMOTE), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.RESERVED_REMOTE), - (StreamState.RESERVED_REMOTE, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.RESERVED_REMOTE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.RESERVED_REMOTE), - - # State: open - (StreamState.OPEN, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_DATA): - (None, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_DATA): - (H2StreamStateMachine.data_received, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_END_STREAM): - (None, StreamState.HALF_CLOSED_LOCAL), - (StreamState.OPEN, StreamInputs.RECV_END_STREAM): - (H2StreamStateMachine.stream_half_closed, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.OPEN, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.OPEN, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.OPEN, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_promise, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_promise, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.send_informational_response, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.recv_informational_response, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.OPEN), - (StreamState.OPEN, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.OPEN), - - # State: half-closed remote - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.response_sent, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_DATA): - (None, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_DATA): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_END_STREAM): - (H2StreamStateMachine.send_end_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_promise, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.reset_stream_on_error, StreamState.CLOSED), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.send_informational_response, - StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.HALF_CLOSED_REMOTE), - (StreamState.HALF_CLOSED_REMOTE, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.HALF_CLOSED_REMOTE), - - # State: half-closed local - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.response_received, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_DATA): - (H2StreamStateMachine.data_received, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_END_STREAM): - (H2StreamStateMachine.stream_ended, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_WINDOW_UPDATE): - (None, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_updated, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_reset_stream, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.stream_reset, StreamState.CLOSED), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_promise, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_INFORMATIONAL_HEADERS): - (H2StreamStateMachine.recv_informational_response, - StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.SEND_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.send_alt_svc, StreamState.HALF_CLOSED_LOCAL), - (StreamState.HALF_CLOSED_LOCAL, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (H2StreamStateMachine.recv_alt_svc, StreamState.HALF_CLOSED_LOCAL), - - # State: closed - (StreamState.CLOSED, StreamInputs.RECV_END_STREAM): - (None, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_ALTERNATIVE_SERVICE): - (None, StreamState.CLOSED), - - # RFC 7540 Section 5.1 defines how the end point should react when - # receiving a frame on a closed stream with the following statements: - # - # > An endpoint that receives any frame other than PRIORITY after receiving - # > a RST_STREAM MUST treat that as a stream error of type STREAM_CLOSED. - # > An endpoint that receives any frames after receiving a frame with the - # > END_STREAM flag set MUST treat that as a connection error of type - # > STREAM_CLOSED. - (StreamState.CLOSED, StreamInputs.RECV_HEADERS): - (H2StreamStateMachine.recv_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_DATA): - (H2StreamStateMachine.recv_on_closed_stream, StreamState.CLOSED), - - # > WINDOW_UPDATE or RST_STREAM frames can be received in this state - # > for a short period after a DATA or HEADERS frame containing a - # > END_STREAM flag is sent. - (StreamState.CLOSED, StreamInputs.RECV_WINDOW_UPDATE): - (H2StreamStateMachine.window_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.RECV_RST_STREAM): - (H2StreamStateMachine.reset_on_closed_stream, StreamState.CLOSED), - - # > A receiver MUST treat the receipt of a PUSH_PROMISE on a stream that is - # > neither "open" nor "half-closed (local)" as a connection error of type - # > PROTOCOL_ERROR. - (StreamState.CLOSED, StreamInputs.RECV_PUSH_PROMISE): - (H2StreamStateMachine.recv_push_on_closed_stream, StreamState.CLOSED), - - # Also, users should be forbidden from sending on closed streams. - (StreamState.CLOSED, StreamInputs.SEND_HEADERS): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_PUSH_PROMISE): - (H2StreamStateMachine.send_push_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_RST_STREAM): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_DATA): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_WINDOW_UPDATE): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), - (StreamState.CLOSED, StreamInputs.SEND_END_STREAM): - (H2StreamStateMachine.send_on_closed_stream, StreamState.CLOSED), -} - - -class H2Stream(object): - """ - A low-level HTTP/2 stream object. This handles building and receiving - frames and maintains per-stream state. - - This wraps a HTTP/2 Stream state machine implementation, ensuring that - frames can only be sent/received when the stream is in a valid state. - Attempts to create frames that cannot be sent will raise a - ``ProtocolError``. - """ - def __init__(self, - stream_id, - config, - inbound_window_size, - outbound_window_size): - self.state_machine = H2StreamStateMachine(stream_id) - self.stream_id = stream_id - self.max_outbound_frame_size = None - self.request_method = None - - # The current value of the outbound stream flow control window - self.outbound_flow_control_window = outbound_window_size - - # The flow control manager. - self._inbound_window_manager = WindowManager(inbound_window_size) - - # The expected content length, if any. - self._expected_content_length = None - - # The actual received content length. Always tracked. - self._actual_content_length = 0 - - # The authority we believe this stream belongs to. - self._authority = None - - # The configuration for this stream. - self.config = config - - def __repr__(self): - return "<%s id:%d state:%r>" % ( - type(self).__name__, - self.stream_id, - self.state_machine.state - ) - - @property - def inbound_flow_control_window(self): - """ - The size of the inbound flow control window for the stream. This is - rarely publicly useful: instead, use :meth:`remote_flow_control_window - `. This shortcut is - largely present to provide a shortcut to this data. - """ - return self._inbound_window_manager.current_window_size - - @property - def open(self): - """ - Whether the stream is 'open' in any sense: that is, whether it counts - against the number of concurrent streams. - """ - # RFC 7540 Section 5.1.2 defines 'open' for this purpose to mean either - # the OPEN state or either of the HALF_CLOSED states. Perplexingly, - # this excludes the reserved states. - # For more detail on why we're doing this in this slightly weird way, - # see the comment on ``STREAM_OPEN`` at the top of the file. - return STREAM_OPEN[self.state_machine.state] - - @property - def closed(self): - """ - Whether the stream is closed. - """ - return self.state_machine.state == StreamState.CLOSED - - @property - def closed_by(self): - """ - Returns how the stream was closed, as one of StreamClosedBy. - """ - return self.state_machine.stream_closed_by - - def upgrade(self, client_side): - """ - Called by the connection to indicate that this stream is the initial - request/response of an upgraded connection. Places the stream into an - appropriate state. - """ - self.config.logger.debug("Upgrading %r", self) - - assert self.stream_id == 1 - input_ = ( - StreamInputs.UPGRADE_CLIENT if client_side - else StreamInputs.UPGRADE_SERVER - ) - - # This may return events, we deliberately don't want them. - self.state_machine.process_input(input_) - return - - def send_headers(self, headers, encoder, end_stream=False): - """ - Returns a list of HEADERS/CONTINUATION frames to emit as either headers - or trailers. - """ - self.config.logger.debug("Send headers %s on %r", headers, self) - - # Because encoding headers makes an irreversible change to the header - # compression context, we make the state transition before we encode - # them. - - # First, check if we're a client. If we are, no problem: if we aren't, - # we need to scan the header block to see if this is an informational - # response. - input_ = StreamInputs.SEND_HEADERS - if ((not self.state_machine.client) and - is_informational_response(headers)): - if end_stream: - raise ProtocolError( - "Cannot set END_STREAM on informational responses." - ) - - input_ = StreamInputs.SEND_INFORMATIONAL_HEADERS - - events = self.state_machine.process_input(input_) - - hf = HeadersFrame(self.stream_id) - hdr_validation_flags = self._build_hdr_validation_flags(events) - frames = self._build_headers_frames( - headers, encoder, hf, hdr_validation_flags - ) - - if end_stream: - # Not a bug: the END_STREAM flag is valid on the initial HEADERS - # frame, not the CONTINUATION frames that follow. - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - frames[0].flags.add('END_STREAM') - - if self.state_machine.trailers_sent and not end_stream: - raise ProtocolError("Trailers must have END_STREAM set.") - - if self.state_machine.client and self._authority is None: - self._authority = authority_from_headers(headers) - - # store request method for _initialize_content_length - self.request_method = extract_method_header(headers) - - return frames - - def push_stream_in_band(self, related_stream_id, headers, encoder): - """ - Returns a list of PUSH_PROMISE/CONTINUATION frames to emit as a pushed - stream header. Called on the stream that has the PUSH_PROMISE frame - sent on it. - """ - self.config.logger.debug("Push stream %r", self) - - # Because encoding headers makes an irreversible change to the header - # compression context, we make the state transition *first*. - - events = self.state_machine.process_input( - StreamInputs.SEND_PUSH_PROMISE - ) - - ppf = PushPromiseFrame(self.stream_id) - ppf.promised_stream_id = related_stream_id - hdr_validation_flags = self._build_hdr_validation_flags(events) - frames = self._build_headers_frames( - headers, encoder, ppf, hdr_validation_flags - ) - - return frames - - def locally_pushed(self): - """ - Mark this stream as one that was pushed by this peer. Must be called - immediately after initialization. Sends no frames, simply updates the - state machine. - """ - # This does not trigger any events. - events = self.state_machine.process_input( - StreamInputs.SEND_PUSH_PROMISE - ) - assert not events - return [] - - def send_data(self, data, end_stream=False, pad_length=None): - """ - Prepare some data frames. Optionally end the stream. - - .. warning:: Does not perform flow control checks. - """ - self.config.logger.debug( - "Send data on %r with end stream set to %s", self, end_stream - ) - - self.state_machine.process_input(StreamInputs.SEND_DATA) - - df = DataFrame(self.stream_id) - df.data = data - if end_stream: - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - df.flags.add('END_STREAM') - if pad_length is not None: - df.flags.add('PADDED') - df.pad_length = pad_length - - # Subtract flow_controlled_length to account for possible padding - self.outbound_flow_control_window -= df.flow_controlled_length - assert self.outbound_flow_control_window >= 0 - - return [df] - - def end_stream(self): - """ - End a stream without sending data. - """ - self.config.logger.debug("End stream %r", self) - - self.state_machine.process_input(StreamInputs.SEND_END_STREAM) - df = DataFrame(self.stream_id) - df.flags.add('END_STREAM') - return [df] - - def advertise_alternative_service(self, field_value): - """ - Advertise an RFC 7838 alternative service. The semantics of this are - better documented in the ``H2Connection`` class. - """ - self.config.logger.debug( - "Advertise alternative service of %r for %r", field_value, self - ) - self.state_machine.process_input(StreamInputs.SEND_ALTERNATIVE_SERVICE) - asf = AltSvcFrame(self.stream_id) - asf.field = field_value - return [asf] - - def increase_flow_control_window(self, increment): - """ - Increase the size of the flow control window for the remote side. - """ - self.config.logger.debug( - "Increase flow control window for %r by %d", - self, increment - ) - self.state_machine.process_input(StreamInputs.SEND_WINDOW_UPDATE) - self._inbound_window_manager.window_opened(increment) - - wuf = WindowUpdateFrame(self.stream_id) - wuf.window_increment = increment - return [wuf] - - def receive_push_promise_in_band(self, - promised_stream_id, - headers, - header_encoding): - """ - Receives a push promise frame sent on this stream, pushing a remote - stream. This is called on the stream that has the PUSH_PROMISE sent - on it. - """ - self.config.logger.debug( - "Receive Push Promise on %r for remote stream %d", - self, promised_stream_id - ) - events = self.state_machine.process_input( - StreamInputs.RECV_PUSH_PROMISE - ) - events[0].pushed_stream_id = promised_stream_id - - hdr_validation_flags = self._build_hdr_validation_flags(events) - events[0].headers = self._process_received_headers( - headers, hdr_validation_flags, header_encoding - ) - return [], events - - def remotely_pushed(self, pushed_headers): - """ - Mark this stream as one that was pushed by the remote peer. Must be - called immediately after initialization. Sends no frames, simply - updates the state machine. - """ - self.config.logger.debug("%r pushed by remote peer", self) - events = self.state_machine.process_input( - StreamInputs.RECV_PUSH_PROMISE - ) - self._authority = authority_from_headers(pushed_headers) - return [], events - - def receive_headers(self, headers, end_stream, header_encoding): - """ - Receive a set of headers (or trailers). - """ - if is_informational_response(headers): - if end_stream: - raise ProtocolError( - "Cannot set END_STREAM on informational responses" - ) - input_ = StreamInputs.RECV_INFORMATIONAL_HEADERS - else: - input_ = StreamInputs.RECV_HEADERS - - events = self.state_machine.process_input(input_) - - if end_stream: - es_events = self.state_machine.process_input( - StreamInputs.RECV_END_STREAM - ) - events[0].stream_ended = es_events[0] - events += es_events - - self._initialize_content_length(headers) - - if isinstance(events[0], TrailersReceived): - if not end_stream: - raise ProtocolError("Trailers must have END_STREAM set") - - hdr_validation_flags = self._build_hdr_validation_flags(events) - events[0].headers = self._process_received_headers( - headers, hdr_validation_flags, header_encoding - ) - return [], events - - def receive_data(self, data, end_stream, flow_control_len): - """ - Receive some data. - """ - self.config.logger.debug( - "Receive data on %r with end stream %s and flow control length " - "set to %d", self, end_stream, flow_control_len - ) - events = self.state_machine.process_input(StreamInputs.RECV_DATA) - self._inbound_window_manager.window_consumed(flow_control_len) - self._track_content_length(len(data), end_stream) - - if end_stream: - es_events = self.state_machine.process_input( - StreamInputs.RECV_END_STREAM - ) - events[0].stream_ended = es_events[0] - events.extend(es_events) - - events[0].data = data - events[0].flow_controlled_length = flow_control_len - return [], events - - def receive_window_update(self, increment): - """ - Handle a WINDOW_UPDATE increment. - """ - self.config.logger.debug( - "Receive Window Update on %r for increment of %d", - self, increment - ) - events = self.state_machine.process_input( - StreamInputs.RECV_WINDOW_UPDATE - ) - frames = [] - - # If we encounter a problem with incrementing the flow control window, - # this should be treated as a *stream* error, not a *connection* error. - # That means we need to catch the error and forcibly close the stream. - if events: - events[0].delta = increment - try: - self.outbound_flow_control_window = guard_increment_window( - self.outbound_flow_control_window, - increment - ) - except FlowControlError: - # Ok, this is bad. We're going to need to perform a local - # reset. - event = StreamReset() - event.stream_id = self.stream_id - event.error_code = ErrorCodes.FLOW_CONTROL_ERROR - event.remote_reset = False - - events = [event] - frames = self.reset_stream(event.error_code) - - return frames, events - - def receive_continuation(self): - """ - A naked CONTINUATION frame has been received. This is always an error, - but the type of error it is depends on the state of the stream and must - transition the state of the stream, so we need to handle it. - """ - self.config.logger.debug("Receive Continuation frame on %r", self) - self.state_machine.process_input( - StreamInputs.RECV_CONTINUATION - ) - assert False, "Should not be reachable" - - def receive_alt_svc(self, frame): - """ - An Alternative Service frame was received on the stream. This frame - inherits the origin associated with this stream. - """ - self.config.logger.debug( - "Receive Alternative Service frame on stream %r", self - ) - - # If the origin is present, RFC 7838 says we have to ignore it. - if frame.origin: - return [], [] - - events = self.state_machine.process_input( - StreamInputs.RECV_ALTERNATIVE_SERVICE - ) - - # There are lots of situations where we want to ignore the ALTSVC - # frame. If we need to pay attention, we'll have an event and should - # fill it out. - if events: - assert isinstance(events[0], AlternativeServiceAvailable) - events[0].origin = self._authority - events[0].field_value = frame.field - - return [], events - - def reset_stream(self, error_code=0): - """ - Close the stream locally. Reset the stream with an error code. - """ - self.config.logger.debug( - "Local reset %r with error code: %d", self, error_code - ) - self.state_machine.process_input(StreamInputs.SEND_RST_STREAM) - - rsf = RstStreamFrame(self.stream_id) - rsf.error_code = error_code - return [rsf] - - def stream_reset(self, frame): - """ - Handle a stream being reset remotely. - """ - self.config.logger.debug( - "Remote reset %r with error code: %d", self, frame.error_code - ) - events = self.state_machine.process_input(StreamInputs.RECV_RST_STREAM) - - if events: - # We don't fire an event if this stream is already closed. - events[0].error_code = _error_code_from_int(frame.error_code) - - return [], events - - def acknowledge_received_data(self, acknowledged_size): - """ - The user has informed us that they've processed some amount of data - that was received on this stream. Pass that to the window manager and - potentially return some WindowUpdate frames. - """ - self.config.logger.debug( - "Acknowledge received data with size %d on %r", - acknowledged_size, self - ) - increment = self._inbound_window_manager.process_bytes( - acknowledged_size - ) - if increment: - f = WindowUpdateFrame(self.stream_id) - f.window_increment = increment - return [f] - - return [] - - def _build_hdr_validation_flags(self, events): - """ - Constructs a set of header validation flags for use when normalizing - and validating header blocks. - """ - is_trailer = isinstance( - events[0], (_TrailersSent, TrailersReceived) - ) - is_response_header = isinstance( - events[0], - ( - _ResponseSent, - ResponseReceived, - InformationalResponseReceived - ) - ) - is_push_promise = isinstance( - events[0], (PushedStreamReceived, _PushedRequestSent) - ) - - return HeaderValidationFlags( - is_client=self.state_machine.client, - is_trailer=is_trailer, - is_response_header=is_response_header, - is_push_promise=is_push_promise, - ) - - def _build_headers_frames(self, - headers, - encoder, - first_frame, - hdr_validation_flags): - """ - Helper method to build headers or push promise frames. - """ - # We need to lowercase the header names, and to ensure that secure - # header fields are kept out of compression contexts. - if self.config.normalize_outbound_headers: - headers = normalize_outbound_headers( - headers, hdr_validation_flags - ) - if self.config.validate_outbound_headers: - headers = validate_outbound_headers( - headers, hdr_validation_flags - ) - - encoded_headers = encoder.encode(headers) - - # Slice into blocks of max_outbound_frame_size. Be careful with this: - # it only works right because we never send padded frames or priority - # information on the frames. Revisit this if we do. - header_blocks = [ - encoded_headers[i:i+self.max_outbound_frame_size] - for i in range( - 0, len(encoded_headers), self.max_outbound_frame_size - ) - ] - - frames = [] - first_frame.data = header_blocks[0] - frames.append(first_frame) - - for block in header_blocks[1:]: - cf = ContinuationFrame(self.stream_id) - cf.data = block - frames.append(cf) - - frames[-1].flags.add('END_HEADERS') - return frames - - def _process_received_headers(self, - headers, - header_validation_flags, - header_encoding): - """ - When headers have been received from the remote peer, run a processing - pipeline on them to transform them into the appropriate form for - attaching to an event. - """ - if self.config.normalize_inbound_headers: - headers = normalize_inbound_headers( - headers, header_validation_flags - ) - - if self.config.validate_inbound_headers: - headers = validate_headers(headers, header_validation_flags) - - if header_encoding: - headers = _decode_headers(headers, header_encoding) - - # The above steps are all generators, so we need to concretize the - # headers now. - return list(headers) - - def _initialize_content_length(self, headers): - """ - Checks the headers for a content-length header and initializes the - _expected_content_length field from it. It's not an error for no - Content-Length header to be present. - """ - if self.request_method == b'HEAD': - self._expected_content_length = 0 - return - - for n, v in headers: - if n == b'content-length': - try: - self._expected_content_length = int(v, 10) - except ValueError: - raise ProtocolError( - "Invalid content-length header: %s" % v - ) - - return - - def _track_content_length(self, length, end_stream): - """ - Update the expected content length in response to data being received. - Validates that the appropriate amount of data is sent. Always updates - the received data, but only validates the length against the - content-length header if one was sent. - - :param length: The length of the body chunk received. - :param end_stream: If this is the last body chunk received. - """ - self._actual_content_length += length - actual = self._actual_content_length - expected = self._expected_content_length - - if expected is not None: - if expected < actual: - raise InvalidBodyLengthError(expected, actual) - - if end_stream and expected != actual: - raise InvalidBodyLengthError(expected, actual) - - def _inbound_flow_control_change_from_settings(self, delta): - """ - We changed SETTINGS_INITIAL_WINDOW_SIZE, which means we need to - update the target window size for flow control. For our flow control - strategy, this means we need to do two things: we need to adjust the - current window size, but we also need to set the target maximum window - size to the new value. - """ - new_max_size = self._inbound_window_manager.max_window_size + delta - self._inbound_window_manager.window_opened(delta) - self._inbound_window_manager.max_window_size = new_max_size - - -def _decode_headers(headers, encoding): - """ - Given an iterable of header two-tuples and an encoding, decodes those - headers using that encoding while preserving the type of the header tuple. - This ensures that the use of ``HeaderTuple`` is preserved. - """ - for header in headers: - # This function expects to work on decoded headers, which are always - # HeaderTuple objects. - assert isinstance(header, HeaderTuple) - - name, value = header - name = name.decode(encoding) - value = value.decode(encoding) - yield header.__class__(name, value) diff --git a/py3.7/lib/python3.7/site-packages/h2/utilities.py b/py3.7/lib/python3.7/site-packages/h2/utilities.py deleted file mode 100644 index 06c916e..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/utilities.py +++ /dev/null @@ -1,660 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/utilities -~~~~~~~~~~~~ - -Utility functions that do not belong in a separate module. -""" -import collections -import re -from string import whitespace -import sys - -from hpack import HeaderTuple, NeverIndexedHeaderTuple - -from .exceptions import ProtocolError, FlowControlError - -UPPER_RE = re.compile(b"[A-Z]") - -# A set of headers that are hop-by-hop or connection-specific and thus -# forbidden in HTTP/2. This list comes from RFC 7540 § 8.1.2.2. -CONNECTION_HEADERS = frozenset([ - b'connection', u'connection', - b'proxy-connection', u'proxy-connection', - b'keep-alive', u'keep-alive', - b'transfer-encoding', u'transfer-encoding', - b'upgrade', u'upgrade', -]) - - -_ALLOWED_PSEUDO_HEADER_FIELDS = frozenset([ - b':method', u':method', - b':scheme', u':scheme', - b':authority', u':authority', - b':path', u':path', - b':status', u':status', - b':protocol', u':protocol', -]) - - -_SECURE_HEADERS = frozenset([ - # May have basic credentials which are vulnerable to dictionary attacks. - b'authorization', u'authorization', - b'proxy-authorization', u'proxy-authorization', -]) - - -_REQUEST_ONLY_HEADERS = frozenset([ - b':scheme', u':scheme', - b':path', u':path', - b':authority', u':authority', - b':method', u':method', - b':protocol', u':protocol', -]) - - -_RESPONSE_ONLY_HEADERS = frozenset([b':status', u':status']) - - -# A Set of pseudo headers that are only valid if the method is -# CONNECT, see RFC 8441 § 5 -_CONNECT_REQUEST_ONLY_HEADERS = frozenset([b':protocol', u':protocol']) - - -if sys.version_info[0] == 2: # Python 2.X - _WHITESPACE = frozenset(whitespace) -else: # Python 3.3+ - _WHITESPACE = frozenset(map(ord, whitespace)) - - -def _secure_headers(headers, hdr_validation_flags): - """ - Certain headers are at risk of being attacked during the header compression - phase, and so need to be kept out of header compression contexts. This - function automatically transforms certain specific headers into HPACK - never-indexed fields to ensure they don't get added to header compression - contexts. - - This function currently implements two rules: - - - 'authorization' and 'proxy-authorization' fields are automatically made - never-indexed. - - Any 'cookie' header field shorter than 20 bytes long is made - never-indexed. - - These fields are the most at-risk. These rules are inspired by Firefox - and nghttp2. - """ - for header in headers: - if header[0] in _SECURE_HEADERS: - yield NeverIndexedHeaderTuple(*header) - elif header[0] in (b'cookie', u'cookie') and len(header[1]) < 20: - yield NeverIndexedHeaderTuple(*header) - else: - yield header - - -def extract_method_header(headers): - """ - Extracts the request method from the headers list. - """ - for k, v in headers: - if k in (b':method', u':method'): - if not isinstance(v, bytes): - return v.encode('utf-8') - else: - return v - - -def is_informational_response(headers): - """ - Searches a header block for a :status header to confirm that a given - collection of headers are an informational response. Assumes the header - block is well formed: that is, that the HTTP/2 special headers are first - in the block, and so that it can stop looking when it finds the first - header field whose name does not begin with a colon. - - :param headers: The HTTP/2 header block. - :returns: A boolean indicating if this is an informational response. - """ - for n, v in headers: - if isinstance(n, bytes): - sigil = b':' - status = b':status' - informational_start = b'1' - else: - sigil = u':' - status = u':status' - informational_start = u'1' - - # If we find a non-special header, we're done here: stop looping. - if not n.startswith(sigil): - return False - - # This isn't the status header, bail. - if n != status: - continue - - # If the first digit is a 1, we've got informational headers. - return v.startswith(informational_start) - - -def guard_increment_window(current, increment): - """ - Increments a flow control window, guarding against that window becoming too - large. - - :param current: The current value of the flow control window. - :param increment: The increment to apply to that window. - :returns: The new value of the window. - :raises: ``FlowControlError`` - """ - # The largest value the flow control window may take. - LARGEST_FLOW_CONTROL_WINDOW = 2**31 - 1 - - new_size = current + increment - - if new_size > LARGEST_FLOW_CONTROL_WINDOW: - raise FlowControlError( - "May not increment flow control window past %d" % - LARGEST_FLOW_CONTROL_WINDOW - ) - - return new_size - - -def authority_from_headers(headers): - """ - Given a header set, searches for the authority header and returns the - value. - - Note that this doesn't terminate early, so should only be called if the - headers are for a client request. Otherwise, will loop over the entire - header set, which is potentially unwise. - - :param headers: The HTTP header set. - :returns: The value of the authority header, or ``None``. - :rtype: ``bytes`` or ``None``. - """ - for n, v in headers: - # This gets run against headers that come both from HPACK and from the - # user, so we may have unicode floating around in here. We only want - # bytes. - if n in (b':authority', u':authority'): - return v.encode('utf-8') if not isinstance(v, bytes) else v - - return None - - -# Flags used by the validate_headers pipeline to determine which checks -# should be applied to a given set of headers. -HeaderValidationFlags = collections.namedtuple( - 'HeaderValidationFlags', - ['is_client', 'is_trailer', 'is_response_header', 'is_push_promise'] -) - - -def validate_headers(headers, hdr_validation_flags): - """ - Validates a header sequence against a set of constraints from RFC 7540. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - """ - # This validation logic is built on a sequence of generators that are - # iterated over to provide the final header list. This reduces some of the - # overhead of doing this checking. However, it's worth noting that this - # checking remains somewhat expensive, and attempts should be made wherever - # possible to reduce the time spent doing them. - # - # For example, we avoid tuple upacking in loops because it represents a - # fixed cost that we don't want to spend, instead indexing into the header - # tuples. - headers = _reject_uppercase_header_fields( - headers, hdr_validation_flags - ) - headers = _reject_surrounding_whitespace( - headers, hdr_validation_flags - ) - headers = _reject_te( - headers, hdr_validation_flags - ) - headers = _reject_connection_header( - headers, hdr_validation_flags - ) - headers = _reject_pseudo_header_fields( - headers, hdr_validation_flags - ) - headers = _check_host_authority_header( - headers, hdr_validation_flags - ) - headers = _check_path_header(headers, hdr_validation_flags) - - return headers - - -def _reject_uppercase_header_fields(headers, hdr_validation_flags): - """ - Raises a ProtocolError if any uppercase character is found in a header - block. - """ - for header in headers: - if UPPER_RE.search(header[0]): - raise ProtocolError( - "Received uppercase header name %s." % header[0]) - yield header - - -def _reject_surrounding_whitespace(headers, hdr_validation_flags): - """ - Raises a ProtocolError if any header name or value is surrounded by - whitespace characters. - """ - # For compatibility with RFC 7230 header fields, we need to allow the field - # value to be an empty string. This is ludicrous, but technically allowed. - # The field name may not be empty, though, so we can safely assume that it - # must have at least one character in it and throw exceptions if it - # doesn't. - for header in headers: - if header[0][0] in _WHITESPACE or header[0][-1] in _WHITESPACE: - raise ProtocolError( - "Received header name surrounded by whitespace %r" % header[0]) - if header[1] and ((header[1][0] in _WHITESPACE) or - (header[1][-1] in _WHITESPACE)): - raise ProtocolError( - "Received header value surrounded by whitespace %r" % header[1] - ) - yield header - - -def _reject_te(headers, hdr_validation_flags): - """ - Raises a ProtocolError if the TE header is present in a header block and - its value is anything other than "trailers". - """ - for header in headers: - if header[0] in (b'te', u'te'): - if header[1].lower() not in (b'trailers', u'trailers'): - raise ProtocolError( - "Invalid value for Transfer-Encoding header: %s" % - header[1] - ) - - yield header - - -def _reject_connection_header(headers, hdr_validation_flags): - """ - Raises a ProtocolError if the Connection header is present in a header - block. - """ - for header in headers: - if header[0] in CONNECTION_HEADERS: - raise ProtocolError( - "Connection-specific header field present: %s." % header[0] - ) - - yield header - - -def _custom_startswith(test_string, bytes_prefix, unicode_prefix): - """ - Given a string that might be a bytestring or a Unicode string, - return True if it starts with the appropriate prefix. - """ - if isinstance(test_string, bytes): - return test_string.startswith(bytes_prefix) - else: - return test_string.startswith(unicode_prefix) - - -def _assert_header_in_set(string_header, bytes_header, header_set): - """ - Given a set of header names, checks whether the string or byte version of - the header name is present. Raises a Protocol error with the appropriate - error if it's missing. - """ - if not (string_header in header_set or bytes_header in header_set): - raise ProtocolError( - "Header block missing mandatory %s header" % string_header - ) - - -def _reject_pseudo_header_fields(headers, hdr_validation_flags): - """ - Raises a ProtocolError if duplicate pseudo-header fields are found in a - header block or if a pseudo-header field appears in a block after an - ordinary header field. - - Raises a ProtocolError if pseudo-header fields are found in trailers. - """ - seen_pseudo_header_fields = set() - seen_regular_header = False - method = None - - for header in headers: - if _custom_startswith(header[0], b':', u':'): - if header[0] in seen_pseudo_header_fields: - raise ProtocolError( - "Received duplicate pseudo-header field %s" % header[0] - ) - - seen_pseudo_header_fields.add(header[0]) - - if seen_regular_header: - raise ProtocolError( - "Received pseudo-header field out of sequence: %s" % - header[0] - ) - - if header[0] not in _ALLOWED_PSEUDO_HEADER_FIELDS: - raise ProtocolError( - "Received custom pseudo-header field %s" % header[0] - ) - - if header[0] in (b':method', u':method'): - if not isinstance(header[1], bytes): - method = header[1].encode('utf-8') - else: - method = header[1] - - else: - seen_regular_header = True - - yield header - - # Check the pseudo-headers we got to confirm they're acceptable. - _check_pseudo_header_field_acceptability( - seen_pseudo_header_fields, method, hdr_validation_flags - ) - - -def _check_pseudo_header_field_acceptability(pseudo_headers, - method, - hdr_validation_flags): - """ - Given the set of pseudo-headers present in a header block and the - validation flags, confirms that RFC 7540 allows them. - """ - # Pseudo-header fields MUST NOT appear in trailers - RFC 7540 § 8.1.2.1 - if hdr_validation_flags.is_trailer and pseudo_headers: - raise ProtocolError( - "Received pseudo-header in trailer %s" % pseudo_headers - ) - - # If ':status' pseudo-header is not there in a response header, reject it. - # Similarly, if ':path', ':method', or ':scheme' are not there in a request - # header, reject it. Additionally, if a response contains any request-only - # headers or vice-versa, reject it. - # Relevant RFC section: RFC 7540 § 8.1.2.4 - # https://tools.ietf.org/html/rfc7540#section-8.1.2.4 - if hdr_validation_flags.is_response_header: - _assert_header_in_set(u':status', b':status', pseudo_headers) - invalid_response_headers = pseudo_headers & _REQUEST_ONLY_HEADERS - if invalid_response_headers: - raise ProtocolError( - "Encountered request-only headers %s" % - invalid_response_headers - ) - elif (not hdr_validation_flags.is_response_header and - not hdr_validation_flags.is_trailer): - # This is a request, so we need to have seen :path, :method, and - # :scheme. - _assert_header_in_set(u':path', b':path', pseudo_headers) - _assert_header_in_set(u':method', b':method', pseudo_headers) - _assert_header_in_set(u':scheme', b':scheme', pseudo_headers) - invalid_request_headers = pseudo_headers & _RESPONSE_ONLY_HEADERS - if invalid_request_headers: - raise ProtocolError( - "Encountered response-only headers %s" % - invalid_request_headers - ) - if method != b'CONNECT': - invalid_headers = pseudo_headers & _CONNECT_REQUEST_ONLY_HEADERS - if invalid_headers: - raise ProtocolError( - "Encountered connect-request-only headers %s" % - invalid_headers - ) - - -def _validate_host_authority_header(headers): - """ - Given the :authority and Host headers from a request block that isn't - a trailer, check that: - 1. At least one of these headers is set. - 2. If both headers are set, they match. - - :param headers: The HTTP header set. - :raises: ``ProtocolError`` - """ - # We use None as a sentinel value. Iterate over the list of headers, - # and record the value of these headers (if present). We don't need - # to worry about receiving duplicate :authority headers, as this is - # enforced by the _reject_pseudo_header_fields() pipeline. - # - # TODO: We should also guard against receiving duplicate Host headers, - # and against sending duplicate headers. - authority_header_val = None - host_header_val = None - - for header in headers: - if header[0] in (b':authority', u':authority'): - authority_header_val = header[1] - elif header[0] in (b'host', u'host'): - host_header_val = header[1] - - yield header - - # If we have not-None values for these variables, then we know we saw - # the corresponding header. - authority_present = (authority_header_val is not None) - host_present = (host_header_val is not None) - - # It is an error for a request header block to contain neither - # an :authority header nor a Host header. - if not authority_present and not host_present: - raise ProtocolError( - "Request header block does not have an :authority or Host header." - ) - - # If we receive both headers, they should definitely match. - if authority_present and host_present: - if authority_header_val != host_header_val: - raise ProtocolError( - "Request header block has mismatched :authority and " - "Host headers: %r / %r" - % (authority_header_val, host_header_val) - ) - - -def _check_host_authority_header(headers, hdr_validation_flags): - """ - Raises a ProtocolError if a header block arrives that does not contain an - :authority or a Host header, or if a header block contains both fields, - but their values do not match. - """ - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return headers - - return _validate_host_authority_header(headers) - - -def _check_path_header(headers, hdr_validation_flags): - """ - Raise a ProtocolError if a header block arrives or is sent that contains an - empty :path header. - """ - def inner(): - for header in headers: - if header[0] in (b':path', u':path'): - if not header[1]: - raise ProtocolError("An empty :path header is forbidden") - - yield header - - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return headers - else: - return inner() - - -def _lowercase_header_names(headers, hdr_validation_flags): - """ - Given an iterable of header two-tuples, rebuilds that iterable with the - header names lowercased. This generator produces tuples that preserve the - original type of the header tuple for tuple and any ``HeaderTuple``. - """ - for header in headers: - if isinstance(header, HeaderTuple): - yield header.__class__(header[0].lower(), header[1]) - else: - yield (header[0].lower(), header[1]) - - -def _strip_surrounding_whitespace(headers, hdr_validation_flags): - """ - Given an iterable of header two-tuples, strip both leading and trailing - whitespace from both header names and header values. This generator - produces tuples that preserve the original type of the header tuple for - tuple and any ``HeaderTuple``. - """ - for header in headers: - if isinstance(header, HeaderTuple): - yield header.__class__(header[0].strip(), header[1].strip()) - else: - yield (header[0].strip(), header[1].strip()) - - -def _strip_connection_headers(headers, hdr_validation_flags): - """ - Strip any connection headers as per RFC7540 § 8.1.2.2. - """ - for header in headers: - if header[0] not in CONNECTION_HEADERS: - yield header - - -def _check_sent_host_authority_header(headers, hdr_validation_flags): - """ - Raises an InvalidHeaderBlockError if we try to send a header block - that does not contain an :authority or a Host header, or if - the header block contains both fields, but their values do not match. - """ - # We only expect to see :authority and Host headers on request header - # blocks that aren't trailers, so skip this validation if this is a - # response header or we're looking at trailer blocks. - skip_validation = ( - hdr_validation_flags.is_response_header or - hdr_validation_flags.is_trailer - ) - if skip_validation: - return headers - - return _validate_host_authority_header(headers) - - -def _combine_cookie_fields(headers, hdr_validation_flags): - """ - RFC 7540 § 8.1.2.5 allows HTTP/2 clients to split the Cookie header field, - which must normally appear only once, into multiple fields for better - compression. However, they MUST be joined back up again when received. - This normalization step applies that transform. The side-effect is that - all cookie fields now appear *last* in the header block. - """ - # There is a problem here about header indexing. Specifically, it's - # possible that all these cookies are sent with different header indexing - # values. At this point it shouldn't matter too much, so we apply our own - # logic and make them never-indexed. - cookies = [] - for header in headers: - if header[0] == b'cookie': - cookies.append(header[1]) - else: - yield header - if cookies: - cookie_val = b'; '.join(cookies) - yield NeverIndexedHeaderTuple(b'cookie', cookie_val) - - -def normalize_outbound_headers(headers, hdr_validation_flags): - """ - Normalizes a header sequence that we are about to send. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - """ - headers = _lowercase_header_names(headers, hdr_validation_flags) - headers = _strip_surrounding_whitespace(headers, hdr_validation_flags) - headers = _strip_connection_headers(headers, hdr_validation_flags) - headers = _secure_headers(headers, hdr_validation_flags) - - return headers - - -def normalize_inbound_headers(headers, hdr_validation_flags): - """ - Normalizes a header sequence that we have received. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags - """ - headers = _combine_cookie_fields(headers, hdr_validation_flags) - return headers - - -def validate_outbound_headers(headers, hdr_validation_flags): - """ - Validates and normalizes a header sequence that we are about to send. - - :param headers: The HTTP header set. - :param hdr_validation_flags: An instance of HeaderValidationFlags. - """ - headers = _reject_te( - headers, hdr_validation_flags - ) - headers = _reject_connection_header( - headers, hdr_validation_flags - ) - headers = _reject_pseudo_header_fields( - headers, hdr_validation_flags - ) - headers = _check_sent_host_authority_header( - headers, hdr_validation_flags - ) - headers = _check_path_header(headers, hdr_validation_flags) - - return headers - - -class SizeLimitDict(collections.OrderedDict): - - def __init__(self, *args, **kwargs): - self._size_limit = kwargs.pop("size_limit", None) - super(SizeLimitDict, self).__init__(*args, **kwargs) - - self._check_size_limit() - - def __setitem__(self, key, value): - super(SizeLimitDict, self).__setitem__(key, value) - - self._check_size_limit() - - def _check_size_limit(self): - if self._size_limit is not None: - while len(self) > self._size_limit: - self.popitem(last=False) diff --git a/py3.7/lib/python3.7/site-packages/h2/windows.py b/py3.7/lib/python3.7/site-packages/h2/windows.py deleted file mode 100644 index 6656975..0000000 --- a/py3.7/lib/python3.7/site-packages/h2/windows.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- -""" -h2/windows -~~~~~~~~~~ - -Defines tools for managing HTTP/2 flow control windows. - -The objects defined in this module are used to automatically manage HTTP/2 -flow control windows. Specifically, they keep track of what the size of the -window is, how much data has been consumed from that window, and how much data -the user has already used. It then implements a basic algorithm that attempts -to manage the flow control window without user input, trying to ensure that it -does not emit too many WINDOW_UPDATE frames. -""" -from __future__ import division - -from .exceptions import FlowControlError - - -# The largest acceptable value for a HTTP/2 flow control window. -LARGEST_FLOW_CONTROL_WINDOW = 2**31 - 1 - - -class WindowManager(object): - """ - A basic HTTP/2 window manager. - - :param max_window_size: The maximum size of the flow control window. - :type max_window_size: ``int`` - """ - def __init__(self, max_window_size): - assert max_window_size <= LARGEST_FLOW_CONTROL_WINDOW - self.max_window_size = max_window_size - self.current_window_size = max_window_size - self._bytes_processed = 0 - - def window_consumed(self, size): - """ - We have received a certain number of bytes from the remote peer. This - necessarily shrinks the flow control window! - - :param size: The number of flow controlled bytes we received from the - remote peer. - :type size: ``int`` - :returns: Nothing. - :rtype: ``None`` - """ - self.current_window_size -= size - if self.current_window_size < 0: - raise FlowControlError("Flow control window shrunk below 0") - - def window_opened(self, size): - """ - The flow control window has been incremented, either because of manual - flow control management or because of the user changing the flow - control settings. This can have the effect of increasing what we - consider to be the "maximum" flow control window size. - - This does not increase our view of how many bytes have been processed, - only of how much space is in the window. - - :param size: The increment to the flow control window we received. - :type size: ``int`` - :returns: Nothing - :rtype: ``None`` - """ - self.current_window_size += size - - if self.current_window_size > LARGEST_FLOW_CONTROL_WINDOW: - raise FlowControlError( - "Flow control window mustn't exceed %d" % - LARGEST_FLOW_CONTROL_WINDOW - ) - - if self.current_window_size > self.max_window_size: - self.max_window_size = self.current_window_size - - def process_bytes(self, size): - """ - The application has informed us that it has processed a certain number - of bytes. This may cause us to want to emit a window update frame. If - we do want to emit a window update frame, this method will return the - number of bytes that we should increment the window by. - - :param size: The number of flow controlled bytes that the application - has processed. - :type size: ``int`` - :returns: The number of bytes to increment the flow control window by, - or ``None``. - :rtype: ``int`` or ``None`` - """ - self._bytes_processed += size - return self._maybe_update_window() - - def _maybe_update_window(self): - """ - Run the algorithm. - - Our current algorithm can be described like this. - - 1. If no bytes have been processed, we immediately return 0. There is - no meaningful way for us to hand space in the window back to the - remote peer, so let's not even try. - 2. If there is no space in the flow control window, and we have - processed at least 1024 bytes (or 1/4 of the window, if the window - is smaller), we will emit a window update frame. This is to avoid - the risk of blocking a stream altogether. - 3. If there is space in the flow control window, and we have processed - at least 1/2 of the window worth of bytes, we will emit a window - update frame. This is to minimise the number of window update frames - we have to emit. - - In a healthy system with large flow control windows, this will - irregularly emit WINDOW_UPDATE frames. This prevents us starving the - connection by emitting eleventy bajillion WINDOW_UPDATE frames, - especially in situations where the remote peer is sending a lot of very - small DATA frames. - """ - # TODO: Can the window be smaller than 1024 bytes? If not, we can - # streamline this algorithm. - if not self._bytes_processed: - return None - - max_increment = (self.max_window_size - self.current_window_size) - increment = 0 - - # Note that, even though we may increment less than _bytes_processed, - # we still want to set it to zero whenever we emit an increment. This - # is because we'll always increment up to the maximum we can. - if (self.current_window_size == 0) and ( - self._bytes_processed > min(1024, self.max_window_size // 4)): - increment = min(self._bytes_processed, max_increment) - self._bytes_processed = 0 - elif self._bytes_processed >= (self.max_window_size // 2): - increment = min(self._bytes_processed, max_increment) - self._bytes_processed = 0 - - self.current_window_size += increment - return increment diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/DESCRIPTION.rst b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/DESCRIPTION.rst deleted file mode 100644 index c7e95d8..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/DESCRIPTION.rst +++ /dev/null @@ -1,179 +0,0 @@ -======================================== -hpack: HTTP/2 Header Encoding for Python -======================================== - -.. image:: https://raw.github.com/Lukasa/hyper/development/docs/source/images/hyper.png - -.. image:: https://travis-ci.org/python-hyper/hpack.png?branch=master - :target: https://travis-ci.org/python-hyper/hpack - -This module contains a pure-Python HTTP/2 header encoding (HPACK) logic for use -in Python programs that implement HTTP/2. It also contains a compatibility -layer that automatically enables the use of ``nghttp2`` if it's available. - -Documentation -============= - -Documentation is available at http://python-hyper.org/hpack/. - -Contributing -============ - -``hpack`` welcomes contributions from anyone! Unlike many other projects we are -happy to accept cosmetic contributions and small contributions, in addition to -large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://hyper.readthedocs.org/en/development/contributing.html - -License -======= - -``hpack`` is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -``hpack`` is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. - - -Release History -=============== - -3.0.0 (2017-03-29) ------------------- - -**API Changes (Backward Incompatible)** - -- Removed nghttp2 support. This support had rotted and was essentially - non-functional, so it has now been removed until someone has time to re-add - the support in a functional form. -- Attempts by the encoder to exceed the maximum allowed header table size via - dynamic table size updates (or the absence thereof) are now forbidden. - -**API Changes (Backward Compatible)** - -- Added a new ``InvalidTableSizeError`` thrown when the encoder does not - respect the maximum table size set by the user. -- Added a ``Decoder.max_allowed_table_size`` field that sets the maximum - allowed size of the decoder header table. See the documentation for an - indication of how this should be used. - -**Bugfixes** - -- Up to 25% performance improvement decoding HPACK-packed integers, depending - on the platform. -- HPACK now tolerates receiving multiple header table size changes in sequence, - rather than only one. -- HPACK now forbids header table size changes anywhere but first in a header - block, as required by RFC 7541 § 4.2. -- Other miscellaneous performance improvements. - -2.3.0 (2016-08-04) ------------------- - -**Security Fixes** - -- CVE-2016-6581: HPACK Bomb. This release now enforces a maximum value of the - decompressed size of the header list. This is to avoid the so-called "HPACK - Bomb" vulnerability, which is caused when a malicious peer sends a compressed - HPACK body that decompresses to a gigantic header list size. - - This also adds a ``OversizedHeaderListError``, which is thrown by the - ``decode`` method if the maximum header list size is being violated. This - places the HPACK decoder into a broken state: it must not be used after this - exception is thrown. - - This also adds a ``max_header_list_size`` to the ``Decoder`` object. This - controls the maximum allowable decompressed size of the header list. By - default this is set to 64kB. - -2.2.0 (2016-04-20) ------------------- - -**API Changes (Backward Compatible)** - -- Added ``HeaderTuple`` and ``NeverIndexedHeaderTuple`` classes that signal - whether a given header field may ever be indexed in HTTP/2 header - compression. -- Changed ``Decoder.decode()`` to return the newly added ``HeaderTuple`` class - and subclass. These objects behave like two-tuples, so this change does not - break working code. - -**Bugfixes** - -- Improve Huffman decoding speed by 4x using an approach borrowed from nghttp2. -- Improve HPACK decoding speed by 10% by caching header table sizes. - -2.1.1 (2016-03-16) ------------------- - -**Bugfixes** - -- When passing a dictionary or dictionary subclass to ``Encoder.encode``, HPACK - now ensures that HTTP/2 special headers (headers whose names begin with - ``:`` characters) appear first in the header block. - -2.1.0 (2016-02-02) ------------------- - -**API Changes (Backward Compatible)** - -- Added new ``InvalidTableIndex`` exception, a subclass of - ``HPACKDecodingError``. -- Instead of throwing ``IndexError`` when encountering invalid encoded integers - HPACK now throws ``HPACKDecodingError``. -- Instead of throwing ``UnicodeDecodeError`` when encountering headers that are - not UTF-8 encoded, HPACK now throws ``HPACKDecodingError``. -- Instead of throwing ``IndexError`` when encountering invalid table offsets, - HPACK now throws ``InvalidTableIndex``. -- Added ``raw`` flag to ``decode``, allowing ``decode`` to return bytes instead - of attempting to decode the headers as UTF-8. - -**Bugfixes** - -- ``memoryview`` objects are now used when decoding HPACK, improving the - performance by avoiding unnecessary data copies. - -2.0.1 (2015-11-09) ------------------- - -- Fixed a bug where the Python HPACK implementation would only emit header - table size changes for the total change between one header block and another, - rather than for the entire sequence of changes. - -2.0.0 (2015-10-12) ------------------- - -- Remove unused ``HPACKEncodingError``. -- Add the shortcut ability to import the public API (``Encoder``, ``Decoder``, - ``HPACKError``, ``HPACKDecodingError``) directly, rather than from - ``hpack.hpack``. - -1.1.0 (2015-07-07) ------------------- - -- Add support for emitting 'never indexed' header fields, by using an optional - third element in the header tuple. With thanks to @jimcarreer! - -1.0.1 (2015-04-19) ------------------- - -- Header fields that have names matching header table entries are now added to - the header table. This improves compression efficiency at the cost of - slightly more table operations. With thanks to `Tatsuhiro Tsujikawa`_. - -.. _Tatsuhiro Tsujikawa: https://github.com/tatsuhiro-t - -1.0.0 (2015-04-13) ------------------- - -- Initial fork of the code from `hyper`_. - -.. _hyper: https://hyper.readthedocs.org/ - - diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/METADATA deleted file mode 100644 index 8c818b7..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/METADATA +++ /dev/null @@ -1,201 +0,0 @@ -Metadata-Version: 2.0 -Name: hpack -Version: 3.0.0 -Summary: Pure-Python HPACK header compression -Home-page: http://hyper.rtfd.org -Author: Cory Benfield -Author-email: cory@lukasa.co.uk -License: MIT License -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython - -======================================== -hpack: HTTP/2 Header Encoding for Python -======================================== - -.. image:: https://raw.github.com/Lukasa/hyper/development/docs/source/images/hyper.png - -.. image:: https://travis-ci.org/python-hyper/hpack.png?branch=master - :target: https://travis-ci.org/python-hyper/hpack - -This module contains a pure-Python HTTP/2 header encoding (HPACK) logic for use -in Python programs that implement HTTP/2. It also contains a compatibility -layer that automatically enables the use of ``nghttp2`` if it's available. - -Documentation -============= - -Documentation is available at http://python-hyper.org/hpack/. - -Contributing -============ - -``hpack`` welcomes contributions from anyone! Unlike many other projects we are -happy to accept cosmetic contributions and small contributions, in addition to -large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://hyper.readthedocs.org/en/development/contributing.html - -License -======= - -``hpack`` is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -``hpack`` is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. - - -Release History -=============== - -3.0.0 (2017-03-29) ------------------- - -**API Changes (Backward Incompatible)** - -- Removed nghttp2 support. This support had rotted and was essentially - non-functional, so it has now been removed until someone has time to re-add - the support in a functional form. -- Attempts by the encoder to exceed the maximum allowed header table size via - dynamic table size updates (or the absence thereof) are now forbidden. - -**API Changes (Backward Compatible)** - -- Added a new ``InvalidTableSizeError`` thrown when the encoder does not - respect the maximum table size set by the user. -- Added a ``Decoder.max_allowed_table_size`` field that sets the maximum - allowed size of the decoder header table. See the documentation for an - indication of how this should be used. - -**Bugfixes** - -- Up to 25% performance improvement decoding HPACK-packed integers, depending - on the platform. -- HPACK now tolerates receiving multiple header table size changes in sequence, - rather than only one. -- HPACK now forbids header table size changes anywhere but first in a header - block, as required by RFC 7541 § 4.2. -- Other miscellaneous performance improvements. - -2.3.0 (2016-08-04) ------------------- - -**Security Fixes** - -- CVE-2016-6581: HPACK Bomb. This release now enforces a maximum value of the - decompressed size of the header list. This is to avoid the so-called "HPACK - Bomb" vulnerability, which is caused when a malicious peer sends a compressed - HPACK body that decompresses to a gigantic header list size. - - This also adds a ``OversizedHeaderListError``, which is thrown by the - ``decode`` method if the maximum header list size is being violated. This - places the HPACK decoder into a broken state: it must not be used after this - exception is thrown. - - This also adds a ``max_header_list_size`` to the ``Decoder`` object. This - controls the maximum allowable decompressed size of the header list. By - default this is set to 64kB. - -2.2.0 (2016-04-20) ------------------- - -**API Changes (Backward Compatible)** - -- Added ``HeaderTuple`` and ``NeverIndexedHeaderTuple`` classes that signal - whether a given header field may ever be indexed in HTTP/2 header - compression. -- Changed ``Decoder.decode()`` to return the newly added ``HeaderTuple`` class - and subclass. These objects behave like two-tuples, so this change does not - break working code. - -**Bugfixes** - -- Improve Huffman decoding speed by 4x using an approach borrowed from nghttp2. -- Improve HPACK decoding speed by 10% by caching header table sizes. - -2.1.1 (2016-03-16) ------------------- - -**Bugfixes** - -- When passing a dictionary or dictionary subclass to ``Encoder.encode``, HPACK - now ensures that HTTP/2 special headers (headers whose names begin with - ``:`` characters) appear first in the header block. - -2.1.0 (2016-02-02) ------------------- - -**API Changes (Backward Compatible)** - -- Added new ``InvalidTableIndex`` exception, a subclass of - ``HPACKDecodingError``. -- Instead of throwing ``IndexError`` when encountering invalid encoded integers - HPACK now throws ``HPACKDecodingError``. -- Instead of throwing ``UnicodeDecodeError`` when encountering headers that are - not UTF-8 encoded, HPACK now throws ``HPACKDecodingError``. -- Instead of throwing ``IndexError`` when encountering invalid table offsets, - HPACK now throws ``InvalidTableIndex``. -- Added ``raw`` flag to ``decode``, allowing ``decode`` to return bytes instead - of attempting to decode the headers as UTF-8. - -**Bugfixes** - -- ``memoryview`` objects are now used when decoding HPACK, improving the - performance by avoiding unnecessary data copies. - -2.0.1 (2015-11-09) ------------------- - -- Fixed a bug where the Python HPACK implementation would only emit header - table size changes for the total change between one header block and another, - rather than for the entire sequence of changes. - -2.0.0 (2015-10-12) ------------------- - -- Remove unused ``HPACKEncodingError``. -- Add the shortcut ability to import the public API (``Encoder``, ``Decoder``, - ``HPACKError``, ``HPACKDecodingError``) directly, rather than from - ``hpack.hpack``. - -1.1.0 (2015-07-07) ------------------- - -- Add support for emitting 'never indexed' header fields, by using an optional - third element in the header tuple. With thanks to @jimcarreer! - -1.0.1 (2015-04-19) ------------------- - -- Header fields that have names matching header table entries are now added to - the header table. This improves compression efficiency at the cost of - slightly more table operations. With thanks to `Tatsuhiro Tsujikawa`_. - -.. _Tatsuhiro Tsujikawa: https://github.com/tatsuhiro-t - -1.0.0 (2015-04-13) ------------------- - -- Initial fork of the code from `hyper`_. - -.. _hyper: https://hyper.readthedocs.org/ - - diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/RECORD deleted file mode 100644 index 719e8bb..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/RECORD +++ /dev/null @@ -1,27 +0,0 @@ -hpack/__init__.py,sha256=Pt27T8qdtME8DpY-_rI0I_oBO670OCt_hymhJlBlc0Y,479 -hpack/compat.py,sha256=gIyA_FOrzA3wKPXpLqJcKU-iffSwGXdJzuQUN3AN5v4,679 -hpack/exceptions.py,sha256=Rrw1Fke5Cfq72OwvwrnS6JucBvw3_bxu3o_ujtAUlrM,974 -hpack/hpack.py,sha256=NTATROnUHErtssiSR08bMgV62ehc7uNvFPnKrJi5NGw,22772 -hpack/hpack_compat.py,sha256=fS9caWAND4k_g8ciXqDpvJunczssnvYAAFIHmGr8qzc,3596 -hpack/huffman.py,sha256=nOOZTGpOXGkwbrWPkYaHNt00RVeyQeN-Lf2SKsi96x4,2521 -hpack/huffman_constants.py,sha256=4szhXrK1EEXNMKZzbSUgrG8S07Vc3ALwj7QpwLTtNh0,4628 -hpack/huffman_table.py,sha256=5yijIuaylIePwkbhWMXKf3EXspeXKY7hakpvPdSRJkg,168580 -hpack/struct.py,sha256=rMfEqhtp6KTOZ0pk33iXTFVfuhVwEUO-XZjrsQMDZ5I,1052 -hpack/table.py,sha256=6cITVnI5X-x4wxu8uA0dp9kkMck8kDFAOUupDGy0Su8,8950 -hpack-3.0.0.dist-info/DESCRIPTION.rst,sha256=a3KmUrtMvB6_oOCsF-WO51EgKWNAu5JwhHb-cO2YQr8,6161 -hpack-3.0.0.dist-info/METADATA,sha256=v0XmuzSPr5PaSa65ecn0yq_jDNz83rTBgcS3CKcaEAo,6995 -hpack-3.0.0.dist-info/RECORD,, -hpack-3.0.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110 -hpack-3.0.0.dist-info/metadata.json,sha256=cHIa1A8fQfSGOPOb9YqdHEYzRVN1yqSmczK-UyefhJk,929 -hpack-3.0.0.dist-info/top_level.txt,sha256=nyrZLbQo-0nC6ot3YO_109pkUiTtK1M0wUJfLHuQceE,6 -hpack-3.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hpack/__pycache__/struct.cpython-37.pyc,, -hpack/__pycache__/__init__.cpython-37.pyc,, -hpack/__pycache__/exceptions.cpython-37.pyc,, -hpack/__pycache__/hpack_compat.cpython-37.pyc,, -hpack/__pycache__/huffman_constants.cpython-37.pyc,, -hpack/__pycache__/compat.cpython-37.pyc,, -hpack/__pycache__/huffman_table.cpython-37.pyc,, -hpack/__pycache__/table.cpython-37.pyc,, -hpack/__pycache__/hpack.cpython-37.pyc,, -hpack/__pycache__/huffman.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/WHEEL deleted file mode 100644 index 8b6dd1b..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.29.0) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/metadata.json b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/metadata.json deleted file mode 100644 index 022bcb6..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython"], "extensions": {"python.details": {"contacts": [{"email": "cory@lukasa.co.uk", "name": "Cory Benfield", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://hyper.rtfd.org"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT License", "metadata_version": "2.0", "name": "hpack", "summary": "Pure-Python HPACK header compression", "version": "3.0.0"} \ No newline at end of file diff --git a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/top_level.txt deleted file mode 100644 index 1a0ac48..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack-3.0.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hpack diff --git a/py3.7/lib/python3.7/site-packages/hpack/__init__.py b/py3.7/lib/python3.7/site-packages/hpack/__init__.py deleted file mode 100644 index 22edde2..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack -~~~~~ - -HTTP/2 header encoding for Python. -""" -from .hpack import Encoder, Decoder -from .struct import HeaderTuple, NeverIndexedHeaderTuple -from .exceptions import ( - HPACKError, HPACKDecodingError, InvalidTableIndex, OversizedHeaderListError -) - -__all__ = [ - 'Encoder', 'Decoder', 'HPACKError', 'HPACKDecodingError', - 'InvalidTableIndex', 'HeaderTuple', 'NeverIndexedHeaderTuple', - 'OversizedHeaderListError' -] - -__version__ = '3.0.0' diff --git a/py3.7/lib/python3.7/site-packages/hpack/compat.py b/py3.7/lib/python3.7/site-packages/hpack/compat.py deleted file mode 100644 index 4fcaad4..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/compat.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/compat -~~~~~~~~~~~~ - -Normalizes the Python 2/3 API for internal use. -""" -import sys - - -_ver = sys.version_info -is_py2 = _ver[0] == 2 -is_py3 = _ver[0] == 3 - -if is_py2: - def to_byte(char): - return ord(char) - - def decode_hex(b): - return b.decode('hex') - - def to_bytes(b): - if isinstance(b, memoryview): - return b.tobytes() - else: - return bytes(b) - - unicode = unicode # noqa - bytes = str - -elif is_py3: - def to_byte(char): - return char - - def decode_hex(b): - return bytes.fromhex(b) - - def to_bytes(b): - return bytes(b) - - unicode = str - bytes = bytes diff --git a/py3.7/lib/python3.7/site-packages/hpack/exceptions.py b/py3.7/lib/python3.7/site-packages/hpack/exceptions.py deleted file mode 100644 index 571ba98..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/exceptions.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hyper/http20/exceptions -~~~~~~~~~~~~~~~~~~~~~~~ - -This defines exceptions used in the HTTP/2 portion of hyper. -""" - - -class HPACKError(Exception): - """ - The base class for all ``hpack`` exceptions. - """ - pass - - -class HPACKDecodingError(HPACKError): - """ - An error has been encountered while performing HPACK decoding. - """ - pass - - -class InvalidTableIndex(HPACKDecodingError): - """ - An invalid table index was received. - """ - pass - - -class OversizedHeaderListError(HPACKDecodingError): - """ - A header list that was larger than we allow has been received. This may be - a DoS attack. - - .. versionadded:: 2.3.0 - """ - pass - - -class InvalidTableSizeError(HPACKDecodingError): - """ - An attempt was made to change the decoder table size to a value larger than - allowed, or the list was shrunk and the remote peer didn't shrink their - table size. - - .. versionadded:: 3.0.0 - """ - pass diff --git a/py3.7/lib/python3.7/site-packages/hpack/hpack.py b/py3.7/lib/python3.7/site-packages/hpack/hpack.py deleted file mode 100644 index 57e8c7f..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/hpack.py +++ /dev/null @@ -1,630 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/hpack -~~~~~~~~~~~ - -Implements the HPACK header compression algorithm as detailed by the IETF. -""" -import logging - -from .table import HeaderTable, table_entry_size -from .compat import to_byte, to_bytes -from .exceptions import ( - HPACKDecodingError, OversizedHeaderListError, InvalidTableSizeError -) -from .huffman import HuffmanEncoder -from .huffman_constants import ( - REQUEST_CODES, REQUEST_CODES_LENGTH -) -from .huffman_table import decode_huffman -from .struct import HeaderTuple, NeverIndexedHeaderTuple - -log = logging.getLogger(__name__) - -INDEX_NONE = b'\x00' -INDEX_NEVER = b'\x10' -INDEX_INCREMENTAL = b'\x40' - -# Precompute 2^i for 1-8 for use in prefix calcs. -# Zero index is not used but there to save a subtraction -# as prefix numbers are not zero indexed. -_PREFIX_BIT_MAX_NUMBERS = [(2 ** i) - 1 for i in range(9)] - -try: # pragma: no cover - basestring = basestring -except NameError: # pragma: no cover - basestring = (str, bytes) - - -# We default the maximum header list we're willing to accept to 64kB. That's a -# lot of headers, but if applications want to raise it they can do. -DEFAULT_MAX_HEADER_LIST_SIZE = 2 ** 16 - - -def _unicode_if_needed(header, raw): - """ - Provides a header as a unicode string if raw is False, otherwise returns - it as a bytestring. - """ - name = to_bytes(header[0]) - value = to_bytes(header[1]) - if not raw: - name = name.decode('utf-8') - value = value.decode('utf-8') - return header.__class__(name, value) - - -def encode_integer(integer, prefix_bits): - """ - This encodes an integer according to the wacky integer encoding rules - defined in the HPACK spec. - """ - log.debug("Encoding %d with %d bits", integer, prefix_bits) - - if integer < 0: - raise ValueError( - "Can only encode positive integers, got %s" % integer - ) - - if prefix_bits < 1 or prefix_bits > 8: - raise ValueError( - "Prefix bits must be between 1 and 8, got %s" % prefix_bits - ) - - max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits] - - if integer < max_number: - return bytearray([integer]) # Seriously? - else: - elements = [max_number] - integer -= max_number - - while integer >= 128: - elements.append((integer & 127) + 128) - integer >>= 7 - - elements.append(integer) - - return bytearray(elements) - - -def decode_integer(data, prefix_bits): - """ - This decodes an integer according to the wacky integer encoding rules - defined in the HPACK spec. Returns a tuple of the decoded integer and the - number of bytes that were consumed from ``data`` in order to get that - integer. - """ - if prefix_bits < 1 or prefix_bits > 8: - raise ValueError( - "Prefix bits must be between 1 and 8, got %s" % prefix_bits - ) - - max_number = _PREFIX_BIT_MAX_NUMBERS[prefix_bits] - index = 1 - shift = 0 - mask = (0xFF >> (8 - prefix_bits)) - - try: - number = to_byte(data[0]) & mask - if number == max_number: - while True: - next_byte = to_byte(data[index]) - index += 1 - - if next_byte >= 128: - number += (next_byte - 128) << shift - else: - number += next_byte << shift - break - shift += 7 - - except IndexError: - raise HPACKDecodingError( - "Unable to decode HPACK integer representation from %r" % data - ) - - log.debug("Decoded %d, consumed %d bytes", number, index) - - return number, index - - -def _dict_to_iterable(header_dict): - """ - This converts a dictionary to an iterable of two-tuples. This is a - HPACK-specific function becuase it pulls "special-headers" out first and - then emits them. - """ - assert isinstance(header_dict, dict) - keys = sorted( - header_dict.keys(), - key=lambda k: not _to_bytes(k).startswith(b':') - ) - for key in keys: - yield key, header_dict[key] - - -def _to_bytes(string): - """ - Convert string to bytes. - """ - if not isinstance(string, basestring): # pragma: no cover - string = str(string) - - return string if isinstance(string, bytes) else string.encode('utf-8') - - -class Encoder(object): - """ - An HPACK encoder object. This object takes HTTP headers and emits encoded - HTTP/2 header blocks. - """ - - def __init__(self): - self.header_table = HeaderTable() - self.huffman_coder = HuffmanEncoder( - REQUEST_CODES, REQUEST_CODES_LENGTH - ) - self.table_size_changes = [] - - @property - def header_table_size(self): - """ - Controls the size of the HPACK header table. - """ - return self.header_table.maxsize - - @header_table_size.setter - def header_table_size(self, value): - self.header_table.maxsize = value - if self.header_table.resized: - self.table_size_changes.append(value) - - def encode(self, headers, huffman=True): - """ - Takes a set of headers and encodes them into a HPACK-encoded header - block. - - :param headers: The headers to encode. Must be either an iterable of - tuples, an iterable of :class:`HeaderTuple - `, or a ``dict``. - - If an iterable of tuples, the tuples may be either - two-tuples or three-tuples. If they are two-tuples, the - tuples must be of the format ``(name, value)``. If they - are three-tuples, they must be of the format - ``(name, value, sensitive)``, where ``sensitive`` is a - boolean value indicating whether the header should be - added to header tables anywhere. If not present, - ``sensitive`` defaults to ``False``. - - If an iterable of :class:`HeaderTuple - `, the tuples must always be - two-tuples. Instead of using ``sensitive`` as a third - tuple entry, use :class:`NeverIndexedHeaderTuple - ` to request that - the field never be indexed. - - .. warning:: HTTP/2 requires that all special headers - (headers whose names begin with ``:`` characters) - appear at the *start* of the header block. While - this method will ensure that happens for ``dict`` - subclasses, callers using any other iterable of - tuples **must** ensure they place their special - headers at the start of the iterable. - - For efficiency reasons users should prefer to use - iterables of two-tuples: fixing the ordering of - dictionary headers is an expensive operation that - should be avoided if possible. - - :param huffman: (optional) Whether to Huffman-encode any header sent as - a literal value. Except for use when debugging, it is - recommended that this be left enabled. - - :returns: A bytestring containing the HPACK-encoded header block. - """ - # Transforming the headers into a header block is a procedure that can - # be modeled as a chain or pipe. First, the headers are encoded. This - # encoding can be done a number of ways. If the header name-value pair - # are already in the header table we can represent them using the - # indexed representation: the same is true if they are in the static - # table. Otherwise, a literal representation will be used. - log.debug("HPACK encoding %s", headers) - header_block = [] - - # Turn the headers into a list of tuples if possible. This is the - # natural way to interact with them in HPACK. Because dictionaries are - # un-ordered, we need to make sure we grab the "special" headers first. - if isinstance(headers, dict): - headers = _dict_to_iterable(headers) - - # Before we begin, if the header table size has been changed we need - # to signal all changes since last emission appropriately. - if self.header_table.resized: - header_block.append(self._encode_table_size_change()) - self.header_table.resized = False - - # Add each header to the header block - for header in headers: - sensitive = False - if isinstance(header, HeaderTuple): - sensitive = not header.indexable - elif len(header) > 2: - sensitive = header[2] - - header = (_to_bytes(header[0]), _to_bytes(header[1])) - header_block.append(self.add(header, sensitive, huffman)) - - header_block = b''.join(header_block) - - log.debug("Encoded header block to %s", header_block) - - return header_block - - def add(self, to_add, sensitive, huffman=False): - """ - This function takes a header key-value tuple and serializes it. - """ - log.debug("Adding %s to the header table", to_add) - - name, value = to_add - - # Set our indexing mode - indexbit = INDEX_INCREMENTAL if not sensitive else INDEX_NEVER - - # Search for a matching header in the header table. - match = self.header_table.search(name, value) - - if match is None: - # Not in the header table. Encode using the literal syntax, - # and add it to the header table. - encoded = self._encode_literal(name, value, indexbit, huffman) - if not sensitive: - self.header_table.add(name, value) - return encoded - - # The header is in the table, break out the values. If we matched - # perfectly, we can use the indexed representation: otherwise we - # can use the indexed literal. - index, name, perfect = match - - if perfect: - # Indexed representation. - encoded = self._encode_indexed(index) - else: - # Indexed literal. We are going to add header to the - # header table unconditionally. It is a future todo to - # filter out headers which are known to be ineffective for - # indexing since they just take space in the table and - # pushed out other valuable headers. - encoded = self._encode_indexed_literal( - index, value, indexbit, huffman - ) - if not sensitive: - self.header_table.add(name, value) - - return encoded - - def _encode_indexed(self, index): - """ - Encodes a header using the indexed representation. - """ - field = encode_integer(index, 7) - field[0] |= 0x80 # we set the top bit - return bytes(field) - - def _encode_literal(self, name, value, indexbit, huffman=False): - """ - Encodes a header with a literal name and literal value. If ``indexing`` - is True, the header will be added to the header table: otherwise it - will not. - """ - if huffman: - name = self.huffman_coder.encode(name) - value = self.huffman_coder.encode(value) - - name_len = encode_integer(len(name), 7) - value_len = encode_integer(len(value), 7) - - if huffman: - name_len[0] |= 0x80 - value_len[0] |= 0x80 - - return b''.join( - [indexbit, bytes(name_len), name, bytes(value_len), value] - ) - - def _encode_indexed_literal(self, index, value, indexbit, huffman=False): - """ - Encodes a header with an indexed name and a literal value and performs - incremental indexing. - """ - if indexbit != INDEX_INCREMENTAL: - prefix = encode_integer(index, 4) - else: - prefix = encode_integer(index, 6) - - prefix[0] |= ord(indexbit) - - if huffman: - value = self.huffman_coder.encode(value) - - value_len = encode_integer(len(value), 7) - - if huffman: - value_len[0] |= 0x80 - - return b''.join([bytes(prefix), bytes(value_len), value]) - - def _encode_table_size_change(self): - """ - Produces the encoded form of all header table size change context - updates. - """ - block = b'' - for size_bytes in self.table_size_changes: - size_bytes = encode_integer(size_bytes, 5) - size_bytes[0] |= 0x20 - block += bytes(size_bytes) - self.table_size_changes = [] - return block - - -class Decoder(object): - """ - An HPACK decoder object. - - .. versionchanged:: 2.3.0 - Added ``max_header_list_size`` argument. - - :param max_header_list_size: The maximum decompressed size we will allow - for any single header block. This is a protection against DoS attacks - that attempt to force the application to expand a relatively small - amount of data into a really large header list, allowing enormous - amounts of memory to be allocated. - - If this amount of data is exceeded, a `OversizedHeaderListError - ` exception will be raised. At this - point the connection should be shut down, as the HPACK state will no - longer be useable. - - Defaults to 64kB. - :type max_header_list_size: ``int`` - """ - def __init__(self, max_header_list_size=DEFAULT_MAX_HEADER_LIST_SIZE): - self.header_table = HeaderTable() - - #: The maximum decompressed size we will allow for any single header - #: block. This is a protection against DoS attacks that attempt to - #: force the application to expand a relatively small amount of data - #: into a really large header list, allowing enormous amounts of memory - #: to be allocated. - #: - #: If this amount of data is exceeded, a `OversizedHeaderListError - #: ` exception will be raised. At this - #: point the connection should be shut down, as the HPACK state will no - #: longer be usable. - #: - #: Defaults to 64kB. - #: - #: .. versionadded:: 2.3.0 - self.max_header_list_size = max_header_list_size - - #: Maximum allowed header table size. - #: - #: A HTTP/2 implementation should set this to the most recent value of - #: SETTINGS_HEADER_TABLE_SIZE that it sent *and has received an ACK - #: for*. Once this setting is set, the actual header table size will be - #: checked at the end of each decoding run and whenever it is changed, - #: to confirm that it fits in this size. - self.max_allowed_table_size = self.header_table.maxsize - - @property - def header_table_size(self): - """ - Controls the size of the HPACK header table. - """ - return self.header_table.maxsize - - @header_table_size.setter - def header_table_size(self, value): - self.header_table.maxsize = value - - def decode(self, data, raw=False): - """ - Takes an HPACK-encoded header block and decodes it into a header set. - - :param data: A bytestring representing a complete HPACK-encoded header - block. - :param raw: (optional) Whether to return the headers as tuples of raw - byte strings or to decode them as UTF-8 before returning - them. The default value is False, which returns tuples of - Unicode strings - :returns: A list of two-tuples of ``(name, value)`` representing the - HPACK-encoded headers, in the order they were decoded. - :raises HPACKDecodingError: If an error is encountered while decoding - the header block. - """ - log.debug("Decoding %s", data) - - data_mem = memoryview(data) - headers = [] - data_len = len(data) - inflated_size = 0 - current_index = 0 - - while current_index < data_len: - # Work out what kind of header we're decoding. - # If the high bit is 1, it's an indexed field. - current = to_byte(data[current_index]) - indexed = True if current & 0x80 else False - - # Otherwise, if the second-highest bit is 1 it's a field that does - # alter the header table. - literal_index = True if current & 0x40 else False - - # Otherwise, if the third-highest bit is 1 it's an encoding context - # update. - encoding_update = True if current & 0x20 else False - - if indexed: - header, consumed = self._decode_indexed( - data_mem[current_index:] - ) - elif literal_index: - # It's a literal header that does affect the header table. - header, consumed = self._decode_literal_index( - data_mem[current_index:] - ) - elif encoding_update: - # It's an update to the encoding context. These are forbidden - # in a header block after any actual header. - if headers: - raise HPACKDecodingError( - "Table size update not at the start of the block" - ) - consumed = self._update_encoding_context( - data_mem[current_index:] - ) - header = None - else: - # It's a literal header that does not affect the header table. - header, consumed = self._decode_literal_no_index( - data_mem[current_index:] - ) - - if header: - headers.append(header) - inflated_size += table_entry_size(*header) - - if inflated_size > self.max_header_list_size: - raise OversizedHeaderListError( - "A header list larger than %d has been received" % - self.max_header_list_size - ) - - current_index += consumed - - # Confirm that the table size is lower than the maximum. We do this - # here to ensure that we catch when the max has been *shrunk* and the - # remote peer hasn't actually done that. - self._assert_valid_table_size() - - try: - return [_unicode_if_needed(h, raw) for h in headers] - except UnicodeDecodeError: - raise HPACKDecodingError("Unable to decode headers as UTF-8.") - - def _assert_valid_table_size(self): - """ - Check that the table size set by the encoder is lower than the maximum - we expect to have. - """ - if self.header_table_size > self.max_allowed_table_size: - raise InvalidTableSizeError( - "Encoder did not shrink table size to within the max" - ) - - def _update_encoding_context(self, data): - """ - Handles a byte that updates the encoding context. - """ - # We've been asked to resize the header table. - new_size, consumed = decode_integer(data, 5) - if new_size > self.max_allowed_table_size: - raise InvalidTableSizeError( - "Encoder exceeded max allowable table size" - ) - self.header_table_size = new_size - return consumed - - def _decode_indexed(self, data): - """ - Decodes a header represented using the indexed representation. - """ - index, consumed = decode_integer(data, 7) - header = HeaderTuple(*self.header_table.get_by_index(index)) - log.debug("Decoded %s, consumed %d", header, consumed) - return header, consumed - - def _decode_literal_no_index(self, data): - return self._decode_literal(data, False) - - def _decode_literal_index(self, data): - return self._decode_literal(data, True) - - def _decode_literal(self, data, should_index): - """ - Decodes a header represented with a literal. - """ - total_consumed = 0 - - # When should_index is true, if the low six bits of the first byte are - # nonzero, the header name is indexed. - # When should_index is false, if the low four bits of the first byte - # are nonzero the header name is indexed. - if should_index: - indexed_name = to_byte(data[0]) & 0x3F - name_len = 6 - not_indexable = False - else: - high_byte = to_byte(data[0]) - indexed_name = high_byte & 0x0F - name_len = 4 - not_indexable = high_byte & 0x10 - - if indexed_name: - # Indexed header name. - index, consumed = decode_integer(data, name_len) - name = self.header_table.get_by_index(index)[0] - - total_consumed = consumed - length = 0 - else: - # Literal header name. The first byte was consumed, so we need to - # move forward. - data = data[1:] - - length, consumed = decode_integer(data, 7) - name = data[consumed:consumed + length] - if len(name) != length: - raise HPACKDecodingError("Truncated header block") - - if to_byte(data[0]) & 0x80: - name = decode_huffman(name) - total_consumed = consumed + length + 1 # Since we moved forward 1. - - data = data[consumed + length:] - - # The header value is definitely length-based. - length, consumed = decode_integer(data, 7) - value = data[consumed:consumed + length] - if len(value) != length: - raise HPACKDecodingError("Truncated header block") - - if to_byte(data[0]) & 0x80: - value = decode_huffman(value) - - # Updated the total consumed length. - total_consumed += length + consumed - - # If we have been told never to index the header field, encode that in - # the tuple we use. - if not_indexable: - header = NeverIndexedHeaderTuple(name, value) - else: - header = HeaderTuple(name, value) - - # If we've been asked to index this, add it to the header table. - if should_index: - self.header_table.add(name, value) - - log.debug( - "Decoded %s, total consumed %d bytes, indexed %s", - header, - total_consumed, - should_index - ) - - return header, total_consumed diff --git a/py3.7/lib/python3.7/site-packages/hpack/hpack_compat.py b/py3.7/lib/python3.7/site-packages/hpack/hpack_compat.py deleted file mode 100644 index e5a76d7..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/hpack_compat.py +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/hpack_compat -~~~~~~~~~~~~~~~~~~ - -Provides an abstraction layer over two HPACK implementations. - -This module has a pure-Python greenfield HPACK implementation that can be used -on all Python platforms. However, this implementation is both slower and more -memory-hungry than could be achieved with a C-language version. Additionally, -nghttp2's HPACK implementation currently achieves better compression ratios -than hyper's in almost all benchmarks. - -For those who care about efficiency and speed in HPACK, this module allows you -to use nghttp2's HPACK implementation instead of ours. This module detects -whether the nghttp2 bindings are installed, and if they are it wraps them in -a hpack-compatible API and uses them instead of its own. If not, it falls back -to the built-in Python bindings. -""" -import logging -from .hpack import _to_bytes - -log = logging.getLogger(__name__) - -# Attempt to import nghttp2. -try: - import nghttp2 - USE_NGHTTP2 = True - log.debug("Using nghttp2's HPACK implementation.") -except ImportError: - USE_NGHTTP2 = False - log.debug("Using our pure-Python HPACK implementation.") - -if USE_NGHTTP2: # noqa - class Encoder(object): - """ - An HPACK encoder object. This object takes HTTP headers and emits - encoded HTTP/2 header blocks. - """ - def __init__(self): - self._e = nghttp2.HDDeflater() - - @property - def header_table_size(self): - """ - Returns the header table size. For the moment this isn't - useful, so we don't use it. - """ - raise NotImplementedError() - - @header_table_size.setter - def header_table_size(self, value): - log.debug("Setting header table size to %d", value) - self._e.change_table_size(value) - - def encode(self, headers, huffman=True): - """ - Encode the headers. The huffman parameter has no effect, it is - simply present for compatibility. - """ - log.debug("HPACK encoding %s", headers) - - # Turn the headers into a list of tuples if possible. This is the - # natural way to interact with them in HPACK. - if isinstance(headers, dict): - headers = headers.items() - - # Next, walk across the headers and turn them all into bytestrings. - headers = [(_to_bytes(n), _to_bytes(v)) for n, v in headers] - - # Now, let nghttp2 do its thing. - header_block = self._e.deflate(headers) - - return header_block - - class Decoder(object): - """ - An HPACK decoder object. - """ - def __init__(self): - self._d = nghttp2.HDInflater() - - @property - def header_table_size(self): - """ - Returns the header table size. For the moment this isn't - useful, so we don't use it. - """ - raise NotImplementedError() - - @header_table_size.setter - def header_table_size(self, value): - log.debug("Setting header table size to %d", value) - self._d.change_table_size(value) - - def decode(self, data): - """ - Takes an HPACK-encoded header block and decodes it into a header - set. - """ - log.debug("Decoding %s", data) - - headers = self._d.inflate(data) - return [(n.decode('utf-8'), v.decode('utf-8')) for n, v in headers] -else: - # Grab the built-in encoder and decoder. - from .hpack import Encoder, Decoder # noqa diff --git a/py3.7/lib/python3.7/site-packages/hpack/huffman.py b/py3.7/lib/python3.7/site-packages/hpack/huffman.py deleted file mode 100644 index 159569c..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/huffman.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/huffman_decoder -~~~~~~~~~~~~~~~~~~~~~ - -An implementation of a bitwise prefix tree specially built for decoding -Huffman-coded content where we already know the Huffman table. -""" -from .compat import to_byte, decode_hex - - -class HuffmanEncoder(object): - """ - Encodes a string according to the Huffman encoding table defined in the - HPACK specification. - """ - def __init__(self, huffman_code_list, huffman_code_list_lengths): - self.huffman_code_list = huffman_code_list - self.huffman_code_list_lengths = huffman_code_list_lengths - - def encode(self, bytes_to_encode): - """ - Given a string of bytes, encodes them according to the HPACK Huffman - specification. - """ - # If handed the empty string, just immediately return. - if not bytes_to_encode: - return b'' - - final_num = 0 - final_int_len = 0 - - # Turn each byte into its huffman code. These codes aren't necessarily - # octet aligned, so keep track of how far through an octet we are. To - # handle this cleanly, just use a single giant integer. - for char in bytes_to_encode: - byte = to_byte(char) - bin_int_len = self.huffman_code_list_lengths[byte] - bin_int = self.huffman_code_list[byte] & ( - 2 ** (bin_int_len + 1) - 1 - ) - final_num <<= bin_int_len - final_num |= bin_int - final_int_len += bin_int_len - - # Pad out to an octet with ones. - bits_to_be_padded = (8 - (final_int_len % 8)) % 8 - final_num <<= bits_to_be_padded - final_num |= (1 << bits_to_be_padded) - 1 - - # Convert the number to hex and strip off the leading '0x' and the - # trailing 'L', if present. - final_num = hex(final_num)[2:].rstrip('L') - - # If this is odd, prepend a zero. - final_num = '0' + final_num if len(final_num) % 2 != 0 else final_num - - # This number should have twice as many digits as bytes. If not, we're - # missing some leading zeroes. Work out how many bytes we want and how - # many digits we have, then add the missing zero digits to the front. - total_bytes = (final_int_len + bits_to_be_padded) // 8 - expected_digits = total_bytes * 2 - - if len(final_num) != expected_digits: - missing_digits = expected_digits - len(final_num) - final_num = ('0' * missing_digits) + final_num - - return decode_hex(final_num) diff --git a/py3.7/lib/python3.7/site-packages/hpack/huffman_constants.py b/py3.7/lib/python3.7/site-packages/hpack/huffman_constants.py deleted file mode 100644 index c2b3bb2..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/huffman_constants.py +++ /dev/null @@ -1,288 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/huffman_constants -~~~~~~~~~~~~~~~~~~~~~~~ - -Defines the constant Huffman table. This takes up an upsetting amount of space, -but c'est la vie. -""" - -REQUEST_CODES = [ - 0x1ff8, - 0x7fffd8, - 0xfffffe2, - 0xfffffe3, - 0xfffffe4, - 0xfffffe5, - 0xfffffe6, - 0xfffffe7, - 0xfffffe8, - 0xffffea, - 0x3ffffffc, - 0xfffffe9, - 0xfffffea, - 0x3ffffffd, - 0xfffffeb, - 0xfffffec, - 0xfffffed, - 0xfffffee, - 0xfffffef, - 0xffffff0, - 0xffffff1, - 0xffffff2, - 0x3ffffffe, - 0xffffff3, - 0xffffff4, - 0xffffff5, - 0xffffff6, - 0xffffff7, - 0xffffff8, - 0xffffff9, - 0xffffffa, - 0xffffffb, - 0x14, - 0x3f8, - 0x3f9, - 0xffa, - 0x1ff9, - 0x15, - 0xf8, - 0x7fa, - 0x3fa, - 0x3fb, - 0xf9, - 0x7fb, - 0xfa, - 0x16, - 0x17, - 0x18, - 0x0, - 0x1, - 0x2, - 0x19, - 0x1a, - 0x1b, - 0x1c, - 0x1d, - 0x1e, - 0x1f, - 0x5c, - 0xfb, - 0x7ffc, - 0x20, - 0xffb, - 0x3fc, - 0x1ffa, - 0x21, - 0x5d, - 0x5e, - 0x5f, - 0x60, - 0x61, - 0x62, - 0x63, - 0x64, - 0x65, - 0x66, - 0x67, - 0x68, - 0x69, - 0x6a, - 0x6b, - 0x6c, - 0x6d, - 0x6e, - 0x6f, - 0x70, - 0x71, - 0x72, - 0xfc, - 0x73, - 0xfd, - 0x1ffb, - 0x7fff0, - 0x1ffc, - 0x3ffc, - 0x22, - 0x7ffd, - 0x3, - 0x23, - 0x4, - 0x24, - 0x5, - 0x25, - 0x26, - 0x27, - 0x6, - 0x74, - 0x75, - 0x28, - 0x29, - 0x2a, - 0x7, - 0x2b, - 0x76, - 0x2c, - 0x8, - 0x9, - 0x2d, - 0x77, - 0x78, - 0x79, - 0x7a, - 0x7b, - 0x7ffe, - 0x7fc, - 0x3ffd, - 0x1ffd, - 0xffffffc, - 0xfffe6, - 0x3fffd2, - 0xfffe7, - 0xfffe8, - 0x3fffd3, - 0x3fffd4, - 0x3fffd5, - 0x7fffd9, - 0x3fffd6, - 0x7fffda, - 0x7fffdb, - 0x7fffdc, - 0x7fffdd, - 0x7fffde, - 0xffffeb, - 0x7fffdf, - 0xffffec, - 0xffffed, - 0x3fffd7, - 0x7fffe0, - 0xffffee, - 0x7fffe1, - 0x7fffe2, - 0x7fffe3, - 0x7fffe4, - 0x1fffdc, - 0x3fffd8, - 0x7fffe5, - 0x3fffd9, - 0x7fffe6, - 0x7fffe7, - 0xffffef, - 0x3fffda, - 0x1fffdd, - 0xfffe9, - 0x3fffdb, - 0x3fffdc, - 0x7fffe8, - 0x7fffe9, - 0x1fffde, - 0x7fffea, - 0x3fffdd, - 0x3fffde, - 0xfffff0, - 0x1fffdf, - 0x3fffdf, - 0x7fffeb, - 0x7fffec, - 0x1fffe0, - 0x1fffe1, - 0x3fffe0, - 0x1fffe2, - 0x7fffed, - 0x3fffe1, - 0x7fffee, - 0x7fffef, - 0xfffea, - 0x3fffe2, - 0x3fffe3, - 0x3fffe4, - 0x7ffff0, - 0x3fffe5, - 0x3fffe6, - 0x7ffff1, - 0x3ffffe0, - 0x3ffffe1, - 0xfffeb, - 0x7fff1, - 0x3fffe7, - 0x7ffff2, - 0x3fffe8, - 0x1ffffec, - 0x3ffffe2, - 0x3ffffe3, - 0x3ffffe4, - 0x7ffffde, - 0x7ffffdf, - 0x3ffffe5, - 0xfffff1, - 0x1ffffed, - 0x7fff2, - 0x1fffe3, - 0x3ffffe6, - 0x7ffffe0, - 0x7ffffe1, - 0x3ffffe7, - 0x7ffffe2, - 0xfffff2, - 0x1fffe4, - 0x1fffe5, - 0x3ffffe8, - 0x3ffffe9, - 0xffffffd, - 0x7ffffe3, - 0x7ffffe4, - 0x7ffffe5, - 0xfffec, - 0xfffff3, - 0xfffed, - 0x1fffe6, - 0x3fffe9, - 0x1fffe7, - 0x1fffe8, - 0x7ffff3, - 0x3fffea, - 0x3fffeb, - 0x1ffffee, - 0x1ffffef, - 0xfffff4, - 0xfffff5, - 0x3ffffea, - 0x7ffff4, - 0x3ffffeb, - 0x7ffffe6, - 0x3ffffec, - 0x3ffffed, - 0x7ffffe7, - 0x7ffffe8, - 0x7ffffe9, - 0x7ffffea, - 0x7ffffeb, - 0xffffffe, - 0x7ffffec, - 0x7ffffed, - 0x7ffffee, - 0x7ffffef, - 0x7fffff0, - 0x3ffffee, - 0x3fffffff, -] - -REQUEST_CODES_LENGTH = [ - 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28, - 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6, - 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10, - 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6, - 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5, - 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28, - 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23, - 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24, - 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23, - 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23, - 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25, - 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27, - 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23, - 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26, - 30, -] diff --git a/py3.7/lib/python3.7/site-packages/hpack/huffman_table.py b/py3.7/lib/python3.7/site-packages/hpack/huffman_table.py deleted file mode 100644 index c199ef5..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/huffman_table.py +++ /dev/null @@ -1,4739 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/huffman_table -~~~~~~~~~~~~~~~~~~~ - -This implementation of a Huffman decoding table for HTTP/2 is essentially a -Python port of the work originally done for nghttp2's Huffman decoding. For -this reason, while this file is made available under the MIT license as is the -rest of this module, this file is undoubtedly a derivative work of the nghttp2 -file ``nghttp2_hd_huffman_data.c``, obtained from -https://github.com/tatsuhiro-t/nghttp2/ at commit -d2b55ad1a245e1d1964579fa3fac36ebf3939e72. That work is made available under -the Apache 2.0 license under the following terms: - - Copyright (c) 2013 Tatsuhiro Tsujikawa - - 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. - -The essence of this approach is that it builds a finite state machine out of -4-bit nibbles of Huffman coded data. The input function passes 4 bits worth of -data to the state machine each time, which uses those 4 bits of data along with -the current accumulated state data to process the data given. - -For the sake of efficiency, the in-memory representation of the states, -transitions, and result values of the state machine are represented as a long -list containing three-tuples. This list is enormously long, and viewing it as -an in-memory representation is not very clear, but it is laid out here in a way -that is intended to be *somewhat* more clear. - -Essentially, the list is structured as 256 collections of 16 entries (one for -each nibble) of three-tuples. Each collection is called a "node", and the -zeroth collection is called the "root node". The state machine tracks one -value: the "state" byte. - -For each nibble passed to the state machine, it first multiplies the "state" -byte by 16 and adds the numerical value of the nibble. This number is the index -into the large flat list. - -The three-tuple that is found by looking up that index consists of three -values: - -- a new state value, used for subsequent decoding -- a collection of flags, used to determine whether data is emitted or whether - the state machine is complete. -- the byte value to emit, assuming that emitting a byte is required. - -The flags are consulted, if necessary a byte is emitted, and then the next -nibble is used. This continues until the state machine believes it has -completely Huffman-decoded the data. - -This approach has relatively little indirection, and therefore performs -relatively well, particularly on implementations like PyPy where the cost of -loops at the Python-level is not too expensive. The total number of loop -iterations is 4x the number of bytes passed to the decoder. -""" -from .exceptions import HPACKDecodingError - - -# This defines the state machine "class" at the top of the file. The reason we -# do this is to keep the terrifing monster state table at the *bottom* of the -# file so you don't have to actually *look* at the damn thing. -def decode_huffman(huffman_string): - """ - Given a bytestring of Huffman-encoded data for HPACK, returns a bytestring - of the decompressed data. - """ - if not huffman_string: - return b'' - - state = 0 - flags = 0 - decoded_bytes = bytearray() - - # Perversely, bytearrays are a lot more convenient across Python 2 and - # Python 3 because they behave *the same way* on both platforms. Given that - # we really do want numerical bytes when we iterate here, let's use a - # bytearray. - huffman_string = bytearray(huffman_string) - - # This loop is unrolled somewhat. Because we use a nibble, not a byte, we - # need to handle each nibble twice. We unroll that: it makes the loop body - # a bit longer, but that's ok. - for input_byte in huffman_string: - index = (state * 16) + (input_byte >> 4) - state, flags, output_byte = HUFFMAN_TABLE[index] - - if flags & HUFFMAN_FAIL: - raise HPACKDecodingError("Invalid Huffman String") - - if flags & HUFFMAN_EMIT_SYMBOL: - decoded_bytes.append(output_byte) - - index = (state * 16) + (input_byte & 0x0F) - state, flags, output_byte = HUFFMAN_TABLE[index] - - if flags & HUFFMAN_FAIL: - raise HPACKDecodingError("Invalid Huffman String") - - if flags & HUFFMAN_EMIT_SYMBOL: - decoded_bytes.append(output_byte) - - if not (flags & HUFFMAN_COMPLETE): - raise HPACKDecodingError("Incomplete Huffman string") - - return bytes(decoded_bytes) - - -# Some decoder flags to control state transitions. -HUFFMAN_COMPLETE = 1 -HUFFMAN_EMIT_SYMBOL = (1 << 1) -HUFFMAN_FAIL = (1 << 2) - -# This is the monster table. Avert your eyes, children. -HUFFMAN_TABLE = [ - # Node 0 (Root Node, never emits symbols.) - (4, 0, 0), - (5, 0, 0), - (7, 0, 0), - (8, 0, 0), - (11, 0, 0), - (12, 0, 0), - (16, 0, 0), - (19, 0, 0), - (25, 0, 0), - (28, 0, 0), - (32, 0, 0), - (35, 0, 0), - (42, 0, 0), - (49, 0, 0), - (57, 0, 0), - (64, HUFFMAN_COMPLETE, 0), - - # Node 1 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (13, 0, 0), - (14, 0, 0), - (17, 0, 0), - (18, 0, 0), - (20, 0, 0), - (21, 0, 0), - - # Node 2 - (1, HUFFMAN_EMIT_SYMBOL, 48), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (1, HUFFMAN_EMIT_SYMBOL, 49), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (1, HUFFMAN_EMIT_SYMBOL, 50), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (1, HUFFMAN_EMIT_SYMBOL, 97), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - (1, HUFFMAN_EMIT_SYMBOL, 99), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (1, HUFFMAN_EMIT_SYMBOL, 101), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (1, HUFFMAN_EMIT_SYMBOL, 105), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (1, HUFFMAN_EMIT_SYMBOL, 111), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 3 - (2, HUFFMAN_EMIT_SYMBOL, 48), - (9, HUFFMAN_EMIT_SYMBOL, 48), - (23, HUFFMAN_EMIT_SYMBOL, 48), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (2, HUFFMAN_EMIT_SYMBOL, 49), - (9, HUFFMAN_EMIT_SYMBOL, 49), - (23, HUFFMAN_EMIT_SYMBOL, 49), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - (2, HUFFMAN_EMIT_SYMBOL, 50), - (9, HUFFMAN_EMIT_SYMBOL, 50), - (23, HUFFMAN_EMIT_SYMBOL, 50), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (2, HUFFMAN_EMIT_SYMBOL, 97), - (9, HUFFMAN_EMIT_SYMBOL, 97), - (23, HUFFMAN_EMIT_SYMBOL, 97), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - - # Node 4 - (3, HUFFMAN_EMIT_SYMBOL, 48), - (6, HUFFMAN_EMIT_SYMBOL, 48), - (10, HUFFMAN_EMIT_SYMBOL, 48), - (15, HUFFMAN_EMIT_SYMBOL, 48), - (24, HUFFMAN_EMIT_SYMBOL, 48), - (31, HUFFMAN_EMIT_SYMBOL, 48), - (41, HUFFMAN_EMIT_SYMBOL, 48), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 48), - (3, HUFFMAN_EMIT_SYMBOL, 49), - (6, HUFFMAN_EMIT_SYMBOL, 49), - (10, HUFFMAN_EMIT_SYMBOL, 49), - (15, HUFFMAN_EMIT_SYMBOL, 49), - (24, HUFFMAN_EMIT_SYMBOL, 49), - (31, HUFFMAN_EMIT_SYMBOL, 49), - (41, HUFFMAN_EMIT_SYMBOL, 49), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 49), - - # Node 5 - (3, HUFFMAN_EMIT_SYMBOL, 50), - (6, HUFFMAN_EMIT_SYMBOL, 50), - (10, HUFFMAN_EMIT_SYMBOL, 50), - (15, HUFFMAN_EMIT_SYMBOL, 50), - (24, HUFFMAN_EMIT_SYMBOL, 50), - (31, HUFFMAN_EMIT_SYMBOL, 50), - (41, HUFFMAN_EMIT_SYMBOL, 50), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 50), - (3, HUFFMAN_EMIT_SYMBOL, 97), - (6, HUFFMAN_EMIT_SYMBOL, 97), - (10, HUFFMAN_EMIT_SYMBOL, 97), - (15, HUFFMAN_EMIT_SYMBOL, 97), - (24, HUFFMAN_EMIT_SYMBOL, 97), - (31, HUFFMAN_EMIT_SYMBOL, 97), - (41, HUFFMAN_EMIT_SYMBOL, 97), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 97), - - # Node 6 - (2, HUFFMAN_EMIT_SYMBOL, 99), - (9, HUFFMAN_EMIT_SYMBOL, 99), - (23, HUFFMAN_EMIT_SYMBOL, 99), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (2, HUFFMAN_EMIT_SYMBOL, 101), - (9, HUFFMAN_EMIT_SYMBOL, 101), - (23, HUFFMAN_EMIT_SYMBOL, 101), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - (2, HUFFMAN_EMIT_SYMBOL, 105), - (9, HUFFMAN_EMIT_SYMBOL, 105), - (23, HUFFMAN_EMIT_SYMBOL, 105), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (2, HUFFMAN_EMIT_SYMBOL, 111), - (9, HUFFMAN_EMIT_SYMBOL, 111), - (23, HUFFMAN_EMIT_SYMBOL, 111), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 7 - (3, HUFFMAN_EMIT_SYMBOL, 99), - (6, HUFFMAN_EMIT_SYMBOL, 99), - (10, HUFFMAN_EMIT_SYMBOL, 99), - (15, HUFFMAN_EMIT_SYMBOL, 99), - (24, HUFFMAN_EMIT_SYMBOL, 99), - (31, HUFFMAN_EMIT_SYMBOL, 99), - (41, HUFFMAN_EMIT_SYMBOL, 99), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 99), - (3, HUFFMAN_EMIT_SYMBOL, 101), - (6, HUFFMAN_EMIT_SYMBOL, 101), - (10, HUFFMAN_EMIT_SYMBOL, 101), - (15, HUFFMAN_EMIT_SYMBOL, 101), - (24, HUFFMAN_EMIT_SYMBOL, 101), - (31, HUFFMAN_EMIT_SYMBOL, 101), - (41, HUFFMAN_EMIT_SYMBOL, 101), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 101), - - # Node 8 - (3, HUFFMAN_EMIT_SYMBOL, 105), - (6, HUFFMAN_EMIT_SYMBOL, 105), - (10, HUFFMAN_EMIT_SYMBOL, 105), - (15, HUFFMAN_EMIT_SYMBOL, 105), - (24, HUFFMAN_EMIT_SYMBOL, 105), - (31, HUFFMAN_EMIT_SYMBOL, 105), - (41, HUFFMAN_EMIT_SYMBOL, 105), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 105), - (3, HUFFMAN_EMIT_SYMBOL, 111), - (6, HUFFMAN_EMIT_SYMBOL, 111), - (10, HUFFMAN_EMIT_SYMBOL, 111), - (15, HUFFMAN_EMIT_SYMBOL, 111), - (24, HUFFMAN_EMIT_SYMBOL, 111), - (31, HUFFMAN_EMIT_SYMBOL, 111), - (41, HUFFMAN_EMIT_SYMBOL, 111), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 111), - - # Node 9 - (1, HUFFMAN_EMIT_SYMBOL, 115), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (1, HUFFMAN_EMIT_SYMBOL, 116), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 10 - (2, HUFFMAN_EMIT_SYMBOL, 115), - (9, HUFFMAN_EMIT_SYMBOL, 115), - (23, HUFFMAN_EMIT_SYMBOL, 115), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (2, HUFFMAN_EMIT_SYMBOL, 116), - (9, HUFFMAN_EMIT_SYMBOL, 116), - (23, HUFFMAN_EMIT_SYMBOL, 116), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - (1, HUFFMAN_EMIT_SYMBOL, 32), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (1, HUFFMAN_EMIT_SYMBOL, 37), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (1, HUFFMAN_EMIT_SYMBOL, 45), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (1, HUFFMAN_EMIT_SYMBOL, 46), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 11 - (3, HUFFMAN_EMIT_SYMBOL, 115), - (6, HUFFMAN_EMIT_SYMBOL, 115), - (10, HUFFMAN_EMIT_SYMBOL, 115), - (15, HUFFMAN_EMIT_SYMBOL, 115), - (24, HUFFMAN_EMIT_SYMBOL, 115), - (31, HUFFMAN_EMIT_SYMBOL, 115), - (41, HUFFMAN_EMIT_SYMBOL, 115), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 115), - (3, HUFFMAN_EMIT_SYMBOL, 116), - (6, HUFFMAN_EMIT_SYMBOL, 116), - (10, HUFFMAN_EMIT_SYMBOL, 116), - (15, HUFFMAN_EMIT_SYMBOL, 116), - (24, HUFFMAN_EMIT_SYMBOL, 116), - (31, HUFFMAN_EMIT_SYMBOL, 116), - (41, HUFFMAN_EMIT_SYMBOL, 116), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 116), - - # Node 12 - (2, HUFFMAN_EMIT_SYMBOL, 32), - (9, HUFFMAN_EMIT_SYMBOL, 32), - (23, HUFFMAN_EMIT_SYMBOL, 32), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (2, HUFFMAN_EMIT_SYMBOL, 37), - (9, HUFFMAN_EMIT_SYMBOL, 37), - (23, HUFFMAN_EMIT_SYMBOL, 37), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - (2, HUFFMAN_EMIT_SYMBOL, 45), - (9, HUFFMAN_EMIT_SYMBOL, 45), - (23, HUFFMAN_EMIT_SYMBOL, 45), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (2, HUFFMAN_EMIT_SYMBOL, 46), - (9, HUFFMAN_EMIT_SYMBOL, 46), - (23, HUFFMAN_EMIT_SYMBOL, 46), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 13 - (3, HUFFMAN_EMIT_SYMBOL, 32), - (6, HUFFMAN_EMIT_SYMBOL, 32), - (10, HUFFMAN_EMIT_SYMBOL, 32), - (15, HUFFMAN_EMIT_SYMBOL, 32), - (24, HUFFMAN_EMIT_SYMBOL, 32), - (31, HUFFMAN_EMIT_SYMBOL, 32), - (41, HUFFMAN_EMIT_SYMBOL, 32), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 32), - (3, HUFFMAN_EMIT_SYMBOL, 37), - (6, HUFFMAN_EMIT_SYMBOL, 37), - (10, HUFFMAN_EMIT_SYMBOL, 37), - (15, HUFFMAN_EMIT_SYMBOL, 37), - (24, HUFFMAN_EMIT_SYMBOL, 37), - (31, HUFFMAN_EMIT_SYMBOL, 37), - (41, HUFFMAN_EMIT_SYMBOL, 37), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 37), - - # Node 14 - (3, HUFFMAN_EMIT_SYMBOL, 45), - (6, HUFFMAN_EMIT_SYMBOL, 45), - (10, HUFFMAN_EMIT_SYMBOL, 45), - (15, HUFFMAN_EMIT_SYMBOL, 45), - (24, HUFFMAN_EMIT_SYMBOL, 45), - (31, HUFFMAN_EMIT_SYMBOL, 45), - (41, HUFFMAN_EMIT_SYMBOL, 45), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 45), - (3, HUFFMAN_EMIT_SYMBOL, 46), - (6, HUFFMAN_EMIT_SYMBOL, 46), - (10, HUFFMAN_EMIT_SYMBOL, 46), - (15, HUFFMAN_EMIT_SYMBOL, 46), - (24, HUFFMAN_EMIT_SYMBOL, 46), - (31, HUFFMAN_EMIT_SYMBOL, 46), - (41, HUFFMAN_EMIT_SYMBOL, 46), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 46), - - # Node 15 - (1, HUFFMAN_EMIT_SYMBOL, 47), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (1, HUFFMAN_EMIT_SYMBOL, 51), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (1, HUFFMAN_EMIT_SYMBOL, 52), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (1, HUFFMAN_EMIT_SYMBOL, 53), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - (1, HUFFMAN_EMIT_SYMBOL, 54), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (1, HUFFMAN_EMIT_SYMBOL, 55), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (1, HUFFMAN_EMIT_SYMBOL, 56), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (1, HUFFMAN_EMIT_SYMBOL, 57), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 16 - (2, HUFFMAN_EMIT_SYMBOL, 47), - (9, HUFFMAN_EMIT_SYMBOL, 47), - (23, HUFFMAN_EMIT_SYMBOL, 47), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (2, HUFFMAN_EMIT_SYMBOL, 51), - (9, HUFFMAN_EMIT_SYMBOL, 51), - (23, HUFFMAN_EMIT_SYMBOL, 51), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - (2, HUFFMAN_EMIT_SYMBOL, 52), - (9, HUFFMAN_EMIT_SYMBOL, 52), - (23, HUFFMAN_EMIT_SYMBOL, 52), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (2, HUFFMAN_EMIT_SYMBOL, 53), - (9, HUFFMAN_EMIT_SYMBOL, 53), - (23, HUFFMAN_EMIT_SYMBOL, 53), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - - # Node 17 - (3, HUFFMAN_EMIT_SYMBOL, 47), - (6, HUFFMAN_EMIT_SYMBOL, 47), - (10, HUFFMAN_EMIT_SYMBOL, 47), - (15, HUFFMAN_EMIT_SYMBOL, 47), - (24, HUFFMAN_EMIT_SYMBOL, 47), - (31, HUFFMAN_EMIT_SYMBOL, 47), - (41, HUFFMAN_EMIT_SYMBOL, 47), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 47), - (3, HUFFMAN_EMIT_SYMBOL, 51), - (6, HUFFMAN_EMIT_SYMBOL, 51), - (10, HUFFMAN_EMIT_SYMBOL, 51), - (15, HUFFMAN_EMIT_SYMBOL, 51), - (24, HUFFMAN_EMIT_SYMBOL, 51), - (31, HUFFMAN_EMIT_SYMBOL, 51), - (41, HUFFMAN_EMIT_SYMBOL, 51), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 51), - - # Node 18 - (3, HUFFMAN_EMIT_SYMBOL, 52), - (6, HUFFMAN_EMIT_SYMBOL, 52), - (10, HUFFMAN_EMIT_SYMBOL, 52), - (15, HUFFMAN_EMIT_SYMBOL, 52), - (24, HUFFMAN_EMIT_SYMBOL, 52), - (31, HUFFMAN_EMIT_SYMBOL, 52), - (41, HUFFMAN_EMIT_SYMBOL, 52), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 52), - (3, HUFFMAN_EMIT_SYMBOL, 53), - (6, HUFFMAN_EMIT_SYMBOL, 53), - (10, HUFFMAN_EMIT_SYMBOL, 53), - (15, HUFFMAN_EMIT_SYMBOL, 53), - (24, HUFFMAN_EMIT_SYMBOL, 53), - (31, HUFFMAN_EMIT_SYMBOL, 53), - (41, HUFFMAN_EMIT_SYMBOL, 53), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 53), - - # Node 19 - (2, HUFFMAN_EMIT_SYMBOL, 54), - (9, HUFFMAN_EMIT_SYMBOL, 54), - (23, HUFFMAN_EMIT_SYMBOL, 54), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (2, HUFFMAN_EMIT_SYMBOL, 55), - (9, HUFFMAN_EMIT_SYMBOL, 55), - (23, HUFFMAN_EMIT_SYMBOL, 55), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - (2, HUFFMAN_EMIT_SYMBOL, 56), - (9, HUFFMAN_EMIT_SYMBOL, 56), - (23, HUFFMAN_EMIT_SYMBOL, 56), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (2, HUFFMAN_EMIT_SYMBOL, 57), - (9, HUFFMAN_EMIT_SYMBOL, 57), - (23, HUFFMAN_EMIT_SYMBOL, 57), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 20 - (3, HUFFMAN_EMIT_SYMBOL, 54), - (6, HUFFMAN_EMIT_SYMBOL, 54), - (10, HUFFMAN_EMIT_SYMBOL, 54), - (15, HUFFMAN_EMIT_SYMBOL, 54), - (24, HUFFMAN_EMIT_SYMBOL, 54), - (31, HUFFMAN_EMIT_SYMBOL, 54), - (41, HUFFMAN_EMIT_SYMBOL, 54), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 54), - (3, HUFFMAN_EMIT_SYMBOL, 55), - (6, HUFFMAN_EMIT_SYMBOL, 55), - (10, HUFFMAN_EMIT_SYMBOL, 55), - (15, HUFFMAN_EMIT_SYMBOL, 55), - (24, HUFFMAN_EMIT_SYMBOL, 55), - (31, HUFFMAN_EMIT_SYMBOL, 55), - (41, HUFFMAN_EMIT_SYMBOL, 55), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 55), - - # Node 21 - (3, HUFFMAN_EMIT_SYMBOL, 56), - (6, HUFFMAN_EMIT_SYMBOL, 56), - (10, HUFFMAN_EMIT_SYMBOL, 56), - (15, HUFFMAN_EMIT_SYMBOL, 56), - (24, HUFFMAN_EMIT_SYMBOL, 56), - (31, HUFFMAN_EMIT_SYMBOL, 56), - (41, HUFFMAN_EMIT_SYMBOL, 56), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 56), - (3, HUFFMAN_EMIT_SYMBOL, 57), - (6, HUFFMAN_EMIT_SYMBOL, 57), - (10, HUFFMAN_EMIT_SYMBOL, 57), - (15, HUFFMAN_EMIT_SYMBOL, 57), - (24, HUFFMAN_EMIT_SYMBOL, 57), - (31, HUFFMAN_EMIT_SYMBOL, 57), - (41, HUFFMAN_EMIT_SYMBOL, 57), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 57), - - # Node 22 - (26, 0, 0), - (27, 0, 0), - (29, 0, 0), - (30, 0, 0), - (33, 0, 0), - (34, 0, 0), - (36, 0, 0), - (37, 0, 0), - (43, 0, 0), - (46, 0, 0), - (50, 0, 0), - (53, 0, 0), - (58, 0, 0), - (61, 0, 0), - (65, 0, 0), - (68, HUFFMAN_COMPLETE, 0), - - # Node 23 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (38, 0, 0), - (39, 0, 0), - - # Node 24 - (1, HUFFMAN_EMIT_SYMBOL, 61), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (1, HUFFMAN_EMIT_SYMBOL, 65), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (1, HUFFMAN_EMIT_SYMBOL, 95), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (1, HUFFMAN_EMIT_SYMBOL, 98), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - (1, HUFFMAN_EMIT_SYMBOL, 100), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (1, HUFFMAN_EMIT_SYMBOL, 102), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (1, HUFFMAN_EMIT_SYMBOL, 103), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (1, HUFFMAN_EMIT_SYMBOL, 104), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 25 - (2, HUFFMAN_EMIT_SYMBOL, 61), - (9, HUFFMAN_EMIT_SYMBOL, 61), - (23, HUFFMAN_EMIT_SYMBOL, 61), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (2, HUFFMAN_EMIT_SYMBOL, 65), - (9, HUFFMAN_EMIT_SYMBOL, 65), - (23, HUFFMAN_EMIT_SYMBOL, 65), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - (2, HUFFMAN_EMIT_SYMBOL, 95), - (9, HUFFMAN_EMIT_SYMBOL, 95), - (23, HUFFMAN_EMIT_SYMBOL, 95), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (2, HUFFMAN_EMIT_SYMBOL, 98), - (9, HUFFMAN_EMIT_SYMBOL, 98), - (23, HUFFMAN_EMIT_SYMBOL, 98), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - - # Node 26 - (3, HUFFMAN_EMIT_SYMBOL, 61), - (6, HUFFMAN_EMIT_SYMBOL, 61), - (10, HUFFMAN_EMIT_SYMBOL, 61), - (15, HUFFMAN_EMIT_SYMBOL, 61), - (24, HUFFMAN_EMIT_SYMBOL, 61), - (31, HUFFMAN_EMIT_SYMBOL, 61), - (41, HUFFMAN_EMIT_SYMBOL, 61), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 61), - (3, HUFFMAN_EMIT_SYMBOL, 65), - (6, HUFFMAN_EMIT_SYMBOL, 65), - (10, HUFFMAN_EMIT_SYMBOL, 65), - (15, HUFFMAN_EMIT_SYMBOL, 65), - (24, HUFFMAN_EMIT_SYMBOL, 65), - (31, HUFFMAN_EMIT_SYMBOL, 65), - (41, HUFFMAN_EMIT_SYMBOL, 65), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 65), - - # Node 27 - (3, HUFFMAN_EMIT_SYMBOL, 95), - (6, HUFFMAN_EMIT_SYMBOL, 95), - (10, HUFFMAN_EMIT_SYMBOL, 95), - (15, HUFFMAN_EMIT_SYMBOL, 95), - (24, HUFFMAN_EMIT_SYMBOL, 95), - (31, HUFFMAN_EMIT_SYMBOL, 95), - (41, HUFFMAN_EMIT_SYMBOL, 95), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 95), - (3, HUFFMAN_EMIT_SYMBOL, 98), - (6, HUFFMAN_EMIT_SYMBOL, 98), - (10, HUFFMAN_EMIT_SYMBOL, 98), - (15, HUFFMAN_EMIT_SYMBOL, 98), - (24, HUFFMAN_EMIT_SYMBOL, 98), - (31, HUFFMAN_EMIT_SYMBOL, 98), - (41, HUFFMAN_EMIT_SYMBOL, 98), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 98), - - # Node 28 - (2, HUFFMAN_EMIT_SYMBOL, 100), - (9, HUFFMAN_EMIT_SYMBOL, 100), - (23, HUFFMAN_EMIT_SYMBOL, 100), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (2, HUFFMAN_EMIT_SYMBOL, 102), - (9, HUFFMAN_EMIT_SYMBOL, 102), - (23, HUFFMAN_EMIT_SYMBOL, 102), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - (2, HUFFMAN_EMIT_SYMBOL, 103), - (9, HUFFMAN_EMIT_SYMBOL, 103), - (23, HUFFMAN_EMIT_SYMBOL, 103), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (2, HUFFMAN_EMIT_SYMBOL, 104), - (9, HUFFMAN_EMIT_SYMBOL, 104), - (23, HUFFMAN_EMIT_SYMBOL, 104), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 29 - (3, HUFFMAN_EMIT_SYMBOL, 100), - (6, HUFFMAN_EMIT_SYMBOL, 100), - (10, HUFFMAN_EMIT_SYMBOL, 100), - (15, HUFFMAN_EMIT_SYMBOL, 100), - (24, HUFFMAN_EMIT_SYMBOL, 100), - (31, HUFFMAN_EMIT_SYMBOL, 100), - (41, HUFFMAN_EMIT_SYMBOL, 100), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 100), - (3, HUFFMAN_EMIT_SYMBOL, 102), - (6, HUFFMAN_EMIT_SYMBOL, 102), - (10, HUFFMAN_EMIT_SYMBOL, 102), - (15, HUFFMAN_EMIT_SYMBOL, 102), - (24, HUFFMAN_EMIT_SYMBOL, 102), - (31, HUFFMAN_EMIT_SYMBOL, 102), - (41, HUFFMAN_EMIT_SYMBOL, 102), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 102), - - # Node 30 - (3, HUFFMAN_EMIT_SYMBOL, 103), - (6, HUFFMAN_EMIT_SYMBOL, 103), - (10, HUFFMAN_EMIT_SYMBOL, 103), - (15, HUFFMAN_EMIT_SYMBOL, 103), - (24, HUFFMAN_EMIT_SYMBOL, 103), - (31, HUFFMAN_EMIT_SYMBOL, 103), - (41, HUFFMAN_EMIT_SYMBOL, 103), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 103), - (3, HUFFMAN_EMIT_SYMBOL, 104), - (6, HUFFMAN_EMIT_SYMBOL, 104), - (10, HUFFMAN_EMIT_SYMBOL, 104), - (15, HUFFMAN_EMIT_SYMBOL, 104), - (24, HUFFMAN_EMIT_SYMBOL, 104), - (31, HUFFMAN_EMIT_SYMBOL, 104), - (41, HUFFMAN_EMIT_SYMBOL, 104), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 104), - - # Node 31 - (1, HUFFMAN_EMIT_SYMBOL, 108), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (1, HUFFMAN_EMIT_SYMBOL, 109), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (1, HUFFMAN_EMIT_SYMBOL, 110), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (1, HUFFMAN_EMIT_SYMBOL, 112), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - (1, HUFFMAN_EMIT_SYMBOL, 114), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (1, HUFFMAN_EMIT_SYMBOL, 117), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 32 - (2, HUFFMAN_EMIT_SYMBOL, 108), - (9, HUFFMAN_EMIT_SYMBOL, 108), - (23, HUFFMAN_EMIT_SYMBOL, 108), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (2, HUFFMAN_EMIT_SYMBOL, 109), - (9, HUFFMAN_EMIT_SYMBOL, 109), - (23, HUFFMAN_EMIT_SYMBOL, 109), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - (2, HUFFMAN_EMIT_SYMBOL, 110), - (9, HUFFMAN_EMIT_SYMBOL, 110), - (23, HUFFMAN_EMIT_SYMBOL, 110), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (2, HUFFMAN_EMIT_SYMBOL, 112), - (9, HUFFMAN_EMIT_SYMBOL, 112), - (23, HUFFMAN_EMIT_SYMBOL, 112), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - - # Node 33 - (3, HUFFMAN_EMIT_SYMBOL, 108), - (6, HUFFMAN_EMIT_SYMBOL, 108), - (10, HUFFMAN_EMIT_SYMBOL, 108), - (15, HUFFMAN_EMIT_SYMBOL, 108), - (24, HUFFMAN_EMIT_SYMBOL, 108), - (31, HUFFMAN_EMIT_SYMBOL, 108), - (41, HUFFMAN_EMIT_SYMBOL, 108), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 108), - (3, HUFFMAN_EMIT_SYMBOL, 109), - (6, HUFFMAN_EMIT_SYMBOL, 109), - (10, HUFFMAN_EMIT_SYMBOL, 109), - (15, HUFFMAN_EMIT_SYMBOL, 109), - (24, HUFFMAN_EMIT_SYMBOL, 109), - (31, HUFFMAN_EMIT_SYMBOL, 109), - (41, HUFFMAN_EMIT_SYMBOL, 109), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 109), - - # Node 34 - (3, HUFFMAN_EMIT_SYMBOL, 110), - (6, HUFFMAN_EMIT_SYMBOL, 110), - (10, HUFFMAN_EMIT_SYMBOL, 110), - (15, HUFFMAN_EMIT_SYMBOL, 110), - (24, HUFFMAN_EMIT_SYMBOL, 110), - (31, HUFFMAN_EMIT_SYMBOL, 110), - (41, HUFFMAN_EMIT_SYMBOL, 110), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 110), - (3, HUFFMAN_EMIT_SYMBOL, 112), - (6, HUFFMAN_EMIT_SYMBOL, 112), - (10, HUFFMAN_EMIT_SYMBOL, 112), - (15, HUFFMAN_EMIT_SYMBOL, 112), - (24, HUFFMAN_EMIT_SYMBOL, 112), - (31, HUFFMAN_EMIT_SYMBOL, 112), - (41, HUFFMAN_EMIT_SYMBOL, 112), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 112), - - # Node 35 - (2, HUFFMAN_EMIT_SYMBOL, 114), - (9, HUFFMAN_EMIT_SYMBOL, 114), - (23, HUFFMAN_EMIT_SYMBOL, 114), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (2, HUFFMAN_EMIT_SYMBOL, 117), - (9, HUFFMAN_EMIT_SYMBOL, 117), - (23, HUFFMAN_EMIT_SYMBOL, 117), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - (1, HUFFMAN_EMIT_SYMBOL, 58), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (1, HUFFMAN_EMIT_SYMBOL, 66), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (1, HUFFMAN_EMIT_SYMBOL, 67), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (1, HUFFMAN_EMIT_SYMBOL, 68), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 36 - (3, HUFFMAN_EMIT_SYMBOL, 114), - (6, HUFFMAN_EMIT_SYMBOL, 114), - (10, HUFFMAN_EMIT_SYMBOL, 114), - (15, HUFFMAN_EMIT_SYMBOL, 114), - (24, HUFFMAN_EMIT_SYMBOL, 114), - (31, HUFFMAN_EMIT_SYMBOL, 114), - (41, HUFFMAN_EMIT_SYMBOL, 114), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 114), - (3, HUFFMAN_EMIT_SYMBOL, 117), - (6, HUFFMAN_EMIT_SYMBOL, 117), - (10, HUFFMAN_EMIT_SYMBOL, 117), - (15, HUFFMAN_EMIT_SYMBOL, 117), - (24, HUFFMAN_EMIT_SYMBOL, 117), - (31, HUFFMAN_EMIT_SYMBOL, 117), - (41, HUFFMAN_EMIT_SYMBOL, 117), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 117), - - # Node 37 - (2, HUFFMAN_EMIT_SYMBOL, 58), - (9, HUFFMAN_EMIT_SYMBOL, 58), - (23, HUFFMAN_EMIT_SYMBOL, 58), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (2, HUFFMAN_EMIT_SYMBOL, 66), - (9, HUFFMAN_EMIT_SYMBOL, 66), - (23, HUFFMAN_EMIT_SYMBOL, 66), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - (2, HUFFMAN_EMIT_SYMBOL, 67), - (9, HUFFMAN_EMIT_SYMBOL, 67), - (23, HUFFMAN_EMIT_SYMBOL, 67), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (2, HUFFMAN_EMIT_SYMBOL, 68), - (9, HUFFMAN_EMIT_SYMBOL, 68), - (23, HUFFMAN_EMIT_SYMBOL, 68), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 38 - (3, HUFFMAN_EMIT_SYMBOL, 58), - (6, HUFFMAN_EMIT_SYMBOL, 58), - (10, HUFFMAN_EMIT_SYMBOL, 58), - (15, HUFFMAN_EMIT_SYMBOL, 58), - (24, HUFFMAN_EMIT_SYMBOL, 58), - (31, HUFFMAN_EMIT_SYMBOL, 58), - (41, HUFFMAN_EMIT_SYMBOL, 58), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 58), - (3, HUFFMAN_EMIT_SYMBOL, 66), - (6, HUFFMAN_EMIT_SYMBOL, 66), - (10, HUFFMAN_EMIT_SYMBOL, 66), - (15, HUFFMAN_EMIT_SYMBOL, 66), - (24, HUFFMAN_EMIT_SYMBOL, 66), - (31, HUFFMAN_EMIT_SYMBOL, 66), - (41, HUFFMAN_EMIT_SYMBOL, 66), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 66), - - # Node 39 - (3, HUFFMAN_EMIT_SYMBOL, 67), - (6, HUFFMAN_EMIT_SYMBOL, 67), - (10, HUFFMAN_EMIT_SYMBOL, 67), - (15, HUFFMAN_EMIT_SYMBOL, 67), - (24, HUFFMAN_EMIT_SYMBOL, 67), - (31, HUFFMAN_EMIT_SYMBOL, 67), - (41, HUFFMAN_EMIT_SYMBOL, 67), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 67), - (3, HUFFMAN_EMIT_SYMBOL, 68), - (6, HUFFMAN_EMIT_SYMBOL, 68), - (10, HUFFMAN_EMIT_SYMBOL, 68), - (15, HUFFMAN_EMIT_SYMBOL, 68), - (24, HUFFMAN_EMIT_SYMBOL, 68), - (31, HUFFMAN_EMIT_SYMBOL, 68), - (41, HUFFMAN_EMIT_SYMBOL, 68), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 68), - - # Node 40 - (44, 0, 0), - (45, 0, 0), - (47, 0, 0), - (48, 0, 0), - (51, 0, 0), - (52, 0, 0), - (54, 0, 0), - (55, 0, 0), - (59, 0, 0), - (60, 0, 0), - (62, 0, 0), - (63, 0, 0), - (66, 0, 0), - (67, 0, 0), - (69, 0, 0), - (72, HUFFMAN_COMPLETE, 0), - - # Node 41 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 42 - (1, HUFFMAN_EMIT_SYMBOL, 69), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (1, HUFFMAN_EMIT_SYMBOL, 70), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (1, HUFFMAN_EMIT_SYMBOL, 71), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (1, HUFFMAN_EMIT_SYMBOL, 72), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - (1, HUFFMAN_EMIT_SYMBOL, 73), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (1, HUFFMAN_EMIT_SYMBOL, 74), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (1, HUFFMAN_EMIT_SYMBOL, 75), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (1, HUFFMAN_EMIT_SYMBOL, 76), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 43 - (2, HUFFMAN_EMIT_SYMBOL, 69), - (9, HUFFMAN_EMIT_SYMBOL, 69), - (23, HUFFMAN_EMIT_SYMBOL, 69), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (2, HUFFMAN_EMIT_SYMBOL, 70), - (9, HUFFMAN_EMIT_SYMBOL, 70), - (23, HUFFMAN_EMIT_SYMBOL, 70), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - (2, HUFFMAN_EMIT_SYMBOL, 71), - (9, HUFFMAN_EMIT_SYMBOL, 71), - (23, HUFFMAN_EMIT_SYMBOL, 71), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (2, HUFFMAN_EMIT_SYMBOL, 72), - (9, HUFFMAN_EMIT_SYMBOL, 72), - (23, HUFFMAN_EMIT_SYMBOL, 72), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - - # Node 44 - (3, HUFFMAN_EMIT_SYMBOL, 69), - (6, HUFFMAN_EMIT_SYMBOL, 69), - (10, HUFFMAN_EMIT_SYMBOL, 69), - (15, HUFFMAN_EMIT_SYMBOL, 69), - (24, HUFFMAN_EMIT_SYMBOL, 69), - (31, HUFFMAN_EMIT_SYMBOL, 69), - (41, HUFFMAN_EMIT_SYMBOL, 69), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 69), - (3, HUFFMAN_EMIT_SYMBOL, 70), - (6, HUFFMAN_EMIT_SYMBOL, 70), - (10, HUFFMAN_EMIT_SYMBOL, 70), - (15, HUFFMAN_EMIT_SYMBOL, 70), - (24, HUFFMAN_EMIT_SYMBOL, 70), - (31, HUFFMAN_EMIT_SYMBOL, 70), - (41, HUFFMAN_EMIT_SYMBOL, 70), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 70), - - # Node 45 - (3, HUFFMAN_EMIT_SYMBOL, 71), - (6, HUFFMAN_EMIT_SYMBOL, 71), - (10, HUFFMAN_EMIT_SYMBOL, 71), - (15, HUFFMAN_EMIT_SYMBOL, 71), - (24, HUFFMAN_EMIT_SYMBOL, 71), - (31, HUFFMAN_EMIT_SYMBOL, 71), - (41, HUFFMAN_EMIT_SYMBOL, 71), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 71), - (3, HUFFMAN_EMIT_SYMBOL, 72), - (6, HUFFMAN_EMIT_SYMBOL, 72), - (10, HUFFMAN_EMIT_SYMBOL, 72), - (15, HUFFMAN_EMIT_SYMBOL, 72), - (24, HUFFMAN_EMIT_SYMBOL, 72), - (31, HUFFMAN_EMIT_SYMBOL, 72), - (41, HUFFMAN_EMIT_SYMBOL, 72), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 72), - - # Node 46 - (2, HUFFMAN_EMIT_SYMBOL, 73), - (9, HUFFMAN_EMIT_SYMBOL, 73), - (23, HUFFMAN_EMIT_SYMBOL, 73), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (2, HUFFMAN_EMIT_SYMBOL, 74), - (9, HUFFMAN_EMIT_SYMBOL, 74), - (23, HUFFMAN_EMIT_SYMBOL, 74), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - (2, HUFFMAN_EMIT_SYMBOL, 75), - (9, HUFFMAN_EMIT_SYMBOL, 75), - (23, HUFFMAN_EMIT_SYMBOL, 75), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (2, HUFFMAN_EMIT_SYMBOL, 76), - (9, HUFFMAN_EMIT_SYMBOL, 76), - (23, HUFFMAN_EMIT_SYMBOL, 76), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 47 - (3, HUFFMAN_EMIT_SYMBOL, 73), - (6, HUFFMAN_EMIT_SYMBOL, 73), - (10, HUFFMAN_EMIT_SYMBOL, 73), - (15, HUFFMAN_EMIT_SYMBOL, 73), - (24, HUFFMAN_EMIT_SYMBOL, 73), - (31, HUFFMAN_EMIT_SYMBOL, 73), - (41, HUFFMAN_EMIT_SYMBOL, 73), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 73), - (3, HUFFMAN_EMIT_SYMBOL, 74), - (6, HUFFMAN_EMIT_SYMBOL, 74), - (10, HUFFMAN_EMIT_SYMBOL, 74), - (15, HUFFMAN_EMIT_SYMBOL, 74), - (24, HUFFMAN_EMIT_SYMBOL, 74), - (31, HUFFMAN_EMIT_SYMBOL, 74), - (41, HUFFMAN_EMIT_SYMBOL, 74), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 74), - - # Node 48 - (3, HUFFMAN_EMIT_SYMBOL, 75), - (6, HUFFMAN_EMIT_SYMBOL, 75), - (10, HUFFMAN_EMIT_SYMBOL, 75), - (15, HUFFMAN_EMIT_SYMBOL, 75), - (24, HUFFMAN_EMIT_SYMBOL, 75), - (31, HUFFMAN_EMIT_SYMBOL, 75), - (41, HUFFMAN_EMIT_SYMBOL, 75), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 75), - (3, HUFFMAN_EMIT_SYMBOL, 76), - (6, HUFFMAN_EMIT_SYMBOL, 76), - (10, HUFFMAN_EMIT_SYMBOL, 76), - (15, HUFFMAN_EMIT_SYMBOL, 76), - (24, HUFFMAN_EMIT_SYMBOL, 76), - (31, HUFFMAN_EMIT_SYMBOL, 76), - (41, HUFFMAN_EMIT_SYMBOL, 76), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 76), - - # Node 49 - (1, HUFFMAN_EMIT_SYMBOL, 77), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (1, HUFFMAN_EMIT_SYMBOL, 78), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (1, HUFFMAN_EMIT_SYMBOL, 79), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (1, HUFFMAN_EMIT_SYMBOL, 80), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - (1, HUFFMAN_EMIT_SYMBOL, 81), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (1, HUFFMAN_EMIT_SYMBOL, 82), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (1, HUFFMAN_EMIT_SYMBOL, 83), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (1, HUFFMAN_EMIT_SYMBOL, 84), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 50 - (2, HUFFMAN_EMIT_SYMBOL, 77), - (9, HUFFMAN_EMIT_SYMBOL, 77), - (23, HUFFMAN_EMIT_SYMBOL, 77), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (2, HUFFMAN_EMIT_SYMBOL, 78), - (9, HUFFMAN_EMIT_SYMBOL, 78), - (23, HUFFMAN_EMIT_SYMBOL, 78), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - (2, HUFFMAN_EMIT_SYMBOL, 79), - (9, HUFFMAN_EMIT_SYMBOL, 79), - (23, HUFFMAN_EMIT_SYMBOL, 79), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (2, HUFFMAN_EMIT_SYMBOL, 80), - (9, HUFFMAN_EMIT_SYMBOL, 80), - (23, HUFFMAN_EMIT_SYMBOL, 80), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - - # Node 51 - (3, HUFFMAN_EMIT_SYMBOL, 77), - (6, HUFFMAN_EMIT_SYMBOL, 77), - (10, HUFFMAN_EMIT_SYMBOL, 77), - (15, HUFFMAN_EMIT_SYMBOL, 77), - (24, HUFFMAN_EMIT_SYMBOL, 77), - (31, HUFFMAN_EMIT_SYMBOL, 77), - (41, HUFFMAN_EMIT_SYMBOL, 77), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 77), - (3, HUFFMAN_EMIT_SYMBOL, 78), - (6, HUFFMAN_EMIT_SYMBOL, 78), - (10, HUFFMAN_EMIT_SYMBOL, 78), - (15, HUFFMAN_EMIT_SYMBOL, 78), - (24, HUFFMAN_EMIT_SYMBOL, 78), - (31, HUFFMAN_EMIT_SYMBOL, 78), - (41, HUFFMAN_EMIT_SYMBOL, 78), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 78), - - # Node 52 - (3, HUFFMAN_EMIT_SYMBOL, 79), - (6, HUFFMAN_EMIT_SYMBOL, 79), - (10, HUFFMAN_EMIT_SYMBOL, 79), - (15, HUFFMAN_EMIT_SYMBOL, 79), - (24, HUFFMAN_EMIT_SYMBOL, 79), - (31, HUFFMAN_EMIT_SYMBOL, 79), - (41, HUFFMAN_EMIT_SYMBOL, 79), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 79), - (3, HUFFMAN_EMIT_SYMBOL, 80), - (6, HUFFMAN_EMIT_SYMBOL, 80), - (10, HUFFMAN_EMIT_SYMBOL, 80), - (15, HUFFMAN_EMIT_SYMBOL, 80), - (24, HUFFMAN_EMIT_SYMBOL, 80), - (31, HUFFMAN_EMIT_SYMBOL, 80), - (41, HUFFMAN_EMIT_SYMBOL, 80), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 80), - - # Node 53 - (2, HUFFMAN_EMIT_SYMBOL, 81), - (9, HUFFMAN_EMIT_SYMBOL, 81), - (23, HUFFMAN_EMIT_SYMBOL, 81), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (2, HUFFMAN_EMIT_SYMBOL, 82), - (9, HUFFMAN_EMIT_SYMBOL, 82), - (23, HUFFMAN_EMIT_SYMBOL, 82), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - (2, HUFFMAN_EMIT_SYMBOL, 83), - (9, HUFFMAN_EMIT_SYMBOL, 83), - (23, HUFFMAN_EMIT_SYMBOL, 83), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (2, HUFFMAN_EMIT_SYMBOL, 84), - (9, HUFFMAN_EMIT_SYMBOL, 84), - (23, HUFFMAN_EMIT_SYMBOL, 84), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 54 - (3, HUFFMAN_EMIT_SYMBOL, 81), - (6, HUFFMAN_EMIT_SYMBOL, 81), - (10, HUFFMAN_EMIT_SYMBOL, 81), - (15, HUFFMAN_EMIT_SYMBOL, 81), - (24, HUFFMAN_EMIT_SYMBOL, 81), - (31, HUFFMAN_EMIT_SYMBOL, 81), - (41, HUFFMAN_EMIT_SYMBOL, 81), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 81), - (3, HUFFMAN_EMIT_SYMBOL, 82), - (6, HUFFMAN_EMIT_SYMBOL, 82), - (10, HUFFMAN_EMIT_SYMBOL, 82), - (15, HUFFMAN_EMIT_SYMBOL, 82), - (24, HUFFMAN_EMIT_SYMBOL, 82), - (31, HUFFMAN_EMIT_SYMBOL, 82), - (41, HUFFMAN_EMIT_SYMBOL, 82), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 82), - - # Node 55 - (3, HUFFMAN_EMIT_SYMBOL, 83), - (6, HUFFMAN_EMIT_SYMBOL, 83), - (10, HUFFMAN_EMIT_SYMBOL, 83), - (15, HUFFMAN_EMIT_SYMBOL, 83), - (24, HUFFMAN_EMIT_SYMBOL, 83), - (31, HUFFMAN_EMIT_SYMBOL, 83), - (41, HUFFMAN_EMIT_SYMBOL, 83), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 83), - (3, HUFFMAN_EMIT_SYMBOL, 84), - (6, HUFFMAN_EMIT_SYMBOL, 84), - (10, HUFFMAN_EMIT_SYMBOL, 84), - (15, HUFFMAN_EMIT_SYMBOL, 84), - (24, HUFFMAN_EMIT_SYMBOL, 84), - (31, HUFFMAN_EMIT_SYMBOL, 84), - (41, HUFFMAN_EMIT_SYMBOL, 84), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 84), - - # Node 56 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - (70, 0, 0), - (71, 0, 0), - (73, 0, 0), - (74, HUFFMAN_COMPLETE, 0), - - # Node 57 - (1, HUFFMAN_EMIT_SYMBOL, 85), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (1, HUFFMAN_EMIT_SYMBOL, 86), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (1, HUFFMAN_EMIT_SYMBOL, 87), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (1, HUFFMAN_EMIT_SYMBOL, 89), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - (1, HUFFMAN_EMIT_SYMBOL, 106), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (1, HUFFMAN_EMIT_SYMBOL, 107), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (1, HUFFMAN_EMIT_SYMBOL, 113), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (1, HUFFMAN_EMIT_SYMBOL, 118), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 58 - (2, HUFFMAN_EMIT_SYMBOL, 85), - (9, HUFFMAN_EMIT_SYMBOL, 85), - (23, HUFFMAN_EMIT_SYMBOL, 85), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (2, HUFFMAN_EMIT_SYMBOL, 86), - (9, HUFFMAN_EMIT_SYMBOL, 86), - (23, HUFFMAN_EMIT_SYMBOL, 86), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - (2, HUFFMAN_EMIT_SYMBOL, 87), - (9, HUFFMAN_EMIT_SYMBOL, 87), - (23, HUFFMAN_EMIT_SYMBOL, 87), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (2, HUFFMAN_EMIT_SYMBOL, 89), - (9, HUFFMAN_EMIT_SYMBOL, 89), - (23, HUFFMAN_EMIT_SYMBOL, 89), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - - # Node 59 - (3, HUFFMAN_EMIT_SYMBOL, 85), - (6, HUFFMAN_EMIT_SYMBOL, 85), - (10, HUFFMAN_EMIT_SYMBOL, 85), - (15, HUFFMAN_EMIT_SYMBOL, 85), - (24, HUFFMAN_EMIT_SYMBOL, 85), - (31, HUFFMAN_EMIT_SYMBOL, 85), - (41, HUFFMAN_EMIT_SYMBOL, 85), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 85), - (3, HUFFMAN_EMIT_SYMBOL, 86), - (6, HUFFMAN_EMIT_SYMBOL, 86), - (10, HUFFMAN_EMIT_SYMBOL, 86), - (15, HUFFMAN_EMIT_SYMBOL, 86), - (24, HUFFMAN_EMIT_SYMBOL, 86), - (31, HUFFMAN_EMIT_SYMBOL, 86), - (41, HUFFMAN_EMIT_SYMBOL, 86), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 86), - - # Node 60 - (3, HUFFMAN_EMIT_SYMBOL, 87), - (6, HUFFMAN_EMIT_SYMBOL, 87), - (10, HUFFMAN_EMIT_SYMBOL, 87), - (15, HUFFMAN_EMIT_SYMBOL, 87), - (24, HUFFMAN_EMIT_SYMBOL, 87), - (31, HUFFMAN_EMIT_SYMBOL, 87), - (41, HUFFMAN_EMIT_SYMBOL, 87), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 87), - (3, HUFFMAN_EMIT_SYMBOL, 89), - (6, HUFFMAN_EMIT_SYMBOL, 89), - (10, HUFFMAN_EMIT_SYMBOL, 89), - (15, HUFFMAN_EMIT_SYMBOL, 89), - (24, HUFFMAN_EMIT_SYMBOL, 89), - (31, HUFFMAN_EMIT_SYMBOL, 89), - (41, HUFFMAN_EMIT_SYMBOL, 89), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 89), - - # Node 61 - (2, HUFFMAN_EMIT_SYMBOL, 106), - (9, HUFFMAN_EMIT_SYMBOL, 106), - (23, HUFFMAN_EMIT_SYMBOL, 106), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (2, HUFFMAN_EMIT_SYMBOL, 107), - (9, HUFFMAN_EMIT_SYMBOL, 107), - (23, HUFFMAN_EMIT_SYMBOL, 107), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - (2, HUFFMAN_EMIT_SYMBOL, 113), - (9, HUFFMAN_EMIT_SYMBOL, 113), - (23, HUFFMAN_EMIT_SYMBOL, 113), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (2, HUFFMAN_EMIT_SYMBOL, 118), - (9, HUFFMAN_EMIT_SYMBOL, 118), - (23, HUFFMAN_EMIT_SYMBOL, 118), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 62 - (3, HUFFMAN_EMIT_SYMBOL, 106), - (6, HUFFMAN_EMIT_SYMBOL, 106), - (10, HUFFMAN_EMIT_SYMBOL, 106), - (15, HUFFMAN_EMIT_SYMBOL, 106), - (24, HUFFMAN_EMIT_SYMBOL, 106), - (31, HUFFMAN_EMIT_SYMBOL, 106), - (41, HUFFMAN_EMIT_SYMBOL, 106), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 106), - (3, HUFFMAN_EMIT_SYMBOL, 107), - (6, HUFFMAN_EMIT_SYMBOL, 107), - (10, HUFFMAN_EMIT_SYMBOL, 107), - (15, HUFFMAN_EMIT_SYMBOL, 107), - (24, HUFFMAN_EMIT_SYMBOL, 107), - (31, HUFFMAN_EMIT_SYMBOL, 107), - (41, HUFFMAN_EMIT_SYMBOL, 107), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 107), - - # Node 63 - (3, HUFFMAN_EMIT_SYMBOL, 113), - (6, HUFFMAN_EMIT_SYMBOL, 113), - (10, HUFFMAN_EMIT_SYMBOL, 113), - (15, HUFFMAN_EMIT_SYMBOL, 113), - (24, HUFFMAN_EMIT_SYMBOL, 113), - (31, HUFFMAN_EMIT_SYMBOL, 113), - (41, HUFFMAN_EMIT_SYMBOL, 113), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 113), - (3, HUFFMAN_EMIT_SYMBOL, 118), - (6, HUFFMAN_EMIT_SYMBOL, 118), - (10, HUFFMAN_EMIT_SYMBOL, 118), - (15, HUFFMAN_EMIT_SYMBOL, 118), - (24, HUFFMAN_EMIT_SYMBOL, 118), - (31, HUFFMAN_EMIT_SYMBOL, 118), - (41, HUFFMAN_EMIT_SYMBOL, 118), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 118), - - # Node 64 - (1, HUFFMAN_EMIT_SYMBOL, 119), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (1, HUFFMAN_EMIT_SYMBOL, 120), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (1, HUFFMAN_EMIT_SYMBOL, 121), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (1, HUFFMAN_EMIT_SYMBOL, 122), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (75, 0, 0), - (78, 0, 0), - - # Node 65 - (2, HUFFMAN_EMIT_SYMBOL, 119), - (9, HUFFMAN_EMIT_SYMBOL, 119), - (23, HUFFMAN_EMIT_SYMBOL, 119), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (2, HUFFMAN_EMIT_SYMBOL, 120), - (9, HUFFMAN_EMIT_SYMBOL, 120), - (23, HUFFMAN_EMIT_SYMBOL, 120), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - (2, HUFFMAN_EMIT_SYMBOL, 121), - (9, HUFFMAN_EMIT_SYMBOL, 121), - (23, HUFFMAN_EMIT_SYMBOL, 121), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (2, HUFFMAN_EMIT_SYMBOL, 122), - (9, HUFFMAN_EMIT_SYMBOL, 122), - (23, HUFFMAN_EMIT_SYMBOL, 122), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - - # Node 66 - (3, HUFFMAN_EMIT_SYMBOL, 119), - (6, HUFFMAN_EMIT_SYMBOL, 119), - (10, HUFFMAN_EMIT_SYMBOL, 119), - (15, HUFFMAN_EMIT_SYMBOL, 119), - (24, HUFFMAN_EMIT_SYMBOL, 119), - (31, HUFFMAN_EMIT_SYMBOL, 119), - (41, HUFFMAN_EMIT_SYMBOL, 119), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 119), - (3, HUFFMAN_EMIT_SYMBOL, 120), - (6, HUFFMAN_EMIT_SYMBOL, 120), - (10, HUFFMAN_EMIT_SYMBOL, 120), - (15, HUFFMAN_EMIT_SYMBOL, 120), - (24, HUFFMAN_EMIT_SYMBOL, 120), - (31, HUFFMAN_EMIT_SYMBOL, 120), - (41, HUFFMAN_EMIT_SYMBOL, 120), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 120), - - # Node 67 - (3, HUFFMAN_EMIT_SYMBOL, 121), - (6, HUFFMAN_EMIT_SYMBOL, 121), - (10, HUFFMAN_EMIT_SYMBOL, 121), - (15, HUFFMAN_EMIT_SYMBOL, 121), - (24, HUFFMAN_EMIT_SYMBOL, 121), - (31, HUFFMAN_EMIT_SYMBOL, 121), - (41, HUFFMAN_EMIT_SYMBOL, 121), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 121), - (3, HUFFMAN_EMIT_SYMBOL, 122), - (6, HUFFMAN_EMIT_SYMBOL, 122), - (10, HUFFMAN_EMIT_SYMBOL, 122), - (15, HUFFMAN_EMIT_SYMBOL, 122), - (24, HUFFMAN_EMIT_SYMBOL, 122), - (31, HUFFMAN_EMIT_SYMBOL, 122), - (41, HUFFMAN_EMIT_SYMBOL, 122), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 122), - - # Node 68 - (1, HUFFMAN_EMIT_SYMBOL, 38), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (1, HUFFMAN_EMIT_SYMBOL, 42), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (1, HUFFMAN_EMIT_SYMBOL, 44), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (1, HUFFMAN_EMIT_SYMBOL, 59), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - (1, HUFFMAN_EMIT_SYMBOL, 88), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (1, HUFFMAN_EMIT_SYMBOL, 90), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (76, 0, 0), - (77, 0, 0), - (79, 0, 0), - (81, 0, 0), - - # Node 69 - (2, HUFFMAN_EMIT_SYMBOL, 38), - (9, HUFFMAN_EMIT_SYMBOL, 38), - (23, HUFFMAN_EMIT_SYMBOL, 38), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (2, HUFFMAN_EMIT_SYMBOL, 42), - (9, HUFFMAN_EMIT_SYMBOL, 42), - (23, HUFFMAN_EMIT_SYMBOL, 42), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - (2, HUFFMAN_EMIT_SYMBOL, 44), - (9, HUFFMAN_EMIT_SYMBOL, 44), - (23, HUFFMAN_EMIT_SYMBOL, 44), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (2, HUFFMAN_EMIT_SYMBOL, 59), - (9, HUFFMAN_EMIT_SYMBOL, 59), - (23, HUFFMAN_EMIT_SYMBOL, 59), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - - # Node 70 - (3, HUFFMAN_EMIT_SYMBOL, 38), - (6, HUFFMAN_EMIT_SYMBOL, 38), - (10, HUFFMAN_EMIT_SYMBOL, 38), - (15, HUFFMAN_EMIT_SYMBOL, 38), - (24, HUFFMAN_EMIT_SYMBOL, 38), - (31, HUFFMAN_EMIT_SYMBOL, 38), - (41, HUFFMAN_EMIT_SYMBOL, 38), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 38), - (3, HUFFMAN_EMIT_SYMBOL, 42), - (6, HUFFMAN_EMIT_SYMBOL, 42), - (10, HUFFMAN_EMIT_SYMBOL, 42), - (15, HUFFMAN_EMIT_SYMBOL, 42), - (24, HUFFMAN_EMIT_SYMBOL, 42), - (31, HUFFMAN_EMIT_SYMBOL, 42), - (41, HUFFMAN_EMIT_SYMBOL, 42), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 42), - - # Node 71 - (3, HUFFMAN_EMIT_SYMBOL, 44), - (6, HUFFMAN_EMIT_SYMBOL, 44), - (10, HUFFMAN_EMIT_SYMBOL, 44), - (15, HUFFMAN_EMIT_SYMBOL, 44), - (24, HUFFMAN_EMIT_SYMBOL, 44), - (31, HUFFMAN_EMIT_SYMBOL, 44), - (41, HUFFMAN_EMIT_SYMBOL, 44), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 44), - (3, HUFFMAN_EMIT_SYMBOL, 59), - (6, HUFFMAN_EMIT_SYMBOL, 59), - (10, HUFFMAN_EMIT_SYMBOL, 59), - (15, HUFFMAN_EMIT_SYMBOL, 59), - (24, HUFFMAN_EMIT_SYMBOL, 59), - (31, HUFFMAN_EMIT_SYMBOL, 59), - (41, HUFFMAN_EMIT_SYMBOL, 59), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 59), - - # Node 72 - (2, HUFFMAN_EMIT_SYMBOL, 88), - (9, HUFFMAN_EMIT_SYMBOL, 88), - (23, HUFFMAN_EMIT_SYMBOL, 88), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (2, HUFFMAN_EMIT_SYMBOL, 90), - (9, HUFFMAN_EMIT_SYMBOL, 90), - (23, HUFFMAN_EMIT_SYMBOL, 90), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (80, 0, 0), - (82, 0, 0), - (84, 0, 0), - - # Node 73 - (3, HUFFMAN_EMIT_SYMBOL, 88), - (6, HUFFMAN_EMIT_SYMBOL, 88), - (10, HUFFMAN_EMIT_SYMBOL, 88), - (15, HUFFMAN_EMIT_SYMBOL, 88), - (24, HUFFMAN_EMIT_SYMBOL, 88), - (31, HUFFMAN_EMIT_SYMBOL, 88), - (41, HUFFMAN_EMIT_SYMBOL, 88), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 88), - (3, HUFFMAN_EMIT_SYMBOL, 90), - (6, HUFFMAN_EMIT_SYMBOL, 90), - (10, HUFFMAN_EMIT_SYMBOL, 90), - (15, HUFFMAN_EMIT_SYMBOL, 90), - (24, HUFFMAN_EMIT_SYMBOL, 90), - (31, HUFFMAN_EMIT_SYMBOL, 90), - (41, HUFFMAN_EMIT_SYMBOL, 90), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 90), - - # Node 74 - (1, HUFFMAN_EMIT_SYMBOL, 33), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (1, HUFFMAN_EMIT_SYMBOL, 34), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (1, HUFFMAN_EMIT_SYMBOL, 40), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (1, HUFFMAN_EMIT_SYMBOL, 41), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - (1, HUFFMAN_EMIT_SYMBOL, 63), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (83, 0, 0), - (85, 0, 0), - (88, 0, 0), - - # Node 75 - (2, HUFFMAN_EMIT_SYMBOL, 33), - (9, HUFFMAN_EMIT_SYMBOL, 33), - (23, HUFFMAN_EMIT_SYMBOL, 33), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (2, HUFFMAN_EMIT_SYMBOL, 34), - (9, HUFFMAN_EMIT_SYMBOL, 34), - (23, HUFFMAN_EMIT_SYMBOL, 34), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - (2, HUFFMAN_EMIT_SYMBOL, 40), - (9, HUFFMAN_EMIT_SYMBOL, 40), - (23, HUFFMAN_EMIT_SYMBOL, 40), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (2, HUFFMAN_EMIT_SYMBOL, 41), - (9, HUFFMAN_EMIT_SYMBOL, 41), - (23, HUFFMAN_EMIT_SYMBOL, 41), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - - # Node 76 - (3, HUFFMAN_EMIT_SYMBOL, 33), - (6, HUFFMAN_EMIT_SYMBOL, 33), - (10, HUFFMAN_EMIT_SYMBOL, 33), - (15, HUFFMAN_EMIT_SYMBOL, 33), - (24, HUFFMAN_EMIT_SYMBOL, 33), - (31, HUFFMAN_EMIT_SYMBOL, 33), - (41, HUFFMAN_EMIT_SYMBOL, 33), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 33), - (3, HUFFMAN_EMIT_SYMBOL, 34), - (6, HUFFMAN_EMIT_SYMBOL, 34), - (10, HUFFMAN_EMIT_SYMBOL, 34), - (15, HUFFMAN_EMIT_SYMBOL, 34), - (24, HUFFMAN_EMIT_SYMBOL, 34), - (31, HUFFMAN_EMIT_SYMBOL, 34), - (41, HUFFMAN_EMIT_SYMBOL, 34), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 34), - - # Node 77 - (3, HUFFMAN_EMIT_SYMBOL, 40), - (6, HUFFMAN_EMIT_SYMBOL, 40), - (10, HUFFMAN_EMIT_SYMBOL, 40), - (15, HUFFMAN_EMIT_SYMBOL, 40), - (24, HUFFMAN_EMIT_SYMBOL, 40), - (31, HUFFMAN_EMIT_SYMBOL, 40), - (41, HUFFMAN_EMIT_SYMBOL, 40), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 40), - (3, HUFFMAN_EMIT_SYMBOL, 41), - (6, HUFFMAN_EMIT_SYMBOL, 41), - (10, HUFFMAN_EMIT_SYMBOL, 41), - (15, HUFFMAN_EMIT_SYMBOL, 41), - (24, HUFFMAN_EMIT_SYMBOL, 41), - (31, HUFFMAN_EMIT_SYMBOL, 41), - (41, HUFFMAN_EMIT_SYMBOL, 41), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 41), - - # Node 78 - (2, HUFFMAN_EMIT_SYMBOL, 63), - (9, HUFFMAN_EMIT_SYMBOL, 63), - (23, HUFFMAN_EMIT_SYMBOL, 63), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (1, HUFFMAN_EMIT_SYMBOL, 39), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (1, HUFFMAN_EMIT_SYMBOL, 43), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - (1, HUFFMAN_EMIT_SYMBOL, 124), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - (86, 0, 0), - (87, 0, 0), - (89, 0, 0), - (90, 0, 0), - - # Node 79 - (3, HUFFMAN_EMIT_SYMBOL, 63), - (6, HUFFMAN_EMIT_SYMBOL, 63), - (10, HUFFMAN_EMIT_SYMBOL, 63), - (15, HUFFMAN_EMIT_SYMBOL, 63), - (24, HUFFMAN_EMIT_SYMBOL, 63), - (31, HUFFMAN_EMIT_SYMBOL, 63), - (41, HUFFMAN_EMIT_SYMBOL, 63), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 63), - (2, HUFFMAN_EMIT_SYMBOL, 39), - (9, HUFFMAN_EMIT_SYMBOL, 39), - (23, HUFFMAN_EMIT_SYMBOL, 39), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (2, HUFFMAN_EMIT_SYMBOL, 43), - (9, HUFFMAN_EMIT_SYMBOL, 43), - (23, HUFFMAN_EMIT_SYMBOL, 43), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - - # Node 80 - (3, HUFFMAN_EMIT_SYMBOL, 39), - (6, HUFFMAN_EMIT_SYMBOL, 39), - (10, HUFFMAN_EMIT_SYMBOL, 39), - (15, HUFFMAN_EMIT_SYMBOL, 39), - (24, HUFFMAN_EMIT_SYMBOL, 39), - (31, HUFFMAN_EMIT_SYMBOL, 39), - (41, HUFFMAN_EMIT_SYMBOL, 39), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 39), - (3, HUFFMAN_EMIT_SYMBOL, 43), - (6, HUFFMAN_EMIT_SYMBOL, 43), - (10, HUFFMAN_EMIT_SYMBOL, 43), - (15, HUFFMAN_EMIT_SYMBOL, 43), - (24, HUFFMAN_EMIT_SYMBOL, 43), - (31, HUFFMAN_EMIT_SYMBOL, 43), - (41, HUFFMAN_EMIT_SYMBOL, 43), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 43), - - # Node 81 - (2, HUFFMAN_EMIT_SYMBOL, 124), - (9, HUFFMAN_EMIT_SYMBOL, 124), - (23, HUFFMAN_EMIT_SYMBOL, 124), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (1, HUFFMAN_EMIT_SYMBOL, 35), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (1, HUFFMAN_EMIT_SYMBOL, 62), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (91, 0, 0), - (92, 0, 0), - - # Node 82 - (3, HUFFMAN_EMIT_SYMBOL, 124), - (6, HUFFMAN_EMIT_SYMBOL, 124), - (10, HUFFMAN_EMIT_SYMBOL, 124), - (15, HUFFMAN_EMIT_SYMBOL, 124), - (24, HUFFMAN_EMIT_SYMBOL, 124), - (31, HUFFMAN_EMIT_SYMBOL, 124), - (41, HUFFMAN_EMIT_SYMBOL, 124), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 124), - (2, HUFFMAN_EMIT_SYMBOL, 35), - (9, HUFFMAN_EMIT_SYMBOL, 35), - (23, HUFFMAN_EMIT_SYMBOL, 35), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (2, HUFFMAN_EMIT_SYMBOL, 62), - (9, HUFFMAN_EMIT_SYMBOL, 62), - (23, HUFFMAN_EMIT_SYMBOL, 62), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - - # Node 83 - (3, HUFFMAN_EMIT_SYMBOL, 35), - (6, HUFFMAN_EMIT_SYMBOL, 35), - (10, HUFFMAN_EMIT_SYMBOL, 35), - (15, HUFFMAN_EMIT_SYMBOL, 35), - (24, HUFFMAN_EMIT_SYMBOL, 35), - (31, HUFFMAN_EMIT_SYMBOL, 35), - (41, HUFFMAN_EMIT_SYMBOL, 35), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 35), - (3, HUFFMAN_EMIT_SYMBOL, 62), - (6, HUFFMAN_EMIT_SYMBOL, 62), - (10, HUFFMAN_EMIT_SYMBOL, 62), - (15, HUFFMAN_EMIT_SYMBOL, 62), - (24, HUFFMAN_EMIT_SYMBOL, 62), - (31, HUFFMAN_EMIT_SYMBOL, 62), - (41, HUFFMAN_EMIT_SYMBOL, 62), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 62), - - # Node 84 - (1, HUFFMAN_EMIT_SYMBOL, 0), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (1, HUFFMAN_EMIT_SYMBOL, 36), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (1, HUFFMAN_EMIT_SYMBOL, 64), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (1, HUFFMAN_EMIT_SYMBOL, 91), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - (1, HUFFMAN_EMIT_SYMBOL, 93), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (1, HUFFMAN_EMIT_SYMBOL, 126), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (93, 0, 0), - (94, 0, 0), - - # Node 85 - (2, HUFFMAN_EMIT_SYMBOL, 0), - (9, HUFFMAN_EMIT_SYMBOL, 0), - (23, HUFFMAN_EMIT_SYMBOL, 0), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (2, HUFFMAN_EMIT_SYMBOL, 36), - (9, HUFFMAN_EMIT_SYMBOL, 36), - (23, HUFFMAN_EMIT_SYMBOL, 36), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - (2, HUFFMAN_EMIT_SYMBOL, 64), - (9, HUFFMAN_EMIT_SYMBOL, 64), - (23, HUFFMAN_EMIT_SYMBOL, 64), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (2, HUFFMAN_EMIT_SYMBOL, 91), - (9, HUFFMAN_EMIT_SYMBOL, 91), - (23, HUFFMAN_EMIT_SYMBOL, 91), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - - # Node 86 - (3, HUFFMAN_EMIT_SYMBOL, 0), - (6, HUFFMAN_EMIT_SYMBOL, 0), - (10, HUFFMAN_EMIT_SYMBOL, 0), - (15, HUFFMAN_EMIT_SYMBOL, 0), - (24, HUFFMAN_EMIT_SYMBOL, 0), - (31, HUFFMAN_EMIT_SYMBOL, 0), - (41, HUFFMAN_EMIT_SYMBOL, 0), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 0), - (3, HUFFMAN_EMIT_SYMBOL, 36), - (6, HUFFMAN_EMIT_SYMBOL, 36), - (10, HUFFMAN_EMIT_SYMBOL, 36), - (15, HUFFMAN_EMIT_SYMBOL, 36), - (24, HUFFMAN_EMIT_SYMBOL, 36), - (31, HUFFMAN_EMIT_SYMBOL, 36), - (41, HUFFMAN_EMIT_SYMBOL, 36), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 36), - - # Node 87 - (3, HUFFMAN_EMIT_SYMBOL, 64), - (6, HUFFMAN_EMIT_SYMBOL, 64), - (10, HUFFMAN_EMIT_SYMBOL, 64), - (15, HUFFMAN_EMIT_SYMBOL, 64), - (24, HUFFMAN_EMIT_SYMBOL, 64), - (31, HUFFMAN_EMIT_SYMBOL, 64), - (41, HUFFMAN_EMIT_SYMBOL, 64), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 64), - (3, HUFFMAN_EMIT_SYMBOL, 91), - (6, HUFFMAN_EMIT_SYMBOL, 91), - (10, HUFFMAN_EMIT_SYMBOL, 91), - (15, HUFFMAN_EMIT_SYMBOL, 91), - (24, HUFFMAN_EMIT_SYMBOL, 91), - (31, HUFFMAN_EMIT_SYMBOL, 91), - (41, HUFFMAN_EMIT_SYMBOL, 91), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 91), - - # Node 88 - (2, HUFFMAN_EMIT_SYMBOL, 93), - (9, HUFFMAN_EMIT_SYMBOL, 93), - (23, HUFFMAN_EMIT_SYMBOL, 93), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (2, HUFFMAN_EMIT_SYMBOL, 126), - (9, HUFFMAN_EMIT_SYMBOL, 126), - (23, HUFFMAN_EMIT_SYMBOL, 126), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - (1, HUFFMAN_EMIT_SYMBOL, 94), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (1, HUFFMAN_EMIT_SYMBOL, 125), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (95, 0, 0), - - # Node 89 - (3, HUFFMAN_EMIT_SYMBOL, 93), - (6, HUFFMAN_EMIT_SYMBOL, 93), - (10, HUFFMAN_EMIT_SYMBOL, 93), - (15, HUFFMAN_EMIT_SYMBOL, 93), - (24, HUFFMAN_EMIT_SYMBOL, 93), - (31, HUFFMAN_EMIT_SYMBOL, 93), - (41, HUFFMAN_EMIT_SYMBOL, 93), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 93), - (3, HUFFMAN_EMIT_SYMBOL, 126), - (6, HUFFMAN_EMIT_SYMBOL, 126), - (10, HUFFMAN_EMIT_SYMBOL, 126), - (15, HUFFMAN_EMIT_SYMBOL, 126), - (24, HUFFMAN_EMIT_SYMBOL, 126), - (31, HUFFMAN_EMIT_SYMBOL, 126), - (41, HUFFMAN_EMIT_SYMBOL, 126), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 126), - - # Node 90 - (2, HUFFMAN_EMIT_SYMBOL, 94), - (9, HUFFMAN_EMIT_SYMBOL, 94), - (23, HUFFMAN_EMIT_SYMBOL, 94), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (2, HUFFMAN_EMIT_SYMBOL, 125), - (9, HUFFMAN_EMIT_SYMBOL, 125), - (23, HUFFMAN_EMIT_SYMBOL, 125), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - (1, HUFFMAN_EMIT_SYMBOL, 60), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (1, HUFFMAN_EMIT_SYMBOL, 96), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (1, HUFFMAN_EMIT_SYMBOL, 123), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (96, 0, 0), - (110, 0, 0), - - # Node 91 - (3, HUFFMAN_EMIT_SYMBOL, 94), - (6, HUFFMAN_EMIT_SYMBOL, 94), - (10, HUFFMAN_EMIT_SYMBOL, 94), - (15, HUFFMAN_EMIT_SYMBOL, 94), - (24, HUFFMAN_EMIT_SYMBOL, 94), - (31, HUFFMAN_EMIT_SYMBOL, 94), - (41, HUFFMAN_EMIT_SYMBOL, 94), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 94), - (3, HUFFMAN_EMIT_SYMBOL, 125), - (6, HUFFMAN_EMIT_SYMBOL, 125), - (10, HUFFMAN_EMIT_SYMBOL, 125), - (15, HUFFMAN_EMIT_SYMBOL, 125), - (24, HUFFMAN_EMIT_SYMBOL, 125), - (31, HUFFMAN_EMIT_SYMBOL, 125), - (41, HUFFMAN_EMIT_SYMBOL, 125), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 125), - - # Node 92 - (2, HUFFMAN_EMIT_SYMBOL, 60), - (9, HUFFMAN_EMIT_SYMBOL, 60), - (23, HUFFMAN_EMIT_SYMBOL, 60), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (2, HUFFMAN_EMIT_SYMBOL, 96), - (9, HUFFMAN_EMIT_SYMBOL, 96), - (23, HUFFMAN_EMIT_SYMBOL, 96), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - (2, HUFFMAN_EMIT_SYMBOL, 123), - (9, HUFFMAN_EMIT_SYMBOL, 123), - (23, HUFFMAN_EMIT_SYMBOL, 123), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (97, 0, 0), - (101, 0, 0), - (111, 0, 0), - (133, 0, 0), - - # Node 93 - (3, HUFFMAN_EMIT_SYMBOL, 60), - (6, HUFFMAN_EMIT_SYMBOL, 60), - (10, HUFFMAN_EMIT_SYMBOL, 60), - (15, HUFFMAN_EMIT_SYMBOL, 60), - (24, HUFFMAN_EMIT_SYMBOL, 60), - (31, HUFFMAN_EMIT_SYMBOL, 60), - (41, HUFFMAN_EMIT_SYMBOL, 60), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 60), - (3, HUFFMAN_EMIT_SYMBOL, 96), - (6, HUFFMAN_EMIT_SYMBOL, 96), - (10, HUFFMAN_EMIT_SYMBOL, 96), - (15, HUFFMAN_EMIT_SYMBOL, 96), - (24, HUFFMAN_EMIT_SYMBOL, 96), - (31, HUFFMAN_EMIT_SYMBOL, 96), - (41, HUFFMAN_EMIT_SYMBOL, 96), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 96), - - # Node 94 - (3, HUFFMAN_EMIT_SYMBOL, 123), - (6, HUFFMAN_EMIT_SYMBOL, 123), - (10, HUFFMAN_EMIT_SYMBOL, 123), - (15, HUFFMAN_EMIT_SYMBOL, 123), - (24, HUFFMAN_EMIT_SYMBOL, 123), - (31, HUFFMAN_EMIT_SYMBOL, 123), - (41, HUFFMAN_EMIT_SYMBOL, 123), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 123), - (98, 0, 0), - (99, 0, 0), - (102, 0, 0), - (105, 0, 0), - (112, 0, 0), - (119, 0, 0), - (134, 0, 0), - (153, 0, 0), - - # Node 95 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (100, 0, 0), - (103, 0, 0), - (104, 0, 0), - (106, 0, 0), - (107, 0, 0), - (113, 0, 0), - (116, 0, 0), - (120, 0, 0), - (126, 0, 0), - (135, 0, 0), - (142, 0, 0), - (154, 0, 0), - (169, 0, 0), - - # Node 96 - (1, HUFFMAN_EMIT_SYMBOL, 92), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (1, HUFFMAN_EMIT_SYMBOL, 195), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (1, HUFFMAN_EMIT_SYMBOL, 208), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (108, 0, 0), - (109, 0, 0), - - # Node 97 - (2, HUFFMAN_EMIT_SYMBOL, 92), - (9, HUFFMAN_EMIT_SYMBOL, 92), - (23, HUFFMAN_EMIT_SYMBOL, 92), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (2, HUFFMAN_EMIT_SYMBOL, 195), - (9, HUFFMAN_EMIT_SYMBOL, 195), - (23, HUFFMAN_EMIT_SYMBOL, 195), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - (2, HUFFMAN_EMIT_SYMBOL, 208), - (9, HUFFMAN_EMIT_SYMBOL, 208), - (23, HUFFMAN_EMIT_SYMBOL, 208), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (1, HUFFMAN_EMIT_SYMBOL, 128), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (1, HUFFMAN_EMIT_SYMBOL, 130), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 98 - (3, HUFFMAN_EMIT_SYMBOL, 92), - (6, HUFFMAN_EMIT_SYMBOL, 92), - (10, HUFFMAN_EMIT_SYMBOL, 92), - (15, HUFFMAN_EMIT_SYMBOL, 92), - (24, HUFFMAN_EMIT_SYMBOL, 92), - (31, HUFFMAN_EMIT_SYMBOL, 92), - (41, HUFFMAN_EMIT_SYMBOL, 92), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 92), - (3, HUFFMAN_EMIT_SYMBOL, 195), - (6, HUFFMAN_EMIT_SYMBOL, 195), - (10, HUFFMAN_EMIT_SYMBOL, 195), - (15, HUFFMAN_EMIT_SYMBOL, 195), - (24, HUFFMAN_EMIT_SYMBOL, 195), - (31, HUFFMAN_EMIT_SYMBOL, 195), - (41, HUFFMAN_EMIT_SYMBOL, 195), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 195), - - # Node 99 - (3, HUFFMAN_EMIT_SYMBOL, 208), - (6, HUFFMAN_EMIT_SYMBOL, 208), - (10, HUFFMAN_EMIT_SYMBOL, 208), - (15, HUFFMAN_EMIT_SYMBOL, 208), - (24, HUFFMAN_EMIT_SYMBOL, 208), - (31, HUFFMAN_EMIT_SYMBOL, 208), - (41, HUFFMAN_EMIT_SYMBOL, 208), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 208), - (2, HUFFMAN_EMIT_SYMBOL, 128), - (9, HUFFMAN_EMIT_SYMBOL, 128), - (23, HUFFMAN_EMIT_SYMBOL, 128), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (2, HUFFMAN_EMIT_SYMBOL, 130), - (9, HUFFMAN_EMIT_SYMBOL, 130), - (23, HUFFMAN_EMIT_SYMBOL, 130), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 100 - (3, HUFFMAN_EMIT_SYMBOL, 128), - (6, HUFFMAN_EMIT_SYMBOL, 128), - (10, HUFFMAN_EMIT_SYMBOL, 128), - (15, HUFFMAN_EMIT_SYMBOL, 128), - (24, HUFFMAN_EMIT_SYMBOL, 128), - (31, HUFFMAN_EMIT_SYMBOL, 128), - (41, HUFFMAN_EMIT_SYMBOL, 128), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 128), - (3, HUFFMAN_EMIT_SYMBOL, 130), - (6, HUFFMAN_EMIT_SYMBOL, 130), - (10, HUFFMAN_EMIT_SYMBOL, 130), - (15, HUFFMAN_EMIT_SYMBOL, 130), - (24, HUFFMAN_EMIT_SYMBOL, 130), - (31, HUFFMAN_EMIT_SYMBOL, 130), - (41, HUFFMAN_EMIT_SYMBOL, 130), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 130), - - # Node 101 - (1, HUFFMAN_EMIT_SYMBOL, 131), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (1, HUFFMAN_EMIT_SYMBOL, 162), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (1, HUFFMAN_EMIT_SYMBOL, 184), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (1, HUFFMAN_EMIT_SYMBOL, 194), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - (1, HUFFMAN_EMIT_SYMBOL, 224), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (1, HUFFMAN_EMIT_SYMBOL, 226), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 102 - (2, HUFFMAN_EMIT_SYMBOL, 131), - (9, HUFFMAN_EMIT_SYMBOL, 131), - (23, HUFFMAN_EMIT_SYMBOL, 131), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (2, HUFFMAN_EMIT_SYMBOL, 162), - (9, HUFFMAN_EMIT_SYMBOL, 162), - (23, HUFFMAN_EMIT_SYMBOL, 162), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - (2, HUFFMAN_EMIT_SYMBOL, 184), - (9, HUFFMAN_EMIT_SYMBOL, 184), - (23, HUFFMAN_EMIT_SYMBOL, 184), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (2, HUFFMAN_EMIT_SYMBOL, 194), - (9, HUFFMAN_EMIT_SYMBOL, 194), - (23, HUFFMAN_EMIT_SYMBOL, 194), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - - # Node 103 - (3, HUFFMAN_EMIT_SYMBOL, 131), - (6, HUFFMAN_EMIT_SYMBOL, 131), - (10, HUFFMAN_EMIT_SYMBOL, 131), - (15, HUFFMAN_EMIT_SYMBOL, 131), - (24, HUFFMAN_EMIT_SYMBOL, 131), - (31, HUFFMAN_EMIT_SYMBOL, 131), - (41, HUFFMAN_EMIT_SYMBOL, 131), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 131), - (3, HUFFMAN_EMIT_SYMBOL, 162), - (6, HUFFMAN_EMIT_SYMBOL, 162), - (10, HUFFMAN_EMIT_SYMBOL, 162), - (15, HUFFMAN_EMIT_SYMBOL, 162), - (24, HUFFMAN_EMIT_SYMBOL, 162), - (31, HUFFMAN_EMIT_SYMBOL, 162), - (41, HUFFMAN_EMIT_SYMBOL, 162), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 162), - - # Node 104 - (3, HUFFMAN_EMIT_SYMBOL, 184), - (6, HUFFMAN_EMIT_SYMBOL, 184), - (10, HUFFMAN_EMIT_SYMBOL, 184), - (15, HUFFMAN_EMIT_SYMBOL, 184), - (24, HUFFMAN_EMIT_SYMBOL, 184), - (31, HUFFMAN_EMIT_SYMBOL, 184), - (41, HUFFMAN_EMIT_SYMBOL, 184), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 184), - (3, HUFFMAN_EMIT_SYMBOL, 194), - (6, HUFFMAN_EMIT_SYMBOL, 194), - (10, HUFFMAN_EMIT_SYMBOL, 194), - (15, HUFFMAN_EMIT_SYMBOL, 194), - (24, HUFFMAN_EMIT_SYMBOL, 194), - (31, HUFFMAN_EMIT_SYMBOL, 194), - (41, HUFFMAN_EMIT_SYMBOL, 194), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 194), - - # Node 105 - (2, HUFFMAN_EMIT_SYMBOL, 224), - (9, HUFFMAN_EMIT_SYMBOL, 224), - (23, HUFFMAN_EMIT_SYMBOL, 224), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (2, HUFFMAN_EMIT_SYMBOL, 226), - (9, HUFFMAN_EMIT_SYMBOL, 226), - (23, HUFFMAN_EMIT_SYMBOL, 226), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - (1, HUFFMAN_EMIT_SYMBOL, 153), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (1, HUFFMAN_EMIT_SYMBOL, 161), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (1, HUFFMAN_EMIT_SYMBOL, 167), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (1, HUFFMAN_EMIT_SYMBOL, 172), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 106 - (3, HUFFMAN_EMIT_SYMBOL, 224), - (6, HUFFMAN_EMIT_SYMBOL, 224), - (10, HUFFMAN_EMIT_SYMBOL, 224), - (15, HUFFMAN_EMIT_SYMBOL, 224), - (24, HUFFMAN_EMIT_SYMBOL, 224), - (31, HUFFMAN_EMIT_SYMBOL, 224), - (41, HUFFMAN_EMIT_SYMBOL, 224), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 224), - (3, HUFFMAN_EMIT_SYMBOL, 226), - (6, HUFFMAN_EMIT_SYMBOL, 226), - (10, HUFFMAN_EMIT_SYMBOL, 226), - (15, HUFFMAN_EMIT_SYMBOL, 226), - (24, HUFFMAN_EMIT_SYMBOL, 226), - (31, HUFFMAN_EMIT_SYMBOL, 226), - (41, HUFFMAN_EMIT_SYMBOL, 226), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 226), - - # Node 107 - (2, HUFFMAN_EMIT_SYMBOL, 153), - (9, HUFFMAN_EMIT_SYMBOL, 153), - (23, HUFFMAN_EMIT_SYMBOL, 153), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (2, HUFFMAN_EMIT_SYMBOL, 161), - (9, HUFFMAN_EMIT_SYMBOL, 161), - (23, HUFFMAN_EMIT_SYMBOL, 161), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - (2, HUFFMAN_EMIT_SYMBOL, 167), - (9, HUFFMAN_EMIT_SYMBOL, 167), - (23, HUFFMAN_EMIT_SYMBOL, 167), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (2, HUFFMAN_EMIT_SYMBOL, 172), - (9, HUFFMAN_EMIT_SYMBOL, 172), - (23, HUFFMAN_EMIT_SYMBOL, 172), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 108 - (3, HUFFMAN_EMIT_SYMBOL, 153), - (6, HUFFMAN_EMIT_SYMBOL, 153), - (10, HUFFMAN_EMIT_SYMBOL, 153), - (15, HUFFMAN_EMIT_SYMBOL, 153), - (24, HUFFMAN_EMIT_SYMBOL, 153), - (31, HUFFMAN_EMIT_SYMBOL, 153), - (41, HUFFMAN_EMIT_SYMBOL, 153), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 153), - (3, HUFFMAN_EMIT_SYMBOL, 161), - (6, HUFFMAN_EMIT_SYMBOL, 161), - (10, HUFFMAN_EMIT_SYMBOL, 161), - (15, HUFFMAN_EMIT_SYMBOL, 161), - (24, HUFFMAN_EMIT_SYMBOL, 161), - (31, HUFFMAN_EMIT_SYMBOL, 161), - (41, HUFFMAN_EMIT_SYMBOL, 161), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 161), - - # Node 109 - (3, HUFFMAN_EMIT_SYMBOL, 167), - (6, HUFFMAN_EMIT_SYMBOL, 167), - (10, HUFFMAN_EMIT_SYMBOL, 167), - (15, HUFFMAN_EMIT_SYMBOL, 167), - (24, HUFFMAN_EMIT_SYMBOL, 167), - (31, HUFFMAN_EMIT_SYMBOL, 167), - (41, HUFFMAN_EMIT_SYMBOL, 167), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 167), - (3, HUFFMAN_EMIT_SYMBOL, 172), - (6, HUFFMAN_EMIT_SYMBOL, 172), - (10, HUFFMAN_EMIT_SYMBOL, 172), - (15, HUFFMAN_EMIT_SYMBOL, 172), - (24, HUFFMAN_EMIT_SYMBOL, 172), - (31, HUFFMAN_EMIT_SYMBOL, 172), - (41, HUFFMAN_EMIT_SYMBOL, 172), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 172), - - # Node 110 - (114, 0, 0), - (115, 0, 0), - (117, 0, 0), - (118, 0, 0), - (121, 0, 0), - (123, 0, 0), - (127, 0, 0), - (130, 0, 0), - (136, 0, 0), - (139, 0, 0), - (143, 0, 0), - (146, 0, 0), - (155, 0, 0), - (162, 0, 0), - (170, 0, 0), - (180, 0, 0), - - # Node 111 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (122, 0, 0), - (124, 0, 0), - (125, 0, 0), - (128, 0, 0), - (129, 0, 0), - (131, 0, 0), - (132, 0, 0), - - # Node 112 - (1, HUFFMAN_EMIT_SYMBOL, 176), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (1, HUFFMAN_EMIT_SYMBOL, 177), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (1, HUFFMAN_EMIT_SYMBOL, 179), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (1, HUFFMAN_EMIT_SYMBOL, 209), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - (1, HUFFMAN_EMIT_SYMBOL, 216), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (1, HUFFMAN_EMIT_SYMBOL, 217), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (1, HUFFMAN_EMIT_SYMBOL, 227), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (1, HUFFMAN_EMIT_SYMBOL, 229), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 113 - (2, HUFFMAN_EMIT_SYMBOL, 176), - (9, HUFFMAN_EMIT_SYMBOL, 176), - (23, HUFFMAN_EMIT_SYMBOL, 176), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (2, HUFFMAN_EMIT_SYMBOL, 177), - (9, HUFFMAN_EMIT_SYMBOL, 177), - (23, HUFFMAN_EMIT_SYMBOL, 177), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - (2, HUFFMAN_EMIT_SYMBOL, 179), - (9, HUFFMAN_EMIT_SYMBOL, 179), - (23, HUFFMAN_EMIT_SYMBOL, 179), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (2, HUFFMAN_EMIT_SYMBOL, 209), - (9, HUFFMAN_EMIT_SYMBOL, 209), - (23, HUFFMAN_EMIT_SYMBOL, 209), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - - # Node 114 - (3, HUFFMAN_EMIT_SYMBOL, 176), - (6, HUFFMAN_EMIT_SYMBOL, 176), - (10, HUFFMAN_EMIT_SYMBOL, 176), - (15, HUFFMAN_EMIT_SYMBOL, 176), - (24, HUFFMAN_EMIT_SYMBOL, 176), - (31, HUFFMAN_EMIT_SYMBOL, 176), - (41, HUFFMAN_EMIT_SYMBOL, 176), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 176), - (3, HUFFMAN_EMIT_SYMBOL, 177), - (6, HUFFMAN_EMIT_SYMBOL, 177), - (10, HUFFMAN_EMIT_SYMBOL, 177), - (15, HUFFMAN_EMIT_SYMBOL, 177), - (24, HUFFMAN_EMIT_SYMBOL, 177), - (31, HUFFMAN_EMIT_SYMBOL, 177), - (41, HUFFMAN_EMIT_SYMBOL, 177), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 177), - - # Node 115 - (3, HUFFMAN_EMIT_SYMBOL, 179), - (6, HUFFMAN_EMIT_SYMBOL, 179), - (10, HUFFMAN_EMIT_SYMBOL, 179), - (15, HUFFMAN_EMIT_SYMBOL, 179), - (24, HUFFMAN_EMIT_SYMBOL, 179), - (31, HUFFMAN_EMIT_SYMBOL, 179), - (41, HUFFMAN_EMIT_SYMBOL, 179), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 179), - (3, HUFFMAN_EMIT_SYMBOL, 209), - (6, HUFFMAN_EMIT_SYMBOL, 209), - (10, HUFFMAN_EMIT_SYMBOL, 209), - (15, HUFFMAN_EMIT_SYMBOL, 209), - (24, HUFFMAN_EMIT_SYMBOL, 209), - (31, HUFFMAN_EMIT_SYMBOL, 209), - (41, HUFFMAN_EMIT_SYMBOL, 209), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 209), - - # Node 116 - (2, HUFFMAN_EMIT_SYMBOL, 216), - (9, HUFFMAN_EMIT_SYMBOL, 216), - (23, HUFFMAN_EMIT_SYMBOL, 216), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (2, HUFFMAN_EMIT_SYMBOL, 217), - (9, HUFFMAN_EMIT_SYMBOL, 217), - (23, HUFFMAN_EMIT_SYMBOL, 217), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - (2, HUFFMAN_EMIT_SYMBOL, 227), - (9, HUFFMAN_EMIT_SYMBOL, 227), - (23, HUFFMAN_EMIT_SYMBOL, 227), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (2, HUFFMAN_EMIT_SYMBOL, 229), - (9, HUFFMAN_EMIT_SYMBOL, 229), - (23, HUFFMAN_EMIT_SYMBOL, 229), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 117 - (3, HUFFMAN_EMIT_SYMBOL, 216), - (6, HUFFMAN_EMIT_SYMBOL, 216), - (10, HUFFMAN_EMIT_SYMBOL, 216), - (15, HUFFMAN_EMIT_SYMBOL, 216), - (24, HUFFMAN_EMIT_SYMBOL, 216), - (31, HUFFMAN_EMIT_SYMBOL, 216), - (41, HUFFMAN_EMIT_SYMBOL, 216), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 216), - (3, HUFFMAN_EMIT_SYMBOL, 217), - (6, HUFFMAN_EMIT_SYMBOL, 217), - (10, HUFFMAN_EMIT_SYMBOL, 217), - (15, HUFFMAN_EMIT_SYMBOL, 217), - (24, HUFFMAN_EMIT_SYMBOL, 217), - (31, HUFFMAN_EMIT_SYMBOL, 217), - (41, HUFFMAN_EMIT_SYMBOL, 217), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 217), - - # Node 118 - (3, HUFFMAN_EMIT_SYMBOL, 227), - (6, HUFFMAN_EMIT_SYMBOL, 227), - (10, HUFFMAN_EMIT_SYMBOL, 227), - (15, HUFFMAN_EMIT_SYMBOL, 227), - (24, HUFFMAN_EMIT_SYMBOL, 227), - (31, HUFFMAN_EMIT_SYMBOL, 227), - (41, HUFFMAN_EMIT_SYMBOL, 227), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 227), - (3, HUFFMAN_EMIT_SYMBOL, 229), - (6, HUFFMAN_EMIT_SYMBOL, 229), - (10, HUFFMAN_EMIT_SYMBOL, 229), - (15, HUFFMAN_EMIT_SYMBOL, 229), - (24, HUFFMAN_EMIT_SYMBOL, 229), - (31, HUFFMAN_EMIT_SYMBOL, 229), - (41, HUFFMAN_EMIT_SYMBOL, 229), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 229), - - # Node 119 - (1, HUFFMAN_EMIT_SYMBOL, 230), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 120 - (2, HUFFMAN_EMIT_SYMBOL, 230), - (9, HUFFMAN_EMIT_SYMBOL, 230), - (23, HUFFMAN_EMIT_SYMBOL, 230), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (1, HUFFMAN_EMIT_SYMBOL, 129), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (1, HUFFMAN_EMIT_SYMBOL, 132), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - (1, HUFFMAN_EMIT_SYMBOL, 133), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (1, HUFFMAN_EMIT_SYMBOL, 134), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (1, HUFFMAN_EMIT_SYMBOL, 136), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (1, HUFFMAN_EMIT_SYMBOL, 146), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 121 - (3, HUFFMAN_EMIT_SYMBOL, 230), - (6, HUFFMAN_EMIT_SYMBOL, 230), - (10, HUFFMAN_EMIT_SYMBOL, 230), - (15, HUFFMAN_EMIT_SYMBOL, 230), - (24, HUFFMAN_EMIT_SYMBOL, 230), - (31, HUFFMAN_EMIT_SYMBOL, 230), - (41, HUFFMAN_EMIT_SYMBOL, 230), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 230), - (2, HUFFMAN_EMIT_SYMBOL, 129), - (9, HUFFMAN_EMIT_SYMBOL, 129), - (23, HUFFMAN_EMIT_SYMBOL, 129), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (2, HUFFMAN_EMIT_SYMBOL, 132), - (9, HUFFMAN_EMIT_SYMBOL, 132), - (23, HUFFMAN_EMIT_SYMBOL, 132), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - - # Node 122 - (3, HUFFMAN_EMIT_SYMBOL, 129), - (6, HUFFMAN_EMIT_SYMBOL, 129), - (10, HUFFMAN_EMIT_SYMBOL, 129), - (15, HUFFMAN_EMIT_SYMBOL, 129), - (24, HUFFMAN_EMIT_SYMBOL, 129), - (31, HUFFMAN_EMIT_SYMBOL, 129), - (41, HUFFMAN_EMIT_SYMBOL, 129), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 129), - (3, HUFFMAN_EMIT_SYMBOL, 132), - (6, HUFFMAN_EMIT_SYMBOL, 132), - (10, HUFFMAN_EMIT_SYMBOL, 132), - (15, HUFFMAN_EMIT_SYMBOL, 132), - (24, HUFFMAN_EMIT_SYMBOL, 132), - (31, HUFFMAN_EMIT_SYMBOL, 132), - (41, HUFFMAN_EMIT_SYMBOL, 132), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 132), - - # Node 123 - (2, HUFFMAN_EMIT_SYMBOL, 133), - (9, HUFFMAN_EMIT_SYMBOL, 133), - (23, HUFFMAN_EMIT_SYMBOL, 133), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (2, HUFFMAN_EMIT_SYMBOL, 134), - (9, HUFFMAN_EMIT_SYMBOL, 134), - (23, HUFFMAN_EMIT_SYMBOL, 134), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - (2, HUFFMAN_EMIT_SYMBOL, 136), - (9, HUFFMAN_EMIT_SYMBOL, 136), - (23, HUFFMAN_EMIT_SYMBOL, 136), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (2, HUFFMAN_EMIT_SYMBOL, 146), - (9, HUFFMAN_EMIT_SYMBOL, 146), - (23, HUFFMAN_EMIT_SYMBOL, 146), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 124 - (3, HUFFMAN_EMIT_SYMBOL, 133), - (6, HUFFMAN_EMIT_SYMBOL, 133), - (10, HUFFMAN_EMIT_SYMBOL, 133), - (15, HUFFMAN_EMIT_SYMBOL, 133), - (24, HUFFMAN_EMIT_SYMBOL, 133), - (31, HUFFMAN_EMIT_SYMBOL, 133), - (41, HUFFMAN_EMIT_SYMBOL, 133), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 133), - (3, HUFFMAN_EMIT_SYMBOL, 134), - (6, HUFFMAN_EMIT_SYMBOL, 134), - (10, HUFFMAN_EMIT_SYMBOL, 134), - (15, HUFFMAN_EMIT_SYMBOL, 134), - (24, HUFFMAN_EMIT_SYMBOL, 134), - (31, HUFFMAN_EMIT_SYMBOL, 134), - (41, HUFFMAN_EMIT_SYMBOL, 134), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 134), - - # Node 125 - (3, HUFFMAN_EMIT_SYMBOL, 136), - (6, HUFFMAN_EMIT_SYMBOL, 136), - (10, HUFFMAN_EMIT_SYMBOL, 136), - (15, HUFFMAN_EMIT_SYMBOL, 136), - (24, HUFFMAN_EMIT_SYMBOL, 136), - (31, HUFFMAN_EMIT_SYMBOL, 136), - (41, HUFFMAN_EMIT_SYMBOL, 136), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 136), - (3, HUFFMAN_EMIT_SYMBOL, 146), - (6, HUFFMAN_EMIT_SYMBOL, 146), - (10, HUFFMAN_EMIT_SYMBOL, 146), - (15, HUFFMAN_EMIT_SYMBOL, 146), - (24, HUFFMAN_EMIT_SYMBOL, 146), - (31, HUFFMAN_EMIT_SYMBOL, 146), - (41, HUFFMAN_EMIT_SYMBOL, 146), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 146), - - # Node 126 - (1, HUFFMAN_EMIT_SYMBOL, 154), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (1, HUFFMAN_EMIT_SYMBOL, 156), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (1, HUFFMAN_EMIT_SYMBOL, 160), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (1, HUFFMAN_EMIT_SYMBOL, 163), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - (1, HUFFMAN_EMIT_SYMBOL, 164), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (1, HUFFMAN_EMIT_SYMBOL, 169), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (1, HUFFMAN_EMIT_SYMBOL, 170), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (1, HUFFMAN_EMIT_SYMBOL, 173), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 127 - (2, HUFFMAN_EMIT_SYMBOL, 154), - (9, HUFFMAN_EMIT_SYMBOL, 154), - (23, HUFFMAN_EMIT_SYMBOL, 154), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (2, HUFFMAN_EMIT_SYMBOL, 156), - (9, HUFFMAN_EMIT_SYMBOL, 156), - (23, HUFFMAN_EMIT_SYMBOL, 156), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - (2, HUFFMAN_EMIT_SYMBOL, 160), - (9, HUFFMAN_EMIT_SYMBOL, 160), - (23, HUFFMAN_EMIT_SYMBOL, 160), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (2, HUFFMAN_EMIT_SYMBOL, 163), - (9, HUFFMAN_EMIT_SYMBOL, 163), - (23, HUFFMAN_EMIT_SYMBOL, 163), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - - # Node 128 - (3, HUFFMAN_EMIT_SYMBOL, 154), - (6, HUFFMAN_EMIT_SYMBOL, 154), - (10, HUFFMAN_EMIT_SYMBOL, 154), - (15, HUFFMAN_EMIT_SYMBOL, 154), - (24, HUFFMAN_EMIT_SYMBOL, 154), - (31, HUFFMAN_EMIT_SYMBOL, 154), - (41, HUFFMAN_EMIT_SYMBOL, 154), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 154), - (3, HUFFMAN_EMIT_SYMBOL, 156), - (6, HUFFMAN_EMIT_SYMBOL, 156), - (10, HUFFMAN_EMIT_SYMBOL, 156), - (15, HUFFMAN_EMIT_SYMBOL, 156), - (24, HUFFMAN_EMIT_SYMBOL, 156), - (31, HUFFMAN_EMIT_SYMBOL, 156), - (41, HUFFMAN_EMIT_SYMBOL, 156), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 156), - - # Node 129 - (3, HUFFMAN_EMIT_SYMBOL, 160), - (6, HUFFMAN_EMIT_SYMBOL, 160), - (10, HUFFMAN_EMIT_SYMBOL, 160), - (15, HUFFMAN_EMIT_SYMBOL, 160), - (24, HUFFMAN_EMIT_SYMBOL, 160), - (31, HUFFMAN_EMIT_SYMBOL, 160), - (41, HUFFMAN_EMIT_SYMBOL, 160), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 160), - (3, HUFFMAN_EMIT_SYMBOL, 163), - (6, HUFFMAN_EMIT_SYMBOL, 163), - (10, HUFFMAN_EMIT_SYMBOL, 163), - (15, HUFFMAN_EMIT_SYMBOL, 163), - (24, HUFFMAN_EMIT_SYMBOL, 163), - (31, HUFFMAN_EMIT_SYMBOL, 163), - (41, HUFFMAN_EMIT_SYMBOL, 163), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 163), - - # Node 130 - (2, HUFFMAN_EMIT_SYMBOL, 164), - (9, HUFFMAN_EMIT_SYMBOL, 164), - (23, HUFFMAN_EMIT_SYMBOL, 164), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (2, HUFFMAN_EMIT_SYMBOL, 169), - (9, HUFFMAN_EMIT_SYMBOL, 169), - (23, HUFFMAN_EMIT_SYMBOL, 169), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - (2, HUFFMAN_EMIT_SYMBOL, 170), - (9, HUFFMAN_EMIT_SYMBOL, 170), - (23, HUFFMAN_EMIT_SYMBOL, 170), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (2, HUFFMAN_EMIT_SYMBOL, 173), - (9, HUFFMAN_EMIT_SYMBOL, 173), - (23, HUFFMAN_EMIT_SYMBOL, 173), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 131 - (3, HUFFMAN_EMIT_SYMBOL, 164), - (6, HUFFMAN_EMIT_SYMBOL, 164), - (10, HUFFMAN_EMIT_SYMBOL, 164), - (15, HUFFMAN_EMIT_SYMBOL, 164), - (24, HUFFMAN_EMIT_SYMBOL, 164), - (31, HUFFMAN_EMIT_SYMBOL, 164), - (41, HUFFMAN_EMIT_SYMBOL, 164), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 164), - (3, HUFFMAN_EMIT_SYMBOL, 169), - (6, HUFFMAN_EMIT_SYMBOL, 169), - (10, HUFFMAN_EMIT_SYMBOL, 169), - (15, HUFFMAN_EMIT_SYMBOL, 169), - (24, HUFFMAN_EMIT_SYMBOL, 169), - (31, HUFFMAN_EMIT_SYMBOL, 169), - (41, HUFFMAN_EMIT_SYMBOL, 169), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 169), - - # Node 132 - (3, HUFFMAN_EMIT_SYMBOL, 170), - (6, HUFFMAN_EMIT_SYMBOL, 170), - (10, HUFFMAN_EMIT_SYMBOL, 170), - (15, HUFFMAN_EMIT_SYMBOL, 170), - (24, HUFFMAN_EMIT_SYMBOL, 170), - (31, HUFFMAN_EMIT_SYMBOL, 170), - (41, HUFFMAN_EMIT_SYMBOL, 170), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 170), - (3, HUFFMAN_EMIT_SYMBOL, 173), - (6, HUFFMAN_EMIT_SYMBOL, 173), - (10, HUFFMAN_EMIT_SYMBOL, 173), - (15, HUFFMAN_EMIT_SYMBOL, 173), - (24, HUFFMAN_EMIT_SYMBOL, 173), - (31, HUFFMAN_EMIT_SYMBOL, 173), - (41, HUFFMAN_EMIT_SYMBOL, 173), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 173), - - # Node 133 - (137, 0, 0), - (138, 0, 0), - (140, 0, 0), - (141, 0, 0), - (144, 0, 0), - (145, 0, 0), - (147, 0, 0), - (150, 0, 0), - (156, 0, 0), - (159, 0, 0), - (163, 0, 0), - (166, 0, 0), - (171, 0, 0), - (174, 0, 0), - (181, 0, 0), - (190, 0, 0), - - # Node 134 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - (148, 0, 0), - (149, 0, 0), - (151, 0, 0), - (152, 0, 0), - - # Node 135 - (1, HUFFMAN_EMIT_SYMBOL, 178), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (1, HUFFMAN_EMIT_SYMBOL, 181), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (1, HUFFMAN_EMIT_SYMBOL, 185), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (1, HUFFMAN_EMIT_SYMBOL, 186), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - (1, HUFFMAN_EMIT_SYMBOL, 187), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (1, HUFFMAN_EMIT_SYMBOL, 189), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (1, HUFFMAN_EMIT_SYMBOL, 190), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (1, HUFFMAN_EMIT_SYMBOL, 196), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 136 - (2, HUFFMAN_EMIT_SYMBOL, 178), - (9, HUFFMAN_EMIT_SYMBOL, 178), - (23, HUFFMAN_EMIT_SYMBOL, 178), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (2, HUFFMAN_EMIT_SYMBOL, 181), - (9, HUFFMAN_EMIT_SYMBOL, 181), - (23, HUFFMAN_EMIT_SYMBOL, 181), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - (2, HUFFMAN_EMIT_SYMBOL, 185), - (9, HUFFMAN_EMIT_SYMBOL, 185), - (23, HUFFMAN_EMIT_SYMBOL, 185), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (2, HUFFMAN_EMIT_SYMBOL, 186), - (9, HUFFMAN_EMIT_SYMBOL, 186), - (23, HUFFMAN_EMIT_SYMBOL, 186), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - - # Node 137 - (3, HUFFMAN_EMIT_SYMBOL, 178), - (6, HUFFMAN_EMIT_SYMBOL, 178), - (10, HUFFMAN_EMIT_SYMBOL, 178), - (15, HUFFMAN_EMIT_SYMBOL, 178), - (24, HUFFMAN_EMIT_SYMBOL, 178), - (31, HUFFMAN_EMIT_SYMBOL, 178), - (41, HUFFMAN_EMIT_SYMBOL, 178), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 178), - (3, HUFFMAN_EMIT_SYMBOL, 181), - (6, HUFFMAN_EMIT_SYMBOL, 181), - (10, HUFFMAN_EMIT_SYMBOL, 181), - (15, HUFFMAN_EMIT_SYMBOL, 181), - (24, HUFFMAN_EMIT_SYMBOL, 181), - (31, HUFFMAN_EMIT_SYMBOL, 181), - (41, HUFFMAN_EMIT_SYMBOL, 181), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 181), - - # Node 138 - (3, HUFFMAN_EMIT_SYMBOL, 185), - (6, HUFFMAN_EMIT_SYMBOL, 185), - (10, HUFFMAN_EMIT_SYMBOL, 185), - (15, HUFFMAN_EMIT_SYMBOL, 185), - (24, HUFFMAN_EMIT_SYMBOL, 185), - (31, HUFFMAN_EMIT_SYMBOL, 185), - (41, HUFFMAN_EMIT_SYMBOL, 185), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 185), - (3, HUFFMAN_EMIT_SYMBOL, 186), - (6, HUFFMAN_EMIT_SYMBOL, 186), - (10, HUFFMAN_EMIT_SYMBOL, 186), - (15, HUFFMAN_EMIT_SYMBOL, 186), - (24, HUFFMAN_EMIT_SYMBOL, 186), - (31, HUFFMAN_EMIT_SYMBOL, 186), - (41, HUFFMAN_EMIT_SYMBOL, 186), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 186), - - # Node 139 - (2, HUFFMAN_EMIT_SYMBOL, 187), - (9, HUFFMAN_EMIT_SYMBOL, 187), - (23, HUFFMAN_EMIT_SYMBOL, 187), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (2, HUFFMAN_EMIT_SYMBOL, 189), - (9, HUFFMAN_EMIT_SYMBOL, 189), - (23, HUFFMAN_EMIT_SYMBOL, 189), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - (2, HUFFMAN_EMIT_SYMBOL, 190), - (9, HUFFMAN_EMIT_SYMBOL, 190), - (23, HUFFMAN_EMIT_SYMBOL, 190), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (2, HUFFMAN_EMIT_SYMBOL, 196), - (9, HUFFMAN_EMIT_SYMBOL, 196), - (23, HUFFMAN_EMIT_SYMBOL, 196), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 140 - (3, HUFFMAN_EMIT_SYMBOL, 187), - (6, HUFFMAN_EMIT_SYMBOL, 187), - (10, HUFFMAN_EMIT_SYMBOL, 187), - (15, HUFFMAN_EMIT_SYMBOL, 187), - (24, HUFFMAN_EMIT_SYMBOL, 187), - (31, HUFFMAN_EMIT_SYMBOL, 187), - (41, HUFFMAN_EMIT_SYMBOL, 187), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 187), - (3, HUFFMAN_EMIT_SYMBOL, 189), - (6, HUFFMAN_EMIT_SYMBOL, 189), - (10, HUFFMAN_EMIT_SYMBOL, 189), - (15, HUFFMAN_EMIT_SYMBOL, 189), - (24, HUFFMAN_EMIT_SYMBOL, 189), - (31, HUFFMAN_EMIT_SYMBOL, 189), - (41, HUFFMAN_EMIT_SYMBOL, 189), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 189), - - # Node 141 - (3, HUFFMAN_EMIT_SYMBOL, 190), - (6, HUFFMAN_EMIT_SYMBOL, 190), - (10, HUFFMAN_EMIT_SYMBOL, 190), - (15, HUFFMAN_EMIT_SYMBOL, 190), - (24, HUFFMAN_EMIT_SYMBOL, 190), - (31, HUFFMAN_EMIT_SYMBOL, 190), - (41, HUFFMAN_EMIT_SYMBOL, 190), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 190), - (3, HUFFMAN_EMIT_SYMBOL, 196), - (6, HUFFMAN_EMIT_SYMBOL, 196), - (10, HUFFMAN_EMIT_SYMBOL, 196), - (15, HUFFMAN_EMIT_SYMBOL, 196), - (24, HUFFMAN_EMIT_SYMBOL, 196), - (31, HUFFMAN_EMIT_SYMBOL, 196), - (41, HUFFMAN_EMIT_SYMBOL, 196), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 196), - - # Node 142 - (1, HUFFMAN_EMIT_SYMBOL, 198), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (1, HUFFMAN_EMIT_SYMBOL, 228), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (1, HUFFMAN_EMIT_SYMBOL, 232), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (1, HUFFMAN_EMIT_SYMBOL, 233), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 143 - (2, HUFFMAN_EMIT_SYMBOL, 198), - (9, HUFFMAN_EMIT_SYMBOL, 198), - (23, HUFFMAN_EMIT_SYMBOL, 198), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (2, HUFFMAN_EMIT_SYMBOL, 228), - (9, HUFFMAN_EMIT_SYMBOL, 228), - (23, HUFFMAN_EMIT_SYMBOL, 228), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - (2, HUFFMAN_EMIT_SYMBOL, 232), - (9, HUFFMAN_EMIT_SYMBOL, 232), - (23, HUFFMAN_EMIT_SYMBOL, 232), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (2, HUFFMAN_EMIT_SYMBOL, 233), - (9, HUFFMAN_EMIT_SYMBOL, 233), - (23, HUFFMAN_EMIT_SYMBOL, 233), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - - # Node 144 - (3, HUFFMAN_EMIT_SYMBOL, 198), - (6, HUFFMAN_EMIT_SYMBOL, 198), - (10, HUFFMAN_EMIT_SYMBOL, 198), - (15, HUFFMAN_EMIT_SYMBOL, 198), - (24, HUFFMAN_EMIT_SYMBOL, 198), - (31, HUFFMAN_EMIT_SYMBOL, 198), - (41, HUFFMAN_EMIT_SYMBOL, 198), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 198), - (3, HUFFMAN_EMIT_SYMBOL, 228), - (6, HUFFMAN_EMIT_SYMBOL, 228), - (10, HUFFMAN_EMIT_SYMBOL, 228), - (15, HUFFMAN_EMIT_SYMBOL, 228), - (24, HUFFMAN_EMIT_SYMBOL, 228), - (31, HUFFMAN_EMIT_SYMBOL, 228), - (41, HUFFMAN_EMIT_SYMBOL, 228), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 228), - - # Node 145 - (3, HUFFMAN_EMIT_SYMBOL, 232), - (6, HUFFMAN_EMIT_SYMBOL, 232), - (10, HUFFMAN_EMIT_SYMBOL, 232), - (15, HUFFMAN_EMIT_SYMBOL, 232), - (24, HUFFMAN_EMIT_SYMBOL, 232), - (31, HUFFMAN_EMIT_SYMBOL, 232), - (41, HUFFMAN_EMIT_SYMBOL, 232), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 232), - (3, HUFFMAN_EMIT_SYMBOL, 233), - (6, HUFFMAN_EMIT_SYMBOL, 233), - (10, HUFFMAN_EMIT_SYMBOL, 233), - (15, HUFFMAN_EMIT_SYMBOL, 233), - (24, HUFFMAN_EMIT_SYMBOL, 233), - (31, HUFFMAN_EMIT_SYMBOL, 233), - (41, HUFFMAN_EMIT_SYMBOL, 233), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 233), - - # Node 146 - (1, HUFFMAN_EMIT_SYMBOL, 1), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (1, HUFFMAN_EMIT_SYMBOL, 135), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (1, HUFFMAN_EMIT_SYMBOL, 137), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (1, HUFFMAN_EMIT_SYMBOL, 138), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - (1, HUFFMAN_EMIT_SYMBOL, 139), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (1, HUFFMAN_EMIT_SYMBOL, 140), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (1, HUFFMAN_EMIT_SYMBOL, 141), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (1, HUFFMAN_EMIT_SYMBOL, 143), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 147 - (2, HUFFMAN_EMIT_SYMBOL, 1), - (9, HUFFMAN_EMIT_SYMBOL, 1), - (23, HUFFMAN_EMIT_SYMBOL, 1), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (2, HUFFMAN_EMIT_SYMBOL, 135), - (9, HUFFMAN_EMIT_SYMBOL, 135), - (23, HUFFMAN_EMIT_SYMBOL, 135), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - (2, HUFFMAN_EMIT_SYMBOL, 137), - (9, HUFFMAN_EMIT_SYMBOL, 137), - (23, HUFFMAN_EMIT_SYMBOL, 137), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (2, HUFFMAN_EMIT_SYMBOL, 138), - (9, HUFFMAN_EMIT_SYMBOL, 138), - (23, HUFFMAN_EMIT_SYMBOL, 138), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - - # Node 148 - (3, HUFFMAN_EMIT_SYMBOL, 1), - (6, HUFFMAN_EMIT_SYMBOL, 1), - (10, HUFFMAN_EMIT_SYMBOL, 1), - (15, HUFFMAN_EMIT_SYMBOL, 1), - (24, HUFFMAN_EMIT_SYMBOL, 1), - (31, HUFFMAN_EMIT_SYMBOL, 1), - (41, HUFFMAN_EMIT_SYMBOL, 1), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 1), - (3, HUFFMAN_EMIT_SYMBOL, 135), - (6, HUFFMAN_EMIT_SYMBOL, 135), - (10, HUFFMAN_EMIT_SYMBOL, 135), - (15, HUFFMAN_EMIT_SYMBOL, 135), - (24, HUFFMAN_EMIT_SYMBOL, 135), - (31, HUFFMAN_EMIT_SYMBOL, 135), - (41, HUFFMAN_EMIT_SYMBOL, 135), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 135), - - # Node 149 - (3, HUFFMAN_EMIT_SYMBOL, 137), - (6, HUFFMAN_EMIT_SYMBOL, 137), - (10, HUFFMAN_EMIT_SYMBOL, 137), - (15, HUFFMAN_EMIT_SYMBOL, 137), - (24, HUFFMAN_EMIT_SYMBOL, 137), - (31, HUFFMAN_EMIT_SYMBOL, 137), - (41, HUFFMAN_EMIT_SYMBOL, 137), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 137), - (3, HUFFMAN_EMIT_SYMBOL, 138), - (6, HUFFMAN_EMIT_SYMBOL, 138), - (10, HUFFMAN_EMIT_SYMBOL, 138), - (15, HUFFMAN_EMIT_SYMBOL, 138), - (24, HUFFMAN_EMIT_SYMBOL, 138), - (31, HUFFMAN_EMIT_SYMBOL, 138), - (41, HUFFMAN_EMIT_SYMBOL, 138), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 138), - - # Node 150 - (2, HUFFMAN_EMIT_SYMBOL, 139), - (9, HUFFMAN_EMIT_SYMBOL, 139), - (23, HUFFMAN_EMIT_SYMBOL, 139), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (2, HUFFMAN_EMIT_SYMBOL, 140), - (9, HUFFMAN_EMIT_SYMBOL, 140), - (23, HUFFMAN_EMIT_SYMBOL, 140), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - (2, HUFFMAN_EMIT_SYMBOL, 141), - (9, HUFFMAN_EMIT_SYMBOL, 141), - (23, HUFFMAN_EMIT_SYMBOL, 141), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (2, HUFFMAN_EMIT_SYMBOL, 143), - (9, HUFFMAN_EMIT_SYMBOL, 143), - (23, HUFFMAN_EMIT_SYMBOL, 143), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 151 - (3, HUFFMAN_EMIT_SYMBOL, 139), - (6, HUFFMAN_EMIT_SYMBOL, 139), - (10, HUFFMAN_EMIT_SYMBOL, 139), - (15, HUFFMAN_EMIT_SYMBOL, 139), - (24, HUFFMAN_EMIT_SYMBOL, 139), - (31, HUFFMAN_EMIT_SYMBOL, 139), - (41, HUFFMAN_EMIT_SYMBOL, 139), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 139), - (3, HUFFMAN_EMIT_SYMBOL, 140), - (6, HUFFMAN_EMIT_SYMBOL, 140), - (10, HUFFMAN_EMIT_SYMBOL, 140), - (15, HUFFMAN_EMIT_SYMBOL, 140), - (24, HUFFMAN_EMIT_SYMBOL, 140), - (31, HUFFMAN_EMIT_SYMBOL, 140), - (41, HUFFMAN_EMIT_SYMBOL, 140), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 140), - - # Node 152 - (3, HUFFMAN_EMIT_SYMBOL, 141), - (6, HUFFMAN_EMIT_SYMBOL, 141), - (10, HUFFMAN_EMIT_SYMBOL, 141), - (15, HUFFMAN_EMIT_SYMBOL, 141), - (24, HUFFMAN_EMIT_SYMBOL, 141), - (31, HUFFMAN_EMIT_SYMBOL, 141), - (41, HUFFMAN_EMIT_SYMBOL, 141), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 141), - (3, HUFFMAN_EMIT_SYMBOL, 143), - (6, HUFFMAN_EMIT_SYMBOL, 143), - (10, HUFFMAN_EMIT_SYMBOL, 143), - (15, HUFFMAN_EMIT_SYMBOL, 143), - (24, HUFFMAN_EMIT_SYMBOL, 143), - (31, HUFFMAN_EMIT_SYMBOL, 143), - (41, HUFFMAN_EMIT_SYMBOL, 143), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 143), - - # Node 153 - (157, 0, 0), - (158, 0, 0), - (160, 0, 0), - (161, 0, 0), - (164, 0, 0), - (165, 0, 0), - (167, 0, 0), - (168, 0, 0), - (172, 0, 0), - (173, 0, 0), - (175, 0, 0), - (177, 0, 0), - (182, 0, 0), - (185, 0, 0), - (191, 0, 0), - (207, 0, 0), - - # Node 154 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 155 - (1, HUFFMAN_EMIT_SYMBOL, 147), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (1, HUFFMAN_EMIT_SYMBOL, 149), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (1, HUFFMAN_EMIT_SYMBOL, 150), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (1, HUFFMAN_EMIT_SYMBOL, 151), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - (1, HUFFMAN_EMIT_SYMBOL, 152), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (1, HUFFMAN_EMIT_SYMBOL, 155), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (1, HUFFMAN_EMIT_SYMBOL, 157), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (1, HUFFMAN_EMIT_SYMBOL, 158), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 156 - (2, HUFFMAN_EMIT_SYMBOL, 147), - (9, HUFFMAN_EMIT_SYMBOL, 147), - (23, HUFFMAN_EMIT_SYMBOL, 147), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (2, HUFFMAN_EMIT_SYMBOL, 149), - (9, HUFFMAN_EMIT_SYMBOL, 149), - (23, HUFFMAN_EMIT_SYMBOL, 149), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - (2, HUFFMAN_EMIT_SYMBOL, 150), - (9, HUFFMAN_EMIT_SYMBOL, 150), - (23, HUFFMAN_EMIT_SYMBOL, 150), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (2, HUFFMAN_EMIT_SYMBOL, 151), - (9, HUFFMAN_EMIT_SYMBOL, 151), - (23, HUFFMAN_EMIT_SYMBOL, 151), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - - # Node 157 - (3, HUFFMAN_EMIT_SYMBOL, 147), - (6, HUFFMAN_EMIT_SYMBOL, 147), - (10, HUFFMAN_EMIT_SYMBOL, 147), - (15, HUFFMAN_EMIT_SYMBOL, 147), - (24, HUFFMAN_EMIT_SYMBOL, 147), - (31, HUFFMAN_EMIT_SYMBOL, 147), - (41, HUFFMAN_EMIT_SYMBOL, 147), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 147), - (3, HUFFMAN_EMIT_SYMBOL, 149), - (6, HUFFMAN_EMIT_SYMBOL, 149), - (10, HUFFMAN_EMIT_SYMBOL, 149), - (15, HUFFMAN_EMIT_SYMBOL, 149), - (24, HUFFMAN_EMIT_SYMBOL, 149), - (31, HUFFMAN_EMIT_SYMBOL, 149), - (41, HUFFMAN_EMIT_SYMBOL, 149), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 149), - - # Node 158 - (3, HUFFMAN_EMIT_SYMBOL, 150), - (6, HUFFMAN_EMIT_SYMBOL, 150), - (10, HUFFMAN_EMIT_SYMBOL, 150), - (15, HUFFMAN_EMIT_SYMBOL, 150), - (24, HUFFMAN_EMIT_SYMBOL, 150), - (31, HUFFMAN_EMIT_SYMBOL, 150), - (41, HUFFMAN_EMIT_SYMBOL, 150), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 150), - (3, HUFFMAN_EMIT_SYMBOL, 151), - (6, HUFFMAN_EMIT_SYMBOL, 151), - (10, HUFFMAN_EMIT_SYMBOL, 151), - (15, HUFFMAN_EMIT_SYMBOL, 151), - (24, HUFFMAN_EMIT_SYMBOL, 151), - (31, HUFFMAN_EMIT_SYMBOL, 151), - (41, HUFFMAN_EMIT_SYMBOL, 151), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 151), - - # Node 159 - (2, HUFFMAN_EMIT_SYMBOL, 152), - (9, HUFFMAN_EMIT_SYMBOL, 152), - (23, HUFFMAN_EMIT_SYMBOL, 152), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (2, HUFFMAN_EMIT_SYMBOL, 155), - (9, HUFFMAN_EMIT_SYMBOL, 155), - (23, HUFFMAN_EMIT_SYMBOL, 155), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - (2, HUFFMAN_EMIT_SYMBOL, 157), - (9, HUFFMAN_EMIT_SYMBOL, 157), - (23, HUFFMAN_EMIT_SYMBOL, 157), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (2, HUFFMAN_EMIT_SYMBOL, 158), - (9, HUFFMAN_EMIT_SYMBOL, 158), - (23, HUFFMAN_EMIT_SYMBOL, 158), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 160 - (3, HUFFMAN_EMIT_SYMBOL, 152), - (6, HUFFMAN_EMIT_SYMBOL, 152), - (10, HUFFMAN_EMIT_SYMBOL, 152), - (15, HUFFMAN_EMIT_SYMBOL, 152), - (24, HUFFMAN_EMIT_SYMBOL, 152), - (31, HUFFMAN_EMIT_SYMBOL, 152), - (41, HUFFMAN_EMIT_SYMBOL, 152), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 152), - (3, HUFFMAN_EMIT_SYMBOL, 155), - (6, HUFFMAN_EMIT_SYMBOL, 155), - (10, HUFFMAN_EMIT_SYMBOL, 155), - (15, HUFFMAN_EMIT_SYMBOL, 155), - (24, HUFFMAN_EMIT_SYMBOL, 155), - (31, HUFFMAN_EMIT_SYMBOL, 155), - (41, HUFFMAN_EMIT_SYMBOL, 155), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 155), - - # Node 161 - (3, HUFFMAN_EMIT_SYMBOL, 157), - (6, HUFFMAN_EMIT_SYMBOL, 157), - (10, HUFFMAN_EMIT_SYMBOL, 157), - (15, HUFFMAN_EMIT_SYMBOL, 157), - (24, HUFFMAN_EMIT_SYMBOL, 157), - (31, HUFFMAN_EMIT_SYMBOL, 157), - (41, HUFFMAN_EMIT_SYMBOL, 157), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 157), - (3, HUFFMAN_EMIT_SYMBOL, 158), - (6, HUFFMAN_EMIT_SYMBOL, 158), - (10, HUFFMAN_EMIT_SYMBOL, 158), - (15, HUFFMAN_EMIT_SYMBOL, 158), - (24, HUFFMAN_EMIT_SYMBOL, 158), - (31, HUFFMAN_EMIT_SYMBOL, 158), - (41, HUFFMAN_EMIT_SYMBOL, 158), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 158), - - # Node 162 - (1, HUFFMAN_EMIT_SYMBOL, 165), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (1, HUFFMAN_EMIT_SYMBOL, 166), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (1, HUFFMAN_EMIT_SYMBOL, 168), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (1, HUFFMAN_EMIT_SYMBOL, 174), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - (1, HUFFMAN_EMIT_SYMBOL, 175), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (1, HUFFMAN_EMIT_SYMBOL, 180), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (1, HUFFMAN_EMIT_SYMBOL, 182), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (1, HUFFMAN_EMIT_SYMBOL, 183), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 163 - (2, HUFFMAN_EMIT_SYMBOL, 165), - (9, HUFFMAN_EMIT_SYMBOL, 165), - (23, HUFFMAN_EMIT_SYMBOL, 165), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (2, HUFFMAN_EMIT_SYMBOL, 166), - (9, HUFFMAN_EMIT_SYMBOL, 166), - (23, HUFFMAN_EMIT_SYMBOL, 166), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - (2, HUFFMAN_EMIT_SYMBOL, 168), - (9, HUFFMAN_EMIT_SYMBOL, 168), - (23, HUFFMAN_EMIT_SYMBOL, 168), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (2, HUFFMAN_EMIT_SYMBOL, 174), - (9, HUFFMAN_EMIT_SYMBOL, 174), - (23, HUFFMAN_EMIT_SYMBOL, 174), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - - # Node 164 - (3, HUFFMAN_EMIT_SYMBOL, 165), - (6, HUFFMAN_EMIT_SYMBOL, 165), - (10, HUFFMAN_EMIT_SYMBOL, 165), - (15, HUFFMAN_EMIT_SYMBOL, 165), - (24, HUFFMAN_EMIT_SYMBOL, 165), - (31, HUFFMAN_EMIT_SYMBOL, 165), - (41, HUFFMAN_EMIT_SYMBOL, 165), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 165), - (3, HUFFMAN_EMIT_SYMBOL, 166), - (6, HUFFMAN_EMIT_SYMBOL, 166), - (10, HUFFMAN_EMIT_SYMBOL, 166), - (15, HUFFMAN_EMIT_SYMBOL, 166), - (24, HUFFMAN_EMIT_SYMBOL, 166), - (31, HUFFMAN_EMIT_SYMBOL, 166), - (41, HUFFMAN_EMIT_SYMBOL, 166), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 166), - - # Node 165 - (3, HUFFMAN_EMIT_SYMBOL, 168), - (6, HUFFMAN_EMIT_SYMBOL, 168), - (10, HUFFMAN_EMIT_SYMBOL, 168), - (15, HUFFMAN_EMIT_SYMBOL, 168), - (24, HUFFMAN_EMIT_SYMBOL, 168), - (31, HUFFMAN_EMIT_SYMBOL, 168), - (41, HUFFMAN_EMIT_SYMBOL, 168), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 168), - (3, HUFFMAN_EMIT_SYMBOL, 174), - (6, HUFFMAN_EMIT_SYMBOL, 174), - (10, HUFFMAN_EMIT_SYMBOL, 174), - (15, HUFFMAN_EMIT_SYMBOL, 174), - (24, HUFFMAN_EMIT_SYMBOL, 174), - (31, HUFFMAN_EMIT_SYMBOL, 174), - (41, HUFFMAN_EMIT_SYMBOL, 174), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 174), - - # Node 166 - (2, HUFFMAN_EMIT_SYMBOL, 175), - (9, HUFFMAN_EMIT_SYMBOL, 175), - (23, HUFFMAN_EMIT_SYMBOL, 175), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (2, HUFFMAN_EMIT_SYMBOL, 180), - (9, HUFFMAN_EMIT_SYMBOL, 180), - (23, HUFFMAN_EMIT_SYMBOL, 180), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - (2, HUFFMAN_EMIT_SYMBOL, 182), - (9, HUFFMAN_EMIT_SYMBOL, 182), - (23, HUFFMAN_EMIT_SYMBOL, 182), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (2, HUFFMAN_EMIT_SYMBOL, 183), - (9, HUFFMAN_EMIT_SYMBOL, 183), - (23, HUFFMAN_EMIT_SYMBOL, 183), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 167 - (3, HUFFMAN_EMIT_SYMBOL, 175), - (6, HUFFMAN_EMIT_SYMBOL, 175), - (10, HUFFMAN_EMIT_SYMBOL, 175), - (15, HUFFMAN_EMIT_SYMBOL, 175), - (24, HUFFMAN_EMIT_SYMBOL, 175), - (31, HUFFMAN_EMIT_SYMBOL, 175), - (41, HUFFMAN_EMIT_SYMBOL, 175), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 175), - (3, HUFFMAN_EMIT_SYMBOL, 180), - (6, HUFFMAN_EMIT_SYMBOL, 180), - (10, HUFFMAN_EMIT_SYMBOL, 180), - (15, HUFFMAN_EMIT_SYMBOL, 180), - (24, HUFFMAN_EMIT_SYMBOL, 180), - (31, HUFFMAN_EMIT_SYMBOL, 180), - (41, HUFFMAN_EMIT_SYMBOL, 180), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 180), - - # Node 168 - (3, HUFFMAN_EMIT_SYMBOL, 182), - (6, HUFFMAN_EMIT_SYMBOL, 182), - (10, HUFFMAN_EMIT_SYMBOL, 182), - (15, HUFFMAN_EMIT_SYMBOL, 182), - (24, HUFFMAN_EMIT_SYMBOL, 182), - (31, HUFFMAN_EMIT_SYMBOL, 182), - (41, HUFFMAN_EMIT_SYMBOL, 182), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 182), - (3, HUFFMAN_EMIT_SYMBOL, 183), - (6, HUFFMAN_EMIT_SYMBOL, 183), - (10, HUFFMAN_EMIT_SYMBOL, 183), - (15, HUFFMAN_EMIT_SYMBOL, 183), - (24, HUFFMAN_EMIT_SYMBOL, 183), - (31, HUFFMAN_EMIT_SYMBOL, 183), - (41, HUFFMAN_EMIT_SYMBOL, 183), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 183), - - # Node 169 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (176, 0, 0), - (178, 0, 0), - (179, 0, 0), - (183, 0, 0), - (184, 0, 0), - (186, 0, 0), - (187, 0, 0), - (192, 0, 0), - (199, 0, 0), - (208, 0, 0), - (223, 0, 0), - - # Node 170 - (1, HUFFMAN_EMIT_SYMBOL, 188), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (1, HUFFMAN_EMIT_SYMBOL, 191), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (1, HUFFMAN_EMIT_SYMBOL, 197), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (1, HUFFMAN_EMIT_SYMBOL, 231), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - (1, HUFFMAN_EMIT_SYMBOL, 239), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 171 - (2, HUFFMAN_EMIT_SYMBOL, 188), - (9, HUFFMAN_EMIT_SYMBOL, 188), - (23, HUFFMAN_EMIT_SYMBOL, 188), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (2, HUFFMAN_EMIT_SYMBOL, 191), - (9, HUFFMAN_EMIT_SYMBOL, 191), - (23, HUFFMAN_EMIT_SYMBOL, 191), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - (2, HUFFMAN_EMIT_SYMBOL, 197), - (9, HUFFMAN_EMIT_SYMBOL, 197), - (23, HUFFMAN_EMIT_SYMBOL, 197), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (2, HUFFMAN_EMIT_SYMBOL, 231), - (9, HUFFMAN_EMIT_SYMBOL, 231), - (23, HUFFMAN_EMIT_SYMBOL, 231), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - - # Node 172 - (3, HUFFMAN_EMIT_SYMBOL, 188), - (6, HUFFMAN_EMIT_SYMBOL, 188), - (10, HUFFMAN_EMIT_SYMBOL, 188), - (15, HUFFMAN_EMIT_SYMBOL, 188), - (24, HUFFMAN_EMIT_SYMBOL, 188), - (31, HUFFMAN_EMIT_SYMBOL, 188), - (41, HUFFMAN_EMIT_SYMBOL, 188), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 188), - (3, HUFFMAN_EMIT_SYMBOL, 191), - (6, HUFFMAN_EMIT_SYMBOL, 191), - (10, HUFFMAN_EMIT_SYMBOL, 191), - (15, HUFFMAN_EMIT_SYMBOL, 191), - (24, HUFFMAN_EMIT_SYMBOL, 191), - (31, HUFFMAN_EMIT_SYMBOL, 191), - (41, HUFFMAN_EMIT_SYMBOL, 191), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 191), - - # Node 173 - (3, HUFFMAN_EMIT_SYMBOL, 197), - (6, HUFFMAN_EMIT_SYMBOL, 197), - (10, HUFFMAN_EMIT_SYMBOL, 197), - (15, HUFFMAN_EMIT_SYMBOL, 197), - (24, HUFFMAN_EMIT_SYMBOL, 197), - (31, HUFFMAN_EMIT_SYMBOL, 197), - (41, HUFFMAN_EMIT_SYMBOL, 197), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 197), - (3, HUFFMAN_EMIT_SYMBOL, 231), - (6, HUFFMAN_EMIT_SYMBOL, 231), - (10, HUFFMAN_EMIT_SYMBOL, 231), - (15, HUFFMAN_EMIT_SYMBOL, 231), - (24, HUFFMAN_EMIT_SYMBOL, 231), - (31, HUFFMAN_EMIT_SYMBOL, 231), - (41, HUFFMAN_EMIT_SYMBOL, 231), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 231), - - # Node 174 - (2, HUFFMAN_EMIT_SYMBOL, 239), - (9, HUFFMAN_EMIT_SYMBOL, 239), - (23, HUFFMAN_EMIT_SYMBOL, 239), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (1, HUFFMAN_EMIT_SYMBOL, 9), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (1, HUFFMAN_EMIT_SYMBOL, 142), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - (1, HUFFMAN_EMIT_SYMBOL, 144), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (1, HUFFMAN_EMIT_SYMBOL, 145), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (1, HUFFMAN_EMIT_SYMBOL, 148), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (1, HUFFMAN_EMIT_SYMBOL, 159), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 175 - (3, HUFFMAN_EMIT_SYMBOL, 239), - (6, HUFFMAN_EMIT_SYMBOL, 239), - (10, HUFFMAN_EMIT_SYMBOL, 239), - (15, HUFFMAN_EMIT_SYMBOL, 239), - (24, HUFFMAN_EMIT_SYMBOL, 239), - (31, HUFFMAN_EMIT_SYMBOL, 239), - (41, HUFFMAN_EMIT_SYMBOL, 239), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 239), - (2, HUFFMAN_EMIT_SYMBOL, 9), - (9, HUFFMAN_EMIT_SYMBOL, 9), - (23, HUFFMAN_EMIT_SYMBOL, 9), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (2, HUFFMAN_EMIT_SYMBOL, 142), - (9, HUFFMAN_EMIT_SYMBOL, 142), - (23, HUFFMAN_EMIT_SYMBOL, 142), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - - # Node 176 - (3, HUFFMAN_EMIT_SYMBOL, 9), - (6, HUFFMAN_EMIT_SYMBOL, 9), - (10, HUFFMAN_EMIT_SYMBOL, 9), - (15, HUFFMAN_EMIT_SYMBOL, 9), - (24, HUFFMAN_EMIT_SYMBOL, 9), - (31, HUFFMAN_EMIT_SYMBOL, 9), - (41, HUFFMAN_EMIT_SYMBOL, 9), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 9), - (3, HUFFMAN_EMIT_SYMBOL, 142), - (6, HUFFMAN_EMIT_SYMBOL, 142), - (10, HUFFMAN_EMIT_SYMBOL, 142), - (15, HUFFMAN_EMIT_SYMBOL, 142), - (24, HUFFMAN_EMIT_SYMBOL, 142), - (31, HUFFMAN_EMIT_SYMBOL, 142), - (41, HUFFMAN_EMIT_SYMBOL, 142), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 142), - - # Node 177 - (2, HUFFMAN_EMIT_SYMBOL, 144), - (9, HUFFMAN_EMIT_SYMBOL, 144), - (23, HUFFMAN_EMIT_SYMBOL, 144), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (2, HUFFMAN_EMIT_SYMBOL, 145), - (9, HUFFMAN_EMIT_SYMBOL, 145), - (23, HUFFMAN_EMIT_SYMBOL, 145), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - (2, HUFFMAN_EMIT_SYMBOL, 148), - (9, HUFFMAN_EMIT_SYMBOL, 148), - (23, HUFFMAN_EMIT_SYMBOL, 148), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (2, HUFFMAN_EMIT_SYMBOL, 159), - (9, HUFFMAN_EMIT_SYMBOL, 159), - (23, HUFFMAN_EMIT_SYMBOL, 159), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 178 - (3, HUFFMAN_EMIT_SYMBOL, 144), - (6, HUFFMAN_EMIT_SYMBOL, 144), - (10, HUFFMAN_EMIT_SYMBOL, 144), - (15, HUFFMAN_EMIT_SYMBOL, 144), - (24, HUFFMAN_EMIT_SYMBOL, 144), - (31, HUFFMAN_EMIT_SYMBOL, 144), - (41, HUFFMAN_EMIT_SYMBOL, 144), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 144), - (3, HUFFMAN_EMIT_SYMBOL, 145), - (6, HUFFMAN_EMIT_SYMBOL, 145), - (10, HUFFMAN_EMIT_SYMBOL, 145), - (15, HUFFMAN_EMIT_SYMBOL, 145), - (24, HUFFMAN_EMIT_SYMBOL, 145), - (31, HUFFMAN_EMIT_SYMBOL, 145), - (41, HUFFMAN_EMIT_SYMBOL, 145), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 145), - - # Node 179 - (3, HUFFMAN_EMIT_SYMBOL, 148), - (6, HUFFMAN_EMIT_SYMBOL, 148), - (10, HUFFMAN_EMIT_SYMBOL, 148), - (15, HUFFMAN_EMIT_SYMBOL, 148), - (24, HUFFMAN_EMIT_SYMBOL, 148), - (31, HUFFMAN_EMIT_SYMBOL, 148), - (41, HUFFMAN_EMIT_SYMBOL, 148), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 148), - (3, HUFFMAN_EMIT_SYMBOL, 159), - (6, HUFFMAN_EMIT_SYMBOL, 159), - (10, HUFFMAN_EMIT_SYMBOL, 159), - (15, HUFFMAN_EMIT_SYMBOL, 159), - (24, HUFFMAN_EMIT_SYMBOL, 159), - (31, HUFFMAN_EMIT_SYMBOL, 159), - (41, HUFFMAN_EMIT_SYMBOL, 159), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 159), - - # Node 180 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (188, 0, 0), - (189, 0, 0), - (193, 0, 0), - (196, 0, 0), - (200, 0, 0), - (203, 0, 0), - (209, 0, 0), - (216, 0, 0), - (224, 0, 0), - (238, 0, 0), - - # Node 181 - (1, HUFFMAN_EMIT_SYMBOL, 171), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (1, HUFFMAN_EMIT_SYMBOL, 206), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (1, HUFFMAN_EMIT_SYMBOL, 215), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (1, HUFFMAN_EMIT_SYMBOL, 225), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - (1, HUFFMAN_EMIT_SYMBOL, 236), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (1, HUFFMAN_EMIT_SYMBOL, 237), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 182 - (2, HUFFMAN_EMIT_SYMBOL, 171), - (9, HUFFMAN_EMIT_SYMBOL, 171), - (23, HUFFMAN_EMIT_SYMBOL, 171), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (2, HUFFMAN_EMIT_SYMBOL, 206), - (9, HUFFMAN_EMIT_SYMBOL, 206), - (23, HUFFMAN_EMIT_SYMBOL, 206), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - (2, HUFFMAN_EMIT_SYMBOL, 215), - (9, HUFFMAN_EMIT_SYMBOL, 215), - (23, HUFFMAN_EMIT_SYMBOL, 215), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (2, HUFFMAN_EMIT_SYMBOL, 225), - (9, HUFFMAN_EMIT_SYMBOL, 225), - (23, HUFFMAN_EMIT_SYMBOL, 225), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - - # Node 183 - (3, HUFFMAN_EMIT_SYMBOL, 171), - (6, HUFFMAN_EMIT_SYMBOL, 171), - (10, HUFFMAN_EMIT_SYMBOL, 171), - (15, HUFFMAN_EMIT_SYMBOL, 171), - (24, HUFFMAN_EMIT_SYMBOL, 171), - (31, HUFFMAN_EMIT_SYMBOL, 171), - (41, HUFFMAN_EMIT_SYMBOL, 171), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 171), - (3, HUFFMAN_EMIT_SYMBOL, 206), - (6, HUFFMAN_EMIT_SYMBOL, 206), - (10, HUFFMAN_EMIT_SYMBOL, 206), - (15, HUFFMAN_EMIT_SYMBOL, 206), - (24, HUFFMAN_EMIT_SYMBOL, 206), - (31, HUFFMAN_EMIT_SYMBOL, 206), - (41, HUFFMAN_EMIT_SYMBOL, 206), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 206), - - # Node 184 - (3, HUFFMAN_EMIT_SYMBOL, 215), - (6, HUFFMAN_EMIT_SYMBOL, 215), - (10, HUFFMAN_EMIT_SYMBOL, 215), - (15, HUFFMAN_EMIT_SYMBOL, 215), - (24, HUFFMAN_EMIT_SYMBOL, 215), - (31, HUFFMAN_EMIT_SYMBOL, 215), - (41, HUFFMAN_EMIT_SYMBOL, 215), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 215), - (3, HUFFMAN_EMIT_SYMBOL, 225), - (6, HUFFMAN_EMIT_SYMBOL, 225), - (10, HUFFMAN_EMIT_SYMBOL, 225), - (15, HUFFMAN_EMIT_SYMBOL, 225), - (24, HUFFMAN_EMIT_SYMBOL, 225), - (31, HUFFMAN_EMIT_SYMBOL, 225), - (41, HUFFMAN_EMIT_SYMBOL, 225), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 225), - - # Node 185 - (2, HUFFMAN_EMIT_SYMBOL, 236), - (9, HUFFMAN_EMIT_SYMBOL, 236), - (23, HUFFMAN_EMIT_SYMBOL, 236), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (2, HUFFMAN_EMIT_SYMBOL, 237), - (9, HUFFMAN_EMIT_SYMBOL, 237), - (23, HUFFMAN_EMIT_SYMBOL, 237), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - (1, HUFFMAN_EMIT_SYMBOL, 199), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (1, HUFFMAN_EMIT_SYMBOL, 207), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (1, HUFFMAN_EMIT_SYMBOL, 234), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (1, HUFFMAN_EMIT_SYMBOL, 235), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 186 - (3, HUFFMAN_EMIT_SYMBOL, 236), - (6, HUFFMAN_EMIT_SYMBOL, 236), - (10, HUFFMAN_EMIT_SYMBOL, 236), - (15, HUFFMAN_EMIT_SYMBOL, 236), - (24, HUFFMAN_EMIT_SYMBOL, 236), - (31, HUFFMAN_EMIT_SYMBOL, 236), - (41, HUFFMAN_EMIT_SYMBOL, 236), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 236), - (3, HUFFMAN_EMIT_SYMBOL, 237), - (6, HUFFMAN_EMIT_SYMBOL, 237), - (10, HUFFMAN_EMIT_SYMBOL, 237), - (15, HUFFMAN_EMIT_SYMBOL, 237), - (24, HUFFMAN_EMIT_SYMBOL, 237), - (31, HUFFMAN_EMIT_SYMBOL, 237), - (41, HUFFMAN_EMIT_SYMBOL, 237), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 237), - - # Node 187 - (2, HUFFMAN_EMIT_SYMBOL, 199), - (9, HUFFMAN_EMIT_SYMBOL, 199), - (23, HUFFMAN_EMIT_SYMBOL, 199), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (2, HUFFMAN_EMIT_SYMBOL, 207), - (9, HUFFMAN_EMIT_SYMBOL, 207), - (23, HUFFMAN_EMIT_SYMBOL, 207), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - (2, HUFFMAN_EMIT_SYMBOL, 234), - (9, HUFFMAN_EMIT_SYMBOL, 234), - (23, HUFFMAN_EMIT_SYMBOL, 234), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (2, HUFFMAN_EMIT_SYMBOL, 235), - (9, HUFFMAN_EMIT_SYMBOL, 235), - (23, HUFFMAN_EMIT_SYMBOL, 235), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 188 - (3, HUFFMAN_EMIT_SYMBOL, 199), - (6, HUFFMAN_EMIT_SYMBOL, 199), - (10, HUFFMAN_EMIT_SYMBOL, 199), - (15, HUFFMAN_EMIT_SYMBOL, 199), - (24, HUFFMAN_EMIT_SYMBOL, 199), - (31, HUFFMAN_EMIT_SYMBOL, 199), - (41, HUFFMAN_EMIT_SYMBOL, 199), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 199), - (3, HUFFMAN_EMIT_SYMBOL, 207), - (6, HUFFMAN_EMIT_SYMBOL, 207), - (10, HUFFMAN_EMIT_SYMBOL, 207), - (15, HUFFMAN_EMIT_SYMBOL, 207), - (24, HUFFMAN_EMIT_SYMBOL, 207), - (31, HUFFMAN_EMIT_SYMBOL, 207), - (41, HUFFMAN_EMIT_SYMBOL, 207), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 207), - - # Node 189 - (3, HUFFMAN_EMIT_SYMBOL, 234), - (6, HUFFMAN_EMIT_SYMBOL, 234), - (10, HUFFMAN_EMIT_SYMBOL, 234), - (15, HUFFMAN_EMIT_SYMBOL, 234), - (24, HUFFMAN_EMIT_SYMBOL, 234), - (31, HUFFMAN_EMIT_SYMBOL, 234), - (41, HUFFMAN_EMIT_SYMBOL, 234), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 234), - (3, HUFFMAN_EMIT_SYMBOL, 235), - (6, HUFFMAN_EMIT_SYMBOL, 235), - (10, HUFFMAN_EMIT_SYMBOL, 235), - (15, HUFFMAN_EMIT_SYMBOL, 235), - (24, HUFFMAN_EMIT_SYMBOL, 235), - (31, HUFFMAN_EMIT_SYMBOL, 235), - (41, HUFFMAN_EMIT_SYMBOL, 235), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 235), - - # Node 190 - (194, 0, 0), - (195, 0, 0), - (197, 0, 0), - (198, 0, 0), - (201, 0, 0), - (202, 0, 0), - (204, 0, 0), - (205, 0, 0), - (210, 0, 0), - (213, 0, 0), - (217, 0, 0), - (220, 0, 0), - (225, 0, 0), - (231, 0, 0), - (239, 0, 0), - (246, 0, 0), - - # Node 191 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (206, 0, 0), - - # Node 192 - (1, HUFFMAN_EMIT_SYMBOL, 192), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (1, HUFFMAN_EMIT_SYMBOL, 193), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (1, HUFFMAN_EMIT_SYMBOL, 200), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (1, HUFFMAN_EMIT_SYMBOL, 201), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - (1, HUFFMAN_EMIT_SYMBOL, 202), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (1, HUFFMAN_EMIT_SYMBOL, 205), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (1, HUFFMAN_EMIT_SYMBOL, 210), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (1, HUFFMAN_EMIT_SYMBOL, 213), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 193 - (2, HUFFMAN_EMIT_SYMBOL, 192), - (9, HUFFMAN_EMIT_SYMBOL, 192), - (23, HUFFMAN_EMIT_SYMBOL, 192), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (2, HUFFMAN_EMIT_SYMBOL, 193), - (9, HUFFMAN_EMIT_SYMBOL, 193), - (23, HUFFMAN_EMIT_SYMBOL, 193), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - (2, HUFFMAN_EMIT_SYMBOL, 200), - (9, HUFFMAN_EMIT_SYMBOL, 200), - (23, HUFFMAN_EMIT_SYMBOL, 200), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (2, HUFFMAN_EMIT_SYMBOL, 201), - (9, HUFFMAN_EMIT_SYMBOL, 201), - (23, HUFFMAN_EMIT_SYMBOL, 201), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - - # Node 194 - (3, HUFFMAN_EMIT_SYMBOL, 192), - (6, HUFFMAN_EMIT_SYMBOL, 192), - (10, HUFFMAN_EMIT_SYMBOL, 192), - (15, HUFFMAN_EMIT_SYMBOL, 192), - (24, HUFFMAN_EMIT_SYMBOL, 192), - (31, HUFFMAN_EMIT_SYMBOL, 192), - (41, HUFFMAN_EMIT_SYMBOL, 192), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 192), - (3, HUFFMAN_EMIT_SYMBOL, 193), - (6, HUFFMAN_EMIT_SYMBOL, 193), - (10, HUFFMAN_EMIT_SYMBOL, 193), - (15, HUFFMAN_EMIT_SYMBOL, 193), - (24, HUFFMAN_EMIT_SYMBOL, 193), - (31, HUFFMAN_EMIT_SYMBOL, 193), - (41, HUFFMAN_EMIT_SYMBOL, 193), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 193), - - # Node 195 - (3, HUFFMAN_EMIT_SYMBOL, 200), - (6, HUFFMAN_EMIT_SYMBOL, 200), - (10, HUFFMAN_EMIT_SYMBOL, 200), - (15, HUFFMAN_EMIT_SYMBOL, 200), - (24, HUFFMAN_EMIT_SYMBOL, 200), - (31, HUFFMAN_EMIT_SYMBOL, 200), - (41, HUFFMAN_EMIT_SYMBOL, 200), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 200), - (3, HUFFMAN_EMIT_SYMBOL, 201), - (6, HUFFMAN_EMIT_SYMBOL, 201), - (10, HUFFMAN_EMIT_SYMBOL, 201), - (15, HUFFMAN_EMIT_SYMBOL, 201), - (24, HUFFMAN_EMIT_SYMBOL, 201), - (31, HUFFMAN_EMIT_SYMBOL, 201), - (41, HUFFMAN_EMIT_SYMBOL, 201), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 201), - - # Node 196 - (2, HUFFMAN_EMIT_SYMBOL, 202), - (9, HUFFMAN_EMIT_SYMBOL, 202), - (23, HUFFMAN_EMIT_SYMBOL, 202), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (2, HUFFMAN_EMIT_SYMBOL, 205), - (9, HUFFMAN_EMIT_SYMBOL, 205), - (23, HUFFMAN_EMIT_SYMBOL, 205), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - (2, HUFFMAN_EMIT_SYMBOL, 210), - (9, HUFFMAN_EMIT_SYMBOL, 210), - (23, HUFFMAN_EMIT_SYMBOL, 210), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (2, HUFFMAN_EMIT_SYMBOL, 213), - (9, HUFFMAN_EMIT_SYMBOL, 213), - (23, HUFFMAN_EMIT_SYMBOL, 213), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 197 - (3, HUFFMAN_EMIT_SYMBOL, 202), - (6, HUFFMAN_EMIT_SYMBOL, 202), - (10, HUFFMAN_EMIT_SYMBOL, 202), - (15, HUFFMAN_EMIT_SYMBOL, 202), - (24, HUFFMAN_EMIT_SYMBOL, 202), - (31, HUFFMAN_EMIT_SYMBOL, 202), - (41, HUFFMAN_EMIT_SYMBOL, 202), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 202), - (3, HUFFMAN_EMIT_SYMBOL, 205), - (6, HUFFMAN_EMIT_SYMBOL, 205), - (10, HUFFMAN_EMIT_SYMBOL, 205), - (15, HUFFMAN_EMIT_SYMBOL, 205), - (24, HUFFMAN_EMIT_SYMBOL, 205), - (31, HUFFMAN_EMIT_SYMBOL, 205), - (41, HUFFMAN_EMIT_SYMBOL, 205), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 205), - - # Node 198 - (3, HUFFMAN_EMIT_SYMBOL, 210), - (6, HUFFMAN_EMIT_SYMBOL, 210), - (10, HUFFMAN_EMIT_SYMBOL, 210), - (15, HUFFMAN_EMIT_SYMBOL, 210), - (24, HUFFMAN_EMIT_SYMBOL, 210), - (31, HUFFMAN_EMIT_SYMBOL, 210), - (41, HUFFMAN_EMIT_SYMBOL, 210), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 210), - (3, HUFFMAN_EMIT_SYMBOL, 213), - (6, HUFFMAN_EMIT_SYMBOL, 213), - (10, HUFFMAN_EMIT_SYMBOL, 213), - (15, HUFFMAN_EMIT_SYMBOL, 213), - (24, HUFFMAN_EMIT_SYMBOL, 213), - (31, HUFFMAN_EMIT_SYMBOL, 213), - (41, HUFFMAN_EMIT_SYMBOL, 213), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 213), - - # Node 199 - (1, HUFFMAN_EMIT_SYMBOL, 218), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (1, HUFFMAN_EMIT_SYMBOL, 219), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (1, HUFFMAN_EMIT_SYMBOL, 238), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (1, HUFFMAN_EMIT_SYMBOL, 240), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - (1, HUFFMAN_EMIT_SYMBOL, 242), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (1, HUFFMAN_EMIT_SYMBOL, 243), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (1, HUFFMAN_EMIT_SYMBOL, 255), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 200 - (2, HUFFMAN_EMIT_SYMBOL, 218), - (9, HUFFMAN_EMIT_SYMBOL, 218), - (23, HUFFMAN_EMIT_SYMBOL, 218), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (2, HUFFMAN_EMIT_SYMBOL, 219), - (9, HUFFMAN_EMIT_SYMBOL, 219), - (23, HUFFMAN_EMIT_SYMBOL, 219), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - (2, HUFFMAN_EMIT_SYMBOL, 238), - (9, HUFFMAN_EMIT_SYMBOL, 238), - (23, HUFFMAN_EMIT_SYMBOL, 238), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (2, HUFFMAN_EMIT_SYMBOL, 240), - (9, HUFFMAN_EMIT_SYMBOL, 240), - (23, HUFFMAN_EMIT_SYMBOL, 240), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - - # Node 201 - (3, HUFFMAN_EMIT_SYMBOL, 218), - (6, HUFFMAN_EMIT_SYMBOL, 218), - (10, HUFFMAN_EMIT_SYMBOL, 218), - (15, HUFFMAN_EMIT_SYMBOL, 218), - (24, HUFFMAN_EMIT_SYMBOL, 218), - (31, HUFFMAN_EMIT_SYMBOL, 218), - (41, HUFFMAN_EMIT_SYMBOL, 218), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 218), - (3, HUFFMAN_EMIT_SYMBOL, 219), - (6, HUFFMAN_EMIT_SYMBOL, 219), - (10, HUFFMAN_EMIT_SYMBOL, 219), - (15, HUFFMAN_EMIT_SYMBOL, 219), - (24, HUFFMAN_EMIT_SYMBOL, 219), - (31, HUFFMAN_EMIT_SYMBOL, 219), - (41, HUFFMAN_EMIT_SYMBOL, 219), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 219), - - # Node 202 - (3, HUFFMAN_EMIT_SYMBOL, 238), - (6, HUFFMAN_EMIT_SYMBOL, 238), - (10, HUFFMAN_EMIT_SYMBOL, 238), - (15, HUFFMAN_EMIT_SYMBOL, 238), - (24, HUFFMAN_EMIT_SYMBOL, 238), - (31, HUFFMAN_EMIT_SYMBOL, 238), - (41, HUFFMAN_EMIT_SYMBOL, 238), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 238), - (3, HUFFMAN_EMIT_SYMBOL, 240), - (6, HUFFMAN_EMIT_SYMBOL, 240), - (10, HUFFMAN_EMIT_SYMBOL, 240), - (15, HUFFMAN_EMIT_SYMBOL, 240), - (24, HUFFMAN_EMIT_SYMBOL, 240), - (31, HUFFMAN_EMIT_SYMBOL, 240), - (41, HUFFMAN_EMIT_SYMBOL, 240), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 240), - - # Node 203 - (2, HUFFMAN_EMIT_SYMBOL, 242), - (9, HUFFMAN_EMIT_SYMBOL, 242), - (23, HUFFMAN_EMIT_SYMBOL, 242), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (2, HUFFMAN_EMIT_SYMBOL, 243), - (9, HUFFMAN_EMIT_SYMBOL, 243), - (23, HUFFMAN_EMIT_SYMBOL, 243), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - (2, HUFFMAN_EMIT_SYMBOL, 255), - (9, HUFFMAN_EMIT_SYMBOL, 255), - (23, HUFFMAN_EMIT_SYMBOL, 255), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (1, HUFFMAN_EMIT_SYMBOL, 203), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (1, HUFFMAN_EMIT_SYMBOL, 204), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 204 - (3, HUFFMAN_EMIT_SYMBOL, 242), - (6, HUFFMAN_EMIT_SYMBOL, 242), - (10, HUFFMAN_EMIT_SYMBOL, 242), - (15, HUFFMAN_EMIT_SYMBOL, 242), - (24, HUFFMAN_EMIT_SYMBOL, 242), - (31, HUFFMAN_EMIT_SYMBOL, 242), - (41, HUFFMAN_EMIT_SYMBOL, 242), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 242), - (3, HUFFMAN_EMIT_SYMBOL, 243), - (6, HUFFMAN_EMIT_SYMBOL, 243), - (10, HUFFMAN_EMIT_SYMBOL, 243), - (15, HUFFMAN_EMIT_SYMBOL, 243), - (24, HUFFMAN_EMIT_SYMBOL, 243), - (31, HUFFMAN_EMIT_SYMBOL, 243), - (41, HUFFMAN_EMIT_SYMBOL, 243), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 243), - - # Node 205 - (3, HUFFMAN_EMIT_SYMBOL, 255), - (6, HUFFMAN_EMIT_SYMBOL, 255), - (10, HUFFMAN_EMIT_SYMBOL, 255), - (15, HUFFMAN_EMIT_SYMBOL, 255), - (24, HUFFMAN_EMIT_SYMBOL, 255), - (31, HUFFMAN_EMIT_SYMBOL, 255), - (41, HUFFMAN_EMIT_SYMBOL, 255), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 255), - (2, HUFFMAN_EMIT_SYMBOL, 203), - (9, HUFFMAN_EMIT_SYMBOL, 203), - (23, HUFFMAN_EMIT_SYMBOL, 203), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (2, HUFFMAN_EMIT_SYMBOL, 204), - (9, HUFFMAN_EMIT_SYMBOL, 204), - (23, HUFFMAN_EMIT_SYMBOL, 204), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 206 - (3, HUFFMAN_EMIT_SYMBOL, 203), - (6, HUFFMAN_EMIT_SYMBOL, 203), - (10, HUFFMAN_EMIT_SYMBOL, 203), - (15, HUFFMAN_EMIT_SYMBOL, 203), - (24, HUFFMAN_EMIT_SYMBOL, 203), - (31, HUFFMAN_EMIT_SYMBOL, 203), - (41, HUFFMAN_EMIT_SYMBOL, 203), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 203), - (3, HUFFMAN_EMIT_SYMBOL, 204), - (6, HUFFMAN_EMIT_SYMBOL, 204), - (10, HUFFMAN_EMIT_SYMBOL, 204), - (15, HUFFMAN_EMIT_SYMBOL, 204), - (24, HUFFMAN_EMIT_SYMBOL, 204), - (31, HUFFMAN_EMIT_SYMBOL, 204), - (41, HUFFMAN_EMIT_SYMBOL, 204), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 204), - - # Node 207 - (211, 0, 0), - (212, 0, 0), - (214, 0, 0), - (215, 0, 0), - (218, 0, 0), - (219, 0, 0), - (221, 0, 0), - (222, 0, 0), - (226, 0, 0), - (228, 0, 0), - (232, 0, 0), - (235, 0, 0), - (240, 0, 0), - (243, 0, 0), - (247, 0, 0), - (250, 0, 0), - - # Node 208 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 209 - (1, HUFFMAN_EMIT_SYMBOL, 211), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (1, HUFFMAN_EMIT_SYMBOL, 212), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (1, HUFFMAN_EMIT_SYMBOL, 214), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (1, HUFFMAN_EMIT_SYMBOL, 221), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - (1, HUFFMAN_EMIT_SYMBOL, 222), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (1, HUFFMAN_EMIT_SYMBOL, 223), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (1, HUFFMAN_EMIT_SYMBOL, 241), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (1, HUFFMAN_EMIT_SYMBOL, 244), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 210 - (2, HUFFMAN_EMIT_SYMBOL, 211), - (9, HUFFMAN_EMIT_SYMBOL, 211), - (23, HUFFMAN_EMIT_SYMBOL, 211), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (2, HUFFMAN_EMIT_SYMBOL, 212), - (9, HUFFMAN_EMIT_SYMBOL, 212), - (23, HUFFMAN_EMIT_SYMBOL, 212), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - (2, HUFFMAN_EMIT_SYMBOL, 214), - (9, HUFFMAN_EMIT_SYMBOL, 214), - (23, HUFFMAN_EMIT_SYMBOL, 214), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (2, HUFFMAN_EMIT_SYMBOL, 221), - (9, HUFFMAN_EMIT_SYMBOL, 221), - (23, HUFFMAN_EMIT_SYMBOL, 221), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - - # Node 211 - (3, HUFFMAN_EMIT_SYMBOL, 211), - (6, HUFFMAN_EMIT_SYMBOL, 211), - (10, HUFFMAN_EMIT_SYMBOL, 211), - (15, HUFFMAN_EMIT_SYMBOL, 211), - (24, HUFFMAN_EMIT_SYMBOL, 211), - (31, HUFFMAN_EMIT_SYMBOL, 211), - (41, HUFFMAN_EMIT_SYMBOL, 211), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 211), - (3, HUFFMAN_EMIT_SYMBOL, 212), - (6, HUFFMAN_EMIT_SYMBOL, 212), - (10, HUFFMAN_EMIT_SYMBOL, 212), - (15, HUFFMAN_EMIT_SYMBOL, 212), - (24, HUFFMAN_EMIT_SYMBOL, 212), - (31, HUFFMAN_EMIT_SYMBOL, 212), - (41, HUFFMAN_EMIT_SYMBOL, 212), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 212), - - # Node 212 - (3, HUFFMAN_EMIT_SYMBOL, 214), - (6, HUFFMAN_EMIT_SYMBOL, 214), - (10, HUFFMAN_EMIT_SYMBOL, 214), - (15, HUFFMAN_EMIT_SYMBOL, 214), - (24, HUFFMAN_EMIT_SYMBOL, 214), - (31, HUFFMAN_EMIT_SYMBOL, 214), - (41, HUFFMAN_EMIT_SYMBOL, 214), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 214), - (3, HUFFMAN_EMIT_SYMBOL, 221), - (6, HUFFMAN_EMIT_SYMBOL, 221), - (10, HUFFMAN_EMIT_SYMBOL, 221), - (15, HUFFMAN_EMIT_SYMBOL, 221), - (24, HUFFMAN_EMIT_SYMBOL, 221), - (31, HUFFMAN_EMIT_SYMBOL, 221), - (41, HUFFMAN_EMIT_SYMBOL, 221), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 221), - - # Node 213 - (2, HUFFMAN_EMIT_SYMBOL, 222), - (9, HUFFMAN_EMIT_SYMBOL, 222), - (23, HUFFMAN_EMIT_SYMBOL, 222), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (2, HUFFMAN_EMIT_SYMBOL, 223), - (9, HUFFMAN_EMIT_SYMBOL, 223), - (23, HUFFMAN_EMIT_SYMBOL, 223), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - (2, HUFFMAN_EMIT_SYMBOL, 241), - (9, HUFFMAN_EMIT_SYMBOL, 241), - (23, HUFFMAN_EMIT_SYMBOL, 241), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (2, HUFFMAN_EMIT_SYMBOL, 244), - (9, HUFFMAN_EMIT_SYMBOL, 244), - (23, HUFFMAN_EMIT_SYMBOL, 244), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 214 - (3, HUFFMAN_EMIT_SYMBOL, 222), - (6, HUFFMAN_EMIT_SYMBOL, 222), - (10, HUFFMAN_EMIT_SYMBOL, 222), - (15, HUFFMAN_EMIT_SYMBOL, 222), - (24, HUFFMAN_EMIT_SYMBOL, 222), - (31, HUFFMAN_EMIT_SYMBOL, 222), - (41, HUFFMAN_EMIT_SYMBOL, 222), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 222), - (3, HUFFMAN_EMIT_SYMBOL, 223), - (6, HUFFMAN_EMIT_SYMBOL, 223), - (10, HUFFMAN_EMIT_SYMBOL, 223), - (15, HUFFMAN_EMIT_SYMBOL, 223), - (24, HUFFMAN_EMIT_SYMBOL, 223), - (31, HUFFMAN_EMIT_SYMBOL, 223), - (41, HUFFMAN_EMIT_SYMBOL, 223), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 223), - - # Node 215 - (3, HUFFMAN_EMIT_SYMBOL, 241), - (6, HUFFMAN_EMIT_SYMBOL, 241), - (10, HUFFMAN_EMIT_SYMBOL, 241), - (15, HUFFMAN_EMIT_SYMBOL, 241), - (24, HUFFMAN_EMIT_SYMBOL, 241), - (31, HUFFMAN_EMIT_SYMBOL, 241), - (41, HUFFMAN_EMIT_SYMBOL, 241), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 241), - (3, HUFFMAN_EMIT_SYMBOL, 244), - (6, HUFFMAN_EMIT_SYMBOL, 244), - (10, HUFFMAN_EMIT_SYMBOL, 244), - (15, HUFFMAN_EMIT_SYMBOL, 244), - (24, HUFFMAN_EMIT_SYMBOL, 244), - (31, HUFFMAN_EMIT_SYMBOL, 244), - (41, HUFFMAN_EMIT_SYMBOL, 244), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 244), - - # Node 216 - (1, HUFFMAN_EMIT_SYMBOL, 245), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (1, HUFFMAN_EMIT_SYMBOL, 246), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (1, HUFFMAN_EMIT_SYMBOL, 247), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (1, HUFFMAN_EMIT_SYMBOL, 248), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - (1, HUFFMAN_EMIT_SYMBOL, 250), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (1, HUFFMAN_EMIT_SYMBOL, 251), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (1, HUFFMAN_EMIT_SYMBOL, 252), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (1, HUFFMAN_EMIT_SYMBOL, 253), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 217 - (2, HUFFMAN_EMIT_SYMBOL, 245), - (9, HUFFMAN_EMIT_SYMBOL, 245), - (23, HUFFMAN_EMIT_SYMBOL, 245), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (2, HUFFMAN_EMIT_SYMBOL, 246), - (9, HUFFMAN_EMIT_SYMBOL, 246), - (23, HUFFMAN_EMIT_SYMBOL, 246), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - (2, HUFFMAN_EMIT_SYMBOL, 247), - (9, HUFFMAN_EMIT_SYMBOL, 247), - (23, HUFFMAN_EMIT_SYMBOL, 247), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (2, HUFFMAN_EMIT_SYMBOL, 248), - (9, HUFFMAN_EMIT_SYMBOL, 248), - (23, HUFFMAN_EMIT_SYMBOL, 248), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - - # Node 218 - (3, HUFFMAN_EMIT_SYMBOL, 245), - (6, HUFFMAN_EMIT_SYMBOL, 245), - (10, HUFFMAN_EMIT_SYMBOL, 245), - (15, HUFFMAN_EMIT_SYMBOL, 245), - (24, HUFFMAN_EMIT_SYMBOL, 245), - (31, HUFFMAN_EMIT_SYMBOL, 245), - (41, HUFFMAN_EMIT_SYMBOL, 245), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 245), - (3, HUFFMAN_EMIT_SYMBOL, 246), - (6, HUFFMAN_EMIT_SYMBOL, 246), - (10, HUFFMAN_EMIT_SYMBOL, 246), - (15, HUFFMAN_EMIT_SYMBOL, 246), - (24, HUFFMAN_EMIT_SYMBOL, 246), - (31, HUFFMAN_EMIT_SYMBOL, 246), - (41, HUFFMAN_EMIT_SYMBOL, 246), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 246), - - # Node 219 - (3, HUFFMAN_EMIT_SYMBOL, 247), - (6, HUFFMAN_EMIT_SYMBOL, 247), - (10, HUFFMAN_EMIT_SYMBOL, 247), - (15, HUFFMAN_EMIT_SYMBOL, 247), - (24, HUFFMAN_EMIT_SYMBOL, 247), - (31, HUFFMAN_EMIT_SYMBOL, 247), - (41, HUFFMAN_EMIT_SYMBOL, 247), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 247), - (3, HUFFMAN_EMIT_SYMBOL, 248), - (6, HUFFMAN_EMIT_SYMBOL, 248), - (10, HUFFMAN_EMIT_SYMBOL, 248), - (15, HUFFMAN_EMIT_SYMBOL, 248), - (24, HUFFMAN_EMIT_SYMBOL, 248), - (31, HUFFMAN_EMIT_SYMBOL, 248), - (41, HUFFMAN_EMIT_SYMBOL, 248), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 248), - - # Node 220 - (2, HUFFMAN_EMIT_SYMBOL, 250), - (9, HUFFMAN_EMIT_SYMBOL, 250), - (23, HUFFMAN_EMIT_SYMBOL, 250), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (2, HUFFMAN_EMIT_SYMBOL, 251), - (9, HUFFMAN_EMIT_SYMBOL, 251), - (23, HUFFMAN_EMIT_SYMBOL, 251), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - (2, HUFFMAN_EMIT_SYMBOL, 252), - (9, HUFFMAN_EMIT_SYMBOL, 252), - (23, HUFFMAN_EMIT_SYMBOL, 252), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (2, HUFFMAN_EMIT_SYMBOL, 253), - (9, HUFFMAN_EMIT_SYMBOL, 253), - (23, HUFFMAN_EMIT_SYMBOL, 253), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 221 - (3, HUFFMAN_EMIT_SYMBOL, 250), - (6, HUFFMAN_EMIT_SYMBOL, 250), - (10, HUFFMAN_EMIT_SYMBOL, 250), - (15, HUFFMAN_EMIT_SYMBOL, 250), - (24, HUFFMAN_EMIT_SYMBOL, 250), - (31, HUFFMAN_EMIT_SYMBOL, 250), - (41, HUFFMAN_EMIT_SYMBOL, 250), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 250), - (3, HUFFMAN_EMIT_SYMBOL, 251), - (6, HUFFMAN_EMIT_SYMBOL, 251), - (10, HUFFMAN_EMIT_SYMBOL, 251), - (15, HUFFMAN_EMIT_SYMBOL, 251), - (24, HUFFMAN_EMIT_SYMBOL, 251), - (31, HUFFMAN_EMIT_SYMBOL, 251), - (41, HUFFMAN_EMIT_SYMBOL, 251), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 251), - - # Node 222 - (3, HUFFMAN_EMIT_SYMBOL, 252), - (6, HUFFMAN_EMIT_SYMBOL, 252), - (10, HUFFMAN_EMIT_SYMBOL, 252), - (15, HUFFMAN_EMIT_SYMBOL, 252), - (24, HUFFMAN_EMIT_SYMBOL, 252), - (31, HUFFMAN_EMIT_SYMBOL, 252), - (41, HUFFMAN_EMIT_SYMBOL, 252), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 252), - (3, HUFFMAN_EMIT_SYMBOL, 253), - (6, HUFFMAN_EMIT_SYMBOL, 253), - (10, HUFFMAN_EMIT_SYMBOL, 253), - (15, HUFFMAN_EMIT_SYMBOL, 253), - (24, HUFFMAN_EMIT_SYMBOL, 253), - (31, HUFFMAN_EMIT_SYMBOL, 253), - (41, HUFFMAN_EMIT_SYMBOL, 253), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 253), - - # Node 223 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (227, 0, 0), - (229, 0, 0), - (230, 0, 0), - (233, 0, 0), - (234, 0, 0), - (236, 0, 0), - (237, 0, 0), - (241, 0, 0), - (242, 0, 0), - (244, 0, 0), - (245, 0, 0), - (248, 0, 0), - (249, 0, 0), - (251, 0, 0), - (252, 0, 0), - - # Node 224 - (1, HUFFMAN_EMIT_SYMBOL, 254), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 225 - (2, HUFFMAN_EMIT_SYMBOL, 254), - (9, HUFFMAN_EMIT_SYMBOL, 254), - (23, HUFFMAN_EMIT_SYMBOL, 254), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (1, HUFFMAN_EMIT_SYMBOL, 2), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (1, HUFFMAN_EMIT_SYMBOL, 3), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - (1, HUFFMAN_EMIT_SYMBOL, 4), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (1, HUFFMAN_EMIT_SYMBOL, 5), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (1, HUFFMAN_EMIT_SYMBOL, 6), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (1, HUFFMAN_EMIT_SYMBOL, 7), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 226 - (3, HUFFMAN_EMIT_SYMBOL, 254), - (6, HUFFMAN_EMIT_SYMBOL, 254), - (10, HUFFMAN_EMIT_SYMBOL, 254), - (15, HUFFMAN_EMIT_SYMBOL, 254), - (24, HUFFMAN_EMIT_SYMBOL, 254), - (31, HUFFMAN_EMIT_SYMBOL, 254), - (41, HUFFMAN_EMIT_SYMBOL, 254), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 254), - (2, HUFFMAN_EMIT_SYMBOL, 2), - (9, HUFFMAN_EMIT_SYMBOL, 2), - (23, HUFFMAN_EMIT_SYMBOL, 2), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (2, HUFFMAN_EMIT_SYMBOL, 3), - (9, HUFFMAN_EMIT_SYMBOL, 3), - (23, HUFFMAN_EMIT_SYMBOL, 3), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - - # Node 227 - (3, HUFFMAN_EMIT_SYMBOL, 2), - (6, HUFFMAN_EMIT_SYMBOL, 2), - (10, HUFFMAN_EMIT_SYMBOL, 2), - (15, HUFFMAN_EMIT_SYMBOL, 2), - (24, HUFFMAN_EMIT_SYMBOL, 2), - (31, HUFFMAN_EMIT_SYMBOL, 2), - (41, HUFFMAN_EMIT_SYMBOL, 2), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 2), - (3, HUFFMAN_EMIT_SYMBOL, 3), - (6, HUFFMAN_EMIT_SYMBOL, 3), - (10, HUFFMAN_EMIT_SYMBOL, 3), - (15, HUFFMAN_EMIT_SYMBOL, 3), - (24, HUFFMAN_EMIT_SYMBOL, 3), - (31, HUFFMAN_EMIT_SYMBOL, 3), - (41, HUFFMAN_EMIT_SYMBOL, 3), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 3), - - # Node 228 - (2, HUFFMAN_EMIT_SYMBOL, 4), - (9, HUFFMAN_EMIT_SYMBOL, 4), - (23, HUFFMAN_EMIT_SYMBOL, 4), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (2, HUFFMAN_EMIT_SYMBOL, 5), - (9, HUFFMAN_EMIT_SYMBOL, 5), - (23, HUFFMAN_EMIT_SYMBOL, 5), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - (2, HUFFMAN_EMIT_SYMBOL, 6), - (9, HUFFMAN_EMIT_SYMBOL, 6), - (23, HUFFMAN_EMIT_SYMBOL, 6), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (2, HUFFMAN_EMIT_SYMBOL, 7), - (9, HUFFMAN_EMIT_SYMBOL, 7), - (23, HUFFMAN_EMIT_SYMBOL, 7), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 229 - (3, HUFFMAN_EMIT_SYMBOL, 4), - (6, HUFFMAN_EMIT_SYMBOL, 4), - (10, HUFFMAN_EMIT_SYMBOL, 4), - (15, HUFFMAN_EMIT_SYMBOL, 4), - (24, HUFFMAN_EMIT_SYMBOL, 4), - (31, HUFFMAN_EMIT_SYMBOL, 4), - (41, HUFFMAN_EMIT_SYMBOL, 4), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 4), - (3, HUFFMAN_EMIT_SYMBOL, 5), - (6, HUFFMAN_EMIT_SYMBOL, 5), - (10, HUFFMAN_EMIT_SYMBOL, 5), - (15, HUFFMAN_EMIT_SYMBOL, 5), - (24, HUFFMAN_EMIT_SYMBOL, 5), - (31, HUFFMAN_EMIT_SYMBOL, 5), - (41, HUFFMAN_EMIT_SYMBOL, 5), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 5), - - # Node 230 - (3, HUFFMAN_EMIT_SYMBOL, 6), - (6, HUFFMAN_EMIT_SYMBOL, 6), - (10, HUFFMAN_EMIT_SYMBOL, 6), - (15, HUFFMAN_EMIT_SYMBOL, 6), - (24, HUFFMAN_EMIT_SYMBOL, 6), - (31, HUFFMAN_EMIT_SYMBOL, 6), - (41, HUFFMAN_EMIT_SYMBOL, 6), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 6), - (3, HUFFMAN_EMIT_SYMBOL, 7), - (6, HUFFMAN_EMIT_SYMBOL, 7), - (10, HUFFMAN_EMIT_SYMBOL, 7), - (15, HUFFMAN_EMIT_SYMBOL, 7), - (24, HUFFMAN_EMIT_SYMBOL, 7), - (31, HUFFMAN_EMIT_SYMBOL, 7), - (41, HUFFMAN_EMIT_SYMBOL, 7), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 7), - - # Node 231 - (1, HUFFMAN_EMIT_SYMBOL, 8), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (1, HUFFMAN_EMIT_SYMBOL, 11), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (1, HUFFMAN_EMIT_SYMBOL, 12), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (1, HUFFMAN_EMIT_SYMBOL, 14), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - (1, HUFFMAN_EMIT_SYMBOL, 15), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (1, HUFFMAN_EMIT_SYMBOL, 16), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (1, HUFFMAN_EMIT_SYMBOL, 17), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (1, HUFFMAN_EMIT_SYMBOL, 18), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 232 - (2, HUFFMAN_EMIT_SYMBOL, 8), - (9, HUFFMAN_EMIT_SYMBOL, 8), - (23, HUFFMAN_EMIT_SYMBOL, 8), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (2, HUFFMAN_EMIT_SYMBOL, 11), - (9, HUFFMAN_EMIT_SYMBOL, 11), - (23, HUFFMAN_EMIT_SYMBOL, 11), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - (2, HUFFMAN_EMIT_SYMBOL, 12), - (9, HUFFMAN_EMIT_SYMBOL, 12), - (23, HUFFMAN_EMIT_SYMBOL, 12), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (2, HUFFMAN_EMIT_SYMBOL, 14), - (9, HUFFMAN_EMIT_SYMBOL, 14), - (23, HUFFMAN_EMIT_SYMBOL, 14), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - - # Node 233 - (3, HUFFMAN_EMIT_SYMBOL, 8), - (6, HUFFMAN_EMIT_SYMBOL, 8), - (10, HUFFMAN_EMIT_SYMBOL, 8), - (15, HUFFMAN_EMIT_SYMBOL, 8), - (24, HUFFMAN_EMIT_SYMBOL, 8), - (31, HUFFMAN_EMIT_SYMBOL, 8), - (41, HUFFMAN_EMIT_SYMBOL, 8), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 8), - (3, HUFFMAN_EMIT_SYMBOL, 11), - (6, HUFFMAN_EMIT_SYMBOL, 11), - (10, HUFFMAN_EMIT_SYMBOL, 11), - (15, HUFFMAN_EMIT_SYMBOL, 11), - (24, HUFFMAN_EMIT_SYMBOL, 11), - (31, HUFFMAN_EMIT_SYMBOL, 11), - (41, HUFFMAN_EMIT_SYMBOL, 11), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 11), - - # Node 234 - (3, HUFFMAN_EMIT_SYMBOL, 12), - (6, HUFFMAN_EMIT_SYMBOL, 12), - (10, HUFFMAN_EMIT_SYMBOL, 12), - (15, HUFFMAN_EMIT_SYMBOL, 12), - (24, HUFFMAN_EMIT_SYMBOL, 12), - (31, HUFFMAN_EMIT_SYMBOL, 12), - (41, HUFFMAN_EMIT_SYMBOL, 12), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 12), - (3, HUFFMAN_EMIT_SYMBOL, 14), - (6, HUFFMAN_EMIT_SYMBOL, 14), - (10, HUFFMAN_EMIT_SYMBOL, 14), - (15, HUFFMAN_EMIT_SYMBOL, 14), - (24, HUFFMAN_EMIT_SYMBOL, 14), - (31, HUFFMAN_EMIT_SYMBOL, 14), - (41, HUFFMAN_EMIT_SYMBOL, 14), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 14), - - # Node 235 - (2, HUFFMAN_EMIT_SYMBOL, 15), - (9, HUFFMAN_EMIT_SYMBOL, 15), - (23, HUFFMAN_EMIT_SYMBOL, 15), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (2, HUFFMAN_EMIT_SYMBOL, 16), - (9, HUFFMAN_EMIT_SYMBOL, 16), - (23, HUFFMAN_EMIT_SYMBOL, 16), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - (2, HUFFMAN_EMIT_SYMBOL, 17), - (9, HUFFMAN_EMIT_SYMBOL, 17), - (23, HUFFMAN_EMIT_SYMBOL, 17), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (2, HUFFMAN_EMIT_SYMBOL, 18), - (9, HUFFMAN_EMIT_SYMBOL, 18), - (23, HUFFMAN_EMIT_SYMBOL, 18), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 236 - (3, HUFFMAN_EMIT_SYMBOL, 15), - (6, HUFFMAN_EMIT_SYMBOL, 15), - (10, HUFFMAN_EMIT_SYMBOL, 15), - (15, HUFFMAN_EMIT_SYMBOL, 15), - (24, HUFFMAN_EMIT_SYMBOL, 15), - (31, HUFFMAN_EMIT_SYMBOL, 15), - (41, HUFFMAN_EMIT_SYMBOL, 15), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 15), - (3, HUFFMAN_EMIT_SYMBOL, 16), - (6, HUFFMAN_EMIT_SYMBOL, 16), - (10, HUFFMAN_EMIT_SYMBOL, 16), - (15, HUFFMAN_EMIT_SYMBOL, 16), - (24, HUFFMAN_EMIT_SYMBOL, 16), - (31, HUFFMAN_EMIT_SYMBOL, 16), - (41, HUFFMAN_EMIT_SYMBOL, 16), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 16), - - # Node 237 - (3, HUFFMAN_EMIT_SYMBOL, 17), - (6, HUFFMAN_EMIT_SYMBOL, 17), - (10, HUFFMAN_EMIT_SYMBOL, 17), - (15, HUFFMAN_EMIT_SYMBOL, 17), - (24, HUFFMAN_EMIT_SYMBOL, 17), - (31, HUFFMAN_EMIT_SYMBOL, 17), - (41, HUFFMAN_EMIT_SYMBOL, 17), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 17), - (3, HUFFMAN_EMIT_SYMBOL, 18), - (6, HUFFMAN_EMIT_SYMBOL, 18), - (10, HUFFMAN_EMIT_SYMBOL, 18), - (15, HUFFMAN_EMIT_SYMBOL, 18), - (24, HUFFMAN_EMIT_SYMBOL, 18), - (31, HUFFMAN_EMIT_SYMBOL, 18), - (41, HUFFMAN_EMIT_SYMBOL, 18), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 18), - - # Node 238 - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (253, 0, 0), - - # Node 239 - (1, HUFFMAN_EMIT_SYMBOL, 19), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (1, HUFFMAN_EMIT_SYMBOL, 20), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (1, HUFFMAN_EMIT_SYMBOL, 21), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (1, HUFFMAN_EMIT_SYMBOL, 23), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - (1, HUFFMAN_EMIT_SYMBOL, 24), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (1, HUFFMAN_EMIT_SYMBOL, 25), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (1, HUFFMAN_EMIT_SYMBOL, 26), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (1, HUFFMAN_EMIT_SYMBOL, 27), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 240 - (2, HUFFMAN_EMIT_SYMBOL, 19), - (9, HUFFMAN_EMIT_SYMBOL, 19), - (23, HUFFMAN_EMIT_SYMBOL, 19), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (2, HUFFMAN_EMIT_SYMBOL, 20), - (9, HUFFMAN_EMIT_SYMBOL, 20), - (23, HUFFMAN_EMIT_SYMBOL, 20), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - (2, HUFFMAN_EMIT_SYMBOL, 21), - (9, HUFFMAN_EMIT_SYMBOL, 21), - (23, HUFFMAN_EMIT_SYMBOL, 21), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (2, HUFFMAN_EMIT_SYMBOL, 23), - (9, HUFFMAN_EMIT_SYMBOL, 23), - (23, HUFFMAN_EMIT_SYMBOL, 23), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - - # Node 241 - (3, HUFFMAN_EMIT_SYMBOL, 19), - (6, HUFFMAN_EMIT_SYMBOL, 19), - (10, HUFFMAN_EMIT_SYMBOL, 19), - (15, HUFFMAN_EMIT_SYMBOL, 19), - (24, HUFFMAN_EMIT_SYMBOL, 19), - (31, HUFFMAN_EMIT_SYMBOL, 19), - (41, HUFFMAN_EMIT_SYMBOL, 19), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 19), - (3, HUFFMAN_EMIT_SYMBOL, 20), - (6, HUFFMAN_EMIT_SYMBOL, 20), - (10, HUFFMAN_EMIT_SYMBOL, 20), - (15, HUFFMAN_EMIT_SYMBOL, 20), - (24, HUFFMAN_EMIT_SYMBOL, 20), - (31, HUFFMAN_EMIT_SYMBOL, 20), - (41, HUFFMAN_EMIT_SYMBOL, 20), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 20), - - # Node 242 - (3, HUFFMAN_EMIT_SYMBOL, 21), - (6, HUFFMAN_EMIT_SYMBOL, 21), - (10, HUFFMAN_EMIT_SYMBOL, 21), - (15, HUFFMAN_EMIT_SYMBOL, 21), - (24, HUFFMAN_EMIT_SYMBOL, 21), - (31, HUFFMAN_EMIT_SYMBOL, 21), - (41, HUFFMAN_EMIT_SYMBOL, 21), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 21), - (3, HUFFMAN_EMIT_SYMBOL, 23), - (6, HUFFMAN_EMIT_SYMBOL, 23), - (10, HUFFMAN_EMIT_SYMBOL, 23), - (15, HUFFMAN_EMIT_SYMBOL, 23), - (24, HUFFMAN_EMIT_SYMBOL, 23), - (31, HUFFMAN_EMIT_SYMBOL, 23), - (41, HUFFMAN_EMIT_SYMBOL, 23), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 23), - - # Node 243 - (2, HUFFMAN_EMIT_SYMBOL, 24), - (9, HUFFMAN_EMIT_SYMBOL, 24), - (23, HUFFMAN_EMIT_SYMBOL, 24), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (2, HUFFMAN_EMIT_SYMBOL, 25), - (9, HUFFMAN_EMIT_SYMBOL, 25), - (23, HUFFMAN_EMIT_SYMBOL, 25), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - (2, HUFFMAN_EMIT_SYMBOL, 26), - (9, HUFFMAN_EMIT_SYMBOL, 26), - (23, HUFFMAN_EMIT_SYMBOL, 26), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (2, HUFFMAN_EMIT_SYMBOL, 27), - (9, HUFFMAN_EMIT_SYMBOL, 27), - (23, HUFFMAN_EMIT_SYMBOL, 27), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 244 - (3, HUFFMAN_EMIT_SYMBOL, 24), - (6, HUFFMAN_EMIT_SYMBOL, 24), - (10, HUFFMAN_EMIT_SYMBOL, 24), - (15, HUFFMAN_EMIT_SYMBOL, 24), - (24, HUFFMAN_EMIT_SYMBOL, 24), - (31, HUFFMAN_EMIT_SYMBOL, 24), - (41, HUFFMAN_EMIT_SYMBOL, 24), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 24), - (3, HUFFMAN_EMIT_SYMBOL, 25), - (6, HUFFMAN_EMIT_SYMBOL, 25), - (10, HUFFMAN_EMIT_SYMBOL, 25), - (15, HUFFMAN_EMIT_SYMBOL, 25), - (24, HUFFMAN_EMIT_SYMBOL, 25), - (31, HUFFMAN_EMIT_SYMBOL, 25), - (41, HUFFMAN_EMIT_SYMBOL, 25), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 25), - - # Node 245 - (3, HUFFMAN_EMIT_SYMBOL, 26), - (6, HUFFMAN_EMIT_SYMBOL, 26), - (10, HUFFMAN_EMIT_SYMBOL, 26), - (15, HUFFMAN_EMIT_SYMBOL, 26), - (24, HUFFMAN_EMIT_SYMBOL, 26), - (31, HUFFMAN_EMIT_SYMBOL, 26), - (41, HUFFMAN_EMIT_SYMBOL, 26), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 26), - (3, HUFFMAN_EMIT_SYMBOL, 27), - (6, HUFFMAN_EMIT_SYMBOL, 27), - (10, HUFFMAN_EMIT_SYMBOL, 27), - (15, HUFFMAN_EMIT_SYMBOL, 27), - (24, HUFFMAN_EMIT_SYMBOL, 27), - (31, HUFFMAN_EMIT_SYMBOL, 27), - (41, HUFFMAN_EMIT_SYMBOL, 27), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 27), - - # Node 246 - (1, HUFFMAN_EMIT_SYMBOL, 28), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (1, HUFFMAN_EMIT_SYMBOL, 29), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (1, HUFFMAN_EMIT_SYMBOL, 30), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (1, HUFFMAN_EMIT_SYMBOL, 31), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - (1, HUFFMAN_EMIT_SYMBOL, 127), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (1, HUFFMAN_EMIT_SYMBOL, 220), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (1, HUFFMAN_EMIT_SYMBOL, 249), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (254, 0, 0), - (255, 0, 0), - - # Node 247 - (2, HUFFMAN_EMIT_SYMBOL, 28), - (9, HUFFMAN_EMIT_SYMBOL, 28), - (23, HUFFMAN_EMIT_SYMBOL, 28), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (2, HUFFMAN_EMIT_SYMBOL, 29), - (9, HUFFMAN_EMIT_SYMBOL, 29), - (23, HUFFMAN_EMIT_SYMBOL, 29), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - (2, HUFFMAN_EMIT_SYMBOL, 30), - (9, HUFFMAN_EMIT_SYMBOL, 30), - (23, HUFFMAN_EMIT_SYMBOL, 30), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (2, HUFFMAN_EMIT_SYMBOL, 31), - (9, HUFFMAN_EMIT_SYMBOL, 31), - (23, HUFFMAN_EMIT_SYMBOL, 31), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - - # Node 248 - (3, HUFFMAN_EMIT_SYMBOL, 28), - (6, HUFFMAN_EMIT_SYMBOL, 28), - (10, HUFFMAN_EMIT_SYMBOL, 28), - (15, HUFFMAN_EMIT_SYMBOL, 28), - (24, HUFFMAN_EMIT_SYMBOL, 28), - (31, HUFFMAN_EMIT_SYMBOL, 28), - (41, HUFFMAN_EMIT_SYMBOL, 28), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 28), - (3, HUFFMAN_EMIT_SYMBOL, 29), - (6, HUFFMAN_EMIT_SYMBOL, 29), - (10, HUFFMAN_EMIT_SYMBOL, 29), - (15, HUFFMAN_EMIT_SYMBOL, 29), - (24, HUFFMAN_EMIT_SYMBOL, 29), - (31, HUFFMAN_EMIT_SYMBOL, 29), - (41, HUFFMAN_EMIT_SYMBOL, 29), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 29), - - # Node 249 - (3, HUFFMAN_EMIT_SYMBOL, 30), - (6, HUFFMAN_EMIT_SYMBOL, 30), - (10, HUFFMAN_EMIT_SYMBOL, 30), - (15, HUFFMAN_EMIT_SYMBOL, 30), - (24, HUFFMAN_EMIT_SYMBOL, 30), - (31, HUFFMAN_EMIT_SYMBOL, 30), - (41, HUFFMAN_EMIT_SYMBOL, 30), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 30), - (3, HUFFMAN_EMIT_SYMBOL, 31), - (6, HUFFMAN_EMIT_SYMBOL, 31), - (10, HUFFMAN_EMIT_SYMBOL, 31), - (15, HUFFMAN_EMIT_SYMBOL, 31), - (24, HUFFMAN_EMIT_SYMBOL, 31), - (31, HUFFMAN_EMIT_SYMBOL, 31), - (41, HUFFMAN_EMIT_SYMBOL, 31), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 31), - - # Node 250 - (2, HUFFMAN_EMIT_SYMBOL, 127), - (9, HUFFMAN_EMIT_SYMBOL, 127), - (23, HUFFMAN_EMIT_SYMBOL, 127), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (2, HUFFMAN_EMIT_SYMBOL, 220), - (9, HUFFMAN_EMIT_SYMBOL, 220), - (23, HUFFMAN_EMIT_SYMBOL, 220), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - (2, HUFFMAN_EMIT_SYMBOL, 249), - (9, HUFFMAN_EMIT_SYMBOL, 249), - (23, HUFFMAN_EMIT_SYMBOL, 249), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (0, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - - # Node 251 - (3, HUFFMAN_EMIT_SYMBOL, 127), - (6, HUFFMAN_EMIT_SYMBOL, 127), - (10, HUFFMAN_EMIT_SYMBOL, 127), - (15, HUFFMAN_EMIT_SYMBOL, 127), - (24, HUFFMAN_EMIT_SYMBOL, 127), - (31, HUFFMAN_EMIT_SYMBOL, 127), - (41, HUFFMAN_EMIT_SYMBOL, 127), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 127), - (3, HUFFMAN_EMIT_SYMBOL, 220), - (6, HUFFMAN_EMIT_SYMBOL, 220), - (10, HUFFMAN_EMIT_SYMBOL, 220), - (15, HUFFMAN_EMIT_SYMBOL, 220), - (24, HUFFMAN_EMIT_SYMBOL, 220), - (31, HUFFMAN_EMIT_SYMBOL, 220), - (41, HUFFMAN_EMIT_SYMBOL, 220), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 220), - - # Node 252 - (3, HUFFMAN_EMIT_SYMBOL, 249), - (6, HUFFMAN_EMIT_SYMBOL, 249), - (10, HUFFMAN_EMIT_SYMBOL, 249), - (15, HUFFMAN_EMIT_SYMBOL, 249), - (24, HUFFMAN_EMIT_SYMBOL, 249), - (31, HUFFMAN_EMIT_SYMBOL, 249), - (41, HUFFMAN_EMIT_SYMBOL, 249), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 249), - (1, HUFFMAN_EMIT_SYMBOL, 10), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (1, HUFFMAN_EMIT_SYMBOL, 13), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (1, HUFFMAN_EMIT_SYMBOL, 22), - (22, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - - # Node 253 - (2, HUFFMAN_EMIT_SYMBOL, 10), - (9, HUFFMAN_EMIT_SYMBOL, 10), - (23, HUFFMAN_EMIT_SYMBOL, 10), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (2, HUFFMAN_EMIT_SYMBOL, 13), - (9, HUFFMAN_EMIT_SYMBOL, 13), - (23, HUFFMAN_EMIT_SYMBOL, 13), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - (2, HUFFMAN_EMIT_SYMBOL, 22), - (9, HUFFMAN_EMIT_SYMBOL, 22), - (23, HUFFMAN_EMIT_SYMBOL, 22), - (40, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - - # Node 254 - (3, HUFFMAN_EMIT_SYMBOL, 10), - (6, HUFFMAN_EMIT_SYMBOL, 10), - (10, HUFFMAN_EMIT_SYMBOL, 10), - (15, HUFFMAN_EMIT_SYMBOL, 10), - (24, HUFFMAN_EMIT_SYMBOL, 10), - (31, HUFFMAN_EMIT_SYMBOL, 10), - (41, HUFFMAN_EMIT_SYMBOL, 10), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 10), - (3, HUFFMAN_EMIT_SYMBOL, 13), - (6, HUFFMAN_EMIT_SYMBOL, 13), - (10, HUFFMAN_EMIT_SYMBOL, 13), - (15, HUFFMAN_EMIT_SYMBOL, 13), - (24, HUFFMAN_EMIT_SYMBOL, 13), - (31, HUFFMAN_EMIT_SYMBOL, 13), - (41, HUFFMAN_EMIT_SYMBOL, 13), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 13), - - # Node 255 - (3, HUFFMAN_EMIT_SYMBOL, 22), - (6, HUFFMAN_EMIT_SYMBOL, 22), - (10, HUFFMAN_EMIT_SYMBOL, 22), - (15, HUFFMAN_EMIT_SYMBOL, 22), - (24, HUFFMAN_EMIT_SYMBOL, 22), - (31, HUFFMAN_EMIT_SYMBOL, 22), - (41, HUFFMAN_EMIT_SYMBOL, 22), - (56, HUFFMAN_COMPLETE | HUFFMAN_EMIT_SYMBOL, 22), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), - (0, HUFFMAN_FAIL, 0), -] diff --git a/py3.7/lib/python3.7/site-packages/hpack/struct.py b/py3.7/lib/python3.7/site-packages/hpack/struct.py deleted file mode 100644 index e860cd7..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/struct.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hpack/struct -~~~~~~~~~~~~ - -Contains structures for representing header fields with associated metadata. -""" - - -class HeaderTuple(tuple): - """ - A data structure that stores a single header field. - - HTTP headers can be thought of as tuples of ``(field name, field value)``. - A single header block is a sequence of such tuples. - - In HTTP/2, however, certain bits of additional information are required for - compressing these headers: in particular, whether the header field can be - safely added to the HPACK compression context. - - This class stores a header that can be added to the compression context. In - all other ways it behaves exactly like a tuple. - """ - __slots__ = () - - indexable = True - - def __new__(_cls, *args): - return tuple.__new__(_cls, args) - - -class NeverIndexedHeaderTuple(HeaderTuple): - """ - A data structure that stores a single header field that cannot be added to - a HTTP/2 header compression context. - """ - __slots__ = () - - indexable = False diff --git a/py3.7/lib/python3.7/site-packages/hpack/table.py b/py3.7/lib/python3.7/site-packages/hpack/table.py deleted file mode 100644 index 9a89c72..0000000 --- a/py3.7/lib/python3.7/site-packages/hpack/table.py +++ /dev/null @@ -1,215 +0,0 @@ -# -*- coding: utf-8 -*- -# flake8: noqa -from collections import deque -import logging - -from .exceptions import InvalidTableIndex - -log = logging.getLogger(__name__) - - -def table_entry_size(name, value): - """ - Calculates the size of a single entry - - This size is mostly irrelevant to us and defined - specifically to accommodate memory management for - lower level implementations. The 32 extra bytes are - considered the "maximum" overhead that would be - required to represent each entry in the table. - - See RFC7541 Section 4.1 - """ - return 32 + len(name) + len(value) - - -class HeaderTable(object): - """ - Implements the combined static and dynamic header table - - The name and value arguments for all the functions - should ONLY be byte strings (b'') however this is not - strictly enforced in the interface. - - See RFC7541 Section 2.3 - """ - #: Default maximum size of the dynamic table. See - #: RFC7540 Section 6.5.2. - DEFAULT_SIZE = 4096 - - #: Constant list of static headers. See RFC7541 Section - #: 2.3.1 and Appendix A - STATIC_TABLE = ( - (b':authority' , b'' ), # noqa - (b':method' , b'GET' ), # noqa - (b':method' , b'POST' ), # noqa - (b':path' , b'/' ), # noqa - (b':path' , b'/index.html' ), # noqa - (b':scheme' , b'http' ), # noqa - (b':scheme' , b'https' ), # noqa - (b':status' , b'200' ), # noqa - (b':status' , b'204' ), # noqa - (b':status' , b'206' ), # noqa - (b':status' , b'304' ), # noqa - (b':status' , b'400' ), # noqa - (b':status' , b'404' ), # noqa - (b':status' , b'500' ), # noqa - (b'accept-charset' , b'' ), # noqa - (b'accept-encoding' , b'gzip, deflate'), # noqa - (b'accept-language' , b'' ), # noqa - (b'accept-ranges' , b'' ), # noqa - (b'accept' , b'' ), # noqa - (b'access-control-allow-origin' , b'' ), # noqa - (b'age' , b'' ), # noqa - (b'allow' , b'' ), # noqa - (b'authorization' , b'' ), # noqa - (b'cache-control' , b'' ), # noqa - (b'content-disposition' , b'' ), # noqa - (b'content-encoding' , b'' ), # noqa - (b'content-language' , b'' ), # noqa - (b'content-length' , b'' ), # noqa - (b'content-location' , b'' ), # noqa - (b'content-range' , b'' ), # noqa - (b'content-type' , b'' ), # noqa - (b'cookie' , b'' ), # noqa - (b'date' , b'' ), # noqa - (b'etag' , b'' ), # noqa - (b'expect' , b'' ), # noqa - (b'expires' , b'' ), # noqa - (b'from' , b'' ), # noqa - (b'host' , b'' ), # noqa - (b'if-match' , b'' ), # noqa - (b'if-modified-since' , b'' ), # noqa - (b'if-none-match' , b'' ), # noqa - (b'if-range' , b'' ), # noqa - (b'if-unmodified-since' , b'' ), # noqa - (b'last-modified' , b'' ), # noqa - (b'link' , b'' ), # noqa - (b'location' , b'' ), # noqa - (b'max-forwards' , b'' ), # noqa - (b'proxy-authenticate' , b'' ), # noqa - (b'proxy-authorization' , b'' ), # noqa - (b'range' , b'' ), # noqa - (b'referer' , b'' ), # noqa - (b'refresh' , b'' ), # noqa - (b'retry-after' , b'' ), # noqa - (b'server' , b'' ), # noqa - (b'set-cookie' , b'' ), # noqa - (b'strict-transport-security' , b'' ), # noqa - (b'transfer-encoding' , b'' ), # noqa - (b'user-agent' , b'' ), # noqa - (b'vary' , b'' ), # noqa - (b'via' , b'' ), # noqa - (b'www-authenticate' , b'' ), # noqa - ) # noqa - - STATIC_TABLE_LENGTH = len(STATIC_TABLE) - - def __init__(self): - self._maxsize = HeaderTable.DEFAULT_SIZE - self._current_size = 0 - self.resized = False - self.dynamic_entries = deque() - - def get_by_index(self, index): - """ - Returns the entry specified by index - - Note that the table is 1-based ie an index of 0 is - invalid. This is due to the fact that a zero value - index signals that a completely unindexed header - follows. - - The entry will either be from the static table or - the dynamic table depending on the value of index. - """ - original_index = index - index -= 1 - if 0 <= index: - if index < HeaderTable.STATIC_TABLE_LENGTH: - return HeaderTable.STATIC_TABLE[index] - - index -= HeaderTable.STATIC_TABLE_LENGTH - if index < len(self.dynamic_entries): - return self.dynamic_entries[index] - - raise InvalidTableIndex("Invalid table index %d" % original_index) - - def __repr__(self): - return "HeaderTable(%d, %s, %r)" % ( - self._maxsize, - self.resized, - self.dynamic_entries - ) - - def add(self, name, value): - """ - Adds a new entry to the table - - We reduce the table size if the entry will make the - table size greater than maxsize. - """ - # We just clear the table if the entry is too big - size = table_entry_size(name, value) - if size > self._maxsize: - self.dynamic_entries.clear() - self._current_size = 0 - else: - # Add new entry - self.dynamic_entries.appendleft((name, value)) - self._current_size += size - self._shrink() - - def search(self, name, value): - """ - Searches the table for the entry specified by name - and value - - Returns one of the following: - - ``None``, no match at all - - ``(index, name, None)`` for partial matches on name only. - - ``(index, name, value)`` for perfect matches. - """ - offset = HeaderTable.STATIC_TABLE_LENGTH + 1 - partial = None - for (i, (n, v)) in enumerate(HeaderTable.STATIC_TABLE): - if n == name: - if v == value: - return i + 1, n, v - elif partial is None: - partial = (i + 1, n, None) - for (i, (n, v)) in enumerate(self.dynamic_entries): - if n == name: - if v == value: - return i + offset, n, v - elif partial is None: - partial = (i + offset, n, None) - return partial - - @property - def maxsize(self): - return self._maxsize - - @maxsize.setter - def maxsize(self, newmax): - newmax = int(newmax) - log.debug("Resizing header table to %d from %d", newmax, self._maxsize) - oldmax = self._maxsize - self._maxsize = newmax - self.resized = (newmax != oldmax) - if newmax <= 0: - self.dynamic_entries.clear() - self._current_size = 0 - elif oldmax > newmax: - self._shrink() - - def _shrink(self): - """ - Shrinks the dynamic table to be at or below maxsize - """ - cursize = self._current_size - while cursize > self._maxsize: - name, value = self.dynamic_entries.pop() - cursize -= table_entry_size(name, value) - log.debug("Evicting %s: %s from the header table", name, value) - self._current_size = cursize diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/__about__.py b/py3.7/lib/python3.7/site-packages/hypercorn/__about__.py deleted file mode 100644 index 906d362..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/__about__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.6.0" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/__init__.py b/py3.7/lib/python3.7/site-packages/hypercorn/__init__.py deleted file mode 100644 index a9b2357..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .__about__ import __version__ -from .config import Config - -__all__ = ("__version__", "Config") diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/__main__.py b/py3.7/lib/python3.7/site-packages/hypercorn/__main__.py deleted file mode 100644 index b1b6ee7..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/__main__.py +++ /dev/null @@ -1,194 +0,0 @@ -import argparse -import ssl -import sys -import warnings -from typing import List, Optional - -from .config import Config -from .run import run - -sentinel = object() - - -def _load_config(config_path: Optional[str]) -> Config: - if config_path is None: - return Config() - elif config_path.startswith("python:"): - return Config.from_pyfile(config_path[len("python:") :]) - else: - return Config.from_toml(config_path) - - -def main(sys_args: Optional[List[str]] = None) -> None: - parser = argparse.ArgumentParser() - parser.add_argument( - "application", help="The application to dispatch to as path.to.module:instance.path" - ) - parser.add_argument( - "--access-log", - help="The target location for the access log, use `-` for stdout", - default=sentinel, - ) - parser.add_argument( - "--access-logformat", - help="The log format for the access log, see help docs", - default=sentinel, - ) - parser.add_argument( - "--backlog", help="The maximum number of pending connections", type=int, default=sentinel - ) - parser.add_argument( - "-b", - "--bind", - dest="binds", - help=""" The host/address to bind to. Should be either host:port, host, - unix:path or fd://num, e.g. 127.0.0.1:5000, 127.0.0.1, - unix:/tmp/socket or fd://33 respectively. """, - default=[], - action="append", - ) - parser.add_argument("--ca-certs", help="Path to the SSL CA certificate file", default=sentinel) - parser.add_argument("--certfile", help="Path to the SSL certificate file", default=sentinel) - parser.add_argument("--cert-reqs", help="See verify mode argument", type=int, default=sentinel) - parser.add_argument("--ciphers", help="Ciphers to use for the SSL setup", default=sentinel) - parser.add_argument( - "-c", - "--config", - help="Location of a TOML config file or when prefixed with `python:` a Python file.", - default=None, - ) - parser.add_argument( - "--debug", - help="Enable debug mode, i.e. extra logging and checks", - action="store_true", - default=sentinel, - ) - parser.add_argument( - "--error-log", - help="The target location for the error log, use `-` for stderr", - default=sentinel, - ) - parser.add_argument( - "-k", - "--worker-class", - dest="worker_class", - help="The type of worker to use. " - "Options include asyncio, uvloop (pip install hypercorn[uvloop]), " - "and trio (pip install hypercorn[trio]).", - default=sentinel, - ) - parser.add_argument( - "--keep-alive", - help="Seconds to keep inactive connections alive for", - default=sentinel, - type=int, - ) - parser.add_argument("--keyfile", help="Path to the SSL key file", default=sentinel) - parser.add_argument( - "--insecure-bind", - dest="insecure_binds", - help="""The host/address to bind to. SSL options will not apply to these binds. - See *bind* for formatting options. Care must be taken! See HTTP -> HTTPS redirection docs. - """, - default=[], - action="append", - ) - parser.add_argument( - "-p", "--pid", help="Location to write the PID (Program ID) to.", default=sentinel - ) - parser.add_argument( - "--reload", - help="Enable automatic reloads on code changes", - action="store_true", - default=sentinel, - ) - parser.add_argument( - "--root-path", help="The setting for the ASGI root_path variable", default=sentinel - ) - parser.add_argument( - "--uvloop", - dest="uvloop", - help="Enable uvloop usage (Deprecated, use `--worker-class uvloop` instead)", - action="store_true", - default=sentinel, - ) - - def _convert_verify_mode(value: str) -> ssl.VerifyMode: # type: ignore - try: - return ssl.VerifyMode[value] # type: ignore - except KeyError: - raise argparse.ArgumentTypeError("Not a valid verify mode") - - parser.add_argument( - "--verify-mode", - help="SSL verify mode for peer's certificate, see ssl.VerifyMode enum for possible values.", - type=_convert_verify_mode, - default=sentinel, - ) - parser.add_argument( - "-w", - "--workers", - dest="workers", - help="The number of workers to spawn and use", - default=sentinel, - type=int, - ) - args = parser.parse_args(sys_args or sys.argv[1:]) - config = _load_config(args.config) - config.application_path = args.application - - if args.access_logformat is not sentinel: - config.access_log_format = args.access_logformat - if args.access_log is not sentinel: - config.access_log_target = args.access_log - if args.backlog is not sentinel: - config.backlog = args.backlog - if args.ca_certs is not sentinel: - config.ca_certs = args.ca_certs - if args.certfile is not sentinel: - config.certfile = args.certfile - if args.cert_reqs is not sentinel: - config.cert_reqs = args.cert_reqs - if args.ciphers is not sentinel: - config.ciphers = args.ciphers - if args.debug is not sentinel: - config.debug = args.debug - if args.error_log is not sentinel: - config.error_log_target = args.error_log - if args.keep_alive is not sentinel: - config.keep_alive_timeout = args.keep_alive - if args.keyfile is not sentinel: - config.keyfile = args.keyfile - if args.pid is not sentinel: - config.pid_path = args.pid - if args.root_path is not sentinel: - config.root_path = args.root_path - if args.reload is not sentinel: - config.use_reloader = args.reload - if args.uvloop is not sentinel: - warnings.warn( - "The uvloop argument is deprecated, use `--worker-class uvloop` instead", - DeprecationWarning, - ) - config.worker_class = "uvloop" - if args.worker_class is not sentinel: - config.worker_class = args.worker_class - if args.workers is not sentinel: - config.workers = args.workers - - if len(args.binds) > 0: - config.bind = args.binds - if len(args.insecure_binds) > 0: - config.insecure_bind = args.insecure_binds - - for bind in config.bind: - scheme = "https" if config.ssl_enabled else "http" - print(f"Running on {bind} over {scheme} (CTRL + C to quit)") # noqa: T001 - for bind in config.insecure_bind: - print(f"Running on {bind} over http (CTRL + C to quit)") # noqa: T001 - - run(config) - - -if __name__ == "__main__": - main() diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/__init__.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h11.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h11.py deleted file mode 100644 index dbd90b5..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h11.py +++ /dev/null @@ -1,151 +0,0 @@ -import asyncio -from itertools import chain -from time import time -from typing import List, Optional, Tuple -from urllib.parse import unquote - -import h11 - -from .run import H2CProtocolRequired, H2ProtocolAssumed, WebsocketProtocolRequired -from .utils import ASGIHTTPState, build_and_validate_headers, UnexpectedMessage -from ..config import Config -from ..typing import ASGIFramework, H11SendableEvent -from ..utils import invoke_asgi, suppress_body - - -class H11Mixin: - # This handles a h11 request in the ASGI system, all I/O - # (including when to close) should be handled by the actual worker - # rather than this class. - - app: ASGIFramework - client: Tuple[str, int] - config: Config - response: Optional[dict] - server: Tuple[str, int] - state: ASGIHTTPState - - @property - def scheme(self) -> str: - pass - - def response_headers(self) -> List[Tuple[bytes, bytes]]: - pass - - async def asend(self, event: H11SendableEvent) -> None: - pass - - async def asgi_put(self, message: dict) -> None: - """Called by the ASGI server to put a message to the ASGI instance. - - See asgi_receive as the get to this put. - """ - pass - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - pass - - def error_response(self, status_code: int) -> h11.Response: - return h11.Response( - status_code=status_code, - headers=chain( - [(b"content-length", b"0"), (b"connection", b"close")], self.response_headers() - ), - ) - - def raise_if_upgrade(self, event: h11.Request, trailing_data: bytes) -> None: - upgrade_value = "" - connection_value = "" - has_body = False - for name, value in event.headers: - sanitised_name = name.decode().strip().lower() - if sanitised_name == "upgrade": - upgrade_value = value.decode().strip() - elif sanitised_name == "connection": - connection_value = value.decode().strip() - elif sanitised_name in {"content-length", "transfer-encoding"}: - has_body = True - - connection_tokens = connection_value.lower().split(",") - if ( - any(token.strip() == "upgrade" for token in connection_tokens) - and upgrade_value.lower() == "websocket" - and event.method.decode().upper() == "GET" - ): - raise WebsocketProtocolRequired(event) - # h2c Upgrade requests with a body are a pain as the body must - # be fully recieved in HTTP/1.1 before the upgrade response - # and HTTP/2 takes over, so Hypercorn ignores the upgrade and - # responds in HTTP/1.1. Use a preflight OPTIONS request to - # initiate the upgrade if really required (or just use h2). - elif upgrade_value.lower() == "h2c" and not has_body: - raise H2CProtocolRequired(event) - elif event.method == b"PRI" and event.target == b"*" and event.http_version == b"2.0": - raise H2ProtocolAssumed(b"PRI * HTTP/2.0\r\n\r\n" + trailing_data) - - async def handle_request(self, request: h11.Request) -> None: - path, _, query_string = request.target.partition(b"?") - self.scope = { - "type": "http", - "http_version": request.http_version.decode(), - "asgi": {"spec_version": "2.1"}, - "method": request.method.decode().upper(), - "scheme": self.scheme, - "path": unquote(path.decode("ascii")), - "query_string": query_string, - "root_path": self.config.root_path, - "headers": request.headers, - "client": self.client, - "server": self.server, - } - await self.handle_asgi_app() - - async def handle_asgi_app(self) -> None: - start_time = time() - try: - await invoke_asgi(self.app, self.scope, self.asgi_receive, self.asgi_send) - except asyncio.CancelledError: - pass - except Exception: - if self.config.error_logger is not None: - self.config.error_logger.exception("Error in ASGI Framework") - - # If the application hasn't sent a response, it has errored - - # send a 500 for it. - if self.state == ASGIHTTPState.REQUEST: - await self.asend(self.error_response(500)) - await self.asend(h11.EndOfMessage()) - self.response = {"status": 500, "headers": []} - - self.config.access_logger.access(self.scope, self.response, time() - start_time) - - async def asgi_send(self, message: dict) -> None: - """Called by the ASGI instance to send a message.""" - if message["type"] == "http.response.start" and self.state == ASGIHTTPState.REQUEST: - self.response = message - elif message["type"] == "http.response.body" and self.state in { - ASGIHTTPState.REQUEST, - ASGIHTTPState.RESPONSE, - }: - if self.state == ASGIHTTPState.REQUEST: - headers = build_and_validate_headers(self.response["headers"]) - headers.extend(self.response_headers()) - await self.asend( - h11.Response(status_code=int(self.response["status"]), headers=headers) - ) - self.state = ASGIHTTPState.RESPONSE - - if ( - not suppress_body(self.scope["method"], int(self.response["status"])) - and message.get("body", b"") != b"" - ): - await self.asend(h11.Data(data=bytes(message["body"]))) - - if not message.get("more_body", False): - if self.state != ASGIHTTPState.CLOSED: - await self.asend(h11.EndOfMessage()) - await self.asgi_put({"type": "http.disconnect"}) - self.state = ASGIHTTPState.CLOSED - else: - raise UnexpectedMessage(self.state, message["type"]) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h2.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h2.py deleted file mode 100644 index 973c637..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/h2.py +++ /dev/null @@ -1,313 +0,0 @@ -import asyncio -from time import time -from typing import Callable, Iterable, List, Tuple -from urllib.parse import unquote - -import h2.config -import h2.connection -import h2.events -import h2.exceptions -import wsproto.connection -import wsproto.events -import wsproto.extensions -import wsproto.frame_protocol -from wsproto.handshake import server_extensions_handshake -from wsproto.utilities import split_comma_header # Specifically to match wsproto expectations - -from .utils import ( - ASGIHTTPState, - ASGIWebsocketState, - build_and_validate_headers, - raise_if_subprotocol_present, - UnexpectedMessage, -) -from ..config import Config -from ..typing import ASGIFramework -from ..utils import invoke_asgi, suppress_body - - -class H2Event: - def __repr__(self) -> str: - kwarg_str = ", ".join( - f"{name}={value}" for name, value in self.__dict__.items() if name[0] != "_" - ) - return f"{self.__class__.__name__}({kwarg_str})" - - def __eq__(self, other: object) -> bool: - return self.__class__ == other.__class__ and self.__dict__ == other.__dict__ - - def __ne__(self, other: object) -> bool: - return not self.__eq__(other) - - # This is an unhashable type. - __hash__ = None - - -class EndStream(H2Event): - pass - - -class Response(H2Event): - def __init__(self, headers: Iterable[Tuple[bytes, bytes]]) -> None: - super().__init__() - self.headers = headers - - -class Data(H2Event): - def __init__(self, data: bytes) -> None: - super().__init__() - self.data = data - - -class ServerPush(H2Event): - def __init__(self, path: str, headers: Iterable[Tuple[bytes, bytes]]) -> None: - super().__init__() - self.path = path - self.headers = headers - - -class H2HTTPStreamMixin: - app: ASGIFramework - asend: Callable - config: Config - response: dict - state: ASGIHTTPState - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - pass - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - headers = [] - for name, value in event.headers: - if name == b":method": - method = value.decode("ascii").upper() - elif name == b":path": - raw_path = value - headers.append((name, value)) - path, _, query_string = raw_path.partition(b"?") - self.scope = { - "type": "http", - "http_version": "2", - "asgi": {"spec_version": "2.1"}, - "method": method, - "scheme": scheme, - "path": unquote(path.decode("ascii")), - "query_string": query_string, - "root_path": self.config.root_path, - "headers": headers, - "client": client, - "server": server, - "extensions": {"http.response.push": {}}, - } - await self.handle_asgi_app() - - async def handle_asgi_app(self) -> None: - start_time = time() - try: - await invoke_asgi(self.app, self.scope, self.asgi_receive, self.asgi_send) - except asyncio.CancelledError: - pass - except Exception: - if self.config.error_logger is not None: - self.config.error_logger.exception("Error in ASGI Framework") - - # If the application hasn't sent a response, it has errored - - # send a 500 for it. - if self.state == ASGIHTTPState.REQUEST: - headers = [(b":status", b"500")] - await self.asend(Response(headers)) - await self.asend(EndStream()) - self.response = {"status": 500, "headers": []} - - self.config.access_logger.access(self.scope, self.response, time() - start_time) - - async def asgi_send(self, message: dict) -> None: - if message["type"] == "http.response.start" and self.state == ASGIHTTPState.REQUEST: - self.response = message - elif message["type"] == "http.response.push": - if not isinstance(message["path"], str): - raise TypeError(f"{message['path']} should be a str") - headers = build_and_validate_headers(message["headers"]) - await self.asend(ServerPush(message["path"], headers)) - elif message["type"] == "http.response.body" and self.state in { - ASGIHTTPState.REQUEST, - ASGIHTTPState.RESPONSE, - }: - if self.state == ASGIHTTPState.REQUEST: - headers = [(b":status", b"%d" % self.response["status"])] - headers.extend(build_and_validate_headers(self.response["headers"])) - await self.asend(Response(headers)) - self.state = ASGIHTTPState.RESPONSE - if ( - not suppress_body(self.scope["method"], self.response["status"]) - and message.get("body", b"") != b"" - ): - await self.asend(Data(bytes(message.get("body", b"")))) - if not message.get("more_body", False): - if self.state != ASGIHTTPState.CLOSED: - await self.asend(EndStream()) - else: - raise UnexpectedMessage(self.state, message["type"]) - - -class H2WebsocketStreamMixin: - app: ASGIFramework - asend: Callable - config: Config - connection: wsproto.connection.Connection - response: dict - state: ASGIWebsocketState - - async def asgi_put(self, message: dict) -> None: - """Called by the ASGI server to put a message to the ASGI instance. - - See asgi_receive as the get to this put. - """ - pass - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - pass - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - headers = [] - for name, value in event.headers: - if name == b":path": - raw_path = value - headers.append((name, value)) - path, _, query_string = raw_path.partition(b"?") - self.scope = { - "type": "websocket", - "asgi": {"spec_version": "2.1"}, - # RFC 8441 (HTTP/2) Says use http or https, ASGI says ws or wss - "scheme": "wss" if scheme == "https" else "ws", - "http_version": "2", - "path": unquote(path.decode("ascii")), - "query_string": query_string, - "root_path": self.config.root_path, - "headers": headers, - "client": client, - "server": server, - "subprotocols": [], - "extensions": {"websocket.http.response": {}}, - } - self.state = ASGIWebsocketState.HANDSHAKE - await self.handle_asgi_app() - - async def send_http_error(self, status: int) -> None: - headers = [(b":status", b"%d" % status)] - await self.asend(Response(headers=headers)) - await self.asend(EndStream()) - self.config.access_logger.access( - self.scope, {"status": status, "headers": []}, time() - self.start_time - ) - - async def handle_asgi_app(self) -> None: - self.start_time = time() - await self.asgi_put({"type": "websocket.connect"}) - try: - await invoke_asgi(self.app, self.scope, self.asgi_receive, self.asgi_send) - except asyncio.CancelledError: - pass - except Exception: - if self.config.error_logger is not None: - self.config.error_logger.exception("Error in ASGI Framework") - - if self.state == ASGIWebsocketState.CONNECTED: - await self.asend( - Data( - self.connection.send( - wsproto.events.CloseConnection( - code=wsproto.frame_protocol.CloseReason.ABNORMAL_CLOSURE - ) - ) - ) - ) - self.state = ASGIWebsocketState.CLOSED - - # If the application hasn't accepted the connection (or sent a - # response) send a 500 for it. Otherwise if the connection - # hasn't been closed then close it. - if self.state == ASGIWebsocketState.HANDSHAKE: - await self.send_http_error(500) - self.state = ASGIWebsocketState.HTTPCLOSED - - async def asgi_send(self, message: dict) -> None: - if message["type"] == "websocket.accept" and self.state == ASGIWebsocketState.HANDSHAKE: - self.state = ASGIWebsocketState.CONNECTED - extensions: List[str] = [] - for name, value in self.scope["headers"]: - if name == b"sec-websocket-extensions": - extensions = split_comma_header(value) - supported_extensions = [wsproto.extensions.PerMessageDeflate()] - accepts = server_extensions_handshake(extensions, supported_extensions) - headers = [(b":status", b"200")] - headers.extend(build_and_validate_headers(message.get("headers", []))) - raise_if_subprotocol_present(headers) - if message.get("subprotocol") is not None: - headers.append((b"sec-websocket-protocol", message["subprotocol"].encode())) - if accepts: - headers.append((b"sec-websocket-extensions", accepts)) - await self.asend(Response(headers)) - self.connection = wsproto.connection.Connection( - wsproto.connection.ConnectionType.SERVER, supported_extensions - ) - self.config.access_logger.access( - self.scope, {"status": 200, "headers": []}, time() - self.start_time - ) - elif ( - message["type"] == "websocket.http.response.start" - and self.state == ASGIWebsocketState.HANDSHAKE - ): - self.response = message - self.config.access_logger.access(self.scope, self.response, time() - self.start_time) - elif message["type"] == "websocket.http.response.body" and self.state in { - ASGIWebsocketState.HANDSHAKE, - ASGIWebsocketState.RESPONSE, - }: - await self._asgi_send_rejection(message) - elif message["type"] == "websocket.send" and self.state == ASGIWebsocketState.CONNECTED: - event: wsproto.events.Event - if message.get("bytes") is not None: - event = wsproto.events.BytesMessage(data=bytes(message["bytes"])) - elif not isinstance(message["text"], str): - raise TypeError(f"{message['text']} should be a str") - else: - event = wsproto.events.TextMessage(data=message["text"]) - await self.asend(Data(self.connection.send(event))) - elif message["type"] == "websocket.close" and self.state == ASGIWebsocketState.HANDSHAKE: - await self.send_http_error(403) - self.state = ASGIWebsocketState.HTTPCLOSED - elif message["type"] == "websocket.close": - data = self.connection.send(wsproto.events.CloseConnection(code=int(message["code"]))) - await self.asend(Data(data)) - self.state = ASGIWebsocketState.CLOSED - else: - raise UnexpectedMessage(self.state, message["type"]) - - async def _asgi_send_rejection(self, message: dict) -> None: - body_suppressed = suppress_body("GET", self.response["status"]) - if self.state == ASGIWebsocketState.HANDSHAKE: - headers = [(b":status", b"%d" % self.response["status"])] - headers.extend(build_and_validate_headers(self.response["headers"])) - await self.asend(Response(headers)) - self.state = ASGIWebsocketState.RESPONSE - if not body_suppressed and message.get("body", b"") != b"": - await self.asend(Data(bytes(message.get("body", b"")))) - if not message.get("more_body", False): - await self.asgi_put({"type": "websocket.disconnect"}) - await self.asend(EndStream()) - self.state = ASGIWebsocketState.HTTPCLOSED diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/run.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/run.py deleted file mode 100644 index a1e1dc1..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/run.py +++ /dev/null @@ -1,19 +0,0 @@ -import h11 - - -class WrongProtocolError(Exception): - def __init__(self, request: h11.Request) -> None: - self.request = request - - -class WebsocketProtocolRequired(WrongProtocolError): - pass - - -class H2CProtocolRequired(WrongProtocolError): - pass - - -class H2ProtocolAssumed(WrongProtocolError): - def __init__(self, data: bytes) -> None: - self.data = data diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/utils.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/utils.py deleted file mode 100644 index b6cd697..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/utils.py +++ /dev/null @@ -1,70 +0,0 @@ -from enum import auto, Enum -from typing import List, Optional, Tuple, Union - -from wsproto.events import Message, TextMessage - - -class ASGIHTTPState(Enum): - # The ASGI Spec is clear that a response should not start till the - # framework has sent at least one body message hence why this - # state tracking is required. - REQUEST = auto() - RESPONSE = auto() - CLOSED = auto() - - -class ASGIWebsocketState(Enum): - # Hypercorn supports the ASGI websocket HTTP response extension, - # which allows HTTP responses rather than acceptance. - HANDSHAKE = auto() - CONNECTED = auto() - RESPONSE = auto() - CLOSED = auto() - HTTPCLOSED = auto() - - -class UnexpectedMessage(Exception): - def __init__(self, state: Enum, message_type: str) -> None: - super().__init__(f"Unexpected message type, {message_type} given the state {state}") - - -class FrameTooLarge(Exception): - pass - - -class WebsocketBuffer: - def __init__(self, max_length: int) -> None: - self.value: Optional[Union[bytes, str]] = None - self.max_length = max_length - - def extend(self, event: Message) -> None: - if self.value is None: - if isinstance(event, TextMessage): - self.value = "" - else: - self.value = b"" - self.value += event.data # type: ignore - if len(self.value) > self.max_length: - raise FrameTooLarge() - - def clear(self) -> None: - self.value = None - - def to_message(self) -> dict: - return { - "type": "websocket.receive", - "bytes": self.value if isinstance(self.value, bytes) else None, - "text": self.value if isinstance(self.value, str) else None, - } - - -def build_and_validate_headers(headers: List[Tuple[bytes, bytes]]) -> List[Tuple[bytes, bytes]]: - # Validates that the header name and value are bytes - return [(bytes(name).lower().strip(), bytes(value).strip()) for name, value in headers] - - -def raise_if_subprotocol_present(headers: List[Tuple[bytes, bytes]]) -> None: - # The headers should be built and validated first. - for name, value in headers: - if name == b"sec-websocket-protocol": - raise Exception("Invalid header, use the subprotocol option instead") diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/wsproto.py b/py3.7/lib/python3.7/site-packages/hypercorn/asgi/wsproto.py deleted file mode 100644 index 60f1633..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asgi/wsproto.py +++ /dev/null @@ -1,175 +0,0 @@ -import asyncio -from time import time -from typing import List, Optional, Tuple, Union -from urllib.parse import unquote - -from wsproto.events import ( - AcceptConnection, - BytesMessage, - CloseConnection, - Event, - RejectConnection, - RejectData, - Request, - TextMessage, -) -from wsproto.extensions import PerMessageDeflate -from wsproto.frame_protocol import CloseReason - -from .utils import ( - ASGIWebsocketState, - build_and_validate_headers, - raise_if_subprotocol_present, - UnexpectedMessage, -) -from ..config import Config -from ..typing import ASGIFramework -from ..utils import invoke_asgi, suppress_body - - -class WebsocketMixin: - app: ASGIFramework - client: Tuple[str, int] - config: Config - response: Optional[dict] - server: Tuple[str, int] - start_time: float - state: ASGIWebsocketState - - @property - def scheme(self) -> str: - pass - - def response_headers(self) -> List[Tuple[bytes, bytes]]: - pass - - async def asend(self, event: Event) -> None: - pass - - async def asgi_put(self, message: dict) -> None: - """Called by the ASGI server to put a message to the ASGI instance. - - See asgi_receive as the get to this put. - """ - pass - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - pass - - async def handle_websocket(self, event: Request) -> None: - path, _, query_string = event.target.partition("?") - headers = [(b"host", event.host.encode())] - headers.extend(event.extra_headers) - self.scope = { - "type": "websocket", - "asgi": {"spec_version": "2.1"}, - "http_version": "1.1", - "scheme": self.scheme, - "path": unquote(path), - "query_string": query_string.encode("ascii"), - "root_path": self.config.root_path, - "headers": headers, - "client": self.client, - "server": self.server, - "subprotocols": event.subprotocols, - "extensions": {"websocket.http.response": {}}, - } - await self.handle_asgi_app(event) - - async def send_http_error(self, status: int) -> None: - await self.asend(RejectConnection(status_code=status, headers=self.response_headers())) - self.config.access_logger.access( - self.scope, {"status": status, "headers": []}, time() - self.start_time - ) - - async def handle_asgi_app(self, event: Request) -> None: - self.start_time = time() - await self.asgi_put({"type": "websocket.connect"}) - try: - await invoke_asgi(self.app, self.scope, self.asgi_receive, self.asgi_send) - except asyncio.CancelledError: - pass - except Exception: - if self.config.error_logger is not None: - self.config.error_logger.exception("Error in ASGI Framework") - - if self.state == ASGIWebsocketState.CONNECTED: - await self.asend(CloseConnection(code=CloseReason.ABNORMAL_CLOSURE)) - self.state = ASGIWebsocketState.CLOSED - - # If the application hasn't accepted the connection (or sent a - # response) send a 500 for it. Otherwise if the connection - # hasn't been closed then close it. - if self.state == ASGIWebsocketState.HANDSHAKE: - await self.send_http_error(500) - self.state = ASGIWebsocketState.HTTPCLOSED - - async def asgi_send(self, message: dict) -> None: - """Called by the ASGI instance to send a message.""" - if message["type"] == "websocket.accept" and self.state == ASGIWebsocketState.HANDSHAKE: - headers = build_and_validate_headers(message.get("headers", [])) - raise_if_subprotocol_present(headers) - headers.extend(self.response_headers()) - await self.asend( - AcceptConnection( - extensions=[PerMessageDeflate()], - extra_headers=headers, - subprotocol=message.get("subprotocol"), - ) - ) - self.state = ASGIWebsocketState.CONNECTED - self.config.access_logger.access( - self.scope, {"status": 101, "headers": []}, time() - self.start_time - ) - elif ( - message["type"] == "websocket.http.response.start" - and self.state == ASGIWebsocketState.HANDSHAKE - ): - self.response = message - self.config.access_logger.access(self.scope, self.response, time() - self.start_time) - elif message["type"] == "websocket.http.response.body" and self.state in { - ASGIWebsocketState.HANDSHAKE, - ASGIWebsocketState.RESPONSE, - }: - await self._asgi_send_rejection(message) - elif message["type"] == "websocket.send" and self.state == ASGIWebsocketState.CONNECTED: - data: Union[bytes, str] - if message.get("bytes") is not None: - await self.asend(BytesMessage(data=bytes(message["bytes"]))) - elif not isinstance(message["text"], str): - raise TypeError(f"{message['text']} should be a str") - else: - await self.asend(TextMessage(data=message["text"])) - elif message["type"] == "websocket.close" and self.state == ASGIWebsocketState.HANDSHAKE: - await self.send_http_error(403) - self.state = ASGIWebsocketState.HTTPCLOSED - elif message["type"] == "websocket.close": - await self.asend(CloseConnection(code=int(message["code"]))) - self.state = ASGIWebsocketState.CLOSED - else: - raise UnexpectedMessage(self.state, message["type"]) - - async def _asgi_send_rejection(self, message: dict) -> None: - body_suppressed = suppress_body("GET", self.response["status"]) - if self.state == ASGIWebsocketState.HANDSHAKE: - headers = build_and_validate_headers(self.response["headers"]) - headers.extend(self.response_headers()) - await self.asend( - RejectConnection( - status_code=int(self.response["status"]), - headers=headers, - has_body=not body_suppressed, - ) - ) - self.state = ASGIWebsocketState.RESPONSE - if not body_suppressed: - await self.asend( - RejectData( - data=bytes(message.get("body", b"")), - body_finished=not message.get("more_body", False), - ) - ) - if not message.get("more_body", False): - await self.asgi_put({"type": "websocket.disconnect"}) - self.state = ASGIWebsocketState.HTTPCLOSED diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/__init__.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/__init__.py deleted file mode 100644 index fcb0515..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -import warnings - -from .run import worker_serve -from ..config import Config -from ..typing import ASGIFramework - - -async def serve(app: ASGIFramework, config: Config) -> None: - """Serve an ASGI framework app given the config. - - This allows for a programmatic way to serve an ASGI framework, it - can be used via, - - .. code-block:: python - - asyncio.run(serve(app, config)) - - It is assumed that the event-loop is configured before calling - this function, therefore configuration values that relate to loop - setup or process setup are ignored. - - """ - if config.debug: - warnings.warn("The config `debug` has no affect when using serve", Warning) - if config.workers != 1: - warnings.warn("The config `workers` has no affect when using serve", Warning) - if config.worker_class != "asyncio": - warnings.warn("The config `worker_class` has no affect when using serve", Warning) - - await worker_serve(app, config) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/base.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/base.py deleted file mode 100644 index d60056a..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/base.py +++ /dev/null @@ -1,82 +0,0 @@ -import asyncio -from typing import List, Optional, Tuple - -from ..config import Config -from ..utils import parse_socket_addr, response_headers - - -class HTTPServer: - def __init__( - self, - loop: asyncio.AbstractEventLoop, - config: Config, - transport: asyncio.BaseTransport, - protocol: str, - ) -> None: - self.loop = loop - self.config = config - self.transport = transport - self.protocol = protocol - - self.closed = False - self._can_write = asyncio.Event(loop=loop) - self._can_write.set() - self.start_keep_alive_timeout() - - socket = self.transport.get_extra_info("socket") - self.client = parse_socket_addr(socket.family, socket.getpeername()) - self.server = parse_socket_addr(socket.family, socket.getsockname()) - self.ssl_info = self.transport.get_extra_info("ssl_object") - - def data_received(self, data: bytes) -> None: - # Called whenever data is received. - pass - - def eof_received(self) -> bool: - # Either received once or not at all, if the client signals - # the connection is closed from their side. Is not called for - # SSL connections. If it returns Falsey the connection is - # closed from our side. - return True - - def pause_writing(self) -> None: - # Will be called whenever the transport crosses the high-water - # mark. - self._can_write.clear() - - def resume_writing(self) -> None: - # Will be called whenever the transport drops back below the - # low-water mark. - self._can_write.set() - - def connection_lost(self, error: Optional[Exception]) -> None: - # This is called once when the connection is closed from our - # side with an argument of None, otherwise something else - # errored. - pass - - async def drain(self) -> None: - await self._can_write.wait() - - def write(self, data: bytes) -> None: - self.transport.write(data) # type: ignore - - def close(self) -> None: - self.transport.close() - self.resume_writing() - self.closed = True - self.stop_keep_alive_timeout() - - def response_headers(self) -> List[Tuple[bytes, bytes]]: - return response_headers(self.protocol) - - def start_keep_alive_timeout(self) -> None: - self._keep_alive_timeout_handle = self.loop.call_later( - self.config.keep_alive_timeout, self.handle_timeout - ) - - def stop_keep_alive_timeout(self) -> None: - self._keep_alive_timeout_handle.cancel() - - def handle_timeout(self) -> None: - self.close() diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h11.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h11.py deleted file mode 100644 index 48308db..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h11.py +++ /dev/null @@ -1,123 +0,0 @@ -import asyncio -from typing import Optional - -import h11 - -from .base import HTTPServer -from ..asgi.h11 import H11Mixin -from ..asgi.run import H2CProtocolRequired -from ..asgi.utils import ASGIHTTPState -from ..config import Config -from ..typing import ASGIFramework, H11SendableEvent - - -class H11Server(HTTPServer, H11Mixin): - def __init__( - self, - app: ASGIFramework, - loop: asyncio.AbstractEventLoop, - config: Config, - transport: asyncio.BaseTransport, - ) -> None: - super().__init__(loop, config, transport, "h11") - self.app = app - self.connection = h11.Connection( - h11.SERVER, max_incomplete_event_size=self.config.h11_max_incomplete_size - ) - - self.app_queue: asyncio.Queue = asyncio.Queue(loop=loop) - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIHTTPState.REQUEST - self.task: Optional[asyncio.Future] = None - - def connection_lost(self, error: Optional[Exception]) -> None: - if error is not None: - self.app_queue.put_nowait({"type": "http.disconnect"}) - self.connection.send_failed() # Set our state to error, prevents recycling - - def eof_received(self) -> bool: - self.data_received(b"") - return True - - def data_received(self, data: bytes) -> None: - self.connection.receive_data(data) - self.handle_events() - - def handle_events(self) -> None: - # Called on receipt of data or after recycling the connection - while True: - if self.connection.they_are_waiting_for_100_continue: - self.send( - h11.InformationalResponse(status_code=100, headers=self.response_headers()) - ) - try: - event = self.connection.next_event() - except h11.RemoteProtocolError: - self.send(self.error_response(400)) - self.send(h11.EndOfMessage()) - self.app_queue.put_nowait({"type": "http.disconnect"}) - self.close() - break - else: - if isinstance(event, h11.Request): - self.stop_keep_alive_timeout() - try: - self.raise_if_upgrade(event, self.connection.trailing_data[0]) - except H2CProtocolRequired as error: - self.send( - h11.InformationalResponse( - status_code=101, - headers=[(b"upgrade", b"h2c")] + self.response_headers(), - ) - ) - raise error - self.task = self.loop.create_task(self.handle_request(event)) - self.task.add_done_callback(self.recycle_or_close) - elif isinstance(event, h11.EndOfMessage): - self.app_queue.put_nowait( - {"type": "http.request", "body": b"", "more_body": False} - ) - elif isinstance(event, h11.Data): - self.app_queue.put_nowait( - {"type": "http.request", "body": event.data, "more_body": True} - ) - elif event is h11.PAUSED: - self.transport.pause_reading() - break - elif isinstance(event, h11.ConnectionClosed) or event is h11.NEED_DATA: - break - - def send(self, event: H11SendableEvent) -> None: - try: - self.write(self.connection.send(event)) # type: ignore - except h11.LocalProtocolError: - pass - - async def asend(self, event: H11SendableEvent) -> None: - self.send(event) - await self.drain() - - def recycle_or_close(self, future: asyncio.Future) -> None: - if self.connection.our_state is h11.DONE: - self.connection.start_next_cycle() - self.transport.resume_reading() # type: ignore - self.app_queue = asyncio.Queue(loop=self.loop) - self.response = None - self.scope = None - self.state = ASGIHTTPState.REQUEST - self.start_keep_alive_timeout() - self.handle_events() - else: # Either reached a good close state, or has errored - self.close() - - async def asgi_put(self, message: dict) -> None: - await self.app_queue.put(message) - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - return await self.app_queue.get() - - @property - def scheme(self) -> str: - return "https" if self.ssl_info is not None else "http" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h2.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h2.py deleted file mode 100644 index 8a84ec7..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/h2.py +++ /dev/null @@ -1,353 +0,0 @@ -import asyncio -from functools import partial -from itertools import chain -from typing import Callable, Dict, Iterable, List, Optional, Tuple - -import h2.config -import h2.connection -import h2.events -import h2.exceptions -import h11 -import wsproto -import wsproto.connection -import wsproto.events - -from .base import HTTPServer -from ..asgi.h2 import ( - Data, - EndStream, - H2Event, - H2HTTPStreamMixin, - H2WebsocketStreamMixin, - Response, - ServerPush, -) -from ..asgi.utils import ASGIHTTPState, ASGIWebsocketState -from ..config import Config -from ..typing import ASGIFramework, H2SyncStream - - -class H2HTTPStream(H2HTTPStreamMixin): - """A HTTP Stream.""" - - def __init__(self, app: ASGIFramework, config: Config, asend: Callable) -> None: - self.app = app - self.config = config - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIHTTPState.REQUEST - - self.asend = asend # type: ignore - self.to_app: asyncio.Queue = asyncio.Queue() - - def data_received(self, data: bytes) -> None: - self.to_app.put_nowait({"type": "http.request", "body": data, "more_body": True}) - - def ended(self) -> None: - self.to_app.put_nowait({"type": "http.request", "body": b"", "more_body": False}) - - def reset(self) -> None: - self.to_app.put_nowait({"type": "http.disconnect"}) - - def close(self) -> None: - self.to_app.put_nowait({"type": "http.disconnect"}) - - async def asgi_receive(self) -> dict: - return await self.to_app.get() - - -class H2WebsocketStream(H2WebsocketStreamMixin): - """A Websocket Stream.""" - - def __init__(self, app: ASGIFramework, config: Config, asend: Callable, send: Callable) -> None: - self.app = app - self.config = config - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIWebsocketState.CONNECTED - self.connection: Optional[wsproto.connection.Connection] = None - - self.asend = asend # type: ignore - self.send = send - self.to_app: asyncio.Queue = asyncio.Queue() - - def data_received(self, data: bytes) -> None: - self.connection.receive_data(data) - for event in self.connection.events(): - if isinstance(event, wsproto.events.TextMessage): - self.to_app.put_nowait({"type": "websocket.receive", "text": event.data}) - elif isinstance(event, wsproto.events.BytesMessage): - self.to_app.put_nowait({"type": "websocket.receive", "bytes": event.data}) - elif isinstance(event, wsproto.events.Ping): - self.send(Data(self.connection.send(event.response()))) - elif isinstance(event, wsproto.events.CloseConnection): - if self.connection.state == wsproto.connection.ConnectionState.REMOTE_CLOSING: - self.send(Data(self.connection.send(event.response()))) - self.to_app.put_nowait({"type": "websocket.disconnect"}) - break - - def ended(self) -> None: - self.to_app.put_nowait({"type": "websocket.disconnect"}) - - def reset(self) -> None: - self.to_app.put_nowait({"type": "websocket.disconnect"}) - - def close(self) -> None: - self.to_app.put_nowait({"type": "websocket.disconnect"}) - - async def asgi_put(self, message: dict) -> None: - await self.to_app.put(message) - - async def asgi_receive(self) -> dict: - return await self.to_app.get() - - -class H2Server(HTTPServer): - def __init__( - self, - app: ASGIFramework, - loop: asyncio.AbstractEventLoop, - config: Config, - transport: asyncio.BaseTransport, - *, - upgrade_request: Optional[h11.Request] = None, - received_data: Optional[bytes] = None, - ) -> None: - super().__init__(loop, config, transport, "h2") - self.app = app - self.streams: Dict[int, H2SyncStream] = {} # type: ignore - self.flow_control: Dict[int, asyncio.Event] = {} - - self.connection = h2.connection.H2Connection( - config=h2.config.H2Configuration(client_side=False, header_encoding=None) - ) - self.connection.DEFAULT_MAX_INBOUND_FRAME_SIZE = config.h2_max_inbound_frame_size - self.connection.local_settings = h2.settings.Settings( - client=False, - initial_values={ - h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: config.h2_max_concurrent_streams, - h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: config.h2_max_header_list_size, - h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL: 1, - }, - ) - - if upgrade_request is None: - self.connection.initiate_connection() - if received_data: - self.data_received(received_data) - else: - settings = "" - headers = [] - for name, value in upgrade_request.headers: - if name.lower() == b"http2-settings": - settings = value.decode() - elif name.lower() == b"host": - headers.append((b":authority", value)) - headers.append((name, value)) - headers.append((b":method", upgrade_request.method)) - headers.append((b":path", upgrade_request.target)) - self.connection.initiate_upgrade_connection(settings) - event = h2.events.RequestReceived() - event.stream_id = 1 - event.headers = headers - self.create_stream(event, complete=True) - self.flush() - - def connection_lost(self, error: Optional[Exception]) -> None: - if error is not None: - self.close() - - def eof_received(self) -> bool: - self.data_received(b"") - return True - - def data_received(self, data: bytes) -> None: - try: - events = self.connection.receive_data(data) - except h2.exceptions.ProtocolError: - self.flush() - self.close() - else: - self.handle_events(events) - - def close(self) -> None: - for stream in self.streams.values(): - stream.close() - super().close() - - def create_stream(self, event: h2.events.RequestReceived, *, complete: bool = False) -> None: - method: str - for name, value in event.headers: - if name == b":method": - method = value.decode("ascii").upper() - if method == "CONNECT": - self.streams[event.stream_id] = H2WebsocketStream( - self.app, - self.config, - partial(self.asend, event.stream_id), - partial(self.send, event.stream_id), - ) - else: - self.streams[event.stream_id] = H2HTTPStream( - self.app, self.config, partial(self.asend, event.stream_id) - ) - if complete: - self.streams[event.stream_id].ended() - self.loop.create_task(self.handle_request(event)) - - async def handle_request(self, event: h2.events.RequestReceived) -> None: - await self.streams[event.stream_id].handle_request( - event, self.scheme, self.client, self.server - ) - if ( - self.connection.state_machine.state is not h2.connection.ConnectionState.CLOSED - and event.stream_id in self.connection.streams - and not self.connection.streams[event.stream_id].closed - ): - # The connection is not closed and there has been an error - # preventing the stream from closing correctly. - self.connection.reset_stream(event.stream_id) - self.streams[event.stream_id].close() - del self.streams[event.stream_id] - if len(self.streams) == 0: - self.start_keep_alive_timeout() - - def handle_events(self, events: List[h2.events.Event]) -> None: - for event in events: - if isinstance(event, h2.events.RequestReceived): - self.stop_keep_alive_timeout() - self.create_stream(event) - elif isinstance(event, h2.events.DataReceived): - self.streams[event.stream_id].data_received(event.data) - self.connection.acknowledge_received_data( - event.flow_controlled_length, event.stream_id - ) - elif isinstance(event, h2.events.StreamReset): - self.streams[event.stream_id].reset() - elif isinstance(event, h2.events.StreamEnded): - self.streams[event.stream_id].ended() - elif isinstance(event, h2.events.WindowUpdated): - self.window_updated(event.stream_id) - elif isinstance(event, h2.events.ConnectionTerminated): - self.close() - return - self.flush() - - def flush(self) -> None: - data = self.connection.data_to_send() - if data != b"": - self.write(data) - - def send(self, stream_id: int, event: H2Event) -> None: - # Solely for websocket stream WSPing and WSClose data to be - # sent, need to find a better way. - connection_state = self.connection.state_machine.state - stream_state = self.connection.streams[stream_id].state_machine.state - if ( - connection_state == h2.connection.ConnectionState.CLOSED - or stream_state == h2.stream.StreamState.CLOSED - ): - return - if isinstance(event, Data): - self.connection.send_data(stream_id, event.data) - self.flush() - - async def asend(self, stream_id: int, event: H2Event) -> None: - connection_state = self.connection.state_machine.state - stream_state = self.connection.streams[stream_id].state_machine.state - if ( - connection_state == h2.connection.ConnectionState.CLOSED - or stream_state == h2.stream.StreamState.CLOSED - ): - return - if isinstance(event, Response): - self.connection.send_headers( - stream_id, event.headers + self.response_headers() # type: ignore - ) - self.flush() - elif isinstance(event, EndStream): - self.connection.end_stream(stream_id) - self.flush() - elif isinstance(event, Data): - await self.send_data(stream_id, event.data) - elif isinstance(event, ServerPush): - self.server_push(stream_id, event.path, event.headers) - - async def send_data(self, stream_id: int, data: bytes) -> None: - while True: - while not self.connection.local_flow_control_window(stream_id): - await self.wait_for_flow_control(stream_id) - - chunk_size = min(len(data), self.connection.local_flow_control_window(stream_id)) - chunk_size = min(chunk_size, self.connection.max_outbound_frame_size) - if chunk_size < 1: # Pathological client sending negative window sizes - continue - self.connection.send_data(stream_id, data[:chunk_size]) - await self.drain() - self.flush() - data = data[chunk_size:] - if not data: - break - - async def wait_for_flow_control(self, stream_id: int) -> None: - event = asyncio.Event() - self.flow_control[stream_id] = event - await event.wait() - - def window_updated(self, stream_id: Optional[int]) -> None: - if stream_id is None or stream_id == 0: - # Unblock all streams - stream_ids = list(self.flow_control.keys()) - for stream_id in stream_ids: - event = self.flow_control.pop(stream_id) - event.set() - elif stream_id is not None: - if stream_id in self.flow_control: - event = self.flow_control.pop(stream_id) - event.set() - - def server_push( - self, stream_id: int, path: str, headers: Iterable[Tuple[bytes, bytes]] - ) -> None: - push_stream_id = self.connection.get_next_available_stream_id() - stream = self.streams[stream_id] - for name, value in stream.scope["headers"]: - if name == b":authority": - authority = value - request_headers = [ - (name, value) - for name, value in chain( - [ - (b":method", b"GET"), - (b":path", path.encode()), - (b":scheme", stream.scope["scheme"].encode()), - (b":authority", authority), - ], - headers, - self.response_headers(), - ) - ] - try: - self.connection.push_stream( - stream_id=stream_id, - promised_stream_id=push_stream_id, - request_headers=request_headers, - ) - except h2.exceptions.ProtocolError: - # Client does not accept push promises or we are trying to - # push on a push promises request. - pass - else: - event = h2.events.RequestReceived() - event.stream_id = push_stream_id - event.headers = request_headers - self.create_stream(event, complete=True) - - @property - def scheme(self) -> str: - return "https" if self.ssl_info is not None else "http" - - def handle_timeout(self) -> None: - self.connection.close_connection() - self.flush() - super().handle_timeout() diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/lifespan.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/lifespan.py deleted file mode 100644 index fa49e8e..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/lifespan.py +++ /dev/null @@ -1,76 +0,0 @@ -import asyncio - -from ..config import Config -from ..typing import ASGIFramework -from ..utils import invoke_asgi, LifespanFailure, LifespanTimeout - - -class UnexpectedMessage(Exception): - pass - - -class Lifespan: - def __init__(self, app: ASGIFramework, config: Config) -> None: - self.app = app - self.config = config - self.startup = asyncio.Event() - self.shutdown = asyncio.Event() - self.app_queue: asyncio.Queue = asyncio.Queue() - self.supported = True - - # This mimics the Trio nursery.start task_status and is - # required to ensure the support has been checked before - # waiting on timeouts. - self._started = asyncio.Event() - - async def handle_lifespan(self) -> None: - self._started.set() - scope = {"type": "lifespan", "asgi": {"spec_version": "2.0"}} - try: - await invoke_asgi(self.app, scope, self.asgi_receive, self.asgi_send) - except LifespanFailure: - # Lifespan failures should crash the server - raise - except Exception: - self.supported = False - if self.config.error_logger is not None: - self.config.error_logger.warning( - "ASGI Framework Lifespan error, continuing without Lifespan support" - ) - - async def wait_for_startup(self) -> None: - await self._started.wait() - if not self.supported: - return - - await self.app_queue.put({"type": "lifespan.startup"}) - try: - await asyncio.wait_for(self.startup.wait(), timeout=self.config.startup_timeout) - except asyncio.TimeoutError as error: - raise LifespanTimeout("startup") from error - - async def wait_for_shutdown(self) -> None: - await self._started.wait() - if not self.supported: - return - - await self.app_queue.put({"type": "lifespan.shutdown"}) - try: - await asyncio.wait_for(self.shutdown.wait(), timeout=self.config.shutdown_timeout) - except asyncio.TimeoutError as error: - raise LifespanTimeout("shutdown") from error - - async def asgi_receive(self) -> dict: - return await self.app_queue.get() - - async def asgi_send(self, message: dict) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup.set() - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown.set() - elif message["type"] == "lifespan.startup.failed": - raise LifespanFailure("startup", message["message"]) - elif message["type"] == "lifespan.shutdown.failed": - raise LifespanFailure("shutdown", message["message"]) - else: - raise UnexpectedMessage(message["type"]) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/run.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/run.py deleted file mode 100644 index 2821223..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/run.py +++ /dev/null @@ -1,263 +0,0 @@ -import asyncio -import platform -import signal -import ssl -from multiprocessing.synchronize import Event as EventType -from typing import Any, Coroutine, Optional - -from .base import HTTPServer -from .h2 import H2Server -from .h11 import H11Server -from .lifespan import Lifespan -from .wsproto import WebsocketServer -from ..asgi.run import H2CProtocolRequired, H2ProtocolAssumed, WebsocketProtocolRequired -from ..config import Config, Sockets -from ..typing import ASGIFramework -from ..utils import ( - check_shutdown, - load_application, - MustReloadException, - observe_changes, - restart, - Shutdown, -) - -try: - from socket import AF_UNIX -except ImportError: - AF_UNIX = None - - -def _raise_shutdown(*args: Any) -> None: - raise Shutdown() - - -class Server(asyncio.Protocol): - def __init__(self, app: ASGIFramework, loop: asyncio.AbstractEventLoop, config: Config) -> None: - self.app = app - self.loop = loop - self.config = config - self._server: Optional[HTTPServer] = None - self._ssl_enabled = False - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - ssl_object = transport.get_extra_info("ssl_object") - if ssl_object is not None: - self._ssl_enabled = True - protocol = ssl_object.selected_alpn_protocol() - else: - protocol = "http/1.1" - - if protocol == "h2": - self._server = H2Server(self.app, self.loop, self.config, transport) - else: - self._server = H11Server(self.app, self.loop, self.config, transport) - - def connection_lost(self, exception: Exception) -> None: - self._server.connection_lost(exception) - - def data_received(self, data: bytes) -> None: - try: - self._server.data_received(data) - except WebsocketProtocolRequired as error: - self._server = WebsocketServer( - self.app, - self.loop, - self.config, - self._server.transport, - upgrade_request=error.request, - ) - except H2CProtocolRequired as error: - self._server = H2Server( - self.app, - self.loop, - self.config, - self._server.transport, - upgrade_request=error.request, - ) - except H2ProtocolAssumed as error: - self._server = H2Server( - self.app, self.loop, self.config, self._server.transport, received_data=error.data - ) - - def eof_received(self) -> bool: - if self._ssl_enabled: - # Returning anything other than False has no affect under - # SSL, and just raises an annoying warning. - return False - return self._server.eof_received() - - def pause_writing(self) -> None: - self._server.pause_writing() - - def resume_writing(self) -> None: - self._server.resume_writing() - - -async def _windows_signal_support() -> None: - # See https://bugs.python.org/issue23057, to catch signals on - # Windows it is necessary for an IO event to happen periodically. - while True: - await asyncio.sleep(1) - - -async def worker_serve( - app: ASGIFramework, - config: Config, - *, - sockets: Optional[Sockets] = None, - shutdown_event: Optional[EventType] = None, -) -> None: - lifespan = Lifespan(app, config) - lifespan_task = asyncio.ensure_future(lifespan.handle_lifespan()) - - await lifespan.wait_for_startup() - - if sockets is None: - sockets = config.create_sockets() - - loop = asyncio.get_event_loop() - tasks = [] - if platform.system() == "Windows": - tasks.append(loop.create_task(_windows_signal_support())) - else: - signal_event = asyncio.Event() - - def _signal_handler(*_: Any) -> None: # noqa: N803 - signal_event.set() - - try: - loop.add_signal_handler(signal.SIGINT, _signal_handler) - loop.add_signal_handler(signal.SIGTERM, _signal_handler) - except AttributeError: - pass - - async def _check_signal() -> None: - await signal_event.wait() - raise Shutdown() - - tasks.append(loop.create_task(_check_signal())) - - if shutdown_event is not None: - tasks.append(loop.create_task(check_shutdown(shutdown_event, asyncio.sleep))) - - if config.use_reloader: - tasks.append(loop.create_task(observe_changes(asyncio.sleep))) - - ssl_handshake_timeout = None - if config.ssl_enabled: - ssl_context = config.create_ssl_context() - ssl_handshake_timeout = config.ssl_handshake_timeout - - servers = [ - await loop.create_server( # type: ignore - lambda: Server(app, loop, config), - backlog=config.backlog, - ssl=ssl_context, - sock=sock, - ssl_handshake_timeout=ssl_handshake_timeout, - ) - for sock in sockets.secure_sockets - ] - servers.extend( - [ - await loop.create_server( # type: ignore - lambda: Server(app, loop, config), backlog=config.backlog, sock=sock - ) - for sock in sockets.insecure_sockets - ] - ) - - reload_ = False - try: - gathered_tasks = asyncio.gather(*tasks) - await gathered_tasks - except MustReloadException: - reload_ = True - except (Shutdown, KeyboardInterrupt): - pass - finally: - for server in servers: - server.close() - await server.wait_closed() - # Retrieve the Gathered Tasks Cancelled Exception, to - # prevent a warning that this hasn't been done. - gathered_tasks.exception() - - await lifespan.wait_for_shutdown() - lifespan_task.cancel() - await lifespan_task - - if reload_: - restart() - - -def asyncio_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - app = load_application(config.application_path) - _run( - worker_serve(app, config, sockets=sockets, shutdown_event=shutdown_event), - debug=config.debug, - ) - - -def uvloop_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - try: - import uvloop - except ImportError as error: - raise Exception("uvloop is not installed") from error - else: - asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) - - app = load_application(config.application_path) - _run( - worker_serve(app, config, sockets=sockets, shutdown_event=shutdown_event), - debug=config.debug, - ) - - -def _run(main: Coroutine, *, debug: bool = False) -> None: - loop = asyncio.new_event_loop() - try: - asyncio.set_event_loop(loop) - loop.set_debug(debug) - loop.set_exception_handler(_exception_handler) - loop.run_until_complete(main) - finally: - try: - _cancel_all_tasks(loop) - loop.run_until_complete(loop.shutdown_asyncgens()) - finally: - asyncio.set_event_loop(None) - loop.close() - - -def _cancel_all_tasks(loop: asyncio.AbstractEventLoop) -> None: - tasks = [task for task in asyncio.all_tasks(loop) if not task.done()] - if not tasks: - return - - for task in tasks: - task.cancel() - loop.run_until_complete(asyncio.gather(*tasks, loop=loop, return_exceptions=True)) - - for task in tasks: - if not task.cancelled() and task.exception() is not None: - loop.call_exception_handler( - { - "message": "unhandled exception during shutdown", - "exception": task.exception(), - "task": task, - } - ) - - -def _exception_handler(loop: asyncio.AbstractEventLoop, context: dict) -> None: - exception = context.get("exception") - if isinstance(exception, ssl.SSLError): - pass # Handshake failure - else: - loop.default_exception_handler(context) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/wsproto.py b/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/wsproto.py deleted file mode 100644 index 9e47a7a..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/asyncio/wsproto.py +++ /dev/null @@ -1,104 +0,0 @@ -import asyncio -from typing import Optional - -import h11 -from wsproto import ConnectionType, WSConnection -from wsproto.connection import ConnectionState -from wsproto.events import CloseConnection, Event, Message, Ping, Request -from wsproto.frame_protocol import CloseReason - -from .base import HTTPServer -from ..asgi.utils import ASGIWebsocketState, FrameTooLarge, WebsocketBuffer -from ..asgi.wsproto import WebsocketMixin -from ..config import Config -from ..typing import ASGIFramework - - -class WebsocketServer(HTTPServer, WebsocketMixin): - def __init__( - self, - app: ASGIFramework, - loop: asyncio.AbstractEventLoop, - config: Config, - transport: asyncio.BaseTransport, - *, - upgrade_request: Optional[h11.Request] = None, - ) -> None: - super().__init__(loop, config, transport, "wsproto") - self.stop_keep_alive_timeout() - self.app = app - self.connection = WSConnection(ConnectionType.SERVER) - - self.app_queue: asyncio.Queue = asyncio.Queue() - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIWebsocketState.HANDSHAKE - self.task: Optional[asyncio.Future] = None - - self.buffer = WebsocketBuffer(self.config.websocket_max_message_size) - - if upgrade_request is not None: - self.connection.initiate_upgrade_connection( - upgrade_request.headers, upgrade_request.target - ) - self.handle_events() - - def connection_lost(self, error: Optional[Exception]) -> None: - if error is not None: - self.app_queue.put_nowait({"type": "websocket.disconnect"}) - - def eof_received(self) -> bool: - self.data_received(None) - return True - - def data_received(self, data: Optional[bytes]) -> None: - self.connection.receive_data(data) - self.handle_events() - - def handle_events(self) -> None: - for event in self.connection.events(): - if isinstance(event, Request): - self.task = self.loop.create_task(self.handle_websocket(event)) - self.task.add_done_callback(self.maybe_close) - elif isinstance(event, Message): - try: - self.buffer.extend(event) - except FrameTooLarge: - self.write( - self.connection.send(CloseConnection(code=CloseReason.MESSAGE_TOO_BIG)) - ) - self.app_queue.put_nowait({"type": "websocket.disconnect"}) - self.close() - break - - if event.message_finished: - self.app_queue.put_nowait(self.buffer.to_message()) - self.buffer.clear() - elif isinstance(event, Ping): - self.write(self.connection.send(event.response())) - elif isinstance(event, CloseConnection): - if self.connection.state == ConnectionState.REMOTE_CLOSING: - self.write(self.connection.send(event.response())) - self.app_queue.put_nowait({"type": "websocket.disconnect"}) - self.close() - break - - def maybe_close(self, future: asyncio.Future) -> None: - # Close the connection iff a HTTP response was sent - if self.state == ASGIWebsocketState.HTTPCLOSED: - self.close() - - async def asend(self, event: Event) -> None: - await self.drain() - self.write(self.connection.send(event)) - - async def asgi_put(self, message: dict) -> None: - await self.app_queue.put(message) - - async def asgi_receive(self) -> dict: - """Called by the ASGI instance to receive a message.""" - return await self.app_queue.get() - - @property - def scheme(self) -> str: - return "wss" if self.ssl_info is not None else "ws" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/config.py b/py3.7/lib/python3.7/site-packages/hypercorn/config.py deleted file mode 100644 index 4f8dfff..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/config.py +++ /dev/null @@ -1,309 +0,0 @@ -import importlib -import importlib.util -import logging -import os -import socket -import ssl -import stat -import sys -import types -import warnings -from dataclasses import dataclass -from ssl import SSLContext, VerifyFlags, VerifyMode # type: ignore -from typing import Any, AnyStr, Dict, List, Mapping, Optional, Type, Union - -import pytoml - -from .logging import AccessLogger - -BYTES = 1 -OCTETS = 1 -SECONDS = 1.0 - -FilePath = Union[AnyStr, os.PathLike] - - -@dataclass -class Sockets: - secure_sockets: List[socket.socket] - insecure_sockets: List[socket.socket] - - -class Config: - - _access_logger: Optional[AccessLogger] = None - _error_log_target: Optional[str] = None - _bind = ["127.0.0.1:8000"] - _insecure_bind: List[str] = [] - - access_log_format = "%(h)s %(S)s %(r)s %(s)s %(b)s %(D)s" - access_log_target: Optional[str] = None - access_logger_class = AccessLogger - alpn_protocols = ["h2", "http/1.1"] - application_path: str - backlog = 100 - ca_certs: Optional[str] = None - certfile: Optional[str] = None - ciphers: str = "ECDHE+AESGCM" - debug = False - error_logger: Optional[logging.Logger] = None - h11_max_incomplete_size = 16 * 1024 * BYTES - h2_max_concurrent_streams = 100 - h2_max_header_list_size = 2 ** 16 - h2_max_inbound_frame_size = 2 ** 14 * OCTETS - keep_alive_timeout = 5 * SECONDS - keyfile: Optional[str] = None - pid_path: Optional[str] = None - root_path = "" - shutdown_timeout = 60 * SECONDS - ssl_handshake_timeout = 60 * SECONDS - startup_timeout = 60 * SECONDS - use_reloader = False - verify_flags: Optional[VerifyFlags] = None - verify_mode: Optional[VerifyMode] = None - websocket_max_message_size = 16 * 1024 * 1024 * BYTES - worker_class = "asyncio" - workers = 1 - - def set_cert_reqs(self, value: int) -> None: - warnings.warn("Please use verify_mode instead", Warning) - self.verify_mode = VerifyMode(value) - - cert_reqs = property(None, set_cert_reqs) - - @property - def access_logger(self) -> AccessLogger: - if self._access_logger is None: - self._access_logger = self.access_logger_class( - self.access_log_format, self.access_log_target - ) - return self._access_logger - - @access_logger.setter - def access_logger(self, value: logging.Logger) -> None: - self._access_logger = self.access_logger_class(self.access_log_format, value) - - @property - def error_log_target(self) -> Optional[str]: - return self._error_log_target - - @error_log_target.setter - def error_log_target(self, value: Optional[str]) -> None: - self._error_log_target = value - if self.error_log_target is not None: - self.error_logger = logging.getLogger("hypercorn.error") - if self.error_log_target == "-": - self.error_logger.addHandler(logging.StreamHandler(sys.stderr)) - else: - self.error_logger.addHandler(logging.FileHandler(self.error_log_target)) - self.error_logger.setLevel(logging.INFO) - - @property - def bind(self) -> List[str]: - return self._bind - - @bind.setter - def bind(self, value: Union[List[str], str]) -> None: - if isinstance(value, str): - self._bind = [value] - else: - self._bind = value - - @property - def insecure_bind(self) -> List[str]: - return self._insecure_bind - - @insecure_bind.setter - def insecure_bind(self, value: Union[List[str], str]) -> None: - if isinstance(value, str): - self._insecure_bind = [value] - else: - self._insecure_bind = value - - def create_ssl_context(self) -> Optional[SSLContext]: - if not self.ssl_enabled: - return None - - context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) - context.set_ciphers(self.ciphers) - cipher_opts = 0 - for attr in ["OP_NO_SSLv2", "OP_NO_SSLv3", "OP_NO_TLSv1", "OP_NO_TLSv1_1"]: - if hasattr(ssl, attr): # To be future proof - cipher_opts |= getattr(ssl, attr) - context.options |= cipher_opts # RFC 7540 Section 9.2: MUST be TLS >=1.2 - context.options |= ssl.OP_NO_COMPRESSION # RFC 7540 Section 9.2.1: MUST disable compression - context.set_alpn_protocols(self.alpn_protocols) - try: - context.set_npn_protocols(self.alpn_protocols) - except NotImplementedError: - pass # NPN is not necessarily available - - context.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile) - if self.ca_certs is not None: - context.load_verify_locations(self.ca_certs) - if self.verify_mode is not None: - context.verify_mode = self.verify_mode - if self.verify_flags is not None: - context.verify_flags = self.verify_flags - - return context - - @property - def ssl_enabled(self) -> bool: - return self.certfile is not None and self.keyfile is not None - - def create_sockets(self) -> Sockets: - if self.ssl_enabled: - secure_sockets = self._create_sockets(self.bind) - insecure_sockets = self._create_sockets(self.insecure_bind) - else: - secure_sockets = [] - insecure_sockets = self._create_sockets(self.bind) - return Sockets(secure_sockets, insecure_sockets) - - def _create_sockets(self, binds: List[str]) -> List[socket.socket]: - sockets: List[socket.socket] = [] - for bind in binds: - binding: Any = None - if bind.startswith("unix:"): - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - binding = bind[5:] - try: - if stat.S_ISSOCK(os.stat(binding).st_mode): - os.remove(binding) - except FileNotFoundError: - pass - elif bind.startswith("fd://"): - sock = socket.fromfd(int(bind[5:]), socket.AF_UNIX, socket.SOCK_STREAM) - else: - try: - value = bind.rsplit(":", 1) - host, port = value[0], int(value[1]) - except (ValueError, IndexError): - host, port = bind, 8000 - sock = socket.socket( - socket.AF_INET6 if ":" in host else socket.AF_INET, socket.SOCK_STREAM - ) - if self.workers > 1: - try: - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # type: ignore - except AttributeError: - pass - binding = (host, port) - - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - if binding is not None: - sock.bind(binding) - sock.setblocking(False) - try: - sock.set_inheritable(True) # type: ignore - except AttributeError: - pass - sockets.append(sock) - return sockets - - @classmethod - def from_mapping( - cls: Type["Config"], mapping: Optional[Mapping[str, Any]] = None, **kwargs: Any - ) -> "Config": - """Create a configuration from a mapping. - - This allows either a mapping to be directly passed or as - keyword arguments, for example, - - .. code-block:: python - - config = {'keep_alive_timeout': 10} - Config.from_mapping(config) - Config.form_mapping(keep_alive_timeout=10) - - Arguments: - mapping: Optionally a mapping object. - kwargs: Optionally a collection of keyword arguments to - form a mapping. - """ - mappings: Dict[str, Any] = {} - if mapping is not None: - mappings.update(mapping) - mappings.update(kwargs) - config = cls() - for key, value in mappings.items(): - try: - setattr(config, key, value) - except AttributeError: - pass - - return config - - @classmethod - def from_pyfile(cls: Type["Config"], filename: FilePath) -> "Config": - """Create a configuration from a Python file. - - .. code-block:: python - - Config.from_pyfile('hypercorn_config.py') - - Arguments: - filename: The filename which gives the path to the file. - """ - file_path = os.fspath(filename) - spec = importlib.util.spec_from_file_location("module.name", file_path) # type: ignore - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) # type: ignore - return cls.from_object(module) - - @classmethod - def from_toml(cls: Type["Config"], filename: FilePath) -> "Config": - """Load the configuration values from a TOML formatted file. - - This allows configuration to be loaded as so - - .. code-block:: python - - Config.from_toml('config.toml') - - Arguments: - filename: The filename which gives the path to the file. - """ - file_path = os.fspath(filename) - with open(file_path) as file_: - data = pytoml.load(file_) - return cls.from_mapping(data) - - @classmethod - def from_object(cls: Type["Config"], instance: Union[object, str]) -> "Config": - """Create a configuration from a Python object. - - This can be used to reference modules or objects within - modules for example, - - .. code-block:: python - - Config.from_object('module') - Config.from_object('module.instance') - from module import instance - Config.from_object(instance) - - are valid. - - Arguments: - instance: Either a str referencing a python object or the - object itself. - - """ - if isinstance(instance, str): - try: - path, config = instance.rsplit(".", 1) - except ValueError: - path = instance - instance = importlib.import_module(instance) - else: - module = importlib.import_module(path) - instance = getattr(module, config) - - mapping = { - key: getattr(instance, key) - for key in dir(instance) - if not isinstance(getattr(instance, key), types.ModuleType) - } - return cls.from_mapping(mapping) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/logging.py b/py3.7/lib/python3.7/site-packages/hypercorn/logging.py deleted file mode 100644 index eb43e55..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/logging.py +++ /dev/null @@ -1,84 +0,0 @@ -import logging -import os -import sys -import time -from typing import Any, Optional, Union - - -class AccessLogger: - def __init__(self, log_format: str, target: Union[logging.Logger, str, None]) -> None: - self.logger: Optional[logging.Logger] = None - self.log_format = log_format - if isinstance(target, logging.Logger): - self.logger = target - elif target is not None: - self.logger = logging.getLogger("hypercorn.access") - self.logger.propagate = False - self.logger.handlers = [] - if target == "-": - self.logger.addHandler(logging.StreamHandler(sys.stdout)) - else: - self.logger.addHandler(logging.FileHandler(target)) - self.logger.setLevel(logging.INFO) - - def access(self, request: dict, response: dict, request_time: float) -> None: - if self.logger is not None: - self.logger.info(self.log_format, AccessLogAtoms(request, response, request_time)) - - def __getattr__(self, name: str) -> Any: - if self.logger is None: - return lambda *_: None - else: - return getattr(self.logger, name) - - -class AccessLogAtoms(dict): - def __init__(self, request: dict, response: dict, request_time: float) -> None: - for name, value in request["headers"]: - self[f"{{{name.decode().lower()}}}i"] = value.decode() - for name, value in response["headers"]: - self[f"{{{name.decode().lower()}}}o"] = value.decode() - for name, value in os.environ.items(): - self[f"{{{name.lower()}}}e"] = value - protocol = request.get("http_version", "ws") - client = request.get("client") - if client is None: - remote_addr = None - elif len(client) == 2: - remote_addr = f"{client[0]}:{client[1]}" - elif len(client) == 1: - remote_addr = client[0] - else: # make sure not to throw UnboundLocalError - remote_addr = f"" - method = request.get("method", "GET") - self.update( - { - "h": remote_addr, - "l": "-", - "t": time.strftime("[%d/%b/%Y:%H:%M:%S %z]"), - "r": f"{method} {request['path']} {protocol}", - "s": response["status"], - "S": request["scheme"], - "m": method, - "U": request["path"], - "q": request["query_string"].decode(), - "H": protocol, - "b": self["{Content-Length}o"], - "B": self["{Content-Length}o"], - "f": self["{Referer}i"], - "a": self["{User-Agent}i"], - "T": int(request_time), - "D": int(request_time * 1_000_000), - "L": f"{request_time:.6f}", - "p": f"<{os.getpid()}>", - } - ) - - def __getitem__(self, key: str) -> str: - try: - if key.startswith("{"): - return super().__getitem__(key.lower()) - else: - return super().__getitem__(key) - except KeyError: - return "-" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/middleware.py b/py3.7/lib/python3.7/site-packages/hypercorn/middleware.py deleted file mode 100644 index 1a5353f..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/middleware.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import Callable -from urllib.parse import urlunsplit - -from .typing import ASGIFramework -from .utils import invoke_asgi - - -class HTTPToHTTPSRedirectMiddleware: - def __init__(self, app: ASGIFramework, host: str) -> None: - self.app = app - self.host = host - - async def __call__(self, scope: dict, receive: Callable, send: Callable) -> None: - if scope["type"] == "http" and scope["scheme"] == "http": - await self._send_http_redirect(scope, send) - elif scope["type"] == "websocket" and scope["scheme"] == "ws": - # If the server supports the WebSocket Denial Response - # extension we can send a redirection response, if not we - # can only deny the WebSocket connection. - if "websocket.http.response" in scope.get("extensions", {}): - await self._send_websocket_redirect(scope, send) - else: - await send({"type": "websocket.close"}) - else: - return await invoke_asgi(self.app, scope, receive, send) - - async def _send_http_redirect(self, scope: dict, send: Callable) -> None: - new_url = urlunsplit( - ("https", self.host, scope["path"], scope["query_string"].decode(), "") - ) - await send( - { - "type": "http.response.start", - "status": 307, - "headers": [(b"location", new_url.encode())], - } - ) - await send({"type": "http.response.body"}) - - async def _send_websocket_redirect(self, scope: dict, send: Callable) -> None: - # If the HTTP version is 2 we should redirect with a https - # scheme not wss. - - scheme = "wss" - if scope.get("http_version", "1.1") == "2.0": - scheme = "https" - - new_url = urlunsplit((scheme, self.host, scope["path"], scope["query_string"].decode(), "")) - await send( - { - "type": "websocket.http.response.start", - "status": 307, - "headers": [(b"location", new_url.encode())], - } - ) - await send({"type": "websocket.http.response.body"}) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/py.typed b/py3.7/lib/python3.7/site-packages/hypercorn/py.typed deleted file mode 100644 index f5642f7..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/py.typed +++ /dev/null @@ -1 +0,0 @@ -Marker diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/run.py b/py3.7/lib/python3.7/site-packages/hypercorn/run.py deleted file mode 100644 index aa24d69..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/run.py +++ /dev/null @@ -1,80 +0,0 @@ -import platform -import random -import signal -import time -from multiprocessing import Event, Process -from typing import Any - -from .config import Config -from .typing import WorkerFunc -from .utils import write_pid_file - - -def run(config: Config) -> None: - if config.pid_path is not None: - write_pid_file(config.pid_path) - - worker_func: WorkerFunc - if config.worker_class == "asyncio": - from .asyncio.run import asyncio_worker - - worker_func = asyncio_worker - elif config.worker_class == "uvloop": - from .asyncio.run import uvloop_worker - - worker_func = uvloop_worker - elif config.worker_class == "trio": - from .trio.run import trio_worker - - worker_func = trio_worker - else: - raise ValueError(f"No worker of class {config.worker_class} exists") - - if config.workers == 1: - worker_func(config) - else: - run_multiple(config, worker_func) - - -def run_multiple(config: Config, worker_func: WorkerFunc) -> None: - if config.use_reloader: - raise RuntimeError("Reloader can only be used with a single worker") - - sockets = config.create_sockets() - - processes = [] - - # Ignore SIGINT before creating the processes, so that they - # inherit the signal handling. This means that the shutdown - # function controls the shutdown. - signal.signal(signal.SIGINT, signal.SIG_IGN) - - shutdown_event = Event() - - for _ in range(config.workers): - process = Process( - target=worker_func, - kwargs={"config": config, "shutdown_event": shutdown_event, "sockets": sockets}, - ) - process.daemon = True - process.start() - processes.append(process) - if platform.system() == "Windows": - time.sleep(0.1 * random.random()) - - def shutdown(*args: Any) -> None: - shutdown_event.set() - - for signal_name in {"SIGINT", "SIGTERM", "SIGBREAK"}: - if hasattr(signal, signal_name): - signal.signal(getattr(signal, signal_name), shutdown) - - for process in processes: - process.join() - for process in processes: - process.terminate() - - for sock in sockets.secure_sockets: - sock.close() - for sock in sockets.insecure_sockets: - sock.close() diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/__init__.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/__init__.py deleted file mode 100644 index 42e4bf6..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -import warnings - -import trio - -from .run import worker_serve -from ..config import Config -from ..typing import ASGIFramework - - -async def serve( - app: ASGIFramework, - config: Config, - *, - task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED, -) -> None: - """Serve an ASGI framework app given the config. - - This allows for a programmatic way to serve an ASGI framework, it - can be used via, - - .. code-block:: python - - trio.run(partial(serve, app, config)) - - It is assumed that the event-loop is configured before calling - this function, therefore configuration values that relate to loop - setup or process setup are ignored. - - """ - if config.debug: - warnings.warn("The config `debug` has no affect when using serve", Warning) - if config.workers != 1: - warnings.warn("The config `workers` has no affect when using serve", Warning) - if config.worker_class != "asyncio": - warnings.warn("The config `worker_class` has no affect when using serve", Warning) - - await worker_serve(app, config, task_status=task_status) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/base.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/base.py deleted file mode 100644 index 53c115d..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/base.py +++ /dev/null @@ -1,31 +0,0 @@ -from typing import List, Tuple - -import trio - -from ..utils import parse_socket_addr, response_headers - - -class HTTPServer: - def __init__(self, stream: trio.abc.Stream, protocol: str) -> None: - self.stream = stream - self.protocol = protocol - - self._is_ssl = isinstance(self.stream, trio.SSLStream) - if self._is_ssl: - socket = self.stream.transport_stream.socket - else: - socket = self.stream.socket - self.client = parse_socket_addr(socket.family, socket.getpeername()) - self.server = parse_socket_addr(socket.family, socket.getsockname()) - - async def aclose(self) -> None: - try: - await self.stream.send_eof() - except (trio.BrokenResourceError, AttributeError): - # They're already gone, nothing to do - # Or it is a SSL stream - return - await self.stream.aclose() - - def response_headers(self) -> List[Tuple[bytes, bytes]]: - return response_headers(self.protocol) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/h11.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/h11.py deleted file mode 100644 index c15f556..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/h11.py +++ /dev/null @@ -1,142 +0,0 @@ -from typing import Optional - -import h11 -import trio - -from .base import HTTPServer -from ..asgi.h11 import H11Mixin -from ..asgi.run import H2CProtocolRequired, WrongProtocolError -from ..asgi.utils import ASGIHTTPState -from ..config import Config -from ..typing import ASGIFramework, H11SendableEvent - -MAX_RECV = 2 ** 16 - - -class MustCloseError(Exception): - pass - - -class H11Server(HTTPServer, H11Mixin): - def __init__(self, app: ASGIFramework, config: Config, stream: trio.abc.Stream) -> None: - super().__init__(stream, "h11") - self.app = app - self.config = config - self.connection = h11.Connection( - h11.SERVER, max_incomplete_event_size=self.config.h11_max_incomplete_size - ) - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIHTTPState.REQUEST - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - - async def handle_connection(self) -> None: - try: - # Loop over the requests in order of receipt (either - # pipelined or due to keep-alive). - while True: - with trio.fail_after(self.config.keep_alive_timeout): - request = await self.read_request() - self.raise_if_upgrade(request, self.connection.trailing_data[0]) - - async with trio.open_nursery() as nursery: - nursery.start_soon(self.handle_request, request) - await self.read_body() - - await self.recycle_or_close() - except (trio.BrokenResourceError, trio.ClosedResourceError): - await self.asgi_put({"type": "http.disconnect"}) - await self.aclose() - except (trio.TooSlowError, MustCloseError): - await self.aclose() - except H2CProtocolRequired as error: - await self.asend( - h11.InformationalResponse( - status_code=101, headers=[(b"upgrade", b"h2c")] + self.response_headers() - ) - ) - raise error - except WrongProtocolError: - raise # Do not close the connection - - async def read_request(self) -> h11.Request: - while True: - try: - event = self.connection.next_event() - except h11.RemoteProtocolError: - await self.send_error() - raise MustCloseError() - else: - if event is h11.NEED_DATA: - await self.read_data() - elif isinstance(event, h11.Request): - return event - else: - raise MustCloseError() - - async def read_body(self) -> None: - while True: - try: - event = self.connection.next_event() - except h11.RemoteProtocolError: - await self.send_error() - await self.asgi_put({"type": "http.disconnect"}) - raise MustCloseError() - else: - if event is h11.NEED_DATA: - await self.read_data() - elif isinstance(event, h11.EndOfMessage): - await self.asgi_put({"type": "http.request", "body": b"", "more_body": False}) - return - elif isinstance(event, h11.Data): - await self.asgi_put( - {"type": "http.request", "body": event.data, "more_body": True} - ) - elif isinstance(event, h11.ConnectionClosed) or event is h11.PAUSED: - break - - async def recycle_or_close(self) -> None: - if self.connection.our_state is h11.DONE: - await self.app_send_channel.aclose() - await self.app_receive_channel.aclose() - self.connection.start_next_cycle() - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - self.response = None - self.scope = None - self.state = ASGIHTTPState.REQUEST - else: - raise MustCloseError() - - async def asend(self, event: H11SendableEvent) -> None: - data = self.connection.send(event) - try: - await self.stream.send_all(data) - except trio.BrokenResourceError: - pass - - async def close(self) -> None: - await self.app_send_channel.aclose() - await self.app_receive_channel.aclose() - await super().aclose() - - async def read_data(self) -> None: - if self.connection.they_are_waiting_for_100_continue: - await self.asend( - h11.InformationalResponse(status_code=100, headers=self.response_headers()) - ) - data = await self.stream.receive_some(MAX_RECV) - self.connection.receive_data(data) - - async def send_error(self) -> None: - await self.asend(self.error_response(400)) - await self.asend(h11.EndOfMessage()) - - async def asgi_put(self, message: dict) -> None: - await self.app_send_channel.send(message) - - async def asgi_receive(self) -> dict: - return await self.app_receive_channel.receive() - - @property - def scheme(self) -> str: - return "https" if self._is_ssl else "http" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/h2.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/h2.py deleted file mode 100644 index 878a7a3..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/h2.py +++ /dev/null @@ -1,357 +0,0 @@ -from functools import partial -from itertools import chain -from typing import Callable, Dict, Iterable, Optional, Tuple - -import h2.config -import h2.connection -import h2.events -import h2.exceptions -import h11 -import trio -import wsproto.connection -import wsproto.events - -from .base import HTTPServer -from ..asgi.h2 import ( - Data, - EndStream, - H2Event, - H2HTTPStreamMixin, - H2WebsocketStreamMixin, - Response, - ServerPush, -) -from ..asgi.utils import ASGIHTTPState, ASGIWebsocketState -from ..config import Config -from ..typing import ASGIFramework, H2AsyncStream - -MAX_RECV = 2 ** 16 - - -class MustCloseError(Exception): - pass - - -class H2HTTPStream(H2HTTPStreamMixin): - """A HTTP Stream.""" - - def __init__(self, app: ASGIFramework, config: Config, asend: Callable) -> None: - self.app = app - self.config = config - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIHTTPState.REQUEST - - self.asend = asend # type: ignore - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - - async def data_received(self, data: bytes) -> None: - await self.app_send_channel.send({"type": "http.request", "body": data, "more_body": True}) - - async def ended(self) -> None: - await self.app_send_channel.send({"type": "http.request", "body": b"", "more_body": False}) - - async def reset(self) -> None: - await self.app_send_channel.send({"type": "http.disconnect"}) - - async def close(self) -> None: - await self.app_send_channel.send({"type": "http.disconnect"}) - - async def asgi_receive(self) -> dict: - return await self.app_receive_channel.receive() - - -class H2WebsocketStream(H2WebsocketStreamMixin): - """A Websocket Stream.""" - - def __init__(self, app: ASGIFramework, config: Config, asend: Callable) -> None: - self.app = app - self.config = config - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.state = ASGIWebsocketState.CONNECTED - self.connection: Optional[wsproto.connection.Connection] = None - - self.asend = asend # type: ignore - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - - async def data_received(self, data: bytes) -> None: - self.connection.receive_data(data) - for event in self.connection.events(): - if isinstance(event, wsproto.events.TextMessage): - await self.app_send_channel.send({"type": "websocket.receive", "text": event.data}) - elif isinstance(event, wsproto.events.BytesMessage): - await self.app_send_channel.send({"type": "websocket.receive", "bytes": event.data}) - elif isinstance(event, wsproto.events.Ping): - await self.asend(Data(self.connection.send(event.response()))) - elif isinstance(event, wsproto.events.CloseConnection): - if self.connection.state == wsproto.connection.ConnectionState.REMOTE_CLOSING: - await self.asend(Data(self.connection.send(event.response()))) - await self.app_send_channel.send({"type": "websocket.disconnect"}) - break - - async def ended(self) -> None: - await self.app_send_channel.send({"type": "websocket.disconnect"}) - - async def reset(self) -> None: - await self.app_send_channel.send({"type": "websocket.disconnect"}) - - async def close(self) -> None: - await self.app_send_channel.send({"type": "websocket.disconnect"}) - - async def asgi_put(self, message: dict) -> None: - await self.app_send_channel.send(message) - - async def asgi_receive(self) -> dict: - return await self.app_receive_channel.receive() - - -class H2Server(HTTPServer): - def __init__( - self, - app: ASGIFramework, - config: Config, - stream: trio.abc.Stream, - *, - upgrade_request: Optional[h11.Request] = None, - received_data: Optional[bytes] = None, - ) -> None: - super().__init__(stream, "h2") - self.app = app - self.config = config - - self.streams: Dict[int, H2AsyncStream] = {} # type: ignore - self.flow_control: Dict[int, trio.Event] = {} - self.send_lock = trio.Lock() - self.upgrade_request = upgrade_request - self.received_data = received_data - - self.connection = h2.connection.H2Connection( - config=h2.config.H2Configuration(client_side=False, header_encoding=None) - ) - self.connection.DEFAULT_MAX_INBOUND_FRAME_SIZE = config.h2_max_inbound_frame_size - self.connection.local_settings = h2.settings.Settings( - client=False, - initial_values={ - h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: config.h2_max_concurrent_streams, - h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: config.h2_max_header_list_size, - h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL: 1, - }, - ) - - async def initiate(self) -> None: - if self.upgrade_request is None: - self.connection.initiate_connection() - if self.received_data: - await self.process_data(self.received_data) - else: - settings = "" - headers = [] - for name, value in self.upgrade_request.headers: - if name.lower() == b"http2-settings": - settings = value.decode() - elif name.lower() == b"host": - headers.append((b":authority", value)) - headers.append((name, value)) - headers.append((b":method", self.upgrade_request.method)) - headers.append((b":path", self.upgrade_request.target)) - self.connection.initiate_upgrade_connection(settings) - event = h2.events.RequestReceived() - event.stream_id = 1 - event.headers = headers - await self.create_stream(event, complete=True) - await self.send() - - async def create_stream( - self, event: h2.events.RequestReceived, *, complete: bool = False - ) -> None: - method: str - for name, value in event.headers: - if name == b":method": - method = value.decode("ascii").upper() - if method == "CONNECT": - self.streams[event.stream_id] = H2WebsocketStream( - self.app, self.config, partial(self.asend, event.stream_id) - ) - else: - self.streams[event.stream_id] = H2HTTPStream( - self.app, self.config, partial(self.asend, event.stream_id) - ) - if complete: - await self.streams[event.stream_id].ended() - self.nursery.start_soon(self.handle_request, event) - - async def handle_request(self, event: h2.events.RequestReceived) -> None: - await self.streams[event.stream_id].handle_request( - event, self.scheme, self.client, self.server - ) - if ( - self.connection.state_machine.state is not h2.connection.ConnectionState.CLOSED - and event.stream_id in self.connection.streams - and not self.connection.streams[event.stream_id].closed - ): - # The connection is not closed and there has been an error - # preventing the stream from closing correctly. - self.connection.reset_stream(event.stream_id) - await self.streams[event.stream_id].close() - del self.streams[event.stream_id] - - async def handle_connection(self) -> None: - try: - async with trio.open_nursery() as nursery: - self.nursery = nursery - await self.initiate() - await self.read_data() - except trio.TooSlowError: - self.connection.close_connection() - await self.send() - except MustCloseError: - await self.send() - except (trio.BrokenResourceError, trio.ClosedResourceError): - pass - finally: - for stream in self.streams.values(): - await stream.close() - await self.aclose() - - async def read_data(self) -> None: - while True: - try: - with trio.fail_after(self.config.keep_alive_timeout): - data = await self.stream.receive_some(MAX_RECV) - except trio.TooSlowError: - if len(self.streams) == 0: - raise - else: - continue # Keep waiting - if data == b"": - return - await self.process_data(data) - - async def process_data(self, data: bytes) -> None: - try: - events = self.connection.receive_data(data) - except h2.exceptions.ProtocolError: - raise MustCloseError() - else: - for event in events: - if isinstance(event, h2.events.RequestReceived): - await self.create_stream(event) - elif isinstance(event, h2.events.DataReceived): - await self.streams[event.stream_id].data_received(event.data) - self.connection.acknowledge_received_data( - event.flow_controlled_length, event.stream_id - ) - elif isinstance(event, h2.events.StreamReset): - await self.streams[event.stream_id].reset() - elif isinstance(event, h2.events.StreamEnded): - await self.streams[event.stream_id].ended() - elif isinstance(event, h2.events.WindowUpdated): - self.window_updated(event.stream_id) - elif isinstance(event, h2.events.ConnectionTerminated): - raise MustCloseError() - await self.send() - - async def asend(self, stream_id: int, event: H2Event) -> None: - connection_state = self.connection.state_machine.state - stream_state = self.connection.streams[stream_id].state_machine.state - if ( - connection_state == h2.connection.ConnectionState.CLOSED - or stream_state == h2.stream.StreamState.CLOSED - ): - return - if isinstance(event, Response): - self.connection.send_headers( - stream_id, event.headers + self.response_headers() # type: ignore - ) - await self.send() - elif isinstance(event, EndStream): - self.connection.end_stream(stream_id) - await self.send() - elif isinstance(event, Data): - await self.send_data(stream_id, event.data) - elif isinstance(event, ServerPush): - await self.server_push(stream_id, event.path, event.headers) - - async def send_data(self, stream_id: int, data: bytes) -> None: - while True: - while not self.connection.local_flow_control_window(stream_id): - await self.wait_for_flow_control(stream_id) - - chunk_size = min(len(data), self.connection.local_flow_control_window(stream_id)) - chunk_size = min(chunk_size, self.connection.max_outbound_frame_size) - if chunk_size < 1: # Pathological client sending negative window sizes - continue - self.connection.send_data(stream_id, data[:chunk_size]) - await self.send() - data = data[chunk_size:] - if not data: - break - - async def send(self) -> None: - data = self.connection.data_to_send() - if data == b"": - return - async with self.send_lock: - try: - await self.stream.send_all(data) - except trio.BrokenResourceError: - pass - - async def wait_for_flow_control(self, stream_id: int) -> None: - event = trio.Event() - self.flow_control[stream_id] = event - await event.wait() - - def window_updated(self, stream_id: Optional[int]) -> None: - if stream_id is None or stream_id == 0: - # Unblock all streams - stream_ids = list(self.flow_control.keys()) - for stream_id in stream_ids: - event = self.flow_control.pop(stream_id) - event.set() - elif stream_id is not None: - if stream_id in self.flow_control: - event = self.flow_control.pop(stream_id) - event.set() - - async def server_push( - self, stream_id: int, path: str, headers: Iterable[Tuple[bytes, bytes]] - ) -> None: - push_stream_id = self.connection.get_next_available_stream_id() - stream = self.streams[stream_id] - for name, value in stream.scope["headers"]: - if name == b":authority": - authority = value - request_headers = [ - (name, value) - for name, value in chain( - [ - (b":method", b"GET"), - (b":path", path.encode()), - (b":scheme", stream.scope["scheme"].encode()), - (b":authority", authority), - ], - headers, - self.response_headers(), - ) - ] - try: - self.connection.push_stream( - stream_id=stream_id, - promised_stream_id=push_stream_id, - request_headers=request_headers, - ) - except h2.exceptions.ProtocolError: - # Client does not accept push promises or we are trying to - # push on a push promises request. - pass - else: - event = h2.events.RequestReceived() - event.stream_id = push_stream_id - event.headers = request_headers - await self.create_stream(event, complete=True) - - @property - def scheme(self) -> str: - return "https" if self._is_ssl else "http" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/lifespan.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/lifespan.py deleted file mode 100644 index 6d73ebe..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/lifespan.py +++ /dev/null @@ -1,76 +0,0 @@ -import trio - -from ..config import Config -from ..typing import ASGIFramework -from ..utils import invoke_asgi, LifespanFailure, LifespanTimeout - - -class UnexpectedMessage(Exception): - pass - - -class Lifespan: - def __init__(self, app: ASGIFramework, config: Config) -> None: - self.app = app - self.config = config - self.startup = trio.Event() - self.shutdown = trio.Event() - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - self.supported = True - - async def handle_lifespan( - self, *, task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED - ) -> None: - task_status.started() - scope = {"type": "lifespan", "asgi": {"spec_version": "2.0"}} - try: - await invoke_asgi(self.app, scope, self.asgi_receive, self.asgi_send) - except LifespanFailure: - # Lifespan failures should crash the server - raise - except Exception: - self.supported = False - if self.config.error_logger is not None: - self.config.error_logger.warning( - "ASGI Framework Lifespan error, continuing without Lifespan support" - ) - finally: - await self.app_send_channel.aclose() - await self.app_receive_channel.aclose() - - async def wait_for_startup(self) -> None: - if not self.supported: - return - - await self.app_send_channel.send({"type": "lifespan.startup"}) - try: - with trio.fail_after(self.config.startup_timeout): - await self.startup.wait() - except trio.TooSlowError as error: - raise LifespanTimeout("startup") from error - - async def wait_for_shutdown(self) -> None: - if not self.supported: - return - - await self.app_send_channel.send({"type": "lifespan.shutdown"}) - try: - with trio.fail_after(self.config.shutdown_timeout): - await self.shutdown.wait() - except trio.TooSlowError as error: - raise LifespanTimeout("startup") from error - - async def asgi_receive(self) -> dict: - return await self.app_receive_channel.receive() - - async def asgi_send(self, message: dict) -> None: - if message["type"] == "lifespan.startup.complete": - self.startup.set() - elif message["type"] == "lifespan.shutdown.complete": - self.shutdown.set() - elif message["type"] == "lifespan.startup.failed": - raise LifespanFailure("startup", message["message"]) - elif message["type"] == "lifespan.shutdown.failed": - raise LifespanFailure("shutdown", message["message"]) - else: - raise UnexpectedMessage(message["type"]) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/run.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/run.py deleted file mode 100644 index 63d8f42..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/run.py +++ /dev/null @@ -1,123 +0,0 @@ -from functools import partial -from multiprocessing.synchronize import Event as EventType -from typing import Optional - -import trio - -from .h2 import H2Server -from .h11 import H11Server -from .lifespan import Lifespan -from .wsproto import WebsocketServer -from ..asgi.run import H2CProtocolRequired, H2ProtocolAssumed, WebsocketProtocolRequired -from ..config import Config, Sockets -from ..typing import ASGIFramework -from ..utils import ( - check_shutdown, - load_application, - MustReloadException, - observe_changes, - restart, - Shutdown, -) - - -async def serve_stream(app: ASGIFramework, config: Config, stream: trio.abc.Stream) -> None: - if config.ssl_enabled: - try: - with trio.fail_after(config.ssl_handshake_timeout): - await stream.do_handshake() - except (trio.BrokenResourceError, trio.TooSlowError): - return # Handshake failed - selected_protocol = stream.selected_alpn_protocol() - else: - selected_protocol = "http/1.1" - - if selected_protocol == "h2": - protocol = H2Server(app, config, stream) - else: - protocol = H11Server(app, config, stream) # type: ignore - try: - await protocol.handle_connection() - except WebsocketProtocolRequired as error: - protocol = WebsocketServer( # type: ignore - app, config, stream, upgrade_request=error.request - ) - await protocol.handle_connection() - except H2CProtocolRequired as error: - protocol = H2Server(app, config, stream, upgrade_request=error.request) - await protocol.handle_connection() - except H2ProtocolAssumed as error: - protocol = H2Server(app, config, stream, received_data=error.data) - await protocol.handle_connection() - - -async def worker_serve( - app: ASGIFramework, - config: Config, - *, - sockets: Optional[Sockets] = None, - shutdown_event: Optional[EventType] = None, - task_status: trio._core._run._TaskStatus = trio.TASK_STATUS_IGNORED, -) -> None: - lifespan = Lifespan(app, config) - reload_ = False - - async with trio.open_nursery() as lifespan_nursery: - await lifespan_nursery.start(lifespan.handle_lifespan) - await lifespan.wait_for_startup() - - try: - async with trio.open_nursery() as nursery: - if config.use_reloader: - nursery.start_soon(observe_changes, trio.sleep) - - if shutdown_event is not None: - nursery.start_soon(check_shutdown, shutdown_event, trio.sleep) - - if sockets is None: - sockets = config.create_sockets() - for sock in sockets.secure_sockets: - sock.listen(config.backlog) - for sock in sockets.insecure_sockets: - sock.listen(config.backlog) - - ssl_context = config.create_ssl_context() - listeners = [ - trio.ssl.SSLListener( - trio.SocketListener(trio.socket.from_stdlib_socket(sock)), - ssl_context, - https_compatible=True, - ) - for sock in sockets.secure_sockets - ] - listeners.extend( - [ - trio.SocketListener(trio.socket.from_stdlib_socket(sock)) - for sock in sockets.insecure_sockets - ] - ) - task_status.started() - await trio.serve_listeners(partial(serve_stream, app, config), listeners) - - except MustReloadException: - reload_ = True - except (Shutdown, KeyboardInterrupt): - pass - finally: - await lifespan.wait_for_shutdown() - lifespan_nursery.cancel_scope.cancel() - - if reload_: - restart() - - -def trio_worker( - config: Config, sockets: Optional[Sockets] = None, shutdown_event: Optional[EventType] = None -) -> None: - if sockets is not None: - for sock in sockets.secure_sockets: - sock.listen(config.backlog) - for sock in sockets.insecure_sockets: - sock.listen(config.backlog) - app = load_application(config.application_path) - trio.run(partial(worker_serve, app, config, sockets=sockets, shutdown_event=shutdown_event)) diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/trio/wsproto.py b/py3.7/lib/python3.7/site-packages/hypercorn/trio/wsproto.py deleted file mode 100644 index 2685dc2..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/trio/wsproto.py +++ /dev/null @@ -1,107 +0,0 @@ -from typing import Optional - -import h11 -import trio -from wsproto import ConnectionType, WSConnection -from wsproto.connection import ConnectionState -from wsproto.events import CloseConnection, Event, Message, Ping, Request -from wsproto.frame_protocol import CloseReason - -from .base import HTTPServer -from ..asgi.utils import ASGIWebsocketState, FrameTooLarge, WebsocketBuffer -from ..asgi.wsproto import WebsocketMixin -from ..config import Config -from ..typing import ASGIFramework - -MAX_RECV = 2 ** 16 - - -class MustCloseError(Exception): - pass - - -class WebsocketServer(HTTPServer, WebsocketMixin): - def __init__( - self, - app: ASGIFramework, - config: Config, - stream: trio.abc.Stream, - *, - upgrade_request: Optional[h11.Request] = None, - ) -> None: - super().__init__(stream, "wsproto") - self.app = app - self.config = config - self.connection = WSConnection(ConnectionType.SERVER) - self.response: Optional[dict] = None - self.scope: Optional[dict] = None - self.send_lock = trio.Lock() - self.state = ASGIWebsocketState.HANDSHAKE - - self.buffer = WebsocketBuffer(self.config.websocket_max_message_size) - self.app_send_channel, self.app_receive_channel = trio.open_memory_channel(10) - - if upgrade_request is not None: - self.connection.initiate_upgrade_connection( - upgrade_request.headers, upgrade_request.target - ) - - async def handle_connection(self) -> None: - try: - request = await self.read_request() - async with trio.open_nursery() as nursery: - nursery.start_soon(self.read_messages) - await self.handle_websocket(request) - if self.state == ASGIWebsocketState.HTTPCLOSED: - raise MustCloseError() - except (trio.BrokenResourceError, trio.ClosedResourceError): - await self.asgi_put({"type": "websocket.disconnect"}) - except MustCloseError: - pass - finally: - await self.aclose() - - async def read_request(self) -> Request: - for event in self.connection.events(): - if isinstance(event, Request): - return event - - async def read_messages(self) -> None: - while True: - data = await self.stream.receive_some(MAX_RECV) - if data == b"": - data = None # wsproto expects None rather than b"" for EOF - self.connection.receive_data(data) - for event in self.connection.events(): - if isinstance(event, Message): - try: - self.buffer.extend(event) - except FrameTooLarge: - await self.asend(CloseConnection(code=CloseReason.MESSAGE_TOO_BIG)) - await self.asgi_put({"type": "websocket.disconnect"}) - raise MustCloseError() - - if event.message_finished: - await self.asgi_put(self.buffer.to_message()) - self.buffer.clear() - elif isinstance(event, Ping): - await self.asend(event.response()) - elif isinstance(event, CloseConnection): - if self.connection.state == ConnectionState.REMOTE_CLOSING: - await self.asend(event.response()) - await self.asgi_put({"type": "websocket.disconnect"}) - raise MustCloseError() - - async def asend(self, event: Event) -> None: - async with self.send_lock: - await self.stream.send_all(self.connection.send(event)) - - async def asgi_put(self, message: dict) -> None: - await self.app_send_channel.send(message) - - async def asgi_receive(self) -> dict: - return await self.app_receive_channel.receive() - - @property - def scheme(self) -> str: - return "wss" if self._is_ssl else "ws" diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/typing.py b/py3.7/lib/python3.7/site-packages/hypercorn/typing.py deleted file mode 100644 index 433309d..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/typing.py +++ /dev/null @@ -1,77 +0,0 @@ -from multiprocessing.synchronize import Event as EventType -from typing import Awaitable, Callable, Optional, Tuple, Type, Union - -import h2.events -import h11 -from typing_extensions import Protocol # Till PEP 544 is accepted - -from .config import Config, Sockets - -H11SendableEvent = Union[h11.Data, h11.EndOfMessage, h11.InformationalResponse, h11.Response] - -WorkerFunc = Callable[[Config, Optional[Sockets], Optional[EventType]], None] - - -class ASGI2Protocol(Protocol): - # Should replace with a Protocol when PEP 544 is accepted. - - def __init__(self, scope: dict) -> None: - ... - - async def __call__(self, receive: Callable, send: Callable) -> None: - ... - - -ASGI2Framework = Type[ASGI2Protocol] -ASGI3Framework = Callable[[dict, Callable, Callable], Awaitable[None]] -ASGIFramework = Union[ASGI2Framework, ASGI3Framework] - - -class H2SyncStream(Protocol): - scope: dict - - def data_received(self, data: bytes) -> None: - ... - - def ended(self) -> None: - ... - - def reset(self) -> None: - ... - - def close(self) -> None: - ... - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - ... - - -class H2AsyncStream(Protocol): - scope: dict - - async def data_received(self, data: bytes) -> None: - ... - - async def ended(self) -> None: - ... - - async def reset(self) -> None: - ... - - async def close(self) -> None: - ... - - async def handle_request( - self, - event: h2.events.RequestReceived, - scheme: str, - client: Tuple[str, int], - server: Tuple[str, int], - ) -> None: - ... diff --git a/py3.7/lib/python3.7/site-packages/hypercorn/utils.py b/py3.7/lib/python3.7/site-packages/hypercorn/utils.py deleted file mode 100644 index e2cd320..0000000 --- a/py3.7/lib/python3.7/site-packages/hypercorn/utils.py +++ /dev/null @@ -1,176 +0,0 @@ -import inspect -import os -import platform -import socket -import sys -from importlib import import_module -from multiprocessing.synchronize import Event as EventType -from pathlib import Path -from time import time -from types import ModuleType -from typing import Any, Awaitable, Callable, cast, Dict, List, Optional, Tuple -from wsgiref.handlers import format_date_time - -from .typing import ASGI2Framework, ASGI3Framework, ASGIFramework - - -class Shutdown(Exception): - pass - - -class MustReloadException(Exception): - pass - - -class NoAppException(Exception): - pass - - -class LifespanTimeout(Exception): - def __init__(self, stage: str) -> None: - super().__init__( - f"Timeout whilst awaiting {stage}. Your application may not support the ASGI Lifespan " - f"protocol correctly, alternatively the {stage}_timeout configuration is incorrect." - ) - - -class LifespanFailure(Exception): - def __init__(self, stage: str, message: str) -> None: - super().__init__(f"Lifespan failure in {stage}. {message}") - - -def suppress_body(method: str, status_code: int) -> bool: - return method == "HEAD" or 100 <= status_code < 200 or status_code in {204, 304, 412} - - -def response_headers(protocol: str) -> List[Tuple[bytes, bytes]]: - return [ - (b"date", format_date_time(time()).encode("ascii")), - (b"server", f"hypercorn-{protocol}".encode("ascii")), - ] - - -def load_application(path: str) -> ASGIFramework: - try: - module_name, app_name = path.split(":", 1) - except ValueError: - module_name, app_name = path, "app" - except AttributeError: - raise NoAppException() - - module_path = Path(module_name).resolve() - sys.path.insert(0, str(module_path.parent)) - if module_path.is_file(): - import_name = module_path.with_suffix("").name - else: - import_name = module_path.name - try: - module = import_module(import_name) - except ModuleNotFoundError as error: - if error.name == import_name: # type: ignore - raise NoAppException() - else: - raise - - try: - return eval(app_name, vars(module)) - except NameError: - raise NoAppException() - - -async def observe_changes(sleep: Callable[[float], Awaitable[Any]]) -> None: - last_updates: Dict[ModuleType, float] = {} - while True: - for module in list(sys.modules.values()): - await sleep(0) - filename = getattr(module, "__file__", None) - if filename is None: - continue - try: - mtime = Path(filename).stat().st_mtime - except FileNotFoundError: - continue - else: - if mtime > last_updates.get(module, mtime): - raise MustReloadException() - last_updates[module] = mtime - await sleep(1) - - -def restart() -> None: - # Restart this process (only safe for dev/debug) - executable = sys.executable - script_path = Path(sys.argv[0]).resolve() - args = sys.argv[1:] - main_package = sys.modules["__main__"].__package__ - - if main_package is None: - # Executed by filename - if platform.system() == "Windows": - if not script_path.exists() and script_path.with_suffix(".exe").exists(): - # quart run - executable = str(script_path.with_suffix(".exe")) - else: - # python run.py - args.append(str(script_path)) - else: - if script_path.is_file() and os.access(script_path, os.X_OK): - # hypercorn run:app --reload - executable = str(script_path) - else: - # python run.py - args.append(str(script_path)) - else: - # Executed as a module e.g. python -m run - module = script_path.stem - import_name = main_package - if module != "__main__": - import_name = f"{main_package}.{module}" - args[:0] = ["-m", import_name.lstrip(".")] - - os.execv(executable, [executable] + args) - - -async def check_shutdown( - shutdown_event: EventType, sleep: Callable[[float], Awaitable[Any]] -) -> None: - while True: - if shutdown_event.is_set(): - raise Shutdown() - await sleep(0.1) - - -def write_pid_file(pid_path: str) -> None: - with open(pid_path, "w") as file_: - file_.write(f"{os.getpid()}") - - -def parse_socket_addr(family: int, address: tuple) -> Optional[Tuple[str, int]]: - if family == socket.AF_INET: - return address # type: ignore - elif family == socket.AF_INET6: - return (address[0], address[1]) - else: - return None - - -async def invoke_asgi(app: ASGIFramework, scope: dict, receive: Callable, send: Callable) -> None: - if _is_asgi_2(app): - scope["asgi"]["version"] = "2.0" - app = cast(ASGI2Framework, app) - asgi_instance = app(scope) - await asgi_instance(receive, send) - else: - scope["asgi"]["version"] = "3.0" - app = cast(ASGI3Framework, app) - await app(scope, receive, send) - - -def _is_asgi_2(app: ASGIFramework) -> bool: - if inspect.isclass(app): - return True - - if hasattr(app, "__call__") and inspect.iscoroutinefunction(app.__call__): # type: ignore - return False - - return not inspect.iscoroutinefunction(app) diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/LICENSE b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/LICENSE deleted file mode 100644 index d24c351..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Cory Benfield - -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. diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/METADATA deleted file mode 100644 index 51f50e7..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/METADATA +++ /dev/null @@ -1,244 +0,0 @@ -Metadata-Version: 2.1 -Name: hyperframe -Version: 5.2.0 -Summary: HTTP/2 framing layer for Python -Home-page: https://python-hyper.org/hyperframe/en/latest/ -Author: Cory Benfield -Author-email: cory@lukasa.co.uk -License: MIT License -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: Implementation :: CPython - -====================================== -hyperframe: Pure-Python HTTP/2 framing -====================================== - -.. image:: https://travis-ci.org/python-hyper/hyperframe.png?branch=master - :target: https://travis-ci.org/python-hyper/hyperframe - -This library contains the HTTP/2 framing code used in the `hyper`_ project. It -provides a pure-Python codebase that is capable of decoding a binary stream -into HTTP/2 frames. - -This library is used directly by `hyper`_ and a number of other projects to -provide HTTP/2 frame decoding logic. - -Contributing -============ - -hyperframe welcomes contributions from anyone! Unlike many other projects we -are happy to accept cosmetic contributions and small contributions, in addition -to large feature requests and changes. - -Before you contribute (either by opening an issue or filing a pull request), -please `read the contribution guidelines`_. - -.. _read the contribution guidelines: http://hyper.readthedocs.org/en/development/contributing.html - -License -======= - -hyperframe is made available under the MIT License. For more details, see the -``LICENSE`` file in the repository. - -Authors -======= - -hyperframe is maintained by Cory Benfield, with contributions from others. For -more details about the contributors, please see ``CONTRIBUTORS.rst``. - -.. _hyper: http://python-hyper.org/ - - -Release History -=============== - -6.0.0dev0 ---------- - -5.2.0 (2019-01-18) ------------------- - -**API Changes (Backward-compatible)** - -- Add a new ENABLE_CONNECT_PROTOCOL settings paramter. - -**Other Changes** - -- Fix collections.abc deprecation. -- Drop support for Python 3.3 and support 3.7. - -5.1.0 (2017-04-24) ------------------- - -**API Changes (Backward-compatible)** - -- Added support for ``DataFrame.data`` being a ``memoryview`` object. - -5.0.0 (2017-03-07) ------------------- - -**Backwards Incompatible API Changes** - -- Added support for unknown extension frames. These will be returned in the new - ``ExtensionFrame`` object. The flag information for these frames is persisted - in ``flag_byte`` if needed. - -4.0.2 (2017-02-20) ------------------- - -**Bugfixes** - -- Fixed AltSvc stream association, which was incorrectly set to ``'both'``: - should have been ``'either'``. -- Fixed a bug where stream IDs on received frames were allowed to be 32-bit, - instead of 31-bit. -- Fixed a bug with frames that had the ``PADDING`` flag set but zero-length - padding, whose flow-controlled length was calculated wrongly. -- Miscellaneous performance improvements to serialization and parsing logic. - -4.0.1 (2016-03-13) ------------------- - -**Bugfixes** - -- Fixed bug with the repr of ``AltSvcFrame``, where building it could throw - exceptions if the frame had been received from the network. - -4.0.0 (2016-03-13) ------------------- - -**Backwards Incompatible API Changes** - -- Updated old ALTSVC frame definition to match the newly specified RFC 7838. -- Remove BLOCKED frame, which was never actually specified. -- Removed previously deprecated ``SettingsFrame.SETTINGS_MAX_FRAME_SIZE`` and - ``SettingsFrame.SETTINGS_MAX_HEADER_LIST_SIZE``. - -3.2.0 (2016-02-02) ------------------- - -**API Changes (Backward-compatible)** - -- Invalid PING frame bodies now raise ``InvalidFrameError``, not - ``ValueError``. Note that ``InvalidFrameError`` is a ``ValueError`` subclass. -- Invalid RST_STREAM frame bodies now raise ``InvalidFramError``, not - ``ValueError``. Note that ``InvalidFrameError`` is a ``ValueError`` subclass. -- Canonicalized the names of ``SettingsFrame.SETTINGS_MAX_FRAME_SIZE`` and - ``SettingsFrame.SETTINGS_MAX_HEADER_LIST_SIZE`` to match their peers, by - adding new properties ``SettingsFrame.MAX_FRAME_SIZE`` and - ``SettingsFrame.SETTINGS_MAX_HEADER_LIST_SIZE``. The old names are still - present, but will be deprecated in 4.0.0. - -**Bugfixes** - -- The change in ``3.1.0`` that ensured that ``InvalidFrameError`` would be - thrown did not affect certain invalid values in ALT_SVC frames. This has been - fixed: ``ValueError`` will no longer be thrown from invalid ALT_SVC bodies. - -3.1.1 (2016-01-18) ------------------- - -**Bugfixes** - -- Correctly error when receiving Ping frames that have insufficient data. - -3.1.0 (2016-01-13) ------------------- - -**API Changes** - -- Added new ``InvalidFrameError`` that is thrown instead of ``struct.error`` - when parsing a frame. - -**Bugfixes** - -- Fixed error when trying to serialize frames that use Priority information - with the defaults for that information. -- Fixed errors when displaying the repr of frames with non-printable bodies. - -3.0.1 (2016-01-08) ------------------- - -**Bugfixes** - -- Fix issue where unpadded DATA, PUSH_PROMISE and HEADERS frames that had empty - bodies would raise ``InvalidPaddingError`` exceptions when parsed. - -3.0.0 (2016-01-08) ------------------- - -**Backwards Incompatible API Changes** - -- Parsing padded frames that have invalid padding sizes now throws an - ``InvalidPaddingError``. - -2.2.0 (2015-10-15) ------------------- - -**API Changes** - -- When an unknown frame is encountered, ``parse_frame_header`` now throws a - ``ValueError`` subclass: ``UnknownFrameError``. This subclass contains the - frame type and the length of the frame body. - -2.1.0 (2015-10-06) ------------------- - -**API Changes** - -- Frames parsed from binary data now carry a ``body_len`` attribute that - matches the frame length (minus the frame header). - -2.0.0 (2015-09-21) ------------------- - -**API Changes** - -- Attempting to parse unrecognised frames now throws ``ValueError`` instead of - ``KeyError``. Thanks to @Kriechi! -- Flags are now validated for correctness, preventing setting flags that - ``hyperframe`` does not recognise and that would not serialize. Thanks to - @mhils! -- Frame properties can now be initialized in the constructors. Thanks to @mhils - and @Kriechi! -- Frames that cannot be sent on a stream now have their stream ID defaulted - to ``0``. Thanks to @Kriechi! - -**Other Changes** - -- Frames have a more useful repr. Thanks to @mhils! - -1.1.1 (2015-07-20) ------------------- - -- Fix a bug where ``FRAME_MAX_LEN`` was one byte too small. - -1.1.0 (2015-06-28) ------------------- - -- Add ``body_len`` property to frames to enable introspection of the actual - frame length. Thanks to @jdecuyper! - -1.0.1 (2015-06-27) ------------------- - -- Fix bug where the frame header would have an incorrect length added to it. - -1.0.0 (2015-04-12) ------------------- - -- Initial extraction from hyper. - - diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/RECORD deleted file mode 100644 index d73c92a..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/RECORD +++ /dev/null @@ -1,14 +0,0 @@ -hyperframe/__init__.py,sha256=9ql6Hb25Q3PrN4r7JdmX8UMzN3cFcDLQe4_qYf8iWJc,136 -hyperframe/exceptions.py,sha256=cFLMN1IjXSPyhpWGOtfhPrVM5qu7kprOQJHSaWSOd88,936 -hyperframe/flags.py,sha256=O_Mvcvzcc-HR_X-dPMb_Z7GMttowb9G9lDyim8R4I7s,1286 -hyperframe/frame.py,sha256=UclwgZMXUnX9IBwKJWvUJcG1JrDnKbBtcXnx4v4uqkw,26658 -hyperframe-5.2.0.dist-info/LICENSE,sha256=djqTQqBN9iBGydx0ilKHk06wpTMcaGOzygruIOGMtO0,1080 -hyperframe-5.2.0.dist-info/METADATA,sha256=AX9DhnXJ__T6f3nKijVXUIQoRZRcoRCX-OuVjdE0p5k,7232 -hyperframe-5.2.0.dist-info/WHEEL,sha256=_wJFdOYk7i3xxT8ElOkUJvOdOvfNGbR9g-bf6UQT6sU,110 -hyperframe-5.2.0.dist-info/top_level.txt,sha256=aIXWNxzKF_jwE8lyWG5Paqn5RP7PDBYeguraia-oHJE,11 -hyperframe-5.2.0.dist-info/RECORD,, -hyperframe-5.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -hyperframe/__pycache__/__init__.cpython-37.pyc,, -hyperframe/__pycache__/exceptions.cpython-37.pyc,, -hyperframe/__pycache__/frame.cpython-37.pyc,, -hyperframe/__pycache__/flags.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/WHEEL deleted file mode 100644 index c4bde30..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.32.3) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/top_level.txt deleted file mode 100644 index b21bb7c..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe-5.2.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -hyperframe diff --git a/py3.7/lib/python3.7/site-packages/hyperframe/__init__.py b/py3.7/lib/python3.7/site-packages/hyperframe/__init__.py deleted file mode 100644 index 7620b4b..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hyperframe -~~~~~~~~~~ - -A module for providing a pure-Python HTTP/2 framing layer. -""" -__version__ = '5.2.0' diff --git a/py3.7/lib/python3.7/site-packages/hyperframe/exceptions.py b/py3.7/lib/python3.7/site-packages/hyperframe/exceptions.py deleted file mode 100644 index dd30369..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe/exceptions.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hyperframe/exceptions -~~~~~~~~~~~~~~~~~~~~~ - -Defines the exceptions that can be thrown by hyperframe. -""" - - -class UnknownFrameError(ValueError): - """ - An frame of unknown type was received. - """ - def __init__(self, frame_type, length): - #: The type byte of the unknown frame that was received. - self.frame_type = frame_type - - #: The length of the data portion of the unknown frame. - self.length = length - - def __str__(self): - return ( - "UnknownFrameError: Unknown frame type 0x%X received, " - "length %d bytes" % (self.frame_type, self.length) - ) - - -class InvalidPaddingError(ValueError): - """ - A frame with invalid padding was received. - """ - pass - - -class InvalidFrameError(ValueError): - """ - Parsing a frame failed because the data was not laid out appropriately. - - .. versionadded:: 3.0.2 - """ - pass diff --git a/py3.7/lib/python3.7/site-packages/hyperframe/flags.py b/py3.7/lib/python3.7/site-packages/hyperframe/flags.py deleted file mode 100644 index 1660bd1..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe/flags.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hyperframe/flags -~~~~~~~~~~~~~~~~ - -Defines basic Flag and Flags data structures. -""" -import collections - -try: - from collections.abc import MutableSet -except ImportError: # pragma: no cover - # Python 2.7 compatibility - from collections import MutableSet - -Flag = collections.namedtuple("Flag", ["name", "bit"]) - - -class Flags(MutableSet): - """ - A simple MutableSet implementation that will only accept known flags as - elements. - - Will behave like a regular set(), except that a ValueError will be thrown - when .add()ing unexpected flags. - """ - def __init__(self, defined_flags): - self._valid_flags = set(flag.name for flag in defined_flags) - self._flags = set() - - def __contains__(self, x): - return self._flags.__contains__(x) - - def __iter__(self): - return self._flags.__iter__() - - def __len__(self): - return self._flags.__len__() - - def discard(self, value): - return self._flags.discard(value) - - def add(self, value): - if value not in self._valid_flags: - raise ValueError( - "Unexpected flag: {}. Valid flags are: {}".format( - value, self._valid_flags - ) - ) - return self._flags.add(value) diff --git a/py3.7/lib/python3.7/site-packages/hyperframe/frame.py b/py3.7/lib/python3.7/site-packages/hyperframe/frame.py deleted file mode 100644 index 7950572..0000000 --- a/py3.7/lib/python3.7/site-packages/hyperframe/frame.py +++ /dev/null @@ -1,822 +0,0 @@ -# -*- coding: utf-8 -*- -""" -hyperframe/frame -~~~~~~~~~~~~~~~~ - -Defines framing logic for HTTP/2. Provides both classes to represent framed -data and logic for aiding the connection when it comes to reading from the -socket. -""" -import struct -import binascii - -from .exceptions import ( - UnknownFrameError, InvalidPaddingError, InvalidFrameError -) -from .flags import Flag, Flags - - -# The maximum initial length of a frame. Some frames have shorter maximum -# lengths. -FRAME_MAX_LEN = (2 ** 14) - -# The maximum allowed length of a frame. -FRAME_MAX_ALLOWED_LEN = (2 ** 24) - 1 - -# Stream association enumerations. -_STREAM_ASSOC_HAS_STREAM = "has-stream" -_STREAM_ASSOC_NO_STREAM = "no-stream" -_STREAM_ASSOC_EITHER = "either" - -# Structs for packing and unpacking -_STRUCT_HBBBL = struct.Struct(">HBBBL") -_STRUCT_LL = struct.Struct(">LL") -_STRUCT_HL = struct.Struct(">HL") -_STRUCT_LB = struct.Struct(">LB") -_STRUCT_L = struct.Struct(">L") -_STRUCT_H = struct.Struct(">H") -_STRUCT_B = struct.Struct(">B") - - -class Frame(object): - """ - The base class for all HTTP/2 frames. - """ - #: The flags defined on this type of frame. - defined_flags = [] - - #: The byte used to define the type of the frame. - type = None - - # If 'has-stream', the frame's stream_id must be non-zero. If 'no-stream', - # it must be zero. If 'either', it's not checked. - stream_association = None - - def __init__(self, stream_id, flags=()): - #: The stream identifier for the stream this frame was received on. - #: Set to 0 for frames sent on the connection (stream-id 0). - self.stream_id = stream_id - - #: The flags set for this frame. - self.flags = Flags(self.defined_flags) - - #: The frame length, excluding the nine-byte header. - self.body_len = 0 - - for flag in flags: - self.flags.add(flag) - - if (not self.stream_id and - self.stream_association == _STREAM_ASSOC_HAS_STREAM): - raise ValueError('Stream ID must be non-zero') - if (self.stream_id and - self.stream_association == _STREAM_ASSOC_NO_STREAM): - raise ValueError('Stream ID must be zero') - - def __repr__(self): - flags = ", ".join(self.flags) or "None" - body = binascii.hexlify(self.serialize_body()).decode('ascii') - if len(body) > 20: - body = body[:20] + "..." - return ( - "{type}(Stream: {stream}; Flags: {flags}): {body}" - ).format( - type=type(self).__name__, - stream=self.stream_id, - flags=flags, - body=body - ) - - @staticmethod - def parse_frame_header(header, strict=False): - """ - Takes a 9-byte frame header and returns a tuple of the appropriate - Frame object and the length that needs to be read from the socket. - - This populates the flags field, and determines how long the body is. - - :param strict: Whether to raise an exception when encountering a frame - not defined by spec and implemented by hyperframe. - - :raises hyperframe.exceptions.UnknownFrameError: If a frame of unknown - type is received. - - .. versionchanged:: 5.0.0 - Added :param:`strict` to accommodate :class:`ExtensionFrame` - """ - try: - fields = _STRUCT_HBBBL.unpack(header) - except struct.error: - raise InvalidFrameError("Invalid frame header") - - # First 24 bits are frame length. - length = (fields[0] << 8) + fields[1] - type = fields[2] - flags = fields[3] - stream_id = fields[4] & 0x7FFFFFFF - - try: - frame = FRAMES[type](stream_id) - except KeyError: - if strict: - raise UnknownFrameError(type, length) - frame = ExtensionFrame(type=type, stream_id=stream_id) - - frame.parse_flags(flags) - return (frame, length) - - def parse_flags(self, flag_byte): - for flag, flag_bit in self.defined_flags: - if flag_byte & flag_bit: - self.flags.add(flag) - - return self.flags - - def serialize(self): - """ - Convert a frame into a bytestring, representing the serialized form of - the frame. - """ - body = self.serialize_body() - self.body_len = len(body) - - # Build the common frame header. - # First, get the flags. - flags = 0 - - for flag, flag_bit in self.defined_flags: - if flag in self.flags: - flags |= flag_bit - - header = _STRUCT_HBBBL.pack( - (self.body_len >> 8) & 0xFFFF, # Length spread over top 24 bits - self.body_len & 0xFF, - self.type, - flags, - self.stream_id & 0x7FFFFFFF # Stream ID is 32 bits. - ) - - return header + body - - def serialize_body(self): - raise NotImplementedError() - - def parse_body(self, data): - """ - Given the body of a frame, parses it into frame data. This populates - the non-header parts of the frame: that is, it does not populate the - stream ID or flags. - - :param data: A memoryview object containing the body data of the frame. - Must not contain *more* data than the length returned by - :meth:`parse_frame_header - `. - """ - raise NotImplementedError() - - -class Padding(object): - """ - Mixin for frames that contain padding. Defines extra fields that can be - used and set by frames that can be padded. - """ - def __init__(self, stream_id, pad_length=0, **kwargs): - super(Padding, self).__init__(stream_id, **kwargs) - - #: The length of the padding to use. - self.pad_length = pad_length - - def serialize_padding_data(self): - if 'PADDED' in self.flags: - return _STRUCT_B.pack(self.pad_length) - return b'' - - def parse_padding_data(self, data): - if 'PADDED' in self.flags: - try: - self.pad_length = struct.unpack('!B', data[:1])[0] - except struct.error: - raise InvalidFrameError("Invalid Padding data") - return 1 - return 0 - - @property - def total_padding(self): - return self.pad_length - - -class Priority(object): - """ - Mixin for frames that contain priority data. Defines extra fields that can - be used and set by frames that contain priority data. - """ - def __init__(self, - stream_id, - depends_on=0x0, - stream_weight=0x0, - exclusive=False, - **kwargs): - super(Priority, self).__init__(stream_id, **kwargs) - - #: The stream ID of the stream on which this stream depends. - self.depends_on = depends_on - - #: The weight of the stream. This is an integer between 0 and 256. - self.stream_weight = stream_weight - - #: Whether the exclusive bit was set. - self.exclusive = exclusive - - def serialize_priority_data(self): - return _STRUCT_LB.pack( - self.depends_on + (0x80000000 if self.exclusive else 0), - self.stream_weight - ) - - def parse_priority_data(self, data): - try: - self.depends_on, self.stream_weight = _STRUCT_LB.unpack(data[:5]) - except struct.error: - raise InvalidFrameError("Invalid Priority data") - - self.exclusive = True if self.depends_on >> 31 else False - self.depends_on &= 0x7FFFFFFF - return 5 - - -class DataFrame(Padding, Frame): - """ - DATA frames convey arbitrary, variable-length sequences of octets - associated with a stream. One or more DATA frames are used, for instance, - to carry HTTP request or response payloads. - """ - #: The flags defined for DATA frames. - defined_flags = [ - Flag('END_STREAM', 0x01), - Flag('PADDED', 0x08), - ] - - #: The type byte for data frames. - type = 0x0 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id, data=b'', **kwargs): - super(DataFrame, self).__init__(stream_id, **kwargs) - - #: The data contained on this frame. - self.data = data - - def serialize_body(self): - padding_data = self.serialize_padding_data() - padding = b'\0' * self.total_padding - if isinstance(self.data, memoryview): - self.data = self.data.tobytes() - return b''.join([padding_data, self.data, padding]) - - def parse_body(self, data): - padding_data_length = self.parse_padding_data(data) - self.data = ( - data[padding_data_length:len(data)-self.total_padding].tobytes() - ) - self.body_len = len(data) - - if self.total_padding and self.total_padding >= self.body_len: - raise InvalidPaddingError("Padding is too long.") - - @property - def flow_controlled_length(self): - """ - The length of the frame that needs to be accounted for when considering - flow control. - """ - padding_len = 0 - if 'PADDED' in self.flags: - # Account for extra 1-byte padding length field, which is still - # present if possibly zero-valued. - padding_len = self.total_padding + 1 - return len(self.data) + padding_len - - -class PriorityFrame(Priority, Frame): - """ - The PRIORITY frame specifies the sender-advised priority of a stream. It - can be sent at any time for an existing stream. This enables - reprioritisation of existing streams. - """ - #: The flags defined for PRIORITY frames. - defined_flags = [] - - #: The type byte defined for PRIORITY frames. - type = 0x02 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def serialize_body(self): - return self.serialize_priority_data() - - def parse_body(self, data): - self.parse_priority_data(data) - self.body_len = len(data) - - -class RstStreamFrame(Frame): - """ - The RST_STREAM frame allows for abnormal termination of a stream. When sent - by the initiator of a stream, it indicates that they wish to cancel the - stream or that an error condition has occurred. When sent by the receiver - of a stream, it indicates that either the receiver is rejecting the stream, - requesting that the stream be cancelled or that an error condition has - occurred. - """ - #: The flags defined for RST_STREAM frames. - defined_flags = [] - - #: The type byte defined for RST_STREAM frames. - type = 0x03 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id, error_code=0, **kwargs): - super(RstStreamFrame, self).__init__(stream_id, **kwargs) - - #: The error code used when resetting the stream. - self.error_code = error_code - - def serialize_body(self): - return _STRUCT_L.pack(self.error_code) - - def parse_body(self, data): - if len(data) != 4: - raise InvalidFrameError( - "RST_STREAM must have 4 byte body: actual length %s." % - len(data) - ) - - try: - self.error_code = _STRUCT_L.unpack(data)[0] - except struct.error: # pragma: no cover - raise InvalidFrameError("Invalid RST_STREAM body") - - self.body_len = 4 - - -class SettingsFrame(Frame): - """ - The SETTINGS frame conveys configuration parameters that affect how - endpoints communicate. The parameters are either constraints on peer - behavior or preferences. - - Settings are not negotiated. Settings describe characteristics of the - sending peer, which are used by the receiving peer. Different values for - the same setting can be advertised by each peer. For example, a client - might set a high initial flow control window, whereas a server might set a - lower value to conserve resources. - """ - #: The flags defined for SETTINGS frames. - defined_flags = [Flag('ACK', 0x01)] - - #: The type byte defined for SETTINGS frames. - type = 0x04 - - stream_association = _STREAM_ASSOC_NO_STREAM - - # We need to define the known settings, they may as well be class - # attributes. - #: The byte that signals the SETTINGS_HEADER_TABLE_SIZE setting. - HEADER_TABLE_SIZE = 0x01 - #: The byte that signals the SETTINGS_ENABLE_PUSH setting. - ENABLE_PUSH = 0x02 - #: The byte that signals the SETTINGS_MAX_CONCURRENT_STREAMS setting. - MAX_CONCURRENT_STREAMS = 0x03 - #: The byte that signals the SETTINGS_INITIAL_WINDOW_SIZE setting. - INITIAL_WINDOW_SIZE = 0x04 - #: The byte that signals the SETTINGS_MAX_FRAME_SIZE setting. - MAX_FRAME_SIZE = 0x05 - #: The byte that signals the SETTINGS_MAX_HEADER_LIST_SIZE setting. - MAX_HEADER_LIST_SIZE = 0x06 - #: The byte that signals SETTINGS_ENABLE_CONNECT_PROTOCOL setting. - ENABLE_CONNECT_PROTOCOL = 0x08 - - def __init__(self, stream_id=0, settings=None, **kwargs): - super(SettingsFrame, self).__init__(stream_id, **kwargs) - - if settings and "ACK" in kwargs.get("flags", ()): - raise ValueError("Settings must be empty if ACK flag is set.") - - #: A dictionary of the setting type byte to the value of the setting. - self.settings = settings or {} - - def serialize_body(self): - return b''.join([_STRUCT_HL.pack(setting & 0xFF, value) - for setting, value in self.settings.items()]) - - def parse_body(self, data): - body_len = 0 - for i in range(0, len(data), 6): - try: - name, value = _STRUCT_HL.unpack(data[i:i+6]) - except struct.error: - raise InvalidFrameError("Invalid SETTINGS body") - - self.settings[name] = value - body_len += 6 - - self.body_len = body_len - - -class PushPromiseFrame(Padding, Frame): - """ - The PUSH_PROMISE frame is used to notify the peer endpoint in advance of - streams the sender intends to initiate. - """ - #: The flags defined for PUSH_PROMISE frames. - defined_flags = [ - Flag('END_HEADERS', 0x04), - Flag('PADDED', 0x08) - ] - - #: The type byte defined for PUSH_PROMISE frames. - type = 0x05 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id, promised_stream_id=0, data=b'', **kwargs): - super(PushPromiseFrame, self).__init__(stream_id, **kwargs) - - #: The stream ID that is promised by this frame. - self.promised_stream_id = promised_stream_id - - #: The HPACK-encoded header block for the simulated request on the new - #: stream. - self.data = data - - def serialize_body(self): - padding_data = self.serialize_padding_data() - padding = b'\0' * self.total_padding - data = _STRUCT_L.pack(self.promised_stream_id) - return b''.join([padding_data, data, self.data, padding]) - - def parse_body(self, data): - padding_data_length = self.parse_padding_data(data) - - try: - self.promised_stream_id = _STRUCT_L.unpack( - data[padding_data_length:padding_data_length + 4] - )[0] - except struct.error: - raise InvalidFrameError("Invalid PUSH_PROMISE body") - - self.data = data[padding_data_length + 4:].tobytes() - self.body_len = len(data) - - if self.total_padding and self.total_padding >= self.body_len: - raise InvalidPaddingError("Padding is too long.") - - -class PingFrame(Frame): - """ - The PING frame is a mechanism for measuring a minimal round-trip time from - the sender, as well as determining whether an idle connection is still - functional. PING frames can be sent from any endpoint. - """ - #: The flags defined for PING frames. - defined_flags = [Flag('ACK', 0x01)] - - #: The type byte defined for PING frames. - type = 0x06 - - stream_association = _STREAM_ASSOC_NO_STREAM - - def __init__(self, stream_id=0, opaque_data=b'', **kwargs): - super(PingFrame, self).__init__(stream_id, **kwargs) - - #: The opaque data sent in this PING frame, as a bytestring. - self.opaque_data = opaque_data - - def serialize_body(self): - if len(self.opaque_data) > 8: - raise InvalidFrameError( - "PING frame may not have more than 8 bytes of data, got %s" % - self.opaque_data - ) - - data = self.opaque_data - data += b'\x00' * (8 - len(self.opaque_data)) - return data - - def parse_body(self, data): - if len(data) != 8: - raise InvalidFrameError( - "PING frame must have 8 byte length: got %s" % len(data) - ) - - self.opaque_data = data.tobytes() - self.body_len = 8 - - -class GoAwayFrame(Frame): - """ - The GOAWAY frame informs the remote peer to stop creating streams on this - connection. It can be sent from the client or the server. Once sent, the - sender will ignore frames sent on new streams for the remainder of the - connection. - """ - #: The flags defined for GOAWAY frames. - defined_flags = [] - - #: The type byte defined for GOAWAY frames. - type = 0x07 - - stream_association = _STREAM_ASSOC_NO_STREAM - - def __init__(self, - stream_id=0, - last_stream_id=0, - error_code=0, - additional_data=b'', - **kwargs): - super(GoAwayFrame, self).__init__(stream_id, **kwargs) - - #: The last stream ID definitely seen by the remote peer. - self.last_stream_id = last_stream_id - - #: The error code for connection teardown. - self.error_code = error_code - - #: Any additional data sent in the GOAWAY. - self.additional_data = additional_data - - def serialize_body(self): - data = _STRUCT_LL.pack( - self.last_stream_id & 0x7FFFFFFF, - self.error_code - ) - data += self.additional_data - - return data - - def parse_body(self, data): - try: - self.last_stream_id, self.error_code = _STRUCT_LL.unpack( - data[:8] - ) - except struct.error: - raise InvalidFrameError("Invalid GOAWAY body.") - - self.body_len = len(data) - - if len(data) > 8: - self.additional_data = data[8:].tobytes() - - -class WindowUpdateFrame(Frame): - """ - The WINDOW_UPDATE frame is used to implement flow control. - - Flow control operates at two levels: on each individual stream and on the - entire connection. - - Both types of flow control are hop by hop; that is, only between the two - endpoints. Intermediaries do not forward WINDOW_UPDATE frames between - dependent connections. However, throttling of data transfer by any receiver - can indirectly cause the propagation of flow control information toward the - original sender. - """ - #: The flags defined for WINDOW_UPDATE frames. - defined_flags = [] - - #: The type byte defined for WINDOW_UPDATE frames. - type = 0x08 - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, stream_id, window_increment=0, **kwargs): - super(WindowUpdateFrame, self).__init__(stream_id, **kwargs) - - #: The amount the flow control window is to be incremented. - self.window_increment = window_increment - - def serialize_body(self): - return _STRUCT_L.pack(self.window_increment & 0x7FFFFFFF) - - def parse_body(self, data): - try: - self.window_increment = _STRUCT_L.unpack(data)[0] - except struct.error: - raise InvalidFrameError("Invalid WINDOW_UPDATE body") - - self.body_len = 4 - - -class HeadersFrame(Padding, Priority, Frame): - """ - The HEADERS frame carries name-value pairs. It is used to open a stream. - HEADERS frames can be sent on a stream in the "open" or "half closed - (remote)" states. - - The HeadersFrame class is actually basically a data frame in this - implementation, because of the requirement to control the sizes of frames. - A header block fragment that doesn't fit in an entire HEADERS frame needs - to be followed with CONTINUATION frames. From the perspective of the frame - building code the header block is an opaque data segment. - """ - #: The flags defined for HEADERS frames. - defined_flags = [ - Flag('END_STREAM', 0x01), - Flag('END_HEADERS', 0x04), - Flag('PADDED', 0x08), - Flag('PRIORITY', 0x20), - ] - - #: The type byte defined for HEADERS frames. - type = 0x01 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id, data=b'', **kwargs): - super(HeadersFrame, self).__init__(stream_id, **kwargs) - - #: The HPACK-encoded header block. - self.data = data - - def serialize_body(self): - padding_data = self.serialize_padding_data() - padding = b'\0' * self.total_padding - - if 'PRIORITY' in self.flags: - priority_data = self.serialize_priority_data() - else: - priority_data = b'' - - return b''.join([padding_data, priority_data, self.data, padding]) - - def parse_body(self, data): - padding_data_length = self.parse_padding_data(data) - data = data[padding_data_length:] - - if 'PRIORITY' in self.flags: - priority_data_length = self.parse_priority_data(data) - else: - priority_data_length = 0 - - self.body_len = len(data) - self.data = ( - data[priority_data_length:len(data)-self.total_padding].tobytes() - ) - - if self.total_padding and self.total_padding >= self.body_len: - raise InvalidPaddingError("Padding is too long.") - - -class ContinuationFrame(Frame): - """ - The CONTINUATION frame is used to continue a sequence of header block - fragments. Any number of CONTINUATION frames can be sent on an existing - stream, as long as the preceding frame on the same stream is one of - HEADERS, PUSH_PROMISE or CONTINUATION without the END_HEADERS flag set. - - Much like the HEADERS frame, hyper treats this as an opaque data frame with - different flags and a different type. - """ - #: The flags defined for CONTINUATION frames. - defined_flags = [Flag('END_HEADERS', 0x04)] - - #: The type byte defined for CONTINUATION frames. - type = 0x09 - - stream_association = _STREAM_ASSOC_HAS_STREAM - - def __init__(self, stream_id, data=b'', **kwargs): - super(ContinuationFrame, self).__init__(stream_id, **kwargs) - - #: The HPACK-encoded header block. - self.data = data - - def serialize_body(self): - return self.data - - def parse_body(self, data): - self.data = data.tobytes() - self.body_len = len(data) - - -class AltSvcFrame(Frame): - """ - The ALTSVC frame is used to advertise alternate services that the current - host, or a different one, can understand. This frame is standardised as - part of RFC 7838. - - This frame does no work to validate that the ALTSVC field parameter is - acceptable per the rules of RFC 7838. - - .. note:: If the ``stream_id`` of this frame is nonzero, the origin field - must have zero length. Conversely, if the ``stream_id`` of this - frame is zero, the origin field must have nonzero length. Put - another way, a valid ALTSVC frame has ``stream_id != 0`` XOR - ``len(origin) != 0``. - """ - type = 0xA - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, stream_id, origin=b'', field=b'', **kwargs): - super(AltSvcFrame, self).__init__(stream_id, **kwargs) - - if not isinstance(origin, bytes): - raise ValueError("AltSvc origin must be bytestring.") - if not isinstance(field, bytes): - raise ValueError("AltSvc field must be a bytestring.") - self.origin = origin - self.field = field - - def serialize_body(self): - origin_len = _STRUCT_H.pack(len(self.origin)) - return b''.join([origin_len, self.origin, self.field]) - - def parse_body(self, data): - try: - origin_len = _STRUCT_H.unpack(data[0:2])[0] - self.origin = data[2:2+origin_len].tobytes() - - if len(self.origin) != origin_len: - raise InvalidFrameError("Invalid ALTSVC frame body.") - - self.field = data[2+origin_len:].tobytes() - except (struct.error, ValueError): - raise InvalidFrameError("Invalid ALTSVC frame body.") - - self.body_len = len(data) - - -class ExtensionFrame(Frame): - """ - ExtensionFrame is used to wrap frames which are not natively interpretable - by hyperframe. - - Although certain byte prefixes are ordained by specification to have - certain contextual meanings, frames with other prefixes are not prohibited, - and may be used to communicate arbitrary meaning between HTTP/2 peers. - - Thus, hyperframe, rather than raising an exception when such a frame is - encountered, wraps it in a generic frame to be properly acted upon by - upstream consumers which might have additional context on how to use it. - - .. versionadded:: 5.0.0 - """ - - stream_association = _STREAM_ASSOC_EITHER - - def __init__(self, type, stream_id, **kwargs): - super(ExtensionFrame, self).__init__(stream_id, **kwargs) - self.type = type - self.flag_byte = None - - def parse_flags(self, flag_byte): - """ - For extension frames, we parse the flags by just storing a flag byte. - """ - self.flag_byte = flag_byte - - def parse_body(self, data): - self.body = data.tobytes() - self.body_len = len(data) - - def serialize(self): - """ - A broad override of the serialize method that ensures that the data - comes back out exactly as it came in. This should not be used in most - user code: it exists only as a helper method if frames need to be - reconstituted. - """ - # Build the frame header. - # First, get the flags. - flags = self.flag_byte - - header = _STRUCT_HBBBL.pack( - (self.body_len >> 8) & 0xFFFF, # Length spread over top 24 bits - self.body_len & 0xFF, - self.type, - flags, - self.stream_id & 0x7FFFFFFF # Stream ID is 32 bits. - ) - - return header + self.body - - -_FRAME_CLASSES = [ - DataFrame, - HeadersFrame, - PriorityFrame, - RstStreamFrame, - SettingsFrame, - PushPromiseFrame, - PingFrame, - GoAwayFrame, - WindowUpdateFrame, - ContinuationFrame, - AltSvcFrame, -] -#: FRAMES maps the type byte for each frame to the class used to represent that -#: frame. -FRAMES = {cls.type: cls for cls in _FRAME_CLASSES} diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/INSTALLER b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/LICENSE.rst b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/LICENSE.rst deleted file mode 100644 index ef9c194..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/LICENSE.rst +++ /dev/null @@ -1,47 +0,0 @@ -`BSD 3-Clause `_ - -Copyright © 2011 by the Pallets team. - -Some rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -- Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -We kindly ask you to use these themes in an unmodified manner only with -Pallets and Pallets-related projects, not for unrelated projects. If you -like the visual style and want to use it for your own projects, please -consider making some larger changes to the themes (such as changing font -faces, sizes, colors or margins). - -THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ----- - -The initial implementation of itsdangerous was inspired by Django's -signing module. - -Copyright © Django Software Foundation and individual contributors. -All rights reserved. diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/METADATA b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/METADATA deleted file mode 100644 index 7389a4d..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/METADATA +++ /dev/null @@ -1,98 +0,0 @@ -Metadata-Version: 2.1 -Name: itsdangerous -Version: 1.1.0 -Summary: Various helpers to pass data to untrusted environments and back. -Home-page: https://palletsprojects.com/p/itsdangerous/ -Author: Armin Ronacher -Author-email: armin.ronacher@active-4.com -Maintainer: Pallets Team -Maintainer-email: contact@palletsprojects.com -License: BSD -Project-URL: Documentation, https://itsdangerous.palletsprojects.com/ -Project-URL: Code, https://github.com/pallets/itsdangerous -Project-URL: Issue tracker, https://github.com/pallets/itsdangerous/issues -Platform: UNKNOWN -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* - -itsdangerous -============ - -... so better sign this - -Various helpers to pass data to untrusted environments and to get it -back safe and sound. Data is cryptographically signed to ensure that a -token has not been tampered with. - -It's possible to customize how data is serialized. Data is compressed as -needed. A timestamp can be added and verified automatically while -loading a token. - - -Installing ----------- - -Install and update using `pip`_: - -.. code-block:: text - - pip install -U itsdangerous - -.. _pip: https://pip.pypa.io/en/stable/quickstart/ - - -A Simple Example ----------------- - -Here's how you could generate a token for transmitting a user's id and -name between web requests. - -.. code-block:: python - - from itsdangerous import URLSafeSerializer - auth_s = URLSafeSerializer("secret key", "auth") - token = auth_s.dumps({"id": 5, "name": "itsdangerous"}) - - print(token) - # eyJpZCI6NSwibmFtZSI6Iml0c2Rhbmdlcm91cyJ9.6YP6T0BaO67XP--9UzTrmurXSmg - - data = auth_s.loads(token) - print(data["name"]) - # itsdangerous - - -Donate ------- - -The Pallets organization develops and supports itsdangerous and other -popular packages. In order to grow the community of contributors and -users, and allow the maintainers to devote more time to the projects, -`please donate today`_. - -.. _please donate today: https://palletsprojects.com/donate - - -Links ------ - -* Website: https://palletsprojects.com/p/itsdangerous/ -* Documentation: https://itsdangerous.palletsprojects.com/ -* License: `BSD `_ -* Releases: https://pypi.org/project/itsdangerous/ -* Code: https://github.com/pallets/itsdangerous -* Issue tracker: https://github.com/pallets/itsdangerous/issues -* Test status: https://travis-ci.org/pallets/itsdangerous -* Test coverage: https://codecov.io/gh/pallets/itsdangerous - - diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/RECORD b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/RECORD deleted file mode 100644 index e873cf9..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/RECORD +++ /dev/null @@ -1,26 +0,0 @@ -itsdangerous/__init__.py,sha256=Dr-SkfFdOyiR_WjiqIXnlFpYRMW0XvPBNV5muzE5N_A,708 -itsdangerous/_compat.py,sha256=oAAMcQAjwQXQpIbuHT3o-aL56ztm_7Fe-4lD7IteF6A,1133 -itsdangerous/_json.py,sha256=W7BLL4RPnSOjNdo2gfKT3BeARMCIikY6O75rwWV0XoE,431 -itsdangerous/encoding.py,sha256=KhY85PsH3bGHe5JANN4LMZ_3b0IwUWRRnnw1wvLlaIg,1224 -itsdangerous/exc.py,sha256=KFxg7K2XMliMQAxL4jkRNgE8e73z2jcRaLrzwqVObnI,2959 -itsdangerous/jws.py,sha256=6Lh9W-Lu8D9s7bRazs0Zb35eyAZm3pzLeZqHmRELeII,7470 -itsdangerous/serializer.py,sha256=bT-dfjKec9zcKa8Qo8n7mHW_8M-XCTPMOFq1TQI_Fv4,8653 -itsdangerous/signer.py,sha256=OOZbK8XomBjQfOFEul8osesn7fc80MXB0L1r7E86_GQ,6345 -itsdangerous/timed.py,sha256=on5Q5lX7LT_LaETOhzF1ZmrRbia8P98263R8FiRyM6Y,5635 -itsdangerous/url_safe.py,sha256=xnFTaukIPmW6Qwn6uNQLgzdau8RuAKnp5N7ukuXykj0,2275 -itsdangerous-1.1.0.dist-info/LICENSE.rst,sha256=_rKL-jSNgWsOfbrt3xhJnufoAHxngT241qs3xl4EbNQ,2120 -itsdangerous-1.1.0.dist-info/METADATA,sha256=yyKjL2WOg_WybH2Yt-7NIvGpV3B93IsMc2HbToWc7Sk,3062 -itsdangerous-1.1.0.dist-info/WHEEL,sha256=CihQvCnsGZQBGAHLEUMf0IdA4fRduS_NBUTMgCTtvPM,110 -itsdangerous-1.1.0.dist-info/top_level.txt,sha256=gKN1OKLk81i7fbWWildJA88EQ9NhnGMSvZqhfz9ICjk,13 -itsdangerous-1.1.0.dist-info/RECORD,, -itsdangerous-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -itsdangerous/__pycache__/jws.cpython-37.pyc,, -itsdangerous/__pycache__/__init__.cpython-37.pyc,, -itsdangerous/__pycache__/url_safe.cpython-37.pyc,, -itsdangerous/__pycache__/serializer.cpython-37.pyc,, -itsdangerous/__pycache__/signer.cpython-37.pyc,, -itsdangerous/__pycache__/timed.cpython-37.pyc,, -itsdangerous/__pycache__/_json.cpython-37.pyc,, -itsdangerous/__pycache__/_compat.cpython-37.pyc,, -itsdangerous/__pycache__/encoding.cpython-37.pyc,, -itsdangerous/__pycache__/exc.cpython-37.pyc,, diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/WHEEL b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/WHEEL deleted file mode 100644 index dea0e20..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.32.2) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/top_level.txt b/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/top_level.txt deleted file mode 100644 index e163955..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous-1.1.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -itsdangerous diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/__init__.py b/py3.7/lib/python3.7/site-packages/itsdangerous/__init__.py deleted file mode 100644 index 0fcd8c1..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from ._json import json -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import want_bytes -from .exc import BadData -from .exc import BadHeader -from .exc import BadPayload -from .exc import BadSignature -from .exc import BadTimeSignature -from .exc import SignatureExpired -from .jws import JSONWebSignatureSerializer -from .jws import TimedJSONWebSignatureSerializer -from .serializer import Serializer -from .signer import HMACAlgorithm -from .signer import NoneAlgorithm -from .signer import Signer -from .timed import TimedSerializer -from .timed import TimestampSigner -from .url_safe import URLSafeSerializer -from .url_safe import URLSafeTimedSerializer - -__version__ = "1.1.0" diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/_compat.py b/py3.7/lib/python3.7/site-packages/itsdangerous/_compat.py deleted file mode 100644 index 2291bce..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/_compat.py +++ /dev/null @@ -1,46 +0,0 @@ -import decimal -import hmac -import numbers -import sys - -PY2 = sys.version_info[0] == 2 - -if PY2: - from itertools import izip - - text_type = unicode # noqa: 821 -else: - izip = zip - text_type = str - -number_types = (numbers.Real, decimal.Decimal) - - -def _constant_time_compare(val1, val2): - """Return ``True`` if the two strings are equal, ``False`` - otherwise. - - The time taken is independent of the number of characters that - match. Do not use this function for anything else than comparision - with known length targets. - - This is should be implemented in C in order to get it completely - right. - - This is an alias of :func:`hmac.compare_digest` on Python>=2.7,3.3. - """ - len_eq = len(val1) == len(val2) - if len_eq: - result = 0 - left = val1 - else: - result = 1 - left = val2 - for x, y in izip(bytearray(left), bytearray(val2)): - result |= x ^ y - return result == 0 - - -# Starting with 2.7/3.3 the standard library has a c-implementation for -# constant time string compares. -constant_time_compare = getattr(hmac, "compare_digest", _constant_time_compare) diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/_json.py b/py3.7/lib/python3.7/site-packages/itsdangerous/_json.py deleted file mode 100644 index 426b36e..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/_json.py +++ /dev/null @@ -1,18 +0,0 @@ -try: - import simplejson as json -except ImportError: - import json - - -class _CompactJSON(object): - """Wrapper around json module that strips whitespace.""" - - @staticmethod - def loads(payload): - return json.loads(payload) - - @staticmethod - def dumps(obj, **kwargs): - kwargs.setdefault("ensure_ascii", False) - kwargs.setdefault("separators", (",", ":")) - return json.dumps(obj, **kwargs) diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/encoding.py b/py3.7/lib/python3.7/site-packages/itsdangerous/encoding.py deleted file mode 100644 index 1e28969..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/encoding.py +++ /dev/null @@ -1,49 +0,0 @@ -import base64 -import string -import struct - -from ._compat import text_type -from .exc import BadData - - -def want_bytes(s, encoding="utf-8", errors="strict"): - if isinstance(s, text_type): - s = s.encode(encoding, errors) - return s - - -def base64_encode(string): - """Base64 encode a string of bytes or text. The resulting bytes are - safe to use in URLs. - """ - string = want_bytes(string) - return base64.urlsafe_b64encode(string).rstrip(b"=") - - -def base64_decode(string): - """Base64 decode a URL-safe string of bytes or text. The result is - bytes. - """ - string = want_bytes(string, encoding="ascii", errors="ignore") - string += b"=" * (-len(string) % 4) - - try: - return base64.urlsafe_b64decode(string) - except (TypeError, ValueError): - raise BadData("Invalid base64-encoded data") - - -# The alphabet used by base64.urlsafe_* -_base64_alphabet = (string.ascii_letters + string.digits + "-_=").encode("ascii") - -_int64_struct = struct.Struct(">Q") -_int_to_bytes = _int64_struct.pack -_bytes_to_int = _int64_struct.unpack - - -def int_to_bytes(num): - return _int_to_bytes(num).lstrip(b"\x00") - - -def bytes_to_int(bytestr): - return _bytes_to_int(bytestr.rjust(8, b"\x00"))[0] diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/exc.py b/py3.7/lib/python3.7/site-packages/itsdangerous/exc.py deleted file mode 100644 index 287d691..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/exc.py +++ /dev/null @@ -1,98 +0,0 @@ -from ._compat import PY2 -from ._compat import text_type - - -class BadData(Exception): - """Raised if bad data of any sort was encountered. This is the base - for all exceptions that itsdangerous defines. - - .. versionadded:: 0.15 - """ - - message = None - - def __init__(self, message): - super(BadData, self).__init__(self, message) - self.message = message - - def __str__(self): - return text_type(self.message) - - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.__unicode__().encode("utf-8") - - -class BadSignature(BadData): - """Raised if a signature does not match.""" - - def __init__(self, message, payload=None): - BadData.__init__(self, message) - - #: The payload that failed the signature test. In some - #: situations you might still want to inspect this, even if - #: you know it was tampered with. - #: - #: .. versionadded:: 0.14 - self.payload = payload - - -class BadTimeSignature(BadSignature): - """Raised if a time-based signature is invalid. This is a subclass - of :class:`BadSignature`. - """ - - def __init__(self, message, payload=None, date_signed=None): - BadSignature.__init__(self, message, payload) - - #: If the signature expired this exposes the date of when the - #: signature was created. This can be helpful in order to - #: tell the user how long a link has been gone stale. - #: - #: .. versionadded:: 0.14 - self.date_signed = date_signed - - -class SignatureExpired(BadTimeSignature): - """Raised if a signature timestamp is older than ``max_age``. This - is a subclass of :exc:`BadTimeSignature`. - """ - - -class BadHeader(BadSignature): - """Raised if a signed header is invalid in some form. This only - happens for serializers that have a header that goes with the - signature. - - .. versionadded:: 0.24 - """ - - def __init__(self, message, payload=None, header=None, original_error=None): - BadSignature.__init__(self, message, payload) - - #: If the header is actually available but just malformed it - #: might be stored here. - self.header = header - - #: If available, the error that indicates why the payload was - #: not valid. This might be ``None``. - self.original_error = original_error - - -class BadPayload(BadData): - """Raised if a payload is invalid. This could happen if the payload - is loaded despite an invalid signature, or if there is a mismatch - between the serializer and deserializer. The original exception - that occurred during loading is stored on as :attr:`original_error`. - - .. versionadded:: 0.15 - """ - - def __init__(self, message, original_error=None): - BadData.__init__(self, message) - - #: If available, the error that indicates why the payload was - #: not valid. This might be ``None``. - self.original_error = original_error diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/jws.py b/py3.7/lib/python3.7/site-packages/itsdangerous/jws.py deleted file mode 100644 index 92e9ec8..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/jws.py +++ /dev/null @@ -1,218 +0,0 @@ -import hashlib -import time -from datetime import datetime - -from ._compat import number_types -from ._json import _CompactJSON -from ._json import json -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import want_bytes -from .exc import BadData -from .exc import BadHeader -from .exc import BadPayload -from .exc import BadSignature -from .exc import SignatureExpired -from .serializer import Serializer -from .signer import HMACAlgorithm -from .signer import NoneAlgorithm - - -class JSONWebSignatureSerializer(Serializer): - """This serializer implements JSON Web Signature (JWS) support. Only - supports the JWS Compact Serialization. - """ - - jws_algorithms = { - "HS256": HMACAlgorithm(hashlib.sha256), - "HS384": HMACAlgorithm(hashlib.sha384), - "HS512": HMACAlgorithm(hashlib.sha512), - "none": NoneAlgorithm(), - } - - #: The default algorithm to use for signature generation - default_algorithm = "HS512" - - default_serializer = _CompactJSON - - def __init__( - self, - secret_key, - salt=None, - serializer=None, - serializer_kwargs=None, - signer=None, - signer_kwargs=None, - algorithm_name=None, - ): - Serializer.__init__( - self, - secret_key=secret_key, - salt=salt, - serializer=serializer, - serializer_kwargs=serializer_kwargs, - signer=signer, - signer_kwargs=signer_kwargs, - ) - if algorithm_name is None: - algorithm_name = self.default_algorithm - self.algorithm_name = algorithm_name - self.algorithm = self.make_algorithm(algorithm_name) - - def load_payload(self, payload, serializer=None, return_header=False): - payload = want_bytes(payload) - if b"." not in payload: - raise BadPayload('No "." found in value') - base64d_header, base64d_payload = payload.split(b".", 1) - try: - json_header = base64_decode(base64d_header) - except Exception as e: - raise BadHeader( - "Could not base64 decode the header because of an exception", - original_error=e, - ) - try: - json_payload = base64_decode(base64d_payload) - except Exception as e: - raise BadPayload( - "Could not base64 decode the payload because of an exception", - original_error=e, - ) - try: - header = Serializer.load_payload(self, json_header, serializer=json) - except BadData as e: - raise BadHeader( - "Could not unserialize header because it was malformed", - original_error=e, - ) - if not isinstance(header, dict): - raise BadHeader("Header payload is not a JSON object", header=header) - payload = Serializer.load_payload(self, json_payload, serializer=serializer) - if return_header: - return payload, header - return payload - - def dump_payload(self, header, obj): - base64d_header = base64_encode( - self.serializer.dumps(header, **self.serializer_kwargs) - ) - base64d_payload = base64_encode( - self.serializer.dumps(obj, **self.serializer_kwargs) - ) - return base64d_header + b"." + base64d_payload - - def make_algorithm(self, algorithm_name): - try: - return self.jws_algorithms[algorithm_name] - except KeyError: - raise NotImplementedError("Algorithm not supported") - - def make_signer(self, salt=None, algorithm=None): - if salt is None: - salt = self.salt - key_derivation = "none" if salt is None else None - if algorithm is None: - algorithm = self.algorithm - return self.signer( - self.secret_key, - salt=salt, - sep=".", - key_derivation=key_derivation, - algorithm=algorithm, - ) - - def make_header(self, header_fields): - header = header_fields.copy() if header_fields else {} - header["alg"] = self.algorithm_name - return header - - def dumps(self, obj, salt=None, header_fields=None): - """Like :meth:`.Serializer.dumps` but creates a JSON Web - Signature. It also allows for specifying additional fields to be - included in the JWS header. - """ - header = self.make_header(header_fields) - signer = self.make_signer(salt, self.algorithm) - return signer.sign(self.dump_payload(header, obj)) - - def loads(self, s, salt=None, return_header=False): - """Reverse of :meth:`dumps`. If requested via ``return_header`` - it will return a tuple of payload and header. - """ - payload, header = self.load_payload( - self.make_signer(salt, self.algorithm).unsign(want_bytes(s)), - return_header=True, - ) - if header.get("alg") != self.algorithm_name: - raise BadHeader("Algorithm mismatch", header=header, payload=payload) - if return_header: - return payload, header - return payload - - def loads_unsafe(self, s, salt=None, return_header=False): - kwargs = {"return_header": return_header} - return self._loads_unsafe_impl(s, salt, kwargs, kwargs) - - -class TimedJSONWebSignatureSerializer(JSONWebSignatureSerializer): - """Works like the regular :class:`JSONWebSignatureSerializer` but - also records the time of the signing and can be used to expire - signatures. - - JWS currently does not specify this behavior but it mentions a - possible extension like this in the spec. Expiry date is encoded - into the header similar to what's specified in `draft-ietf-oauth - -json-web-token `_. - """ - - DEFAULT_EXPIRES_IN = 3600 - - def __init__(self, secret_key, expires_in=None, **kwargs): - JSONWebSignatureSerializer.__init__(self, secret_key, **kwargs) - if expires_in is None: - expires_in = self.DEFAULT_EXPIRES_IN - self.expires_in = expires_in - - def make_header(self, header_fields): - header = JSONWebSignatureSerializer.make_header(self, header_fields) - iat = self.now() - exp = iat + self.expires_in - header["iat"] = iat - header["exp"] = exp - return header - - def loads(self, s, salt=None, return_header=False): - payload, header = JSONWebSignatureSerializer.loads( - self, s, salt, return_header=True - ) - - if "exp" not in header: - raise BadSignature("Missing expiry date", payload=payload) - - int_date_error = BadHeader("Expiry date is not an IntDate", payload=payload) - try: - header["exp"] = int(header["exp"]) - except ValueError: - raise int_date_error - if header["exp"] < 0: - raise int_date_error - - if header["exp"] < self.now(): - raise SignatureExpired( - "Signature expired", - payload=payload, - date_signed=self.get_issue_date(header), - ) - - if return_header: - return payload, header - return payload - - def get_issue_date(self, header): - rv = header.get("iat") - if isinstance(rv, number_types): - return datetime.utcfromtimestamp(int(rv)) - - def now(self): - return int(time.time()) diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/serializer.py b/py3.7/lib/python3.7/site-packages/itsdangerous/serializer.py deleted file mode 100644 index 12c20f4..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/serializer.py +++ /dev/null @@ -1,233 +0,0 @@ -import hashlib - -from ._compat import text_type -from ._json import json -from .encoding import want_bytes -from .exc import BadPayload -from .exc import BadSignature -from .signer import Signer - - -def is_text_serializer(serializer): - """Checks whether a serializer generates text or binary.""" - return isinstance(serializer.dumps({}), text_type) - - -class Serializer(object): - """This class provides a serialization interface on top of the - signer. It provides a similar API to json/pickle and other modules - but is structured differently internally. If you want to change the - underlying implementation for parsing and loading you have to - override the :meth:`load_payload` and :meth:`dump_payload` - functions. - - This implementation uses simplejson if available for dumping and - loading and will fall back to the standard library's json module if - it's not available. - - You do not need to subclass this class in order to switch out or - customize the :class:`.Signer`. You can instead pass a different - class to the constructor as well as keyword arguments as a dict that - should be forwarded. - - .. code-block:: python - - s = Serializer(signer_kwargs={'key_derivation': 'hmac'}) - - You may want to upgrade the signing parameters without invalidating - existing signatures that are in use. Fallback signatures can be - given that will be tried if unsigning with the current signer fails. - - Fallback signers can be defined by providing a list of - ``fallback_signers``. Each item can be one of the following: a - signer class (which is instantiated with ``signer_kwargs``, - ``salt``, and ``secret_key``), a tuple - ``(signer_class, signer_kwargs)``, or a dict of ``signer_kwargs``. - - For example, this is a serializer that signs using SHA-512, but will - unsign using either SHA-512 or SHA1: - - .. code-block:: python - - s = Serializer( - signer_kwargs={"digest_method": hashlib.sha512}, - fallback_signers=[{"digest_method": hashlib.sha1}] - ) - - .. versionchanged:: 0.14: - The ``signer`` and ``signer_kwargs`` parameters were added to - the constructor. - - .. versionchanged:: 1.1.0: - Added support for ``fallback_signers`` and configured a default - SHA-512 fallback. This fallback is for users who used the yanked - 1.0.0 release which defaulted to SHA-512. - """ - - #: If a serializer module or class is not passed to the constructor - #: this one is picked up. This currently defaults to :mod:`json`. - default_serializer = json - - #: The default :class:`Signer` class that is being used by this - #: serializer. - #: - #: .. versionadded:: 0.14 - default_signer = Signer - - #: The default fallback signers. - default_fallback_signers = [{"digest_method": hashlib.sha512}] - - def __init__( - self, - secret_key, - salt=b"itsdangerous", - serializer=None, - serializer_kwargs=None, - signer=None, - signer_kwargs=None, - fallback_signers=None, - ): - self.secret_key = want_bytes(secret_key) - self.salt = want_bytes(salt) - if serializer is None: - serializer = self.default_serializer - self.serializer = serializer - self.is_text_serializer = is_text_serializer(serializer) - if signer is None: - signer = self.default_signer - self.signer = signer - self.signer_kwargs = signer_kwargs or {} - if fallback_signers is None: - fallback_signers = list(self.default_fallback_signers or ()) - self.fallback_signers = fallback_signers - self.serializer_kwargs = serializer_kwargs or {} - - def load_payload(self, payload, serializer=None): - """Loads the encoded object. This function raises - :class:`.BadPayload` if the payload is not valid. The - ``serializer`` parameter can be used to override the serializer - stored on the class. The encoded ``payload`` should always be - bytes. - """ - if serializer is None: - serializer = self.serializer - is_text = self.is_text_serializer - else: - is_text = is_text_serializer(serializer) - try: - if is_text: - payload = payload.decode("utf-8") - return serializer.loads(payload) - except Exception as e: - raise BadPayload( - "Could not load the payload because an exception" - " occurred on unserializing the data.", - original_error=e, - ) - - def dump_payload(self, obj): - """Dumps the encoded object. The return value is always bytes. - If the internal serializer returns text, the value will be - encoded as UTF-8. - """ - return want_bytes(self.serializer.dumps(obj, **self.serializer_kwargs)) - - def make_signer(self, salt=None): - """Creates a new instance of the signer to be used. The default - implementation uses the :class:`.Signer` base class. - """ - if salt is None: - salt = self.salt - return self.signer(self.secret_key, salt=salt, **self.signer_kwargs) - - def iter_unsigners(self, salt=None): - """Iterates over all signers to be tried for unsigning. Starts - with the configured signer, then constructs each signer - specified in ``fallback_signers``. - """ - if salt is None: - salt = self.salt - yield self.make_signer(salt) - for fallback in self.fallback_signers: - if type(fallback) is dict: - kwargs = fallback - fallback = self.signer - elif type(fallback) is tuple: - fallback, kwargs = fallback - else: - kwargs = self.signer_kwargs - yield fallback(self.secret_key, salt=salt, **kwargs) - - def dumps(self, obj, salt=None): - """Returns a signed string serialized with the internal - serializer. The return value can be either a byte or unicode - string depending on the format of the internal serializer. - """ - payload = want_bytes(self.dump_payload(obj)) - rv = self.make_signer(salt).sign(payload) - if self.is_text_serializer: - rv = rv.decode("utf-8") - return rv - - def dump(self, obj, f, salt=None): - """Like :meth:`dumps` but dumps into a file. The file handle has - to be compatible with what the internal serializer expects. - """ - f.write(self.dumps(obj, salt)) - - def loads(self, s, salt=None): - """Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the - signature validation fails. - """ - s = want_bytes(s) - last_exception = None - for signer in self.iter_unsigners(salt): - try: - return self.load_payload(signer.unsign(s)) - except BadSignature as err: - last_exception = err - raise last_exception - - def load(self, f, salt=None): - """Like :meth:`loads` but loads from a file.""" - return self.loads(f.read(), salt) - - def loads_unsafe(self, s, salt=None): - """Like :meth:`loads` but without verifying the signature. This - is potentially very dangerous to use depending on how your - serializer works. The return value is ``(signature_valid, - payload)`` instead of just the payload. The first item will be a - boolean that indicates if the signature is valid. This function - never fails. - - Use it for debugging only and if you know that your serializer - module is not exploitable (for example, do not use it with a - pickle serializer). - - .. versionadded:: 0.15 - """ - return self._loads_unsafe_impl(s, salt) - - def _loads_unsafe_impl(self, s, salt, load_kwargs=None, load_payload_kwargs=None): - """Low level helper function to implement :meth:`loads_unsafe` - in serializer subclasses. - """ - try: - return True, self.loads(s, salt=salt, **(load_kwargs or {})) - except BadSignature as e: - if e.payload is None: - return False, None - try: - return ( - False, - self.load_payload(e.payload, **(load_payload_kwargs or {})), - ) - except BadPayload: - return False, None - - def load_unsafe(self, f, *args, **kwargs): - """Like :meth:`loads_unsafe` but loads from a file. - - .. versionadded:: 0.15 - """ - return self.loads_unsafe(f.read(), *args, **kwargs) diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/signer.py b/py3.7/lib/python3.7/site-packages/itsdangerous/signer.py deleted file mode 100644 index 6bddc03..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/signer.py +++ /dev/null @@ -1,179 +0,0 @@ -import hashlib -import hmac - -from ._compat import constant_time_compare -from .encoding import _base64_alphabet -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import want_bytes -from .exc import BadSignature - - -class SigningAlgorithm(object): - """Subclasses must implement :meth:`get_signature` to provide - signature generation functionality. - """ - - def get_signature(self, key, value): - """Returns the signature for the given key and value.""" - raise NotImplementedError() - - def verify_signature(self, key, value, sig): - """Verifies the given signature matches the expected - signature. - """ - return constant_time_compare(sig, self.get_signature(key, value)) - - -class NoneAlgorithm(SigningAlgorithm): - """Provides an algorithm that does not perform any signing and - returns an empty signature. - """ - - def get_signature(self, key, value): - return b"" - - -class HMACAlgorithm(SigningAlgorithm): - """Provides signature generation using HMACs.""" - - #: The digest method to use with the MAC algorithm. This defaults to - #: SHA1, but can be changed to any other function in the hashlib - #: module. - default_digest_method = staticmethod(hashlib.sha1) - - def __init__(self, digest_method=None): - if digest_method is None: - digest_method = self.default_digest_method - self.digest_method = digest_method - - def get_signature(self, key, value): - mac = hmac.new(key, msg=value, digestmod=self.digest_method) - return mac.digest() - - -class Signer(object): - """This class can sign and unsign bytes, validating the signature - provided. - - Salt can be used to namespace the hash, so that a signed string is - only valid for a given namespace. Leaving this at the default value - or re-using a salt value across different parts of your application - where the same signed value in one part can mean something different - in another part is a security risk. - - See :ref:`the-salt` for an example of what the salt is doing and how - you can utilize it. - - .. versionadded:: 0.14 - ``key_derivation`` and ``digest_method`` were added as arguments - to the class constructor. - - .. versionadded:: 0.18 - ``algorithm`` was added as an argument to the class constructor. - """ - - #: The digest method to use for the signer. This defaults to - #: SHA1 but can be changed to any other function in the hashlib - #: module. - #: - #: .. versionadded:: 0.14 - default_digest_method = staticmethod(hashlib.sha1) - - #: Controls how the key is derived. The default is Django-style - #: concatenation. Possible values are ``concat``, ``django-concat`` - #: and ``hmac``. This is used for deriving a key from the secret key - #: with an added salt. - #: - #: .. versionadded:: 0.14 - default_key_derivation = "django-concat" - - def __init__( - self, - secret_key, - salt=None, - sep=".", - key_derivation=None, - digest_method=None, - algorithm=None, - ): - self.secret_key = want_bytes(secret_key) - self.sep = want_bytes(sep) - if self.sep in _base64_alphabet: - raise ValueError( - "The given separator cannot be used because it may be" - " contained in the signature itself. Alphanumeric" - " characters and `-_=` must not be used." - ) - self.salt = "itsdangerous.Signer" if salt is None else salt - if key_derivation is None: - key_derivation = self.default_key_derivation - self.key_derivation = key_derivation - if digest_method is None: - digest_method = self.default_digest_method - self.digest_method = digest_method - if algorithm is None: - algorithm = HMACAlgorithm(self.digest_method) - self.algorithm = algorithm - - def derive_key(self): - """This method is called to derive the key. The default key - derivation choices can be overridden here. Key derivation is not - intended to be used as a security method to make a complex key - out of a short password. Instead you should use large random - secret keys. - """ - salt = want_bytes(self.salt) - if self.key_derivation == "concat": - return self.digest_method(salt + self.secret_key).digest() - elif self.key_derivation == "django-concat": - return self.digest_method(salt + b"signer" + self.secret_key).digest() - elif self.key_derivation == "hmac": - mac = hmac.new(self.secret_key, digestmod=self.digest_method) - mac.update(salt) - return mac.digest() - elif self.key_derivation == "none": - return self.secret_key - else: - raise TypeError("Unknown key derivation method") - - def get_signature(self, value): - """Returns the signature for the given value.""" - value = want_bytes(value) - key = self.derive_key() - sig = self.algorithm.get_signature(key, value) - return base64_encode(sig) - - def sign(self, value): - """Signs the given string.""" - return want_bytes(value) + want_bytes(self.sep) + self.get_signature(value) - - def verify_signature(self, value, sig): - """Verifies the signature for the given value.""" - key = self.derive_key() - try: - sig = base64_decode(sig) - except Exception: - return False - return self.algorithm.verify_signature(key, value, sig) - - def unsign(self, signed_value): - """Unsigns the given string.""" - signed_value = want_bytes(signed_value) - sep = want_bytes(self.sep) - if sep not in signed_value: - raise BadSignature("No %r found in value" % self.sep) - value, sig = signed_value.rsplit(sep, 1) - if self.verify_signature(value, sig): - return value - raise BadSignature("Signature %r does not match" % sig, payload=value) - - def validate(self, signed_value): - """Only validates the given signed value. Returns ``True`` if - the signature exists and is valid. - """ - try: - self.unsign(signed_value) - return True - except BadSignature: - return False diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/timed.py b/py3.7/lib/python3.7/site-packages/itsdangerous/timed.py deleted file mode 100644 index 4c117e4..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/timed.py +++ /dev/null @@ -1,147 +0,0 @@ -import time -from datetime import datetime - -from ._compat import text_type -from .encoding import base64_decode -from .encoding import base64_encode -from .encoding import bytes_to_int -from .encoding import int_to_bytes -from .encoding import want_bytes -from .exc import BadSignature -from .exc import BadTimeSignature -from .exc import SignatureExpired -from .serializer import Serializer -from .signer import Signer - - -class TimestampSigner(Signer): - """Works like the regular :class:`.Signer` but also records the time - of the signing and can be used to expire signatures. The - :meth:`unsign` method can raise :exc:`.SignatureExpired` if the - unsigning failed because the signature is expired. - """ - - def get_timestamp(self): - """Returns the current timestamp. The function must return an - integer. - """ - return int(time.time()) - - def timestamp_to_datetime(self, ts): - """Used to convert the timestamp from :meth:`get_timestamp` into - a datetime object. - """ - return datetime.utcfromtimestamp(ts) - - def sign(self, value): - """Signs the given string and also attaches time information.""" - value = want_bytes(value) - timestamp = base64_encode(int_to_bytes(self.get_timestamp())) - sep = want_bytes(self.sep) - value = value + sep + timestamp - return value + sep + self.get_signature(value) - - def unsign(self, value, max_age=None, return_timestamp=False): - """Works like the regular :meth:`.Signer.unsign` but can also - validate the time. See the base docstring of the class for - the general behavior. If ``return_timestamp`` is ``True`` the - timestamp of the signature will be returned as a naive - :class:`datetime.datetime` object in UTC. - """ - try: - result = Signer.unsign(self, value) - sig_error = None - except BadSignature as e: - sig_error = e - result = e.payload or b"" - sep = want_bytes(self.sep) - - # If there is no timestamp in the result there is something - # seriously wrong. In case there was a signature error, we raise - # that one directly, otherwise we have a weird situation in - # which we shouldn't have come except someone uses a time-based - # serializer on non-timestamp data, so catch that. - if sep not in result: - if sig_error: - raise sig_error - raise BadTimeSignature("timestamp missing", payload=result) - - value, timestamp = result.rsplit(sep, 1) - try: - timestamp = bytes_to_int(base64_decode(timestamp)) - except Exception: - timestamp = None - - # Signature is *not* okay. Raise a proper error now that we have - # split the value and the timestamp. - if sig_error is not None: - raise BadTimeSignature( - text_type(sig_error), payload=value, date_signed=timestamp - ) - - # Signature was okay but the timestamp is actually not there or - # malformed. Should not happen, but we handle it anyway. - if timestamp is None: - raise BadTimeSignature("Malformed timestamp", payload=value) - - # Check timestamp is not older than max_age - if max_age is not None: - age = self.get_timestamp() - timestamp - if age > max_age: - raise SignatureExpired( - "Signature age %s > %s seconds" % (age, max_age), - payload=value, - date_signed=self.timestamp_to_datetime(timestamp), - ) - - if return_timestamp: - return value, self.timestamp_to_datetime(timestamp) - return value - - def validate(self, signed_value, max_age=None): - """Only validates the given signed value. Returns ``True`` if - the signature exists and is valid.""" - try: - self.unsign(signed_value, max_age=max_age) - return True - except BadSignature: - return False - - -class TimedSerializer(Serializer): - """Uses :class:`TimestampSigner` instead of the default - :class:`.Signer`. - """ - - default_signer = TimestampSigner - - def loads(self, s, max_age=None, return_timestamp=False, salt=None): - """Reverse of :meth:`dumps`, raises :exc:`.BadSignature` if the - signature validation fails. If a ``max_age`` is provided it will - ensure the signature is not older than that time in seconds. In - case the signature is outdated, :exc:`.SignatureExpired` is - raised. All arguments are forwarded to the signer's - :meth:`~TimestampSigner.unsign` method. - """ - s = want_bytes(s) - last_exception = None - for signer in self.iter_unsigners(salt): - try: - base64d, timestamp = signer.unsign(s, max_age, return_timestamp=True) - payload = self.load_payload(base64d) - if return_timestamp: - return payload, timestamp - return payload - # If we get a signature expired it means we could read the - # signature but it's invalid. In that case we do not want to - # try the next signer. - except SignatureExpired: - raise - except BadSignature as err: - last_exception = err - raise last_exception - - def loads_unsafe(self, s, max_age=None, salt=None): - load_kwargs = {"max_age": max_age} - load_payload_kwargs = {} - return self._loads_unsafe_impl(s, salt, load_kwargs, load_payload_kwargs) diff --git a/py3.7/lib/python3.7/site-packages/itsdangerous/url_safe.py b/py3.7/lib/python3.7/site-packages/itsdangerous/url_safe.py deleted file mode 100644 index fcaa011..0000000 --- a/py3.7/lib/python3.7/site-packages/itsdangerous/url_safe.py +++ /dev/null @@ -1,65 +0,0 @@ -import zlib - -from ._json import _CompactJSON -from .encoding import base64_decode -from .encoding import base64_encode -from .exc import BadPayload -from .serializer import Serializer -from .timed import TimedSerializer - - -class URLSafeSerializerMixin(object): - """Mixed in with a regular serializer it will attempt to zlib - compress the string to make it shorter if necessary. It will also - base64 encode the string so that it can safely be placed in a URL. - """ - - default_serializer = _CompactJSON - - def load_payload(self, payload, *args, **kwargs): - decompress = False - if payload.startswith(b"."): - payload = payload[1:] - decompress = True - try: - json = base64_decode(payload) - except Exception as e: - raise BadPayload( - "Could not base64 decode the payload because of an exception", - original_error=e, - ) - if decompress: - try: - json = zlib.decompress(json) - except Exception as e: - raise BadPayload( - "Could not zlib decompress the payload before decoding the payload", - original_error=e, - ) - return super(URLSafeSerializerMixin, self).load_payload(json, *args, **kwargs) - - def dump_payload(self, obj): - json = super(URLSafeSerializerMixin, self).dump_payload(obj) - is_compressed = False - compressed = zlib.compress(json) - if len(compressed) < (len(json) - 1): - json = compressed - is_compressed = True - base64d = base64_encode(json) - if is_compressed: - base64d = b"." + base64d - return base64d - - -class URLSafeSerializer(URLSafeSerializerMixin, Serializer): - """Works like :class:`.Serializer` but dumps and loads into a URL - safe string consisting of the upper and lowercase character of the - alphabet as well as ``'_'``, ``'-'`` and ``'.'``. - """ - - -class URLSafeTimedSerializer(URLSafeSerializerMixin, TimedSerializer): - """Works like :class:`.TimedSerializer` but dumps and loads into a - URL safe string consisting of the upper and lowercase character of - the alphabet as well as ``'_'``, ``'-'`` and ``'.'``. - """ diff --git a/py3.7/lib/python3.7/site-packages/jinja2/__init__.py b/py3.7/lib/python3.7/site-packages/jinja2/__init__.py deleted file mode 100644 index 15e13b6..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/__init__.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2 - ~~~~~~ - - Jinja2 is a template engine written in pure Python. It provides a - Django inspired non-XML syntax but supports inline expressions and - an optional sandboxed environment. - - Nutshell - -------- - - Here a small example of a Jinja2 template:: - - {% extends 'base.html' %} - {% block title %}Memberlist{% endblock %} - {% block content %} - - {% endblock %} - - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -__docformat__ = 'restructuredtext en' -__version__ = '2.10.1' - -# high level interface -from jinja2.environment import Environment, Template - -# loaders -from jinja2.loaders import BaseLoader, FileSystemLoader, PackageLoader, \ - DictLoader, FunctionLoader, PrefixLoader, ChoiceLoader, \ - ModuleLoader - -# bytecode caches -from jinja2.bccache import BytecodeCache, FileSystemBytecodeCache, \ - MemcachedBytecodeCache - -# undefined types -from jinja2.runtime import Undefined, DebugUndefined, StrictUndefined, \ - make_logging_undefined - -# exceptions -from jinja2.exceptions import TemplateError, UndefinedError, \ - TemplateNotFound, TemplatesNotFound, TemplateSyntaxError, \ - TemplateAssertionError, TemplateRuntimeError - -# decorators and public utilities -from jinja2.filters import environmentfilter, contextfilter, \ - evalcontextfilter -from jinja2.utils import Markup, escape, clear_caches, \ - environmentfunction, evalcontextfunction, contextfunction, \ - is_undefined, select_autoescape - -__all__ = [ - 'Environment', 'Template', 'BaseLoader', 'FileSystemLoader', - 'PackageLoader', 'DictLoader', 'FunctionLoader', 'PrefixLoader', - 'ChoiceLoader', 'BytecodeCache', 'FileSystemBytecodeCache', - 'MemcachedBytecodeCache', 'Undefined', 'DebugUndefined', - 'StrictUndefined', 'TemplateError', 'UndefinedError', 'TemplateNotFound', - 'TemplatesNotFound', 'TemplateSyntaxError', 'TemplateAssertionError', - 'TemplateRuntimeError', - 'ModuleLoader', 'environmentfilter', 'contextfilter', 'Markup', 'escape', - 'environmentfunction', 'contextfunction', 'clear_caches', 'is_undefined', - 'evalcontextfilter', 'evalcontextfunction', 'make_logging_undefined', - 'select_autoescape', -] - - -def _patch_async(): - from jinja2.utils import have_async_gen - if have_async_gen: - from jinja2.asyncsupport import patch_all - patch_all() - - -_patch_async() -del _patch_async diff --git a/py3.7/lib/python3.7/site-packages/jinja2/_compat.py b/py3.7/lib/python3.7/site-packages/jinja2/_compat.py deleted file mode 100644 index 61d8530..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/_compat.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2._compat - ~~~~~~~~~~~~~~ - - Some py2/py3 compatibility support based on a stripped down - version of six so we don't have to depend on a specific version - of it. - - :copyright: Copyright 2013 by the Jinja team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" -import sys - -PY2 = sys.version_info[0] == 2 -PYPY = hasattr(sys, 'pypy_translation_info') -_identity = lambda x: x - - -if not PY2: - unichr = chr - range_type = range - text_type = str - string_types = (str,) - integer_types = (int,) - - iterkeys = lambda d: iter(d.keys()) - itervalues = lambda d: iter(d.values()) - iteritems = lambda d: iter(d.items()) - - import pickle - from io import BytesIO, StringIO - NativeStringIO = StringIO - - def reraise(tp, value, tb=None): - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - - ifilter = filter - imap = map - izip = zip - intern = sys.intern - - implements_iterator = _identity - implements_to_string = _identity - encode_filename = _identity - -else: - unichr = unichr - text_type = unicode - range_type = xrange - string_types = (str, unicode) - integer_types = (int, long) - - iterkeys = lambda d: d.iterkeys() - itervalues = lambda d: d.itervalues() - iteritems = lambda d: d.iteritems() - - import cPickle as pickle - from cStringIO import StringIO as BytesIO, StringIO - NativeStringIO = BytesIO - - exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') - - from itertools import imap, izip, ifilter - intern = intern - - def implements_iterator(cls): - cls.next = cls.__next__ - del cls.__next__ - return cls - - def implements_to_string(cls): - cls.__unicode__ = cls.__str__ - cls.__str__ = lambda x: x.__unicode__().encode('utf-8') - return cls - - def encode_filename(filename): - if isinstance(filename, unicode): - return filename.encode('utf-8') - return filename - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a - # dummy metaclass for one level of class instantiation that replaces - # itself with the actual metaclass. - class metaclass(type): - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -try: - from urllib.parse import quote_from_bytes as url_quote -except ImportError: - from urllib import quote as url_quote diff --git a/py3.7/lib/python3.7/site-packages/jinja2/_identifier.py b/py3.7/lib/python3.7/site-packages/jinja2/_identifier.py deleted file mode 100644 index 2eac35d..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/_identifier.py +++ /dev/null @@ -1,2 +0,0 @@ -# generated by scripts/generate_identifier_pattern.py -pattern = '·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯' diff --git a/py3.7/lib/python3.7/site-packages/jinja2/asyncfilters.py b/py3.7/lib/python3.7/site-packages/jinja2/asyncfilters.py deleted file mode 100644 index 5c1f46d..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/asyncfilters.py +++ /dev/null @@ -1,146 +0,0 @@ -from functools import wraps - -from jinja2.asyncsupport import auto_aiter -from jinja2 import filters - - -async def auto_to_seq(value): - seq = [] - if hasattr(value, '__aiter__'): - async for item in value: - seq.append(item) - else: - for item in value: - seq.append(item) - return seq - - -async def async_select_or_reject(args, kwargs, modfunc, lookup_attr): - seq, func = filters.prepare_select_or_reject( - args, kwargs, modfunc, lookup_attr) - if seq: - async for item in auto_aiter(seq): - if func(item): - yield item - - -def dualfilter(normal_filter, async_filter): - wrap_evalctx = False - if getattr(normal_filter, 'environmentfilter', False): - is_async = lambda args: args[0].is_async - wrap_evalctx = False - else: - if not getattr(normal_filter, 'evalcontextfilter', False) and \ - not getattr(normal_filter, 'contextfilter', False): - wrap_evalctx = True - is_async = lambda args: args[0].environment.is_async - - @wraps(normal_filter) - def wrapper(*args, **kwargs): - b = is_async(args) - if wrap_evalctx: - args = args[1:] - if b: - return async_filter(*args, **kwargs) - return normal_filter(*args, **kwargs) - - if wrap_evalctx: - wrapper.evalcontextfilter = True - - wrapper.asyncfiltervariant = True - - return wrapper - - -def asyncfiltervariant(original): - def decorator(f): - return dualfilter(original, f) - return decorator - - -@asyncfiltervariant(filters.do_first) -async def do_first(environment, seq): - try: - return await auto_aiter(seq).__anext__() - except StopAsyncIteration: - return environment.undefined('No first item, sequence was empty.') - - -@asyncfiltervariant(filters.do_groupby) -async def do_groupby(environment, value, attribute): - expr = filters.make_attrgetter(environment, attribute) - return [filters._GroupTuple(key, await auto_to_seq(values)) - for key, values in filters.groupby(sorted( - await auto_to_seq(value), key=expr), expr)] - - -@asyncfiltervariant(filters.do_join) -async def do_join(eval_ctx, value, d=u'', attribute=None): - return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute) - - -@asyncfiltervariant(filters.do_list) -async def do_list(value): - return await auto_to_seq(value) - - -@asyncfiltervariant(filters.do_reject) -async def do_reject(*args, **kwargs): - return async_select_or_reject(args, kwargs, lambda x: not x, False) - - -@asyncfiltervariant(filters.do_rejectattr) -async def do_rejectattr(*args, **kwargs): - return async_select_or_reject(args, kwargs, lambda x: not x, True) - - -@asyncfiltervariant(filters.do_select) -async def do_select(*args, **kwargs): - return async_select_or_reject(args, kwargs, lambda x: x, False) - - -@asyncfiltervariant(filters.do_selectattr) -async def do_selectattr(*args, **kwargs): - return async_select_or_reject(args, kwargs, lambda x: x, True) - - -@asyncfiltervariant(filters.do_map) -async def do_map(*args, **kwargs): - seq, func = filters.prepare_map(args, kwargs) - if seq: - async for item in auto_aiter(seq): - yield func(item) - - -@asyncfiltervariant(filters.do_sum) -async def do_sum(environment, iterable, attribute=None, start=0): - rv = start - if attribute is not None: - func = filters.make_attrgetter(environment, attribute) - else: - func = lambda x: x - async for item in auto_aiter(iterable): - rv += func(item) - return rv - - -@asyncfiltervariant(filters.do_slice) -async def do_slice(value, slices, fill_with=None): - return filters.do_slice(await auto_to_seq(value), slices, fill_with) - - -ASYNC_FILTERS = { - 'first': do_first, - 'groupby': do_groupby, - 'join': do_join, - 'list': do_list, - # we intentionally do not support do_last because that would be - # ridiculous - 'reject': do_reject, - 'rejectattr': do_rejectattr, - 'map': do_map, - 'select': do_select, - 'selectattr': do_selectattr, - 'sum': do_sum, - 'slice': do_slice, -} diff --git a/py3.7/lib/python3.7/site-packages/jinja2/asyncsupport.py b/py3.7/lib/python3.7/site-packages/jinja2/asyncsupport.py deleted file mode 100644 index b1e7b5c..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/asyncsupport.py +++ /dev/null @@ -1,256 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.asyncsupport - ~~~~~~~~~~~~~~~~~~~ - - Has all the code for async support which is implemented as a patch - for supported Python versions. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -import sys -import asyncio -import inspect -from functools import update_wrapper - -from jinja2.utils import concat, internalcode, Markup -from jinja2.environment import TemplateModule -from jinja2.runtime import LoopContextBase, _last_iteration - - -async def concat_async(async_gen): - rv = [] - async def collect(): - async for event in async_gen: - rv.append(event) - await collect() - return concat(rv) - - -async def generate_async(self, *args, **kwargs): - vars = dict(*args, **kwargs) - try: - async for event in self.root_render_func(self.new_context(vars)): - yield event - except Exception: - exc_info = sys.exc_info() - else: - return - yield self.environment.handle_exception(exc_info, True) - - -def wrap_generate_func(original_generate): - def _convert_generator(self, loop, args, kwargs): - async_gen = self.generate_async(*args, **kwargs) - try: - while 1: - yield loop.run_until_complete(async_gen.__anext__()) - except StopAsyncIteration: - pass - def generate(self, *args, **kwargs): - if not self.environment.is_async: - return original_generate(self, *args, **kwargs) - return _convert_generator(self, asyncio.get_event_loop(), args, kwargs) - return update_wrapper(generate, original_generate) - - -async def render_async(self, *args, **kwargs): - if not self.environment.is_async: - raise RuntimeError('The environment was not created with async mode ' - 'enabled.') - - vars = dict(*args, **kwargs) - ctx = self.new_context(vars) - - try: - return await concat_async(self.root_render_func(ctx)) - except Exception: - exc_info = sys.exc_info() - return self.environment.handle_exception(exc_info, True) - - -def wrap_render_func(original_render): - def render(self, *args, **kwargs): - if not self.environment.is_async: - return original_render(self, *args, **kwargs) - loop = asyncio.get_event_loop() - return loop.run_until_complete(self.render_async(*args, **kwargs)) - return update_wrapper(render, original_render) - - -def wrap_block_reference_call(original_call): - @internalcode - async def async_call(self): - rv = await concat_async(self._stack[self._depth](self._context)) - if self._context.eval_ctx.autoescape: - rv = Markup(rv) - return rv - - @internalcode - def __call__(self): - if not self._context.environment.is_async: - return original_call(self) - return async_call(self) - - return update_wrapper(__call__, original_call) - - -def wrap_macro_invoke(original_invoke): - @internalcode - async def async_invoke(self, arguments, autoescape): - rv = await self._func(*arguments) - if autoescape: - rv = Markup(rv) - return rv - - @internalcode - def _invoke(self, arguments, autoescape): - if not self._environment.is_async: - return original_invoke(self, arguments, autoescape) - return async_invoke(self, arguments, autoescape) - return update_wrapper(_invoke, original_invoke) - - -@internalcode -async def get_default_module_async(self): - if self._module is not None: - return self._module - self._module = rv = await self.make_module_async() - return rv - - -def wrap_default_module(original_default_module): - @internalcode - def _get_default_module(self): - if self.environment.is_async: - raise RuntimeError('Template module attribute is unavailable ' - 'in async mode') - return original_default_module(self) - return _get_default_module - - -async def make_module_async(self, vars=None, shared=False, locals=None): - context = self.new_context(vars, shared, locals) - body_stream = [] - async for item in self.root_render_func(context): - body_stream.append(item) - return TemplateModule(self, context, body_stream) - - -def patch_template(): - from jinja2 import Template - Template.generate = wrap_generate_func(Template.generate) - Template.generate_async = update_wrapper( - generate_async, Template.generate_async) - Template.render_async = update_wrapper( - render_async, Template.render_async) - Template.render = wrap_render_func(Template.render) - Template._get_default_module = wrap_default_module( - Template._get_default_module) - Template._get_default_module_async = get_default_module_async - Template.make_module_async = update_wrapper( - make_module_async, Template.make_module_async) - - -def patch_runtime(): - from jinja2.runtime import BlockReference, Macro - BlockReference.__call__ = wrap_block_reference_call( - BlockReference.__call__) - Macro._invoke = wrap_macro_invoke(Macro._invoke) - - -def patch_filters(): - from jinja2.filters import FILTERS - from jinja2.asyncfilters import ASYNC_FILTERS - FILTERS.update(ASYNC_FILTERS) - - -def patch_all(): - patch_template() - patch_runtime() - patch_filters() - - -async def auto_await(value): - if inspect.isawaitable(value): - return await value - return value - - -async def auto_aiter(iterable): - if hasattr(iterable, '__aiter__'): - async for item in iterable: - yield item - return - for item in iterable: - yield item - - -class AsyncLoopContext(LoopContextBase): - - def __init__(self, async_iterator, undefined, after, length, recurse=None, - depth0=0): - LoopContextBase.__init__(self, undefined, recurse, depth0) - self._async_iterator = async_iterator - self._after = after - self._length = length - - @property - def length(self): - if self._length is None: - raise TypeError('Loop length for some iterators cannot be ' - 'lazily calculated in async mode') - return self._length - - def __aiter__(self): - return AsyncLoopContextIterator(self) - - -class AsyncLoopContextIterator(object): - __slots__ = ('context',) - - def __init__(self, context): - self.context = context - - def __aiter__(self): - return self - - async def __anext__(self): - ctx = self.context - ctx.index0 += 1 - if ctx._after is _last_iteration: - raise StopAsyncIteration() - ctx._before = ctx._current - ctx._current = ctx._after - try: - ctx._after = await ctx._async_iterator.__anext__() - except StopAsyncIteration: - ctx._after = _last_iteration - return ctx._current, ctx - - -async def make_async_loop_context(iterable, undefined, recurse=None, depth0=0): - # Length is more complicated and less efficient in async mode. The - # reason for this is that we cannot know if length will be used - # upfront but because length is a property we cannot lazily execute it - # later. This means that we need to buffer it up and measure :( - # - # We however only do this for actual iterators, not for async - # iterators as blocking here does not seem like the best idea in the - # world. - try: - length = len(iterable) - except (TypeError, AttributeError): - if not hasattr(iterable, '__aiter__'): - iterable = tuple(iterable) - length = len(iterable) - else: - length = None - async_iterator = auto_aiter(iterable) - try: - after = await async_iterator.__anext__() - except StopAsyncIteration: - after = _last_iteration - return AsyncLoopContext(async_iterator, undefined, after, length, recurse, - depth0) diff --git a/py3.7/lib/python3.7/site-packages/jinja2/bccache.py b/py3.7/lib/python3.7/site-packages/jinja2/bccache.py deleted file mode 100644 index 080e527..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/bccache.py +++ /dev/null @@ -1,362 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.bccache - ~~~~~~~~~~~~~~ - - This module implements the bytecode cache system Jinja is optionally - using. This is useful if you have very complex template situations and - the compiliation of all those templates slow down your application too - much. - - Situations where this is useful are often forking web applications that - are initialized on the first request. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD. -""" -from os import path, listdir -import os -import sys -import stat -import errno -import marshal -import tempfile -import fnmatch -from hashlib import sha1 -from jinja2.utils import open_if_exists -from jinja2._compat import BytesIO, pickle, PY2, text_type - - -# marshal works better on 3.x, one hack less required -if not PY2: - marshal_dump = marshal.dump - marshal_load = marshal.load -else: - - def marshal_dump(code, f): - if isinstance(f, file): - marshal.dump(code, f) - else: - f.write(marshal.dumps(code)) - - def marshal_load(f): - if isinstance(f, file): - return marshal.load(f) - return marshal.loads(f.read()) - - -bc_version = 3 - -# magic version used to only change with new jinja versions. With 2.6 -# we change this to also take Python version changes into account. The -# reason for this is that Python tends to segfault if fed earlier bytecode -# versions because someone thought it would be a good idea to reuse opcodes -# or make Python incompatible with earlier versions. -bc_magic = 'j2'.encode('ascii') + \ - pickle.dumps(bc_version, 2) + \ - pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1]) - - -class Bucket(object): - """Buckets are used to store the bytecode for one template. It's created - and initialized by the bytecode cache and passed to the loading functions. - - The buckets get an internal checksum from the cache assigned and use this - to automatically reject outdated cache material. Individual bytecode - cache subclasses don't have to care about cache invalidation. - """ - - def __init__(self, environment, key, checksum): - self.environment = environment - self.key = key - self.checksum = checksum - self.reset() - - def reset(self): - """Resets the bucket (unloads the bytecode).""" - self.code = None - - def load_bytecode(self, f): - """Loads bytecode from a file or file like object.""" - # make sure the magic header is correct - magic = f.read(len(bc_magic)) - if magic != bc_magic: - self.reset() - return - # the source code of the file changed, we need to reload - checksum = pickle.load(f) - if self.checksum != checksum: - self.reset() - return - # if marshal_load fails then we need to reload - try: - self.code = marshal_load(f) - except (EOFError, ValueError, TypeError): - self.reset() - return - - def write_bytecode(self, f): - """Dump the bytecode into the file or file like object passed.""" - if self.code is None: - raise TypeError('can\'t write empty bucket') - f.write(bc_magic) - pickle.dump(self.checksum, f, 2) - marshal_dump(self.code, f) - - def bytecode_from_string(self, string): - """Load bytecode from a string.""" - self.load_bytecode(BytesIO(string)) - - def bytecode_to_string(self): - """Return the bytecode as string.""" - out = BytesIO() - self.write_bytecode(out) - return out.getvalue() - - -class BytecodeCache(object): - """To implement your own bytecode cache you have to subclass this class - and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of - these methods are passed a :class:`~jinja2.bccache.Bucket`. - - A very basic bytecode cache that saves the bytecode on the file system:: - - from os import path - - class MyCache(BytecodeCache): - - def __init__(self, directory): - self.directory = directory - - def load_bytecode(self, bucket): - filename = path.join(self.directory, bucket.key) - if path.exists(filename): - with open(filename, 'rb') as f: - bucket.load_bytecode(f) - - def dump_bytecode(self, bucket): - filename = path.join(self.directory, bucket.key) - with open(filename, 'wb') as f: - bucket.write_bytecode(f) - - A more advanced version of a filesystem based bytecode cache is part of - Jinja2. - """ - - def load_bytecode(self, bucket): - """Subclasses have to override this method to load bytecode into a - bucket. If they are not able to find code in the cache for the - bucket, it must not do anything. - """ - raise NotImplementedError() - - def dump_bytecode(self, bucket): - """Subclasses have to override this method to write the bytecode - from a bucket back to the cache. If it unable to do so it must not - fail silently but raise an exception. - """ - raise NotImplementedError() - - def clear(self): - """Clears the cache. This method is not used by Jinja2 but should be - implemented to allow applications to clear the bytecode cache used - by a particular environment. - """ - - def get_cache_key(self, name, filename=None): - """Returns the unique hash key for this template name.""" - hash = sha1(name.encode('utf-8')) - if filename is not None: - filename = '|' + filename - if isinstance(filename, text_type): - filename = filename.encode('utf-8') - hash.update(filename) - return hash.hexdigest() - - def get_source_checksum(self, source): - """Returns a checksum for the source.""" - return sha1(source.encode('utf-8')).hexdigest() - - def get_bucket(self, environment, name, filename, source): - """Return a cache bucket for the given template. All arguments are - mandatory but filename may be `None`. - """ - key = self.get_cache_key(name, filename) - checksum = self.get_source_checksum(source) - bucket = Bucket(environment, key, checksum) - self.load_bytecode(bucket) - return bucket - - def set_bucket(self, bucket): - """Put the bucket into the cache.""" - self.dump_bytecode(bucket) - - -class FileSystemBytecodeCache(BytecodeCache): - """A bytecode cache that stores bytecode on the filesystem. It accepts - two arguments: The directory where the cache items are stored and a - pattern string that is used to build the filename. - - If no directory is specified a default cache directory is selected. On - Windows the user's temp directory is used, on UNIX systems a directory - is created for the user in the system temp directory. - - The pattern can be used to have multiple separate caches operate on the - same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` - is replaced with the cache key. - - >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') - - This bytecode cache supports clearing of the cache using the clear method. - """ - - def __init__(self, directory=None, pattern='__jinja2_%s.cache'): - if directory is None: - directory = self._get_default_cache_dir() - self.directory = directory - self.pattern = pattern - - def _get_default_cache_dir(self): - def _unsafe_dir(): - raise RuntimeError('Cannot determine safe temp directory. You ' - 'need to explicitly provide one.') - - tmpdir = tempfile.gettempdir() - - # On windows the temporary directory is used specific unless - # explicitly forced otherwise. We can just use that. - if os.name == 'nt': - return tmpdir - if not hasattr(os, 'getuid'): - _unsafe_dir() - - dirname = '_jinja2-cache-%d' % os.getuid() - actual_dir = os.path.join(tmpdir, dirname) - - try: - os.mkdir(actual_dir, stat.S_IRWXU) - except OSError as e: - if e.errno != errno.EEXIST: - raise - try: - os.chmod(actual_dir, stat.S_IRWXU) - actual_dir_stat = os.lstat(actual_dir) - if actual_dir_stat.st_uid != os.getuid() \ - or not stat.S_ISDIR(actual_dir_stat.st_mode) \ - or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU: - _unsafe_dir() - except OSError as e: - if e.errno != errno.EEXIST: - raise - - actual_dir_stat = os.lstat(actual_dir) - if actual_dir_stat.st_uid != os.getuid() \ - or not stat.S_ISDIR(actual_dir_stat.st_mode) \ - or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU: - _unsafe_dir() - - return actual_dir - - def _get_cache_filename(self, bucket): - return path.join(self.directory, self.pattern % bucket.key) - - def load_bytecode(self, bucket): - f = open_if_exists(self._get_cache_filename(bucket), 'rb') - if f is not None: - try: - bucket.load_bytecode(f) - finally: - f.close() - - def dump_bytecode(self, bucket): - f = open(self._get_cache_filename(bucket), 'wb') - try: - bucket.write_bytecode(f) - finally: - f.close() - - def clear(self): - # imported lazily here because google app-engine doesn't support - # write access on the file system and the function does not exist - # normally. - from os import remove - files = fnmatch.filter(listdir(self.directory), self.pattern % '*') - for filename in files: - try: - remove(path.join(self.directory, filename)) - except OSError: - pass - - -class MemcachedBytecodeCache(BytecodeCache): - """This class implements a bytecode cache that uses a memcache cache for - storing the information. It does not enforce a specific memcache library - (tummy's memcache or cmemcache) but will accept any class that provides - the minimal interface required. - - Libraries compatible with this class: - - - `werkzeug `_.contrib.cache - - `python-memcached `_ - - `cmemcache `_ - - (Unfortunately the django cache interface is not compatible because it - does not support storing binary data, only unicode. You can however pass - the underlying cache client to the bytecode cache which is available - as `django.core.cache.cache._client`.) - - The minimal interface for the client passed to the constructor is this: - - .. class:: MinimalClientInterface - - .. method:: set(key, value[, timeout]) - - Stores the bytecode in the cache. `value` is a string and - `timeout` the timeout of the key. If timeout is not provided - a default timeout or no timeout should be assumed, if it's - provided it's an integer with the number of seconds the cache - item should exist. - - .. method:: get(key) - - Returns the value for the cache key. If the item does not - exist in the cache the return value must be `None`. - - The other arguments to the constructor are the prefix for all keys that - is added before the actual cache key and the timeout for the bytecode in - the cache system. We recommend a high (or no) timeout. - - This bytecode cache does not support clearing of used items in the cache. - The clear method is a no-operation function. - - .. versionadded:: 2.7 - Added support for ignoring memcache errors through the - `ignore_memcache_errors` parameter. - """ - - def __init__(self, client, prefix='jinja2/bytecode/', timeout=None, - ignore_memcache_errors=True): - self.client = client - self.prefix = prefix - self.timeout = timeout - self.ignore_memcache_errors = ignore_memcache_errors - - def load_bytecode(self, bucket): - try: - code = self.client.get(self.prefix + bucket.key) - except Exception: - if not self.ignore_memcache_errors: - raise - code = None - if code is not None: - bucket.bytecode_from_string(code) - - def dump_bytecode(self, bucket): - args = (self.prefix + bucket.key, bucket.bytecode_to_string()) - if self.timeout is not None: - args += (self.timeout,) - try: - self.client.set(*args) - except Exception: - if not self.ignore_memcache_errors: - raise diff --git a/py3.7/lib/python3.7/site-packages/jinja2/compiler.py b/py3.7/lib/python3.7/site-packages/jinja2/compiler.py deleted file mode 100644 index d534a82..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/compiler.py +++ /dev/null @@ -1,1721 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.compiler - ~~~~~~~~~~~~~~~ - - Compiles nodes into python code. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -from itertools import chain -from copy import deepcopy -from keyword import iskeyword as is_python_keyword -from functools import update_wrapper -from jinja2 import nodes -from jinja2.nodes import EvalContext -from jinja2.visitor import NodeVisitor -from jinja2.optimizer import Optimizer -from jinja2.exceptions import TemplateAssertionError -from jinja2.utils import Markup, concat, escape -from jinja2._compat import range_type, text_type, string_types, \ - iteritems, NativeStringIO, imap, izip -from jinja2.idtracking import Symbols, VAR_LOAD_PARAMETER, \ - VAR_LOAD_RESOLVE, VAR_LOAD_ALIAS, VAR_LOAD_UNDEFINED - - -operators = { - 'eq': '==', - 'ne': '!=', - 'gt': '>', - 'gteq': '>=', - 'lt': '<', - 'lteq': '<=', - 'in': 'in', - 'notin': 'not in' -} - -# what method to iterate over items do we want to use for dict iteration -# in generated code? on 2.x let's go with iteritems, on 3.x with items -if hasattr(dict, 'iteritems'): - dict_item_iter = 'iteritems' -else: - dict_item_iter = 'items' - -code_features = ['division'] - -# does this python version support generator stops? (PEP 0479) -try: - exec('from __future__ import generator_stop') - code_features.append('generator_stop') -except SyntaxError: - pass - -# does this python version support yield from? -try: - exec('def f(): yield from x()') -except SyntaxError: - supports_yield_from = False -else: - supports_yield_from = True - - -def optimizeconst(f): - def new_func(self, node, frame, **kwargs): - # Only optimize if the frame is not volatile - if self.optimized and not frame.eval_ctx.volatile: - new_node = self.optimizer.visit(node, frame.eval_ctx) - if new_node != node: - return self.visit(new_node, frame) - return f(self, node, frame, **kwargs) - return update_wrapper(new_func, f) - - -def generate(node, environment, name, filename, stream=None, - defer_init=False, optimized=True): - """Generate the python source for a node tree.""" - if not isinstance(node, nodes.Template): - raise TypeError('Can\'t compile non template nodes') - generator = environment.code_generator_class(environment, name, filename, - stream, defer_init, - optimized) - generator.visit(node) - if stream is None: - return generator.stream.getvalue() - - -def has_safe_repr(value): - """Does the node have a safe representation?""" - if value is None or value is NotImplemented or value is Ellipsis: - return True - if type(value) in (bool, int, float, complex, range_type, Markup) + string_types: - return True - if type(value) in (tuple, list, set, frozenset): - for item in value: - if not has_safe_repr(item): - return False - return True - elif type(value) is dict: - for key, value in iteritems(value): - if not has_safe_repr(key): - return False - if not has_safe_repr(value): - return False - return True - return False - - -def find_undeclared(nodes, names): - """Check if the names passed are accessed undeclared. The return value - is a set of all the undeclared names from the sequence of names found. - """ - visitor = UndeclaredNameVisitor(names) - try: - for node in nodes: - visitor.visit(node) - except VisitorExit: - pass - return visitor.undeclared - - -class MacroRef(object): - - def __init__(self, node): - self.node = node - self.accesses_caller = False - self.accesses_kwargs = False - self.accesses_varargs = False - - -class Frame(object): - """Holds compile time information for us.""" - - def __init__(self, eval_ctx, parent=None, level=None): - self.eval_ctx = eval_ctx - self.symbols = Symbols(parent and parent.symbols or None, - level=level) - - # a toplevel frame is the root + soft frames such as if conditions. - self.toplevel = False - - # the root frame is basically just the outermost frame, so no if - # conditions. This information is used to optimize inheritance - # situations. - self.rootlevel = False - - # in some dynamic inheritance situations the compiler needs to add - # write tests around output statements. - self.require_output_check = parent and parent.require_output_check - - # inside some tags we are using a buffer rather than yield statements. - # this for example affects {% filter %} or {% macro %}. If a frame - # is buffered this variable points to the name of the list used as - # buffer. - self.buffer = None - - # the name of the block we're in, otherwise None. - self.block = parent and parent.block or None - - # the parent of this frame - self.parent = parent - - if parent is not None: - self.buffer = parent.buffer - - def copy(self): - """Create a copy of the current one.""" - rv = object.__new__(self.__class__) - rv.__dict__.update(self.__dict__) - rv.symbols = self.symbols.copy() - return rv - - def inner(self, isolated=False): - """Return an inner frame.""" - if isolated: - return Frame(self.eval_ctx, level=self.symbols.level + 1) - return Frame(self.eval_ctx, self) - - def soft(self): - """Return a soft frame. A soft frame may not be modified as - standalone thing as it shares the resources with the frame it - was created of, but it's not a rootlevel frame any longer. - - This is only used to implement if-statements. - """ - rv = self.copy() - rv.rootlevel = False - return rv - - __copy__ = copy - - -class VisitorExit(RuntimeError): - """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" - - -class DependencyFinderVisitor(NodeVisitor): - """A visitor that collects filter and test calls.""" - - def __init__(self): - self.filters = set() - self.tests = set() - - def visit_Filter(self, node): - self.generic_visit(node) - self.filters.add(node.name) - - def visit_Test(self, node): - self.generic_visit(node) - self.tests.add(node.name) - - def visit_Block(self, node): - """Stop visiting at blocks.""" - - -class UndeclaredNameVisitor(NodeVisitor): - """A visitor that checks if a name is accessed without being - declared. This is different from the frame visitor as it will - not stop at closure frames. - """ - - def __init__(self, names): - self.names = set(names) - self.undeclared = set() - - def visit_Name(self, node): - if node.ctx == 'load' and node.name in self.names: - self.undeclared.add(node.name) - if self.undeclared == self.names: - raise VisitorExit() - else: - self.names.discard(node.name) - - def visit_Block(self, node): - """Stop visiting a blocks.""" - - -class CompilerExit(Exception): - """Raised if the compiler encountered a situation where it just - doesn't make sense to further process the code. Any block that - raises such an exception is not further processed. - """ - - -class CodeGenerator(NodeVisitor): - - def __init__(self, environment, name, filename, stream=None, - defer_init=False, optimized=True): - if stream is None: - stream = NativeStringIO() - self.environment = environment - self.name = name - self.filename = filename - self.stream = stream - self.created_block_context = False - self.defer_init = defer_init - self.optimized = optimized - if optimized: - self.optimizer = Optimizer(environment) - - # aliases for imports - self.import_aliases = {} - - # a registry for all blocks. Because blocks are moved out - # into the global python scope they are registered here - self.blocks = {} - - # the number of extends statements so far - self.extends_so_far = 0 - - # some templates have a rootlevel extends. In this case we - # can safely assume that we're a child template and do some - # more optimizations. - self.has_known_extends = False - - # the current line number - self.code_lineno = 1 - - # registry of all filters and tests (global, not block local) - self.tests = {} - self.filters = {} - - # the debug information - self.debug_info = [] - self._write_debug_info = None - - # the number of new lines before the next write() - self._new_lines = 0 - - # the line number of the last written statement - self._last_line = 0 - - # true if nothing was written so far. - self._first_write = True - - # used by the `temporary_identifier` method to get new - # unique, temporary identifier - self._last_identifier = 0 - - # the current indentation - self._indentation = 0 - - # Tracks toplevel assignments - self._assign_stack = [] - - # Tracks parameter definition blocks - self._param_def_block = [] - - # Tracks the current context. - self._context_reference_stack = ['context'] - - # -- Various compilation helpers - - def fail(self, msg, lineno): - """Fail with a :exc:`TemplateAssertionError`.""" - raise TemplateAssertionError(msg, lineno, self.name, self.filename) - - def temporary_identifier(self): - """Get a new unique identifier.""" - self._last_identifier += 1 - return 't_%d' % self._last_identifier - - def buffer(self, frame): - """Enable buffering for the frame from that point onwards.""" - frame.buffer = self.temporary_identifier() - self.writeline('%s = []' % frame.buffer) - - def return_buffer_contents(self, frame, force_unescaped=False): - """Return the buffer contents of the frame.""" - if not force_unescaped: - if frame.eval_ctx.volatile: - self.writeline('if context.eval_ctx.autoescape:') - self.indent() - self.writeline('return Markup(concat(%s))' % frame.buffer) - self.outdent() - self.writeline('else:') - self.indent() - self.writeline('return concat(%s)' % frame.buffer) - self.outdent() - return - elif frame.eval_ctx.autoescape: - self.writeline('return Markup(concat(%s))' % frame.buffer) - return - self.writeline('return concat(%s)' % frame.buffer) - - def indent(self): - """Indent by one.""" - self._indentation += 1 - - def outdent(self, step=1): - """Outdent by step.""" - self._indentation -= step - - def start_write(self, frame, node=None): - """Yield or write into the frame buffer.""" - if frame.buffer is None: - self.writeline('yield ', node) - else: - self.writeline('%s.append(' % frame.buffer, node) - - def end_write(self, frame): - """End the writing process started by `start_write`.""" - if frame.buffer is not None: - self.write(')') - - def simple_write(self, s, frame, node=None): - """Simple shortcut for start_write + write + end_write.""" - self.start_write(frame, node) - self.write(s) - self.end_write(frame) - - def blockvisit(self, nodes, frame): - """Visit a list of nodes as block in a frame. If the current frame - is no buffer a dummy ``if 0: yield None`` is written automatically. - """ - try: - self.writeline('pass') - for node in nodes: - self.visit(node, frame) - except CompilerExit: - pass - - def write(self, x): - """Write a string into the output stream.""" - if self._new_lines: - if not self._first_write: - self.stream.write('\n' * self._new_lines) - self.code_lineno += self._new_lines - if self._write_debug_info is not None: - self.debug_info.append((self._write_debug_info, - self.code_lineno)) - self._write_debug_info = None - self._first_write = False - self.stream.write(' ' * self._indentation) - self._new_lines = 0 - self.stream.write(x) - - def writeline(self, x, node=None, extra=0): - """Combination of newline and write.""" - self.newline(node, extra) - self.write(x) - - def newline(self, node=None, extra=0): - """Add one or more newlines before the next write.""" - self._new_lines = max(self._new_lines, 1 + extra) - if node is not None and node.lineno != self._last_line: - self._write_debug_info = node.lineno - self._last_line = node.lineno - - def signature(self, node, frame, extra_kwargs=None): - """Writes a function call to the stream for the current node. - A leading comma is added automatically. The extra keyword - arguments may not include python keywords otherwise a syntax - error could occour. The extra keyword arguments should be given - as python dict. - """ - # if any of the given keyword arguments is a python keyword - # we have to make sure that no invalid call is created. - kwarg_workaround = False - for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()): - if is_python_keyword(kwarg): - kwarg_workaround = True - break - - for arg in node.args: - self.write(', ') - self.visit(arg, frame) - - if not kwarg_workaround: - for kwarg in node.kwargs: - self.write(', ') - self.visit(kwarg, frame) - if extra_kwargs is not None: - for key, value in iteritems(extra_kwargs): - self.write(', %s=%s' % (key, value)) - if node.dyn_args: - self.write(', *') - self.visit(node.dyn_args, frame) - - if kwarg_workaround: - if node.dyn_kwargs is not None: - self.write(', **dict({') - else: - self.write(', **{') - for kwarg in node.kwargs: - self.write('%r: ' % kwarg.key) - self.visit(kwarg.value, frame) - self.write(', ') - if extra_kwargs is not None: - for key, value in iteritems(extra_kwargs): - self.write('%r: %s, ' % (key, value)) - if node.dyn_kwargs is not None: - self.write('}, **') - self.visit(node.dyn_kwargs, frame) - self.write(')') - else: - self.write('}') - - elif node.dyn_kwargs is not None: - self.write(', **') - self.visit(node.dyn_kwargs, frame) - - def pull_dependencies(self, nodes): - """Pull all the dependencies.""" - visitor = DependencyFinderVisitor() - for node in nodes: - visitor.visit(node) - for dependency in 'filters', 'tests': - mapping = getattr(self, dependency) - for name in getattr(visitor, dependency): - if name not in mapping: - mapping[name] = self.temporary_identifier() - self.writeline('%s = environment.%s[%r]' % - (mapping[name], dependency, name)) - - def enter_frame(self, frame): - undefs = [] - for target, (action, param) in iteritems(frame.symbols.loads): - if action == VAR_LOAD_PARAMETER: - pass - elif action == VAR_LOAD_RESOLVE: - self.writeline('%s = %s(%r)' % - (target, self.get_resolve_func(), param)) - elif action == VAR_LOAD_ALIAS: - self.writeline('%s = %s' % (target, param)) - elif action == VAR_LOAD_UNDEFINED: - undefs.append(target) - else: - raise NotImplementedError('unknown load instruction') - if undefs: - self.writeline('%s = missing' % ' = '.join(undefs)) - - def leave_frame(self, frame, with_python_scope=False): - if not with_python_scope: - undefs = [] - for target, _ in iteritems(frame.symbols.loads): - undefs.append(target) - if undefs: - self.writeline('%s = missing' % ' = '.join(undefs)) - - def func(self, name): - if self.environment.is_async: - return 'async def %s' % name - return 'def %s' % name - - def macro_body(self, node, frame): - """Dump the function def of a macro or call block.""" - frame = frame.inner() - frame.symbols.analyze_node(node) - macro_ref = MacroRef(node) - - explicit_caller = None - skip_special_params = set() - args = [] - for idx, arg in enumerate(node.args): - if arg.name == 'caller': - explicit_caller = idx - if arg.name in ('kwargs', 'varargs'): - skip_special_params.add(arg.name) - args.append(frame.symbols.ref(arg.name)) - - undeclared = find_undeclared(node.body, ('caller', 'kwargs', 'varargs')) - - if 'caller' in undeclared: - # In older Jinja2 versions there was a bug that allowed caller - # to retain the special behavior even if it was mentioned in - # the argument list. However thankfully this was only really - # working if it was the last argument. So we are explicitly - # checking this now and error out if it is anywhere else in - # the argument list. - if explicit_caller is not None: - try: - node.defaults[explicit_caller - len(node.args)] - except IndexError: - self.fail('When defining macros or call blocks the ' - 'special "caller" argument must be omitted ' - 'or be given a default.', node.lineno) - else: - args.append(frame.symbols.declare_parameter('caller')) - macro_ref.accesses_caller = True - if 'kwargs' in undeclared and not 'kwargs' in skip_special_params: - args.append(frame.symbols.declare_parameter('kwargs')) - macro_ref.accesses_kwargs = True - if 'varargs' in undeclared and not 'varargs' in skip_special_params: - args.append(frame.symbols.declare_parameter('varargs')) - macro_ref.accesses_varargs = True - - # macros are delayed, they never require output checks - frame.require_output_check = False - frame.symbols.analyze_node(node) - self.writeline('%s(%s):' % (self.func('macro'), ', '.join(args)), node) - self.indent() - - self.buffer(frame) - self.enter_frame(frame) - - self.push_parameter_definitions(frame) - for idx, arg in enumerate(node.args): - ref = frame.symbols.ref(arg.name) - self.writeline('if %s is missing:' % ref) - self.indent() - try: - default = node.defaults[idx - len(node.args)] - except IndexError: - self.writeline('%s = undefined(%r, name=%r)' % ( - ref, - 'parameter %r was not provided' % arg.name, - arg.name)) - else: - self.writeline('%s = ' % ref) - self.visit(default, frame) - self.mark_parameter_stored(ref) - self.outdent() - self.pop_parameter_definitions() - - self.blockvisit(node.body, frame) - self.return_buffer_contents(frame, force_unescaped=True) - self.leave_frame(frame, with_python_scope=True) - self.outdent() - - return frame, macro_ref - - def macro_def(self, macro_ref, frame): - """Dump the macro definition for the def created by macro_body.""" - arg_tuple = ', '.join(repr(x.name) for x in macro_ref.node.args) - name = getattr(macro_ref.node, 'name', None) - if len(macro_ref.node.args) == 1: - arg_tuple += ',' - self.write('Macro(environment, macro, %r, (%s), %r, %r, %r, ' - 'context.eval_ctx.autoescape)' % - (name, arg_tuple, macro_ref.accesses_kwargs, - macro_ref.accesses_varargs, macro_ref.accesses_caller)) - - def position(self, node): - """Return a human readable position for the node.""" - rv = 'line %d' % node.lineno - if self.name is not None: - rv += ' in ' + repr(self.name) - return rv - - def dump_local_context(self, frame): - return '{%s}' % ', '.join( - '%r: %s' % (name, target) for name, target - in iteritems(frame.symbols.dump_stores())) - - def write_commons(self): - """Writes a common preamble that is used by root and block functions. - Primarily this sets up common local helpers and enforces a generator - through a dead branch. - """ - self.writeline('resolve = context.resolve_or_missing') - self.writeline('undefined = environment.undefined') - self.writeline('if 0: yield None') - - def push_parameter_definitions(self, frame): - """Pushes all parameter targets from the given frame into a local - stack that permits tracking of yet to be assigned parameters. In - particular this enables the optimization from `visit_Name` to skip - undefined expressions for parameters in macros as macros can reference - otherwise unbound parameters. - """ - self._param_def_block.append(frame.symbols.dump_param_targets()) - - def pop_parameter_definitions(self): - """Pops the current parameter definitions set.""" - self._param_def_block.pop() - - def mark_parameter_stored(self, target): - """Marks a parameter in the current parameter definitions as stored. - This will skip the enforced undefined checks. - """ - if self._param_def_block: - self._param_def_block[-1].discard(target) - - def push_context_reference(self, target): - self._context_reference_stack.append(target) - - def pop_context_reference(self): - self._context_reference_stack.pop() - - def get_context_ref(self): - return self._context_reference_stack[-1] - - def get_resolve_func(self): - target = self._context_reference_stack[-1] - if target == 'context': - return 'resolve' - return '%s.resolve' % target - - def derive_context(self, frame): - return '%s.derived(%s)' % ( - self.get_context_ref(), - self.dump_local_context(frame), - ) - - def parameter_is_undeclared(self, target): - """Checks if a given target is an undeclared parameter.""" - if not self._param_def_block: - return False - return target in self._param_def_block[-1] - - def push_assign_tracking(self): - """Pushes a new layer for assignment tracking.""" - self._assign_stack.append(set()) - - def pop_assign_tracking(self, frame): - """Pops the topmost level for assignment tracking and updates the - context variables if necessary. - """ - vars = self._assign_stack.pop() - if not frame.toplevel or not vars: - return - public_names = [x for x in vars if x[:1] != '_'] - if len(vars) == 1: - name = next(iter(vars)) - ref = frame.symbols.ref(name) - self.writeline('context.vars[%r] = %s' % (name, ref)) - else: - self.writeline('context.vars.update({') - for idx, name in enumerate(vars): - if idx: - self.write(', ') - ref = frame.symbols.ref(name) - self.write('%r: %s' % (name, ref)) - self.write('})') - if public_names: - if len(public_names) == 1: - self.writeline('context.exported_vars.add(%r)' % - public_names[0]) - else: - self.writeline('context.exported_vars.update((%s))' % - ', '.join(imap(repr, public_names))) - - # -- Statement Visitors - - def visit_Template(self, node, frame=None): - assert frame is None, 'no root frame allowed' - eval_ctx = EvalContext(self.environment, self.name) - - from jinja2.runtime import __all__ as exported - self.writeline('from __future__ import %s' % ', '.join(code_features)) - self.writeline('from jinja2.runtime import ' + ', '.join(exported)) - - if self.environment.is_async: - self.writeline('from jinja2.asyncsupport import auto_await, ' - 'auto_aiter, make_async_loop_context') - - # if we want a deferred initialization we cannot move the - # environment into a local name - envenv = not self.defer_init and ', environment=environment' or '' - - # do we have an extends tag at all? If not, we can save some - # overhead by just not processing any inheritance code. - have_extends = node.find(nodes.Extends) is not None - - # find all blocks - for block in node.find_all(nodes.Block): - if block.name in self.blocks: - self.fail('block %r defined twice' % block.name, block.lineno) - self.blocks[block.name] = block - - # find all imports and import them - for import_ in node.find_all(nodes.ImportedName): - if import_.importname not in self.import_aliases: - imp = import_.importname - self.import_aliases[imp] = alias = self.temporary_identifier() - if '.' in imp: - module, obj = imp.rsplit('.', 1) - self.writeline('from %s import %s as %s' % - (module, obj, alias)) - else: - self.writeline('import %s as %s' % (imp, alias)) - - # add the load name - self.writeline('name = %r' % self.name) - - # generate the root render function. - self.writeline('%s(context, missing=missing%s):' % - (self.func('root'), envenv), extra=1) - self.indent() - self.write_commons() - - # process the root - frame = Frame(eval_ctx) - if 'self' in find_undeclared(node.body, ('self',)): - ref = frame.symbols.declare_parameter('self') - self.writeline('%s = TemplateReference(context)' % ref) - frame.symbols.analyze_node(node) - frame.toplevel = frame.rootlevel = True - frame.require_output_check = have_extends and not self.has_known_extends - if have_extends: - self.writeline('parent_template = None') - self.enter_frame(frame) - self.pull_dependencies(node.body) - self.blockvisit(node.body, frame) - self.leave_frame(frame, with_python_scope=True) - self.outdent() - - # make sure that the parent root is called. - if have_extends: - if not self.has_known_extends: - self.indent() - self.writeline('if parent_template is not None:') - self.indent() - if supports_yield_from and not self.environment.is_async: - self.writeline('yield from parent_template.' - 'root_render_func(context)') - else: - self.writeline('%sfor event in parent_template.' - 'root_render_func(context):' % - (self.environment.is_async and 'async ' or '')) - self.indent() - self.writeline('yield event') - self.outdent() - self.outdent(1 + (not self.has_known_extends)) - - # at this point we now have the blocks collected and can visit them too. - for name, block in iteritems(self.blocks): - self.writeline('%s(context, missing=missing%s):' % - (self.func('block_' + name), envenv), - block, 1) - self.indent() - self.write_commons() - # It's important that we do not make this frame a child of the - # toplevel template. This would cause a variety of - # interesting issues with identifier tracking. - block_frame = Frame(eval_ctx) - undeclared = find_undeclared(block.body, ('self', 'super')) - if 'self' in undeclared: - ref = block_frame.symbols.declare_parameter('self') - self.writeline('%s = TemplateReference(context)' % ref) - if 'super' in undeclared: - ref = block_frame.symbols.declare_parameter('super') - self.writeline('%s = context.super(%r, ' - 'block_%s)' % (ref, name, name)) - block_frame.symbols.analyze_node(block) - block_frame.block = name - self.enter_frame(block_frame) - self.pull_dependencies(block.body) - self.blockvisit(block.body, block_frame) - self.leave_frame(block_frame, with_python_scope=True) - self.outdent() - - self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x) - for x in self.blocks), - extra=1) - - # add a function that returns the debug info - self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x - in self.debug_info)) - - def visit_Block(self, node, frame): - """Call a block and register it for the template.""" - level = 0 - if frame.toplevel: - # if we know that we are a child template, there is no need to - # check if we are one - if self.has_known_extends: - return - if self.extends_so_far > 0: - self.writeline('if parent_template is None:') - self.indent() - level += 1 - - if node.scoped: - context = self.derive_context(frame) - else: - context = self.get_context_ref() - - if supports_yield_from and not self.environment.is_async and \ - frame.buffer is None: - self.writeline('yield from context.blocks[%r][0](%s)' % ( - node.name, context), node) - else: - loop = self.environment.is_async and 'async for' or 'for' - self.writeline('%s event in context.blocks[%r][0](%s):' % ( - loop, node.name, context), node) - self.indent() - self.simple_write('event', frame) - self.outdent() - - self.outdent(level) - - def visit_Extends(self, node, frame): - """Calls the extender.""" - if not frame.toplevel: - self.fail('cannot use extend from a non top-level scope', - node.lineno) - - # if the number of extends statements in general is zero so - # far, we don't have to add a check if something extended - # the template before this one. - if self.extends_so_far > 0: - - # if we have a known extends we just add a template runtime - # error into the generated code. We could catch that at compile - # time too, but i welcome it not to confuse users by throwing the - # same error at different times just "because we can". - if not self.has_known_extends: - self.writeline('if parent_template is not None:') - self.indent() - self.writeline('raise TemplateRuntimeError(%r)' % - 'extended multiple times') - - # if we have a known extends already we don't need that code here - # as we know that the template execution will end here. - if self.has_known_extends: - raise CompilerExit() - else: - self.outdent() - - self.writeline('parent_template = environment.get_template(', node) - self.visit(node.template, frame) - self.write(', %r)' % self.name) - self.writeline('for name, parent_block in parent_template.' - 'blocks.%s():' % dict_item_iter) - self.indent() - self.writeline('context.blocks.setdefault(name, []).' - 'append(parent_block)') - self.outdent() - - # if this extends statement was in the root level we can take - # advantage of that information and simplify the generated code - # in the top level from this point onwards - if frame.rootlevel: - self.has_known_extends = True - - # and now we have one more - self.extends_so_far += 1 - - def visit_Include(self, node, frame): - """Handles includes.""" - if node.ignore_missing: - self.writeline('try:') - self.indent() - - func_name = 'get_or_select_template' - if isinstance(node.template, nodes.Const): - if isinstance(node.template.value, string_types): - func_name = 'get_template' - elif isinstance(node.template.value, (tuple, list)): - func_name = 'select_template' - elif isinstance(node.template, (nodes.Tuple, nodes.List)): - func_name = 'select_template' - - self.writeline('template = environment.%s(' % func_name, node) - self.visit(node.template, frame) - self.write(', %r)' % self.name) - if node.ignore_missing: - self.outdent() - self.writeline('except TemplateNotFound:') - self.indent() - self.writeline('pass') - self.outdent() - self.writeline('else:') - self.indent() - - skip_event_yield = False - if node.with_context: - loop = self.environment.is_async and 'async for' or 'for' - self.writeline('%s event in template.root_render_func(' - 'template.new_context(context.get_all(), True, ' - '%s)):' % (loop, self.dump_local_context(frame))) - elif self.environment.is_async: - self.writeline('for event in (await ' - 'template._get_default_module_async())' - '._body_stream:') - else: - if supports_yield_from: - self.writeline('yield from template._get_default_module()' - '._body_stream') - skip_event_yield = True - else: - self.writeline('for event in template._get_default_module()' - '._body_stream:') - - if not skip_event_yield: - self.indent() - self.simple_write('event', frame) - self.outdent() - - if node.ignore_missing: - self.outdent() - - def visit_Import(self, node, frame): - """Visit regular imports.""" - self.writeline('%s = ' % frame.symbols.ref(node.target), node) - if frame.toplevel: - self.write('context.vars[%r] = ' % node.target) - if self.environment.is_async: - self.write('await ') - self.write('environment.get_template(') - self.visit(node.template, frame) - self.write(', %r).' % self.name) - if node.with_context: - self.write('make_module%s(context.get_all(), True, %s)' - % (self.environment.is_async and '_async' or '', - self.dump_local_context(frame))) - elif self.environment.is_async: - self.write('_get_default_module_async()') - else: - self.write('_get_default_module()') - if frame.toplevel and not node.target.startswith('_'): - self.writeline('context.exported_vars.discard(%r)' % node.target) - - def visit_FromImport(self, node, frame): - """Visit named imports.""" - self.newline(node) - self.write('included_template = %senvironment.get_template(' - % (self.environment.is_async and 'await ' or '')) - self.visit(node.template, frame) - self.write(', %r).' % self.name) - if node.with_context: - self.write('make_module%s(context.get_all(), True, %s)' - % (self.environment.is_async and '_async' or '', - self.dump_local_context(frame))) - elif self.environment.is_async: - self.write('_get_default_module_async()') - else: - self.write('_get_default_module()') - - var_names = [] - discarded_names = [] - for name in node.names: - if isinstance(name, tuple): - name, alias = name - else: - alias = name - self.writeline('%s = getattr(included_template, ' - '%r, missing)' % (frame.symbols.ref(alias), name)) - self.writeline('if %s is missing:' % frame.symbols.ref(alias)) - self.indent() - self.writeline('%s = undefined(%r %% ' - 'included_template.__name__, ' - 'name=%r)' % - (frame.symbols.ref(alias), - 'the template %%r (imported on %s) does ' - 'not export the requested name %s' % ( - self.position(node), - repr(name) - ), name)) - self.outdent() - if frame.toplevel: - var_names.append(alias) - if not alias.startswith('_'): - discarded_names.append(alias) - - if var_names: - if len(var_names) == 1: - name = var_names[0] - self.writeline('context.vars[%r] = %s' % - (name, frame.symbols.ref(name))) - else: - self.writeline('context.vars.update({%s})' % ', '.join( - '%r: %s' % (name, frame.symbols.ref(name)) for name in var_names - )) - if discarded_names: - if len(discarded_names) == 1: - self.writeline('context.exported_vars.discard(%r)' % - discarded_names[0]) - else: - self.writeline('context.exported_vars.difference_' - 'update((%s))' % ', '.join(imap(repr, discarded_names))) - - def visit_For(self, node, frame): - loop_frame = frame.inner() - test_frame = frame.inner() - else_frame = frame.inner() - - # try to figure out if we have an extended loop. An extended loop - # is necessary if the loop is in recursive mode if the special loop - # variable is accessed in the body. - extended_loop = node.recursive or 'loop' in \ - find_undeclared(node.iter_child_nodes( - only=('body',)), ('loop',)) - - loop_ref = None - if extended_loop: - loop_ref = loop_frame.symbols.declare_parameter('loop') - - loop_frame.symbols.analyze_node(node, for_branch='body') - if node.else_: - else_frame.symbols.analyze_node(node, for_branch='else') - - if node.test: - loop_filter_func = self.temporary_identifier() - test_frame.symbols.analyze_node(node, for_branch='test') - self.writeline('%s(fiter):' % self.func(loop_filter_func), node.test) - self.indent() - self.enter_frame(test_frame) - self.writeline(self.environment.is_async and 'async for ' or 'for ') - self.visit(node.target, loop_frame) - self.write(' in ') - self.write(self.environment.is_async and 'auto_aiter(fiter)' or 'fiter') - self.write(':') - self.indent() - self.writeline('if ', node.test) - self.visit(node.test, test_frame) - self.write(':') - self.indent() - self.writeline('yield ') - self.visit(node.target, loop_frame) - self.outdent(3) - self.leave_frame(test_frame, with_python_scope=True) - - # if we don't have an recursive loop we have to find the shadowed - # variables at that point. Because loops can be nested but the loop - # variable is a special one we have to enforce aliasing for it. - if node.recursive: - self.writeline('%s(reciter, loop_render_func, depth=0):' % - self.func('loop'), node) - self.indent() - self.buffer(loop_frame) - - # Use the same buffer for the else frame - else_frame.buffer = loop_frame.buffer - - # make sure the loop variable is a special one and raise a template - # assertion error if a loop tries to write to loop - if extended_loop: - self.writeline('%s = missing' % loop_ref) - - for name in node.find_all(nodes.Name): - if name.ctx == 'store' and name.name == 'loop': - self.fail('Can\'t assign to special loop variable ' - 'in for-loop target', name.lineno) - - if node.else_: - iteration_indicator = self.temporary_identifier() - self.writeline('%s = 1' % iteration_indicator) - - self.writeline(self.environment.is_async and 'async for ' or 'for ', node) - self.visit(node.target, loop_frame) - if extended_loop: - if self.environment.is_async: - self.write(', %s in await make_async_loop_context(' % loop_ref) - else: - self.write(', %s in LoopContext(' % loop_ref) - else: - self.write(' in ') - - if node.test: - self.write('%s(' % loop_filter_func) - if node.recursive: - self.write('reciter') - else: - if self.environment.is_async and not extended_loop: - self.write('auto_aiter(') - self.visit(node.iter, frame) - if self.environment.is_async and not extended_loop: - self.write(')') - if node.test: - self.write(')') - - if node.recursive: - self.write(', undefined, loop_render_func, depth):') - else: - self.write(extended_loop and ', undefined):' or ':') - - self.indent() - self.enter_frame(loop_frame) - - self.blockvisit(node.body, loop_frame) - if node.else_: - self.writeline('%s = 0' % iteration_indicator) - self.outdent() - self.leave_frame(loop_frame, with_python_scope=node.recursive - and not node.else_) - - if node.else_: - self.writeline('if %s:' % iteration_indicator) - self.indent() - self.enter_frame(else_frame) - self.blockvisit(node.else_, else_frame) - self.leave_frame(else_frame) - self.outdent() - - # if the node was recursive we have to return the buffer contents - # and start the iteration code - if node.recursive: - self.return_buffer_contents(loop_frame) - self.outdent() - self.start_write(frame, node) - if self.environment.is_async: - self.write('await ') - self.write('loop(') - if self.environment.is_async: - self.write('auto_aiter(') - self.visit(node.iter, frame) - if self.environment.is_async: - self.write(')') - self.write(', loop)') - self.end_write(frame) - - def visit_If(self, node, frame): - if_frame = frame.soft() - self.writeline('if ', node) - self.visit(node.test, if_frame) - self.write(':') - self.indent() - self.blockvisit(node.body, if_frame) - self.outdent() - for elif_ in node.elif_: - self.writeline('elif ', elif_) - self.visit(elif_.test, if_frame) - self.write(':') - self.indent() - self.blockvisit(elif_.body, if_frame) - self.outdent() - if node.else_: - self.writeline('else:') - self.indent() - self.blockvisit(node.else_, if_frame) - self.outdent() - - def visit_Macro(self, node, frame): - macro_frame, macro_ref = self.macro_body(node, frame) - self.newline() - if frame.toplevel: - if not node.name.startswith('_'): - self.write('context.exported_vars.add(%r)' % node.name) - ref = frame.symbols.ref(node.name) - self.writeline('context.vars[%r] = ' % node.name) - self.write('%s = ' % frame.symbols.ref(node.name)) - self.macro_def(macro_ref, macro_frame) - - def visit_CallBlock(self, node, frame): - call_frame, macro_ref = self.macro_body(node, frame) - self.writeline('caller = ') - self.macro_def(macro_ref, call_frame) - self.start_write(frame, node) - self.visit_Call(node.call, frame, forward_caller=True) - self.end_write(frame) - - def visit_FilterBlock(self, node, frame): - filter_frame = frame.inner() - filter_frame.symbols.analyze_node(node) - self.enter_frame(filter_frame) - self.buffer(filter_frame) - self.blockvisit(node.body, filter_frame) - self.start_write(frame, node) - self.visit_Filter(node.filter, filter_frame) - self.end_write(frame) - self.leave_frame(filter_frame) - - def visit_With(self, node, frame): - with_frame = frame.inner() - with_frame.symbols.analyze_node(node) - self.enter_frame(with_frame) - for idx, (target, expr) in enumerate(izip(node.targets, node.values)): - self.newline() - self.visit(target, with_frame) - self.write(' = ') - self.visit(expr, frame) - self.blockvisit(node.body, with_frame) - self.leave_frame(with_frame) - - def visit_ExprStmt(self, node, frame): - self.newline(node) - self.visit(node.node, frame) - - def visit_Output(self, node, frame): - # if we have a known extends statement, we don't output anything - # if we are in a require_output_check section - if self.has_known_extends and frame.require_output_check: - return - - allow_constant_finalize = True - if self.environment.finalize: - func = self.environment.finalize - if getattr(func, 'contextfunction', False) or \ - getattr(func, 'evalcontextfunction', False): - allow_constant_finalize = False - elif getattr(func, 'environmentfunction', False): - finalize = lambda x: text_type( - self.environment.finalize(self.environment, x)) - else: - finalize = lambda x: text_type(self.environment.finalize(x)) - else: - finalize = text_type - - # if we are inside a frame that requires output checking, we do so - outdent_later = False - if frame.require_output_check: - self.writeline('if parent_template is None:') - self.indent() - outdent_later = True - - # try to evaluate as many chunks as possible into a static - # string at compile time. - body = [] - for child in node.nodes: - try: - if not allow_constant_finalize: - raise nodes.Impossible() - const = child.as_const(frame.eval_ctx) - except nodes.Impossible: - body.append(child) - continue - # the frame can't be volatile here, becaus otherwise the - # as_const() function would raise an Impossible exception - # at that point. - try: - if frame.eval_ctx.autoescape: - if hasattr(const, '__html__'): - const = const.__html__() - else: - const = escape(const) - const = finalize(const) - except Exception: - # if something goes wrong here we evaluate the node - # at runtime for easier debugging - body.append(child) - continue - if body and isinstance(body[-1], list): - body[-1].append(const) - else: - body.append([const]) - - # if we have less than 3 nodes or a buffer we yield or extend/append - if len(body) < 3 or frame.buffer is not None: - if frame.buffer is not None: - # for one item we append, for more we extend - if len(body) == 1: - self.writeline('%s.append(' % frame.buffer) - else: - self.writeline('%s.extend((' % frame.buffer) - self.indent() - for item in body: - if isinstance(item, list): - val = repr(concat(item)) - if frame.buffer is None: - self.writeline('yield ' + val) - else: - self.writeline(val + ',') - else: - if frame.buffer is None: - self.writeline('yield ', item) - else: - self.newline(item) - close = 1 - if frame.eval_ctx.volatile: - self.write('(escape if context.eval_ctx.autoescape' - ' else to_string)(') - elif frame.eval_ctx.autoescape: - self.write('escape(') - else: - self.write('to_string(') - if self.environment.finalize is not None: - self.write('environment.finalize(') - if getattr(self.environment.finalize, - "contextfunction", False): - self.write('context, ') - close += 1 - self.visit(item, frame) - self.write(')' * close) - if frame.buffer is not None: - self.write(',') - if frame.buffer is not None: - # close the open parentheses - self.outdent() - self.writeline(len(body) == 1 and ')' or '))') - - # otherwise we create a format string as this is faster in that case - else: - format = [] - arguments = [] - for item in body: - if isinstance(item, list): - format.append(concat(item).replace('%', '%%')) - else: - format.append('%s') - arguments.append(item) - self.writeline('yield ') - self.write(repr(concat(format)) + ' % (') - self.indent() - for argument in arguments: - self.newline(argument) - close = 0 - if frame.eval_ctx.volatile: - self.write('(escape if context.eval_ctx.autoescape else' - ' to_string)(') - close += 1 - elif frame.eval_ctx.autoescape: - self.write('escape(') - close += 1 - if self.environment.finalize is not None: - self.write('environment.finalize(') - if getattr(self.environment.finalize, - 'contextfunction', False): - self.write('context, ') - elif getattr(self.environment.finalize, - 'evalcontextfunction', False): - self.write('context.eval_ctx, ') - elif getattr(self.environment.finalize, - 'environmentfunction', False): - self.write('environment, ') - close += 1 - self.visit(argument, frame) - self.write(')' * close + ', ') - self.outdent() - self.writeline(')') - - if outdent_later: - self.outdent() - - def visit_Assign(self, node, frame): - self.push_assign_tracking() - self.newline(node) - self.visit(node.target, frame) - self.write(' = ') - self.visit(node.node, frame) - self.pop_assign_tracking(frame) - - def visit_AssignBlock(self, node, frame): - self.push_assign_tracking() - block_frame = frame.inner() - # This is a special case. Since a set block always captures we - # will disable output checks. This way one can use set blocks - # toplevel even in extended templates. - block_frame.require_output_check = False - block_frame.symbols.analyze_node(node) - self.enter_frame(block_frame) - self.buffer(block_frame) - self.blockvisit(node.body, block_frame) - self.newline(node) - self.visit(node.target, frame) - self.write(' = (Markup if context.eval_ctx.autoescape ' - 'else identity)(') - if node.filter is not None: - self.visit_Filter(node.filter, block_frame) - else: - self.write('concat(%s)' % block_frame.buffer) - self.write(')') - self.pop_assign_tracking(frame) - self.leave_frame(block_frame) - - # -- Expression Visitors - - def visit_Name(self, node, frame): - if node.ctx == 'store' and frame.toplevel: - if self._assign_stack: - self._assign_stack[-1].add(node.name) - ref = frame.symbols.ref(node.name) - - # If we are looking up a variable we might have to deal with the - # case where it's undefined. We can skip that case if the load - # instruction indicates a parameter which are always defined. - if node.ctx == 'load': - load = frame.symbols.find_load(ref) - if not (load is not None and load[0] == VAR_LOAD_PARAMETER and \ - not self.parameter_is_undeclared(ref)): - self.write('(undefined(name=%r) if %s is missing else %s)' % - (node.name, ref, ref)) - return - - self.write(ref) - - def visit_NSRef(self, node, frame): - # NSRefs can only be used to store values; since they use the normal - # `foo.bar` notation they will be parsed as a normal attribute access - # when used anywhere but in a `set` context - ref = frame.symbols.ref(node.name) - self.writeline('if not isinstance(%s, Namespace):' % ref) - self.indent() - self.writeline('raise TemplateRuntimeError(%r)' % - 'cannot assign attribute on non-namespace object') - self.outdent() - self.writeline('%s[%r]' % (ref, node.attr)) - - def visit_Const(self, node, frame): - val = node.as_const(frame.eval_ctx) - if isinstance(val, float): - self.write(str(val)) - else: - self.write(repr(val)) - - def visit_TemplateData(self, node, frame): - try: - self.write(repr(node.as_const(frame.eval_ctx))) - except nodes.Impossible: - self.write('(Markup if context.eval_ctx.autoescape else identity)(%r)' - % node.data) - - def visit_Tuple(self, node, frame): - self.write('(') - idx = -1 - for idx, item in enumerate(node.items): - if idx: - self.write(', ') - self.visit(item, frame) - self.write(idx == 0 and ',)' or ')') - - def visit_List(self, node, frame): - self.write('[') - for idx, item in enumerate(node.items): - if idx: - self.write(', ') - self.visit(item, frame) - self.write(']') - - def visit_Dict(self, node, frame): - self.write('{') - for idx, item in enumerate(node.items): - if idx: - self.write(', ') - self.visit(item.key, frame) - self.write(': ') - self.visit(item.value, frame) - self.write('}') - - def binop(operator, interceptable=True): - @optimizeconst - def visitor(self, node, frame): - if self.environment.sandboxed and \ - operator in self.environment.intercepted_binops: - self.write('environment.call_binop(context, %r, ' % operator) - self.visit(node.left, frame) - self.write(', ') - self.visit(node.right, frame) - else: - self.write('(') - self.visit(node.left, frame) - self.write(' %s ' % operator) - self.visit(node.right, frame) - self.write(')') - return visitor - - def uaop(operator, interceptable=True): - @optimizeconst - def visitor(self, node, frame): - if self.environment.sandboxed and \ - operator in self.environment.intercepted_unops: - self.write('environment.call_unop(context, %r, ' % operator) - self.visit(node.node, frame) - else: - self.write('(' + operator) - self.visit(node.node, frame) - self.write(')') - return visitor - - visit_Add = binop('+') - visit_Sub = binop('-') - visit_Mul = binop('*') - visit_Div = binop('/') - visit_FloorDiv = binop('//') - visit_Pow = binop('**') - visit_Mod = binop('%') - visit_And = binop('and', interceptable=False) - visit_Or = binop('or', interceptable=False) - visit_Pos = uaop('+') - visit_Neg = uaop('-') - visit_Not = uaop('not ', interceptable=False) - del binop, uaop - - @optimizeconst - def visit_Concat(self, node, frame): - if frame.eval_ctx.volatile: - func_name = '(context.eval_ctx.volatile and' \ - ' markup_join or unicode_join)' - elif frame.eval_ctx.autoescape: - func_name = 'markup_join' - else: - func_name = 'unicode_join' - self.write('%s((' % func_name) - for arg in node.nodes: - self.visit(arg, frame) - self.write(', ') - self.write('))') - - @optimizeconst - def visit_Compare(self, node, frame): - self.visit(node.expr, frame) - for op in node.ops: - self.visit(op, frame) - - def visit_Operand(self, node, frame): - self.write(' %s ' % operators[node.op]) - self.visit(node.expr, frame) - - @optimizeconst - def visit_Getattr(self, node, frame): - self.write('environment.getattr(') - self.visit(node.node, frame) - self.write(', %r)' % node.attr) - - @optimizeconst - def visit_Getitem(self, node, frame): - # slices bypass the environment getitem method. - if isinstance(node.arg, nodes.Slice): - self.visit(node.node, frame) - self.write('[') - self.visit(node.arg, frame) - self.write(']') - else: - self.write('environment.getitem(') - self.visit(node.node, frame) - self.write(', ') - self.visit(node.arg, frame) - self.write(')') - - def visit_Slice(self, node, frame): - if node.start is not None: - self.visit(node.start, frame) - self.write(':') - if node.stop is not None: - self.visit(node.stop, frame) - if node.step is not None: - self.write(':') - self.visit(node.step, frame) - - @optimizeconst - def visit_Filter(self, node, frame): - if self.environment.is_async: - self.write('await auto_await(') - self.write(self.filters[node.name] + '(') - func = self.environment.filters.get(node.name) - if func is None: - self.fail('no filter named %r' % node.name, node.lineno) - if getattr(func, 'contextfilter', False): - self.write('context, ') - elif getattr(func, 'evalcontextfilter', False): - self.write('context.eval_ctx, ') - elif getattr(func, 'environmentfilter', False): - self.write('environment, ') - - # if the filter node is None we are inside a filter block - # and want to write to the current buffer - if node.node is not None: - self.visit(node.node, frame) - elif frame.eval_ctx.volatile: - self.write('(context.eval_ctx.autoescape and' - ' Markup(concat(%s)) or concat(%s))' % - (frame.buffer, frame.buffer)) - elif frame.eval_ctx.autoescape: - self.write('Markup(concat(%s))' % frame.buffer) - else: - self.write('concat(%s)' % frame.buffer) - self.signature(node, frame) - self.write(')') - if self.environment.is_async: - self.write(')') - - @optimizeconst - def visit_Test(self, node, frame): - self.write(self.tests[node.name] + '(') - if node.name not in self.environment.tests: - self.fail('no test named %r' % node.name, node.lineno) - self.visit(node.node, frame) - self.signature(node, frame) - self.write(')') - - @optimizeconst - def visit_CondExpr(self, node, frame): - def write_expr2(): - if node.expr2 is not None: - return self.visit(node.expr2, frame) - self.write('undefined(%r)' % ('the inline if-' - 'expression on %s evaluated to false and ' - 'no else section was defined.' % self.position(node))) - - self.write('(') - self.visit(node.expr1, frame) - self.write(' if ') - self.visit(node.test, frame) - self.write(' else ') - write_expr2() - self.write(')') - - @optimizeconst - def visit_Call(self, node, frame, forward_caller=False): - if self.environment.is_async: - self.write('await auto_await(') - if self.environment.sandboxed: - self.write('environment.call(context, ') - else: - self.write('context.call(') - self.visit(node.node, frame) - extra_kwargs = forward_caller and {'caller': 'caller'} or None - self.signature(node, frame, extra_kwargs) - self.write(')') - if self.environment.is_async: - self.write(')') - - def visit_Keyword(self, node, frame): - self.write(node.key + '=') - self.visit(node.value, frame) - - # -- Unused nodes for extensions - - def visit_MarkSafe(self, node, frame): - self.write('Markup(') - self.visit(node.expr, frame) - self.write(')') - - def visit_MarkSafeIfAutoescape(self, node, frame): - self.write('(context.eval_ctx.autoescape and Markup or identity)(') - self.visit(node.expr, frame) - self.write(')') - - def visit_EnvironmentAttribute(self, node, frame): - self.write('environment.' + node.name) - - def visit_ExtensionAttribute(self, node, frame): - self.write('environment.extensions[%r].%s' % (node.identifier, node.name)) - - def visit_ImportedName(self, node, frame): - self.write(self.import_aliases[node.importname]) - - def visit_InternalName(self, node, frame): - self.write(node.name) - - def visit_ContextReference(self, node, frame): - self.write('context') - - def visit_Continue(self, node, frame): - self.writeline('continue', node) - - def visit_Break(self, node, frame): - self.writeline('break', node) - - def visit_Scope(self, node, frame): - scope_frame = frame.inner() - scope_frame.symbols.analyze_node(node) - self.enter_frame(scope_frame) - self.blockvisit(node.body, scope_frame) - self.leave_frame(scope_frame) - - def visit_OverlayScope(self, node, frame): - ctx = self.temporary_identifier() - self.writeline('%s = %s' % (ctx, self.derive_context(frame))) - self.writeline('%s.vars = ' % ctx) - self.visit(node.context, frame) - self.push_context_reference(ctx) - - scope_frame = frame.inner(isolated=True) - scope_frame.symbols.analyze_node(node) - self.enter_frame(scope_frame) - self.blockvisit(node.body, scope_frame) - self.leave_frame(scope_frame) - self.pop_context_reference() - - def visit_EvalContextModifier(self, node, frame): - for keyword in node.options: - self.writeline('context.eval_ctx.%s = ' % keyword.key) - self.visit(keyword.value, frame) - try: - val = keyword.value.as_const(frame.eval_ctx) - except nodes.Impossible: - frame.eval_ctx.volatile = True - else: - setattr(frame.eval_ctx, keyword.key, val) - - def visit_ScopedEvalContextModifier(self, node, frame): - old_ctx_name = self.temporary_identifier() - saved_ctx = frame.eval_ctx.save() - self.writeline('%s = context.eval_ctx.save()' % old_ctx_name) - self.visit_EvalContextModifier(node, frame) - for child in node.body: - self.visit(child, frame) - frame.eval_ctx.revert(saved_ctx) - self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name) diff --git a/py3.7/lib/python3.7/site-packages/jinja2/constants.py b/py3.7/lib/python3.7/site-packages/jinja2/constants.py deleted file mode 100644 index 11efd1e..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/constants.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja.constants - ~~~~~~~~~~~~~~~ - - Various constants. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" - - -#: list of lorem ipsum words used by the lipsum() helper function -LOREM_IPSUM_WORDS = u'''\ -a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at -auctor augue bibendum blandit class commodo condimentum congue consectetuer -consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus -diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend -elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames -faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac -hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum -justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem -luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie -mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non -nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque -penatibus per pharetra phasellus placerat platea porta porttitor posuere -potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus -ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit -sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor -tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices -ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus -viverra volutpat vulputate''' diff --git a/py3.7/lib/python3.7/site-packages/jinja2/debug.py b/py3.7/lib/python3.7/site-packages/jinja2/debug.py deleted file mode 100644 index b61139f..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/debug.py +++ /dev/null @@ -1,372 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.debug - ~~~~~~~~~~~~ - - Implements the debug interface for Jinja. This module does some pretty - ugly stuff with the Python traceback system in order to achieve tracebacks - with correct line numbers, locals and contents. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -import sys -import traceback -from types import TracebackType, CodeType -from jinja2.utils import missing, internal_code -from jinja2.exceptions import TemplateSyntaxError -from jinja2._compat import iteritems, reraise, PY2 - -# on pypy we can take advantage of transparent proxies -try: - from __pypy__ import tproxy -except ImportError: - tproxy = None - - -# how does the raise helper look like? -try: - exec("raise TypeError, 'foo'") -except SyntaxError: - raise_helper = 'raise __jinja_exception__[1]' -except TypeError: - raise_helper = 'raise __jinja_exception__[0], __jinja_exception__[1]' - - -class TracebackFrameProxy(object): - """Proxies a traceback frame.""" - - def __init__(self, tb): - self.tb = tb - self._tb_next = None - - @property - def tb_next(self): - return self._tb_next - - def set_next(self, next): - if tb_set_next is not None: - try: - tb_set_next(self.tb, next and next.tb or None) - except Exception: - # this function can fail due to all the hackery it does - # on various python implementations. We just catch errors - # down and ignore them if necessary. - pass - self._tb_next = next - - @property - def is_jinja_frame(self): - return '__jinja_template__' in self.tb.tb_frame.f_globals - - def __getattr__(self, name): - return getattr(self.tb, name) - - -def make_frame_proxy(frame): - proxy = TracebackFrameProxy(frame) - if tproxy is None: - return proxy - def operation_handler(operation, *args, **kwargs): - if operation in ('__getattribute__', '__getattr__'): - return getattr(proxy, args[0]) - elif operation == '__setattr__': - proxy.__setattr__(*args, **kwargs) - else: - return getattr(proxy, operation)(*args, **kwargs) - return tproxy(TracebackType, operation_handler) - - -class ProcessedTraceback(object): - """Holds a Jinja preprocessed traceback for printing or reraising.""" - - def __init__(self, exc_type, exc_value, frames): - assert frames, 'no frames for this traceback?' - self.exc_type = exc_type - self.exc_value = exc_value - self.frames = frames - - # newly concatenate the frames (which are proxies) - prev_tb = None - for tb in self.frames: - if prev_tb is not None: - prev_tb.set_next(tb) - prev_tb = tb - prev_tb.set_next(None) - - def render_as_text(self, limit=None): - """Return a string with the traceback.""" - lines = traceback.format_exception(self.exc_type, self.exc_value, - self.frames[0], limit=limit) - return ''.join(lines).rstrip() - - def render_as_html(self, full=False): - """Return a unicode string with the traceback as rendered HTML.""" - from jinja2.debugrenderer import render_traceback - return u'%s\n\n' % ( - render_traceback(self, full=full), - self.render_as_text().decode('utf-8', 'replace') - ) - - @property - def is_template_syntax_error(self): - """`True` if this is a template syntax error.""" - return isinstance(self.exc_value, TemplateSyntaxError) - - @property - def exc_info(self): - """Exception info tuple with a proxy around the frame objects.""" - return self.exc_type, self.exc_value, self.frames[0] - - @property - def standard_exc_info(self): - """Standard python exc_info for re-raising""" - tb = self.frames[0] - # the frame will be an actual traceback (or transparent proxy) if - # we are on pypy or a python implementation with support for tproxy - if type(tb) is not TracebackType: - tb = tb.tb - return self.exc_type, self.exc_value, tb - - -def make_traceback(exc_info, source_hint=None): - """Creates a processed traceback object from the exc_info.""" - exc_type, exc_value, tb = exc_info - if isinstance(exc_value, TemplateSyntaxError): - exc_info = translate_syntax_error(exc_value, source_hint) - initial_skip = 0 - else: - initial_skip = 1 - return translate_exception(exc_info, initial_skip) - - -def translate_syntax_error(error, source=None): - """Rewrites a syntax error to please traceback systems.""" - error.source = source - error.translated = True - exc_info = (error.__class__, error, None) - filename = error.filename - if filename is None: - filename = '' - return fake_exc_info(exc_info, filename, error.lineno) - - -def translate_exception(exc_info, initial_skip=0): - """If passed an exc_info it will automatically rewrite the exceptions - all the way down to the correct line numbers and frames. - """ - tb = exc_info[2] - frames = [] - - # skip some internal frames if wanted - for x in range(initial_skip): - if tb is not None: - tb = tb.tb_next - initial_tb = tb - - while tb is not None: - # skip frames decorated with @internalcode. These are internal - # calls we can't avoid and that are useless in template debugging - # output. - if tb.tb_frame.f_code in internal_code: - tb = tb.tb_next - continue - - # save a reference to the next frame if we override the current - # one with a faked one. - next = tb.tb_next - - # fake template exceptions - template = tb.tb_frame.f_globals.get('__jinja_template__') - if template is not None: - lineno = template.get_corresponding_lineno(tb.tb_lineno) - tb = fake_exc_info(exc_info[:2] + (tb,), template.filename, - lineno)[2] - - frames.append(make_frame_proxy(tb)) - tb = next - - # if we don't have any exceptions in the frames left, we have to - # reraise it unchanged. - # XXX: can we backup here? when could this happen? - if not frames: - reraise(exc_info[0], exc_info[1], exc_info[2]) - - return ProcessedTraceback(exc_info[0], exc_info[1], frames) - - -def get_jinja_locals(real_locals): - ctx = real_locals.get('context') - if ctx: - locals = ctx.get_all().copy() - else: - locals = {} - - local_overrides = {} - - for name, value in iteritems(real_locals): - if not name.startswith('l_') or value is missing: - continue - try: - _, depth, name = name.split('_', 2) - depth = int(depth) - except ValueError: - continue - cur_depth = local_overrides.get(name, (-1,))[0] - if cur_depth < depth: - local_overrides[name] = (depth, value) - - for name, (_, value) in iteritems(local_overrides): - if value is missing: - locals.pop(name, None) - else: - locals[name] = value - - return locals - - -def fake_exc_info(exc_info, filename, lineno): - """Helper for `translate_exception`.""" - exc_type, exc_value, tb = exc_info - - # figure the real context out - if tb is not None: - locals = get_jinja_locals(tb.tb_frame.f_locals) - - # if there is a local called __jinja_exception__, we get - # rid of it to not break the debug functionality. - locals.pop('__jinja_exception__', None) - else: - locals = {} - - # assamble fake globals we need - globals = { - '__name__': filename, - '__file__': filename, - '__jinja_exception__': exc_info[:2], - - # we don't want to keep the reference to the template around - # to not cause circular dependencies, but we mark it as Jinja - # frame for the ProcessedTraceback - '__jinja_template__': None - } - - # and fake the exception - code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec') - - # if it's possible, change the name of the code. This won't work - # on some python environments such as google appengine - try: - if tb is None: - location = 'template' - else: - function = tb.tb_frame.f_code.co_name - if function == 'root': - location = 'top-level template code' - elif function.startswith('block_'): - location = 'block "%s"' % function[6:] - else: - location = 'template' - - if PY2: - code = CodeType(0, code.co_nlocals, code.co_stacksize, - code.co_flags, code.co_code, code.co_consts, - code.co_names, code.co_varnames, filename, - location, code.co_firstlineno, - code.co_lnotab, (), ()) - else: - code = CodeType(0, code.co_kwonlyargcount, - code.co_nlocals, code.co_stacksize, - code.co_flags, code.co_code, code.co_consts, - code.co_names, code.co_varnames, filename, - location, code.co_firstlineno, - code.co_lnotab, (), ()) - except Exception as e: - pass - - # execute the code and catch the new traceback - try: - exec(code, globals, locals) - except: - exc_info = sys.exc_info() - new_tb = exc_info[2].tb_next - - # return without this frame - return exc_info[:2] + (new_tb,) - - -def _init_ugly_crap(): - """This function implements a few ugly things so that we can patch the - traceback objects. The function returned allows resetting `tb_next` on - any python traceback object. Do not attempt to use this on non cpython - interpreters - """ - import ctypes - from types import TracebackType - - if PY2: - # figure out size of _Py_ssize_t for Python 2: - if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'): - _Py_ssize_t = ctypes.c_int64 - else: - _Py_ssize_t = ctypes.c_int - else: - # platform ssize_t on Python 3 - _Py_ssize_t = ctypes.c_ssize_t - - # regular python - class _PyObject(ctypes.Structure): - pass - _PyObject._fields_ = [ - ('ob_refcnt', _Py_ssize_t), - ('ob_type', ctypes.POINTER(_PyObject)) - ] - - # python with trace - if hasattr(sys, 'getobjects'): - class _PyObject(ctypes.Structure): - pass - _PyObject._fields_ = [ - ('_ob_next', ctypes.POINTER(_PyObject)), - ('_ob_prev', ctypes.POINTER(_PyObject)), - ('ob_refcnt', _Py_ssize_t), - ('ob_type', ctypes.POINTER(_PyObject)) - ] - - class _Traceback(_PyObject): - pass - _Traceback._fields_ = [ - ('tb_next', ctypes.POINTER(_Traceback)), - ('tb_frame', ctypes.POINTER(_PyObject)), - ('tb_lasti', ctypes.c_int), - ('tb_lineno', ctypes.c_int) - ] - - def tb_set_next(tb, next): - """Set the tb_next attribute of a traceback object.""" - if not (isinstance(tb, TracebackType) and - (next is None or isinstance(next, TracebackType))): - raise TypeError('tb_set_next arguments must be traceback objects') - obj = _Traceback.from_address(id(tb)) - if tb.tb_next is not None: - old = _Traceback.from_address(id(tb.tb_next)) - old.ob_refcnt -= 1 - if next is None: - obj.tb_next = ctypes.POINTER(_Traceback)() - else: - next = _Traceback.from_address(id(next)) - next.ob_refcnt += 1 - obj.tb_next = ctypes.pointer(next) - - return tb_set_next - - -# try to get a tb_set_next implementation if we don't have transparent -# proxies. -tb_set_next = None -if tproxy is None: - try: - tb_set_next = _init_ugly_crap() - except: - pass - del _init_ugly_crap diff --git a/py3.7/lib/python3.7/site-packages/jinja2/defaults.py b/py3.7/lib/python3.7/site-packages/jinja2/defaults.py deleted file mode 100644 index 7c93dec..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/defaults.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.defaults - ~~~~~~~~~~~~~~~ - - Jinja default filters and tags. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -from jinja2._compat import range_type -from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner, Namespace - - -# defaults for the parser / lexer -BLOCK_START_STRING = '{%' -BLOCK_END_STRING = '%}' -VARIABLE_START_STRING = '{{' -VARIABLE_END_STRING = '}}' -COMMENT_START_STRING = '{#' -COMMENT_END_STRING = '#}' -LINE_STATEMENT_PREFIX = None -LINE_COMMENT_PREFIX = None -TRIM_BLOCKS = False -LSTRIP_BLOCKS = False -NEWLINE_SEQUENCE = '\n' -KEEP_TRAILING_NEWLINE = False - - -# default filters, tests and namespace -from jinja2.filters import FILTERS as DEFAULT_FILTERS -from jinja2.tests import TESTS as DEFAULT_TESTS -DEFAULT_NAMESPACE = { - 'range': range_type, - 'dict': dict, - 'lipsum': generate_lorem_ipsum, - 'cycler': Cycler, - 'joiner': Joiner, - 'namespace': Namespace -} - - -# default policies -DEFAULT_POLICIES = { - 'compiler.ascii_str': True, - 'urlize.rel': 'noopener', - 'urlize.target': None, - 'truncate.leeway': 5, - 'json.dumps_function': None, - 'json.dumps_kwargs': {'sort_keys': True}, - 'ext.i18n.trimmed': False, -} - - -# export all constants -__all__ = tuple(x for x in locals().keys() if x.isupper()) diff --git a/py3.7/lib/python3.7/site-packages/jinja2/environment.py b/py3.7/lib/python3.7/site-packages/jinja2/environment.py deleted file mode 100644 index 549d9af..0000000 --- a/py3.7/lib/python3.7/site-packages/jinja2/environment.py +++ /dev/null @@ -1,1276 +0,0 @@ -# -*- coding: utf-8 -*- -""" - jinja2.environment - ~~~~~~~~~~~~~~~~~~ - - Provides a class that holds runtime and parsing time options. - - :copyright: (c) 2017 by the Jinja Team. - :license: BSD, see LICENSE for more details. -""" -import os -import sys -import weakref -from functools import reduce, partial -from jinja2 import nodes -from jinja2.defaults import BLOCK_START_STRING, \ - BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \ - COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \ - LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \ - DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \ - DEFAULT_POLICIES, KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS -from jinja2.lexer import get_lexer, TokenStream -from jinja2.parser import Parser -from jinja2.nodes import EvalContext -from jinja2.compiler import generate, CodeGenerator -from jinja2.runtime import Undefined, new_context, Context -from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \ - TemplatesNotFound, TemplateRuntimeError -from jinja2.utils import import_string, LRUCache, Markup, missing, \ - concat, consume, internalcode, have_async_gen -from jinja2._compat import imap, ifilter, string_types, iteritems, \ - text_type, reraise, implements_iterator, implements_to_string, \ - encode_filename, PY2, PYPY - - -# for direct template usage we have up to ten living environments -_spontaneous_environments = LRUCache(10) - -# the function to create jinja traceback objects. This is dynamically -# imported on the first exception in the exception handler. -_make_traceback = None - - -def get_spontaneous_environment(*args): - """Return a new spontaneous environment. A spontaneous environment is an - unnamed and unaccessible (in theory) environment that is used for - templates generated from a string and not from the file system. - """ - try: - env = _spontaneous_environments.get(args) - except TypeError: - return Environment(*args) - if env is not None: - return env - _spontaneous_environments[args] = env = Environment(*args) - env.shared = True - return env - - -def create_cache(size): - """Return the cache class for the given size.""" - if size == 0: - return None - if size < 0: - return {} - return LRUCache(size) - - -def copy_cache(cache): - """Create an empty copy of the given cache.""" - if cache is None: - return None - elif type(cache) is dict: - return {} - return LRUCache(cache.capacity) - - -def load_extensions(environment, extensions): - """Load the extensions from the list and bind it to the environment. - Returns a dict of instantiated environments. - """ - result = {} - for extension in extensions: - if isinstance(extension, string_types): - extension = import_string(extension) - result[extension.identifier] = extension(environment) - return result - - -def fail_for_missing_callable(string, name): - msg = string % name - if isinstance(name, Undefined): - try: - name._fail_with_undefined_error() - except Exception as e: - msg = '%s (%s; did you forget to quote the callable name?)' % (msg, e) - raise TemplateRuntimeError(msg) - - -def _environment_sanity_check(environment): - """Perform a sanity check on the environment.""" - assert issubclass(environment.undefined, Undefined), 'undefined must ' \ - 'be a subclass of undefined because filters depend on it.' - assert environment.block_start_string != \ - environment.variable_start_string != \ - environment.comment_start_string, 'block, variable and comment ' \ - 'start strings must be different' - assert environment.newline_sequence in ('\r', '\r\n', '\n'), \ - 'newline_sequence set to unknown line ending string.' - return environment - - -class Environment(object): - r"""The core component of Jinja is the `Environment`. It contains - important shared variables like configuration, filters, tests, - globals and others. Instances of this class may be modified if - they are not shared and if no template was loaded so far. - Modifications on environments after the first template was loaded - will lead to surprising effects and undefined behavior. - - Here are the possible initialization parameters: - - `block_start_string` - The string marking the beginning of a block. Defaults to ``'{%'``. - - `block_end_string` - The string marking the end of a block. Defaults to ``'%}'``. - - `variable_start_string` - The string marking the beginning of a print statement. - Defaults to ``'{{'``. - - `variable_end_string` - The string marking the end of a print statement. Defaults to - ``'}}'``. - - `comment_start_string` - The string marking the beginning of a comment. Defaults to ``'{#'``. - - `comment_end_string` - The string marking the end of a comment. Defaults to ``'#}'``. - - `line_statement_prefix` - If given and a string, this will be used as prefix for line based - statements. See also :ref:`line-statements`. - - `line_comment_prefix` - If given and a string, this will be used as prefix for line based - comments. See also :ref:`line-statements`. - - .. versionadded:: 2.2 - - `trim_blocks` - If this is set to ``True`` the first newline after a block is - removed (block, not variable tag!). Defaults to `False`. - - `lstrip_blocks` - If this is set to ``True`` leading spaces and tabs are stripped - from the start of a line to a block. Defaults to `False`. - - `newline_sequence` - The sequence that starts a newline. Must be one of ``'\r'``, - ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a - useful default for Linux and OS X systems as well as web - applications. - - `keep_trailing_newline` - Preserve the trailing newline when rendering templates. - The default is ``False``, which causes a single newline, - if present, to be stripped from the end of the template. - - .. versionadded:: 2.7 - - `extensions` - List of Jinja extensions to use. This can either be import paths - as strings or extension classes. For more information have a - look at :ref:`the extensions documentation `. - - `optimized` - should the optimizer be enabled? Default is ``True``. - - `undefined` - :class:`Undefined` or a subclass of it that is used to represent - undefined values in the template. - - `finalize` - A callable that can be used to process the result of a variable - expression before it is output. For example one can convert - ``None`` implicitly into an empty string here. - - `autoescape` - If set to ``True`` the XML/HTML autoescaping feature is enabled by - default. For more details about autoescaping see - :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also - be a callable that is passed the template name and has to - return ``True`` or ``False`` depending on autoescape should be - enabled by default. - - .. versionchanged:: 2.4 - `autoescape` can now be a function - - `loader` - The template loader for this environment. - - `cache_size` - The size of the cache. Per default this is ``400`` which means - that if more than 400 templates are loaded the loader will clean - out the least recently used template. If the cache size is set to - ``0`` templates are recompiled all the time, if the cache size is - ``-1`` the cache will not be cleaned. - - .. versionchanged:: 2.8 - The cache size was increased to 400 from a low 50. - - `auto_reload` - Some loaders load templates from locations where the template - sources may change (ie: file system or database). If - ``auto_reload`` is set to ``True`` (default) every time a template is - requested the loader checks if the source changed and if yes, it - will reload the template. For higher performance it's possible to - disable that. - - `bytecode_cache` - If set to a bytecode cache object, this object will provide a - cache for the internal Jinja bytecode so that templates don't - have to be parsed if they were not changed. - - See :ref:`bytecode-cache` for more information. - - `enable_async` - If set to true this enables async template execution which allows - you to take advantage of newer Python features. This requires - Python 3.6 or later. - """ - - #: if this environment is sandboxed. Modifying this variable won't make - #: the environment sandboxed though. For a real sandboxed environment - #: have a look at jinja2.sandbox. This flag alone controls the code - #: generation by the compiler. - sandboxed = False - - #: True if the environment is just an overlay - overlayed = False - - #: the environment this environment is linked to if it is an overlay - linked_to = None - - #: shared environments have this set to `True`. A shared environment - #: must not be modified - shared = False - - #: these are currently EXPERIMENTAL undocumented features. - exception_handler = None - exception_formatter = None - - #: the class that is used for code generation. See - #: :class:`~jinja2.compiler.CodeGenerator` for more information. - code_generator_class = CodeGenerator - - #: the context class thatis used for templates. See - #: :class:`~jinja2.runtime.Context` for more information. - context_class = Context - - def __init__(self, - block_start_string=BLOCK_START_STRING, - block_end_string=BLOCK_END_STRING, - variable_start_string=VARIABLE_START_STRING, - variable_end_string=VARIABLE_END_STRING, - comment_start_string=COMMENT_START_STRING, - comment_end_string=COMMENT_END_STRING, - line_statement_prefix=LINE_STATEMENT_PREFIX, - line_comment_prefix=LINE_COMMENT_PREFIX, - trim_blocks=TRIM_BLOCKS, - lstrip_blocks=LSTRIP_BLOCKS, - newline_sequence=NEWLINE_SEQUENCE, - keep_trailing_newline=KEEP_TRAILING_NEWLINE, - extensions=(), - optimized=True, - undefined=Undefined, - finalize=None, - autoescape=False, - loader=None, - cache_size=400, - auto_reload=True, - bytecode_cache=None, - enable_async=False): - # !!Important notice!! - # The constructor accepts quite a few arguments that should be - # passed by keyword rather than position. However it's important to - # not change the order of arguments because it's used at least - # internally in those cases: - # - spontaneous environments (i18n extension and Template) - # - unittests - # If parameter changes are required only add parameters at the end - # and don't change the arguments (or the defaults!) of the arguments - # existing already. - - # lexer / parser information - self.block_start_string = block_start_string - self.block_end_string = block_end_string - self.variable_start_string = variable_start_string - self.variable_end_string = variable_end_string - self.comment_start_string = comment_start_string - self.comment_end_string = comment_end_string - self.line_statement_prefix = line_statement_prefix - self.line_comment_prefix = line_comment_prefix - self.trim_blocks = trim_blocks - self.lstrip_blocks = lstrip_blocks - self.newline_sequence = newline_sequence - self.keep_trailing_newline = keep_trailing_newline - - # runtime information - self.undefined = undefined - self.optimized = optimized - self.finalize = finalize - self.autoescape = autoescape - - # defaults - self.filters = DEFAULT_FILTERS.copy() - self.tests = DEFAULT_TESTS.copy() - self.globals = DEFAULT_NAMESPACE.copy() - - # set the loader provided - self.loader = loader - self.cache = create_cache(cache_size) - self.bytecode_cache = bytecode_cache - self.auto_reload = auto_reload - - # configurable policies - self.policies = DEFAULT_POLICIES.copy() - - # load extensions - self.extensions = load_extensions(self, extensions) - - self.enable_async = enable_async - self.is_async = self.enable_async and have_async_gen - - _environment_sanity_check(self) - - def add_extension(self, extension): - """Adds an extension after the environment was created. - - .. versionadded:: 2.5 - """ - self.extensions.update(load_extensions(self, [extension])) - - def extend(self, **attributes): - """Add the items to the instance of the environment if they do not exist - yet. This is used by :ref:`extensions ` to register - callbacks and configuration values without breaking inheritance. - """ - for key, value in iteritems(attributes): - if not hasattr(self, key): - setattr(self, key, value) - - def overlay(self, block_start_string=missing, block_end_string=missing, - variable_start_string=missing, variable_end_string=missing, - comment_start_string=missing, comment_end_string=missing, - line_statement_prefix=missing, line_comment_prefix=missing, - trim_blocks=missing, lstrip_blocks=missing, - extensions=missing, optimized=missing, - undefined=missing, finalize=missing, autoescape=missing, - loader=missing, cache_size=missing, auto_reload=missing, - bytecode_cache=missing): - """Create a new overlay environment that shares all the data with the - current environment except for cache and the overridden attributes. - Extensions cannot be removed for an overlayed environment. An overlayed - environment automatically gets all the extensions of the environment it - is linked to plus optional extra extensions. - - Creating overlays should happen after the initial environment was set - up completely. Not all attributes are truly linked, some are just - copied over so modifications on the original environment may not shine - through. - """ - args = dict(locals()) - del args['self'], args['cache_size'], args['extensions'] - - rv = object.__new__(self.__class__) - rv.__dict__.update(self.__dict__) - rv.overlayed = True - rv.linked_to = self - - for key, value in iteritems(args): - if value is not missing: - setattr(rv, key, value) - - if cache_size is not missing: - rv.cache = create_cache(cache_size) - else: - rv.cache = copy_cache(self.cache) - - rv.extensions = {} - for key, value in iteritems(self.extensions): - rv.extensions[key] = value.bind(rv) - if extensions is not missing: - rv.extensions.update(load_extensions(rv, extensions)) - - return _environment_sanity_check(rv) - - lexer = property(get_lexer, doc="The lexer for this environment.") - - def iter_extensions(self): - """Iterates over the extensions by priority.""" - return iter(sorted(self.extensions.values(), - key=lambda x: x.priority)) - - def getitem(self, obj, argument): - """Get an item or attribute of an object but prefer the item.""" - try: - return obj[argument] - except (AttributeError, TypeError, LookupError): - if isinstance(argument, string_types): - try: - attr = str(argument) - except Exception: - pass - else: - try: - return getattr(obj, attr) - except AttributeError: - pass - return self.undefined(obj=obj, name=argument) - - def getattr(self, obj, attribute): - """Get an item or attribute of an object but prefer the attribute. - Unlike :meth:`getitem` the attribute *must* be a bytestring. - """ - try: - return getattr(obj, attribute) - except AttributeError: - pass - try: - return obj[attribute] - except (TypeError, LookupError, AttributeError): - return self.undefined(obj=obj, name=attribute) - - def call_filter(self, name, value, args=None, kwargs=None, - context=None, eval_ctx=None): - """Invokes a filter on a value the same way the compiler does it. - - Note that on Python 3 this might return a coroutine in case the - filter is running from an environment in async mode and the filter - supports async execution. It's your responsibility to await this - if needed. - - .. versionadded:: 2.7 - """ - func = self.filters.get(name) - if func is None: - fail_for_missing_callable('no filter named %r', name) - args = [value] + list(args or ()) - if getattr(func, 'contextfilter', False): - if context is None: - raise TemplateRuntimeError('Attempted to invoke context ' - 'filter without context') - args.insert(0, context) - elif getattr(func, 'evalcontextfilter', False): - if eval_ctx is None: - if context is not None: - eval_ctx = context.eval_ctx - else: - eval_ctx = EvalContext(self) - args.insert(0, eval_ctx) - elif getattr(func, 'environmentfilter', False): - args.insert(0, self) - return func(*args, **(kwargs or {})) - - def call_test(self, name, value, args=None, kwargs=None): - """Invokes a test on a value the same way the compiler does it. - - .. versionadded:: 2.7 - """ - func = self.tests.get(name) - if func is None: - fail_for_missing_callable('no test named %r', name) - return func(value, *(args or ()), **(kwargs or {})) - - @internalcode - def parse(self, source, name=None, filename=None): - """Parse the sourcecode and return the abstract syntax tree. This - tree of nodes is used by the compiler to convert the template into - executable source- or bytecode. This is useful for debugging or to - extract information from templates. - - If you are :ref:`developing Jinja2 extensions ` - this gives you a good overview of the node tree generated. - """ - try: - return self._parse(source, name, filename) - except TemplateSyntaxError: - exc_info = sys.exc_info() - self.handle_exception(exc_info, source_hint=source) - - def _parse(self, source, name, filename): - """Internal parsing function used by `parse` and `compile`.""" - return Parser(self, source, name, encode_filename(filename)).parse() - - def lex(self, source, name=None, filename=None): - """Lex the given sourcecode and return a generator that yields - tokens as tuples in the form ``(lineno, token_type, value)``. - This can be useful for :ref:`extension development ` - and debugging templates. - - This does not perform preprocessing. If you want the preprocessing - of the extensions to be applied you have to filter source through - the :meth:`preprocess` method. - """ - source = text_type(source) - try: - return self.lexer.tokeniter(source, name, filename) - except TemplateSyntaxError: - exc_info = sys.exc_info() - self.handle_exception(exc_info, source_hint=source) - - def preprocess(self, source, name=None, filename=None): - """Preprocesses the source with all extensions. This is automatically - called for all parsing and compiling methods but *not* for :meth:`lex` - because there you usually only want the actual source tokenized. - """ - return reduce(lambda s, e: e.preprocess(s, name, filename), - self.iter_extensions(), text_type(source)) - - def _tokenize(self, source, name, filename=None, state=None): - """Called by the parser to do the preprocessing and filtering - for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. - """ - source = self.preprocess(source, name, filename) - stream = self.lexer.tokenize(source, name, filename, state) - for ext in self.iter_extensions(): - stream = ext.filter_stream(stream) - if not isinstance(stream, TokenStream): - stream = TokenStream(stream, name, filename) - return stream - - def _generate(self, source, name, filename, defer_init=False): - """Internal hook that can be overridden to hook a different generate - method in. - - .. versionadded:: 2.5 - """ - return generate(source, self, name, filename, defer_init=defer_init, - optimized=self.optimized) - - def _compile(self, source, filename): - """Internal hook that can be overridden to hook a different compile - method in. - - .. versionadded:: 2.5 - """ - return compile(source, filename, 'exec') - - @internalcode - def compile(self, source, name=None, filename=None, raw=False, - defer_init=False): - """Compile a node or template source code. The `name` parameter is - the load name of the template after it was joined using - :meth:`join_path` if necessary, not the filename on the file system. - the `filename` parameter is the estimated filename of the template on - the file system. If the template came from a database or memory this - can be omitted. - - The return value of this method is a python code object. If the `raw` - parameter is `True` the return value will be a string with python - code equivalent to the bytecode returned otherwise. This method is - mainly used internally. - - `defer_init` is use internally to aid the module code generator. This - causes the generated code to be able to import without the global - environment variable to be set. - - .. versionadded:: 2.4 - `defer_init` parameter added. - """ - source_hint = None - try: - if isinstance(source, string_types): - source_hint = source - source = self._parse(source, name, filename) - source = self._generate(source, name, filename, - defer_init=defer_init) - if raw: - return source - if filename is None: - filename = '