Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +6 -0
- my_container_sandbox/workspace/anaconda3/bin/x86_64-conda_cos6-linux-gnu-ld +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_csv.cpython-38-x86_64-linux-gnu.so +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_tkinter.cpython-38-x86_64-linux-gnu.so +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/mmap.cpython-38-x86_64-linux-gnu.so +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/unicodedata.cpython-38-x86_64-linux-gnu.so +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/METADATA +232 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/RECORD +57 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/WHEEL +6 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/top_level.txt +2 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/click/_termui_impl.py +717 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/google_auth-2.9.0-py3.10-nspkg.pth +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/__init__.py +2190 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_channel.py +1585 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_common.py +168 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_compression.py +55 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_grpcio_metadata.py +1 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_interceptor.py +562 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_plugin_wrapping.py +113 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_runtime_protos.py +155 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_server.py +1003 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_simple_stubs.py +486 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/_impl.py +101 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/errors.py +141 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/grammar_parser.py +144 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/version.py +13 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3114.py +77 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3281.py +331 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3779.py +137 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5917.py +55 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5934.py +786 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5940.py +59 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc6031.py +469 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7229.py +29 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7585.py +50 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7894.py +92 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/INSTALLER +1 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/LICENSE +25 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/METADATA +1063 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/RECORD +12 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/REQUESTED +0 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/WHEEL +6 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/entry_points.txt +3 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/namespace_packages.txt +1 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/top_level.txt +1 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/__init__.py +180 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/__version__.py +14 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/_internal_utils.py +48 -0
- my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/adapters.py +584 -0
.gitattributes
CHANGED
|
@@ -226,3 +226,9 @@ my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_sha3.cpython
|
|
| 226 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_codecs_jp.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 227 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_decimal.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 228 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/readline.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_codecs_jp.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 227 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_decimal.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 228 |
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/readline.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 229 |
+
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_tkinter.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 230 |
+
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/mmap.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 231 |
+
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_csv.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 232 |
+
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/unicodedata.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 233 |
+
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 234 |
+
my_container_sandbox/workspace/anaconda3/bin/x86_64-conda_cos6-linux-gnu-ld filter=lfs diff=lfs merge=lfs -text
|
my_container_sandbox/workspace/anaconda3/bin/x86_64-conda_cos6-linux-gnu-ld
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:db98363adc9b1f3f785009e63bc77617093f5841ce0736b0407fc4bf66a30ab9
|
| 3 |
+
size 2568888
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_csv.cpython-38-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b589b745b5e75b99f3e76ced322e018482546477129c6a26ab08d1634b2b2cfe
|
| 3 |
+
size 121936
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/_tkinter.cpython-38-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:832b13f4e094686c809adb072054d79139f80531479ab8dd90efe991c76d1691
|
| 3 |
+
size 221992
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/math.cpython-38-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6788eb7b2bc17778d5694e2d0100dd6c74e955f0740c55f48f8da2c997ba2420
|
| 3 |
+
size 253424
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/mmap.cpython-38-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:58be3da0f728647b97e53afa534e95e42ac7731b8cb014371d0f53eee118ac3f
|
| 3 |
+
size 104664
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/lib-dynload/unicodedata.cpython-38-x86_64-linux-gnu.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a4a47c7a22336b3de31509eaa3e60a65daf3d486a1deef81610fc2f3d163eb0c
|
| 3 |
+
size 1170032
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.1
|
| 2 |
+
Name: attrs
|
| 3 |
+
Version: 21.4.0
|
| 4 |
+
Summary: Classes Without Boilerplate
|
| 5 |
+
Home-page: https://www.attrs.org/
|
| 6 |
+
Author: Hynek Schlawack
|
| 7 |
+
Author-email: hs@ox.cx
|
| 8 |
+
Maintainer: Hynek Schlawack
|
| 9 |
+
Maintainer-email: hs@ox.cx
|
| 10 |
+
License: MIT
|
| 11 |
+
Project-URL: Documentation, https://www.attrs.org/
|
| 12 |
+
Project-URL: Changelog, https://www.attrs.org/en/stable/changelog.html
|
| 13 |
+
Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues
|
| 14 |
+
Project-URL: Source Code, https://github.com/python-attrs/attrs
|
| 15 |
+
Project-URL: Funding, https://github.com/sponsors/hynek
|
| 16 |
+
Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi
|
| 17 |
+
Project-URL: Ko-fi, https://ko-fi.com/the_hynek
|
| 18 |
+
Keywords: class,attribute,boilerplate
|
| 19 |
+
Platform: UNKNOWN
|
| 20 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 21 |
+
Classifier: Intended Audience :: Developers
|
| 22 |
+
Classifier: Natural Language :: English
|
| 23 |
+
Classifier: License :: OSI Approved :: MIT License
|
| 24 |
+
Classifier: Operating System :: OS Independent
|
| 25 |
+
Classifier: Programming Language :: Python
|
| 26 |
+
Classifier: Programming Language :: Python :: 2
|
| 27 |
+
Classifier: Programming Language :: Python :: 2.7
|
| 28 |
+
Classifier: Programming Language :: Python :: 3
|
| 29 |
+
Classifier: Programming Language :: Python :: 3.5
|
| 30 |
+
Classifier: Programming Language :: Python :: 3.6
|
| 31 |
+
Classifier: Programming Language :: Python :: 3.7
|
| 32 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 33 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 34 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 35 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 36 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 37 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
| 38 |
+
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
| 39 |
+
Description-Content-Type: text/x-rst
|
| 40 |
+
License-File: LICENSE
|
| 41 |
+
License-File: AUTHORS.rst
|
| 42 |
+
Provides-Extra: dev
|
| 43 |
+
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'dev'
|
| 44 |
+
Requires-Dist: hypothesis ; extra == 'dev'
|
| 45 |
+
Requires-Dist: pympler ; extra == 'dev'
|
| 46 |
+
Requires-Dist: pytest (>=4.3.0) ; extra == 'dev'
|
| 47 |
+
Requires-Dist: six ; extra == 'dev'
|
| 48 |
+
Requires-Dist: mypy ; extra == 'dev'
|
| 49 |
+
Requires-Dist: pytest-mypy-plugins ; extra == 'dev'
|
| 50 |
+
Requires-Dist: zope.interface ; extra == 'dev'
|
| 51 |
+
Requires-Dist: furo ; extra == 'dev'
|
| 52 |
+
Requires-Dist: sphinx ; extra == 'dev'
|
| 53 |
+
Requires-Dist: sphinx-notfound-page ; extra == 'dev'
|
| 54 |
+
Requires-Dist: pre-commit ; extra == 'dev'
|
| 55 |
+
Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'dev'
|
| 56 |
+
Provides-Extra: docs
|
| 57 |
+
Requires-Dist: furo ; extra == 'docs'
|
| 58 |
+
Requires-Dist: sphinx ; extra == 'docs'
|
| 59 |
+
Requires-Dist: zope.interface ; extra == 'docs'
|
| 60 |
+
Requires-Dist: sphinx-notfound-page ; extra == 'docs'
|
| 61 |
+
Provides-Extra: tests
|
| 62 |
+
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests'
|
| 63 |
+
Requires-Dist: hypothesis ; extra == 'tests'
|
| 64 |
+
Requires-Dist: pympler ; extra == 'tests'
|
| 65 |
+
Requires-Dist: pytest (>=4.3.0) ; extra == 'tests'
|
| 66 |
+
Requires-Dist: six ; extra == 'tests'
|
| 67 |
+
Requires-Dist: mypy ; extra == 'tests'
|
| 68 |
+
Requires-Dist: pytest-mypy-plugins ; extra == 'tests'
|
| 69 |
+
Requires-Dist: zope.interface ; extra == 'tests'
|
| 70 |
+
Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'tests'
|
| 71 |
+
Provides-Extra: tests_no_zope
|
| 72 |
+
Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope'
|
| 73 |
+
Requires-Dist: hypothesis ; extra == 'tests_no_zope'
|
| 74 |
+
Requires-Dist: pympler ; extra == 'tests_no_zope'
|
| 75 |
+
Requires-Dist: pytest (>=4.3.0) ; extra == 'tests_no_zope'
|
| 76 |
+
Requires-Dist: six ; extra == 'tests_no_zope'
|
| 77 |
+
Requires-Dist: mypy ; extra == 'tests_no_zope'
|
| 78 |
+
Requires-Dist: pytest-mypy-plugins ; extra == 'tests_no_zope'
|
| 79 |
+
Requires-Dist: cloudpickle ; (platform_python_implementation == "CPython") and extra == 'tests_no_zope'
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
.. image:: https://www.attrs.org/en/stable/_static/attrs_logo.png
|
| 83 |
+
:alt: attrs logo
|
| 84 |
+
:align: center
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
``attrs`` is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka `dunder methods <https://www.attrs.org/en/latest/glossary.html#term-dunder-methods>`_).
|
| 88 |
+
`Trusted by NASA <https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-badge>`_ for Mars missions since 2020!
|
| 89 |
+
|
| 90 |
+
Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
|
| 91 |
+
|
| 92 |
+
.. teaser-end
|
| 93 |
+
|
| 94 |
+
For that, it gives you a class decorator and a way to declaratively define the attributes on that class:
|
| 95 |
+
|
| 96 |
+
.. -code-begin-
|
| 97 |
+
|
| 98 |
+
.. code-block:: pycon
|
| 99 |
+
|
| 100 |
+
>>> from attrs import asdict, define, make_class, Factory
|
| 101 |
+
|
| 102 |
+
>>> @define
|
| 103 |
+
... class SomeClass:
|
| 104 |
+
... a_number: int = 42
|
| 105 |
+
... list_of_numbers: list[int] = Factory(list)
|
| 106 |
+
...
|
| 107 |
+
... def hard_math(self, another_number):
|
| 108 |
+
... return self.a_number + sum(self.list_of_numbers) * another_number
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
>>> sc = SomeClass(1, [1, 2, 3])
|
| 112 |
+
>>> sc
|
| 113 |
+
SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
|
| 114 |
+
|
| 115 |
+
>>> sc.hard_math(3)
|
| 116 |
+
19
|
| 117 |
+
>>> sc == SomeClass(1, [1, 2, 3])
|
| 118 |
+
True
|
| 119 |
+
>>> sc != SomeClass(2, [3, 2, 1])
|
| 120 |
+
True
|
| 121 |
+
|
| 122 |
+
>>> asdict(sc)
|
| 123 |
+
{'a_number': 1, 'list_of_numbers': [1, 2, 3]}
|
| 124 |
+
|
| 125 |
+
>>> SomeClass()
|
| 126 |
+
SomeClass(a_number=42, list_of_numbers=[])
|
| 127 |
+
|
| 128 |
+
>>> C = make_class("C", ["a", "b"])
|
| 129 |
+
>>> C("foo", "bar")
|
| 130 |
+
C(a='foo', b='bar')
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
After *declaring* your attributes ``attrs`` gives you:
|
| 134 |
+
|
| 135 |
+
- a concise and explicit overview of the class's attributes,
|
| 136 |
+
- a nice human-readable ``__repr__``,
|
| 137 |
+
- a equality-checking methods,
|
| 138 |
+
- an initializer,
|
| 139 |
+
- and much more,
|
| 140 |
+
|
| 141 |
+
*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
|
| 142 |
+
|
| 143 |
+
**Hate type annotations**!?
|
| 144 |
+
No problem!
|
| 145 |
+
Types are entirely **optional** with ``attrs``.
|
| 146 |
+
Simply assign ``attrs.field()`` to the attributes instead of annotating them with types.
|
| 147 |
+
|
| 148 |
+
----
|
| 149 |
+
|
| 150 |
+
This example uses ``attrs``'s modern APIs that have been introduced in version 20.1.0, and the ``attrs`` package import name that has been added in version 21.3.0.
|
| 151 |
+
The classic APIs (``@attr.s``, ``attr.ib``, plus their serious business aliases) and the ``attr`` package import name will remain **indefinitely**.
|
| 152 |
+
|
| 153 |
+
Please check out `On The Core API Names <https://www.attrs.org/en/latest/names.html>`_ for a more in-depth explanation.
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
Data Classes
|
| 157 |
+
============
|
| 158 |
+
|
| 159 |
+
On the tin, ``attrs`` might remind you of ``dataclasses`` (and indeed, ``dataclasses`` are a descendant of ``attrs``).
|
| 160 |
+
In practice it does a lot more and is more flexible.
|
| 161 |
+
For instance it allows you to define `special handling of NumPy arrays for equality checks <https://www.attrs.org/en/stable/comparison.html#customization>`_, or allows more ways to `plug into the initialization process <https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization>`_.
|
| 162 |
+
|
| 163 |
+
For more details, please refer to our `comparison page <https://www.attrs.org/en/stable/why.html#data-classes>`_.
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
.. -getting-help-
|
| 167 |
+
|
| 168 |
+
Getting Help
|
| 169 |
+
============
|
| 170 |
+
|
| 171 |
+
Please use the ``python-attrs`` tag on `Stack Overflow <https://stackoverflow.com/questions/tagged/python-attrs>`_ to get help.
|
| 172 |
+
|
| 173 |
+
Answering questions of your fellow developers is also a great way to help the project!
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
.. -project-information-
|
| 177 |
+
|
| 178 |
+
Project Information
|
| 179 |
+
===================
|
| 180 |
+
|
| 181 |
+
``attrs`` is released under the `MIT <https://choosealicense.com/licenses/mit/>`_ license,
|
| 182 |
+
its documentation lives at `Read the Docs <https://www.attrs.org/>`_,
|
| 183 |
+
the code on `GitHub <https://github.com/python-attrs/attrs>`_,
|
| 184 |
+
and the latest release on `PyPI <https://pypi.org/project/attrs/>`_.
|
| 185 |
+
It’s rigorously tested on Python 2.7, 3.5+, and PyPy.
|
| 186 |
+
|
| 187 |
+
We collect information on **third-party extensions** in our `wiki <https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs>`_.
|
| 188 |
+
Feel free to browse and add your own!
|
| 189 |
+
|
| 190 |
+
If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide <https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md>`_ to get you started!
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
``attrs`` for Enterprise
|
| 194 |
+
------------------------
|
| 195 |
+
|
| 196 |
+
Available as part of the Tidelift Subscription.
|
| 197 |
+
|
| 198 |
+
The maintainers of ``attrs`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.
|
| 199 |
+
Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
|
| 200 |
+
`Learn more. <https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`_
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
Release Information
|
| 204 |
+
===================
|
| 205 |
+
|
| 206 |
+
21.4.0 (2021-12-29)
|
| 207 |
+
-------------------
|
| 208 |
+
|
| 209 |
+
Changes
|
| 210 |
+
^^^^^^^
|
| 211 |
+
|
| 212 |
+
- Fixed the test suite on PyPy3.8 where ``cloudpickle`` does not work.
|
| 213 |
+
`#892 <https://github.com/python-attrs/attrs/issues/892>`_
|
| 214 |
+
- Fixed ``coverage report`` for projects that use ``attrs`` and don't set a ``--source``.
|
| 215 |
+
`#895 <https://github.com/python-attrs/attrs/issues/895>`_,
|
| 216 |
+
`#896 <https://github.com/python-attrs/attrs/issues/896>`_
|
| 217 |
+
|
| 218 |
+
`Full changelog <https://www.attrs.org/en/stable/changelog.html>`_.
|
| 219 |
+
|
| 220 |
+
Credits
|
| 221 |
+
=======
|
| 222 |
+
|
| 223 |
+
``attrs`` is written and maintained by `Hynek Schlawack <https://hynek.me/>`_.
|
| 224 |
+
|
| 225 |
+
The development is kindly supported by `Variomedia AG <https://www.variomedia.de/>`_.
|
| 226 |
+
|
| 227 |
+
A full list of contributors can be found in `GitHub's overview <https://github.com/python-attrs/attrs/graphs/contributors>`_.
|
| 228 |
+
|
| 229 |
+
It’s the spiritual successor of `characteristic <https://characteristic.readthedocs.io/>`_ and aspires to fix some of it clunkiness and unfortunate decisions.
|
| 230 |
+
Both were inspired by Twisted’s `FancyEqMixin <https://twistedmatrix.com/documents/current/api/twisted.python.util.FancyEqMixin.html>`_ but both are implemented using class decorators because `subclassing is bad for you <https://www.youtube.com/watch?v=3MNVP9-hglc>`_, m’kay?
|
| 231 |
+
|
| 232 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
attr/__init__.py,sha256=_zhJ4O8Q5KR5gaIrjX73vkR5nA6NjfpMGXQChEdNljI,1667
|
| 2 |
+
attr/__init__.pyi,sha256=ubRkstoRHPpQN17iA0OCh8waIwZ5NeJgbz0lwI8XUjY,15100
|
| 3 |
+
attr/__pycache__/__init__.cpython-38.pyc,,
|
| 4 |
+
attr/__pycache__/_cmp.cpython-38.pyc,,
|
| 5 |
+
attr/__pycache__/_compat.cpython-38.pyc,,
|
| 6 |
+
attr/__pycache__/_config.cpython-38.pyc,,
|
| 7 |
+
attr/__pycache__/_funcs.cpython-38.pyc,,
|
| 8 |
+
attr/__pycache__/_make.cpython-38.pyc,,
|
| 9 |
+
attr/__pycache__/_next_gen.cpython-38.pyc,,
|
| 10 |
+
attr/__pycache__/_version_info.cpython-38.pyc,,
|
| 11 |
+
attr/__pycache__/converters.cpython-38.pyc,,
|
| 12 |
+
attr/__pycache__/exceptions.cpython-38.pyc,,
|
| 13 |
+
attr/__pycache__/filters.cpython-38.pyc,,
|
| 14 |
+
attr/__pycache__/setters.cpython-38.pyc,,
|
| 15 |
+
attr/__pycache__/validators.cpython-38.pyc,,
|
| 16 |
+
attr/_cmp.py,sha256=JP0N7OIyTqIR3prUDfMZOR4DV4tlV_xXf39-bQg7xOo,4165
|
| 17 |
+
attr/_cmp.pyi,sha256=oyjJVytrwwkUJOoe332IiYzp6pCVZEKKcKveH-ev604,317
|
| 18 |
+
attr/_compat.py,sha256=i8u27AAK_4SzQnmTf3aliGV27UdYbJxdZ-O0tOHbLU8,8396
|
| 19 |
+
attr/_config.py,sha256=aj1Lh8t2CuVa5nSxgCrLQtg_ZSdO8ZKeNJQd6RvpIp8,892
|
| 20 |
+
attr/_funcs.py,sha256=sm_D12y2IyRW_bCnR7M-O7U5qHaieXr0BzINwJ7_K38,14753
|
| 21 |
+
attr/_make.py,sha256=D05j0_ckcVIRFn2xHch5SPUCwh3t7WpeFj-3Ku9SocQ,102736
|
| 22 |
+
attr/_next_gen.py,sha256=s5jCsVEQ4IhOjAykP4N0ETaWpg0RsgQttMvEZErUrhQ,5752
|
| 23 |
+
attr/_version_info.py,sha256=sxD9yNai0jGbur_-RGEQHbgV2YX5_5G9PhrhBA5pA54,2194
|
| 24 |
+
attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209
|
| 25 |
+
attr/converters.py,sha256=uiiWTz8GLJe8I1Ty7UICK1DegVUnqHTXbOSnar7g7Nk,4078
|
| 26 |
+
attr/converters.pyi,sha256=MQo7iEzPNVoFpKqD30sVwgVpdNoIeSCF2nsXvoxLZ-Y,416
|
| 27 |
+
attr/exceptions.py,sha256=BMg7AljkJnvG-irMwL2TBHYlaLBXhSKnzoEWo4e42Zw,1981
|
| 28 |
+
attr/exceptions.pyi,sha256=zZq8bCUnKAy9mDtBEw42ZhPhAUIHoTKedDQInJD883M,539
|
| 29 |
+
attr/filters.py,sha256=JGZgvPGkdOfttkoL6XhXS6ZCoaVV5nZ8GCYeZNUN_mE,1124
|
| 30 |
+
attr/filters.pyi,sha256=_Sm80jGySETX_Clzdkon5NHVjQWRl3Y3liQKZX1czXc,215
|
| 31 |
+
attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 32 |
+
attr/setters.py,sha256=rH_UtQuHgQEC7hfZyMO_SJW0R1Gus7-a83U8igZfqs8,1466
|
| 33 |
+
attr/setters.pyi,sha256=7dM10rqpQVDW0y-iJUnq8rabdO5Wx2Sbo5LwNa0IXl0,573
|
| 34 |
+
attr/validators.py,sha256=jVE9roaSOmTf0dJNSLHNaQNilkrlzc3pNNBKmv0g7pk,15966
|
| 35 |
+
attr/validators.pyi,sha256=adn6rNbIXmRXlg_FKrTmWj0dOX0vKTsGG82Jd3YcJbQ,2268
|
| 36 |
+
attrs-21.4.0.dist-info/AUTHORS.rst,sha256=wsqCNbGz_mklcJrt54APIZHZpoTIJLkXqEhhn4Nd8hc,752
|
| 37 |
+
attrs-21.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 38 |
+
attrs-21.4.0.dist-info/LICENSE,sha256=v2WaKLSSQGAvVrvfSQy-LsUJsVuY-Z17GaUsdA4yeGM,1082
|
| 39 |
+
attrs-21.4.0.dist-info/METADATA,sha256=WwgR4MfxE55PpGGv21UOEOEtXZGCqwekfXYg-JgA5HY,9810
|
| 40 |
+
attrs-21.4.0.dist-info/RECORD,,
|
| 41 |
+
attrs-21.4.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 42 |
+
attrs-21.4.0.dist-info/WHEEL,sha256=z9j0xAa_JmUKMpmz72K0ZGALSM_n-wQVmGbleXx2VHg,110
|
| 43 |
+
attrs-21.4.0.dist-info/top_level.txt,sha256=AGbmKnOtYpdkLRsDRQVSBIwfL32pAQ6BSo1mt-BxI7M,11
|
| 44 |
+
attrs/__init__.py,sha256=CeyxLGVViAEKKsLOLaif8vF3vs1a28vsrRVLv7eMEgM,1109
|
| 45 |
+
attrs/__init__.pyi,sha256=57aCxUJukK9lZlrUgk9RuWiBiPY5DzDKJAJkhbrStYw,1982
|
| 46 |
+
attrs/__pycache__/__init__.cpython-38.pyc,,
|
| 47 |
+
attrs/__pycache__/converters.cpython-38.pyc,,
|
| 48 |
+
attrs/__pycache__/exceptions.cpython-38.pyc,,
|
| 49 |
+
attrs/__pycache__/filters.cpython-38.pyc,,
|
| 50 |
+
attrs/__pycache__/setters.cpython-38.pyc,,
|
| 51 |
+
attrs/__pycache__/validators.cpython-38.pyc,,
|
| 52 |
+
attrs/converters.py,sha256=fCBEdlYWcmI3sCnpUk2pz22GYtXzqTkp6NeOpdI64PY,70
|
| 53 |
+
attrs/exceptions.py,sha256=SlDli6AY77f6ny-H7oy98OkQjsrw-D_supEuErIVYkE,70
|
| 54 |
+
attrs/filters.py,sha256=dc_dNey29kH6KLU1mT2Dakq7tZ3kBfzEGwzOmDzw1F8,67
|
| 55 |
+
attrs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 56 |
+
attrs/setters.py,sha256=oKw51C72Hh45wTwYvDHJP9kbicxiMhMR4Y5GvdpKdHQ,67
|
| 57 |
+
attrs/validators.py,sha256=4ag1SyVD2Hm3PYKiNG_NOtR_e7f81Hr6GiNl4YvXo4Q,70
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: bdist_wheel (0.37.1)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py2-none-any
|
| 5 |
+
Tag: py3-none-any
|
| 6 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/attrs-21.4.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
attr
|
| 2 |
+
attrs
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/click/_termui_impl.py
ADDED
|
@@ -0,0 +1,717 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
This module contains implementations for the termui module. To keep the
|
| 3 |
+
import time of Click down, some infrequently used functionality is
|
| 4 |
+
placed in this module and only imported as needed.
|
| 5 |
+
"""
|
| 6 |
+
import contextlib
|
| 7 |
+
import math
|
| 8 |
+
import os
|
| 9 |
+
import sys
|
| 10 |
+
import time
|
| 11 |
+
import typing as t
|
| 12 |
+
from gettext import gettext as _
|
| 13 |
+
|
| 14 |
+
from ._compat import _default_text_stdout
|
| 15 |
+
from ._compat import CYGWIN
|
| 16 |
+
from ._compat import get_best_encoding
|
| 17 |
+
from ._compat import isatty
|
| 18 |
+
from ._compat import open_stream
|
| 19 |
+
from ._compat import strip_ansi
|
| 20 |
+
from ._compat import term_len
|
| 21 |
+
from ._compat import WIN
|
| 22 |
+
from .exceptions import ClickException
|
| 23 |
+
from .utils import echo
|
| 24 |
+
|
| 25 |
+
V = t.TypeVar("V")
|
| 26 |
+
|
| 27 |
+
if os.name == "nt":
|
| 28 |
+
BEFORE_BAR = "\r"
|
| 29 |
+
AFTER_BAR = "\n"
|
| 30 |
+
else:
|
| 31 |
+
BEFORE_BAR = "\r\033[?25l"
|
| 32 |
+
AFTER_BAR = "\033[?25h\n"
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class ProgressBar(t.Generic[V]):
|
| 36 |
+
def __init__(
|
| 37 |
+
self,
|
| 38 |
+
iterable: t.Optional[t.Iterable[V]],
|
| 39 |
+
length: t.Optional[int] = None,
|
| 40 |
+
fill_char: str = "#",
|
| 41 |
+
empty_char: str = " ",
|
| 42 |
+
bar_template: str = "%(bar)s",
|
| 43 |
+
info_sep: str = " ",
|
| 44 |
+
show_eta: bool = True,
|
| 45 |
+
show_percent: t.Optional[bool] = None,
|
| 46 |
+
show_pos: bool = False,
|
| 47 |
+
item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None,
|
| 48 |
+
label: t.Optional[str] = None,
|
| 49 |
+
file: t.Optional[t.TextIO] = None,
|
| 50 |
+
color: t.Optional[bool] = None,
|
| 51 |
+
update_min_steps: int = 1,
|
| 52 |
+
width: int = 30,
|
| 53 |
+
) -> None:
|
| 54 |
+
self.fill_char = fill_char
|
| 55 |
+
self.empty_char = empty_char
|
| 56 |
+
self.bar_template = bar_template
|
| 57 |
+
self.info_sep = info_sep
|
| 58 |
+
self.show_eta = show_eta
|
| 59 |
+
self.show_percent = show_percent
|
| 60 |
+
self.show_pos = show_pos
|
| 61 |
+
self.item_show_func = item_show_func
|
| 62 |
+
self.label = label or ""
|
| 63 |
+
if file is None:
|
| 64 |
+
file = _default_text_stdout()
|
| 65 |
+
self.file = file
|
| 66 |
+
self.color = color
|
| 67 |
+
self.update_min_steps = update_min_steps
|
| 68 |
+
self._completed_intervals = 0
|
| 69 |
+
self.width = width
|
| 70 |
+
self.autowidth = width == 0
|
| 71 |
+
|
| 72 |
+
if length is None:
|
| 73 |
+
from operator import length_hint
|
| 74 |
+
|
| 75 |
+
length = length_hint(iterable, -1)
|
| 76 |
+
|
| 77 |
+
if length == -1:
|
| 78 |
+
length = None
|
| 79 |
+
if iterable is None:
|
| 80 |
+
if length is None:
|
| 81 |
+
raise TypeError("iterable or length is required")
|
| 82 |
+
iterable = t.cast(t.Iterable[V], range(length))
|
| 83 |
+
self.iter = iter(iterable)
|
| 84 |
+
self.length = length
|
| 85 |
+
self.pos = 0
|
| 86 |
+
self.avg: t.List[float] = []
|
| 87 |
+
self.start = self.last_eta = time.time()
|
| 88 |
+
self.eta_known = False
|
| 89 |
+
self.finished = False
|
| 90 |
+
self.max_width: t.Optional[int] = None
|
| 91 |
+
self.entered = False
|
| 92 |
+
self.current_item: t.Optional[V] = None
|
| 93 |
+
self.is_hidden = not isatty(self.file)
|
| 94 |
+
self._last_line: t.Optional[str] = None
|
| 95 |
+
|
| 96 |
+
def __enter__(self) -> "ProgressBar":
|
| 97 |
+
self.entered = True
|
| 98 |
+
self.render_progress()
|
| 99 |
+
return self
|
| 100 |
+
|
| 101 |
+
def __exit__(self, exc_type, exc_value, tb): # type: ignore
|
| 102 |
+
self.render_finish()
|
| 103 |
+
|
| 104 |
+
def __iter__(self) -> t.Iterator[V]:
|
| 105 |
+
if not self.entered:
|
| 106 |
+
raise RuntimeError("You need to use progress bars in a with block.")
|
| 107 |
+
self.render_progress()
|
| 108 |
+
return self.generator()
|
| 109 |
+
|
| 110 |
+
def __next__(self) -> V:
|
| 111 |
+
# Iteration is defined in terms of a generator function,
|
| 112 |
+
# returned by iter(self); use that to define next(). This works
|
| 113 |
+
# because `self.iter` is an iterable consumed by that generator,
|
| 114 |
+
# so it is re-entry safe. Calling `next(self.generator())`
|
| 115 |
+
# twice works and does "what you want".
|
| 116 |
+
return next(iter(self))
|
| 117 |
+
|
| 118 |
+
def render_finish(self) -> None:
|
| 119 |
+
if self.is_hidden:
|
| 120 |
+
return
|
| 121 |
+
self.file.write(AFTER_BAR)
|
| 122 |
+
self.file.flush()
|
| 123 |
+
|
| 124 |
+
@property
|
| 125 |
+
def pct(self) -> float:
|
| 126 |
+
if self.finished:
|
| 127 |
+
return 1.0
|
| 128 |
+
return min(self.pos / (float(self.length or 1) or 1), 1.0)
|
| 129 |
+
|
| 130 |
+
@property
|
| 131 |
+
def time_per_iteration(self) -> float:
|
| 132 |
+
if not self.avg:
|
| 133 |
+
return 0.0
|
| 134 |
+
return sum(self.avg) / float(len(self.avg))
|
| 135 |
+
|
| 136 |
+
@property
|
| 137 |
+
def eta(self) -> float:
|
| 138 |
+
if self.length is not None and not self.finished:
|
| 139 |
+
return self.time_per_iteration * (self.length - self.pos)
|
| 140 |
+
return 0.0
|
| 141 |
+
|
| 142 |
+
def format_eta(self) -> str:
|
| 143 |
+
if self.eta_known:
|
| 144 |
+
t = int(self.eta)
|
| 145 |
+
seconds = t % 60
|
| 146 |
+
t //= 60
|
| 147 |
+
minutes = t % 60
|
| 148 |
+
t //= 60
|
| 149 |
+
hours = t % 24
|
| 150 |
+
t //= 24
|
| 151 |
+
if t > 0:
|
| 152 |
+
return f"{t}d {hours:02}:{minutes:02}:{seconds:02}"
|
| 153 |
+
else:
|
| 154 |
+
return f"{hours:02}:{minutes:02}:{seconds:02}"
|
| 155 |
+
return ""
|
| 156 |
+
|
| 157 |
+
def format_pos(self) -> str:
|
| 158 |
+
pos = str(self.pos)
|
| 159 |
+
if self.length is not None:
|
| 160 |
+
pos += f"/{self.length}"
|
| 161 |
+
return pos
|
| 162 |
+
|
| 163 |
+
def format_pct(self) -> str:
|
| 164 |
+
return f"{int(self.pct * 100): 4}%"[1:]
|
| 165 |
+
|
| 166 |
+
def format_bar(self) -> str:
|
| 167 |
+
if self.length is not None:
|
| 168 |
+
bar_length = int(self.pct * self.width)
|
| 169 |
+
bar = self.fill_char * bar_length
|
| 170 |
+
bar += self.empty_char * (self.width - bar_length)
|
| 171 |
+
elif self.finished:
|
| 172 |
+
bar = self.fill_char * self.width
|
| 173 |
+
else:
|
| 174 |
+
chars = list(self.empty_char * (self.width or 1))
|
| 175 |
+
if self.time_per_iteration != 0:
|
| 176 |
+
chars[
|
| 177 |
+
int(
|
| 178 |
+
(math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5)
|
| 179 |
+
* self.width
|
| 180 |
+
)
|
| 181 |
+
] = self.fill_char
|
| 182 |
+
bar = "".join(chars)
|
| 183 |
+
return bar
|
| 184 |
+
|
| 185 |
+
def format_progress_line(self) -> str:
|
| 186 |
+
show_percent = self.show_percent
|
| 187 |
+
|
| 188 |
+
info_bits = []
|
| 189 |
+
if self.length is not None and show_percent is None:
|
| 190 |
+
show_percent = not self.show_pos
|
| 191 |
+
|
| 192 |
+
if self.show_pos:
|
| 193 |
+
info_bits.append(self.format_pos())
|
| 194 |
+
if show_percent:
|
| 195 |
+
info_bits.append(self.format_pct())
|
| 196 |
+
if self.show_eta and self.eta_known and not self.finished:
|
| 197 |
+
info_bits.append(self.format_eta())
|
| 198 |
+
if self.item_show_func is not None:
|
| 199 |
+
item_info = self.item_show_func(self.current_item)
|
| 200 |
+
if item_info is not None:
|
| 201 |
+
info_bits.append(item_info)
|
| 202 |
+
|
| 203 |
+
return (
|
| 204 |
+
self.bar_template
|
| 205 |
+
% {
|
| 206 |
+
"label": self.label,
|
| 207 |
+
"bar": self.format_bar(),
|
| 208 |
+
"info": self.info_sep.join(info_bits),
|
| 209 |
+
}
|
| 210 |
+
).rstrip()
|
| 211 |
+
|
| 212 |
+
def render_progress(self) -> None:
|
| 213 |
+
import shutil
|
| 214 |
+
|
| 215 |
+
if self.is_hidden:
|
| 216 |
+
# Only output the label as it changes if the output is not a
|
| 217 |
+
# TTY. Use file=stderr if you expect to be piping stdout.
|
| 218 |
+
if self._last_line != self.label:
|
| 219 |
+
self._last_line = self.label
|
| 220 |
+
echo(self.label, file=self.file, color=self.color)
|
| 221 |
+
|
| 222 |
+
return
|
| 223 |
+
|
| 224 |
+
buf = []
|
| 225 |
+
# Update width in case the terminal has been resized
|
| 226 |
+
if self.autowidth:
|
| 227 |
+
old_width = self.width
|
| 228 |
+
self.width = 0
|
| 229 |
+
clutter_length = term_len(self.format_progress_line())
|
| 230 |
+
new_width = max(0, shutil.get_terminal_size().columns - clutter_length)
|
| 231 |
+
if new_width < old_width:
|
| 232 |
+
buf.append(BEFORE_BAR)
|
| 233 |
+
buf.append(" " * self.max_width) # type: ignore
|
| 234 |
+
self.max_width = new_width
|
| 235 |
+
self.width = new_width
|
| 236 |
+
|
| 237 |
+
clear_width = self.width
|
| 238 |
+
if self.max_width is not None:
|
| 239 |
+
clear_width = self.max_width
|
| 240 |
+
|
| 241 |
+
buf.append(BEFORE_BAR)
|
| 242 |
+
line = self.format_progress_line()
|
| 243 |
+
line_len = term_len(line)
|
| 244 |
+
if self.max_width is None or self.max_width < line_len:
|
| 245 |
+
self.max_width = line_len
|
| 246 |
+
|
| 247 |
+
buf.append(line)
|
| 248 |
+
buf.append(" " * (clear_width - line_len))
|
| 249 |
+
line = "".join(buf)
|
| 250 |
+
# Render the line only if it changed.
|
| 251 |
+
|
| 252 |
+
if line != self._last_line:
|
| 253 |
+
self._last_line = line
|
| 254 |
+
echo(line, file=self.file, color=self.color, nl=False)
|
| 255 |
+
self.file.flush()
|
| 256 |
+
|
| 257 |
+
def make_step(self, n_steps: int) -> None:
|
| 258 |
+
self.pos += n_steps
|
| 259 |
+
if self.length is not None and self.pos >= self.length:
|
| 260 |
+
self.finished = True
|
| 261 |
+
|
| 262 |
+
if (time.time() - self.last_eta) < 1.0:
|
| 263 |
+
return
|
| 264 |
+
|
| 265 |
+
self.last_eta = time.time()
|
| 266 |
+
|
| 267 |
+
# self.avg is a rolling list of length <= 7 of steps where steps are
|
| 268 |
+
# defined as time elapsed divided by the total progress through
|
| 269 |
+
# self.length.
|
| 270 |
+
if self.pos:
|
| 271 |
+
step = (time.time() - self.start) / self.pos
|
| 272 |
+
else:
|
| 273 |
+
step = time.time() - self.start
|
| 274 |
+
|
| 275 |
+
self.avg = self.avg[-6:] + [step]
|
| 276 |
+
|
| 277 |
+
self.eta_known = self.length is not None
|
| 278 |
+
|
| 279 |
+
def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None:
|
| 280 |
+
"""Update the progress bar by advancing a specified number of
|
| 281 |
+
steps, and optionally set the ``current_item`` for this new
|
| 282 |
+
position.
|
| 283 |
+
|
| 284 |
+
:param n_steps: Number of steps to advance.
|
| 285 |
+
:param current_item: Optional item to set as ``current_item``
|
| 286 |
+
for the updated position.
|
| 287 |
+
|
| 288 |
+
.. versionchanged:: 8.0
|
| 289 |
+
Added the ``current_item`` optional parameter.
|
| 290 |
+
|
| 291 |
+
.. versionchanged:: 8.0
|
| 292 |
+
Only render when the number of steps meets the
|
| 293 |
+
``update_min_steps`` threshold.
|
| 294 |
+
"""
|
| 295 |
+
if current_item is not None:
|
| 296 |
+
self.current_item = current_item
|
| 297 |
+
|
| 298 |
+
self._completed_intervals += n_steps
|
| 299 |
+
|
| 300 |
+
if self._completed_intervals >= self.update_min_steps:
|
| 301 |
+
self.make_step(self._completed_intervals)
|
| 302 |
+
self.render_progress()
|
| 303 |
+
self._completed_intervals = 0
|
| 304 |
+
|
| 305 |
+
def finish(self) -> None:
|
| 306 |
+
self.eta_known = False
|
| 307 |
+
self.current_item = None
|
| 308 |
+
self.finished = True
|
| 309 |
+
|
| 310 |
+
def generator(self) -> t.Iterator[V]:
|
| 311 |
+
"""Return a generator which yields the items added to the bar
|
| 312 |
+
during construction, and updates the progress bar *after* the
|
| 313 |
+
yielded block returns.
|
| 314 |
+
"""
|
| 315 |
+
# WARNING: the iterator interface for `ProgressBar` relies on
|
| 316 |
+
# this and only works because this is a simple generator which
|
| 317 |
+
# doesn't create or manage additional state. If this function
|
| 318 |
+
# changes, the impact should be evaluated both against
|
| 319 |
+
# `iter(bar)` and `next(bar)`. `next()` in particular may call
|
| 320 |
+
# `self.generator()` repeatedly, and this must remain safe in
|
| 321 |
+
# order for that interface to work.
|
| 322 |
+
if not self.entered:
|
| 323 |
+
raise RuntimeError("You need to use progress bars in a with block.")
|
| 324 |
+
|
| 325 |
+
if self.is_hidden:
|
| 326 |
+
yield from self.iter
|
| 327 |
+
else:
|
| 328 |
+
for rv in self.iter:
|
| 329 |
+
self.current_item = rv
|
| 330 |
+
|
| 331 |
+
# This allows show_item_func to be updated before the
|
| 332 |
+
# item is processed. Only trigger at the beginning of
|
| 333 |
+
# the update interval.
|
| 334 |
+
if self._completed_intervals == 0:
|
| 335 |
+
self.render_progress()
|
| 336 |
+
|
| 337 |
+
yield rv
|
| 338 |
+
self.update(1)
|
| 339 |
+
|
| 340 |
+
self.finish()
|
| 341 |
+
self.render_progress()
|
| 342 |
+
|
| 343 |
+
|
| 344 |
+
def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None:
|
| 345 |
+
"""Decide what method to use for paging through text."""
|
| 346 |
+
stdout = _default_text_stdout()
|
| 347 |
+
if not isatty(sys.stdin) or not isatty(stdout):
|
| 348 |
+
return _nullpager(stdout, generator, color)
|
| 349 |
+
pager_cmd = (os.environ.get("PAGER", None) or "").strip()
|
| 350 |
+
if pager_cmd:
|
| 351 |
+
if WIN:
|
| 352 |
+
return _tempfilepager(generator, pager_cmd, color)
|
| 353 |
+
return _pipepager(generator, pager_cmd, color)
|
| 354 |
+
if os.environ.get("TERM") in ("dumb", "emacs"):
|
| 355 |
+
return _nullpager(stdout, generator, color)
|
| 356 |
+
if WIN or sys.platform.startswith("os2"):
|
| 357 |
+
return _tempfilepager(generator, "more <", color)
|
| 358 |
+
if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0:
|
| 359 |
+
return _pipepager(generator, "less", color)
|
| 360 |
+
|
| 361 |
+
import tempfile
|
| 362 |
+
|
| 363 |
+
fd, filename = tempfile.mkstemp()
|
| 364 |
+
os.close(fd)
|
| 365 |
+
try:
|
| 366 |
+
if hasattr(os, "system") and os.system(f'more "{filename}"') == 0:
|
| 367 |
+
return _pipepager(generator, "more", color)
|
| 368 |
+
return _nullpager(stdout, generator, color)
|
| 369 |
+
finally:
|
| 370 |
+
os.unlink(filename)
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None:
|
| 374 |
+
"""Page through text by feeding it to another program. Invoking a
|
| 375 |
+
pager through this might support colors.
|
| 376 |
+
"""
|
| 377 |
+
import subprocess
|
| 378 |
+
|
| 379 |
+
env = dict(os.environ)
|
| 380 |
+
|
| 381 |
+
# If we're piping to less we might support colors under the
|
| 382 |
+
# condition that
|
| 383 |
+
cmd_detail = cmd.rsplit("/", 1)[-1].split()
|
| 384 |
+
if color is None and cmd_detail[0] == "less":
|
| 385 |
+
less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}"
|
| 386 |
+
if not less_flags:
|
| 387 |
+
env["LESS"] = "-R"
|
| 388 |
+
color = True
|
| 389 |
+
elif "r" in less_flags or "R" in less_flags:
|
| 390 |
+
color = True
|
| 391 |
+
|
| 392 |
+
c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env)
|
| 393 |
+
stdin = t.cast(t.BinaryIO, c.stdin)
|
| 394 |
+
encoding = get_best_encoding(stdin)
|
| 395 |
+
try:
|
| 396 |
+
for text in generator:
|
| 397 |
+
if not color:
|
| 398 |
+
text = strip_ansi(text)
|
| 399 |
+
|
| 400 |
+
stdin.write(text.encode(encoding, "replace"))
|
| 401 |
+
except (OSError, KeyboardInterrupt):
|
| 402 |
+
pass
|
| 403 |
+
else:
|
| 404 |
+
stdin.close()
|
| 405 |
+
|
| 406 |
+
# Less doesn't respect ^C, but catches it for its own UI purposes (aborting
|
| 407 |
+
# search or other commands inside less).
|
| 408 |
+
#
|
| 409 |
+
# That means when the user hits ^C, the parent process (click) terminates,
|
| 410 |
+
# but less is still alive, paging the output and messing up the terminal.
|
| 411 |
+
#
|
| 412 |
+
# If the user wants to make the pager exit on ^C, they should set
|
| 413 |
+
# `LESS='-K'`. It's not our decision to make.
|
| 414 |
+
while True:
|
| 415 |
+
try:
|
| 416 |
+
c.wait()
|
| 417 |
+
except KeyboardInterrupt:
|
| 418 |
+
pass
|
| 419 |
+
else:
|
| 420 |
+
break
|
| 421 |
+
|
| 422 |
+
|
| 423 |
+
def _tempfilepager(
|
| 424 |
+
generator: t.Iterable[str], cmd: str, color: t.Optional[bool]
|
| 425 |
+
) -> None:
|
| 426 |
+
"""Page through text by invoking a program on a temporary file."""
|
| 427 |
+
import tempfile
|
| 428 |
+
|
| 429 |
+
fd, filename = tempfile.mkstemp()
|
| 430 |
+
# TODO: This never terminates if the passed generator never terminates.
|
| 431 |
+
text = "".join(generator)
|
| 432 |
+
if not color:
|
| 433 |
+
text = strip_ansi(text)
|
| 434 |
+
encoding = get_best_encoding(sys.stdout)
|
| 435 |
+
with open_stream(filename, "wb")[0] as f:
|
| 436 |
+
f.write(text.encode(encoding))
|
| 437 |
+
try:
|
| 438 |
+
os.system(f'{cmd} "{filename}"')
|
| 439 |
+
finally:
|
| 440 |
+
os.close(fd)
|
| 441 |
+
os.unlink(filename)
|
| 442 |
+
|
| 443 |
+
|
| 444 |
+
def _nullpager(
|
| 445 |
+
stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool]
|
| 446 |
+
) -> None:
|
| 447 |
+
"""Simply print unformatted text. This is the ultimate fallback."""
|
| 448 |
+
for text in generator:
|
| 449 |
+
if not color:
|
| 450 |
+
text = strip_ansi(text)
|
| 451 |
+
stream.write(text)
|
| 452 |
+
|
| 453 |
+
|
| 454 |
+
class Editor:
|
| 455 |
+
def __init__(
|
| 456 |
+
self,
|
| 457 |
+
editor: t.Optional[str] = None,
|
| 458 |
+
env: t.Optional[t.Mapping[str, str]] = None,
|
| 459 |
+
require_save: bool = True,
|
| 460 |
+
extension: str = ".txt",
|
| 461 |
+
) -> None:
|
| 462 |
+
self.editor = editor
|
| 463 |
+
self.env = env
|
| 464 |
+
self.require_save = require_save
|
| 465 |
+
self.extension = extension
|
| 466 |
+
|
| 467 |
+
def get_editor(self) -> str:
|
| 468 |
+
if self.editor is not None:
|
| 469 |
+
return self.editor
|
| 470 |
+
for key in "VISUAL", "EDITOR":
|
| 471 |
+
rv = os.environ.get(key)
|
| 472 |
+
if rv:
|
| 473 |
+
return rv
|
| 474 |
+
if WIN:
|
| 475 |
+
return "notepad"
|
| 476 |
+
for editor in "sensible-editor", "vim", "nano":
|
| 477 |
+
if os.system(f"which {editor} >/dev/null 2>&1") == 0:
|
| 478 |
+
return editor
|
| 479 |
+
return "vi"
|
| 480 |
+
|
| 481 |
+
def edit_file(self, filename: str) -> None:
|
| 482 |
+
import subprocess
|
| 483 |
+
|
| 484 |
+
editor = self.get_editor()
|
| 485 |
+
environ: t.Optional[t.Dict[str, str]] = None
|
| 486 |
+
|
| 487 |
+
if self.env:
|
| 488 |
+
environ = os.environ.copy()
|
| 489 |
+
environ.update(self.env)
|
| 490 |
+
|
| 491 |
+
try:
|
| 492 |
+
c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True)
|
| 493 |
+
exit_code = c.wait()
|
| 494 |
+
if exit_code != 0:
|
| 495 |
+
raise ClickException(
|
| 496 |
+
_("{editor}: Editing failed").format(editor=editor)
|
| 497 |
+
)
|
| 498 |
+
except OSError as e:
|
| 499 |
+
raise ClickException(
|
| 500 |
+
_("{editor}: Editing failed: {e}").format(editor=editor, e=e)
|
| 501 |
+
) from e
|
| 502 |
+
|
| 503 |
+
def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]:
|
| 504 |
+
import tempfile
|
| 505 |
+
|
| 506 |
+
if not text:
|
| 507 |
+
data = b""
|
| 508 |
+
elif isinstance(text, (bytes, bytearray)):
|
| 509 |
+
data = text
|
| 510 |
+
else:
|
| 511 |
+
if text and not text.endswith("\n"):
|
| 512 |
+
text += "\n"
|
| 513 |
+
|
| 514 |
+
if WIN:
|
| 515 |
+
data = text.replace("\n", "\r\n").encode("utf-8-sig")
|
| 516 |
+
else:
|
| 517 |
+
data = text.encode("utf-8")
|
| 518 |
+
|
| 519 |
+
fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension)
|
| 520 |
+
f: t.BinaryIO
|
| 521 |
+
|
| 522 |
+
try:
|
| 523 |
+
with os.fdopen(fd, "wb") as f:
|
| 524 |
+
f.write(data)
|
| 525 |
+
|
| 526 |
+
# If the filesystem resolution is 1 second, like Mac OS
|
| 527 |
+
# 10.12 Extended, or 2 seconds, like FAT32, and the editor
|
| 528 |
+
# closes very fast, require_save can fail. Set the modified
|
| 529 |
+
# time to be 2 seconds in the past to work around this.
|
| 530 |
+
os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2))
|
| 531 |
+
# Depending on the resolution, the exact value might not be
|
| 532 |
+
# recorded, so get the new recorded value.
|
| 533 |
+
timestamp = os.path.getmtime(name)
|
| 534 |
+
|
| 535 |
+
self.edit_file(name)
|
| 536 |
+
|
| 537 |
+
if self.require_save and os.path.getmtime(name) == timestamp:
|
| 538 |
+
return None
|
| 539 |
+
|
| 540 |
+
with open(name, "rb") as f:
|
| 541 |
+
rv = f.read()
|
| 542 |
+
|
| 543 |
+
if isinstance(text, (bytes, bytearray)):
|
| 544 |
+
return rv
|
| 545 |
+
|
| 546 |
+
return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore
|
| 547 |
+
finally:
|
| 548 |
+
os.unlink(name)
|
| 549 |
+
|
| 550 |
+
|
| 551 |
+
def open_url(url: str, wait: bool = False, locate: bool = False) -> int:
|
| 552 |
+
import subprocess
|
| 553 |
+
|
| 554 |
+
def _unquote_file(url: str) -> str:
|
| 555 |
+
from urllib.parse import unquote
|
| 556 |
+
|
| 557 |
+
if url.startswith("file://"):
|
| 558 |
+
url = unquote(url[7:])
|
| 559 |
+
|
| 560 |
+
return url
|
| 561 |
+
|
| 562 |
+
if sys.platform == "darwin":
|
| 563 |
+
args = ["open"]
|
| 564 |
+
if wait:
|
| 565 |
+
args.append("-W")
|
| 566 |
+
if locate:
|
| 567 |
+
args.append("-R")
|
| 568 |
+
args.append(_unquote_file(url))
|
| 569 |
+
null = open("/dev/null", "w")
|
| 570 |
+
try:
|
| 571 |
+
return subprocess.Popen(args, stderr=null).wait()
|
| 572 |
+
finally:
|
| 573 |
+
null.close()
|
| 574 |
+
elif WIN:
|
| 575 |
+
if locate:
|
| 576 |
+
url = _unquote_file(url.replace('"', ""))
|
| 577 |
+
args = f'explorer /select,"{url}"'
|
| 578 |
+
else:
|
| 579 |
+
url = url.replace('"', "")
|
| 580 |
+
wait_str = "/WAIT" if wait else ""
|
| 581 |
+
args = f'start {wait_str} "" "{url}"'
|
| 582 |
+
return os.system(args)
|
| 583 |
+
elif CYGWIN:
|
| 584 |
+
if locate:
|
| 585 |
+
url = os.path.dirname(_unquote_file(url).replace('"', ""))
|
| 586 |
+
args = f'cygstart "{url}"'
|
| 587 |
+
else:
|
| 588 |
+
url = url.replace('"', "")
|
| 589 |
+
wait_str = "-w" if wait else ""
|
| 590 |
+
args = f'cygstart {wait_str} "{url}"'
|
| 591 |
+
return os.system(args)
|
| 592 |
+
|
| 593 |
+
try:
|
| 594 |
+
if locate:
|
| 595 |
+
url = os.path.dirname(_unquote_file(url)) or "."
|
| 596 |
+
else:
|
| 597 |
+
url = _unquote_file(url)
|
| 598 |
+
c = subprocess.Popen(["xdg-open", url])
|
| 599 |
+
if wait:
|
| 600 |
+
return c.wait()
|
| 601 |
+
return 0
|
| 602 |
+
except OSError:
|
| 603 |
+
if url.startswith(("http://", "https://")) and not locate and not wait:
|
| 604 |
+
import webbrowser
|
| 605 |
+
|
| 606 |
+
webbrowser.open(url)
|
| 607 |
+
return 0
|
| 608 |
+
return 1
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]:
|
| 612 |
+
if ch == "\x03":
|
| 613 |
+
raise KeyboardInterrupt()
|
| 614 |
+
|
| 615 |
+
if ch == "\x04" and not WIN: # Unix-like, Ctrl+D
|
| 616 |
+
raise EOFError()
|
| 617 |
+
|
| 618 |
+
if ch == "\x1a" and WIN: # Windows, Ctrl+Z
|
| 619 |
+
raise EOFError()
|
| 620 |
+
|
| 621 |
+
return None
|
| 622 |
+
|
| 623 |
+
|
| 624 |
+
if WIN:
|
| 625 |
+
import msvcrt
|
| 626 |
+
|
| 627 |
+
@contextlib.contextmanager
|
| 628 |
+
def raw_terminal() -> t.Iterator[int]:
|
| 629 |
+
yield -1
|
| 630 |
+
|
| 631 |
+
def getchar(echo: bool) -> str:
|
| 632 |
+
# The function `getch` will return a bytes object corresponding to
|
| 633 |
+
# the pressed character. Since Windows 10 build 1803, it will also
|
| 634 |
+
# return \x00 when called a second time after pressing a regular key.
|
| 635 |
+
#
|
| 636 |
+
# `getwch` does not share this probably-bugged behavior. Moreover, it
|
| 637 |
+
# returns a Unicode object by default, which is what we want.
|
| 638 |
+
#
|
| 639 |
+
# Either of these functions will return \x00 or \xe0 to indicate
|
| 640 |
+
# a special key, and you need to call the same function again to get
|
| 641 |
+
# the "rest" of the code. The fun part is that \u00e0 is
|
| 642 |
+
# "latin small letter a with grave", so if you type that on a French
|
| 643 |
+
# keyboard, you _also_ get a \xe0.
|
| 644 |
+
# E.g., consider the Up arrow. This returns \xe0 and then \x48. The
|
| 645 |
+
# resulting Unicode string reads as "a with grave" + "capital H".
|
| 646 |
+
# This is indistinguishable from when the user actually types
|
| 647 |
+
# "a with grave" and then "capital H".
|
| 648 |
+
#
|
| 649 |
+
# When \xe0 is returned, we assume it's part of a special-key sequence
|
| 650 |
+
# and call `getwch` again, but that means that when the user types
|
| 651 |
+
# the \u00e0 character, `getchar` doesn't return until a second
|
| 652 |
+
# character is typed.
|
| 653 |
+
# The alternative is returning immediately, but that would mess up
|
| 654 |
+
# cross-platform handling of arrow keys and others that start with
|
| 655 |
+
# \xe0. Another option is using `getch`, but then we can't reliably
|
| 656 |
+
# read non-ASCII characters, because return values of `getch` are
|
| 657 |
+
# limited to the current 8-bit codepage.
|
| 658 |
+
#
|
| 659 |
+
# Anyway, Click doesn't claim to do this Right(tm), and using `getwch`
|
| 660 |
+
# is doing the right thing in more situations than with `getch`.
|
| 661 |
+
func: t.Callable[[], str]
|
| 662 |
+
|
| 663 |
+
if echo:
|
| 664 |
+
func = msvcrt.getwche # type: ignore
|
| 665 |
+
else:
|
| 666 |
+
func = msvcrt.getwch # type: ignore
|
| 667 |
+
|
| 668 |
+
rv = func()
|
| 669 |
+
|
| 670 |
+
if rv in ("\x00", "\xe0"):
|
| 671 |
+
# \x00 and \xe0 are control characters that indicate special key,
|
| 672 |
+
# see above.
|
| 673 |
+
rv += func()
|
| 674 |
+
|
| 675 |
+
_translate_ch_to_exc(rv)
|
| 676 |
+
return rv
|
| 677 |
+
|
| 678 |
+
else:
|
| 679 |
+
import tty
|
| 680 |
+
import termios
|
| 681 |
+
|
| 682 |
+
@contextlib.contextmanager
|
| 683 |
+
def raw_terminal() -> t.Iterator[int]:
|
| 684 |
+
f: t.Optional[t.TextIO]
|
| 685 |
+
fd: int
|
| 686 |
+
|
| 687 |
+
if not isatty(sys.stdin):
|
| 688 |
+
f = open("/dev/tty")
|
| 689 |
+
fd = f.fileno()
|
| 690 |
+
else:
|
| 691 |
+
fd = sys.stdin.fileno()
|
| 692 |
+
f = None
|
| 693 |
+
|
| 694 |
+
try:
|
| 695 |
+
old_settings = termios.tcgetattr(fd)
|
| 696 |
+
|
| 697 |
+
try:
|
| 698 |
+
tty.setraw(fd)
|
| 699 |
+
yield fd
|
| 700 |
+
finally:
|
| 701 |
+
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
| 702 |
+
sys.stdout.flush()
|
| 703 |
+
|
| 704 |
+
if f is not None:
|
| 705 |
+
f.close()
|
| 706 |
+
except termios.error:
|
| 707 |
+
pass
|
| 708 |
+
|
| 709 |
+
def getchar(echo: bool) -> str:
|
| 710 |
+
with raw_terminal() as fd:
|
| 711 |
+
ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace")
|
| 712 |
+
|
| 713 |
+
if echo and isatty(sys.stdout):
|
| 714 |
+
sys.stdout.write(ch)
|
| 715 |
+
|
| 716 |
+
_translate_ch_to_exc(ch)
|
| 717 |
+
return ch
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/google_auth-2.9.0-py3.10-nspkg.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c47e604f1738522a583f7aab6cffb80821cd18157dede051e10aa185e0af065e
|
| 3 |
+
size 539
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/__init__.py
ADDED
|
@@ -0,0 +1,2190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2015-2016 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""gRPC's Python API."""
|
| 15 |
+
|
| 16 |
+
import abc
|
| 17 |
+
import contextlib
|
| 18 |
+
import enum
|
| 19 |
+
import logging
|
| 20 |
+
import sys
|
| 21 |
+
|
| 22 |
+
from grpc import _compression
|
| 23 |
+
from grpc._cython import cygrpc as _cygrpc
|
| 24 |
+
from grpc._runtime_protos import protos
|
| 25 |
+
from grpc._runtime_protos import protos_and_services
|
| 26 |
+
from grpc._runtime_protos import services
|
| 27 |
+
import six
|
| 28 |
+
|
| 29 |
+
logging.getLogger(__name__).addHandler(logging.NullHandler())
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
# pylint: disable=ungrouped-imports
|
| 33 |
+
from grpc._grpcio_metadata import __version__
|
| 34 |
+
except ImportError:
|
| 35 |
+
__version__ = "dev0"
|
| 36 |
+
|
| 37 |
+
############################## Future Interface ###############################
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class FutureTimeoutError(Exception):
|
| 41 |
+
"""Indicates that a method call on a Future timed out."""
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class FutureCancelledError(Exception):
|
| 45 |
+
"""Indicates that the computation underlying a Future was cancelled."""
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class Future(six.with_metaclass(abc.ABCMeta)):
|
| 49 |
+
"""A representation of a computation in another control flow.
|
| 50 |
+
|
| 51 |
+
Computations represented by a Future may be yet to be begun,
|
| 52 |
+
may be ongoing, or may have already completed.
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
@abc.abstractmethod
|
| 56 |
+
def cancel(self):
|
| 57 |
+
"""Attempts to cancel the computation.
|
| 58 |
+
|
| 59 |
+
This method does not block.
|
| 60 |
+
|
| 61 |
+
Returns:
|
| 62 |
+
bool:
|
| 63 |
+
Returns True if the computation was canceled.
|
| 64 |
+
|
| 65 |
+
Returns False under all other circumstances, for example:
|
| 66 |
+
|
| 67 |
+
1. computation has begun and could not be canceled.
|
| 68 |
+
2. computation has finished
|
| 69 |
+
3. computation is scheduled for execution and it is impossible
|
| 70 |
+
to determine its state without blocking.
|
| 71 |
+
"""
|
| 72 |
+
raise NotImplementedError()
|
| 73 |
+
|
| 74 |
+
@abc.abstractmethod
|
| 75 |
+
def cancelled(self):
|
| 76 |
+
"""Describes whether the computation was cancelled.
|
| 77 |
+
|
| 78 |
+
This method does not block.
|
| 79 |
+
|
| 80 |
+
Returns:
|
| 81 |
+
bool:
|
| 82 |
+
Returns True if the computation was cancelled before its result became
|
| 83 |
+
available.
|
| 84 |
+
|
| 85 |
+
Returns False under all other circumstances, for example:
|
| 86 |
+
|
| 87 |
+
1. computation was not cancelled.
|
| 88 |
+
2. computation's result is available.
|
| 89 |
+
"""
|
| 90 |
+
raise NotImplementedError()
|
| 91 |
+
|
| 92 |
+
@abc.abstractmethod
|
| 93 |
+
def running(self):
|
| 94 |
+
"""Describes whether the computation is taking place.
|
| 95 |
+
|
| 96 |
+
This method does not block.
|
| 97 |
+
|
| 98 |
+
Returns:
|
| 99 |
+
Returns True if the computation is scheduled for execution or
|
| 100 |
+
currently executing.
|
| 101 |
+
|
| 102 |
+
Returns False if the computation already executed or was cancelled.
|
| 103 |
+
"""
|
| 104 |
+
raise NotImplementedError()
|
| 105 |
+
|
| 106 |
+
@abc.abstractmethod
|
| 107 |
+
def done(self):
|
| 108 |
+
"""Describes whether the computation has taken place.
|
| 109 |
+
|
| 110 |
+
This method does not block.
|
| 111 |
+
|
| 112 |
+
Returns:
|
| 113 |
+
bool:
|
| 114 |
+
Returns True if the computation already executed or was cancelled.
|
| 115 |
+
Returns False if the computation is scheduled for execution or
|
| 116 |
+
currently executing.
|
| 117 |
+
This is exactly opposite of the running() method's result.
|
| 118 |
+
"""
|
| 119 |
+
raise NotImplementedError()
|
| 120 |
+
|
| 121 |
+
@abc.abstractmethod
|
| 122 |
+
def result(self, timeout=None):
|
| 123 |
+
"""Returns the result of the computation or raises its exception.
|
| 124 |
+
|
| 125 |
+
This method may return immediately or may block.
|
| 126 |
+
|
| 127 |
+
Args:
|
| 128 |
+
timeout: The length of time in seconds to wait for the computation to
|
| 129 |
+
finish or be cancelled. If None, the call will block until the
|
| 130 |
+
computations's termination.
|
| 131 |
+
|
| 132 |
+
Returns:
|
| 133 |
+
The return value of the computation.
|
| 134 |
+
|
| 135 |
+
Raises:
|
| 136 |
+
FutureTimeoutError: If a timeout value is passed and the computation
|
| 137 |
+
does not terminate within the allotted time.
|
| 138 |
+
FutureCancelledError: If the computation was cancelled.
|
| 139 |
+
Exception: If the computation raised an exception, this call will
|
| 140 |
+
raise the same exception.
|
| 141 |
+
"""
|
| 142 |
+
raise NotImplementedError()
|
| 143 |
+
|
| 144 |
+
@abc.abstractmethod
|
| 145 |
+
def exception(self, timeout=None):
|
| 146 |
+
"""Return the exception raised by the computation.
|
| 147 |
+
|
| 148 |
+
This method may return immediately or may block.
|
| 149 |
+
|
| 150 |
+
Args:
|
| 151 |
+
timeout: The length of time in seconds to wait for the computation to
|
| 152 |
+
terminate or be cancelled. If None, the call will block until the
|
| 153 |
+
computations's termination.
|
| 154 |
+
|
| 155 |
+
Returns:
|
| 156 |
+
The exception raised by the computation, or None if the computation
|
| 157 |
+
did not raise an exception.
|
| 158 |
+
|
| 159 |
+
Raises:
|
| 160 |
+
FutureTimeoutError: If a timeout value is passed and the computation
|
| 161 |
+
does not terminate within the allotted time.
|
| 162 |
+
FutureCancelledError: If the computation was cancelled.
|
| 163 |
+
"""
|
| 164 |
+
raise NotImplementedError()
|
| 165 |
+
|
| 166 |
+
@abc.abstractmethod
|
| 167 |
+
def traceback(self, timeout=None):
|
| 168 |
+
"""Access the traceback of the exception raised by the computation.
|
| 169 |
+
|
| 170 |
+
This method may return immediately or may block.
|
| 171 |
+
|
| 172 |
+
Args:
|
| 173 |
+
timeout: The length of time in seconds to wait for the computation
|
| 174 |
+
to terminate or be cancelled. If None, the call will block until
|
| 175 |
+
the computation's termination.
|
| 176 |
+
|
| 177 |
+
Returns:
|
| 178 |
+
The traceback of the exception raised by the computation, or None
|
| 179 |
+
if the computation did not raise an exception.
|
| 180 |
+
|
| 181 |
+
Raises:
|
| 182 |
+
FutureTimeoutError: If a timeout value is passed and the computation
|
| 183 |
+
does not terminate within the allotted time.
|
| 184 |
+
FutureCancelledError: If the computation was cancelled.
|
| 185 |
+
"""
|
| 186 |
+
raise NotImplementedError()
|
| 187 |
+
|
| 188 |
+
@abc.abstractmethod
|
| 189 |
+
def add_done_callback(self, fn):
|
| 190 |
+
"""Adds a function to be called at completion of the computation.
|
| 191 |
+
|
| 192 |
+
The callback will be passed this Future object describing the outcome
|
| 193 |
+
of the computation. Callbacks will be invoked after the future is
|
| 194 |
+
terminated, whether successfully or not.
|
| 195 |
+
|
| 196 |
+
If the computation has already completed, the callback will be called
|
| 197 |
+
immediately.
|
| 198 |
+
|
| 199 |
+
Exceptions raised in the callback will be logged at ERROR level, but
|
| 200 |
+
will not terminate any threads of execution.
|
| 201 |
+
|
| 202 |
+
Args:
|
| 203 |
+
fn: A callable taking this Future object as its single parameter.
|
| 204 |
+
"""
|
| 205 |
+
raise NotImplementedError()
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
################################ gRPC Enums ##################################
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
@enum.unique
|
| 212 |
+
class ChannelConnectivity(enum.Enum):
|
| 213 |
+
"""Mirrors grpc_connectivity_state in the gRPC Core.
|
| 214 |
+
|
| 215 |
+
Attributes:
|
| 216 |
+
IDLE: The channel is idle.
|
| 217 |
+
CONNECTING: The channel is connecting.
|
| 218 |
+
READY: The channel is ready to conduct RPCs.
|
| 219 |
+
TRANSIENT_FAILURE: The channel has seen a failure from which it expects
|
| 220 |
+
to recover.
|
| 221 |
+
SHUTDOWN: The channel has seen a failure from which it cannot recover.
|
| 222 |
+
"""
|
| 223 |
+
IDLE = (_cygrpc.ConnectivityState.idle, 'idle')
|
| 224 |
+
CONNECTING = (_cygrpc.ConnectivityState.connecting, 'connecting')
|
| 225 |
+
READY = (_cygrpc.ConnectivityState.ready, 'ready')
|
| 226 |
+
TRANSIENT_FAILURE = (_cygrpc.ConnectivityState.transient_failure,
|
| 227 |
+
'transient failure')
|
| 228 |
+
SHUTDOWN = (_cygrpc.ConnectivityState.shutdown, 'shutdown')
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
@enum.unique
|
| 232 |
+
class StatusCode(enum.Enum):
|
| 233 |
+
"""Mirrors grpc_status_code in the gRPC Core.
|
| 234 |
+
|
| 235 |
+
Attributes:
|
| 236 |
+
OK: Not an error; returned on success
|
| 237 |
+
CANCELLED: The operation was cancelled (typically by the caller).
|
| 238 |
+
UNKNOWN: Unknown error.
|
| 239 |
+
INVALID_ARGUMENT: Client specified an invalid argument.
|
| 240 |
+
DEADLINE_EXCEEDED: Deadline expired before operation could complete.
|
| 241 |
+
NOT_FOUND: Some requested entity (e.g., file or directory) was not found.
|
| 242 |
+
ALREADY_EXISTS: Some entity that we attempted to create (e.g., file or directory)
|
| 243 |
+
already exists.
|
| 244 |
+
PERMISSION_DENIED: The caller does not have permission to execute the specified
|
| 245 |
+
operation.
|
| 246 |
+
UNAUTHENTICATED: The request does not have valid authentication credentials for the
|
| 247 |
+
operation.
|
| 248 |
+
RESOURCE_EXHAUSTED: Some resource has been exhausted, perhaps a per-user quota, or
|
| 249 |
+
perhaps the entire file system is out of space.
|
| 250 |
+
FAILED_PRECONDITION: Operation was rejected because the system is not in a state
|
| 251 |
+
required for the operation's execution.
|
| 252 |
+
ABORTED: The operation was aborted, typically due to a concurrency issue
|
| 253 |
+
like sequencer check failures, transaction aborts, etc.
|
| 254 |
+
UNIMPLEMENTED: Operation is not implemented or not supported/enabled in this service.
|
| 255 |
+
INTERNAL: Internal errors. Means some invariants expected by underlying
|
| 256 |
+
system has been broken.
|
| 257 |
+
UNAVAILABLE: The service is currently unavailable.
|
| 258 |
+
DATA_LOSS: Unrecoverable data loss or corruption.
|
| 259 |
+
"""
|
| 260 |
+
OK = (_cygrpc.StatusCode.ok, 'ok')
|
| 261 |
+
CANCELLED = (_cygrpc.StatusCode.cancelled, 'cancelled')
|
| 262 |
+
UNKNOWN = (_cygrpc.StatusCode.unknown, 'unknown')
|
| 263 |
+
INVALID_ARGUMENT = (_cygrpc.StatusCode.invalid_argument, 'invalid argument')
|
| 264 |
+
DEADLINE_EXCEEDED = (_cygrpc.StatusCode.deadline_exceeded,
|
| 265 |
+
'deadline exceeded')
|
| 266 |
+
NOT_FOUND = (_cygrpc.StatusCode.not_found, 'not found')
|
| 267 |
+
ALREADY_EXISTS = (_cygrpc.StatusCode.already_exists, 'already exists')
|
| 268 |
+
PERMISSION_DENIED = (_cygrpc.StatusCode.permission_denied,
|
| 269 |
+
'permission denied')
|
| 270 |
+
RESOURCE_EXHAUSTED = (_cygrpc.StatusCode.resource_exhausted,
|
| 271 |
+
'resource exhausted')
|
| 272 |
+
FAILED_PRECONDITION = (_cygrpc.StatusCode.failed_precondition,
|
| 273 |
+
'failed precondition')
|
| 274 |
+
ABORTED = (_cygrpc.StatusCode.aborted, 'aborted')
|
| 275 |
+
OUT_OF_RANGE = (_cygrpc.StatusCode.out_of_range, 'out of range')
|
| 276 |
+
UNIMPLEMENTED = (_cygrpc.StatusCode.unimplemented, 'unimplemented')
|
| 277 |
+
INTERNAL = (_cygrpc.StatusCode.internal, 'internal')
|
| 278 |
+
UNAVAILABLE = (_cygrpc.StatusCode.unavailable, 'unavailable')
|
| 279 |
+
DATA_LOSS = (_cygrpc.StatusCode.data_loss, 'data loss')
|
| 280 |
+
UNAUTHENTICATED = (_cygrpc.StatusCode.unauthenticated, 'unauthenticated')
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
############################# gRPC Status ################################
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
class Status(six.with_metaclass(abc.ABCMeta)):
|
| 287 |
+
"""Describes the status of an RPC.
|
| 288 |
+
|
| 289 |
+
This is an EXPERIMENTAL API.
|
| 290 |
+
|
| 291 |
+
Attributes:
|
| 292 |
+
code: A StatusCode object to be sent to the client.
|
| 293 |
+
details: A UTF-8-encodable string to be sent to the client upon
|
| 294 |
+
termination of the RPC.
|
| 295 |
+
trailing_metadata: The trailing :term:`metadata` in the RPC.
|
| 296 |
+
"""
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
############################# gRPC Exceptions ################################
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
class RpcError(Exception):
|
| 303 |
+
"""Raised by the gRPC library to indicate non-OK-status RPC termination."""
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
############################## Shared Context ################################
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
class RpcContext(six.with_metaclass(abc.ABCMeta)):
|
| 310 |
+
"""Provides RPC-related information and action."""
|
| 311 |
+
|
| 312 |
+
@abc.abstractmethod
|
| 313 |
+
def is_active(self):
|
| 314 |
+
"""Describes whether the RPC is active or has terminated.
|
| 315 |
+
|
| 316 |
+
Returns:
|
| 317 |
+
bool:
|
| 318 |
+
True if RPC is active, False otherwise.
|
| 319 |
+
"""
|
| 320 |
+
raise NotImplementedError()
|
| 321 |
+
|
| 322 |
+
@abc.abstractmethod
|
| 323 |
+
def time_remaining(self):
|
| 324 |
+
"""Describes the length of allowed time remaining for the RPC.
|
| 325 |
+
|
| 326 |
+
Returns:
|
| 327 |
+
A nonnegative float indicating the length of allowed time in seconds
|
| 328 |
+
remaining for the RPC to complete before it is considered to have
|
| 329 |
+
timed out, or None if no deadline was specified for the RPC.
|
| 330 |
+
"""
|
| 331 |
+
raise NotImplementedError()
|
| 332 |
+
|
| 333 |
+
@abc.abstractmethod
|
| 334 |
+
def cancel(self):
|
| 335 |
+
"""Cancels the RPC.
|
| 336 |
+
|
| 337 |
+
Idempotent and has no effect if the RPC has already terminated.
|
| 338 |
+
"""
|
| 339 |
+
raise NotImplementedError()
|
| 340 |
+
|
| 341 |
+
@abc.abstractmethod
|
| 342 |
+
def add_callback(self, callback):
|
| 343 |
+
"""Registers a callback to be called on RPC termination.
|
| 344 |
+
|
| 345 |
+
Args:
|
| 346 |
+
callback: A no-parameter callable to be called on RPC termination.
|
| 347 |
+
|
| 348 |
+
Returns:
|
| 349 |
+
True if the callback was added and will be called later; False if
|
| 350 |
+
the callback was not added and will not be called (because the RPC
|
| 351 |
+
already terminated or some other reason).
|
| 352 |
+
"""
|
| 353 |
+
raise NotImplementedError()
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
######################### Invocation-Side Context ############################
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
class Call(six.with_metaclass(abc.ABCMeta, RpcContext)):
|
| 360 |
+
"""Invocation-side utility object for an RPC."""
|
| 361 |
+
|
| 362 |
+
@abc.abstractmethod
|
| 363 |
+
def initial_metadata(self):
|
| 364 |
+
"""Accesses the initial metadata sent by the server.
|
| 365 |
+
|
| 366 |
+
This method blocks until the value is available.
|
| 367 |
+
|
| 368 |
+
Returns:
|
| 369 |
+
The initial :term:`metadata`.
|
| 370 |
+
"""
|
| 371 |
+
raise NotImplementedError()
|
| 372 |
+
|
| 373 |
+
@abc.abstractmethod
|
| 374 |
+
def trailing_metadata(self):
|
| 375 |
+
"""Accesses the trailing metadata sent by the server.
|
| 376 |
+
|
| 377 |
+
This method blocks until the value is available.
|
| 378 |
+
|
| 379 |
+
Returns:
|
| 380 |
+
The trailing :term:`metadata`.
|
| 381 |
+
"""
|
| 382 |
+
raise NotImplementedError()
|
| 383 |
+
|
| 384 |
+
@abc.abstractmethod
|
| 385 |
+
def code(self):
|
| 386 |
+
"""Accesses the status code sent by the server.
|
| 387 |
+
|
| 388 |
+
This method blocks until the value is available.
|
| 389 |
+
|
| 390 |
+
Returns:
|
| 391 |
+
The StatusCode value for the RPC.
|
| 392 |
+
"""
|
| 393 |
+
raise NotImplementedError()
|
| 394 |
+
|
| 395 |
+
@abc.abstractmethod
|
| 396 |
+
def details(self):
|
| 397 |
+
"""Accesses the details sent by the server.
|
| 398 |
+
|
| 399 |
+
This method blocks until the value is available.
|
| 400 |
+
|
| 401 |
+
Returns:
|
| 402 |
+
The details string of the RPC.
|
| 403 |
+
"""
|
| 404 |
+
raise NotImplementedError()
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
############## Invocation-Side Interceptor Interfaces & Classes ##############
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
class ClientCallDetails(six.with_metaclass(abc.ABCMeta)):
|
| 411 |
+
"""Describes an RPC to be invoked.
|
| 412 |
+
|
| 413 |
+
Attributes:
|
| 414 |
+
method: The method name of the RPC.
|
| 415 |
+
timeout: An optional duration of time in seconds to allow for the RPC.
|
| 416 |
+
metadata: Optional :term:`metadata` to be transmitted to
|
| 417 |
+
the service-side of the RPC.
|
| 418 |
+
credentials: An optional CallCredentials for the RPC.
|
| 419 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 420 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 421 |
+
compression: An element of grpc.compression, e.g.
|
| 422 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 423 |
+
"""
|
| 424 |
+
|
| 425 |
+
|
| 426 |
+
class UnaryUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)):
|
| 427 |
+
"""Affords intercepting unary-unary invocations."""
|
| 428 |
+
|
| 429 |
+
@abc.abstractmethod
|
| 430 |
+
def intercept_unary_unary(self, continuation, client_call_details, request):
|
| 431 |
+
"""Intercepts a unary-unary invocation asynchronously.
|
| 432 |
+
|
| 433 |
+
Args:
|
| 434 |
+
continuation: A function that proceeds with the invocation by
|
| 435 |
+
executing the next interceptor in chain or invoking the
|
| 436 |
+
actual RPC on the underlying Channel. It is the interceptor's
|
| 437 |
+
responsibility to call it if it decides to move the RPC forward.
|
| 438 |
+
The interceptor can use
|
| 439 |
+
`response_future = continuation(client_call_details, request)`
|
| 440 |
+
to continue with the RPC. `continuation` returns an object that is
|
| 441 |
+
both a Call for the RPC and a Future. In the event of RPC
|
| 442 |
+
completion, the return Call-Future's result value will be
|
| 443 |
+
the response message of the RPC. Should the event terminate
|
| 444 |
+
with non-OK status, the returned Call-Future's exception value
|
| 445 |
+
will be an RpcError.
|
| 446 |
+
client_call_details: A ClientCallDetails object describing the
|
| 447 |
+
outgoing RPC.
|
| 448 |
+
request: The request value for the RPC.
|
| 449 |
+
|
| 450 |
+
Returns:
|
| 451 |
+
An object that is both a Call for the RPC and a Future.
|
| 452 |
+
In the event of RPC completion, the return Call-Future's
|
| 453 |
+
result value will be the response message of the RPC.
|
| 454 |
+
Should the event terminate with non-OK status, the returned
|
| 455 |
+
Call-Future's exception value will be an RpcError.
|
| 456 |
+
"""
|
| 457 |
+
raise NotImplementedError()
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
class UnaryStreamClientInterceptor(six.with_metaclass(abc.ABCMeta)):
|
| 461 |
+
"""Affords intercepting unary-stream invocations."""
|
| 462 |
+
|
| 463 |
+
@abc.abstractmethod
|
| 464 |
+
def intercept_unary_stream(self, continuation, client_call_details,
|
| 465 |
+
request):
|
| 466 |
+
"""Intercepts a unary-stream invocation.
|
| 467 |
+
|
| 468 |
+
Args:
|
| 469 |
+
continuation: A function that proceeds with the invocation by
|
| 470 |
+
executing the next interceptor in chain or invoking the
|
| 471 |
+
actual RPC on the underlying Channel. It is the interceptor's
|
| 472 |
+
responsibility to call it if it decides to move the RPC forward.
|
| 473 |
+
The interceptor can use
|
| 474 |
+
`response_iterator = continuation(client_call_details, request)`
|
| 475 |
+
to continue with the RPC. `continuation` returns an object that is
|
| 476 |
+
both a Call for the RPC and an iterator for response values.
|
| 477 |
+
Drawing response values from the returned Call-iterator may
|
| 478 |
+
raise RpcError indicating termination of the RPC with non-OK
|
| 479 |
+
status.
|
| 480 |
+
client_call_details: A ClientCallDetails object describing the
|
| 481 |
+
outgoing RPC.
|
| 482 |
+
request: The request value for the RPC.
|
| 483 |
+
|
| 484 |
+
Returns:
|
| 485 |
+
An object that is both a Call for the RPC and an iterator of
|
| 486 |
+
response values. Drawing response values from the returned
|
| 487 |
+
Call-iterator may raise RpcError indicating termination of
|
| 488 |
+
the RPC with non-OK status. This object *should* also fulfill the
|
| 489 |
+
Future interface, though it may not.
|
| 490 |
+
"""
|
| 491 |
+
raise NotImplementedError()
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
class StreamUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)):
|
| 495 |
+
"""Affords intercepting stream-unary invocations."""
|
| 496 |
+
|
| 497 |
+
@abc.abstractmethod
|
| 498 |
+
def intercept_stream_unary(self, continuation, client_call_details,
|
| 499 |
+
request_iterator):
|
| 500 |
+
"""Intercepts a stream-unary invocation asynchronously.
|
| 501 |
+
|
| 502 |
+
Args:
|
| 503 |
+
continuation: A function that proceeds with the invocation by
|
| 504 |
+
executing the next interceptor in chain or invoking the
|
| 505 |
+
actual RPC on the underlying Channel. It is the interceptor's
|
| 506 |
+
responsibility to call it if it decides to move the RPC forward.
|
| 507 |
+
The interceptor can use
|
| 508 |
+
`response_future = continuation(client_call_details, request_iterator)`
|
| 509 |
+
to continue with the RPC. `continuation` returns an object that is
|
| 510 |
+
both a Call for the RPC and a Future. In the event of RPC completion,
|
| 511 |
+
the return Call-Future's result value will be the response message
|
| 512 |
+
of the RPC. Should the event terminate with non-OK status, the
|
| 513 |
+
returned Call-Future's exception value will be an RpcError.
|
| 514 |
+
client_call_details: A ClientCallDetails object describing the
|
| 515 |
+
outgoing RPC.
|
| 516 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 517 |
+
|
| 518 |
+
Returns:
|
| 519 |
+
An object that is both a Call for the RPC and a Future.
|
| 520 |
+
In the event of RPC completion, the return Call-Future's
|
| 521 |
+
result value will be the response message of the RPC.
|
| 522 |
+
Should the event terminate with non-OK status, the returned
|
| 523 |
+
Call-Future's exception value will be an RpcError.
|
| 524 |
+
"""
|
| 525 |
+
raise NotImplementedError()
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
class StreamStreamClientInterceptor(six.with_metaclass(abc.ABCMeta)):
|
| 529 |
+
"""Affords intercepting stream-stream invocations."""
|
| 530 |
+
|
| 531 |
+
@abc.abstractmethod
|
| 532 |
+
def intercept_stream_stream(self, continuation, client_call_details,
|
| 533 |
+
request_iterator):
|
| 534 |
+
"""Intercepts a stream-stream invocation.
|
| 535 |
+
|
| 536 |
+
Args:
|
| 537 |
+
continuation: A function that proceeds with the invocation by
|
| 538 |
+
executing the next interceptor in chain or invoking the
|
| 539 |
+
actual RPC on the underlying Channel. It is the interceptor's
|
| 540 |
+
responsibility to call it if it decides to move the RPC forward.
|
| 541 |
+
The interceptor can use
|
| 542 |
+
`response_iterator = continuation(client_call_details, request_iterator)`
|
| 543 |
+
to continue with the RPC. `continuation` returns an object that is
|
| 544 |
+
both a Call for the RPC and an iterator for response values.
|
| 545 |
+
Drawing response values from the returned Call-iterator may
|
| 546 |
+
raise RpcError indicating termination of the RPC with non-OK
|
| 547 |
+
status.
|
| 548 |
+
client_call_details: A ClientCallDetails object describing the
|
| 549 |
+
outgoing RPC.
|
| 550 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 551 |
+
|
| 552 |
+
Returns:
|
| 553 |
+
An object that is both a Call for the RPC and an iterator of
|
| 554 |
+
response values. Drawing response values from the returned
|
| 555 |
+
Call-iterator may raise RpcError indicating termination of
|
| 556 |
+
the RPC with non-OK status. This object *should* also fulfill the
|
| 557 |
+
Future interface, though it may not.
|
| 558 |
+
"""
|
| 559 |
+
raise NotImplementedError()
|
| 560 |
+
|
| 561 |
+
|
| 562 |
+
############ Authentication & Authorization Interfaces & Classes #############
|
| 563 |
+
|
| 564 |
+
|
| 565 |
+
class ChannelCredentials(object):
|
| 566 |
+
"""An encapsulation of the data required to create a secure Channel.
|
| 567 |
+
|
| 568 |
+
This class has no supported interface - it exists to define the type of its
|
| 569 |
+
instances and its instances exist to be passed to other functions. For
|
| 570 |
+
example, ssl_channel_credentials returns an instance of this class and
|
| 571 |
+
secure_channel requires an instance of this class.
|
| 572 |
+
"""
|
| 573 |
+
|
| 574 |
+
def __init__(self, credentials):
|
| 575 |
+
self._credentials = credentials
|
| 576 |
+
|
| 577 |
+
|
| 578 |
+
class CallCredentials(object):
|
| 579 |
+
"""An encapsulation of the data required to assert an identity over a call.
|
| 580 |
+
|
| 581 |
+
A CallCredentials has to be used with secure Channel, otherwise the
|
| 582 |
+
metadata will not be transmitted to the server.
|
| 583 |
+
|
| 584 |
+
A CallCredentials may be composed with ChannelCredentials to always assert
|
| 585 |
+
identity for every call over that Channel.
|
| 586 |
+
|
| 587 |
+
This class has no supported interface - it exists to define the type of its
|
| 588 |
+
instances and its instances exist to be passed to other functions.
|
| 589 |
+
"""
|
| 590 |
+
|
| 591 |
+
def __init__(self, credentials):
|
| 592 |
+
self._credentials = credentials
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
class AuthMetadataContext(six.with_metaclass(abc.ABCMeta)):
|
| 596 |
+
"""Provides information to call credentials metadata plugins.
|
| 597 |
+
|
| 598 |
+
Attributes:
|
| 599 |
+
service_url: A string URL of the service being called into.
|
| 600 |
+
method_name: A string of the fully qualified method name being called.
|
| 601 |
+
"""
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)):
|
| 605 |
+
"""Callback object received by a metadata plugin."""
|
| 606 |
+
|
| 607 |
+
def __call__(self, metadata, error):
|
| 608 |
+
"""Passes to the gRPC runtime authentication metadata for an RPC.
|
| 609 |
+
|
| 610 |
+
Args:
|
| 611 |
+
metadata: The :term:`metadata` used to construct the CallCredentials.
|
| 612 |
+
error: An Exception to indicate error or None to indicate success.
|
| 613 |
+
"""
|
| 614 |
+
raise NotImplementedError()
|
| 615 |
+
|
| 616 |
+
|
| 617 |
+
class AuthMetadataPlugin(six.with_metaclass(abc.ABCMeta)):
|
| 618 |
+
"""A specification for custom authentication."""
|
| 619 |
+
|
| 620 |
+
def __call__(self, context, callback):
|
| 621 |
+
"""Implements authentication by passing metadata to a callback.
|
| 622 |
+
|
| 623 |
+
This method will be invoked asynchronously in a separate thread.
|
| 624 |
+
|
| 625 |
+
Args:
|
| 626 |
+
context: An AuthMetadataContext providing information on the RPC that
|
| 627 |
+
the plugin is being called to authenticate.
|
| 628 |
+
callback: An AuthMetadataPluginCallback to be invoked either
|
| 629 |
+
synchronously or asynchronously.
|
| 630 |
+
"""
|
| 631 |
+
raise NotImplementedError()
|
| 632 |
+
|
| 633 |
+
|
| 634 |
+
class ServerCredentials(object):
|
| 635 |
+
"""An encapsulation of the data required to open a secure port on a Server.
|
| 636 |
+
|
| 637 |
+
This class has no supported interface - it exists to define the type of its
|
| 638 |
+
instances and its instances exist to be passed to other functions.
|
| 639 |
+
"""
|
| 640 |
+
|
| 641 |
+
def __init__(self, credentials):
|
| 642 |
+
self._credentials = credentials
|
| 643 |
+
|
| 644 |
+
|
| 645 |
+
class ServerCertificateConfiguration(object):
|
| 646 |
+
"""A certificate configuration for use with an SSL-enabled Server.
|
| 647 |
+
|
| 648 |
+
Instances of this class can be returned in the certificate configuration
|
| 649 |
+
fetching callback.
|
| 650 |
+
|
| 651 |
+
This class has no supported interface -- it exists to define the
|
| 652 |
+
type of its instances and its instances exist to be passed to
|
| 653 |
+
other functions.
|
| 654 |
+
"""
|
| 655 |
+
|
| 656 |
+
def __init__(self, certificate_configuration):
|
| 657 |
+
self._certificate_configuration = certificate_configuration
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
######################## Multi-Callable Interfaces ###########################
|
| 661 |
+
|
| 662 |
+
|
| 663 |
+
class UnaryUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
|
| 664 |
+
"""Affords invoking a unary-unary RPC from client-side."""
|
| 665 |
+
|
| 666 |
+
@abc.abstractmethod
|
| 667 |
+
def __call__(self,
|
| 668 |
+
request,
|
| 669 |
+
timeout=None,
|
| 670 |
+
metadata=None,
|
| 671 |
+
credentials=None,
|
| 672 |
+
wait_for_ready=None,
|
| 673 |
+
compression=None):
|
| 674 |
+
"""Synchronously invokes the underlying RPC.
|
| 675 |
+
|
| 676 |
+
Args:
|
| 677 |
+
request: The request value for the RPC.
|
| 678 |
+
timeout: An optional duration of time in seconds to allow
|
| 679 |
+
for the RPC.
|
| 680 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 681 |
+
service-side of the RPC.
|
| 682 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 683 |
+
secure Channel.
|
| 684 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 685 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 686 |
+
compression: An element of grpc.compression, e.g.
|
| 687 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 688 |
+
|
| 689 |
+
Returns:
|
| 690 |
+
The response value for the RPC.
|
| 691 |
+
|
| 692 |
+
Raises:
|
| 693 |
+
RpcError: Indicating that the RPC terminated with non-OK status. The
|
| 694 |
+
raised RpcError will also be a Call for the RPC affording the RPC's
|
| 695 |
+
metadata, status code, and details.
|
| 696 |
+
"""
|
| 697 |
+
raise NotImplementedError()
|
| 698 |
+
|
| 699 |
+
@abc.abstractmethod
|
| 700 |
+
def with_call(self,
|
| 701 |
+
request,
|
| 702 |
+
timeout=None,
|
| 703 |
+
metadata=None,
|
| 704 |
+
credentials=None,
|
| 705 |
+
wait_for_ready=None,
|
| 706 |
+
compression=None):
|
| 707 |
+
"""Synchronously invokes the underlying RPC.
|
| 708 |
+
|
| 709 |
+
Args:
|
| 710 |
+
request: The request value for the RPC.
|
| 711 |
+
timeout: An optional durating of time in seconds to allow for
|
| 712 |
+
the RPC.
|
| 713 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 714 |
+
service-side of the RPC.
|
| 715 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 716 |
+
secure Channel.
|
| 717 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 718 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 719 |
+
compression: An element of grpc.compression, e.g.
|
| 720 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 721 |
+
|
| 722 |
+
Returns:
|
| 723 |
+
The response value for the RPC and a Call value for the RPC.
|
| 724 |
+
|
| 725 |
+
Raises:
|
| 726 |
+
RpcError: Indicating that the RPC terminated with non-OK status. The
|
| 727 |
+
raised RpcError will also be a Call for the RPC affording the RPC's
|
| 728 |
+
metadata, status code, and details.
|
| 729 |
+
"""
|
| 730 |
+
raise NotImplementedError()
|
| 731 |
+
|
| 732 |
+
@abc.abstractmethod
|
| 733 |
+
def future(self,
|
| 734 |
+
request,
|
| 735 |
+
timeout=None,
|
| 736 |
+
metadata=None,
|
| 737 |
+
credentials=None,
|
| 738 |
+
wait_for_ready=None,
|
| 739 |
+
compression=None):
|
| 740 |
+
"""Asynchronously invokes the underlying RPC.
|
| 741 |
+
|
| 742 |
+
Args:
|
| 743 |
+
request: The request value for the RPC.
|
| 744 |
+
timeout: An optional duration of time in seconds to allow for
|
| 745 |
+
the RPC.
|
| 746 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 747 |
+
service-side of the RPC.
|
| 748 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 749 |
+
secure Channel.
|
| 750 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 751 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 752 |
+
compression: An element of grpc.compression, e.g.
|
| 753 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 754 |
+
|
| 755 |
+
Returns:
|
| 756 |
+
An object that is both a Call for the RPC and a Future.
|
| 757 |
+
In the event of RPC completion, the return Call-Future's result
|
| 758 |
+
value will be the response message of the RPC.
|
| 759 |
+
Should the event terminate with non-OK status,
|
| 760 |
+
the returned Call-Future's exception value will be an RpcError.
|
| 761 |
+
"""
|
| 762 |
+
raise NotImplementedError()
|
| 763 |
+
|
| 764 |
+
|
| 765 |
+
class UnaryStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
|
| 766 |
+
"""Affords invoking a unary-stream RPC from client-side."""
|
| 767 |
+
|
| 768 |
+
@abc.abstractmethod
|
| 769 |
+
def __call__(self,
|
| 770 |
+
request,
|
| 771 |
+
timeout=None,
|
| 772 |
+
metadata=None,
|
| 773 |
+
credentials=None,
|
| 774 |
+
wait_for_ready=None,
|
| 775 |
+
compression=None):
|
| 776 |
+
"""Invokes the underlying RPC.
|
| 777 |
+
|
| 778 |
+
Args:
|
| 779 |
+
request: The request value for the RPC.
|
| 780 |
+
timeout: An optional duration of time in seconds to allow for
|
| 781 |
+
the RPC. If None, the timeout is considered infinite.
|
| 782 |
+
metadata: An optional :term:`metadata` to be transmitted to the
|
| 783 |
+
service-side of the RPC.
|
| 784 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 785 |
+
secure Channel.
|
| 786 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 787 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 788 |
+
compression: An element of grpc.compression, e.g.
|
| 789 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 790 |
+
|
| 791 |
+
Returns:
|
| 792 |
+
An object that is a Call for the RPC, an iterator of response
|
| 793 |
+
values, and a Future for the RPC. Drawing response values from the
|
| 794 |
+
returned Call-iterator may raise RpcError indicating termination of
|
| 795 |
+
the RPC with non-OK status.
|
| 796 |
+
"""
|
| 797 |
+
raise NotImplementedError()
|
| 798 |
+
|
| 799 |
+
|
| 800 |
+
class StreamUnaryMultiCallable(six.with_metaclass(abc.ABCMeta)):
|
| 801 |
+
"""Affords invoking a stream-unary RPC from client-side."""
|
| 802 |
+
|
| 803 |
+
@abc.abstractmethod
|
| 804 |
+
def __call__(self,
|
| 805 |
+
request_iterator,
|
| 806 |
+
timeout=None,
|
| 807 |
+
metadata=None,
|
| 808 |
+
credentials=None,
|
| 809 |
+
wait_for_ready=None,
|
| 810 |
+
compression=None):
|
| 811 |
+
"""Synchronously invokes the underlying RPC.
|
| 812 |
+
|
| 813 |
+
Args:
|
| 814 |
+
request_iterator: An iterator that yields request values for
|
| 815 |
+
the RPC.
|
| 816 |
+
timeout: An optional duration of time in seconds to allow for
|
| 817 |
+
the RPC. If None, the timeout is considered infinite.
|
| 818 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 819 |
+
service-side of the RPC.
|
| 820 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 821 |
+
secure Channel.
|
| 822 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 823 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 824 |
+
compression: An element of grpc.compression, e.g.
|
| 825 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 826 |
+
|
| 827 |
+
Returns:
|
| 828 |
+
The response value for the RPC.
|
| 829 |
+
|
| 830 |
+
Raises:
|
| 831 |
+
RpcError: Indicating that the RPC terminated with non-OK status. The
|
| 832 |
+
raised RpcError will also implement grpc.Call, affording methods
|
| 833 |
+
such as metadata, code, and details.
|
| 834 |
+
"""
|
| 835 |
+
raise NotImplementedError()
|
| 836 |
+
|
| 837 |
+
@abc.abstractmethod
|
| 838 |
+
def with_call(self,
|
| 839 |
+
request_iterator,
|
| 840 |
+
timeout=None,
|
| 841 |
+
metadata=None,
|
| 842 |
+
credentials=None,
|
| 843 |
+
wait_for_ready=None,
|
| 844 |
+
compression=None):
|
| 845 |
+
"""Synchronously invokes the underlying RPC on the client.
|
| 846 |
+
|
| 847 |
+
Args:
|
| 848 |
+
request_iterator: An iterator that yields request values for
|
| 849 |
+
the RPC.
|
| 850 |
+
timeout: An optional duration of time in seconds to allow for
|
| 851 |
+
the RPC. If None, the timeout is considered infinite.
|
| 852 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 853 |
+
service-side of the RPC.
|
| 854 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 855 |
+
secure Channel.
|
| 856 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 857 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 858 |
+
compression: An element of grpc.compression, e.g.
|
| 859 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 860 |
+
|
| 861 |
+
Returns:
|
| 862 |
+
The response value for the RPC and a Call object for the RPC.
|
| 863 |
+
|
| 864 |
+
Raises:
|
| 865 |
+
RpcError: Indicating that the RPC terminated with non-OK status. The
|
| 866 |
+
raised RpcError will also be a Call for the RPC affording the RPC's
|
| 867 |
+
metadata, status code, and details.
|
| 868 |
+
"""
|
| 869 |
+
raise NotImplementedError()
|
| 870 |
+
|
| 871 |
+
@abc.abstractmethod
|
| 872 |
+
def future(self,
|
| 873 |
+
request_iterator,
|
| 874 |
+
timeout=None,
|
| 875 |
+
metadata=None,
|
| 876 |
+
credentials=None,
|
| 877 |
+
wait_for_ready=None,
|
| 878 |
+
compression=None):
|
| 879 |
+
"""Asynchronously invokes the underlying RPC on the client.
|
| 880 |
+
|
| 881 |
+
Args:
|
| 882 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 883 |
+
timeout: An optional duration of time in seconds to allow for
|
| 884 |
+
the RPC. If None, the timeout is considered infinite.
|
| 885 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 886 |
+
service-side of the RPC.
|
| 887 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 888 |
+
secure Channel.
|
| 889 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 890 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 891 |
+
compression: An element of grpc.compression, e.g.
|
| 892 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 893 |
+
|
| 894 |
+
Returns:
|
| 895 |
+
An object that is both a Call for the RPC and a Future.
|
| 896 |
+
In the event of RPC completion, the return Call-Future's result value
|
| 897 |
+
will be the response message of the RPC. Should the event terminate
|
| 898 |
+
with non-OK status, the returned Call-Future's exception value will
|
| 899 |
+
be an RpcError.
|
| 900 |
+
"""
|
| 901 |
+
raise NotImplementedError()
|
| 902 |
+
|
| 903 |
+
|
| 904 |
+
class StreamStreamMultiCallable(six.with_metaclass(abc.ABCMeta)):
|
| 905 |
+
"""Affords invoking a stream-stream RPC on client-side."""
|
| 906 |
+
|
| 907 |
+
@abc.abstractmethod
|
| 908 |
+
def __call__(self,
|
| 909 |
+
request_iterator,
|
| 910 |
+
timeout=None,
|
| 911 |
+
metadata=None,
|
| 912 |
+
credentials=None,
|
| 913 |
+
wait_for_ready=None,
|
| 914 |
+
compression=None):
|
| 915 |
+
"""Invokes the underlying RPC on the client.
|
| 916 |
+
|
| 917 |
+
Args:
|
| 918 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 919 |
+
timeout: An optional duration of time in seconds to allow for
|
| 920 |
+
the RPC. If not specified, the timeout is considered infinite.
|
| 921 |
+
metadata: Optional :term:`metadata` to be transmitted to the
|
| 922 |
+
service-side of the RPC.
|
| 923 |
+
credentials: An optional CallCredentials for the RPC. Only valid for
|
| 924 |
+
secure Channel.
|
| 925 |
+
wait_for_ready: This is an EXPERIMENTAL argument. An optional
|
| 926 |
+
flag to enable :term:`wait_for_ready` mechanism.
|
| 927 |
+
compression: An element of grpc.compression, e.g.
|
| 928 |
+
grpc.compression.Gzip. This is an EXPERIMENTAL option.
|
| 929 |
+
|
| 930 |
+
Returns:
|
| 931 |
+
An object that is a Call for the RPC, an iterator of response
|
| 932 |
+
values, and a Future for the RPC. Drawing response values from the
|
| 933 |
+
returned Call-iterator may raise RpcError indicating termination of
|
| 934 |
+
the RPC with non-OK status.
|
| 935 |
+
"""
|
| 936 |
+
raise NotImplementedError()
|
| 937 |
+
|
| 938 |
+
|
| 939 |
+
############################# Channel Interface ##############################
|
| 940 |
+
|
| 941 |
+
|
| 942 |
+
class Channel(six.with_metaclass(abc.ABCMeta)):
|
| 943 |
+
"""Affords RPC invocation via generic methods on client-side.
|
| 944 |
+
|
| 945 |
+
Channel objects implement the Context Manager type, although they need not
|
| 946 |
+
support being entered and exited multiple times.
|
| 947 |
+
"""
|
| 948 |
+
|
| 949 |
+
@abc.abstractmethod
|
| 950 |
+
def subscribe(self, callback, try_to_connect=False):
|
| 951 |
+
"""Subscribe to this Channel's connectivity state machine.
|
| 952 |
+
|
| 953 |
+
A Channel may be in any of the states described by ChannelConnectivity.
|
| 954 |
+
This method allows application to monitor the state transitions.
|
| 955 |
+
The typical use case is to debug or gain better visibility into gRPC
|
| 956 |
+
runtime's state.
|
| 957 |
+
|
| 958 |
+
Args:
|
| 959 |
+
callback: A callable to be invoked with ChannelConnectivity argument.
|
| 960 |
+
ChannelConnectivity describes current state of the channel.
|
| 961 |
+
The callable will be invoked immediately upon subscription
|
| 962 |
+
and again for every change to ChannelConnectivity until it
|
| 963 |
+
is unsubscribed or this Channel object goes out of scope.
|
| 964 |
+
try_to_connect: A boolean indicating whether or not this Channel
|
| 965 |
+
should attempt to connect immediately. If set to False, gRPC
|
| 966 |
+
runtime decides when to connect.
|
| 967 |
+
"""
|
| 968 |
+
raise NotImplementedError()
|
| 969 |
+
|
| 970 |
+
@abc.abstractmethod
|
| 971 |
+
def unsubscribe(self, callback):
|
| 972 |
+
"""Unsubscribes a subscribed callback from this Channel's connectivity.
|
| 973 |
+
|
| 974 |
+
Args:
|
| 975 |
+
callback: A callable previously registered with this Channel from
|
| 976 |
+
having been passed to its "subscribe" method.
|
| 977 |
+
"""
|
| 978 |
+
raise NotImplementedError()
|
| 979 |
+
|
| 980 |
+
@abc.abstractmethod
|
| 981 |
+
def unary_unary(self,
|
| 982 |
+
method,
|
| 983 |
+
request_serializer=None,
|
| 984 |
+
response_deserializer=None):
|
| 985 |
+
"""Creates a UnaryUnaryMultiCallable for a unary-unary method.
|
| 986 |
+
|
| 987 |
+
Args:
|
| 988 |
+
method: The name of the RPC method.
|
| 989 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 990 |
+
message. Request goes unserialized in case None is passed.
|
| 991 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the
|
| 992 |
+
response message. Response goes undeserialized in case None
|
| 993 |
+
is passed.
|
| 994 |
+
|
| 995 |
+
Returns:
|
| 996 |
+
A UnaryUnaryMultiCallable value for the named unary-unary method.
|
| 997 |
+
"""
|
| 998 |
+
raise NotImplementedError()
|
| 999 |
+
|
| 1000 |
+
@abc.abstractmethod
|
| 1001 |
+
def unary_stream(self,
|
| 1002 |
+
method,
|
| 1003 |
+
request_serializer=None,
|
| 1004 |
+
response_deserializer=None):
|
| 1005 |
+
"""Creates a UnaryStreamMultiCallable for a unary-stream method.
|
| 1006 |
+
|
| 1007 |
+
Args:
|
| 1008 |
+
method: The name of the RPC method.
|
| 1009 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 1010 |
+
message. Request goes unserialized in case None is passed.
|
| 1011 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the
|
| 1012 |
+
response message. Response goes undeserialized in case None is
|
| 1013 |
+
passed.
|
| 1014 |
+
|
| 1015 |
+
Returns:
|
| 1016 |
+
A UnaryStreamMultiCallable value for the name unary-stream method.
|
| 1017 |
+
"""
|
| 1018 |
+
raise NotImplementedError()
|
| 1019 |
+
|
| 1020 |
+
@abc.abstractmethod
|
| 1021 |
+
def stream_unary(self,
|
| 1022 |
+
method,
|
| 1023 |
+
request_serializer=None,
|
| 1024 |
+
response_deserializer=None):
|
| 1025 |
+
"""Creates a StreamUnaryMultiCallable for a stream-unary method.
|
| 1026 |
+
|
| 1027 |
+
Args:
|
| 1028 |
+
method: The name of the RPC method.
|
| 1029 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 1030 |
+
message. Request goes unserialized in case None is passed.
|
| 1031 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the
|
| 1032 |
+
response message. Response goes undeserialized in case None is
|
| 1033 |
+
passed.
|
| 1034 |
+
|
| 1035 |
+
Returns:
|
| 1036 |
+
A StreamUnaryMultiCallable value for the named stream-unary method.
|
| 1037 |
+
"""
|
| 1038 |
+
raise NotImplementedError()
|
| 1039 |
+
|
| 1040 |
+
@abc.abstractmethod
|
| 1041 |
+
def stream_stream(self,
|
| 1042 |
+
method,
|
| 1043 |
+
request_serializer=None,
|
| 1044 |
+
response_deserializer=None):
|
| 1045 |
+
"""Creates a StreamStreamMultiCallable for a stream-stream method.
|
| 1046 |
+
|
| 1047 |
+
Args:
|
| 1048 |
+
method: The name of the RPC method.
|
| 1049 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 1050 |
+
message. Request goes unserialized in case None is passed.
|
| 1051 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the
|
| 1052 |
+
response message. Response goes undeserialized in case None
|
| 1053 |
+
is passed.
|
| 1054 |
+
|
| 1055 |
+
Returns:
|
| 1056 |
+
A StreamStreamMultiCallable value for the named stream-stream method.
|
| 1057 |
+
"""
|
| 1058 |
+
raise NotImplementedError()
|
| 1059 |
+
|
| 1060 |
+
@abc.abstractmethod
|
| 1061 |
+
def close(self):
|
| 1062 |
+
"""Closes this Channel and releases all resources held by it.
|
| 1063 |
+
|
| 1064 |
+
Closing the Channel will immediately terminate all RPCs active with the
|
| 1065 |
+
Channel and it is not valid to invoke new RPCs with the Channel.
|
| 1066 |
+
|
| 1067 |
+
This method is idempotent.
|
| 1068 |
+
"""
|
| 1069 |
+
raise NotImplementedError()
|
| 1070 |
+
|
| 1071 |
+
def __enter__(self):
|
| 1072 |
+
"""Enters the runtime context related to the channel object."""
|
| 1073 |
+
raise NotImplementedError()
|
| 1074 |
+
|
| 1075 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 1076 |
+
"""Exits the runtime context related to the channel object."""
|
| 1077 |
+
raise NotImplementedError()
|
| 1078 |
+
|
| 1079 |
+
|
| 1080 |
+
########################## Service-Side Context ##############################
|
| 1081 |
+
|
| 1082 |
+
|
| 1083 |
+
class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)):
|
| 1084 |
+
"""A context object passed to method implementations."""
|
| 1085 |
+
|
| 1086 |
+
@abc.abstractmethod
|
| 1087 |
+
def invocation_metadata(self):
|
| 1088 |
+
"""Accesses the metadata from the sent by the client.
|
| 1089 |
+
|
| 1090 |
+
Returns:
|
| 1091 |
+
The invocation :term:`metadata`.
|
| 1092 |
+
"""
|
| 1093 |
+
raise NotImplementedError()
|
| 1094 |
+
|
| 1095 |
+
@abc.abstractmethod
|
| 1096 |
+
def peer(self):
|
| 1097 |
+
"""Identifies the peer that invoked the RPC being serviced.
|
| 1098 |
+
|
| 1099 |
+
Returns:
|
| 1100 |
+
A string identifying the peer that invoked the RPC being serviced.
|
| 1101 |
+
The string format is determined by gRPC runtime.
|
| 1102 |
+
"""
|
| 1103 |
+
raise NotImplementedError()
|
| 1104 |
+
|
| 1105 |
+
@abc.abstractmethod
|
| 1106 |
+
def peer_identities(self):
|
| 1107 |
+
"""Gets one or more peer identity(s).
|
| 1108 |
+
|
| 1109 |
+
Equivalent to
|
| 1110 |
+
servicer_context.auth_context().get(servicer_context.peer_identity_key())
|
| 1111 |
+
|
| 1112 |
+
Returns:
|
| 1113 |
+
An iterable of the identities, or None if the call is not
|
| 1114 |
+
authenticated. Each identity is returned as a raw bytes type.
|
| 1115 |
+
"""
|
| 1116 |
+
raise NotImplementedError()
|
| 1117 |
+
|
| 1118 |
+
@abc.abstractmethod
|
| 1119 |
+
def peer_identity_key(self):
|
| 1120 |
+
"""The auth property used to identify the peer.
|
| 1121 |
+
|
| 1122 |
+
For example, "x509_common_name" or "x509_subject_alternative_name" are
|
| 1123 |
+
used to identify an SSL peer.
|
| 1124 |
+
|
| 1125 |
+
Returns:
|
| 1126 |
+
The auth property (string) that indicates the
|
| 1127 |
+
peer identity, or None if the call is not authenticated.
|
| 1128 |
+
"""
|
| 1129 |
+
raise NotImplementedError()
|
| 1130 |
+
|
| 1131 |
+
@abc.abstractmethod
|
| 1132 |
+
def auth_context(self):
|
| 1133 |
+
"""Gets the auth context for the call.
|
| 1134 |
+
|
| 1135 |
+
Returns:
|
| 1136 |
+
A map of strings to an iterable of bytes for each auth property.
|
| 1137 |
+
"""
|
| 1138 |
+
raise NotImplementedError()
|
| 1139 |
+
|
| 1140 |
+
def set_compression(self, compression):
|
| 1141 |
+
"""Set the compression algorithm to be used for the entire call.
|
| 1142 |
+
|
| 1143 |
+
This is an EXPERIMENTAL method.
|
| 1144 |
+
|
| 1145 |
+
Args:
|
| 1146 |
+
compression: An element of grpc.compression, e.g.
|
| 1147 |
+
grpc.compression.Gzip.
|
| 1148 |
+
"""
|
| 1149 |
+
raise NotImplementedError()
|
| 1150 |
+
|
| 1151 |
+
@abc.abstractmethod
|
| 1152 |
+
def send_initial_metadata(self, initial_metadata):
|
| 1153 |
+
"""Sends the initial metadata value to the client.
|
| 1154 |
+
|
| 1155 |
+
This method need not be called by implementations if they have no
|
| 1156 |
+
metadata to add to what the gRPC runtime will transmit.
|
| 1157 |
+
|
| 1158 |
+
Args:
|
| 1159 |
+
initial_metadata: The initial :term:`metadata`.
|
| 1160 |
+
"""
|
| 1161 |
+
raise NotImplementedError()
|
| 1162 |
+
|
| 1163 |
+
@abc.abstractmethod
|
| 1164 |
+
def set_trailing_metadata(self, trailing_metadata):
|
| 1165 |
+
"""Sets the trailing metadata for the RPC.
|
| 1166 |
+
|
| 1167 |
+
Sets the trailing metadata to be sent upon completion of the RPC.
|
| 1168 |
+
|
| 1169 |
+
If this method is invoked multiple times throughout the lifetime of an
|
| 1170 |
+
RPC, the value supplied in the final invocation will be the value sent
|
| 1171 |
+
over the wire.
|
| 1172 |
+
|
| 1173 |
+
This method need not be called by implementations if they have no
|
| 1174 |
+
metadata to add to what the gRPC runtime will transmit.
|
| 1175 |
+
|
| 1176 |
+
Args:
|
| 1177 |
+
trailing_metadata: The trailing :term:`metadata`.
|
| 1178 |
+
"""
|
| 1179 |
+
raise NotImplementedError()
|
| 1180 |
+
|
| 1181 |
+
def trailing_metadata(self):
|
| 1182 |
+
"""Access value to be used as trailing metadata upon RPC completion.
|
| 1183 |
+
|
| 1184 |
+
This is an EXPERIMENTAL API.
|
| 1185 |
+
|
| 1186 |
+
Returns:
|
| 1187 |
+
The trailing :term:`metadata` for the RPC.
|
| 1188 |
+
"""
|
| 1189 |
+
raise NotImplementedError()
|
| 1190 |
+
|
| 1191 |
+
@abc.abstractmethod
|
| 1192 |
+
def abort(self, code, details):
|
| 1193 |
+
"""Raises an exception to terminate the RPC with a non-OK status.
|
| 1194 |
+
|
| 1195 |
+
The code and details passed as arguments will supercede any existing
|
| 1196 |
+
ones.
|
| 1197 |
+
|
| 1198 |
+
Args:
|
| 1199 |
+
code: A StatusCode object to be sent to the client.
|
| 1200 |
+
It must not be StatusCode.OK.
|
| 1201 |
+
details: A UTF-8-encodable string to be sent to the client upon
|
| 1202 |
+
termination of the RPC.
|
| 1203 |
+
|
| 1204 |
+
Raises:
|
| 1205 |
+
Exception: An exception is always raised to signal the abortion the
|
| 1206 |
+
RPC to the gRPC runtime.
|
| 1207 |
+
"""
|
| 1208 |
+
raise NotImplementedError()
|
| 1209 |
+
|
| 1210 |
+
@abc.abstractmethod
|
| 1211 |
+
def abort_with_status(self, status):
|
| 1212 |
+
"""Raises an exception to terminate the RPC with a non-OK status.
|
| 1213 |
+
|
| 1214 |
+
The status passed as argument will supercede any existing status code,
|
| 1215 |
+
status message and trailing metadata.
|
| 1216 |
+
|
| 1217 |
+
This is an EXPERIMENTAL API.
|
| 1218 |
+
|
| 1219 |
+
Args:
|
| 1220 |
+
status: A grpc.Status object. The status code in it must not be
|
| 1221 |
+
StatusCode.OK.
|
| 1222 |
+
|
| 1223 |
+
Raises:
|
| 1224 |
+
Exception: An exception is always raised to signal the abortion the
|
| 1225 |
+
RPC to the gRPC runtime.
|
| 1226 |
+
"""
|
| 1227 |
+
raise NotImplementedError()
|
| 1228 |
+
|
| 1229 |
+
@abc.abstractmethod
|
| 1230 |
+
def set_code(self, code):
|
| 1231 |
+
"""Sets the value to be used as status code upon RPC completion.
|
| 1232 |
+
|
| 1233 |
+
This method need not be called by method implementations if they wish
|
| 1234 |
+
the gRPC runtime to determine the status code of the RPC.
|
| 1235 |
+
|
| 1236 |
+
Args:
|
| 1237 |
+
code: A StatusCode object to be sent to the client.
|
| 1238 |
+
"""
|
| 1239 |
+
raise NotImplementedError()
|
| 1240 |
+
|
| 1241 |
+
@abc.abstractmethod
|
| 1242 |
+
def set_details(self, details):
|
| 1243 |
+
"""Sets the value to be used as detail string upon RPC completion.
|
| 1244 |
+
|
| 1245 |
+
This method need not be called by method implementations if they have
|
| 1246 |
+
no details to transmit.
|
| 1247 |
+
|
| 1248 |
+
Args:
|
| 1249 |
+
details: A UTF-8-encodable string to be sent to the client upon
|
| 1250 |
+
termination of the RPC.
|
| 1251 |
+
"""
|
| 1252 |
+
raise NotImplementedError()
|
| 1253 |
+
|
| 1254 |
+
def code(self):
|
| 1255 |
+
"""Accesses the value to be used as status code upon RPC completion.
|
| 1256 |
+
|
| 1257 |
+
This is an EXPERIMENTAL API.
|
| 1258 |
+
|
| 1259 |
+
Returns:
|
| 1260 |
+
The StatusCode value for the RPC.
|
| 1261 |
+
"""
|
| 1262 |
+
raise NotImplementedError()
|
| 1263 |
+
|
| 1264 |
+
def details(self):
|
| 1265 |
+
"""Accesses the value to be used as detail string upon RPC completion.
|
| 1266 |
+
|
| 1267 |
+
This is an EXPERIMENTAL API.
|
| 1268 |
+
|
| 1269 |
+
Returns:
|
| 1270 |
+
The details string of the RPC.
|
| 1271 |
+
"""
|
| 1272 |
+
raise NotImplementedError()
|
| 1273 |
+
|
| 1274 |
+
def disable_next_message_compression(self):
|
| 1275 |
+
"""Disables compression for the next response message.
|
| 1276 |
+
|
| 1277 |
+
This is an EXPERIMENTAL method.
|
| 1278 |
+
|
| 1279 |
+
This method will override any compression configuration set during
|
| 1280 |
+
server creation or set on the call.
|
| 1281 |
+
"""
|
| 1282 |
+
raise NotImplementedError()
|
| 1283 |
+
|
| 1284 |
+
|
| 1285 |
+
##################### Service-Side Handler Interfaces ########################
|
| 1286 |
+
|
| 1287 |
+
|
| 1288 |
+
class RpcMethodHandler(six.with_metaclass(abc.ABCMeta)):
|
| 1289 |
+
"""An implementation of a single RPC method.
|
| 1290 |
+
|
| 1291 |
+
Attributes:
|
| 1292 |
+
request_streaming: Whether the RPC supports exactly one request message
|
| 1293 |
+
or any arbitrary number of request messages.
|
| 1294 |
+
response_streaming: Whether the RPC supports exactly one response message
|
| 1295 |
+
or any arbitrary number of response messages.
|
| 1296 |
+
request_deserializer: A callable :term:`deserializer` that accepts a byte string and
|
| 1297 |
+
returns an object suitable to be passed to this object's business
|
| 1298 |
+
logic, or None to indicate that this object's business logic should be
|
| 1299 |
+
passed the raw request bytes.
|
| 1300 |
+
response_serializer: A callable :term:`serializer` that accepts an object produced
|
| 1301 |
+
by this object's business logic and returns a byte string, or None to
|
| 1302 |
+
indicate that the byte strings produced by this object's business logic
|
| 1303 |
+
should be transmitted on the wire as they are.
|
| 1304 |
+
unary_unary: This object's application-specific business logic as a
|
| 1305 |
+
callable value that takes a request value and a ServicerContext object
|
| 1306 |
+
and returns a response value. Only non-None if both request_streaming
|
| 1307 |
+
and response_streaming are False.
|
| 1308 |
+
unary_stream: This object's application-specific business logic as a
|
| 1309 |
+
callable value that takes a request value and a ServicerContext object
|
| 1310 |
+
and returns an iterator of response values. Only non-None if
|
| 1311 |
+
request_streaming is False and response_streaming is True.
|
| 1312 |
+
stream_unary: This object's application-specific business logic as a
|
| 1313 |
+
callable value that takes an iterator of request values and a
|
| 1314 |
+
ServicerContext object and returns a response value. Only non-None if
|
| 1315 |
+
request_streaming is True and response_streaming is False.
|
| 1316 |
+
stream_stream: This object's application-specific business logic as a
|
| 1317 |
+
callable value that takes an iterator of request values and a
|
| 1318 |
+
ServicerContext object and returns an iterator of response values.
|
| 1319 |
+
Only non-None if request_streaming and response_streaming are both
|
| 1320 |
+
True.
|
| 1321 |
+
"""
|
| 1322 |
+
|
| 1323 |
+
|
| 1324 |
+
class HandlerCallDetails(six.with_metaclass(abc.ABCMeta)):
|
| 1325 |
+
"""Describes an RPC that has just arrived for service.
|
| 1326 |
+
|
| 1327 |
+
Attributes:
|
| 1328 |
+
method: The method name of the RPC.
|
| 1329 |
+
invocation_metadata: The :term:`metadata` sent by the client.
|
| 1330 |
+
"""
|
| 1331 |
+
|
| 1332 |
+
|
| 1333 |
+
class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)):
|
| 1334 |
+
"""An implementation of arbitrarily many RPC methods."""
|
| 1335 |
+
|
| 1336 |
+
@abc.abstractmethod
|
| 1337 |
+
def service(self, handler_call_details):
|
| 1338 |
+
"""Returns the handler for servicing the RPC.
|
| 1339 |
+
|
| 1340 |
+
Args:
|
| 1341 |
+
handler_call_details: A HandlerCallDetails describing the RPC.
|
| 1342 |
+
|
| 1343 |
+
Returns:
|
| 1344 |
+
An RpcMethodHandler with which the RPC may be serviced if the
|
| 1345 |
+
implementation chooses to service this RPC, or None otherwise.
|
| 1346 |
+
"""
|
| 1347 |
+
raise NotImplementedError()
|
| 1348 |
+
|
| 1349 |
+
|
| 1350 |
+
class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)):
|
| 1351 |
+
"""An implementation of RPC methods belonging to a service.
|
| 1352 |
+
|
| 1353 |
+
A service handles RPC methods with structured names of the form
|
| 1354 |
+
'/Service.Name/Service.Method', where 'Service.Name' is the value
|
| 1355 |
+
returned by service_name(), and 'Service.Method' is the method
|
| 1356 |
+
name. A service can have multiple method names, but only a single
|
| 1357 |
+
service name.
|
| 1358 |
+
"""
|
| 1359 |
+
|
| 1360 |
+
@abc.abstractmethod
|
| 1361 |
+
def service_name(self):
|
| 1362 |
+
"""Returns this service's name.
|
| 1363 |
+
|
| 1364 |
+
Returns:
|
| 1365 |
+
The service name.
|
| 1366 |
+
"""
|
| 1367 |
+
raise NotImplementedError()
|
| 1368 |
+
|
| 1369 |
+
|
| 1370 |
+
#################### Service-Side Interceptor Interfaces #####################
|
| 1371 |
+
|
| 1372 |
+
|
| 1373 |
+
class ServerInterceptor(six.with_metaclass(abc.ABCMeta)):
|
| 1374 |
+
"""Affords intercepting incoming RPCs on the service-side."""
|
| 1375 |
+
|
| 1376 |
+
@abc.abstractmethod
|
| 1377 |
+
def intercept_service(self, continuation, handler_call_details):
|
| 1378 |
+
"""Intercepts incoming RPCs before handing them over to a handler.
|
| 1379 |
+
|
| 1380 |
+
Args:
|
| 1381 |
+
continuation: A function that takes a HandlerCallDetails and
|
| 1382 |
+
proceeds to invoke the next interceptor in the chain, if any,
|
| 1383 |
+
or the RPC handler lookup logic, with the call details passed
|
| 1384 |
+
as an argument, and returns an RpcMethodHandler instance if
|
| 1385 |
+
the RPC is considered serviced, or None otherwise.
|
| 1386 |
+
handler_call_details: A HandlerCallDetails describing the RPC.
|
| 1387 |
+
|
| 1388 |
+
Returns:
|
| 1389 |
+
An RpcMethodHandler with which the RPC may be serviced if the
|
| 1390 |
+
interceptor chooses to service this RPC, or None otherwise.
|
| 1391 |
+
"""
|
| 1392 |
+
raise NotImplementedError()
|
| 1393 |
+
|
| 1394 |
+
|
| 1395 |
+
############################# Server Interface ###############################
|
| 1396 |
+
|
| 1397 |
+
|
| 1398 |
+
class Server(six.with_metaclass(abc.ABCMeta)):
|
| 1399 |
+
"""Services RPCs."""
|
| 1400 |
+
|
| 1401 |
+
@abc.abstractmethod
|
| 1402 |
+
def add_generic_rpc_handlers(self, generic_rpc_handlers):
|
| 1403 |
+
"""Registers GenericRpcHandlers with this Server.
|
| 1404 |
+
|
| 1405 |
+
This method is only safe to call before the server is started.
|
| 1406 |
+
|
| 1407 |
+
Args:
|
| 1408 |
+
generic_rpc_handlers: An iterable of GenericRpcHandlers that will be
|
| 1409 |
+
used to service RPCs.
|
| 1410 |
+
"""
|
| 1411 |
+
raise NotImplementedError()
|
| 1412 |
+
|
| 1413 |
+
@abc.abstractmethod
|
| 1414 |
+
def add_insecure_port(self, address):
|
| 1415 |
+
"""Opens an insecure port for accepting RPCs.
|
| 1416 |
+
|
| 1417 |
+
This method may only be called before starting the server.
|
| 1418 |
+
|
| 1419 |
+
Args:
|
| 1420 |
+
address: The address for which to open a port. If the port is 0,
|
| 1421 |
+
or not specified in the address, then gRPC runtime will choose a port.
|
| 1422 |
+
|
| 1423 |
+
Returns:
|
| 1424 |
+
An integer port on which server will accept RPC requests.
|
| 1425 |
+
"""
|
| 1426 |
+
raise NotImplementedError()
|
| 1427 |
+
|
| 1428 |
+
@abc.abstractmethod
|
| 1429 |
+
def add_secure_port(self, address, server_credentials):
|
| 1430 |
+
"""Opens a secure port for accepting RPCs.
|
| 1431 |
+
|
| 1432 |
+
This method may only be called before starting the server.
|
| 1433 |
+
|
| 1434 |
+
Args:
|
| 1435 |
+
address: The address for which to open a port.
|
| 1436 |
+
if the port is 0, or not specified in the address, then gRPC
|
| 1437 |
+
runtime will choose a port.
|
| 1438 |
+
server_credentials: A ServerCredentials object.
|
| 1439 |
+
|
| 1440 |
+
Returns:
|
| 1441 |
+
An integer port on which server will accept RPC requests.
|
| 1442 |
+
"""
|
| 1443 |
+
raise NotImplementedError()
|
| 1444 |
+
|
| 1445 |
+
@abc.abstractmethod
|
| 1446 |
+
def start(self):
|
| 1447 |
+
"""Starts this Server.
|
| 1448 |
+
|
| 1449 |
+
This method may only be called once. (i.e. it is not idempotent).
|
| 1450 |
+
"""
|
| 1451 |
+
raise NotImplementedError()
|
| 1452 |
+
|
| 1453 |
+
@abc.abstractmethod
|
| 1454 |
+
def stop(self, grace):
|
| 1455 |
+
"""Stops this Server.
|
| 1456 |
+
|
| 1457 |
+
This method immediately stop service of new RPCs in all cases.
|
| 1458 |
+
|
| 1459 |
+
If a grace period is specified, this method returns immediately
|
| 1460 |
+
and all RPCs active at the end of the grace period are aborted.
|
| 1461 |
+
If a grace period is not specified (by passing None for `grace`),
|
| 1462 |
+
all existing RPCs are aborted immediately and this method
|
| 1463 |
+
blocks until the last RPC handler terminates.
|
| 1464 |
+
|
| 1465 |
+
This method is idempotent and may be called at any time.
|
| 1466 |
+
Passing a smaller grace value in a subsequent call will have
|
| 1467 |
+
the effect of stopping the Server sooner (passing None will
|
| 1468 |
+
have the effect of stopping the server immediately). Passing
|
| 1469 |
+
a larger grace value in a subsequent call *will not* have the
|
| 1470 |
+
effect of stopping the server later (i.e. the most restrictive
|
| 1471 |
+
grace value is used).
|
| 1472 |
+
|
| 1473 |
+
Args:
|
| 1474 |
+
grace: A duration of time in seconds or None.
|
| 1475 |
+
|
| 1476 |
+
Returns:
|
| 1477 |
+
A threading.Event that will be set when this Server has completely
|
| 1478 |
+
stopped, i.e. when running RPCs either complete or are aborted and
|
| 1479 |
+
all handlers have terminated.
|
| 1480 |
+
"""
|
| 1481 |
+
raise NotImplementedError()
|
| 1482 |
+
|
| 1483 |
+
def wait_for_termination(self, timeout=None):
|
| 1484 |
+
"""Block current thread until the server stops.
|
| 1485 |
+
|
| 1486 |
+
This is an EXPERIMENTAL API.
|
| 1487 |
+
|
| 1488 |
+
The wait will not consume computational resources during blocking, and
|
| 1489 |
+
it will block until one of the two following conditions are met:
|
| 1490 |
+
|
| 1491 |
+
1) The server is stopped or terminated;
|
| 1492 |
+
2) A timeout occurs if timeout is not `None`.
|
| 1493 |
+
|
| 1494 |
+
The timeout argument works in the same way as `threading.Event.wait()`.
|
| 1495 |
+
https://docs.python.org/3/library/threading.html#threading.Event.wait
|
| 1496 |
+
|
| 1497 |
+
Args:
|
| 1498 |
+
timeout: A floating point number specifying a timeout for the
|
| 1499 |
+
operation in seconds.
|
| 1500 |
+
|
| 1501 |
+
Returns:
|
| 1502 |
+
A bool indicates if the operation times out.
|
| 1503 |
+
"""
|
| 1504 |
+
raise NotImplementedError()
|
| 1505 |
+
|
| 1506 |
+
|
| 1507 |
+
################################# Functions ################################
|
| 1508 |
+
|
| 1509 |
+
|
| 1510 |
+
def unary_unary_rpc_method_handler(behavior,
|
| 1511 |
+
request_deserializer=None,
|
| 1512 |
+
response_serializer=None):
|
| 1513 |
+
"""Creates an RpcMethodHandler for a unary-unary RPC method.
|
| 1514 |
+
|
| 1515 |
+
Args:
|
| 1516 |
+
behavior: The implementation of an RPC that accepts one request
|
| 1517 |
+
and returns one response.
|
| 1518 |
+
request_deserializer: An optional :term:`deserializer` for request deserialization.
|
| 1519 |
+
response_serializer: An optional :term:`serializer` for response serialization.
|
| 1520 |
+
|
| 1521 |
+
Returns:
|
| 1522 |
+
An RpcMethodHandler object that is typically used by grpc.Server.
|
| 1523 |
+
"""
|
| 1524 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1525 |
+
return _utilities.RpcMethodHandler(False, False, request_deserializer,
|
| 1526 |
+
response_serializer, behavior, None,
|
| 1527 |
+
None, None)
|
| 1528 |
+
|
| 1529 |
+
|
| 1530 |
+
def unary_stream_rpc_method_handler(behavior,
|
| 1531 |
+
request_deserializer=None,
|
| 1532 |
+
response_serializer=None):
|
| 1533 |
+
"""Creates an RpcMethodHandler for a unary-stream RPC method.
|
| 1534 |
+
|
| 1535 |
+
Args:
|
| 1536 |
+
behavior: The implementation of an RPC that accepts one request
|
| 1537 |
+
and returns an iterator of response values.
|
| 1538 |
+
request_deserializer: An optional :term:`deserializer` for request deserialization.
|
| 1539 |
+
response_serializer: An optional :term:`serializer` for response serialization.
|
| 1540 |
+
|
| 1541 |
+
Returns:
|
| 1542 |
+
An RpcMethodHandler object that is typically used by grpc.Server.
|
| 1543 |
+
"""
|
| 1544 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1545 |
+
return _utilities.RpcMethodHandler(False, True, request_deserializer,
|
| 1546 |
+
response_serializer, None, behavior,
|
| 1547 |
+
None, None)
|
| 1548 |
+
|
| 1549 |
+
|
| 1550 |
+
def stream_unary_rpc_method_handler(behavior,
|
| 1551 |
+
request_deserializer=None,
|
| 1552 |
+
response_serializer=None):
|
| 1553 |
+
"""Creates an RpcMethodHandler for a stream-unary RPC method.
|
| 1554 |
+
|
| 1555 |
+
Args:
|
| 1556 |
+
behavior: The implementation of an RPC that accepts an iterator of
|
| 1557 |
+
request values and returns a single response value.
|
| 1558 |
+
request_deserializer: An optional :term:`deserializer` for request deserialization.
|
| 1559 |
+
response_serializer: An optional :term:`serializer` for response serialization.
|
| 1560 |
+
|
| 1561 |
+
Returns:
|
| 1562 |
+
An RpcMethodHandler object that is typically used by grpc.Server.
|
| 1563 |
+
"""
|
| 1564 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1565 |
+
return _utilities.RpcMethodHandler(True, False, request_deserializer,
|
| 1566 |
+
response_serializer, None, None,
|
| 1567 |
+
behavior, None)
|
| 1568 |
+
|
| 1569 |
+
|
| 1570 |
+
def stream_stream_rpc_method_handler(behavior,
|
| 1571 |
+
request_deserializer=None,
|
| 1572 |
+
response_serializer=None):
|
| 1573 |
+
"""Creates an RpcMethodHandler for a stream-stream RPC method.
|
| 1574 |
+
|
| 1575 |
+
Args:
|
| 1576 |
+
behavior: The implementation of an RPC that accepts an iterator of
|
| 1577 |
+
request values and returns an iterator of response values.
|
| 1578 |
+
request_deserializer: An optional :term:`deserializer` for request deserialization.
|
| 1579 |
+
response_serializer: An optional :term:`serializer` for response serialization.
|
| 1580 |
+
|
| 1581 |
+
Returns:
|
| 1582 |
+
An RpcMethodHandler object that is typically used by grpc.Server.
|
| 1583 |
+
"""
|
| 1584 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1585 |
+
return _utilities.RpcMethodHandler(True, True, request_deserializer,
|
| 1586 |
+
response_serializer, None, None, None,
|
| 1587 |
+
behavior)
|
| 1588 |
+
|
| 1589 |
+
|
| 1590 |
+
def method_handlers_generic_handler(service, method_handlers):
|
| 1591 |
+
"""Creates a GenericRpcHandler from RpcMethodHandlers.
|
| 1592 |
+
|
| 1593 |
+
Args:
|
| 1594 |
+
service: The name of the service that is implemented by the
|
| 1595 |
+
method_handlers.
|
| 1596 |
+
method_handlers: A dictionary that maps method names to corresponding
|
| 1597 |
+
RpcMethodHandler.
|
| 1598 |
+
|
| 1599 |
+
Returns:
|
| 1600 |
+
A GenericRpcHandler. This is typically added to the grpc.Server object
|
| 1601 |
+
with add_generic_rpc_handlers() before starting the server.
|
| 1602 |
+
"""
|
| 1603 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1604 |
+
return _utilities.DictionaryGenericHandler(service, method_handlers)
|
| 1605 |
+
|
| 1606 |
+
|
| 1607 |
+
def ssl_channel_credentials(root_certificates=None,
|
| 1608 |
+
private_key=None,
|
| 1609 |
+
certificate_chain=None):
|
| 1610 |
+
"""Creates a ChannelCredentials for use with an SSL-enabled Channel.
|
| 1611 |
+
|
| 1612 |
+
Args:
|
| 1613 |
+
root_certificates: The PEM-encoded root certificates as a byte string,
|
| 1614 |
+
or None to retrieve them from a default location chosen by gRPC
|
| 1615 |
+
runtime.
|
| 1616 |
+
private_key: The PEM-encoded private key as a byte string, or None if no
|
| 1617 |
+
private key should be used.
|
| 1618 |
+
certificate_chain: The PEM-encoded certificate chain as a byte string
|
| 1619 |
+
to use or None if no certificate chain should be used.
|
| 1620 |
+
|
| 1621 |
+
Returns:
|
| 1622 |
+
A ChannelCredentials for use with an SSL-enabled Channel.
|
| 1623 |
+
"""
|
| 1624 |
+
return ChannelCredentials(
|
| 1625 |
+
_cygrpc.SSLChannelCredentials(root_certificates, private_key,
|
| 1626 |
+
certificate_chain))
|
| 1627 |
+
|
| 1628 |
+
|
| 1629 |
+
def xds_channel_credentials(fallback_credentials=None):
|
| 1630 |
+
"""Creates a ChannelCredentials for use with xDS. This is an EXPERIMENTAL
|
| 1631 |
+
API.
|
| 1632 |
+
|
| 1633 |
+
Args:
|
| 1634 |
+
fallback_credentials: Credentials to use in case it is not possible to
|
| 1635 |
+
establish a secure connection via xDS. If no fallback_credentials
|
| 1636 |
+
argument is supplied, a default SSLChannelCredentials is used.
|
| 1637 |
+
"""
|
| 1638 |
+
fallback_credentials = ssl_channel_credentials(
|
| 1639 |
+
) if fallback_credentials is None else fallback_credentials
|
| 1640 |
+
return ChannelCredentials(
|
| 1641 |
+
_cygrpc.XDSChannelCredentials(fallback_credentials._credentials))
|
| 1642 |
+
|
| 1643 |
+
|
| 1644 |
+
def metadata_call_credentials(metadata_plugin, name=None):
|
| 1645 |
+
"""Construct CallCredentials from an AuthMetadataPlugin.
|
| 1646 |
+
|
| 1647 |
+
Args:
|
| 1648 |
+
metadata_plugin: An AuthMetadataPlugin to use for authentication.
|
| 1649 |
+
name: An optional name for the plugin.
|
| 1650 |
+
|
| 1651 |
+
Returns:
|
| 1652 |
+
A CallCredentials.
|
| 1653 |
+
"""
|
| 1654 |
+
from grpc import _plugin_wrapping # pylint: disable=cyclic-import
|
| 1655 |
+
return _plugin_wrapping.metadata_plugin_call_credentials(
|
| 1656 |
+
metadata_plugin, name)
|
| 1657 |
+
|
| 1658 |
+
|
| 1659 |
+
def access_token_call_credentials(access_token):
|
| 1660 |
+
"""Construct CallCredentials from an access token.
|
| 1661 |
+
|
| 1662 |
+
Args:
|
| 1663 |
+
access_token: A string to place directly in the http request
|
| 1664 |
+
authorization header, for example
|
| 1665 |
+
"authorization: Bearer <access_token>".
|
| 1666 |
+
|
| 1667 |
+
Returns:
|
| 1668 |
+
A CallCredentials.
|
| 1669 |
+
"""
|
| 1670 |
+
from grpc import _auth # pylint: disable=cyclic-import
|
| 1671 |
+
from grpc import _plugin_wrapping # pylint: disable=cyclic-import
|
| 1672 |
+
return _plugin_wrapping.metadata_plugin_call_credentials(
|
| 1673 |
+
_auth.AccessTokenAuthMetadataPlugin(access_token), None)
|
| 1674 |
+
|
| 1675 |
+
|
| 1676 |
+
def composite_call_credentials(*call_credentials):
|
| 1677 |
+
"""Compose multiple CallCredentials to make a new CallCredentials.
|
| 1678 |
+
|
| 1679 |
+
Args:
|
| 1680 |
+
*call_credentials: At least two CallCredentials objects.
|
| 1681 |
+
|
| 1682 |
+
Returns:
|
| 1683 |
+
A CallCredentials object composed of the given CallCredentials objects.
|
| 1684 |
+
"""
|
| 1685 |
+
return CallCredentials(
|
| 1686 |
+
_cygrpc.CompositeCallCredentials(
|
| 1687 |
+
tuple(single_call_credentials._credentials
|
| 1688 |
+
for single_call_credentials in call_credentials)))
|
| 1689 |
+
|
| 1690 |
+
|
| 1691 |
+
def composite_channel_credentials(channel_credentials, *call_credentials):
|
| 1692 |
+
"""Compose a ChannelCredentials and one or more CallCredentials objects.
|
| 1693 |
+
|
| 1694 |
+
Args:
|
| 1695 |
+
channel_credentials: A ChannelCredentials object.
|
| 1696 |
+
*call_credentials: One or more CallCredentials objects.
|
| 1697 |
+
|
| 1698 |
+
Returns:
|
| 1699 |
+
A ChannelCredentials composed of the given ChannelCredentials and
|
| 1700 |
+
CallCredentials objects.
|
| 1701 |
+
"""
|
| 1702 |
+
return ChannelCredentials(
|
| 1703 |
+
_cygrpc.CompositeChannelCredentials(
|
| 1704 |
+
tuple(single_call_credentials._credentials
|
| 1705 |
+
for single_call_credentials in call_credentials),
|
| 1706 |
+
channel_credentials._credentials))
|
| 1707 |
+
|
| 1708 |
+
|
| 1709 |
+
def ssl_server_credentials(private_key_certificate_chain_pairs,
|
| 1710 |
+
root_certificates=None,
|
| 1711 |
+
require_client_auth=False):
|
| 1712 |
+
"""Creates a ServerCredentials for use with an SSL-enabled Server.
|
| 1713 |
+
|
| 1714 |
+
Args:
|
| 1715 |
+
private_key_certificate_chain_pairs: A list of pairs of the form
|
| 1716 |
+
[PEM-encoded private key, PEM-encoded certificate chain].
|
| 1717 |
+
root_certificates: An optional byte string of PEM-encoded client root
|
| 1718 |
+
certificates that the server will use to verify client authentication.
|
| 1719 |
+
If omitted, require_client_auth must also be False.
|
| 1720 |
+
require_client_auth: A boolean indicating whether or not to require
|
| 1721 |
+
clients to be authenticated. May only be True if root_certificates
|
| 1722 |
+
is not None.
|
| 1723 |
+
|
| 1724 |
+
Returns:
|
| 1725 |
+
A ServerCredentials for use with an SSL-enabled Server. Typically, this
|
| 1726 |
+
object is an argument to add_secure_port() method during server setup.
|
| 1727 |
+
"""
|
| 1728 |
+
if not private_key_certificate_chain_pairs:
|
| 1729 |
+
raise ValueError(
|
| 1730 |
+
'At least one private key-certificate chain pair is required!')
|
| 1731 |
+
elif require_client_auth and root_certificates is None:
|
| 1732 |
+
raise ValueError(
|
| 1733 |
+
'Illegal to require client auth without providing root certificates!'
|
| 1734 |
+
)
|
| 1735 |
+
else:
|
| 1736 |
+
return ServerCredentials(
|
| 1737 |
+
_cygrpc.server_credentials_ssl(root_certificates, [
|
| 1738 |
+
_cygrpc.SslPemKeyCertPair(key, pem)
|
| 1739 |
+
for key, pem in private_key_certificate_chain_pairs
|
| 1740 |
+
], require_client_auth))
|
| 1741 |
+
|
| 1742 |
+
|
| 1743 |
+
def xds_server_credentials(fallback_credentials):
|
| 1744 |
+
"""Creates a ServerCredentials for use with xDS. This is an EXPERIMENTAL
|
| 1745 |
+
API.
|
| 1746 |
+
|
| 1747 |
+
Args:
|
| 1748 |
+
fallback_credentials: Credentials to use in case it is not possible to
|
| 1749 |
+
establish a secure connection via xDS. No default value is provided.
|
| 1750 |
+
"""
|
| 1751 |
+
return ServerCredentials(
|
| 1752 |
+
_cygrpc.xds_server_credentials(fallback_credentials._credentials))
|
| 1753 |
+
|
| 1754 |
+
|
| 1755 |
+
def insecure_server_credentials():
|
| 1756 |
+
"""Creates a credentials object directing the server to use no credentials.
|
| 1757 |
+
This is an EXPERIMENTAL API.
|
| 1758 |
+
|
| 1759 |
+
This object cannot be used directly in a call to `add_secure_port`.
|
| 1760 |
+
Instead, it should be used to construct other credentials objects, e.g.
|
| 1761 |
+
with xds_server_credentials.
|
| 1762 |
+
"""
|
| 1763 |
+
return ServerCredentials(_cygrpc.insecure_server_credentials())
|
| 1764 |
+
|
| 1765 |
+
|
| 1766 |
+
def ssl_server_certificate_configuration(private_key_certificate_chain_pairs,
|
| 1767 |
+
root_certificates=None):
|
| 1768 |
+
"""Creates a ServerCertificateConfiguration for use with a Server.
|
| 1769 |
+
|
| 1770 |
+
Args:
|
| 1771 |
+
private_key_certificate_chain_pairs: A collection of pairs of
|
| 1772 |
+
the form [PEM-encoded private key, PEM-encoded certificate
|
| 1773 |
+
chain].
|
| 1774 |
+
root_certificates: An optional byte string of PEM-encoded client root
|
| 1775 |
+
certificates that the server will use to verify client authentication.
|
| 1776 |
+
|
| 1777 |
+
Returns:
|
| 1778 |
+
A ServerCertificateConfiguration that can be returned in the certificate
|
| 1779 |
+
configuration fetching callback.
|
| 1780 |
+
"""
|
| 1781 |
+
if private_key_certificate_chain_pairs:
|
| 1782 |
+
return ServerCertificateConfiguration(
|
| 1783 |
+
_cygrpc.server_certificate_config_ssl(root_certificates, [
|
| 1784 |
+
_cygrpc.SslPemKeyCertPair(key, pem)
|
| 1785 |
+
for key, pem in private_key_certificate_chain_pairs
|
| 1786 |
+
]))
|
| 1787 |
+
else:
|
| 1788 |
+
raise ValueError(
|
| 1789 |
+
'At least one private key-certificate chain pair is required!')
|
| 1790 |
+
|
| 1791 |
+
|
| 1792 |
+
def dynamic_ssl_server_credentials(initial_certificate_configuration,
|
| 1793 |
+
certificate_configuration_fetcher,
|
| 1794 |
+
require_client_authentication=False):
|
| 1795 |
+
"""Creates a ServerCredentials for use with an SSL-enabled Server.
|
| 1796 |
+
|
| 1797 |
+
Args:
|
| 1798 |
+
initial_certificate_configuration (ServerCertificateConfiguration): The
|
| 1799 |
+
certificate configuration with which the server will be initialized.
|
| 1800 |
+
certificate_configuration_fetcher (callable): A callable that takes no
|
| 1801 |
+
arguments and should return a ServerCertificateConfiguration to
|
| 1802 |
+
replace the server's current certificate, or None for no change
|
| 1803 |
+
(i.e., the server will continue its current certificate
|
| 1804 |
+
config). The library will call this callback on *every* new
|
| 1805 |
+
client connection before starting the TLS handshake with the
|
| 1806 |
+
client, thus allowing the user application to optionally
|
| 1807 |
+
return a new ServerCertificateConfiguration that the server will then
|
| 1808 |
+
use for the handshake.
|
| 1809 |
+
require_client_authentication: A boolean indicating whether or not to
|
| 1810 |
+
require clients to be authenticated.
|
| 1811 |
+
|
| 1812 |
+
Returns:
|
| 1813 |
+
A ServerCredentials.
|
| 1814 |
+
"""
|
| 1815 |
+
return ServerCredentials(
|
| 1816 |
+
_cygrpc.server_credentials_ssl_dynamic_cert_config(
|
| 1817 |
+
initial_certificate_configuration,
|
| 1818 |
+
certificate_configuration_fetcher, require_client_authentication))
|
| 1819 |
+
|
| 1820 |
+
|
| 1821 |
+
@enum.unique
|
| 1822 |
+
class LocalConnectionType(enum.Enum):
|
| 1823 |
+
"""Types of local connection for local credential creation.
|
| 1824 |
+
|
| 1825 |
+
Attributes:
|
| 1826 |
+
UDS: Unix domain socket connections
|
| 1827 |
+
LOCAL_TCP: Local TCP connections.
|
| 1828 |
+
"""
|
| 1829 |
+
UDS = _cygrpc.LocalConnectionType.uds
|
| 1830 |
+
LOCAL_TCP = _cygrpc.LocalConnectionType.local_tcp
|
| 1831 |
+
|
| 1832 |
+
|
| 1833 |
+
def local_channel_credentials(local_connect_type=LocalConnectionType.LOCAL_TCP):
|
| 1834 |
+
"""Creates a local ChannelCredentials used for local connections.
|
| 1835 |
+
|
| 1836 |
+
This is an EXPERIMENTAL API.
|
| 1837 |
+
|
| 1838 |
+
Local credentials are used by local TCP endpoints (e.g. localhost:10000)
|
| 1839 |
+
also UDS connections.
|
| 1840 |
+
|
| 1841 |
+
The connections created by local channel credentials are not
|
| 1842 |
+
encrypted, but will be checked if they are local or not.
|
| 1843 |
+
The UDS connections are considered secure by providing peer authentication
|
| 1844 |
+
and data confidentiality while TCP connections are considered insecure.
|
| 1845 |
+
|
| 1846 |
+
It is allowed to transmit call credentials over connections created by
|
| 1847 |
+
local channel credentials.
|
| 1848 |
+
|
| 1849 |
+
Local channel credentials are useful for 1) eliminating insecure_channel usage;
|
| 1850 |
+
2) enable unit testing for call credentials without setting up secrets.
|
| 1851 |
+
|
| 1852 |
+
Args:
|
| 1853 |
+
local_connect_type: Local connection type (either
|
| 1854 |
+
grpc.LocalConnectionType.UDS or grpc.LocalConnectionType.LOCAL_TCP)
|
| 1855 |
+
|
| 1856 |
+
Returns:
|
| 1857 |
+
A ChannelCredentials for use with a local Channel
|
| 1858 |
+
"""
|
| 1859 |
+
return ChannelCredentials(
|
| 1860 |
+
_cygrpc.channel_credentials_local(local_connect_type.value))
|
| 1861 |
+
|
| 1862 |
+
|
| 1863 |
+
def local_server_credentials(local_connect_type=LocalConnectionType.LOCAL_TCP):
|
| 1864 |
+
"""Creates a local ServerCredentials used for local connections.
|
| 1865 |
+
|
| 1866 |
+
This is an EXPERIMENTAL API.
|
| 1867 |
+
|
| 1868 |
+
Local credentials are used by local TCP endpoints (e.g. localhost:10000)
|
| 1869 |
+
also UDS connections.
|
| 1870 |
+
|
| 1871 |
+
The connections created by local server credentials are not
|
| 1872 |
+
encrypted, but will be checked if they are local or not.
|
| 1873 |
+
The UDS connections are considered secure by providing peer authentication
|
| 1874 |
+
and data confidentiality while TCP connections are considered insecure.
|
| 1875 |
+
|
| 1876 |
+
It is allowed to transmit call credentials over connections created by local
|
| 1877 |
+
server credentials.
|
| 1878 |
+
|
| 1879 |
+
Local server credentials are useful for 1) eliminating insecure_channel usage;
|
| 1880 |
+
2) enable unit testing for call credentials without setting up secrets.
|
| 1881 |
+
|
| 1882 |
+
Args:
|
| 1883 |
+
local_connect_type: Local connection type (either
|
| 1884 |
+
grpc.LocalConnectionType.UDS or grpc.LocalConnectionType.LOCAL_TCP)
|
| 1885 |
+
|
| 1886 |
+
Returns:
|
| 1887 |
+
A ServerCredentials for use with a local Server
|
| 1888 |
+
"""
|
| 1889 |
+
return ServerCredentials(
|
| 1890 |
+
_cygrpc.server_credentials_local(local_connect_type.value))
|
| 1891 |
+
|
| 1892 |
+
|
| 1893 |
+
def alts_channel_credentials(service_accounts=None):
|
| 1894 |
+
"""Creates a ChannelCredentials for use with an ALTS-enabled Channel.
|
| 1895 |
+
|
| 1896 |
+
This is an EXPERIMENTAL API.
|
| 1897 |
+
ALTS credentials API can only be used in GCP environment as it relies on
|
| 1898 |
+
handshaker service being available. For more info about ALTS see
|
| 1899 |
+
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
|
| 1900 |
+
|
| 1901 |
+
Args:
|
| 1902 |
+
service_accounts: A list of server identities accepted by the client.
|
| 1903 |
+
If target service accounts are provided and none of them matches the
|
| 1904 |
+
peer identity of the server, handshake will fail. The arg can be empty
|
| 1905 |
+
if the client does not have any information about trusted server
|
| 1906 |
+
identity.
|
| 1907 |
+
Returns:
|
| 1908 |
+
A ChannelCredentials for use with an ALTS-enabled Channel
|
| 1909 |
+
"""
|
| 1910 |
+
return ChannelCredentials(
|
| 1911 |
+
_cygrpc.channel_credentials_alts(service_accounts or []))
|
| 1912 |
+
|
| 1913 |
+
|
| 1914 |
+
def alts_server_credentials():
|
| 1915 |
+
"""Creates a ServerCredentials for use with an ALTS-enabled connection.
|
| 1916 |
+
|
| 1917 |
+
This is an EXPERIMENTAL API.
|
| 1918 |
+
ALTS credentials API can only be used in GCP environment as it relies on
|
| 1919 |
+
handshaker service being available. For more info about ALTS see
|
| 1920 |
+
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
|
| 1921 |
+
|
| 1922 |
+
Returns:
|
| 1923 |
+
A ServerCredentials for use with an ALTS-enabled Server
|
| 1924 |
+
"""
|
| 1925 |
+
return ServerCredentials(_cygrpc.server_credentials_alts())
|
| 1926 |
+
|
| 1927 |
+
|
| 1928 |
+
def compute_engine_channel_credentials(call_credentials):
|
| 1929 |
+
"""Creates a compute engine channel credential.
|
| 1930 |
+
|
| 1931 |
+
This credential can only be used in a GCP environment as it relies on
|
| 1932 |
+
a handshaker service. For more info about ALTS, see
|
| 1933 |
+
https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security
|
| 1934 |
+
|
| 1935 |
+
This channel credential is expected to be used as part of a composite
|
| 1936 |
+
credential in conjunction with a call credentials that authenticates the
|
| 1937 |
+
VM's default service account. If used with any other sort of call
|
| 1938 |
+
credential, the connection may suddenly and unexpectedly begin failing RPCs.
|
| 1939 |
+
"""
|
| 1940 |
+
return ChannelCredentials(
|
| 1941 |
+
_cygrpc.channel_credentials_compute_engine(
|
| 1942 |
+
call_credentials._credentials))
|
| 1943 |
+
|
| 1944 |
+
|
| 1945 |
+
def channel_ready_future(channel):
|
| 1946 |
+
"""Creates a Future that tracks when a Channel is ready.
|
| 1947 |
+
|
| 1948 |
+
Cancelling the Future does not affect the channel's state machine.
|
| 1949 |
+
It merely decouples the Future from channel state machine.
|
| 1950 |
+
|
| 1951 |
+
Args:
|
| 1952 |
+
channel: A Channel object.
|
| 1953 |
+
|
| 1954 |
+
Returns:
|
| 1955 |
+
A Future object that matures when the channel connectivity is
|
| 1956 |
+
ChannelConnectivity.READY.
|
| 1957 |
+
"""
|
| 1958 |
+
from grpc import _utilities # pylint: disable=cyclic-import
|
| 1959 |
+
return _utilities.channel_ready_future(channel)
|
| 1960 |
+
|
| 1961 |
+
|
| 1962 |
+
def insecure_channel(target, options=None, compression=None):
|
| 1963 |
+
"""Creates an insecure Channel to a server.
|
| 1964 |
+
|
| 1965 |
+
The returned Channel is thread-safe.
|
| 1966 |
+
|
| 1967 |
+
Args:
|
| 1968 |
+
target: The server address
|
| 1969 |
+
options: An optional list of key-value pairs (:term:`channel_arguments`
|
| 1970 |
+
in gRPC Core runtime) to configure the channel.
|
| 1971 |
+
compression: An optional value indicating the compression method to be
|
| 1972 |
+
used over the lifetime of the channel. This is an EXPERIMENTAL option.
|
| 1973 |
+
|
| 1974 |
+
Returns:
|
| 1975 |
+
A Channel.
|
| 1976 |
+
"""
|
| 1977 |
+
from grpc import _channel # pylint: disable=cyclic-import
|
| 1978 |
+
return _channel.Channel(target, () if options is None else options, None,
|
| 1979 |
+
compression)
|
| 1980 |
+
|
| 1981 |
+
|
| 1982 |
+
def secure_channel(target, credentials, options=None, compression=None):
|
| 1983 |
+
"""Creates a secure Channel to a server.
|
| 1984 |
+
|
| 1985 |
+
The returned Channel is thread-safe.
|
| 1986 |
+
|
| 1987 |
+
Args:
|
| 1988 |
+
target: The server address.
|
| 1989 |
+
credentials: A ChannelCredentials instance.
|
| 1990 |
+
options: An optional list of key-value pairs (:term:`channel_arguments`
|
| 1991 |
+
in gRPC Core runtime) to configure the channel.
|
| 1992 |
+
compression: An optional value indicating the compression method to be
|
| 1993 |
+
used over the lifetime of the channel. This is an EXPERIMENTAL option.
|
| 1994 |
+
|
| 1995 |
+
Returns:
|
| 1996 |
+
A Channel.
|
| 1997 |
+
"""
|
| 1998 |
+
from grpc import _channel # pylint: disable=cyclic-import
|
| 1999 |
+
from grpc.experimental import _insecure_channel_credentials
|
| 2000 |
+
if credentials._credentials is _insecure_channel_credentials:
|
| 2001 |
+
raise ValueError(
|
| 2002 |
+
"secure_channel cannot be called with insecure credentials." +
|
| 2003 |
+
" Call insecure_channel instead.")
|
| 2004 |
+
return _channel.Channel(target, () if options is None else options,
|
| 2005 |
+
credentials._credentials, compression)
|
| 2006 |
+
|
| 2007 |
+
|
| 2008 |
+
def intercept_channel(channel, *interceptors):
|
| 2009 |
+
"""Intercepts a channel through a set of interceptors.
|
| 2010 |
+
|
| 2011 |
+
Args:
|
| 2012 |
+
channel: A Channel.
|
| 2013 |
+
interceptors: Zero or more objects of type
|
| 2014 |
+
UnaryUnaryClientInterceptor,
|
| 2015 |
+
UnaryStreamClientInterceptor,
|
| 2016 |
+
StreamUnaryClientInterceptor, or
|
| 2017 |
+
StreamStreamClientInterceptor.
|
| 2018 |
+
Interceptors are given control in the order they are listed.
|
| 2019 |
+
|
| 2020 |
+
Returns:
|
| 2021 |
+
A Channel that intercepts each invocation via the provided interceptors.
|
| 2022 |
+
|
| 2023 |
+
Raises:
|
| 2024 |
+
TypeError: If interceptor does not derive from any of
|
| 2025 |
+
UnaryUnaryClientInterceptor,
|
| 2026 |
+
UnaryStreamClientInterceptor,
|
| 2027 |
+
StreamUnaryClientInterceptor, or
|
| 2028 |
+
StreamStreamClientInterceptor.
|
| 2029 |
+
"""
|
| 2030 |
+
from grpc import _interceptor # pylint: disable=cyclic-import
|
| 2031 |
+
return _interceptor.intercept_channel(channel, *interceptors)
|
| 2032 |
+
|
| 2033 |
+
|
| 2034 |
+
def server(thread_pool,
|
| 2035 |
+
handlers=None,
|
| 2036 |
+
interceptors=None,
|
| 2037 |
+
options=None,
|
| 2038 |
+
maximum_concurrent_rpcs=None,
|
| 2039 |
+
compression=None,
|
| 2040 |
+
xds=False):
|
| 2041 |
+
"""Creates a Server with which RPCs can be serviced.
|
| 2042 |
+
|
| 2043 |
+
Args:
|
| 2044 |
+
thread_pool: A futures.ThreadPoolExecutor to be used by the Server
|
| 2045 |
+
to execute RPC handlers.
|
| 2046 |
+
handlers: An optional list of GenericRpcHandlers used for executing RPCs.
|
| 2047 |
+
More handlers may be added by calling add_generic_rpc_handlers any time
|
| 2048 |
+
before the server is started.
|
| 2049 |
+
interceptors: An optional list of ServerInterceptor objects that observe
|
| 2050 |
+
and optionally manipulate the incoming RPCs before handing them over to
|
| 2051 |
+
handlers. The interceptors are given control in the order they are
|
| 2052 |
+
specified. This is an EXPERIMENTAL API.
|
| 2053 |
+
options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC runtime)
|
| 2054 |
+
to configure the channel.
|
| 2055 |
+
maximum_concurrent_rpcs: The maximum number of concurrent RPCs this server
|
| 2056 |
+
will service before returning RESOURCE_EXHAUSTED status, or None to
|
| 2057 |
+
indicate no limit.
|
| 2058 |
+
compression: An element of grpc.compression, e.g.
|
| 2059 |
+
grpc.compression.Gzip. This compression algorithm will be used for the
|
| 2060 |
+
lifetime of the server unless overridden. This is an EXPERIMENTAL option.
|
| 2061 |
+
xds: If set to true, retrieves server configuration via xDS. This is an
|
| 2062 |
+
EXPERIMENTAL option.
|
| 2063 |
+
|
| 2064 |
+
Returns:
|
| 2065 |
+
A Server object.
|
| 2066 |
+
"""
|
| 2067 |
+
from grpc import _server # pylint: disable=cyclic-import
|
| 2068 |
+
return _server.create_server(thread_pool,
|
| 2069 |
+
() if handlers is None else handlers,
|
| 2070 |
+
() if interceptors is None else interceptors,
|
| 2071 |
+
() if options is None else options,
|
| 2072 |
+
maximum_concurrent_rpcs, compression, xds)
|
| 2073 |
+
|
| 2074 |
+
|
| 2075 |
+
@contextlib.contextmanager
|
| 2076 |
+
def _create_servicer_context(rpc_event, state, request_deserializer):
|
| 2077 |
+
from grpc import _server # pylint: disable=cyclic-import
|
| 2078 |
+
context = _server._Context(rpc_event, state, request_deserializer)
|
| 2079 |
+
yield context
|
| 2080 |
+
context._finalize_state() # pylint: disable=protected-access
|
| 2081 |
+
|
| 2082 |
+
|
| 2083 |
+
@enum.unique
|
| 2084 |
+
class Compression(enum.IntEnum):
|
| 2085 |
+
"""Indicates the compression method to be used for an RPC.
|
| 2086 |
+
|
| 2087 |
+
This enumeration is part of an EXPERIMENTAL API.
|
| 2088 |
+
|
| 2089 |
+
Attributes:
|
| 2090 |
+
NoCompression: Do not use compression algorithm.
|
| 2091 |
+
Deflate: Use "Deflate" compression algorithm.
|
| 2092 |
+
Gzip: Use "Gzip" compression algorithm.
|
| 2093 |
+
"""
|
| 2094 |
+
NoCompression = _compression.NoCompression
|
| 2095 |
+
Deflate = _compression.Deflate
|
| 2096 |
+
Gzip = _compression.Gzip
|
| 2097 |
+
|
| 2098 |
+
|
| 2099 |
+
################################### __all__ #################################
|
| 2100 |
+
|
| 2101 |
+
__all__ = (
|
| 2102 |
+
'FutureTimeoutError',
|
| 2103 |
+
'FutureCancelledError',
|
| 2104 |
+
'Future',
|
| 2105 |
+
'ChannelConnectivity',
|
| 2106 |
+
'StatusCode',
|
| 2107 |
+
'Status',
|
| 2108 |
+
'RpcError',
|
| 2109 |
+
'RpcContext',
|
| 2110 |
+
'Call',
|
| 2111 |
+
'ChannelCredentials',
|
| 2112 |
+
'CallCredentials',
|
| 2113 |
+
'AuthMetadataContext',
|
| 2114 |
+
'AuthMetadataPluginCallback',
|
| 2115 |
+
'AuthMetadataPlugin',
|
| 2116 |
+
'Compression',
|
| 2117 |
+
'ClientCallDetails',
|
| 2118 |
+
'ServerCertificateConfiguration',
|
| 2119 |
+
'ServerCredentials',
|
| 2120 |
+
'LocalConnectionType',
|
| 2121 |
+
'UnaryUnaryMultiCallable',
|
| 2122 |
+
'UnaryStreamMultiCallable',
|
| 2123 |
+
'StreamUnaryMultiCallable',
|
| 2124 |
+
'StreamStreamMultiCallable',
|
| 2125 |
+
'UnaryUnaryClientInterceptor',
|
| 2126 |
+
'UnaryStreamClientInterceptor',
|
| 2127 |
+
'StreamUnaryClientInterceptor',
|
| 2128 |
+
'StreamStreamClientInterceptor',
|
| 2129 |
+
'Channel',
|
| 2130 |
+
'ServicerContext',
|
| 2131 |
+
'RpcMethodHandler',
|
| 2132 |
+
'HandlerCallDetails',
|
| 2133 |
+
'GenericRpcHandler',
|
| 2134 |
+
'ServiceRpcHandler',
|
| 2135 |
+
'Server',
|
| 2136 |
+
'ServerInterceptor',
|
| 2137 |
+
'unary_unary_rpc_method_handler',
|
| 2138 |
+
'unary_stream_rpc_method_handler',
|
| 2139 |
+
'stream_unary_rpc_method_handler',
|
| 2140 |
+
'stream_stream_rpc_method_handler',
|
| 2141 |
+
'method_handlers_generic_handler',
|
| 2142 |
+
'ssl_channel_credentials',
|
| 2143 |
+
'metadata_call_credentials',
|
| 2144 |
+
'access_token_call_credentials',
|
| 2145 |
+
'composite_call_credentials',
|
| 2146 |
+
'composite_channel_credentials',
|
| 2147 |
+
'compute_engine_channel_credentials',
|
| 2148 |
+
'local_channel_credentials',
|
| 2149 |
+
'local_server_credentials',
|
| 2150 |
+
'alts_channel_credentials',
|
| 2151 |
+
'alts_server_credentials',
|
| 2152 |
+
'ssl_server_credentials',
|
| 2153 |
+
'ssl_server_certificate_configuration',
|
| 2154 |
+
'dynamic_ssl_server_credentials',
|
| 2155 |
+
'channel_ready_future',
|
| 2156 |
+
'insecure_channel',
|
| 2157 |
+
'secure_channel',
|
| 2158 |
+
'intercept_channel',
|
| 2159 |
+
'server',
|
| 2160 |
+
'protos',
|
| 2161 |
+
'services',
|
| 2162 |
+
'protos_and_services',
|
| 2163 |
+
'xds_channel_credentials',
|
| 2164 |
+
'xds_server_credentials',
|
| 2165 |
+
'insecure_server_credentials',
|
| 2166 |
+
)
|
| 2167 |
+
|
| 2168 |
+
############################### Extension Shims ################################
|
| 2169 |
+
|
| 2170 |
+
# Here to maintain backwards compatibility; avoid using these in new code!
|
| 2171 |
+
try:
|
| 2172 |
+
import grpc_tools
|
| 2173 |
+
sys.modules.update({'grpc.tools': grpc_tools})
|
| 2174 |
+
except ImportError:
|
| 2175 |
+
pass
|
| 2176 |
+
try:
|
| 2177 |
+
import grpc_health
|
| 2178 |
+
sys.modules.update({'grpc.health': grpc_health})
|
| 2179 |
+
except ImportError:
|
| 2180 |
+
pass
|
| 2181 |
+
try:
|
| 2182 |
+
import grpc_reflection
|
| 2183 |
+
sys.modules.update({'grpc.reflection': grpc_reflection})
|
| 2184 |
+
except ImportError:
|
| 2185 |
+
pass
|
| 2186 |
+
|
| 2187 |
+
# Prevents import order issue in the case of renamed path.
|
| 2188 |
+
if sys.version_info >= (3, 6) and __name__ == "grpc":
|
| 2189 |
+
from grpc import aio # pylint: disable=ungrouped-imports
|
| 2190 |
+
sys.modules.update({'grpc.aio': aio})
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_channel.py
ADDED
|
@@ -0,0 +1,1585 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2016 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Invocation-side implementation of gRPC Python."""
|
| 15 |
+
|
| 16 |
+
import copy
|
| 17 |
+
import functools
|
| 18 |
+
import logging
|
| 19 |
+
import os
|
| 20 |
+
import sys
|
| 21 |
+
import threading
|
| 22 |
+
import time
|
| 23 |
+
|
| 24 |
+
import grpc
|
| 25 |
+
from grpc import _common
|
| 26 |
+
from grpc import _compression
|
| 27 |
+
from grpc import _grpcio_metadata
|
| 28 |
+
from grpc._cython import cygrpc
|
| 29 |
+
import grpc.experimental
|
| 30 |
+
|
| 31 |
+
_LOGGER = logging.getLogger(__name__)
|
| 32 |
+
|
| 33 |
+
_USER_AGENT = 'grpc-python/{}'.format(_grpcio_metadata.__version__)
|
| 34 |
+
|
| 35 |
+
_EMPTY_FLAGS = 0
|
| 36 |
+
|
| 37 |
+
# NOTE(rbellevi): No guarantees are given about the maintenance of this
|
| 38 |
+
# environment variable.
|
| 39 |
+
_DEFAULT_SINGLE_THREADED_UNARY_STREAM = os.getenv(
|
| 40 |
+
"GRPC_SINGLE_THREADED_UNARY_STREAM") is not None
|
| 41 |
+
|
| 42 |
+
_UNARY_UNARY_INITIAL_DUE = (
|
| 43 |
+
cygrpc.OperationType.send_initial_metadata,
|
| 44 |
+
cygrpc.OperationType.send_message,
|
| 45 |
+
cygrpc.OperationType.send_close_from_client,
|
| 46 |
+
cygrpc.OperationType.receive_initial_metadata,
|
| 47 |
+
cygrpc.OperationType.receive_message,
|
| 48 |
+
cygrpc.OperationType.receive_status_on_client,
|
| 49 |
+
)
|
| 50 |
+
_UNARY_STREAM_INITIAL_DUE = (
|
| 51 |
+
cygrpc.OperationType.send_initial_metadata,
|
| 52 |
+
cygrpc.OperationType.send_message,
|
| 53 |
+
cygrpc.OperationType.send_close_from_client,
|
| 54 |
+
cygrpc.OperationType.receive_initial_metadata,
|
| 55 |
+
cygrpc.OperationType.receive_status_on_client,
|
| 56 |
+
)
|
| 57 |
+
_STREAM_UNARY_INITIAL_DUE = (
|
| 58 |
+
cygrpc.OperationType.send_initial_metadata,
|
| 59 |
+
cygrpc.OperationType.receive_initial_metadata,
|
| 60 |
+
cygrpc.OperationType.receive_message,
|
| 61 |
+
cygrpc.OperationType.receive_status_on_client,
|
| 62 |
+
)
|
| 63 |
+
_STREAM_STREAM_INITIAL_DUE = (
|
| 64 |
+
cygrpc.OperationType.send_initial_metadata,
|
| 65 |
+
cygrpc.OperationType.receive_initial_metadata,
|
| 66 |
+
cygrpc.OperationType.receive_status_on_client,
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = (
|
| 70 |
+
'Exception calling channel subscription callback!')
|
| 71 |
+
|
| 72 |
+
_OK_RENDEZVOUS_REPR_FORMAT = ('<{} of RPC that terminated with:\n'
|
| 73 |
+
'\tstatus = {}\n'
|
| 74 |
+
'\tdetails = "{}"\n'
|
| 75 |
+
'>')
|
| 76 |
+
|
| 77 |
+
_NON_OK_RENDEZVOUS_REPR_FORMAT = ('<{} of RPC that terminated with:\n'
|
| 78 |
+
'\tstatus = {}\n'
|
| 79 |
+
'\tdetails = "{}"\n'
|
| 80 |
+
'\tdebug_error_string = "{}"\n'
|
| 81 |
+
'>')
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def _deadline(timeout):
|
| 85 |
+
return None if timeout is None else time.time() + timeout
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
def _unknown_code_details(unknown_cygrpc_code, details):
|
| 89 |
+
return 'Server sent unknown code {} and details "{}"'.format(
|
| 90 |
+
unknown_cygrpc_code, details)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class _RPCState(object):
|
| 94 |
+
|
| 95 |
+
def __init__(self, due, initial_metadata, trailing_metadata, code, details):
|
| 96 |
+
# `condition` guards all members of _RPCState. `notify_all` is called on
|
| 97 |
+
# `condition` when the state of the RPC has changed.
|
| 98 |
+
self.condition = threading.Condition()
|
| 99 |
+
|
| 100 |
+
# The cygrpc.OperationType objects representing events due from the RPC's
|
| 101 |
+
# completion queue. If an operation is in `due`, it is guaranteed that
|
| 102 |
+
# `operate()` has been called on a corresponding operation. But the
|
| 103 |
+
# converse is not true. That is, in the case of failed `operate()`
|
| 104 |
+
# calls, there may briefly be events in `due` that do not correspond to
|
| 105 |
+
# operations submitted to Core.
|
| 106 |
+
self.due = set(due)
|
| 107 |
+
self.initial_metadata = initial_metadata
|
| 108 |
+
self.response = None
|
| 109 |
+
self.trailing_metadata = trailing_metadata
|
| 110 |
+
self.code = code
|
| 111 |
+
self.details = details
|
| 112 |
+
self.debug_error_string = None
|
| 113 |
+
|
| 114 |
+
# The semantics of grpc.Future.cancel and grpc.Future.cancelled are
|
| 115 |
+
# slightly wonky, so they have to be tracked separately from the rest of the
|
| 116 |
+
# result of the RPC. This field tracks whether cancellation was requested
|
| 117 |
+
# prior to termination of the RPC.
|
| 118 |
+
self.cancelled = False
|
| 119 |
+
self.callbacks = []
|
| 120 |
+
self.fork_epoch = cygrpc.get_fork_epoch()
|
| 121 |
+
|
| 122 |
+
def reset_postfork_child(self):
|
| 123 |
+
self.condition = threading.Condition()
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def _abort(state, code, details):
|
| 127 |
+
if state.code is None:
|
| 128 |
+
state.code = code
|
| 129 |
+
state.details = details
|
| 130 |
+
if state.initial_metadata is None:
|
| 131 |
+
state.initial_metadata = ()
|
| 132 |
+
state.trailing_metadata = ()
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def _handle_event(event, state, response_deserializer):
|
| 136 |
+
callbacks = []
|
| 137 |
+
for batch_operation in event.batch_operations:
|
| 138 |
+
operation_type = batch_operation.type()
|
| 139 |
+
state.due.remove(operation_type)
|
| 140 |
+
if operation_type == cygrpc.OperationType.receive_initial_metadata:
|
| 141 |
+
state.initial_metadata = batch_operation.initial_metadata()
|
| 142 |
+
elif operation_type == cygrpc.OperationType.receive_message:
|
| 143 |
+
serialized_response = batch_operation.message()
|
| 144 |
+
if serialized_response is not None:
|
| 145 |
+
response = _common.deserialize(serialized_response,
|
| 146 |
+
response_deserializer)
|
| 147 |
+
if response is None:
|
| 148 |
+
details = 'Exception deserializing response!'
|
| 149 |
+
_abort(state, grpc.StatusCode.INTERNAL, details)
|
| 150 |
+
else:
|
| 151 |
+
state.response = response
|
| 152 |
+
elif operation_type == cygrpc.OperationType.receive_status_on_client:
|
| 153 |
+
state.trailing_metadata = batch_operation.trailing_metadata()
|
| 154 |
+
if state.code is None:
|
| 155 |
+
code = _common.CYGRPC_STATUS_CODE_TO_STATUS_CODE.get(
|
| 156 |
+
batch_operation.code())
|
| 157 |
+
if code is None:
|
| 158 |
+
state.code = grpc.StatusCode.UNKNOWN
|
| 159 |
+
state.details = _unknown_code_details(
|
| 160 |
+
code, batch_operation.details())
|
| 161 |
+
else:
|
| 162 |
+
state.code = code
|
| 163 |
+
state.details = batch_operation.details()
|
| 164 |
+
state.debug_error_string = batch_operation.error_string()
|
| 165 |
+
callbacks.extend(state.callbacks)
|
| 166 |
+
state.callbacks = None
|
| 167 |
+
return callbacks
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def _event_handler(state, response_deserializer):
|
| 171 |
+
|
| 172 |
+
def handle_event(event):
|
| 173 |
+
with state.condition:
|
| 174 |
+
callbacks = _handle_event(event, state, response_deserializer)
|
| 175 |
+
state.condition.notify_all()
|
| 176 |
+
done = not state.due
|
| 177 |
+
for callback in callbacks:
|
| 178 |
+
try:
|
| 179 |
+
callback()
|
| 180 |
+
except Exception as e: # pylint: disable=broad-except
|
| 181 |
+
# NOTE(rbellevi): We suppress but log errors here so as not to
|
| 182 |
+
# kill the channel spin thread.
|
| 183 |
+
logging.error('Exception in callback %s: %s',
|
| 184 |
+
repr(callback.func), repr(e))
|
| 185 |
+
return done and state.fork_epoch >= cygrpc.get_fork_epoch()
|
| 186 |
+
|
| 187 |
+
return handle_event
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
#pylint: disable=too-many-statements
|
| 191 |
+
def _consume_request_iterator(request_iterator, state, call, request_serializer,
|
| 192 |
+
event_handler):
|
| 193 |
+
"""Consume a request iterator supplied by the user."""
|
| 194 |
+
|
| 195 |
+
def consume_request_iterator(): # pylint: disable=too-many-branches
|
| 196 |
+
# Iterate over the request iterator until it is exhausted or an error
|
| 197 |
+
# condition is encountered.
|
| 198 |
+
while True:
|
| 199 |
+
return_from_user_request_generator_invoked = False
|
| 200 |
+
try:
|
| 201 |
+
# The thread may die in user-code. Do not block fork for this.
|
| 202 |
+
cygrpc.enter_user_request_generator()
|
| 203 |
+
request = next(request_iterator)
|
| 204 |
+
except StopIteration:
|
| 205 |
+
break
|
| 206 |
+
except Exception: # pylint: disable=broad-except
|
| 207 |
+
cygrpc.return_from_user_request_generator()
|
| 208 |
+
return_from_user_request_generator_invoked = True
|
| 209 |
+
code = grpc.StatusCode.UNKNOWN
|
| 210 |
+
details = 'Exception iterating requests!'
|
| 211 |
+
_LOGGER.exception(details)
|
| 212 |
+
call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
|
| 213 |
+
details)
|
| 214 |
+
_abort(state, code, details)
|
| 215 |
+
return
|
| 216 |
+
finally:
|
| 217 |
+
if not return_from_user_request_generator_invoked:
|
| 218 |
+
cygrpc.return_from_user_request_generator()
|
| 219 |
+
serialized_request = _common.serialize(request, request_serializer)
|
| 220 |
+
with state.condition:
|
| 221 |
+
if state.code is None and not state.cancelled:
|
| 222 |
+
if serialized_request is None:
|
| 223 |
+
code = grpc.StatusCode.INTERNAL
|
| 224 |
+
details = 'Exception serializing request!'
|
| 225 |
+
call.cancel(
|
| 226 |
+
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
|
| 227 |
+
details)
|
| 228 |
+
_abort(state, code, details)
|
| 229 |
+
return
|
| 230 |
+
else:
|
| 231 |
+
state.due.add(cygrpc.OperationType.send_message)
|
| 232 |
+
operations = (cygrpc.SendMessageOperation(
|
| 233 |
+
serialized_request, _EMPTY_FLAGS),)
|
| 234 |
+
operating = call.operate(operations, event_handler)
|
| 235 |
+
if not operating:
|
| 236 |
+
state.due.remove(cygrpc.OperationType.send_message)
|
| 237 |
+
return
|
| 238 |
+
|
| 239 |
+
def _done():
|
| 240 |
+
return (state.code is not None or
|
| 241 |
+
cygrpc.OperationType.send_message
|
| 242 |
+
not in state.due)
|
| 243 |
+
|
| 244 |
+
_common.wait(state.condition.wait,
|
| 245 |
+
_done,
|
| 246 |
+
spin_cb=functools.partial(
|
| 247 |
+
cygrpc.block_if_fork_in_progress,
|
| 248 |
+
state))
|
| 249 |
+
if state.code is not None:
|
| 250 |
+
return
|
| 251 |
+
else:
|
| 252 |
+
return
|
| 253 |
+
with state.condition:
|
| 254 |
+
if state.code is None:
|
| 255 |
+
state.due.add(cygrpc.OperationType.send_close_from_client)
|
| 256 |
+
operations = (
|
| 257 |
+
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),)
|
| 258 |
+
operating = call.operate(operations, event_handler)
|
| 259 |
+
if not operating:
|
| 260 |
+
state.due.remove(
|
| 261 |
+
cygrpc.OperationType.send_close_from_client)
|
| 262 |
+
|
| 263 |
+
consumption_thread = cygrpc.ForkManagedThread(
|
| 264 |
+
target=consume_request_iterator)
|
| 265 |
+
consumption_thread.setDaemon(True)
|
| 266 |
+
consumption_thread.start()
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
def _rpc_state_string(class_name, rpc_state):
|
| 270 |
+
"""Calculates error string for RPC."""
|
| 271 |
+
with rpc_state.condition:
|
| 272 |
+
if rpc_state.code is None:
|
| 273 |
+
return '<{} object>'.format(class_name)
|
| 274 |
+
elif rpc_state.code is grpc.StatusCode.OK:
|
| 275 |
+
return _OK_RENDEZVOUS_REPR_FORMAT.format(class_name, rpc_state.code,
|
| 276 |
+
rpc_state.details)
|
| 277 |
+
else:
|
| 278 |
+
return _NON_OK_RENDEZVOUS_REPR_FORMAT.format(
|
| 279 |
+
class_name, rpc_state.code, rpc_state.details,
|
| 280 |
+
rpc_state.debug_error_string)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
class _InactiveRpcError(grpc.RpcError, grpc.Call, grpc.Future):
|
| 284 |
+
"""An RPC error not tied to the execution of a particular RPC.
|
| 285 |
+
|
| 286 |
+
The RPC represented by the state object must not be in-progress or
|
| 287 |
+
cancelled.
|
| 288 |
+
|
| 289 |
+
Attributes:
|
| 290 |
+
_state: An instance of _RPCState.
|
| 291 |
+
"""
|
| 292 |
+
|
| 293 |
+
def __init__(self, state):
|
| 294 |
+
with state.condition:
|
| 295 |
+
self._state = _RPCState((), copy.deepcopy(state.initial_metadata),
|
| 296 |
+
copy.deepcopy(state.trailing_metadata),
|
| 297 |
+
state.code, copy.deepcopy(state.details))
|
| 298 |
+
self._state.response = copy.copy(state.response)
|
| 299 |
+
self._state.debug_error_string = copy.copy(state.debug_error_string)
|
| 300 |
+
|
| 301 |
+
def initial_metadata(self):
|
| 302 |
+
return self._state.initial_metadata
|
| 303 |
+
|
| 304 |
+
def trailing_metadata(self):
|
| 305 |
+
return self._state.trailing_metadata
|
| 306 |
+
|
| 307 |
+
def code(self):
|
| 308 |
+
return self._state.code
|
| 309 |
+
|
| 310 |
+
def details(self):
|
| 311 |
+
return _common.decode(self._state.details)
|
| 312 |
+
|
| 313 |
+
def debug_error_string(self):
|
| 314 |
+
return _common.decode(self._state.debug_error_string)
|
| 315 |
+
|
| 316 |
+
def _repr(self):
|
| 317 |
+
return _rpc_state_string(self.__class__.__name__, self._state)
|
| 318 |
+
|
| 319 |
+
def __repr__(self):
|
| 320 |
+
return self._repr()
|
| 321 |
+
|
| 322 |
+
def __str__(self):
|
| 323 |
+
return self._repr()
|
| 324 |
+
|
| 325 |
+
def cancel(self):
|
| 326 |
+
"""See grpc.Future.cancel."""
|
| 327 |
+
return False
|
| 328 |
+
|
| 329 |
+
def cancelled(self):
|
| 330 |
+
"""See grpc.Future.cancelled."""
|
| 331 |
+
return False
|
| 332 |
+
|
| 333 |
+
def running(self):
|
| 334 |
+
"""See grpc.Future.running."""
|
| 335 |
+
return False
|
| 336 |
+
|
| 337 |
+
def done(self):
|
| 338 |
+
"""See grpc.Future.done."""
|
| 339 |
+
return True
|
| 340 |
+
|
| 341 |
+
def result(self, timeout=None): # pylint: disable=unused-argument
|
| 342 |
+
"""See grpc.Future.result."""
|
| 343 |
+
raise self
|
| 344 |
+
|
| 345 |
+
def exception(self, timeout=None): # pylint: disable=unused-argument
|
| 346 |
+
"""See grpc.Future.exception."""
|
| 347 |
+
return self
|
| 348 |
+
|
| 349 |
+
def traceback(self, timeout=None): # pylint: disable=unused-argument
|
| 350 |
+
"""See grpc.Future.traceback."""
|
| 351 |
+
try:
|
| 352 |
+
raise self
|
| 353 |
+
except grpc.RpcError:
|
| 354 |
+
return sys.exc_info()[2]
|
| 355 |
+
|
| 356 |
+
def add_done_callback(self, fn, timeout=None): # pylint: disable=unused-argument
|
| 357 |
+
"""See grpc.Future.add_done_callback."""
|
| 358 |
+
fn(self)
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
class _Rendezvous(grpc.RpcError, grpc.RpcContext):
|
| 362 |
+
"""An RPC iterator.
|
| 363 |
+
|
| 364 |
+
Attributes:
|
| 365 |
+
_state: An instance of _RPCState.
|
| 366 |
+
_call: An instance of SegregatedCall or IntegratedCall.
|
| 367 |
+
In either case, the _call object is expected to have operate, cancel,
|
| 368 |
+
and next_event methods.
|
| 369 |
+
_response_deserializer: A callable taking bytes and return a Python
|
| 370 |
+
object.
|
| 371 |
+
_deadline: A float representing the deadline of the RPC in seconds. Or
|
| 372 |
+
possibly None, to represent an RPC with no deadline at all.
|
| 373 |
+
"""
|
| 374 |
+
|
| 375 |
+
def __init__(self, state, call, response_deserializer, deadline):
|
| 376 |
+
super(_Rendezvous, self).__init__()
|
| 377 |
+
self._state = state
|
| 378 |
+
self._call = call
|
| 379 |
+
self._response_deserializer = response_deserializer
|
| 380 |
+
self._deadline = deadline
|
| 381 |
+
|
| 382 |
+
def is_active(self):
|
| 383 |
+
"""See grpc.RpcContext.is_active"""
|
| 384 |
+
with self._state.condition:
|
| 385 |
+
return self._state.code is None
|
| 386 |
+
|
| 387 |
+
def time_remaining(self):
|
| 388 |
+
"""See grpc.RpcContext.time_remaining"""
|
| 389 |
+
with self._state.condition:
|
| 390 |
+
if self._deadline is None:
|
| 391 |
+
return None
|
| 392 |
+
else:
|
| 393 |
+
return max(self._deadline - time.time(), 0)
|
| 394 |
+
|
| 395 |
+
def cancel(self):
|
| 396 |
+
"""See grpc.RpcContext.cancel"""
|
| 397 |
+
with self._state.condition:
|
| 398 |
+
if self._state.code is None:
|
| 399 |
+
code = grpc.StatusCode.CANCELLED
|
| 400 |
+
details = 'Locally cancelled by application!'
|
| 401 |
+
self._call.cancel(
|
| 402 |
+
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details)
|
| 403 |
+
self._state.cancelled = True
|
| 404 |
+
_abort(self._state, code, details)
|
| 405 |
+
self._state.condition.notify_all()
|
| 406 |
+
return True
|
| 407 |
+
else:
|
| 408 |
+
return False
|
| 409 |
+
|
| 410 |
+
def add_callback(self, callback):
|
| 411 |
+
"""See grpc.RpcContext.add_callback"""
|
| 412 |
+
with self._state.condition:
|
| 413 |
+
if self._state.callbacks is None:
|
| 414 |
+
return False
|
| 415 |
+
else:
|
| 416 |
+
self._state.callbacks.append(callback)
|
| 417 |
+
return True
|
| 418 |
+
|
| 419 |
+
def __iter__(self):
|
| 420 |
+
return self
|
| 421 |
+
|
| 422 |
+
def next(self):
|
| 423 |
+
return self._next()
|
| 424 |
+
|
| 425 |
+
def __next__(self):
|
| 426 |
+
return self._next()
|
| 427 |
+
|
| 428 |
+
def _next(self):
|
| 429 |
+
raise NotImplementedError()
|
| 430 |
+
|
| 431 |
+
def debug_error_string(self):
|
| 432 |
+
raise NotImplementedError()
|
| 433 |
+
|
| 434 |
+
def _repr(self):
|
| 435 |
+
return _rpc_state_string(self.__class__.__name__, self._state)
|
| 436 |
+
|
| 437 |
+
def __repr__(self):
|
| 438 |
+
return self._repr()
|
| 439 |
+
|
| 440 |
+
def __str__(self):
|
| 441 |
+
return self._repr()
|
| 442 |
+
|
| 443 |
+
def __del__(self):
|
| 444 |
+
with self._state.condition:
|
| 445 |
+
if self._state.code is None:
|
| 446 |
+
self._state.code = grpc.StatusCode.CANCELLED
|
| 447 |
+
self._state.details = 'Cancelled upon garbage collection!'
|
| 448 |
+
self._state.cancelled = True
|
| 449 |
+
self._call.cancel(
|
| 450 |
+
_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[self._state.code],
|
| 451 |
+
self._state.details)
|
| 452 |
+
self._state.condition.notify_all()
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
class _SingleThreadedRendezvous(_Rendezvous, grpc.Call, grpc.Future): # pylint: disable=too-many-ancestors
|
| 456 |
+
"""An RPC iterator operating entirely on a single thread.
|
| 457 |
+
|
| 458 |
+
The __next__ method of _SingleThreadedRendezvous does not depend on the
|
| 459 |
+
existence of any other thread, including the "channel spin thread".
|
| 460 |
+
However, this means that its interface is entirely synchronous. So this
|
| 461 |
+
class cannot completely fulfill the grpc.Future interface. The result,
|
| 462 |
+
exception, and traceback methods will never block and will instead raise
|
| 463 |
+
an exception if calling the method would result in blocking.
|
| 464 |
+
|
| 465 |
+
This means that these methods are safe to call from add_done_callback
|
| 466 |
+
handlers.
|
| 467 |
+
"""
|
| 468 |
+
|
| 469 |
+
def _is_complete(self):
|
| 470 |
+
return self._state.code is not None
|
| 471 |
+
|
| 472 |
+
def cancelled(self):
|
| 473 |
+
with self._state.condition:
|
| 474 |
+
return self._state.cancelled
|
| 475 |
+
|
| 476 |
+
def running(self):
|
| 477 |
+
with self._state.condition:
|
| 478 |
+
return self._state.code is None
|
| 479 |
+
|
| 480 |
+
def done(self):
|
| 481 |
+
with self._state.condition:
|
| 482 |
+
return self._state.code is not None
|
| 483 |
+
|
| 484 |
+
def result(self, timeout=None):
|
| 485 |
+
"""Returns the result of the computation or raises its exception.
|
| 486 |
+
|
| 487 |
+
This method will never block. Instead, it will raise an exception
|
| 488 |
+
if calling this method would otherwise result in blocking.
|
| 489 |
+
|
| 490 |
+
Since this method will never block, any `timeout` argument passed will
|
| 491 |
+
be ignored.
|
| 492 |
+
"""
|
| 493 |
+
del timeout
|
| 494 |
+
with self._state.condition:
|
| 495 |
+
if not self._is_complete():
|
| 496 |
+
raise grpc.experimental.UsageError(
|
| 497 |
+
"_SingleThreadedRendezvous only supports result() when the RPC is complete."
|
| 498 |
+
)
|
| 499 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 500 |
+
return self._state.response
|
| 501 |
+
elif self._state.cancelled:
|
| 502 |
+
raise grpc.FutureCancelledError()
|
| 503 |
+
else:
|
| 504 |
+
raise self
|
| 505 |
+
|
| 506 |
+
def exception(self, timeout=None):
|
| 507 |
+
"""Return the exception raised by the computation.
|
| 508 |
+
|
| 509 |
+
This method will never block. Instead, it will raise an exception
|
| 510 |
+
if calling this method would otherwise result in blocking.
|
| 511 |
+
|
| 512 |
+
Since this method will never block, any `timeout` argument passed will
|
| 513 |
+
be ignored.
|
| 514 |
+
"""
|
| 515 |
+
del timeout
|
| 516 |
+
with self._state.condition:
|
| 517 |
+
if not self._is_complete():
|
| 518 |
+
raise grpc.experimental.UsageError(
|
| 519 |
+
"_SingleThreadedRendezvous only supports exception() when the RPC is complete."
|
| 520 |
+
)
|
| 521 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 522 |
+
return None
|
| 523 |
+
elif self._state.cancelled:
|
| 524 |
+
raise grpc.FutureCancelledError()
|
| 525 |
+
else:
|
| 526 |
+
return self
|
| 527 |
+
|
| 528 |
+
def traceback(self, timeout=None):
|
| 529 |
+
"""Access the traceback of the exception raised by the computation.
|
| 530 |
+
|
| 531 |
+
This method will never block. Instead, it will raise an exception
|
| 532 |
+
if calling this method would otherwise result in blocking.
|
| 533 |
+
|
| 534 |
+
Since this method will never block, any `timeout` argument passed will
|
| 535 |
+
be ignored.
|
| 536 |
+
"""
|
| 537 |
+
del timeout
|
| 538 |
+
with self._state.condition:
|
| 539 |
+
if not self._is_complete():
|
| 540 |
+
raise grpc.experimental.UsageError(
|
| 541 |
+
"_SingleThreadedRendezvous only supports traceback() when the RPC is complete."
|
| 542 |
+
)
|
| 543 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 544 |
+
return None
|
| 545 |
+
elif self._state.cancelled:
|
| 546 |
+
raise grpc.FutureCancelledError()
|
| 547 |
+
else:
|
| 548 |
+
try:
|
| 549 |
+
raise self
|
| 550 |
+
except grpc.RpcError:
|
| 551 |
+
return sys.exc_info()[2]
|
| 552 |
+
|
| 553 |
+
def add_done_callback(self, fn):
|
| 554 |
+
with self._state.condition:
|
| 555 |
+
if self._state.code is None:
|
| 556 |
+
self._state.callbacks.append(functools.partial(fn, self))
|
| 557 |
+
return
|
| 558 |
+
|
| 559 |
+
fn(self)
|
| 560 |
+
|
| 561 |
+
def initial_metadata(self):
|
| 562 |
+
"""See grpc.Call.initial_metadata"""
|
| 563 |
+
with self._state.condition:
|
| 564 |
+
# NOTE(gnossen): Based on our initial call batch, we are guaranteed
|
| 565 |
+
# to receive initial metadata before any messages.
|
| 566 |
+
while self._state.initial_metadata is None:
|
| 567 |
+
self._consume_next_event()
|
| 568 |
+
return self._state.initial_metadata
|
| 569 |
+
|
| 570 |
+
def trailing_metadata(self):
|
| 571 |
+
"""See grpc.Call.trailing_metadata"""
|
| 572 |
+
with self._state.condition:
|
| 573 |
+
if self._state.trailing_metadata is None:
|
| 574 |
+
raise grpc.experimental.UsageError(
|
| 575 |
+
"Cannot get trailing metadata until RPC is completed.")
|
| 576 |
+
return self._state.trailing_metadata
|
| 577 |
+
|
| 578 |
+
def code(self):
|
| 579 |
+
"""See grpc.Call.code"""
|
| 580 |
+
with self._state.condition:
|
| 581 |
+
if self._state.code is None:
|
| 582 |
+
raise grpc.experimental.UsageError(
|
| 583 |
+
"Cannot get code until RPC is completed.")
|
| 584 |
+
return self._state.code
|
| 585 |
+
|
| 586 |
+
def details(self):
|
| 587 |
+
"""See grpc.Call.details"""
|
| 588 |
+
with self._state.condition:
|
| 589 |
+
if self._state.details is None:
|
| 590 |
+
raise grpc.experimental.UsageError(
|
| 591 |
+
"Cannot get details until RPC is completed.")
|
| 592 |
+
return _common.decode(self._state.details)
|
| 593 |
+
|
| 594 |
+
def _consume_next_event(self):
|
| 595 |
+
event = self._call.next_event()
|
| 596 |
+
with self._state.condition:
|
| 597 |
+
callbacks = _handle_event(event, self._state,
|
| 598 |
+
self._response_deserializer)
|
| 599 |
+
for callback in callbacks:
|
| 600 |
+
# NOTE(gnossen): We intentionally allow exceptions to bubble up
|
| 601 |
+
# to the user when running on a single thread.
|
| 602 |
+
callback()
|
| 603 |
+
return event
|
| 604 |
+
|
| 605 |
+
def _next_response(self):
|
| 606 |
+
while True:
|
| 607 |
+
self._consume_next_event()
|
| 608 |
+
with self._state.condition:
|
| 609 |
+
if self._state.response is not None:
|
| 610 |
+
response = self._state.response
|
| 611 |
+
self._state.response = None
|
| 612 |
+
return response
|
| 613 |
+
elif cygrpc.OperationType.receive_message not in self._state.due:
|
| 614 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 615 |
+
raise StopIteration()
|
| 616 |
+
elif self._state.code is not None:
|
| 617 |
+
raise self
|
| 618 |
+
|
| 619 |
+
def _next(self):
|
| 620 |
+
with self._state.condition:
|
| 621 |
+
if self._state.code is None:
|
| 622 |
+
# We tentatively add the operation as expected and remove
|
| 623 |
+
# it if the enqueue operation fails. This allows us to guarantee that
|
| 624 |
+
# if an event has been submitted to the core completion queue,
|
| 625 |
+
# it is in `due`. If we waited until after a successful
|
| 626 |
+
# enqueue operation then a signal could interrupt this
|
| 627 |
+
# thread between the enqueue operation and the addition of the
|
| 628 |
+
# operation to `due`. This would cause an exception on the
|
| 629 |
+
# channel spin thread when the operation completes and no
|
| 630 |
+
# corresponding operation would be present in state.due.
|
| 631 |
+
# Note that, since `condition` is held through this block, there is
|
| 632 |
+
# no data race on `due`.
|
| 633 |
+
self._state.due.add(cygrpc.OperationType.receive_message)
|
| 634 |
+
operating = self._call.operate(
|
| 635 |
+
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),), None)
|
| 636 |
+
if not operating:
|
| 637 |
+
self._state.due.remove(cygrpc.OperationType.receive_message)
|
| 638 |
+
elif self._state.code is grpc.StatusCode.OK:
|
| 639 |
+
raise StopIteration()
|
| 640 |
+
else:
|
| 641 |
+
raise self
|
| 642 |
+
return self._next_response()
|
| 643 |
+
|
| 644 |
+
def debug_error_string(self):
|
| 645 |
+
with self._state.condition:
|
| 646 |
+
if self._state.debug_error_string is None:
|
| 647 |
+
raise grpc.experimental.UsageError(
|
| 648 |
+
"Cannot get debug error string until RPC is completed.")
|
| 649 |
+
return _common.decode(self._state.debug_error_string)
|
| 650 |
+
|
| 651 |
+
|
| 652 |
+
class _MultiThreadedRendezvous(_Rendezvous, grpc.Call, grpc.Future): # pylint: disable=too-many-ancestors
|
| 653 |
+
"""An RPC iterator that depends on a channel spin thread.
|
| 654 |
+
|
| 655 |
+
This iterator relies upon a per-channel thread running in the background,
|
| 656 |
+
dequeueing events from the completion queue, and notifying threads waiting
|
| 657 |
+
on the threading.Condition object in the _RPCState object.
|
| 658 |
+
|
| 659 |
+
This extra thread allows _MultiThreadedRendezvous to fulfill the grpc.Future interface
|
| 660 |
+
and to mediate a bidirection streaming RPC.
|
| 661 |
+
"""
|
| 662 |
+
|
| 663 |
+
def initial_metadata(self):
|
| 664 |
+
"""See grpc.Call.initial_metadata"""
|
| 665 |
+
with self._state.condition:
|
| 666 |
+
|
| 667 |
+
def _done():
|
| 668 |
+
return self._state.initial_metadata is not None
|
| 669 |
+
|
| 670 |
+
_common.wait(self._state.condition.wait, _done)
|
| 671 |
+
return self._state.initial_metadata
|
| 672 |
+
|
| 673 |
+
def trailing_metadata(self):
|
| 674 |
+
"""See grpc.Call.trailing_metadata"""
|
| 675 |
+
with self._state.condition:
|
| 676 |
+
|
| 677 |
+
def _done():
|
| 678 |
+
return self._state.trailing_metadata is not None
|
| 679 |
+
|
| 680 |
+
_common.wait(self._state.condition.wait, _done)
|
| 681 |
+
return self._state.trailing_metadata
|
| 682 |
+
|
| 683 |
+
def code(self):
|
| 684 |
+
"""See grpc.Call.code"""
|
| 685 |
+
with self._state.condition:
|
| 686 |
+
|
| 687 |
+
def _done():
|
| 688 |
+
return self._state.code is not None
|
| 689 |
+
|
| 690 |
+
_common.wait(self._state.condition.wait, _done)
|
| 691 |
+
return self._state.code
|
| 692 |
+
|
| 693 |
+
def details(self):
|
| 694 |
+
"""See grpc.Call.details"""
|
| 695 |
+
with self._state.condition:
|
| 696 |
+
|
| 697 |
+
def _done():
|
| 698 |
+
return self._state.details is not None
|
| 699 |
+
|
| 700 |
+
_common.wait(self._state.condition.wait, _done)
|
| 701 |
+
return _common.decode(self._state.details)
|
| 702 |
+
|
| 703 |
+
def debug_error_string(self):
|
| 704 |
+
with self._state.condition:
|
| 705 |
+
|
| 706 |
+
def _done():
|
| 707 |
+
return self._state.debug_error_string is not None
|
| 708 |
+
|
| 709 |
+
_common.wait(self._state.condition.wait, _done)
|
| 710 |
+
return _common.decode(self._state.debug_error_string)
|
| 711 |
+
|
| 712 |
+
def cancelled(self):
|
| 713 |
+
with self._state.condition:
|
| 714 |
+
return self._state.cancelled
|
| 715 |
+
|
| 716 |
+
def running(self):
|
| 717 |
+
with self._state.condition:
|
| 718 |
+
return self._state.code is None
|
| 719 |
+
|
| 720 |
+
def done(self):
|
| 721 |
+
with self._state.condition:
|
| 722 |
+
return self._state.code is not None
|
| 723 |
+
|
| 724 |
+
def _is_complete(self):
|
| 725 |
+
return self._state.code is not None
|
| 726 |
+
|
| 727 |
+
def result(self, timeout=None):
|
| 728 |
+
"""Returns the result of the computation or raises its exception.
|
| 729 |
+
|
| 730 |
+
See grpc.Future.result for the full API contract.
|
| 731 |
+
"""
|
| 732 |
+
with self._state.condition:
|
| 733 |
+
timed_out = _common.wait(self._state.condition.wait,
|
| 734 |
+
self._is_complete,
|
| 735 |
+
timeout=timeout)
|
| 736 |
+
if timed_out:
|
| 737 |
+
raise grpc.FutureTimeoutError()
|
| 738 |
+
else:
|
| 739 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 740 |
+
return self._state.response
|
| 741 |
+
elif self._state.cancelled:
|
| 742 |
+
raise grpc.FutureCancelledError()
|
| 743 |
+
else:
|
| 744 |
+
raise self
|
| 745 |
+
|
| 746 |
+
def exception(self, timeout=None):
|
| 747 |
+
"""Return the exception raised by the computation.
|
| 748 |
+
|
| 749 |
+
See grpc.Future.exception for the full API contract.
|
| 750 |
+
"""
|
| 751 |
+
with self._state.condition:
|
| 752 |
+
timed_out = _common.wait(self._state.condition.wait,
|
| 753 |
+
self._is_complete,
|
| 754 |
+
timeout=timeout)
|
| 755 |
+
if timed_out:
|
| 756 |
+
raise grpc.FutureTimeoutError()
|
| 757 |
+
else:
|
| 758 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 759 |
+
return None
|
| 760 |
+
elif self._state.cancelled:
|
| 761 |
+
raise grpc.FutureCancelledError()
|
| 762 |
+
else:
|
| 763 |
+
return self
|
| 764 |
+
|
| 765 |
+
def traceback(self, timeout=None):
|
| 766 |
+
"""Access the traceback of the exception raised by the computation.
|
| 767 |
+
|
| 768 |
+
See grpc.future.traceback for the full API contract.
|
| 769 |
+
"""
|
| 770 |
+
with self._state.condition:
|
| 771 |
+
timed_out = _common.wait(self._state.condition.wait,
|
| 772 |
+
self._is_complete,
|
| 773 |
+
timeout=timeout)
|
| 774 |
+
if timed_out:
|
| 775 |
+
raise grpc.FutureTimeoutError()
|
| 776 |
+
else:
|
| 777 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 778 |
+
return None
|
| 779 |
+
elif self._state.cancelled:
|
| 780 |
+
raise grpc.FutureCancelledError()
|
| 781 |
+
else:
|
| 782 |
+
try:
|
| 783 |
+
raise self
|
| 784 |
+
except grpc.RpcError:
|
| 785 |
+
return sys.exc_info()[2]
|
| 786 |
+
|
| 787 |
+
def add_done_callback(self, fn):
|
| 788 |
+
with self._state.condition:
|
| 789 |
+
if self._state.code is None:
|
| 790 |
+
self._state.callbacks.append(functools.partial(fn, self))
|
| 791 |
+
return
|
| 792 |
+
|
| 793 |
+
fn(self)
|
| 794 |
+
|
| 795 |
+
def _next(self):
|
| 796 |
+
with self._state.condition:
|
| 797 |
+
if self._state.code is None:
|
| 798 |
+
event_handler = _event_handler(self._state,
|
| 799 |
+
self._response_deserializer)
|
| 800 |
+
self._state.due.add(cygrpc.OperationType.receive_message)
|
| 801 |
+
operating = self._call.operate(
|
| 802 |
+
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
|
| 803 |
+
event_handler)
|
| 804 |
+
if not operating:
|
| 805 |
+
self._state.due.remove(cygrpc.OperationType.receive_message)
|
| 806 |
+
elif self._state.code is grpc.StatusCode.OK:
|
| 807 |
+
raise StopIteration()
|
| 808 |
+
else:
|
| 809 |
+
raise self
|
| 810 |
+
|
| 811 |
+
def _response_ready():
|
| 812 |
+
return (self._state.response is not None or
|
| 813 |
+
(cygrpc.OperationType.receive_message
|
| 814 |
+
not in self._state.due and
|
| 815 |
+
self._state.code is not None))
|
| 816 |
+
|
| 817 |
+
_common.wait(self._state.condition.wait, _response_ready)
|
| 818 |
+
if self._state.response is not None:
|
| 819 |
+
response = self._state.response
|
| 820 |
+
self._state.response = None
|
| 821 |
+
return response
|
| 822 |
+
elif cygrpc.OperationType.receive_message not in self._state.due:
|
| 823 |
+
if self._state.code is grpc.StatusCode.OK:
|
| 824 |
+
raise StopIteration()
|
| 825 |
+
elif self._state.code is not None:
|
| 826 |
+
raise self
|
| 827 |
+
|
| 828 |
+
|
| 829 |
+
def _start_unary_request(request, timeout, request_serializer):
|
| 830 |
+
deadline = _deadline(timeout)
|
| 831 |
+
serialized_request = _common.serialize(request, request_serializer)
|
| 832 |
+
if serialized_request is None:
|
| 833 |
+
state = _RPCState((), (), (), grpc.StatusCode.INTERNAL,
|
| 834 |
+
'Exception serializing request!')
|
| 835 |
+
error = _InactiveRpcError(state)
|
| 836 |
+
return deadline, None, error
|
| 837 |
+
else:
|
| 838 |
+
return deadline, serialized_request, None
|
| 839 |
+
|
| 840 |
+
|
| 841 |
+
def _end_unary_response_blocking(state, call, with_call, deadline):
|
| 842 |
+
if state.code is grpc.StatusCode.OK:
|
| 843 |
+
if with_call:
|
| 844 |
+
rendezvous = _MultiThreadedRendezvous(state, call, None, deadline)
|
| 845 |
+
return state.response, rendezvous
|
| 846 |
+
else:
|
| 847 |
+
return state.response
|
| 848 |
+
else:
|
| 849 |
+
raise _InactiveRpcError(state)
|
| 850 |
+
|
| 851 |
+
|
| 852 |
+
def _stream_unary_invocation_operationses(metadata, initial_metadata_flags):
|
| 853 |
+
return (
|
| 854 |
+
(
|
| 855 |
+
cygrpc.SendInitialMetadataOperation(metadata,
|
| 856 |
+
initial_metadata_flags),
|
| 857 |
+
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
|
| 858 |
+
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
|
| 859 |
+
),
|
| 860 |
+
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
|
| 861 |
+
)
|
| 862 |
+
|
| 863 |
+
|
| 864 |
+
def _stream_unary_invocation_operationses_and_tags(metadata,
|
| 865 |
+
initial_metadata_flags):
|
| 866 |
+
return tuple((
|
| 867 |
+
operations,
|
| 868 |
+
None,
|
| 869 |
+
) for operations in _stream_unary_invocation_operationses(
|
| 870 |
+
metadata, initial_metadata_flags))
|
| 871 |
+
|
| 872 |
+
|
| 873 |
+
def _determine_deadline(user_deadline):
|
| 874 |
+
parent_deadline = cygrpc.get_deadline_from_context()
|
| 875 |
+
if parent_deadline is None and user_deadline is None:
|
| 876 |
+
return None
|
| 877 |
+
elif parent_deadline is not None and user_deadline is None:
|
| 878 |
+
return parent_deadline
|
| 879 |
+
elif user_deadline is not None and parent_deadline is None:
|
| 880 |
+
return user_deadline
|
| 881 |
+
else:
|
| 882 |
+
return min(parent_deadline, user_deadline)
|
| 883 |
+
|
| 884 |
+
|
| 885 |
+
class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
|
| 886 |
+
|
| 887 |
+
# pylint: disable=too-many-arguments
|
| 888 |
+
def __init__(self, channel, managed_call, method, request_serializer,
|
| 889 |
+
response_deserializer):
|
| 890 |
+
self._channel = channel
|
| 891 |
+
self._managed_call = managed_call
|
| 892 |
+
self._method = method
|
| 893 |
+
self._request_serializer = request_serializer
|
| 894 |
+
self._response_deserializer = response_deserializer
|
| 895 |
+
self._context = cygrpc.build_census_context()
|
| 896 |
+
|
| 897 |
+
def _prepare(self, request, timeout, metadata, wait_for_ready, compression):
|
| 898 |
+
deadline, serialized_request, rendezvous = _start_unary_request(
|
| 899 |
+
request, timeout, self._request_serializer)
|
| 900 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 901 |
+
wait_for_ready)
|
| 902 |
+
augmented_metadata = _compression.augment_metadata(
|
| 903 |
+
metadata, compression)
|
| 904 |
+
if serialized_request is None:
|
| 905 |
+
return None, None, None, rendezvous
|
| 906 |
+
else:
|
| 907 |
+
state = _RPCState(_UNARY_UNARY_INITIAL_DUE, None, None, None, None)
|
| 908 |
+
operations = (
|
| 909 |
+
cygrpc.SendInitialMetadataOperation(augmented_metadata,
|
| 910 |
+
initial_metadata_flags),
|
| 911 |
+
cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS),
|
| 912 |
+
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
|
| 913 |
+
cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
|
| 914 |
+
cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
|
| 915 |
+
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
|
| 916 |
+
)
|
| 917 |
+
return state, operations, deadline, None
|
| 918 |
+
|
| 919 |
+
def _blocking(self, request, timeout, metadata, credentials, wait_for_ready,
|
| 920 |
+
compression):
|
| 921 |
+
state, operations, deadline, rendezvous = self._prepare(
|
| 922 |
+
request, timeout, metadata, wait_for_ready, compression)
|
| 923 |
+
if state is None:
|
| 924 |
+
raise rendezvous # pylint: disable-msg=raising-bad-type
|
| 925 |
+
else:
|
| 926 |
+
call = self._channel.segregated_call(
|
| 927 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS,
|
| 928 |
+
self._method, None, _determine_deadline(deadline), metadata,
|
| 929 |
+
None if credentials is None else credentials._credentials, ((
|
| 930 |
+
operations,
|
| 931 |
+
None,
|
| 932 |
+
),), self._context)
|
| 933 |
+
event = call.next_event()
|
| 934 |
+
_handle_event(event, state, self._response_deserializer)
|
| 935 |
+
return state, call
|
| 936 |
+
|
| 937 |
+
def __call__(self,
|
| 938 |
+
request,
|
| 939 |
+
timeout=None,
|
| 940 |
+
metadata=None,
|
| 941 |
+
credentials=None,
|
| 942 |
+
wait_for_ready=None,
|
| 943 |
+
compression=None):
|
| 944 |
+
state, call, = self._blocking(request, timeout, metadata, credentials,
|
| 945 |
+
wait_for_ready, compression)
|
| 946 |
+
return _end_unary_response_blocking(state, call, False, None)
|
| 947 |
+
|
| 948 |
+
def with_call(self,
|
| 949 |
+
request,
|
| 950 |
+
timeout=None,
|
| 951 |
+
metadata=None,
|
| 952 |
+
credentials=None,
|
| 953 |
+
wait_for_ready=None,
|
| 954 |
+
compression=None):
|
| 955 |
+
state, call, = self._blocking(request, timeout, metadata, credentials,
|
| 956 |
+
wait_for_ready, compression)
|
| 957 |
+
return _end_unary_response_blocking(state, call, True, None)
|
| 958 |
+
|
| 959 |
+
def future(self,
|
| 960 |
+
request,
|
| 961 |
+
timeout=None,
|
| 962 |
+
metadata=None,
|
| 963 |
+
credentials=None,
|
| 964 |
+
wait_for_ready=None,
|
| 965 |
+
compression=None):
|
| 966 |
+
state, operations, deadline, rendezvous = self._prepare(
|
| 967 |
+
request, timeout, metadata, wait_for_ready, compression)
|
| 968 |
+
if state is None:
|
| 969 |
+
raise rendezvous # pylint: disable-msg=raising-bad-type
|
| 970 |
+
else:
|
| 971 |
+
event_handler = _event_handler(state, self._response_deserializer)
|
| 972 |
+
call = self._managed_call(
|
| 973 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS,
|
| 974 |
+
self._method, None, deadline, metadata,
|
| 975 |
+
None if credentials is None else credentials._credentials,
|
| 976 |
+
(operations,), event_handler, self._context)
|
| 977 |
+
return _MultiThreadedRendezvous(state, call,
|
| 978 |
+
self._response_deserializer,
|
| 979 |
+
deadline)
|
| 980 |
+
|
| 981 |
+
|
| 982 |
+
class _SingleThreadedUnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
|
| 983 |
+
|
| 984 |
+
# pylint: disable=too-many-arguments
|
| 985 |
+
def __init__(self, channel, method, request_serializer,
|
| 986 |
+
response_deserializer):
|
| 987 |
+
self._channel = channel
|
| 988 |
+
self._method = method
|
| 989 |
+
self._request_serializer = request_serializer
|
| 990 |
+
self._response_deserializer = response_deserializer
|
| 991 |
+
self._context = cygrpc.build_census_context()
|
| 992 |
+
|
| 993 |
+
def __call__( # pylint: disable=too-many-locals
|
| 994 |
+
self,
|
| 995 |
+
request,
|
| 996 |
+
timeout=None,
|
| 997 |
+
metadata=None,
|
| 998 |
+
credentials=None,
|
| 999 |
+
wait_for_ready=None,
|
| 1000 |
+
compression=None):
|
| 1001 |
+
deadline = _deadline(timeout)
|
| 1002 |
+
serialized_request = _common.serialize(request,
|
| 1003 |
+
self._request_serializer)
|
| 1004 |
+
if serialized_request is None:
|
| 1005 |
+
state = _RPCState((), (), (), grpc.StatusCode.INTERNAL,
|
| 1006 |
+
'Exception serializing request!')
|
| 1007 |
+
raise _InactiveRpcError(state)
|
| 1008 |
+
|
| 1009 |
+
state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None)
|
| 1010 |
+
call_credentials = None if credentials is None else credentials._credentials
|
| 1011 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 1012 |
+
wait_for_ready)
|
| 1013 |
+
augmented_metadata = _compression.augment_metadata(
|
| 1014 |
+
metadata, compression)
|
| 1015 |
+
operations = (
|
| 1016 |
+
(cygrpc.SendInitialMetadataOperation(augmented_metadata,
|
| 1017 |
+
initial_metadata_flags),
|
| 1018 |
+
cygrpc.SendMessageOperation(serialized_request, _EMPTY_FLAGS),
|
| 1019 |
+
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS)),
|
| 1020 |
+
(cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),),
|
| 1021 |
+
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
|
| 1022 |
+
)
|
| 1023 |
+
operations_and_tags = tuple((ops, None) for ops in operations)
|
| 1024 |
+
call = self._channel.segregated_call(
|
| 1025 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method,
|
| 1026 |
+
None, _determine_deadline(deadline), metadata, call_credentials,
|
| 1027 |
+
operations_and_tags, self._context)
|
| 1028 |
+
return _SingleThreadedRendezvous(state, call,
|
| 1029 |
+
self._response_deserializer, deadline)
|
| 1030 |
+
|
| 1031 |
+
|
| 1032 |
+
class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
|
| 1033 |
+
|
| 1034 |
+
# pylint: disable=too-many-arguments
|
| 1035 |
+
def __init__(self, channel, managed_call, method, request_serializer,
|
| 1036 |
+
response_deserializer):
|
| 1037 |
+
self._channel = channel
|
| 1038 |
+
self._managed_call = managed_call
|
| 1039 |
+
self._method = method
|
| 1040 |
+
self._request_serializer = request_serializer
|
| 1041 |
+
self._response_deserializer = response_deserializer
|
| 1042 |
+
self._context = cygrpc.build_census_context()
|
| 1043 |
+
|
| 1044 |
+
def __call__( # pylint: disable=too-many-locals
|
| 1045 |
+
self,
|
| 1046 |
+
request,
|
| 1047 |
+
timeout=None,
|
| 1048 |
+
metadata=None,
|
| 1049 |
+
credentials=None,
|
| 1050 |
+
wait_for_ready=None,
|
| 1051 |
+
compression=None):
|
| 1052 |
+
deadline, serialized_request, rendezvous = _start_unary_request(
|
| 1053 |
+
request, timeout, self._request_serializer)
|
| 1054 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 1055 |
+
wait_for_ready)
|
| 1056 |
+
if serialized_request is None:
|
| 1057 |
+
raise rendezvous # pylint: disable-msg=raising-bad-type
|
| 1058 |
+
else:
|
| 1059 |
+
augmented_metadata = _compression.augment_metadata(
|
| 1060 |
+
metadata, compression)
|
| 1061 |
+
state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None)
|
| 1062 |
+
operationses = (
|
| 1063 |
+
(
|
| 1064 |
+
cygrpc.SendInitialMetadataOperation(augmented_metadata,
|
| 1065 |
+
initial_metadata_flags),
|
| 1066 |
+
cygrpc.SendMessageOperation(serialized_request,
|
| 1067 |
+
_EMPTY_FLAGS),
|
| 1068 |
+
cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
|
| 1069 |
+
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
|
| 1070 |
+
),
|
| 1071 |
+
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
|
| 1072 |
+
)
|
| 1073 |
+
call = self._managed_call(
|
| 1074 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS,
|
| 1075 |
+
self._method, None, _determine_deadline(deadline), metadata,
|
| 1076 |
+
None if credentials is None else credentials._credentials,
|
| 1077 |
+
operationses, _event_handler(state,
|
| 1078 |
+
self._response_deserializer),
|
| 1079 |
+
self._context)
|
| 1080 |
+
return _MultiThreadedRendezvous(state, call,
|
| 1081 |
+
self._response_deserializer,
|
| 1082 |
+
deadline)
|
| 1083 |
+
|
| 1084 |
+
|
| 1085 |
+
class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
|
| 1086 |
+
|
| 1087 |
+
# pylint: disable=too-many-arguments
|
| 1088 |
+
def __init__(self, channel, managed_call, method, request_serializer,
|
| 1089 |
+
response_deserializer):
|
| 1090 |
+
self._channel = channel
|
| 1091 |
+
self._managed_call = managed_call
|
| 1092 |
+
self._method = method
|
| 1093 |
+
self._request_serializer = request_serializer
|
| 1094 |
+
self._response_deserializer = response_deserializer
|
| 1095 |
+
self._context = cygrpc.build_census_context()
|
| 1096 |
+
|
| 1097 |
+
def _blocking(self, request_iterator, timeout, metadata, credentials,
|
| 1098 |
+
wait_for_ready, compression):
|
| 1099 |
+
deadline = _deadline(timeout)
|
| 1100 |
+
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
|
| 1101 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 1102 |
+
wait_for_ready)
|
| 1103 |
+
augmented_metadata = _compression.augment_metadata(
|
| 1104 |
+
metadata, compression)
|
| 1105 |
+
call = self._channel.segregated_call(
|
| 1106 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method,
|
| 1107 |
+
None, _determine_deadline(deadline), augmented_metadata,
|
| 1108 |
+
None if credentials is None else credentials._credentials,
|
| 1109 |
+
_stream_unary_invocation_operationses_and_tags(
|
| 1110 |
+
augmented_metadata, initial_metadata_flags), self._context)
|
| 1111 |
+
_consume_request_iterator(request_iterator, state, call,
|
| 1112 |
+
self._request_serializer, None)
|
| 1113 |
+
while True:
|
| 1114 |
+
event = call.next_event()
|
| 1115 |
+
with state.condition:
|
| 1116 |
+
_handle_event(event, state, self._response_deserializer)
|
| 1117 |
+
state.condition.notify_all()
|
| 1118 |
+
if not state.due:
|
| 1119 |
+
break
|
| 1120 |
+
return state, call
|
| 1121 |
+
|
| 1122 |
+
def __call__(self,
|
| 1123 |
+
request_iterator,
|
| 1124 |
+
timeout=None,
|
| 1125 |
+
metadata=None,
|
| 1126 |
+
credentials=None,
|
| 1127 |
+
wait_for_ready=None,
|
| 1128 |
+
compression=None):
|
| 1129 |
+
state, call, = self._blocking(request_iterator, timeout, metadata,
|
| 1130 |
+
credentials, wait_for_ready, compression)
|
| 1131 |
+
return _end_unary_response_blocking(state, call, False, None)
|
| 1132 |
+
|
| 1133 |
+
def with_call(self,
|
| 1134 |
+
request_iterator,
|
| 1135 |
+
timeout=None,
|
| 1136 |
+
metadata=None,
|
| 1137 |
+
credentials=None,
|
| 1138 |
+
wait_for_ready=None,
|
| 1139 |
+
compression=None):
|
| 1140 |
+
state, call, = self._blocking(request_iterator, timeout, metadata,
|
| 1141 |
+
credentials, wait_for_ready, compression)
|
| 1142 |
+
return _end_unary_response_blocking(state, call, True, None)
|
| 1143 |
+
|
| 1144 |
+
def future(self,
|
| 1145 |
+
request_iterator,
|
| 1146 |
+
timeout=None,
|
| 1147 |
+
metadata=None,
|
| 1148 |
+
credentials=None,
|
| 1149 |
+
wait_for_ready=None,
|
| 1150 |
+
compression=None):
|
| 1151 |
+
deadline = _deadline(timeout)
|
| 1152 |
+
state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
|
| 1153 |
+
event_handler = _event_handler(state, self._response_deserializer)
|
| 1154 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 1155 |
+
wait_for_ready)
|
| 1156 |
+
augmented_metadata = _compression.augment_metadata(
|
| 1157 |
+
metadata, compression)
|
| 1158 |
+
call = self._managed_call(
|
| 1159 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method,
|
| 1160 |
+
None, deadline, augmented_metadata,
|
| 1161 |
+
None if credentials is None else credentials._credentials,
|
| 1162 |
+
_stream_unary_invocation_operationses(metadata,
|
| 1163 |
+
initial_metadata_flags),
|
| 1164 |
+
event_handler, self._context)
|
| 1165 |
+
_consume_request_iterator(request_iterator, state, call,
|
| 1166 |
+
self._request_serializer, event_handler)
|
| 1167 |
+
return _MultiThreadedRendezvous(state, call,
|
| 1168 |
+
self._response_deserializer, deadline)
|
| 1169 |
+
|
| 1170 |
+
|
| 1171 |
+
class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
|
| 1172 |
+
|
| 1173 |
+
# pylint: disable=too-many-arguments
|
| 1174 |
+
def __init__(self, channel, managed_call, method, request_serializer,
|
| 1175 |
+
response_deserializer):
|
| 1176 |
+
self._channel = channel
|
| 1177 |
+
self._managed_call = managed_call
|
| 1178 |
+
self._method = method
|
| 1179 |
+
self._request_serializer = request_serializer
|
| 1180 |
+
self._response_deserializer = response_deserializer
|
| 1181 |
+
self._context = cygrpc.build_census_context()
|
| 1182 |
+
|
| 1183 |
+
def __call__(self,
|
| 1184 |
+
request_iterator,
|
| 1185 |
+
timeout=None,
|
| 1186 |
+
metadata=None,
|
| 1187 |
+
credentials=None,
|
| 1188 |
+
wait_for_ready=None,
|
| 1189 |
+
compression=None):
|
| 1190 |
+
deadline = _deadline(timeout)
|
| 1191 |
+
state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None)
|
| 1192 |
+
initial_metadata_flags = _InitialMetadataFlags().with_wait_for_ready(
|
| 1193 |
+
wait_for_ready)
|
| 1194 |
+
augmented_metadata = _compression.augment_metadata(
|
| 1195 |
+
metadata, compression)
|
| 1196 |
+
operationses = (
|
| 1197 |
+
(
|
| 1198 |
+
cygrpc.SendInitialMetadataOperation(augmented_metadata,
|
| 1199 |
+
initial_metadata_flags),
|
| 1200 |
+
cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
|
| 1201 |
+
),
|
| 1202 |
+
(cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
|
| 1203 |
+
)
|
| 1204 |
+
event_handler = _event_handler(state, self._response_deserializer)
|
| 1205 |
+
call = self._managed_call(
|
| 1206 |
+
cygrpc.PropagationConstants.GRPC_PROPAGATE_DEFAULTS, self._method,
|
| 1207 |
+
None, _determine_deadline(deadline), augmented_metadata,
|
| 1208 |
+
None if credentials is None else credentials._credentials,
|
| 1209 |
+
operationses, event_handler, self._context)
|
| 1210 |
+
_consume_request_iterator(request_iterator, state, call,
|
| 1211 |
+
self._request_serializer, event_handler)
|
| 1212 |
+
return _MultiThreadedRendezvous(state, call,
|
| 1213 |
+
self._response_deserializer, deadline)
|
| 1214 |
+
|
| 1215 |
+
|
| 1216 |
+
class _InitialMetadataFlags(int):
|
| 1217 |
+
"""Stores immutable initial metadata flags"""
|
| 1218 |
+
|
| 1219 |
+
def __new__(cls, value=_EMPTY_FLAGS):
|
| 1220 |
+
value &= cygrpc.InitialMetadataFlags.used_mask
|
| 1221 |
+
return super(_InitialMetadataFlags, cls).__new__(cls, value)
|
| 1222 |
+
|
| 1223 |
+
def with_wait_for_ready(self, wait_for_ready):
|
| 1224 |
+
if wait_for_ready is not None:
|
| 1225 |
+
if wait_for_ready:
|
| 1226 |
+
return self.__class__(self | cygrpc.InitialMetadataFlags.wait_for_ready | \
|
| 1227 |
+
cygrpc.InitialMetadataFlags.wait_for_ready_explicitly_set)
|
| 1228 |
+
elif not wait_for_ready:
|
| 1229 |
+
return self.__class__(self & ~cygrpc.InitialMetadataFlags.wait_for_ready | \
|
| 1230 |
+
cygrpc.InitialMetadataFlags.wait_for_ready_explicitly_set)
|
| 1231 |
+
return self
|
| 1232 |
+
|
| 1233 |
+
|
| 1234 |
+
class _ChannelCallState(object):
|
| 1235 |
+
|
| 1236 |
+
def __init__(self, channel):
|
| 1237 |
+
self.lock = threading.Lock()
|
| 1238 |
+
self.channel = channel
|
| 1239 |
+
self.managed_calls = 0
|
| 1240 |
+
self.threading = False
|
| 1241 |
+
|
| 1242 |
+
def reset_postfork_child(self):
|
| 1243 |
+
self.managed_calls = 0
|
| 1244 |
+
|
| 1245 |
+
def __del__(self):
|
| 1246 |
+
try:
|
| 1247 |
+
self.channel.close(cygrpc.StatusCode.cancelled,
|
| 1248 |
+
'Channel deallocated!')
|
| 1249 |
+
except (TypeError, AttributeError):
|
| 1250 |
+
pass
|
| 1251 |
+
|
| 1252 |
+
|
| 1253 |
+
def _run_channel_spin_thread(state):
|
| 1254 |
+
|
| 1255 |
+
def channel_spin():
|
| 1256 |
+
while True:
|
| 1257 |
+
cygrpc.block_if_fork_in_progress(state)
|
| 1258 |
+
event = state.channel.next_call_event()
|
| 1259 |
+
if event.completion_type == cygrpc.CompletionType.queue_timeout:
|
| 1260 |
+
continue
|
| 1261 |
+
call_completed = event.tag(event)
|
| 1262 |
+
if call_completed:
|
| 1263 |
+
with state.lock:
|
| 1264 |
+
state.managed_calls -= 1
|
| 1265 |
+
if state.managed_calls == 0:
|
| 1266 |
+
return
|
| 1267 |
+
|
| 1268 |
+
channel_spin_thread = cygrpc.ForkManagedThread(target=channel_spin)
|
| 1269 |
+
channel_spin_thread.setDaemon(True)
|
| 1270 |
+
channel_spin_thread.start()
|
| 1271 |
+
|
| 1272 |
+
|
| 1273 |
+
def _channel_managed_call_management(state):
|
| 1274 |
+
|
| 1275 |
+
# pylint: disable=too-many-arguments
|
| 1276 |
+
def create(flags, method, host, deadline, metadata, credentials,
|
| 1277 |
+
operationses, event_handler, context):
|
| 1278 |
+
"""Creates a cygrpc.IntegratedCall.
|
| 1279 |
+
|
| 1280 |
+
Args:
|
| 1281 |
+
flags: An integer bitfield of call flags.
|
| 1282 |
+
method: The RPC method.
|
| 1283 |
+
host: A host string for the created call.
|
| 1284 |
+
deadline: A float to be the deadline of the created call or None if
|
| 1285 |
+
the call is to have an infinite deadline.
|
| 1286 |
+
metadata: The metadata for the call or None.
|
| 1287 |
+
credentials: A cygrpc.CallCredentials or None.
|
| 1288 |
+
operationses: An iterable of iterables of cygrpc.Operations to be
|
| 1289 |
+
started on the call.
|
| 1290 |
+
event_handler: A behavior to call to handle the events resultant from
|
| 1291 |
+
the operations on the call.
|
| 1292 |
+
context: Context object for distributed tracing.
|
| 1293 |
+
Returns:
|
| 1294 |
+
A cygrpc.IntegratedCall with which to conduct an RPC.
|
| 1295 |
+
"""
|
| 1296 |
+
operationses_and_tags = tuple((
|
| 1297 |
+
operations,
|
| 1298 |
+
event_handler,
|
| 1299 |
+
) for operations in operationses)
|
| 1300 |
+
with state.lock:
|
| 1301 |
+
call = state.channel.integrated_call(flags, method, host, deadline,
|
| 1302 |
+
metadata, credentials,
|
| 1303 |
+
operationses_and_tags, context)
|
| 1304 |
+
if state.managed_calls == 0:
|
| 1305 |
+
state.managed_calls = 1
|
| 1306 |
+
_run_channel_spin_thread(state)
|
| 1307 |
+
else:
|
| 1308 |
+
state.managed_calls += 1
|
| 1309 |
+
return call
|
| 1310 |
+
|
| 1311 |
+
return create
|
| 1312 |
+
|
| 1313 |
+
|
| 1314 |
+
class _ChannelConnectivityState(object):
|
| 1315 |
+
|
| 1316 |
+
def __init__(self, channel):
|
| 1317 |
+
self.lock = threading.RLock()
|
| 1318 |
+
self.channel = channel
|
| 1319 |
+
self.polling = False
|
| 1320 |
+
self.connectivity = None
|
| 1321 |
+
self.try_to_connect = False
|
| 1322 |
+
self.callbacks_and_connectivities = []
|
| 1323 |
+
self.delivering = False
|
| 1324 |
+
|
| 1325 |
+
def reset_postfork_child(self):
|
| 1326 |
+
self.polling = False
|
| 1327 |
+
self.connectivity = None
|
| 1328 |
+
self.try_to_connect = False
|
| 1329 |
+
self.callbacks_and_connectivities = []
|
| 1330 |
+
self.delivering = False
|
| 1331 |
+
|
| 1332 |
+
|
| 1333 |
+
def _deliveries(state):
|
| 1334 |
+
callbacks_needing_update = []
|
| 1335 |
+
for callback_and_connectivity in state.callbacks_and_connectivities:
|
| 1336 |
+
callback, callback_connectivity, = callback_and_connectivity
|
| 1337 |
+
if callback_connectivity is not state.connectivity:
|
| 1338 |
+
callbacks_needing_update.append(callback)
|
| 1339 |
+
callback_and_connectivity[1] = state.connectivity
|
| 1340 |
+
return callbacks_needing_update
|
| 1341 |
+
|
| 1342 |
+
|
| 1343 |
+
def _deliver(state, initial_connectivity, initial_callbacks):
|
| 1344 |
+
connectivity = initial_connectivity
|
| 1345 |
+
callbacks = initial_callbacks
|
| 1346 |
+
while True:
|
| 1347 |
+
for callback in callbacks:
|
| 1348 |
+
cygrpc.block_if_fork_in_progress(state)
|
| 1349 |
+
try:
|
| 1350 |
+
callback(connectivity)
|
| 1351 |
+
except Exception: # pylint: disable=broad-except
|
| 1352 |
+
_LOGGER.exception(
|
| 1353 |
+
_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE)
|
| 1354 |
+
with state.lock:
|
| 1355 |
+
callbacks = _deliveries(state)
|
| 1356 |
+
if callbacks:
|
| 1357 |
+
connectivity = state.connectivity
|
| 1358 |
+
else:
|
| 1359 |
+
state.delivering = False
|
| 1360 |
+
return
|
| 1361 |
+
|
| 1362 |
+
|
| 1363 |
+
def _spawn_delivery(state, callbacks):
|
| 1364 |
+
delivering_thread = cygrpc.ForkManagedThread(target=_deliver,
|
| 1365 |
+
args=(
|
| 1366 |
+
state,
|
| 1367 |
+
state.connectivity,
|
| 1368 |
+
callbacks,
|
| 1369 |
+
))
|
| 1370 |
+
delivering_thread.setDaemon(True)
|
| 1371 |
+
delivering_thread.start()
|
| 1372 |
+
state.delivering = True
|
| 1373 |
+
|
| 1374 |
+
|
| 1375 |
+
# NOTE(https://github.com/grpc/grpc/issues/3064): We'd rather not poll.
|
| 1376 |
+
def _poll_connectivity(state, channel, initial_try_to_connect):
|
| 1377 |
+
try_to_connect = initial_try_to_connect
|
| 1378 |
+
connectivity = channel.check_connectivity_state(try_to_connect)
|
| 1379 |
+
with state.lock:
|
| 1380 |
+
state.connectivity = (
|
| 1381 |
+
_common.
|
| 1382 |
+
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[connectivity])
|
| 1383 |
+
callbacks = tuple(
|
| 1384 |
+
callback for callback, unused_but_known_to_be_none_connectivity in
|
| 1385 |
+
state.callbacks_and_connectivities)
|
| 1386 |
+
for callback_and_connectivity in state.callbacks_and_connectivities:
|
| 1387 |
+
callback_and_connectivity[1] = state.connectivity
|
| 1388 |
+
if callbacks:
|
| 1389 |
+
_spawn_delivery(state, callbacks)
|
| 1390 |
+
while True:
|
| 1391 |
+
event = channel.watch_connectivity_state(connectivity,
|
| 1392 |
+
time.time() + 0.2)
|
| 1393 |
+
cygrpc.block_if_fork_in_progress(state)
|
| 1394 |
+
with state.lock:
|
| 1395 |
+
if not state.callbacks_and_connectivities and not state.try_to_connect:
|
| 1396 |
+
state.polling = False
|
| 1397 |
+
state.connectivity = None
|
| 1398 |
+
break
|
| 1399 |
+
try_to_connect = state.try_to_connect
|
| 1400 |
+
state.try_to_connect = False
|
| 1401 |
+
if event.success or try_to_connect:
|
| 1402 |
+
connectivity = channel.check_connectivity_state(try_to_connect)
|
| 1403 |
+
with state.lock:
|
| 1404 |
+
state.connectivity = (
|
| 1405 |
+
_common.CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[
|
| 1406 |
+
connectivity])
|
| 1407 |
+
if not state.delivering:
|
| 1408 |
+
callbacks = _deliveries(state)
|
| 1409 |
+
if callbacks:
|
| 1410 |
+
_spawn_delivery(state, callbacks)
|
| 1411 |
+
|
| 1412 |
+
|
| 1413 |
+
def _subscribe(state, callback, try_to_connect):
|
| 1414 |
+
with state.lock:
|
| 1415 |
+
if not state.callbacks_and_connectivities and not state.polling:
|
| 1416 |
+
polling_thread = cygrpc.ForkManagedThread(
|
| 1417 |
+
target=_poll_connectivity,
|
| 1418 |
+
args=(state, state.channel, bool(try_to_connect)))
|
| 1419 |
+
polling_thread.setDaemon(True)
|
| 1420 |
+
polling_thread.start()
|
| 1421 |
+
state.polling = True
|
| 1422 |
+
state.callbacks_and_connectivities.append([callback, None])
|
| 1423 |
+
elif not state.delivering and state.connectivity is not None:
|
| 1424 |
+
_spawn_delivery(state, (callback,))
|
| 1425 |
+
state.try_to_connect |= bool(try_to_connect)
|
| 1426 |
+
state.callbacks_and_connectivities.append(
|
| 1427 |
+
[callback, state.connectivity])
|
| 1428 |
+
else:
|
| 1429 |
+
state.try_to_connect |= bool(try_to_connect)
|
| 1430 |
+
state.callbacks_and_connectivities.append([callback, None])
|
| 1431 |
+
|
| 1432 |
+
|
| 1433 |
+
def _unsubscribe(state, callback):
|
| 1434 |
+
with state.lock:
|
| 1435 |
+
for index, (subscribed_callback, unused_connectivity) in enumerate(
|
| 1436 |
+
state.callbacks_and_connectivities):
|
| 1437 |
+
if callback == subscribed_callback:
|
| 1438 |
+
state.callbacks_and_connectivities.pop(index)
|
| 1439 |
+
break
|
| 1440 |
+
|
| 1441 |
+
|
| 1442 |
+
def _augment_options(base_options, compression):
|
| 1443 |
+
compression_option = _compression.create_channel_option(compression)
|
| 1444 |
+
return tuple(base_options) + compression_option + ((
|
| 1445 |
+
cygrpc.ChannelArgKey.primary_user_agent_string,
|
| 1446 |
+
_USER_AGENT,
|
| 1447 |
+
),)
|
| 1448 |
+
|
| 1449 |
+
|
| 1450 |
+
def _separate_channel_options(options):
|
| 1451 |
+
"""Separates core channel options from Python channel options."""
|
| 1452 |
+
core_options = []
|
| 1453 |
+
python_options = []
|
| 1454 |
+
for pair in options:
|
| 1455 |
+
if pair[0] == grpc.experimental.ChannelOptions.SingleThreadedUnaryStream:
|
| 1456 |
+
python_options.append(pair)
|
| 1457 |
+
else:
|
| 1458 |
+
core_options.append(pair)
|
| 1459 |
+
return python_options, core_options
|
| 1460 |
+
|
| 1461 |
+
|
| 1462 |
+
class Channel(grpc.Channel):
|
| 1463 |
+
"""A cygrpc.Channel-backed implementation of grpc.Channel."""
|
| 1464 |
+
|
| 1465 |
+
def __init__(self, target, options, credentials, compression):
|
| 1466 |
+
"""Constructor.
|
| 1467 |
+
|
| 1468 |
+
Args:
|
| 1469 |
+
target: The target to which to connect.
|
| 1470 |
+
options: Configuration options for the channel.
|
| 1471 |
+
credentials: A cygrpc.ChannelCredentials or None.
|
| 1472 |
+
compression: An optional value indicating the compression method to be
|
| 1473 |
+
used over the lifetime of the channel.
|
| 1474 |
+
"""
|
| 1475 |
+
python_options, core_options = _separate_channel_options(options)
|
| 1476 |
+
self._single_threaded_unary_stream = _DEFAULT_SINGLE_THREADED_UNARY_STREAM
|
| 1477 |
+
self._process_python_options(python_options)
|
| 1478 |
+
self._channel = cygrpc.Channel(
|
| 1479 |
+
_common.encode(target), _augment_options(core_options, compression),
|
| 1480 |
+
credentials)
|
| 1481 |
+
self._call_state = _ChannelCallState(self._channel)
|
| 1482 |
+
self._connectivity_state = _ChannelConnectivityState(self._channel)
|
| 1483 |
+
cygrpc.fork_register_channel(self)
|
| 1484 |
+
if cygrpc.g_gevent_activated:
|
| 1485 |
+
cygrpc.gevent_increment_channel_count()
|
| 1486 |
+
|
| 1487 |
+
def _process_python_options(self, python_options):
|
| 1488 |
+
"""Sets channel attributes according to python-only channel options."""
|
| 1489 |
+
for pair in python_options:
|
| 1490 |
+
if pair[0] == grpc.experimental.ChannelOptions.SingleThreadedUnaryStream:
|
| 1491 |
+
self._single_threaded_unary_stream = True
|
| 1492 |
+
|
| 1493 |
+
def subscribe(self, callback, try_to_connect=None):
|
| 1494 |
+
_subscribe(self._connectivity_state, callback, try_to_connect)
|
| 1495 |
+
|
| 1496 |
+
def unsubscribe(self, callback):
|
| 1497 |
+
_unsubscribe(self._connectivity_state, callback)
|
| 1498 |
+
|
| 1499 |
+
def unary_unary(self,
|
| 1500 |
+
method,
|
| 1501 |
+
request_serializer=None,
|
| 1502 |
+
response_deserializer=None):
|
| 1503 |
+
return _UnaryUnaryMultiCallable(
|
| 1504 |
+
self._channel, _channel_managed_call_management(self._call_state),
|
| 1505 |
+
_common.encode(method), request_serializer, response_deserializer)
|
| 1506 |
+
|
| 1507 |
+
def unary_stream(self,
|
| 1508 |
+
method,
|
| 1509 |
+
request_serializer=None,
|
| 1510 |
+
response_deserializer=None):
|
| 1511 |
+
# NOTE(rbellevi): Benchmarks have shown that running a unary-stream RPC
|
| 1512 |
+
# on a single Python thread results in an appreciable speed-up. However,
|
| 1513 |
+
# due to slight differences in capability, the multi-threaded variant
|
| 1514 |
+
# remains the default.
|
| 1515 |
+
if self._single_threaded_unary_stream:
|
| 1516 |
+
return _SingleThreadedUnaryStreamMultiCallable(
|
| 1517 |
+
self._channel, _common.encode(method), request_serializer,
|
| 1518 |
+
response_deserializer)
|
| 1519 |
+
else:
|
| 1520 |
+
return _UnaryStreamMultiCallable(
|
| 1521 |
+
self._channel,
|
| 1522 |
+
_channel_managed_call_management(self._call_state),
|
| 1523 |
+
_common.encode(method), request_serializer,
|
| 1524 |
+
response_deserializer)
|
| 1525 |
+
|
| 1526 |
+
def stream_unary(self,
|
| 1527 |
+
method,
|
| 1528 |
+
request_serializer=None,
|
| 1529 |
+
response_deserializer=None):
|
| 1530 |
+
return _StreamUnaryMultiCallable(
|
| 1531 |
+
self._channel, _channel_managed_call_management(self._call_state),
|
| 1532 |
+
_common.encode(method), request_serializer, response_deserializer)
|
| 1533 |
+
|
| 1534 |
+
def stream_stream(self,
|
| 1535 |
+
method,
|
| 1536 |
+
request_serializer=None,
|
| 1537 |
+
response_deserializer=None):
|
| 1538 |
+
return _StreamStreamMultiCallable(
|
| 1539 |
+
self._channel, _channel_managed_call_management(self._call_state),
|
| 1540 |
+
_common.encode(method), request_serializer, response_deserializer)
|
| 1541 |
+
|
| 1542 |
+
def _unsubscribe_all(self):
|
| 1543 |
+
state = self._connectivity_state
|
| 1544 |
+
if state:
|
| 1545 |
+
with state.lock:
|
| 1546 |
+
del state.callbacks_and_connectivities[:]
|
| 1547 |
+
|
| 1548 |
+
def _close(self):
|
| 1549 |
+
self._unsubscribe_all()
|
| 1550 |
+
self._channel.close(cygrpc.StatusCode.cancelled, 'Channel closed!')
|
| 1551 |
+
cygrpc.fork_unregister_channel(self)
|
| 1552 |
+
if cygrpc.g_gevent_activated:
|
| 1553 |
+
cygrpc.gevent_decrement_channel_count()
|
| 1554 |
+
|
| 1555 |
+
def _close_on_fork(self):
|
| 1556 |
+
self._unsubscribe_all()
|
| 1557 |
+
self._channel.close_on_fork(cygrpc.StatusCode.cancelled,
|
| 1558 |
+
'Channel closed due to fork')
|
| 1559 |
+
|
| 1560 |
+
def __enter__(self):
|
| 1561 |
+
return self
|
| 1562 |
+
|
| 1563 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 1564 |
+
self._close()
|
| 1565 |
+
return False
|
| 1566 |
+
|
| 1567 |
+
def close(self):
|
| 1568 |
+
self._close()
|
| 1569 |
+
|
| 1570 |
+
def __del__(self):
|
| 1571 |
+
# TODO(https://github.com/grpc/grpc/issues/12531): Several releases
|
| 1572 |
+
# after 1.12 (1.16 or thereabouts?) add a "self._channel.close" call
|
| 1573 |
+
# here (or more likely, call self._close() here). We don't do this today
|
| 1574 |
+
# because many valid use cases today allow the channel to be deleted
|
| 1575 |
+
# immediately after stubs are created. After a sufficient period of time
|
| 1576 |
+
# has passed for all users to be trusted to freeze out to their channels
|
| 1577 |
+
# for as long as they are in use and to close them after using them,
|
| 1578 |
+
# then deletion of this grpc._channel.Channel instance can be made to
|
| 1579 |
+
# effect closure of the underlying cygrpc.Channel instance.
|
| 1580 |
+
try:
|
| 1581 |
+
self._unsubscribe_all()
|
| 1582 |
+
except: # pylint: disable=bare-except
|
| 1583 |
+
# Exceptions in __del__ are ignored by Python anyway, but they can
|
| 1584 |
+
# keep spamming logs. Just silence them.
|
| 1585 |
+
pass
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_common.py
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2016 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Shared implementation."""
|
| 15 |
+
|
| 16 |
+
import logging
|
| 17 |
+
import time
|
| 18 |
+
|
| 19 |
+
import grpc
|
| 20 |
+
from grpc._cython import cygrpc
|
| 21 |
+
import six
|
| 22 |
+
|
| 23 |
+
_LOGGER = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
|
| 26 |
+
cygrpc.ConnectivityState.idle:
|
| 27 |
+
grpc.ChannelConnectivity.IDLE,
|
| 28 |
+
cygrpc.ConnectivityState.connecting:
|
| 29 |
+
grpc.ChannelConnectivity.CONNECTING,
|
| 30 |
+
cygrpc.ConnectivityState.ready:
|
| 31 |
+
grpc.ChannelConnectivity.READY,
|
| 32 |
+
cygrpc.ConnectivityState.transient_failure:
|
| 33 |
+
grpc.ChannelConnectivity.TRANSIENT_FAILURE,
|
| 34 |
+
cygrpc.ConnectivityState.shutdown:
|
| 35 |
+
grpc.ChannelConnectivity.SHUTDOWN,
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
CYGRPC_STATUS_CODE_TO_STATUS_CODE = {
|
| 39 |
+
cygrpc.StatusCode.ok: grpc.StatusCode.OK,
|
| 40 |
+
cygrpc.StatusCode.cancelled: grpc.StatusCode.CANCELLED,
|
| 41 |
+
cygrpc.StatusCode.unknown: grpc.StatusCode.UNKNOWN,
|
| 42 |
+
cygrpc.StatusCode.invalid_argument: grpc.StatusCode.INVALID_ARGUMENT,
|
| 43 |
+
cygrpc.StatusCode.deadline_exceeded: grpc.StatusCode.DEADLINE_EXCEEDED,
|
| 44 |
+
cygrpc.StatusCode.not_found: grpc.StatusCode.NOT_FOUND,
|
| 45 |
+
cygrpc.StatusCode.already_exists: grpc.StatusCode.ALREADY_EXISTS,
|
| 46 |
+
cygrpc.StatusCode.permission_denied: grpc.StatusCode.PERMISSION_DENIED,
|
| 47 |
+
cygrpc.StatusCode.unauthenticated: grpc.StatusCode.UNAUTHENTICATED,
|
| 48 |
+
cygrpc.StatusCode.resource_exhausted: grpc.StatusCode.RESOURCE_EXHAUSTED,
|
| 49 |
+
cygrpc.StatusCode.failed_precondition: grpc.StatusCode.FAILED_PRECONDITION,
|
| 50 |
+
cygrpc.StatusCode.aborted: grpc.StatusCode.ABORTED,
|
| 51 |
+
cygrpc.StatusCode.out_of_range: grpc.StatusCode.OUT_OF_RANGE,
|
| 52 |
+
cygrpc.StatusCode.unimplemented: grpc.StatusCode.UNIMPLEMENTED,
|
| 53 |
+
cygrpc.StatusCode.internal: grpc.StatusCode.INTERNAL,
|
| 54 |
+
cygrpc.StatusCode.unavailable: grpc.StatusCode.UNAVAILABLE,
|
| 55 |
+
cygrpc.StatusCode.data_loss: grpc.StatusCode.DATA_LOSS,
|
| 56 |
+
}
|
| 57 |
+
STATUS_CODE_TO_CYGRPC_STATUS_CODE = {
|
| 58 |
+
grpc_code: cygrpc_code for cygrpc_code, grpc_code in six.iteritems(
|
| 59 |
+
CYGRPC_STATUS_CODE_TO_STATUS_CODE)
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
MAXIMUM_WAIT_TIMEOUT = 0.1
|
| 63 |
+
|
| 64 |
+
_ERROR_MESSAGE_PORT_BINDING_FAILED = 'Failed to bind to address %s; set ' \
|
| 65 |
+
'GRPC_VERBOSITY=debug environment variable to see detailed error message.'
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def encode(s):
|
| 69 |
+
if isinstance(s, bytes):
|
| 70 |
+
return s
|
| 71 |
+
else:
|
| 72 |
+
return s.encode('utf8')
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def decode(b):
|
| 76 |
+
if isinstance(b, bytes):
|
| 77 |
+
return b.decode('utf-8', 'replace')
|
| 78 |
+
return b
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def _transform(message, transformer, exception_message):
|
| 82 |
+
if transformer is None:
|
| 83 |
+
return message
|
| 84 |
+
else:
|
| 85 |
+
try:
|
| 86 |
+
return transformer(message)
|
| 87 |
+
except Exception: # pylint: disable=broad-except
|
| 88 |
+
_LOGGER.exception(exception_message)
|
| 89 |
+
return None
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def serialize(message, serializer):
|
| 93 |
+
return _transform(message, serializer, 'Exception serializing message!')
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def deserialize(serialized_message, deserializer):
|
| 97 |
+
return _transform(serialized_message, deserializer,
|
| 98 |
+
'Exception deserializing message!')
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def fully_qualified_method(group, method):
|
| 102 |
+
return '/{}/{}'.format(group, method)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def _wait_once(wait_fn, timeout, spin_cb):
|
| 106 |
+
wait_fn(timeout=timeout)
|
| 107 |
+
if spin_cb is not None:
|
| 108 |
+
spin_cb()
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def wait(wait_fn, wait_complete_fn, timeout=None, spin_cb=None):
|
| 112 |
+
"""Blocks waiting for an event without blocking the thread indefinitely.
|
| 113 |
+
|
| 114 |
+
See https://github.com/grpc/grpc/issues/19464 for full context. CPython's
|
| 115 |
+
`threading.Event.wait` and `threading.Condition.wait` methods, if invoked
|
| 116 |
+
without a timeout kwarg, may block the calling thread indefinitely. If the
|
| 117 |
+
call is made from the main thread, this means that signal handlers may not
|
| 118 |
+
run for an arbitrarily long period of time.
|
| 119 |
+
|
| 120 |
+
This wrapper calls the supplied wait function with an arbitrary short
|
| 121 |
+
timeout to ensure that no signal handler has to wait longer than
|
| 122 |
+
MAXIMUM_WAIT_TIMEOUT before executing.
|
| 123 |
+
|
| 124 |
+
Args:
|
| 125 |
+
wait_fn: A callable acceptable a single float-valued kwarg named
|
| 126 |
+
`timeout`. This function is expected to be one of `threading.Event.wait`
|
| 127 |
+
or `threading.Condition.wait`.
|
| 128 |
+
wait_complete_fn: A callable taking no arguments and returning a bool.
|
| 129 |
+
When this function returns true, it indicates that waiting should cease.
|
| 130 |
+
timeout: An optional float-valued number of seconds after which the wait
|
| 131 |
+
should cease.
|
| 132 |
+
spin_cb: An optional Callable taking no arguments and returning nothing.
|
| 133 |
+
This callback will be called on each iteration of the spin. This may be
|
| 134 |
+
used for, e.g. work related to forking.
|
| 135 |
+
|
| 136 |
+
Returns:
|
| 137 |
+
True if a timeout was supplied and it was reached. False otherwise.
|
| 138 |
+
"""
|
| 139 |
+
if timeout is None:
|
| 140 |
+
while not wait_complete_fn():
|
| 141 |
+
_wait_once(wait_fn, MAXIMUM_WAIT_TIMEOUT, spin_cb)
|
| 142 |
+
else:
|
| 143 |
+
end = time.time() + timeout
|
| 144 |
+
while not wait_complete_fn():
|
| 145 |
+
remaining = min(end - time.time(), MAXIMUM_WAIT_TIMEOUT)
|
| 146 |
+
if remaining < 0:
|
| 147 |
+
return True
|
| 148 |
+
_wait_once(wait_fn, remaining, spin_cb)
|
| 149 |
+
return False
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def validate_port_binding_result(address, port):
|
| 153 |
+
"""Validates if the port binding succeed.
|
| 154 |
+
|
| 155 |
+
If the port returned by Core is 0, the binding is failed. However, in that
|
| 156 |
+
case, the Core API doesn't return a detailed failing reason. The best we
|
| 157 |
+
can do is raising an exception to prevent further confusion.
|
| 158 |
+
|
| 159 |
+
Args:
|
| 160 |
+
address: The address string to be bound.
|
| 161 |
+
port: An int returned by core
|
| 162 |
+
"""
|
| 163 |
+
if port == 0:
|
| 164 |
+
# The Core API doesn't return a failure message. The best we can do
|
| 165 |
+
# is raising an exception to prevent further confusion.
|
| 166 |
+
raise RuntimeError(_ERROR_MESSAGE_PORT_BINDING_FAILED % address)
|
| 167 |
+
else:
|
| 168 |
+
return port
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_compression.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2019 The gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
from grpc._cython import cygrpc
|
| 16 |
+
|
| 17 |
+
NoCompression = cygrpc.CompressionAlgorithm.none
|
| 18 |
+
Deflate = cygrpc.CompressionAlgorithm.deflate
|
| 19 |
+
Gzip = cygrpc.CompressionAlgorithm.gzip
|
| 20 |
+
|
| 21 |
+
_METADATA_STRING_MAPPING = {
|
| 22 |
+
NoCompression: 'identity',
|
| 23 |
+
Deflate: 'deflate',
|
| 24 |
+
Gzip: 'gzip',
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def _compression_algorithm_to_metadata_value(compression):
|
| 29 |
+
return _METADATA_STRING_MAPPING[compression]
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def compression_algorithm_to_metadata(compression):
|
| 33 |
+
return (cygrpc.GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY,
|
| 34 |
+
_compression_algorithm_to_metadata_value(compression))
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def create_channel_option(compression):
|
| 38 |
+
return ((cygrpc.GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM,
|
| 39 |
+
int(compression)),) if compression else ()
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def augment_metadata(metadata, compression):
|
| 43 |
+
if not metadata and not compression:
|
| 44 |
+
return None
|
| 45 |
+
base_metadata = tuple(metadata) if metadata else ()
|
| 46 |
+
compression_metadata = (
|
| 47 |
+
compression_algorithm_to_metadata(compression),) if compression else ()
|
| 48 |
+
return base_metadata + compression_metadata
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
__all__ = (
|
| 52 |
+
"NoCompression",
|
| 53 |
+
"Deflate",
|
| 54 |
+
"Gzip",
|
| 55 |
+
)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_grpcio_metadata.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
__version__ = """1.47.0"""
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_interceptor.py
ADDED
|
@@ -0,0 +1,562 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2017 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Implementation of gRPC Python interceptors."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
import sys
|
| 18 |
+
|
| 19 |
+
import grpc
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class _ServicePipeline(object):
|
| 23 |
+
|
| 24 |
+
def __init__(self, interceptors):
|
| 25 |
+
self.interceptors = tuple(interceptors)
|
| 26 |
+
|
| 27 |
+
def _continuation(self, thunk, index):
|
| 28 |
+
return lambda context: self._intercept_at(thunk, index, context)
|
| 29 |
+
|
| 30 |
+
def _intercept_at(self, thunk, index, context):
|
| 31 |
+
if index < len(self.interceptors):
|
| 32 |
+
interceptor = self.interceptors[index]
|
| 33 |
+
thunk = self._continuation(thunk, index + 1)
|
| 34 |
+
return interceptor.intercept_service(thunk, context)
|
| 35 |
+
else:
|
| 36 |
+
return thunk(context)
|
| 37 |
+
|
| 38 |
+
def execute(self, thunk, context):
|
| 39 |
+
return self._intercept_at(thunk, 0, context)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def service_pipeline(interceptors):
|
| 43 |
+
return _ServicePipeline(interceptors) if interceptors else None
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class _ClientCallDetails(
|
| 47 |
+
collections.namedtuple('_ClientCallDetails',
|
| 48 |
+
('method', 'timeout', 'metadata', 'credentials',
|
| 49 |
+
'wait_for_ready', 'compression')),
|
| 50 |
+
grpc.ClientCallDetails):
|
| 51 |
+
pass
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _unwrap_client_call_details(call_details, default_details):
|
| 55 |
+
try:
|
| 56 |
+
method = call_details.method
|
| 57 |
+
except AttributeError:
|
| 58 |
+
method = default_details.method
|
| 59 |
+
|
| 60 |
+
try:
|
| 61 |
+
timeout = call_details.timeout
|
| 62 |
+
except AttributeError:
|
| 63 |
+
timeout = default_details.timeout
|
| 64 |
+
|
| 65 |
+
try:
|
| 66 |
+
metadata = call_details.metadata
|
| 67 |
+
except AttributeError:
|
| 68 |
+
metadata = default_details.metadata
|
| 69 |
+
|
| 70 |
+
try:
|
| 71 |
+
credentials = call_details.credentials
|
| 72 |
+
except AttributeError:
|
| 73 |
+
credentials = default_details.credentials
|
| 74 |
+
|
| 75 |
+
try:
|
| 76 |
+
wait_for_ready = call_details.wait_for_ready
|
| 77 |
+
except AttributeError:
|
| 78 |
+
wait_for_ready = default_details.wait_for_ready
|
| 79 |
+
|
| 80 |
+
try:
|
| 81 |
+
compression = call_details.compression
|
| 82 |
+
except AttributeError:
|
| 83 |
+
compression = default_details.compression
|
| 84 |
+
|
| 85 |
+
return method, timeout, metadata, credentials, wait_for_ready, compression
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
class _FailureOutcome(grpc.RpcError, grpc.Future, grpc.Call): # pylint: disable=too-many-ancestors
|
| 89 |
+
|
| 90 |
+
def __init__(self, exception, traceback):
|
| 91 |
+
super(_FailureOutcome, self).__init__()
|
| 92 |
+
self._exception = exception
|
| 93 |
+
self._traceback = traceback
|
| 94 |
+
|
| 95 |
+
def initial_metadata(self):
|
| 96 |
+
return None
|
| 97 |
+
|
| 98 |
+
def trailing_metadata(self):
|
| 99 |
+
return None
|
| 100 |
+
|
| 101 |
+
def code(self):
|
| 102 |
+
return grpc.StatusCode.INTERNAL
|
| 103 |
+
|
| 104 |
+
def details(self):
|
| 105 |
+
return 'Exception raised while intercepting the RPC'
|
| 106 |
+
|
| 107 |
+
def cancel(self):
|
| 108 |
+
return False
|
| 109 |
+
|
| 110 |
+
def cancelled(self):
|
| 111 |
+
return False
|
| 112 |
+
|
| 113 |
+
def is_active(self):
|
| 114 |
+
return False
|
| 115 |
+
|
| 116 |
+
def time_remaining(self):
|
| 117 |
+
return None
|
| 118 |
+
|
| 119 |
+
def running(self):
|
| 120 |
+
return False
|
| 121 |
+
|
| 122 |
+
def done(self):
|
| 123 |
+
return True
|
| 124 |
+
|
| 125 |
+
def result(self, ignored_timeout=None):
|
| 126 |
+
raise self._exception
|
| 127 |
+
|
| 128 |
+
def exception(self, ignored_timeout=None):
|
| 129 |
+
return self._exception
|
| 130 |
+
|
| 131 |
+
def traceback(self, ignored_timeout=None):
|
| 132 |
+
return self._traceback
|
| 133 |
+
|
| 134 |
+
def add_callback(self, unused_callback):
|
| 135 |
+
return False
|
| 136 |
+
|
| 137 |
+
def add_done_callback(self, fn):
|
| 138 |
+
fn(self)
|
| 139 |
+
|
| 140 |
+
def __iter__(self):
|
| 141 |
+
return self
|
| 142 |
+
|
| 143 |
+
def __next__(self):
|
| 144 |
+
raise self._exception
|
| 145 |
+
|
| 146 |
+
def next(self):
|
| 147 |
+
return self.__next__()
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class _UnaryOutcome(grpc.Call, grpc.Future):
|
| 151 |
+
|
| 152 |
+
def __init__(self, response, call):
|
| 153 |
+
self._response = response
|
| 154 |
+
self._call = call
|
| 155 |
+
|
| 156 |
+
def initial_metadata(self):
|
| 157 |
+
return self._call.initial_metadata()
|
| 158 |
+
|
| 159 |
+
def trailing_metadata(self):
|
| 160 |
+
return self._call.trailing_metadata()
|
| 161 |
+
|
| 162 |
+
def code(self):
|
| 163 |
+
return self._call.code()
|
| 164 |
+
|
| 165 |
+
def details(self):
|
| 166 |
+
return self._call.details()
|
| 167 |
+
|
| 168 |
+
def is_active(self):
|
| 169 |
+
return self._call.is_active()
|
| 170 |
+
|
| 171 |
+
def time_remaining(self):
|
| 172 |
+
return self._call.time_remaining()
|
| 173 |
+
|
| 174 |
+
def cancel(self):
|
| 175 |
+
return self._call.cancel()
|
| 176 |
+
|
| 177 |
+
def add_callback(self, callback):
|
| 178 |
+
return self._call.add_callback(callback)
|
| 179 |
+
|
| 180 |
+
def cancelled(self):
|
| 181 |
+
return False
|
| 182 |
+
|
| 183 |
+
def running(self):
|
| 184 |
+
return False
|
| 185 |
+
|
| 186 |
+
def done(self):
|
| 187 |
+
return True
|
| 188 |
+
|
| 189 |
+
def result(self, ignored_timeout=None):
|
| 190 |
+
return self._response
|
| 191 |
+
|
| 192 |
+
def exception(self, ignored_timeout=None):
|
| 193 |
+
return None
|
| 194 |
+
|
| 195 |
+
def traceback(self, ignored_timeout=None):
|
| 196 |
+
return None
|
| 197 |
+
|
| 198 |
+
def add_done_callback(self, fn):
|
| 199 |
+
fn(self)
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
|
| 203 |
+
|
| 204 |
+
def __init__(self, thunk, method, interceptor):
|
| 205 |
+
self._thunk = thunk
|
| 206 |
+
self._method = method
|
| 207 |
+
self._interceptor = interceptor
|
| 208 |
+
|
| 209 |
+
def __call__(self,
|
| 210 |
+
request,
|
| 211 |
+
timeout=None,
|
| 212 |
+
metadata=None,
|
| 213 |
+
credentials=None,
|
| 214 |
+
wait_for_ready=None,
|
| 215 |
+
compression=None):
|
| 216 |
+
response, ignored_call = self._with_call(request,
|
| 217 |
+
timeout=timeout,
|
| 218 |
+
metadata=metadata,
|
| 219 |
+
credentials=credentials,
|
| 220 |
+
wait_for_ready=wait_for_ready,
|
| 221 |
+
compression=compression)
|
| 222 |
+
return response
|
| 223 |
+
|
| 224 |
+
def _with_call(self,
|
| 225 |
+
request,
|
| 226 |
+
timeout=None,
|
| 227 |
+
metadata=None,
|
| 228 |
+
credentials=None,
|
| 229 |
+
wait_for_ready=None,
|
| 230 |
+
compression=None):
|
| 231 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 232 |
+
metadata, credentials,
|
| 233 |
+
wait_for_ready, compression)
|
| 234 |
+
|
| 235 |
+
def continuation(new_details, request):
|
| 236 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 237 |
+
new_wait_for_ready,
|
| 238 |
+
new_compression) = (_unwrap_client_call_details(
|
| 239 |
+
new_details, client_call_details))
|
| 240 |
+
try:
|
| 241 |
+
response, call = self._thunk(new_method).with_call(
|
| 242 |
+
request,
|
| 243 |
+
timeout=new_timeout,
|
| 244 |
+
metadata=new_metadata,
|
| 245 |
+
credentials=new_credentials,
|
| 246 |
+
wait_for_ready=new_wait_for_ready,
|
| 247 |
+
compression=new_compression)
|
| 248 |
+
return _UnaryOutcome(response, call)
|
| 249 |
+
except grpc.RpcError as rpc_error:
|
| 250 |
+
return rpc_error
|
| 251 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 252 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 253 |
+
|
| 254 |
+
call = self._interceptor.intercept_unary_unary(continuation,
|
| 255 |
+
client_call_details,
|
| 256 |
+
request)
|
| 257 |
+
return call.result(), call
|
| 258 |
+
|
| 259 |
+
def with_call(self,
|
| 260 |
+
request,
|
| 261 |
+
timeout=None,
|
| 262 |
+
metadata=None,
|
| 263 |
+
credentials=None,
|
| 264 |
+
wait_for_ready=None,
|
| 265 |
+
compression=None):
|
| 266 |
+
return self._with_call(request,
|
| 267 |
+
timeout=timeout,
|
| 268 |
+
metadata=metadata,
|
| 269 |
+
credentials=credentials,
|
| 270 |
+
wait_for_ready=wait_for_ready,
|
| 271 |
+
compression=compression)
|
| 272 |
+
|
| 273 |
+
def future(self,
|
| 274 |
+
request,
|
| 275 |
+
timeout=None,
|
| 276 |
+
metadata=None,
|
| 277 |
+
credentials=None,
|
| 278 |
+
wait_for_ready=None,
|
| 279 |
+
compression=None):
|
| 280 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 281 |
+
metadata, credentials,
|
| 282 |
+
wait_for_ready, compression)
|
| 283 |
+
|
| 284 |
+
def continuation(new_details, request):
|
| 285 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 286 |
+
new_wait_for_ready,
|
| 287 |
+
new_compression) = (_unwrap_client_call_details(
|
| 288 |
+
new_details, client_call_details))
|
| 289 |
+
return self._thunk(new_method).future(
|
| 290 |
+
request,
|
| 291 |
+
timeout=new_timeout,
|
| 292 |
+
metadata=new_metadata,
|
| 293 |
+
credentials=new_credentials,
|
| 294 |
+
wait_for_ready=new_wait_for_ready,
|
| 295 |
+
compression=new_compression)
|
| 296 |
+
|
| 297 |
+
try:
|
| 298 |
+
return self._interceptor.intercept_unary_unary(
|
| 299 |
+
continuation, client_call_details, request)
|
| 300 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 301 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
class _UnaryStreamMultiCallable(grpc.UnaryStreamMultiCallable):
|
| 305 |
+
|
| 306 |
+
def __init__(self, thunk, method, interceptor):
|
| 307 |
+
self._thunk = thunk
|
| 308 |
+
self._method = method
|
| 309 |
+
self._interceptor = interceptor
|
| 310 |
+
|
| 311 |
+
def __call__(self,
|
| 312 |
+
request,
|
| 313 |
+
timeout=None,
|
| 314 |
+
metadata=None,
|
| 315 |
+
credentials=None,
|
| 316 |
+
wait_for_ready=None,
|
| 317 |
+
compression=None):
|
| 318 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 319 |
+
metadata, credentials,
|
| 320 |
+
wait_for_ready, compression)
|
| 321 |
+
|
| 322 |
+
def continuation(new_details, request):
|
| 323 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 324 |
+
new_wait_for_ready,
|
| 325 |
+
new_compression) = (_unwrap_client_call_details(
|
| 326 |
+
new_details, client_call_details))
|
| 327 |
+
return self._thunk(new_method)(request,
|
| 328 |
+
timeout=new_timeout,
|
| 329 |
+
metadata=new_metadata,
|
| 330 |
+
credentials=new_credentials,
|
| 331 |
+
wait_for_ready=new_wait_for_ready,
|
| 332 |
+
compression=new_compression)
|
| 333 |
+
|
| 334 |
+
try:
|
| 335 |
+
return self._interceptor.intercept_unary_stream(
|
| 336 |
+
continuation, client_call_details, request)
|
| 337 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 338 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
class _StreamUnaryMultiCallable(grpc.StreamUnaryMultiCallable):
|
| 342 |
+
|
| 343 |
+
def __init__(self, thunk, method, interceptor):
|
| 344 |
+
self._thunk = thunk
|
| 345 |
+
self._method = method
|
| 346 |
+
self._interceptor = interceptor
|
| 347 |
+
|
| 348 |
+
def __call__(self,
|
| 349 |
+
request_iterator,
|
| 350 |
+
timeout=None,
|
| 351 |
+
metadata=None,
|
| 352 |
+
credentials=None,
|
| 353 |
+
wait_for_ready=None,
|
| 354 |
+
compression=None):
|
| 355 |
+
response, ignored_call = self._with_call(request_iterator,
|
| 356 |
+
timeout=timeout,
|
| 357 |
+
metadata=metadata,
|
| 358 |
+
credentials=credentials,
|
| 359 |
+
wait_for_ready=wait_for_ready,
|
| 360 |
+
compression=compression)
|
| 361 |
+
return response
|
| 362 |
+
|
| 363 |
+
def _with_call(self,
|
| 364 |
+
request_iterator,
|
| 365 |
+
timeout=None,
|
| 366 |
+
metadata=None,
|
| 367 |
+
credentials=None,
|
| 368 |
+
wait_for_ready=None,
|
| 369 |
+
compression=None):
|
| 370 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 371 |
+
metadata, credentials,
|
| 372 |
+
wait_for_ready, compression)
|
| 373 |
+
|
| 374 |
+
def continuation(new_details, request_iterator):
|
| 375 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 376 |
+
new_wait_for_ready,
|
| 377 |
+
new_compression) = (_unwrap_client_call_details(
|
| 378 |
+
new_details, client_call_details))
|
| 379 |
+
try:
|
| 380 |
+
response, call = self._thunk(new_method).with_call(
|
| 381 |
+
request_iterator,
|
| 382 |
+
timeout=new_timeout,
|
| 383 |
+
metadata=new_metadata,
|
| 384 |
+
credentials=new_credentials,
|
| 385 |
+
wait_for_ready=new_wait_for_ready,
|
| 386 |
+
compression=new_compression)
|
| 387 |
+
return _UnaryOutcome(response, call)
|
| 388 |
+
except grpc.RpcError as rpc_error:
|
| 389 |
+
return rpc_error
|
| 390 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 391 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 392 |
+
|
| 393 |
+
call = self._interceptor.intercept_stream_unary(continuation,
|
| 394 |
+
client_call_details,
|
| 395 |
+
request_iterator)
|
| 396 |
+
return call.result(), call
|
| 397 |
+
|
| 398 |
+
def with_call(self,
|
| 399 |
+
request_iterator,
|
| 400 |
+
timeout=None,
|
| 401 |
+
metadata=None,
|
| 402 |
+
credentials=None,
|
| 403 |
+
wait_for_ready=None,
|
| 404 |
+
compression=None):
|
| 405 |
+
return self._with_call(request_iterator,
|
| 406 |
+
timeout=timeout,
|
| 407 |
+
metadata=metadata,
|
| 408 |
+
credentials=credentials,
|
| 409 |
+
wait_for_ready=wait_for_ready,
|
| 410 |
+
compression=compression)
|
| 411 |
+
|
| 412 |
+
def future(self,
|
| 413 |
+
request_iterator,
|
| 414 |
+
timeout=None,
|
| 415 |
+
metadata=None,
|
| 416 |
+
credentials=None,
|
| 417 |
+
wait_for_ready=None,
|
| 418 |
+
compression=None):
|
| 419 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 420 |
+
metadata, credentials,
|
| 421 |
+
wait_for_ready, compression)
|
| 422 |
+
|
| 423 |
+
def continuation(new_details, request_iterator):
|
| 424 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 425 |
+
new_wait_for_ready,
|
| 426 |
+
new_compression) = (_unwrap_client_call_details(
|
| 427 |
+
new_details, client_call_details))
|
| 428 |
+
return self._thunk(new_method).future(
|
| 429 |
+
request_iterator,
|
| 430 |
+
timeout=new_timeout,
|
| 431 |
+
metadata=new_metadata,
|
| 432 |
+
credentials=new_credentials,
|
| 433 |
+
wait_for_ready=new_wait_for_ready,
|
| 434 |
+
compression=new_compression)
|
| 435 |
+
|
| 436 |
+
try:
|
| 437 |
+
return self._interceptor.intercept_stream_unary(
|
| 438 |
+
continuation, client_call_details, request_iterator)
|
| 439 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 440 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 441 |
+
|
| 442 |
+
|
| 443 |
+
class _StreamStreamMultiCallable(grpc.StreamStreamMultiCallable):
|
| 444 |
+
|
| 445 |
+
def __init__(self, thunk, method, interceptor):
|
| 446 |
+
self._thunk = thunk
|
| 447 |
+
self._method = method
|
| 448 |
+
self._interceptor = interceptor
|
| 449 |
+
|
| 450 |
+
def __call__(self,
|
| 451 |
+
request_iterator,
|
| 452 |
+
timeout=None,
|
| 453 |
+
metadata=None,
|
| 454 |
+
credentials=None,
|
| 455 |
+
wait_for_ready=None,
|
| 456 |
+
compression=None):
|
| 457 |
+
client_call_details = _ClientCallDetails(self._method, timeout,
|
| 458 |
+
metadata, credentials,
|
| 459 |
+
wait_for_ready, compression)
|
| 460 |
+
|
| 461 |
+
def continuation(new_details, request_iterator):
|
| 462 |
+
(new_method, new_timeout, new_metadata, new_credentials,
|
| 463 |
+
new_wait_for_ready,
|
| 464 |
+
new_compression) = (_unwrap_client_call_details(
|
| 465 |
+
new_details, client_call_details))
|
| 466 |
+
return self._thunk(new_method)(request_iterator,
|
| 467 |
+
timeout=new_timeout,
|
| 468 |
+
metadata=new_metadata,
|
| 469 |
+
credentials=new_credentials,
|
| 470 |
+
wait_for_ready=new_wait_for_ready,
|
| 471 |
+
compression=new_compression)
|
| 472 |
+
|
| 473 |
+
try:
|
| 474 |
+
return self._interceptor.intercept_stream_stream(
|
| 475 |
+
continuation, client_call_details, request_iterator)
|
| 476 |
+
except Exception as exception: # pylint:disable=broad-except
|
| 477 |
+
return _FailureOutcome(exception, sys.exc_info()[2])
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
class _Channel(grpc.Channel):
|
| 481 |
+
|
| 482 |
+
def __init__(self, channel, interceptor):
|
| 483 |
+
self._channel = channel
|
| 484 |
+
self._interceptor = interceptor
|
| 485 |
+
|
| 486 |
+
def subscribe(self, callback, try_to_connect=False):
|
| 487 |
+
self._channel.subscribe(callback, try_to_connect=try_to_connect)
|
| 488 |
+
|
| 489 |
+
def unsubscribe(self, callback):
|
| 490 |
+
self._channel.unsubscribe(callback)
|
| 491 |
+
|
| 492 |
+
def unary_unary(self,
|
| 493 |
+
method,
|
| 494 |
+
request_serializer=None,
|
| 495 |
+
response_deserializer=None):
|
| 496 |
+
thunk = lambda m: self._channel.unary_unary(m, request_serializer,
|
| 497 |
+
response_deserializer)
|
| 498 |
+
if isinstance(self._interceptor, grpc.UnaryUnaryClientInterceptor):
|
| 499 |
+
return _UnaryUnaryMultiCallable(thunk, method, self._interceptor)
|
| 500 |
+
else:
|
| 501 |
+
return thunk(method)
|
| 502 |
+
|
| 503 |
+
def unary_stream(self,
|
| 504 |
+
method,
|
| 505 |
+
request_serializer=None,
|
| 506 |
+
response_deserializer=None):
|
| 507 |
+
thunk = lambda m: self._channel.unary_stream(m, request_serializer,
|
| 508 |
+
response_deserializer)
|
| 509 |
+
if isinstance(self._interceptor, grpc.UnaryStreamClientInterceptor):
|
| 510 |
+
return _UnaryStreamMultiCallable(thunk, method, self._interceptor)
|
| 511 |
+
else:
|
| 512 |
+
return thunk(method)
|
| 513 |
+
|
| 514 |
+
def stream_unary(self,
|
| 515 |
+
method,
|
| 516 |
+
request_serializer=None,
|
| 517 |
+
response_deserializer=None):
|
| 518 |
+
thunk = lambda m: self._channel.stream_unary(m, request_serializer,
|
| 519 |
+
response_deserializer)
|
| 520 |
+
if isinstance(self._interceptor, grpc.StreamUnaryClientInterceptor):
|
| 521 |
+
return _StreamUnaryMultiCallable(thunk, method, self._interceptor)
|
| 522 |
+
else:
|
| 523 |
+
return thunk(method)
|
| 524 |
+
|
| 525 |
+
def stream_stream(self,
|
| 526 |
+
method,
|
| 527 |
+
request_serializer=None,
|
| 528 |
+
response_deserializer=None):
|
| 529 |
+
thunk = lambda m: self._channel.stream_stream(m, request_serializer,
|
| 530 |
+
response_deserializer)
|
| 531 |
+
if isinstance(self._interceptor, grpc.StreamStreamClientInterceptor):
|
| 532 |
+
return _StreamStreamMultiCallable(thunk, method, self._interceptor)
|
| 533 |
+
else:
|
| 534 |
+
return thunk(method)
|
| 535 |
+
|
| 536 |
+
def _close(self):
|
| 537 |
+
self._channel.close()
|
| 538 |
+
|
| 539 |
+
def __enter__(self):
|
| 540 |
+
return self
|
| 541 |
+
|
| 542 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 543 |
+
self._close()
|
| 544 |
+
return False
|
| 545 |
+
|
| 546 |
+
def close(self):
|
| 547 |
+
self._channel.close()
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
def intercept_channel(channel, *interceptors):
|
| 551 |
+
for interceptor in reversed(list(interceptors)):
|
| 552 |
+
if not isinstance(interceptor, grpc.UnaryUnaryClientInterceptor) and \
|
| 553 |
+
not isinstance(interceptor, grpc.UnaryStreamClientInterceptor) and \
|
| 554 |
+
not isinstance(interceptor, grpc.StreamUnaryClientInterceptor) and \
|
| 555 |
+
not isinstance(interceptor, grpc.StreamStreamClientInterceptor):
|
| 556 |
+
raise TypeError('interceptor must be '
|
| 557 |
+
'grpc.UnaryUnaryClientInterceptor or '
|
| 558 |
+
'grpc.UnaryStreamClientInterceptor or '
|
| 559 |
+
'grpc.StreamUnaryClientInterceptor or '
|
| 560 |
+
'grpc.StreamStreamClientInterceptor or ')
|
| 561 |
+
channel = _Channel(channel, interceptor)
|
| 562 |
+
return channel
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_plugin_wrapping.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2015 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import collections
|
| 16 |
+
import logging
|
| 17 |
+
import threading
|
| 18 |
+
|
| 19 |
+
import grpc
|
| 20 |
+
from grpc import _common
|
| 21 |
+
from grpc._cython import cygrpc
|
| 22 |
+
|
| 23 |
+
_LOGGER = logging.getLogger(__name__)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class _AuthMetadataContext(
|
| 27 |
+
collections.namedtuple('AuthMetadataContext', (
|
| 28 |
+
'service_url',
|
| 29 |
+
'method_name',
|
| 30 |
+
)), grpc.AuthMetadataContext):
|
| 31 |
+
pass
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class _CallbackState(object):
|
| 35 |
+
|
| 36 |
+
def __init__(self):
|
| 37 |
+
self.lock = threading.Lock()
|
| 38 |
+
self.called = False
|
| 39 |
+
self.exception = None
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class _AuthMetadataPluginCallback(grpc.AuthMetadataPluginCallback):
|
| 43 |
+
|
| 44 |
+
def __init__(self, state, callback):
|
| 45 |
+
self._state = state
|
| 46 |
+
self._callback = callback
|
| 47 |
+
|
| 48 |
+
def __call__(self, metadata, error):
|
| 49 |
+
with self._state.lock:
|
| 50 |
+
if self._state.exception is None:
|
| 51 |
+
if self._state.called:
|
| 52 |
+
raise RuntimeError(
|
| 53 |
+
'AuthMetadataPluginCallback invoked more than once!')
|
| 54 |
+
else:
|
| 55 |
+
self._state.called = True
|
| 56 |
+
else:
|
| 57 |
+
raise RuntimeError(
|
| 58 |
+
'AuthMetadataPluginCallback raised exception "{}"!'.format(
|
| 59 |
+
self._state.exception))
|
| 60 |
+
if error is None:
|
| 61 |
+
self._callback(metadata, cygrpc.StatusCode.ok, None)
|
| 62 |
+
else:
|
| 63 |
+
self._callback(None, cygrpc.StatusCode.internal,
|
| 64 |
+
_common.encode(str(error)))
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class _Plugin(object):
|
| 68 |
+
|
| 69 |
+
def __init__(self, metadata_plugin):
|
| 70 |
+
self._metadata_plugin = metadata_plugin
|
| 71 |
+
self._stored_ctx = None
|
| 72 |
+
|
| 73 |
+
try:
|
| 74 |
+
import contextvars # pylint: disable=wrong-import-position
|
| 75 |
+
|
| 76 |
+
# The plugin may be invoked on a thread created by Core, which will not
|
| 77 |
+
# have the context propagated. This context is stored and installed in
|
| 78 |
+
# the thread invoking the plugin.
|
| 79 |
+
self._stored_ctx = contextvars.copy_context()
|
| 80 |
+
except ImportError:
|
| 81 |
+
# Support versions predating contextvars.
|
| 82 |
+
pass
|
| 83 |
+
|
| 84 |
+
def __call__(self, service_url, method_name, callback):
|
| 85 |
+
context = _AuthMetadataContext(_common.decode(service_url),
|
| 86 |
+
_common.decode(method_name))
|
| 87 |
+
callback_state = _CallbackState()
|
| 88 |
+
try:
|
| 89 |
+
self._metadata_plugin(
|
| 90 |
+
context, _AuthMetadataPluginCallback(callback_state, callback))
|
| 91 |
+
except Exception as exception: # pylint: disable=broad-except
|
| 92 |
+
_LOGGER.exception(
|
| 93 |
+
'AuthMetadataPluginCallback "%s" raised exception!',
|
| 94 |
+
self._metadata_plugin)
|
| 95 |
+
with callback_state.lock:
|
| 96 |
+
callback_state.exception = exception
|
| 97 |
+
if callback_state.called:
|
| 98 |
+
return
|
| 99 |
+
callback(None, cygrpc.StatusCode.internal,
|
| 100 |
+
_common.encode(str(exception)))
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def metadata_plugin_call_credentials(metadata_plugin, name):
|
| 104 |
+
if name is None:
|
| 105 |
+
try:
|
| 106 |
+
effective_name = metadata_plugin.__name__
|
| 107 |
+
except AttributeError:
|
| 108 |
+
effective_name = metadata_plugin.__class__.__name__
|
| 109 |
+
else:
|
| 110 |
+
effective_name = name
|
| 111 |
+
return grpc.CallCredentials(
|
| 112 |
+
cygrpc.MetadataPluginCallCredentials(_Plugin(metadata_plugin),
|
| 113 |
+
_common.encode(effective_name)))
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_runtime_protos.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import sys
|
| 16 |
+
|
| 17 |
+
_REQUIRED_SYMBOLS = ("_protos", "_services", "_protos_and_services")
|
| 18 |
+
_MINIMUM_VERSION = (3, 5, 0)
|
| 19 |
+
|
| 20 |
+
_UNINSTALLED_TEMPLATE = "Install the grpcio-tools package (1.32.0+) to use the {} function."
|
| 21 |
+
_VERSION_ERROR_TEMPLATE = "The {} function is only on available on Python 3.X interpreters."
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def _has_runtime_proto_symbols(mod):
|
| 25 |
+
return all(hasattr(mod, sym) for sym in _REQUIRED_SYMBOLS)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def _is_grpc_tools_importable():
|
| 29 |
+
try:
|
| 30 |
+
import grpc_tools # pylint: disable=unused-import
|
| 31 |
+
return True
|
| 32 |
+
except ImportError as e:
|
| 33 |
+
# NOTE: It's possible that we're encountering a transitive ImportError, so
|
| 34 |
+
# we check for that and re-raise if so.
|
| 35 |
+
if "grpc_tools" not in e.args[0]:
|
| 36 |
+
raise
|
| 37 |
+
return False
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def _call_with_lazy_import(fn_name, protobuf_path):
|
| 41 |
+
"""Calls one of the three functions, lazily importing grpc_tools.
|
| 42 |
+
|
| 43 |
+
Args:
|
| 44 |
+
fn_name: The name of the function to import from grpc_tools.protoc.
|
| 45 |
+
protobuf_path: The path to import.
|
| 46 |
+
|
| 47 |
+
Returns:
|
| 48 |
+
The appropriate module object.
|
| 49 |
+
"""
|
| 50 |
+
if sys.version_info < _MINIMUM_VERSION:
|
| 51 |
+
raise NotImplementedError(_VERSION_ERROR_TEMPLATE.format(fn_name))
|
| 52 |
+
else:
|
| 53 |
+
if not _is_grpc_tools_importable():
|
| 54 |
+
raise NotImplementedError(_UNINSTALLED_TEMPLATE.format(fn_name))
|
| 55 |
+
import grpc_tools.protoc
|
| 56 |
+
if _has_runtime_proto_symbols(grpc_tools.protoc):
|
| 57 |
+
fn = getattr(grpc_tools.protoc, '_' + fn_name)
|
| 58 |
+
return fn(protobuf_path)
|
| 59 |
+
else:
|
| 60 |
+
raise NotImplementedError(_UNINSTALLED_TEMPLATE.format(fn_name))
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def protos(protobuf_path): # pylint: disable=unused-argument
|
| 64 |
+
"""Returns a module generated by the indicated .proto file.
|
| 65 |
+
|
| 66 |
+
THIS IS AN EXPERIMENTAL API.
|
| 67 |
+
|
| 68 |
+
Use this function to retrieve classes corresponding to message
|
| 69 |
+
definitions in the .proto file.
|
| 70 |
+
|
| 71 |
+
To inspect the contents of the returned module, use the dir function.
|
| 72 |
+
For example:
|
| 73 |
+
|
| 74 |
+
```
|
| 75 |
+
protos = grpc.protos("foo.proto")
|
| 76 |
+
print(dir(protos))
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
The returned module object corresponds to the _pb2.py file generated
|
| 80 |
+
by protoc. The path is expected to be relative to an entry on sys.path
|
| 81 |
+
and all transitive dependencies of the file should also be resolveable
|
| 82 |
+
from an entry on sys.path.
|
| 83 |
+
|
| 84 |
+
To completely disable the machinery behind this function, set the
|
| 85 |
+
GRPC_PYTHON_DISABLE_DYNAMIC_STUBS environment variable to "true".
|
| 86 |
+
|
| 87 |
+
Args:
|
| 88 |
+
protobuf_path: The path to the .proto file on the filesystem. This path
|
| 89 |
+
must be resolveable from an entry on sys.path and so must all of its
|
| 90 |
+
transitive dependencies.
|
| 91 |
+
|
| 92 |
+
Returns:
|
| 93 |
+
A module object corresponding to the message code for the indicated
|
| 94 |
+
.proto file. Equivalent to a generated _pb2.py file.
|
| 95 |
+
"""
|
| 96 |
+
return _call_with_lazy_import("protos", protobuf_path)
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
def services(protobuf_path): # pylint: disable=unused-argument
|
| 100 |
+
"""Returns a module generated by the indicated .proto file.
|
| 101 |
+
|
| 102 |
+
THIS IS AN EXPERIMENTAL API.
|
| 103 |
+
|
| 104 |
+
Use this function to retrieve classes and functions corresponding to
|
| 105 |
+
service definitions in the .proto file, including both stub and servicer
|
| 106 |
+
definitions.
|
| 107 |
+
|
| 108 |
+
To inspect the contents of the returned module, use the dir function.
|
| 109 |
+
For example:
|
| 110 |
+
|
| 111 |
+
```
|
| 112 |
+
services = grpc.services("foo.proto")
|
| 113 |
+
print(dir(services))
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
The returned module object corresponds to the _pb2_grpc.py file generated
|
| 117 |
+
by protoc. The path is expected to be relative to an entry on sys.path
|
| 118 |
+
and all transitive dependencies of the file should also be resolveable
|
| 119 |
+
from an entry on sys.path.
|
| 120 |
+
|
| 121 |
+
To completely disable the machinery behind this function, set the
|
| 122 |
+
GRPC_PYTHON_DISABLE_DYNAMIC_STUBS environment variable to "true".
|
| 123 |
+
|
| 124 |
+
Args:
|
| 125 |
+
protobuf_path: The path to the .proto file on the filesystem. This path
|
| 126 |
+
must be resolveable from an entry on sys.path and so must all of its
|
| 127 |
+
transitive dependencies.
|
| 128 |
+
|
| 129 |
+
Returns:
|
| 130 |
+
A module object corresponding to the stub/service code for the indicated
|
| 131 |
+
.proto file. Equivalent to a generated _pb2_grpc.py file.
|
| 132 |
+
"""
|
| 133 |
+
return _call_with_lazy_import("services", protobuf_path)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def protos_and_services(protobuf_path): # pylint: disable=unused-argument
|
| 137 |
+
"""Returns a 2-tuple of modules corresponding to protos and services.
|
| 138 |
+
|
| 139 |
+
THIS IS AN EXPERIMENTAL API.
|
| 140 |
+
|
| 141 |
+
The return value of this function is equivalent to a call to protos and a
|
| 142 |
+
call to services.
|
| 143 |
+
|
| 144 |
+
To completely disable the machinery behind this function, set the
|
| 145 |
+
GRPC_PYTHON_DISABLE_DYNAMIC_STUBS environment variable to "true".
|
| 146 |
+
|
| 147 |
+
Args:
|
| 148 |
+
protobuf_path: The path to the .proto file on the filesystem. This path
|
| 149 |
+
must be resolveable from an entry on sys.path and so must all of its
|
| 150 |
+
transitive dependencies.
|
| 151 |
+
|
| 152 |
+
Returns:
|
| 153 |
+
A 2-tuple of module objects corresponding to (protos(path), services(path)).
|
| 154 |
+
"""
|
| 155 |
+
return _call_with_lazy_import("protos_and_services", protobuf_path)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_server.py
ADDED
|
@@ -0,0 +1,1003 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2016 gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Service-side implementation of gRPC Python."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
from concurrent import futures
|
| 18 |
+
import enum
|
| 19 |
+
import logging
|
| 20 |
+
import threading
|
| 21 |
+
import time
|
| 22 |
+
|
| 23 |
+
import grpc
|
| 24 |
+
from grpc import _common
|
| 25 |
+
from grpc import _compression
|
| 26 |
+
from grpc import _interceptor
|
| 27 |
+
from grpc._cython import cygrpc
|
| 28 |
+
import six
|
| 29 |
+
|
| 30 |
+
_LOGGER = logging.getLogger(__name__)
|
| 31 |
+
|
| 32 |
+
_SHUTDOWN_TAG = 'shutdown'
|
| 33 |
+
_REQUEST_CALL_TAG = 'request_call'
|
| 34 |
+
|
| 35 |
+
_RECEIVE_CLOSE_ON_SERVER_TOKEN = 'receive_close_on_server'
|
| 36 |
+
_SEND_INITIAL_METADATA_TOKEN = 'send_initial_metadata'
|
| 37 |
+
_RECEIVE_MESSAGE_TOKEN = 'receive_message'
|
| 38 |
+
_SEND_MESSAGE_TOKEN = 'send_message'
|
| 39 |
+
_SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN = (
|
| 40 |
+
'send_initial_metadata * send_message')
|
| 41 |
+
_SEND_STATUS_FROM_SERVER_TOKEN = 'send_status_from_server'
|
| 42 |
+
_SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN = (
|
| 43 |
+
'send_initial_metadata * send_status_from_server')
|
| 44 |
+
|
| 45 |
+
_OPEN = 'open'
|
| 46 |
+
_CLOSED = 'closed'
|
| 47 |
+
_CANCELLED = 'cancelled'
|
| 48 |
+
|
| 49 |
+
_EMPTY_FLAGS = 0
|
| 50 |
+
|
| 51 |
+
_DEALLOCATED_SERVER_CHECK_PERIOD_S = 1.0
|
| 52 |
+
_INF_TIMEOUT = 1e9
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _serialized_request(request_event):
|
| 56 |
+
return request_event.batch_operations[0].message()
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _application_code(code):
|
| 60 |
+
cygrpc_code = _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE.get(code)
|
| 61 |
+
return cygrpc.StatusCode.unknown if cygrpc_code is None else cygrpc_code
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _completion_code(state):
|
| 65 |
+
if state.code is None:
|
| 66 |
+
return cygrpc.StatusCode.ok
|
| 67 |
+
else:
|
| 68 |
+
return _application_code(state.code)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def _abortion_code(state, code):
|
| 72 |
+
if state.code is None:
|
| 73 |
+
return code
|
| 74 |
+
else:
|
| 75 |
+
return _application_code(state.code)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _details(state):
|
| 79 |
+
return b'' if state.details is None else state.details
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class _HandlerCallDetails(
|
| 83 |
+
collections.namedtuple('_HandlerCallDetails', (
|
| 84 |
+
'method',
|
| 85 |
+
'invocation_metadata',
|
| 86 |
+
)), grpc.HandlerCallDetails):
|
| 87 |
+
pass
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
class _RPCState(object):
|
| 91 |
+
|
| 92 |
+
def __init__(self):
|
| 93 |
+
self.condition = threading.Condition()
|
| 94 |
+
self.due = set()
|
| 95 |
+
self.request = None
|
| 96 |
+
self.client = _OPEN
|
| 97 |
+
self.initial_metadata_allowed = True
|
| 98 |
+
self.compression_algorithm = None
|
| 99 |
+
self.disable_next_compression = False
|
| 100 |
+
self.trailing_metadata = None
|
| 101 |
+
self.code = None
|
| 102 |
+
self.details = None
|
| 103 |
+
self.statused = False
|
| 104 |
+
self.rpc_errors = []
|
| 105 |
+
self.callbacks = []
|
| 106 |
+
self.aborted = False
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def _raise_rpc_error(state):
|
| 110 |
+
rpc_error = grpc.RpcError()
|
| 111 |
+
state.rpc_errors.append(rpc_error)
|
| 112 |
+
raise rpc_error
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _possibly_finish_call(state, token):
|
| 116 |
+
state.due.remove(token)
|
| 117 |
+
if not _is_rpc_state_active(state) and not state.due:
|
| 118 |
+
callbacks = state.callbacks
|
| 119 |
+
state.callbacks = None
|
| 120 |
+
return state, callbacks
|
| 121 |
+
else:
|
| 122 |
+
return None, ()
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def _send_status_from_server(state, token):
|
| 126 |
+
|
| 127 |
+
def send_status_from_server(unused_send_status_from_server_event):
|
| 128 |
+
with state.condition:
|
| 129 |
+
return _possibly_finish_call(state, token)
|
| 130 |
+
|
| 131 |
+
return send_status_from_server
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _get_initial_metadata(state, metadata):
|
| 135 |
+
with state.condition:
|
| 136 |
+
if state.compression_algorithm:
|
| 137 |
+
compression_metadata = (
|
| 138 |
+
_compression.compression_algorithm_to_metadata(
|
| 139 |
+
state.compression_algorithm),)
|
| 140 |
+
if metadata is None:
|
| 141 |
+
return compression_metadata
|
| 142 |
+
else:
|
| 143 |
+
return compression_metadata + tuple(metadata)
|
| 144 |
+
else:
|
| 145 |
+
return metadata
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def _get_initial_metadata_operation(state, metadata):
|
| 149 |
+
operation = cygrpc.SendInitialMetadataOperation(
|
| 150 |
+
_get_initial_metadata(state, metadata), _EMPTY_FLAGS)
|
| 151 |
+
return operation
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def _abort(state, call, code, details):
|
| 155 |
+
if state.client is not _CANCELLED:
|
| 156 |
+
effective_code = _abortion_code(state, code)
|
| 157 |
+
effective_details = details if state.details is None else state.details
|
| 158 |
+
if state.initial_metadata_allowed:
|
| 159 |
+
operations = (
|
| 160 |
+
_get_initial_metadata_operation(state, None),
|
| 161 |
+
cygrpc.SendStatusFromServerOperation(state.trailing_metadata,
|
| 162 |
+
effective_code,
|
| 163 |
+
effective_details,
|
| 164 |
+
_EMPTY_FLAGS),
|
| 165 |
+
)
|
| 166 |
+
token = _SEND_INITIAL_METADATA_AND_SEND_STATUS_FROM_SERVER_TOKEN
|
| 167 |
+
else:
|
| 168 |
+
operations = (cygrpc.SendStatusFromServerOperation(
|
| 169 |
+
state.trailing_metadata, effective_code, effective_details,
|
| 170 |
+
_EMPTY_FLAGS),)
|
| 171 |
+
token = _SEND_STATUS_FROM_SERVER_TOKEN
|
| 172 |
+
call.start_server_batch(operations,
|
| 173 |
+
_send_status_from_server(state, token))
|
| 174 |
+
state.statused = True
|
| 175 |
+
state.due.add(token)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
def _receive_close_on_server(state):
|
| 179 |
+
|
| 180 |
+
def receive_close_on_server(receive_close_on_server_event):
|
| 181 |
+
with state.condition:
|
| 182 |
+
if receive_close_on_server_event.batch_operations[0].cancelled():
|
| 183 |
+
state.client = _CANCELLED
|
| 184 |
+
elif state.client is _OPEN:
|
| 185 |
+
state.client = _CLOSED
|
| 186 |
+
state.condition.notify_all()
|
| 187 |
+
return _possibly_finish_call(state, _RECEIVE_CLOSE_ON_SERVER_TOKEN)
|
| 188 |
+
|
| 189 |
+
return receive_close_on_server
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def _receive_message(state, call, request_deserializer):
|
| 193 |
+
|
| 194 |
+
def receive_message(receive_message_event):
|
| 195 |
+
serialized_request = _serialized_request(receive_message_event)
|
| 196 |
+
if serialized_request is None:
|
| 197 |
+
with state.condition:
|
| 198 |
+
if state.client is _OPEN:
|
| 199 |
+
state.client = _CLOSED
|
| 200 |
+
state.condition.notify_all()
|
| 201 |
+
return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN)
|
| 202 |
+
else:
|
| 203 |
+
request = _common.deserialize(serialized_request,
|
| 204 |
+
request_deserializer)
|
| 205 |
+
with state.condition:
|
| 206 |
+
if request is None:
|
| 207 |
+
_abort(state, call, cygrpc.StatusCode.internal,
|
| 208 |
+
b'Exception deserializing request!')
|
| 209 |
+
else:
|
| 210 |
+
state.request = request
|
| 211 |
+
state.condition.notify_all()
|
| 212 |
+
return _possibly_finish_call(state, _RECEIVE_MESSAGE_TOKEN)
|
| 213 |
+
|
| 214 |
+
return receive_message
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
def _send_initial_metadata(state):
|
| 218 |
+
|
| 219 |
+
def send_initial_metadata(unused_send_initial_metadata_event):
|
| 220 |
+
with state.condition:
|
| 221 |
+
return _possibly_finish_call(state, _SEND_INITIAL_METADATA_TOKEN)
|
| 222 |
+
|
| 223 |
+
return send_initial_metadata
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def _send_message(state, token):
|
| 227 |
+
|
| 228 |
+
def send_message(unused_send_message_event):
|
| 229 |
+
with state.condition:
|
| 230 |
+
state.condition.notify_all()
|
| 231 |
+
return _possibly_finish_call(state, token)
|
| 232 |
+
|
| 233 |
+
return send_message
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
class _Context(grpc.ServicerContext):
|
| 237 |
+
|
| 238 |
+
def __init__(self, rpc_event, state, request_deserializer):
|
| 239 |
+
self._rpc_event = rpc_event
|
| 240 |
+
self._state = state
|
| 241 |
+
self._request_deserializer = request_deserializer
|
| 242 |
+
|
| 243 |
+
def is_active(self):
|
| 244 |
+
with self._state.condition:
|
| 245 |
+
return _is_rpc_state_active(self._state)
|
| 246 |
+
|
| 247 |
+
def time_remaining(self):
|
| 248 |
+
return max(self._rpc_event.call_details.deadline - time.time(), 0)
|
| 249 |
+
|
| 250 |
+
def cancel(self):
|
| 251 |
+
self._rpc_event.call.cancel()
|
| 252 |
+
|
| 253 |
+
def add_callback(self, callback):
|
| 254 |
+
with self._state.condition:
|
| 255 |
+
if self._state.callbacks is None:
|
| 256 |
+
return False
|
| 257 |
+
else:
|
| 258 |
+
self._state.callbacks.append(callback)
|
| 259 |
+
return True
|
| 260 |
+
|
| 261 |
+
def disable_next_message_compression(self):
|
| 262 |
+
with self._state.condition:
|
| 263 |
+
self._state.disable_next_compression = True
|
| 264 |
+
|
| 265 |
+
def invocation_metadata(self):
|
| 266 |
+
return self._rpc_event.invocation_metadata
|
| 267 |
+
|
| 268 |
+
def peer(self):
|
| 269 |
+
return _common.decode(self._rpc_event.call.peer())
|
| 270 |
+
|
| 271 |
+
def peer_identities(self):
|
| 272 |
+
return cygrpc.peer_identities(self._rpc_event.call)
|
| 273 |
+
|
| 274 |
+
def peer_identity_key(self):
|
| 275 |
+
id_key = cygrpc.peer_identity_key(self._rpc_event.call)
|
| 276 |
+
return id_key if id_key is None else _common.decode(id_key)
|
| 277 |
+
|
| 278 |
+
def auth_context(self):
|
| 279 |
+
return {
|
| 280 |
+
_common.decode(key): value for key, value in six.iteritems(
|
| 281 |
+
cygrpc.auth_context(self._rpc_event.call))
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
def set_compression(self, compression):
|
| 285 |
+
with self._state.condition:
|
| 286 |
+
self._state.compression_algorithm = compression
|
| 287 |
+
|
| 288 |
+
def send_initial_metadata(self, initial_metadata):
|
| 289 |
+
with self._state.condition:
|
| 290 |
+
if self._state.client is _CANCELLED:
|
| 291 |
+
_raise_rpc_error(self._state)
|
| 292 |
+
else:
|
| 293 |
+
if self._state.initial_metadata_allowed:
|
| 294 |
+
operation = _get_initial_metadata_operation(
|
| 295 |
+
self._state, initial_metadata)
|
| 296 |
+
self._rpc_event.call.start_server_batch(
|
| 297 |
+
(operation,), _send_initial_metadata(self._state))
|
| 298 |
+
self._state.initial_metadata_allowed = False
|
| 299 |
+
self._state.due.add(_SEND_INITIAL_METADATA_TOKEN)
|
| 300 |
+
else:
|
| 301 |
+
raise ValueError('Initial metadata no longer allowed!')
|
| 302 |
+
|
| 303 |
+
def set_trailing_metadata(self, trailing_metadata):
|
| 304 |
+
with self._state.condition:
|
| 305 |
+
self._state.trailing_metadata = trailing_metadata
|
| 306 |
+
|
| 307 |
+
def trailing_metadata(self):
|
| 308 |
+
return self._state.trailing_metadata
|
| 309 |
+
|
| 310 |
+
def abort(self, code, details):
|
| 311 |
+
# treat OK like other invalid arguments: fail the RPC
|
| 312 |
+
if code == grpc.StatusCode.OK:
|
| 313 |
+
_LOGGER.error(
|
| 314 |
+
'abort() called with StatusCode.OK; returning UNKNOWN')
|
| 315 |
+
code = grpc.StatusCode.UNKNOWN
|
| 316 |
+
details = ''
|
| 317 |
+
with self._state.condition:
|
| 318 |
+
self._state.code = code
|
| 319 |
+
self._state.details = _common.encode(details)
|
| 320 |
+
self._state.aborted = True
|
| 321 |
+
raise Exception()
|
| 322 |
+
|
| 323 |
+
def abort_with_status(self, status):
|
| 324 |
+
self._state.trailing_metadata = status.trailing_metadata
|
| 325 |
+
self.abort(status.code, status.details)
|
| 326 |
+
|
| 327 |
+
def set_code(self, code):
|
| 328 |
+
with self._state.condition:
|
| 329 |
+
self._state.code = code
|
| 330 |
+
|
| 331 |
+
def code(self):
|
| 332 |
+
return self._state.code
|
| 333 |
+
|
| 334 |
+
def set_details(self, details):
|
| 335 |
+
with self._state.condition:
|
| 336 |
+
self._state.details = _common.encode(details)
|
| 337 |
+
|
| 338 |
+
def details(self):
|
| 339 |
+
return self._state.details
|
| 340 |
+
|
| 341 |
+
def _finalize_state(self):
|
| 342 |
+
pass
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
class _RequestIterator(object):
|
| 346 |
+
|
| 347 |
+
def __init__(self, state, call, request_deserializer):
|
| 348 |
+
self._state = state
|
| 349 |
+
self._call = call
|
| 350 |
+
self._request_deserializer = request_deserializer
|
| 351 |
+
|
| 352 |
+
def _raise_or_start_receive_message(self):
|
| 353 |
+
if self._state.client is _CANCELLED:
|
| 354 |
+
_raise_rpc_error(self._state)
|
| 355 |
+
elif not _is_rpc_state_active(self._state):
|
| 356 |
+
raise StopIteration()
|
| 357 |
+
else:
|
| 358 |
+
self._call.start_server_batch(
|
| 359 |
+
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
|
| 360 |
+
_receive_message(self._state, self._call,
|
| 361 |
+
self._request_deserializer))
|
| 362 |
+
self._state.due.add(_RECEIVE_MESSAGE_TOKEN)
|
| 363 |
+
|
| 364 |
+
def _look_for_request(self):
|
| 365 |
+
if self._state.client is _CANCELLED:
|
| 366 |
+
_raise_rpc_error(self._state)
|
| 367 |
+
elif (self._state.request is None and
|
| 368 |
+
_RECEIVE_MESSAGE_TOKEN not in self._state.due):
|
| 369 |
+
raise StopIteration()
|
| 370 |
+
else:
|
| 371 |
+
request = self._state.request
|
| 372 |
+
self._state.request = None
|
| 373 |
+
return request
|
| 374 |
+
|
| 375 |
+
raise AssertionError() # should never run
|
| 376 |
+
|
| 377 |
+
def _next(self):
|
| 378 |
+
with self._state.condition:
|
| 379 |
+
self._raise_or_start_receive_message()
|
| 380 |
+
while True:
|
| 381 |
+
self._state.condition.wait()
|
| 382 |
+
request = self._look_for_request()
|
| 383 |
+
if request is not None:
|
| 384 |
+
return request
|
| 385 |
+
|
| 386 |
+
def __iter__(self):
|
| 387 |
+
return self
|
| 388 |
+
|
| 389 |
+
def __next__(self):
|
| 390 |
+
return self._next()
|
| 391 |
+
|
| 392 |
+
def next(self):
|
| 393 |
+
return self._next()
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
def _unary_request(rpc_event, state, request_deserializer):
|
| 397 |
+
|
| 398 |
+
def unary_request():
|
| 399 |
+
with state.condition:
|
| 400 |
+
if not _is_rpc_state_active(state):
|
| 401 |
+
return None
|
| 402 |
+
else:
|
| 403 |
+
rpc_event.call.start_server_batch(
|
| 404 |
+
(cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
|
| 405 |
+
_receive_message(state, rpc_event.call,
|
| 406 |
+
request_deserializer))
|
| 407 |
+
state.due.add(_RECEIVE_MESSAGE_TOKEN)
|
| 408 |
+
while True:
|
| 409 |
+
state.condition.wait()
|
| 410 |
+
if state.request is None:
|
| 411 |
+
if state.client is _CLOSED:
|
| 412 |
+
details = '"{}" requires exactly one request message.'.format(
|
| 413 |
+
rpc_event.call_details.method)
|
| 414 |
+
_abort(state, rpc_event.call,
|
| 415 |
+
cygrpc.StatusCode.unimplemented,
|
| 416 |
+
_common.encode(details))
|
| 417 |
+
return None
|
| 418 |
+
elif state.client is _CANCELLED:
|
| 419 |
+
return None
|
| 420 |
+
else:
|
| 421 |
+
request = state.request
|
| 422 |
+
state.request = None
|
| 423 |
+
return request
|
| 424 |
+
|
| 425 |
+
return unary_request
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
def _call_behavior(rpc_event,
|
| 429 |
+
state,
|
| 430 |
+
behavior,
|
| 431 |
+
argument,
|
| 432 |
+
request_deserializer,
|
| 433 |
+
send_response_callback=None):
|
| 434 |
+
from grpc import _create_servicer_context
|
| 435 |
+
with _create_servicer_context(rpc_event, state,
|
| 436 |
+
request_deserializer) as context:
|
| 437 |
+
try:
|
| 438 |
+
response_or_iterator = None
|
| 439 |
+
if send_response_callback is not None:
|
| 440 |
+
response_or_iterator = behavior(argument, context,
|
| 441 |
+
send_response_callback)
|
| 442 |
+
else:
|
| 443 |
+
response_or_iterator = behavior(argument, context)
|
| 444 |
+
return response_or_iterator, True
|
| 445 |
+
except Exception as exception: # pylint: disable=broad-except
|
| 446 |
+
with state.condition:
|
| 447 |
+
if state.aborted:
|
| 448 |
+
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
|
| 449 |
+
b'RPC Aborted')
|
| 450 |
+
elif exception not in state.rpc_errors:
|
| 451 |
+
details = 'Exception calling application: {}'.format(
|
| 452 |
+
exception)
|
| 453 |
+
_LOGGER.exception(details)
|
| 454 |
+
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
|
| 455 |
+
_common.encode(details))
|
| 456 |
+
return None, False
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
def _take_response_from_response_iterator(rpc_event, state, response_iterator):
|
| 460 |
+
try:
|
| 461 |
+
return next(response_iterator), True
|
| 462 |
+
except StopIteration:
|
| 463 |
+
return None, True
|
| 464 |
+
except Exception as exception: # pylint: disable=broad-except
|
| 465 |
+
with state.condition:
|
| 466 |
+
if state.aborted:
|
| 467 |
+
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
|
| 468 |
+
b'RPC Aborted')
|
| 469 |
+
elif exception not in state.rpc_errors:
|
| 470 |
+
details = 'Exception iterating responses: {}'.format(exception)
|
| 471 |
+
_LOGGER.exception(details)
|
| 472 |
+
_abort(state, rpc_event.call, cygrpc.StatusCode.unknown,
|
| 473 |
+
_common.encode(details))
|
| 474 |
+
return None, False
|
| 475 |
+
|
| 476 |
+
|
| 477 |
+
def _serialize_response(rpc_event, state, response, response_serializer):
|
| 478 |
+
serialized_response = _common.serialize(response, response_serializer)
|
| 479 |
+
if serialized_response is None:
|
| 480 |
+
with state.condition:
|
| 481 |
+
_abort(state, rpc_event.call, cygrpc.StatusCode.internal,
|
| 482 |
+
b'Failed to serialize response!')
|
| 483 |
+
return None
|
| 484 |
+
else:
|
| 485 |
+
return serialized_response
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
def _get_send_message_op_flags_from_state(state):
|
| 489 |
+
if state.disable_next_compression:
|
| 490 |
+
return cygrpc.WriteFlag.no_compress
|
| 491 |
+
else:
|
| 492 |
+
return _EMPTY_FLAGS
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
def _reset_per_message_state(state):
|
| 496 |
+
with state.condition:
|
| 497 |
+
state.disable_next_compression = False
|
| 498 |
+
|
| 499 |
+
|
| 500 |
+
def _send_response(rpc_event, state, serialized_response):
|
| 501 |
+
with state.condition:
|
| 502 |
+
if not _is_rpc_state_active(state):
|
| 503 |
+
return False
|
| 504 |
+
else:
|
| 505 |
+
if state.initial_metadata_allowed:
|
| 506 |
+
operations = (
|
| 507 |
+
_get_initial_metadata_operation(state, None),
|
| 508 |
+
cygrpc.SendMessageOperation(
|
| 509 |
+
serialized_response,
|
| 510 |
+
_get_send_message_op_flags_from_state(state)),
|
| 511 |
+
)
|
| 512 |
+
state.initial_metadata_allowed = False
|
| 513 |
+
token = _SEND_INITIAL_METADATA_AND_SEND_MESSAGE_TOKEN
|
| 514 |
+
else:
|
| 515 |
+
operations = (cygrpc.SendMessageOperation(
|
| 516 |
+
serialized_response,
|
| 517 |
+
_get_send_message_op_flags_from_state(state)),)
|
| 518 |
+
token = _SEND_MESSAGE_TOKEN
|
| 519 |
+
rpc_event.call.start_server_batch(operations,
|
| 520 |
+
_send_message(state, token))
|
| 521 |
+
state.due.add(token)
|
| 522 |
+
_reset_per_message_state(state)
|
| 523 |
+
while True:
|
| 524 |
+
state.condition.wait()
|
| 525 |
+
if token not in state.due:
|
| 526 |
+
return _is_rpc_state_active(state)
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
def _status(rpc_event, state, serialized_response):
|
| 530 |
+
with state.condition:
|
| 531 |
+
if state.client is not _CANCELLED:
|
| 532 |
+
code = _completion_code(state)
|
| 533 |
+
details = _details(state)
|
| 534 |
+
operations = [
|
| 535 |
+
cygrpc.SendStatusFromServerOperation(state.trailing_metadata,
|
| 536 |
+
code, details,
|
| 537 |
+
_EMPTY_FLAGS),
|
| 538 |
+
]
|
| 539 |
+
if state.initial_metadata_allowed:
|
| 540 |
+
operations.append(_get_initial_metadata_operation(state, None))
|
| 541 |
+
if serialized_response is not None:
|
| 542 |
+
operations.append(
|
| 543 |
+
cygrpc.SendMessageOperation(
|
| 544 |
+
serialized_response,
|
| 545 |
+
_get_send_message_op_flags_from_state(state)))
|
| 546 |
+
rpc_event.call.start_server_batch(
|
| 547 |
+
operations,
|
| 548 |
+
_send_status_from_server(state, _SEND_STATUS_FROM_SERVER_TOKEN))
|
| 549 |
+
state.statused = True
|
| 550 |
+
_reset_per_message_state(state)
|
| 551 |
+
state.due.add(_SEND_STATUS_FROM_SERVER_TOKEN)
|
| 552 |
+
|
| 553 |
+
|
| 554 |
+
def _unary_response_in_pool(rpc_event, state, behavior, argument_thunk,
|
| 555 |
+
request_deserializer, response_serializer):
|
| 556 |
+
cygrpc.install_context_from_request_call_event(rpc_event)
|
| 557 |
+
try:
|
| 558 |
+
argument = argument_thunk()
|
| 559 |
+
if argument is not None:
|
| 560 |
+
response, proceed = _call_behavior(rpc_event, state, behavior,
|
| 561 |
+
argument, request_deserializer)
|
| 562 |
+
if proceed:
|
| 563 |
+
serialized_response = _serialize_response(
|
| 564 |
+
rpc_event, state, response, response_serializer)
|
| 565 |
+
if serialized_response is not None:
|
| 566 |
+
_status(rpc_event, state, serialized_response)
|
| 567 |
+
finally:
|
| 568 |
+
cygrpc.uninstall_context()
|
| 569 |
+
|
| 570 |
+
|
| 571 |
+
def _stream_response_in_pool(rpc_event, state, behavior, argument_thunk,
|
| 572 |
+
request_deserializer, response_serializer):
|
| 573 |
+
cygrpc.install_context_from_request_call_event(rpc_event)
|
| 574 |
+
|
| 575 |
+
def send_response(response):
|
| 576 |
+
if response is None:
|
| 577 |
+
_status(rpc_event, state, None)
|
| 578 |
+
else:
|
| 579 |
+
serialized_response = _serialize_response(rpc_event, state,
|
| 580 |
+
response,
|
| 581 |
+
response_serializer)
|
| 582 |
+
if serialized_response is not None:
|
| 583 |
+
_send_response(rpc_event, state, serialized_response)
|
| 584 |
+
|
| 585 |
+
try:
|
| 586 |
+
argument = argument_thunk()
|
| 587 |
+
if argument is not None:
|
| 588 |
+
if hasattr(behavior, 'experimental_non_blocking'
|
| 589 |
+
) and behavior.experimental_non_blocking:
|
| 590 |
+
_call_behavior(rpc_event,
|
| 591 |
+
state,
|
| 592 |
+
behavior,
|
| 593 |
+
argument,
|
| 594 |
+
request_deserializer,
|
| 595 |
+
send_response_callback=send_response)
|
| 596 |
+
else:
|
| 597 |
+
response_iterator, proceed = _call_behavior(
|
| 598 |
+
rpc_event, state, behavior, argument, request_deserializer)
|
| 599 |
+
if proceed:
|
| 600 |
+
_send_message_callback_to_blocking_iterator_adapter(
|
| 601 |
+
rpc_event, state, send_response, response_iterator)
|
| 602 |
+
finally:
|
| 603 |
+
cygrpc.uninstall_context()
|
| 604 |
+
|
| 605 |
+
|
| 606 |
+
def _is_rpc_state_active(state):
|
| 607 |
+
return state.client is not _CANCELLED and not state.statused
|
| 608 |
+
|
| 609 |
+
|
| 610 |
+
def _send_message_callback_to_blocking_iterator_adapter(rpc_event, state,
|
| 611 |
+
send_response_callback,
|
| 612 |
+
response_iterator):
|
| 613 |
+
while True:
|
| 614 |
+
response, proceed = _take_response_from_response_iterator(
|
| 615 |
+
rpc_event, state, response_iterator)
|
| 616 |
+
if proceed:
|
| 617 |
+
send_response_callback(response)
|
| 618 |
+
if not _is_rpc_state_active(state):
|
| 619 |
+
break
|
| 620 |
+
else:
|
| 621 |
+
break
|
| 622 |
+
|
| 623 |
+
|
| 624 |
+
def _select_thread_pool_for_behavior(behavior, default_thread_pool):
|
| 625 |
+
if hasattr(behavior, 'experimental_thread_pool') and isinstance(
|
| 626 |
+
behavior.experimental_thread_pool, futures.ThreadPoolExecutor):
|
| 627 |
+
return behavior.experimental_thread_pool
|
| 628 |
+
else:
|
| 629 |
+
return default_thread_pool
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
def _handle_unary_unary(rpc_event, state, method_handler, default_thread_pool):
|
| 633 |
+
unary_request = _unary_request(rpc_event, state,
|
| 634 |
+
method_handler.request_deserializer)
|
| 635 |
+
thread_pool = _select_thread_pool_for_behavior(method_handler.unary_unary,
|
| 636 |
+
default_thread_pool)
|
| 637 |
+
return thread_pool.submit(_unary_response_in_pool, rpc_event, state,
|
| 638 |
+
method_handler.unary_unary, unary_request,
|
| 639 |
+
method_handler.request_deserializer,
|
| 640 |
+
method_handler.response_serializer)
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
def _handle_unary_stream(rpc_event, state, method_handler, default_thread_pool):
|
| 644 |
+
unary_request = _unary_request(rpc_event, state,
|
| 645 |
+
method_handler.request_deserializer)
|
| 646 |
+
thread_pool = _select_thread_pool_for_behavior(method_handler.unary_stream,
|
| 647 |
+
default_thread_pool)
|
| 648 |
+
return thread_pool.submit(_stream_response_in_pool, rpc_event, state,
|
| 649 |
+
method_handler.unary_stream, unary_request,
|
| 650 |
+
method_handler.request_deserializer,
|
| 651 |
+
method_handler.response_serializer)
|
| 652 |
+
|
| 653 |
+
|
| 654 |
+
def _handle_stream_unary(rpc_event, state, method_handler, default_thread_pool):
|
| 655 |
+
request_iterator = _RequestIterator(state, rpc_event.call,
|
| 656 |
+
method_handler.request_deserializer)
|
| 657 |
+
thread_pool = _select_thread_pool_for_behavior(method_handler.stream_unary,
|
| 658 |
+
default_thread_pool)
|
| 659 |
+
return thread_pool.submit(_unary_response_in_pool, rpc_event, state,
|
| 660 |
+
method_handler.stream_unary,
|
| 661 |
+
lambda: request_iterator,
|
| 662 |
+
method_handler.request_deserializer,
|
| 663 |
+
method_handler.response_serializer)
|
| 664 |
+
|
| 665 |
+
|
| 666 |
+
def _handle_stream_stream(rpc_event, state, method_handler,
|
| 667 |
+
default_thread_pool):
|
| 668 |
+
request_iterator = _RequestIterator(state, rpc_event.call,
|
| 669 |
+
method_handler.request_deserializer)
|
| 670 |
+
thread_pool = _select_thread_pool_for_behavior(method_handler.stream_stream,
|
| 671 |
+
default_thread_pool)
|
| 672 |
+
return thread_pool.submit(_stream_response_in_pool, rpc_event, state,
|
| 673 |
+
method_handler.stream_stream,
|
| 674 |
+
lambda: request_iterator,
|
| 675 |
+
method_handler.request_deserializer,
|
| 676 |
+
method_handler.response_serializer)
|
| 677 |
+
|
| 678 |
+
|
| 679 |
+
def _find_method_handler(rpc_event, generic_handlers, interceptor_pipeline):
|
| 680 |
+
|
| 681 |
+
def query_handlers(handler_call_details):
|
| 682 |
+
for generic_handler in generic_handlers:
|
| 683 |
+
method_handler = generic_handler.service(handler_call_details)
|
| 684 |
+
if method_handler is not None:
|
| 685 |
+
return method_handler
|
| 686 |
+
return None
|
| 687 |
+
|
| 688 |
+
handler_call_details = _HandlerCallDetails(
|
| 689 |
+
_common.decode(rpc_event.call_details.method),
|
| 690 |
+
rpc_event.invocation_metadata)
|
| 691 |
+
|
| 692 |
+
if interceptor_pipeline is not None:
|
| 693 |
+
return interceptor_pipeline.execute(query_handlers,
|
| 694 |
+
handler_call_details)
|
| 695 |
+
else:
|
| 696 |
+
return query_handlers(handler_call_details)
|
| 697 |
+
|
| 698 |
+
|
| 699 |
+
def _reject_rpc(rpc_event, status, details):
|
| 700 |
+
rpc_state = _RPCState()
|
| 701 |
+
operations = (
|
| 702 |
+
_get_initial_metadata_operation(rpc_state, None),
|
| 703 |
+
cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS),
|
| 704 |
+
cygrpc.SendStatusFromServerOperation(None, status, details,
|
| 705 |
+
_EMPTY_FLAGS),
|
| 706 |
+
)
|
| 707 |
+
rpc_event.call.start_server_batch(operations, lambda ignored_event: (
|
| 708 |
+
rpc_state,
|
| 709 |
+
(),
|
| 710 |
+
))
|
| 711 |
+
return rpc_state
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
def _handle_with_method_handler(rpc_event, method_handler, thread_pool):
|
| 715 |
+
state = _RPCState()
|
| 716 |
+
with state.condition:
|
| 717 |
+
rpc_event.call.start_server_batch(
|
| 718 |
+
(cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS),),
|
| 719 |
+
_receive_close_on_server(state))
|
| 720 |
+
state.due.add(_RECEIVE_CLOSE_ON_SERVER_TOKEN)
|
| 721 |
+
if method_handler.request_streaming:
|
| 722 |
+
if method_handler.response_streaming:
|
| 723 |
+
return state, _handle_stream_stream(rpc_event, state,
|
| 724 |
+
method_handler, thread_pool)
|
| 725 |
+
else:
|
| 726 |
+
return state, _handle_stream_unary(rpc_event, state,
|
| 727 |
+
method_handler, thread_pool)
|
| 728 |
+
else:
|
| 729 |
+
if method_handler.response_streaming:
|
| 730 |
+
return state, _handle_unary_stream(rpc_event, state,
|
| 731 |
+
method_handler, thread_pool)
|
| 732 |
+
else:
|
| 733 |
+
return state, _handle_unary_unary(rpc_event, state,
|
| 734 |
+
method_handler, thread_pool)
|
| 735 |
+
|
| 736 |
+
|
| 737 |
+
def _handle_call(rpc_event, generic_handlers, interceptor_pipeline, thread_pool,
|
| 738 |
+
concurrency_exceeded):
|
| 739 |
+
if not rpc_event.success:
|
| 740 |
+
return None, None
|
| 741 |
+
if rpc_event.call_details.method is not None:
|
| 742 |
+
try:
|
| 743 |
+
method_handler = _find_method_handler(rpc_event, generic_handlers,
|
| 744 |
+
interceptor_pipeline)
|
| 745 |
+
except Exception as exception: # pylint: disable=broad-except
|
| 746 |
+
details = 'Exception servicing handler: {}'.format(exception)
|
| 747 |
+
_LOGGER.exception(details)
|
| 748 |
+
return _reject_rpc(rpc_event, cygrpc.StatusCode.unknown,
|
| 749 |
+
b'Error in service handler!'), None
|
| 750 |
+
if method_handler is None:
|
| 751 |
+
return _reject_rpc(rpc_event, cygrpc.StatusCode.unimplemented,
|
| 752 |
+
b'Method not found!'), None
|
| 753 |
+
elif concurrency_exceeded:
|
| 754 |
+
return _reject_rpc(rpc_event, cygrpc.StatusCode.resource_exhausted,
|
| 755 |
+
b'Concurrent RPC limit exceeded!'), None
|
| 756 |
+
else:
|
| 757 |
+
return _handle_with_method_handler(rpc_event, method_handler,
|
| 758 |
+
thread_pool)
|
| 759 |
+
else:
|
| 760 |
+
return None, None
|
| 761 |
+
|
| 762 |
+
|
| 763 |
+
@enum.unique
|
| 764 |
+
class _ServerStage(enum.Enum):
|
| 765 |
+
STOPPED = 'stopped'
|
| 766 |
+
STARTED = 'started'
|
| 767 |
+
GRACE = 'grace'
|
| 768 |
+
|
| 769 |
+
|
| 770 |
+
class _ServerState(object):
|
| 771 |
+
|
| 772 |
+
# pylint: disable=too-many-arguments
|
| 773 |
+
def __init__(self, completion_queue, server, generic_handlers,
|
| 774 |
+
interceptor_pipeline, thread_pool, maximum_concurrent_rpcs):
|
| 775 |
+
self.lock = threading.RLock()
|
| 776 |
+
self.completion_queue = completion_queue
|
| 777 |
+
self.server = server
|
| 778 |
+
self.generic_handlers = list(generic_handlers)
|
| 779 |
+
self.interceptor_pipeline = interceptor_pipeline
|
| 780 |
+
self.thread_pool = thread_pool
|
| 781 |
+
self.stage = _ServerStage.STOPPED
|
| 782 |
+
self.termination_event = threading.Event()
|
| 783 |
+
self.shutdown_events = [self.termination_event]
|
| 784 |
+
self.maximum_concurrent_rpcs = maximum_concurrent_rpcs
|
| 785 |
+
self.active_rpc_count = 0
|
| 786 |
+
|
| 787 |
+
# TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields.
|
| 788 |
+
self.rpc_states = set()
|
| 789 |
+
self.due = set()
|
| 790 |
+
|
| 791 |
+
# A "volatile" flag to interrupt the daemon serving thread
|
| 792 |
+
self.server_deallocated = False
|
| 793 |
+
|
| 794 |
+
|
| 795 |
+
def _add_generic_handlers(state, generic_handlers):
|
| 796 |
+
with state.lock:
|
| 797 |
+
state.generic_handlers.extend(generic_handlers)
|
| 798 |
+
|
| 799 |
+
|
| 800 |
+
def _add_insecure_port(state, address):
|
| 801 |
+
with state.lock:
|
| 802 |
+
return state.server.add_http2_port(address)
|
| 803 |
+
|
| 804 |
+
|
| 805 |
+
def _add_secure_port(state, address, server_credentials):
|
| 806 |
+
with state.lock:
|
| 807 |
+
return state.server.add_http2_port(address,
|
| 808 |
+
server_credentials._credentials)
|
| 809 |
+
|
| 810 |
+
|
| 811 |
+
def _request_call(state):
|
| 812 |
+
state.server.request_call(state.completion_queue, state.completion_queue,
|
| 813 |
+
_REQUEST_CALL_TAG)
|
| 814 |
+
state.due.add(_REQUEST_CALL_TAG)
|
| 815 |
+
|
| 816 |
+
|
| 817 |
+
# TODO(https://github.com/grpc/grpc/issues/6597): delete this function.
|
| 818 |
+
def _stop_serving(state):
|
| 819 |
+
if not state.rpc_states and not state.due:
|
| 820 |
+
state.server.destroy()
|
| 821 |
+
for shutdown_event in state.shutdown_events:
|
| 822 |
+
shutdown_event.set()
|
| 823 |
+
state.stage = _ServerStage.STOPPED
|
| 824 |
+
return True
|
| 825 |
+
else:
|
| 826 |
+
return False
|
| 827 |
+
|
| 828 |
+
|
| 829 |
+
def _on_call_completed(state):
|
| 830 |
+
with state.lock:
|
| 831 |
+
state.active_rpc_count -= 1
|
| 832 |
+
|
| 833 |
+
|
| 834 |
+
def _process_event_and_continue(state, event):
|
| 835 |
+
should_continue = True
|
| 836 |
+
if event.tag is _SHUTDOWN_TAG:
|
| 837 |
+
with state.lock:
|
| 838 |
+
state.due.remove(_SHUTDOWN_TAG)
|
| 839 |
+
if _stop_serving(state):
|
| 840 |
+
should_continue = False
|
| 841 |
+
elif event.tag is _REQUEST_CALL_TAG:
|
| 842 |
+
with state.lock:
|
| 843 |
+
state.due.remove(_REQUEST_CALL_TAG)
|
| 844 |
+
concurrency_exceeded = (
|
| 845 |
+
state.maximum_concurrent_rpcs is not None and
|
| 846 |
+
state.active_rpc_count >= state.maximum_concurrent_rpcs)
|
| 847 |
+
rpc_state, rpc_future = _handle_call(event, state.generic_handlers,
|
| 848 |
+
state.interceptor_pipeline,
|
| 849 |
+
state.thread_pool,
|
| 850 |
+
concurrency_exceeded)
|
| 851 |
+
if rpc_state is not None:
|
| 852 |
+
state.rpc_states.add(rpc_state)
|
| 853 |
+
if rpc_future is not None:
|
| 854 |
+
state.active_rpc_count += 1
|
| 855 |
+
rpc_future.add_done_callback(
|
| 856 |
+
lambda unused_future: _on_call_completed(state))
|
| 857 |
+
if state.stage is _ServerStage.STARTED:
|
| 858 |
+
_request_call(state)
|
| 859 |
+
elif _stop_serving(state):
|
| 860 |
+
should_continue = False
|
| 861 |
+
else:
|
| 862 |
+
rpc_state, callbacks = event.tag(event)
|
| 863 |
+
for callback in callbacks:
|
| 864 |
+
try:
|
| 865 |
+
callback()
|
| 866 |
+
except Exception: # pylint: disable=broad-except
|
| 867 |
+
_LOGGER.exception('Exception calling callback!')
|
| 868 |
+
if rpc_state is not None:
|
| 869 |
+
with state.lock:
|
| 870 |
+
state.rpc_states.remove(rpc_state)
|
| 871 |
+
if _stop_serving(state):
|
| 872 |
+
should_continue = False
|
| 873 |
+
return should_continue
|
| 874 |
+
|
| 875 |
+
|
| 876 |
+
def _serve(state):
|
| 877 |
+
while True:
|
| 878 |
+
timeout = time.time() + _DEALLOCATED_SERVER_CHECK_PERIOD_S
|
| 879 |
+
event = state.completion_queue.poll(timeout)
|
| 880 |
+
if state.server_deallocated:
|
| 881 |
+
_begin_shutdown_once(state)
|
| 882 |
+
if event.completion_type != cygrpc.CompletionType.queue_timeout:
|
| 883 |
+
if not _process_event_and_continue(state, event):
|
| 884 |
+
return
|
| 885 |
+
# We want to force the deletion of the previous event
|
| 886 |
+
# ~before~ we poll again; if the event has a reference
|
| 887 |
+
# to a shutdown Call object, this can induce spinlock.
|
| 888 |
+
event = None
|
| 889 |
+
|
| 890 |
+
|
| 891 |
+
def _begin_shutdown_once(state):
|
| 892 |
+
with state.lock:
|
| 893 |
+
if state.stage is _ServerStage.STARTED:
|
| 894 |
+
state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG)
|
| 895 |
+
state.stage = _ServerStage.GRACE
|
| 896 |
+
state.due.add(_SHUTDOWN_TAG)
|
| 897 |
+
|
| 898 |
+
|
| 899 |
+
def _stop(state, grace):
|
| 900 |
+
with state.lock:
|
| 901 |
+
if state.stage is _ServerStage.STOPPED:
|
| 902 |
+
shutdown_event = threading.Event()
|
| 903 |
+
shutdown_event.set()
|
| 904 |
+
return shutdown_event
|
| 905 |
+
else:
|
| 906 |
+
_begin_shutdown_once(state)
|
| 907 |
+
shutdown_event = threading.Event()
|
| 908 |
+
state.shutdown_events.append(shutdown_event)
|
| 909 |
+
if grace is None:
|
| 910 |
+
state.server.cancel_all_calls()
|
| 911 |
+
else:
|
| 912 |
+
|
| 913 |
+
def cancel_all_calls_after_grace():
|
| 914 |
+
shutdown_event.wait(timeout=grace)
|
| 915 |
+
with state.lock:
|
| 916 |
+
state.server.cancel_all_calls()
|
| 917 |
+
|
| 918 |
+
thread = threading.Thread(target=cancel_all_calls_after_grace)
|
| 919 |
+
thread.start()
|
| 920 |
+
return shutdown_event
|
| 921 |
+
shutdown_event.wait()
|
| 922 |
+
return shutdown_event
|
| 923 |
+
|
| 924 |
+
|
| 925 |
+
def _start(state):
|
| 926 |
+
with state.lock:
|
| 927 |
+
if state.stage is not _ServerStage.STOPPED:
|
| 928 |
+
raise ValueError('Cannot start already-started server!')
|
| 929 |
+
state.server.start()
|
| 930 |
+
state.stage = _ServerStage.STARTED
|
| 931 |
+
_request_call(state)
|
| 932 |
+
|
| 933 |
+
thread = threading.Thread(target=_serve, args=(state,))
|
| 934 |
+
thread.daemon = True
|
| 935 |
+
thread.start()
|
| 936 |
+
|
| 937 |
+
|
| 938 |
+
def _validate_generic_rpc_handlers(generic_rpc_handlers):
|
| 939 |
+
for generic_rpc_handler in generic_rpc_handlers:
|
| 940 |
+
service_attribute = getattr(generic_rpc_handler, 'service', None)
|
| 941 |
+
if service_attribute is None:
|
| 942 |
+
raise AttributeError(
|
| 943 |
+
'"{}" must conform to grpc.GenericRpcHandler type but does '
|
| 944 |
+
'not have "service" method!'.format(generic_rpc_handler))
|
| 945 |
+
|
| 946 |
+
|
| 947 |
+
def _augment_options(base_options, compression):
|
| 948 |
+
compression_option = _compression.create_channel_option(compression)
|
| 949 |
+
return tuple(base_options) + compression_option
|
| 950 |
+
|
| 951 |
+
|
| 952 |
+
class _Server(grpc.Server):
|
| 953 |
+
|
| 954 |
+
# pylint: disable=too-many-arguments
|
| 955 |
+
def __init__(self, thread_pool, generic_handlers, interceptors, options,
|
| 956 |
+
maximum_concurrent_rpcs, compression, xds):
|
| 957 |
+
completion_queue = cygrpc.CompletionQueue()
|
| 958 |
+
server = cygrpc.Server(_augment_options(options, compression), xds)
|
| 959 |
+
server.register_completion_queue(completion_queue)
|
| 960 |
+
self._state = _ServerState(completion_queue, server, generic_handlers,
|
| 961 |
+
_interceptor.service_pipeline(interceptors),
|
| 962 |
+
thread_pool, maximum_concurrent_rpcs)
|
| 963 |
+
|
| 964 |
+
def add_generic_rpc_handlers(self, generic_rpc_handlers):
|
| 965 |
+
_validate_generic_rpc_handlers(generic_rpc_handlers)
|
| 966 |
+
_add_generic_handlers(self._state, generic_rpc_handlers)
|
| 967 |
+
|
| 968 |
+
def add_insecure_port(self, address):
|
| 969 |
+
return _common.validate_port_binding_result(
|
| 970 |
+
address, _add_insecure_port(self._state, _common.encode(address)))
|
| 971 |
+
|
| 972 |
+
def add_secure_port(self, address, server_credentials):
|
| 973 |
+
return _common.validate_port_binding_result(
|
| 974 |
+
address,
|
| 975 |
+
_add_secure_port(self._state, _common.encode(address),
|
| 976 |
+
server_credentials))
|
| 977 |
+
|
| 978 |
+
def start(self):
|
| 979 |
+
_start(self._state)
|
| 980 |
+
|
| 981 |
+
def wait_for_termination(self, timeout=None):
|
| 982 |
+
# NOTE(https://bugs.python.org/issue35935)
|
| 983 |
+
# Remove this workaround once threading.Event.wait() is working with
|
| 984 |
+
# CTRL+C across platforms.
|
| 985 |
+
return _common.wait(self._state.termination_event.wait,
|
| 986 |
+
self._state.termination_event.is_set,
|
| 987 |
+
timeout=timeout)
|
| 988 |
+
|
| 989 |
+
def stop(self, grace):
|
| 990 |
+
return _stop(self._state, grace)
|
| 991 |
+
|
| 992 |
+
def __del__(self):
|
| 993 |
+
if hasattr(self, '_state'):
|
| 994 |
+
# We can not grab a lock in __del__(), so set a flag to signal the
|
| 995 |
+
# serving daemon thread (if it exists) to initiate shutdown.
|
| 996 |
+
self._state.server_deallocated = True
|
| 997 |
+
|
| 998 |
+
|
| 999 |
+
def create_server(thread_pool, generic_rpc_handlers, interceptors, options,
|
| 1000 |
+
maximum_concurrent_rpcs, compression, xds):
|
| 1001 |
+
_validate_generic_rpc_handlers(generic_rpc_handlers)
|
| 1002 |
+
return _Server(thread_pool, generic_rpc_handlers, interceptors, options,
|
| 1003 |
+
maximum_concurrent_rpcs, compression, xds)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/grpc/_simple_stubs.py
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2020 The gRPC authors.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
"""Functions that obviate explicit stubs and explicit channels."""
|
| 15 |
+
|
| 16 |
+
import collections
|
| 17 |
+
import datetime
|
| 18 |
+
import logging
|
| 19 |
+
import os
|
| 20 |
+
import threading
|
| 21 |
+
from typing import (Any, AnyStr, Callable, Dict, Iterator, Optional, Sequence,
|
| 22 |
+
Tuple, TypeVar, Union)
|
| 23 |
+
|
| 24 |
+
import grpc
|
| 25 |
+
from grpc.experimental import experimental_api
|
| 26 |
+
|
| 27 |
+
RequestType = TypeVar('RequestType')
|
| 28 |
+
ResponseType = TypeVar('ResponseType')
|
| 29 |
+
|
| 30 |
+
OptionsType = Sequence[Tuple[str, str]]
|
| 31 |
+
CacheKey = Tuple[str, OptionsType, Optional[grpc.ChannelCredentials],
|
| 32 |
+
Optional[grpc.Compression]]
|
| 33 |
+
|
| 34 |
+
_LOGGER = logging.getLogger(__name__)
|
| 35 |
+
|
| 36 |
+
_EVICTION_PERIOD_KEY = "GRPC_PYTHON_MANAGED_CHANNEL_EVICTION_SECONDS"
|
| 37 |
+
if _EVICTION_PERIOD_KEY in os.environ:
|
| 38 |
+
_EVICTION_PERIOD = datetime.timedelta(
|
| 39 |
+
seconds=float(os.environ[_EVICTION_PERIOD_KEY]))
|
| 40 |
+
_LOGGER.debug("Setting managed channel eviction period to %s",
|
| 41 |
+
_EVICTION_PERIOD)
|
| 42 |
+
else:
|
| 43 |
+
_EVICTION_PERIOD = datetime.timedelta(minutes=10)
|
| 44 |
+
|
| 45 |
+
_MAXIMUM_CHANNELS_KEY = "GRPC_PYTHON_MANAGED_CHANNEL_MAXIMUM"
|
| 46 |
+
if _MAXIMUM_CHANNELS_KEY in os.environ:
|
| 47 |
+
_MAXIMUM_CHANNELS = int(os.environ[_MAXIMUM_CHANNELS_KEY])
|
| 48 |
+
_LOGGER.debug("Setting maximum managed channels to %d", _MAXIMUM_CHANNELS)
|
| 49 |
+
else:
|
| 50 |
+
_MAXIMUM_CHANNELS = 2**8
|
| 51 |
+
|
| 52 |
+
_DEFAULT_TIMEOUT_KEY = "GRPC_PYTHON_DEFAULT_TIMEOUT_SECONDS"
|
| 53 |
+
if _DEFAULT_TIMEOUT_KEY in os.environ:
|
| 54 |
+
_DEFAULT_TIMEOUT = float(os.environ[_DEFAULT_TIMEOUT_KEY])
|
| 55 |
+
_LOGGER.debug("Setting default timeout seconds to %f", _DEFAULT_TIMEOUT)
|
| 56 |
+
else:
|
| 57 |
+
_DEFAULT_TIMEOUT = 60.0
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def _create_channel(target: str, options: Sequence[Tuple[str, str]],
|
| 61 |
+
channel_credentials: Optional[grpc.ChannelCredentials],
|
| 62 |
+
compression: Optional[grpc.Compression]) -> grpc.Channel:
|
| 63 |
+
_LOGGER.debug(
|
| 64 |
+
f"Creating secure channel with credentials '{channel_credentials}', " +
|
| 65 |
+
f"options '{options}' and compression '{compression}'")
|
| 66 |
+
return grpc.secure_channel(target,
|
| 67 |
+
credentials=channel_credentials,
|
| 68 |
+
options=options,
|
| 69 |
+
compression=compression)
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class ChannelCache:
|
| 73 |
+
# NOTE(rbellevi): Untyped due to reference cycle.
|
| 74 |
+
_singleton = None
|
| 75 |
+
_lock: threading.RLock = threading.RLock()
|
| 76 |
+
_condition: threading.Condition = threading.Condition(lock=_lock)
|
| 77 |
+
_eviction_ready: threading.Event = threading.Event()
|
| 78 |
+
|
| 79 |
+
_mapping: Dict[CacheKey, Tuple[grpc.Channel, datetime.datetime]]
|
| 80 |
+
_eviction_thread: threading.Thread
|
| 81 |
+
|
| 82 |
+
def __init__(self):
|
| 83 |
+
self._mapping = collections.OrderedDict()
|
| 84 |
+
self._eviction_thread = threading.Thread(
|
| 85 |
+
target=ChannelCache._perform_evictions, daemon=True)
|
| 86 |
+
self._eviction_thread.start()
|
| 87 |
+
|
| 88 |
+
@staticmethod
|
| 89 |
+
def get():
|
| 90 |
+
with ChannelCache._lock:
|
| 91 |
+
if ChannelCache._singleton is None:
|
| 92 |
+
ChannelCache._singleton = ChannelCache()
|
| 93 |
+
ChannelCache._eviction_ready.wait()
|
| 94 |
+
return ChannelCache._singleton
|
| 95 |
+
|
| 96 |
+
def _evict_locked(self, key: CacheKey):
|
| 97 |
+
channel, _ = self._mapping.pop(key)
|
| 98 |
+
_LOGGER.debug("Evicting channel %s with configuration %s.", channel,
|
| 99 |
+
key)
|
| 100 |
+
channel.close()
|
| 101 |
+
del channel
|
| 102 |
+
|
| 103 |
+
@staticmethod
|
| 104 |
+
def _perform_evictions():
|
| 105 |
+
while True:
|
| 106 |
+
with ChannelCache._lock:
|
| 107 |
+
ChannelCache._eviction_ready.set()
|
| 108 |
+
if not ChannelCache._singleton._mapping:
|
| 109 |
+
ChannelCache._condition.wait()
|
| 110 |
+
elif len(ChannelCache._singleton._mapping) > _MAXIMUM_CHANNELS:
|
| 111 |
+
key = next(iter(ChannelCache._singleton._mapping.keys()))
|
| 112 |
+
ChannelCache._singleton._evict_locked(key)
|
| 113 |
+
# And immediately reevaluate.
|
| 114 |
+
else:
|
| 115 |
+
key, (_, eviction_time) = next(
|
| 116 |
+
iter(ChannelCache._singleton._mapping.items()))
|
| 117 |
+
now = datetime.datetime.now()
|
| 118 |
+
if eviction_time <= now:
|
| 119 |
+
ChannelCache._singleton._evict_locked(key)
|
| 120 |
+
continue
|
| 121 |
+
else:
|
| 122 |
+
time_to_eviction = (eviction_time - now).total_seconds()
|
| 123 |
+
# NOTE: We aim to *eventually* coalesce to a state in
|
| 124 |
+
# which no overdue channels are in the cache and the
|
| 125 |
+
# length of the cache is longer than _MAXIMUM_CHANNELS.
|
| 126 |
+
# We tolerate momentary states in which these two
|
| 127 |
+
# criteria are not met.
|
| 128 |
+
ChannelCache._condition.wait(timeout=time_to_eviction)
|
| 129 |
+
|
| 130 |
+
def get_channel(self, target: str, options: Sequence[Tuple[str, str]],
|
| 131 |
+
channel_credentials: Optional[grpc.ChannelCredentials],
|
| 132 |
+
insecure: bool,
|
| 133 |
+
compression: Optional[grpc.Compression]) -> grpc.Channel:
|
| 134 |
+
if insecure and channel_credentials:
|
| 135 |
+
raise ValueError("The insecure option is mutually exclusive with " +
|
| 136 |
+
"the channel_credentials option. Please use one " +
|
| 137 |
+
"or the other.")
|
| 138 |
+
if insecure:
|
| 139 |
+
channel_credentials = grpc.experimental.insecure_channel_credentials(
|
| 140 |
+
)
|
| 141 |
+
elif channel_credentials is None:
|
| 142 |
+
_LOGGER.debug("Defaulting to SSL channel credentials.")
|
| 143 |
+
channel_credentials = grpc.ssl_channel_credentials()
|
| 144 |
+
key = (target, options, channel_credentials, compression)
|
| 145 |
+
with self._lock:
|
| 146 |
+
channel_data = self._mapping.get(key, None)
|
| 147 |
+
if channel_data is not None:
|
| 148 |
+
channel = channel_data[0]
|
| 149 |
+
self._mapping.pop(key)
|
| 150 |
+
self._mapping[key] = (channel, datetime.datetime.now() +
|
| 151 |
+
_EVICTION_PERIOD)
|
| 152 |
+
return channel
|
| 153 |
+
else:
|
| 154 |
+
channel = _create_channel(target, options, channel_credentials,
|
| 155 |
+
compression)
|
| 156 |
+
self._mapping[key] = (channel, datetime.datetime.now() +
|
| 157 |
+
_EVICTION_PERIOD)
|
| 158 |
+
if len(self._mapping) == 1 or len(
|
| 159 |
+
self._mapping) >= _MAXIMUM_CHANNELS:
|
| 160 |
+
self._condition.notify()
|
| 161 |
+
return channel
|
| 162 |
+
|
| 163 |
+
def _test_only_channel_count(self) -> int:
|
| 164 |
+
with self._lock:
|
| 165 |
+
return len(self._mapping)
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
@experimental_api
|
| 169 |
+
def unary_unary(
|
| 170 |
+
request: RequestType,
|
| 171 |
+
target: str,
|
| 172 |
+
method: str,
|
| 173 |
+
request_serializer: Optional[Callable[[Any], bytes]] = None,
|
| 174 |
+
response_deserializer: Optional[Callable[[bytes], Any]] = None,
|
| 175 |
+
options: Sequence[Tuple[AnyStr, AnyStr]] = (),
|
| 176 |
+
channel_credentials: Optional[grpc.ChannelCredentials] = None,
|
| 177 |
+
insecure: bool = False,
|
| 178 |
+
call_credentials: Optional[grpc.CallCredentials] = None,
|
| 179 |
+
compression: Optional[grpc.Compression] = None,
|
| 180 |
+
wait_for_ready: Optional[bool] = None,
|
| 181 |
+
timeout: Optional[float] = _DEFAULT_TIMEOUT,
|
| 182 |
+
metadata: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None
|
| 183 |
+
) -> ResponseType:
|
| 184 |
+
"""Invokes a unary-unary RPC without an explicitly specified channel.
|
| 185 |
+
|
| 186 |
+
THIS IS AN EXPERIMENTAL API.
|
| 187 |
+
|
| 188 |
+
This is backed by a per-process cache of channels. Channels are evicted
|
| 189 |
+
from the cache after a fixed period by a background. Channels will also be
|
| 190 |
+
evicted if more than a configured maximum accumulate.
|
| 191 |
+
|
| 192 |
+
The default eviction period is 10 minutes. One may set the environment
|
| 193 |
+
variable "GRPC_PYTHON_MANAGED_CHANNEL_EVICTION_SECONDS" to configure this.
|
| 194 |
+
|
| 195 |
+
The default maximum number of channels is 256. One may set the
|
| 196 |
+
environment variable "GRPC_PYTHON_MANAGED_CHANNEL_MAXIMUM" to configure
|
| 197 |
+
this.
|
| 198 |
+
|
| 199 |
+
Args:
|
| 200 |
+
request: An iterator that yields request values for the RPC.
|
| 201 |
+
target: The server address.
|
| 202 |
+
method: The name of the RPC method.
|
| 203 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 204 |
+
message. Request goes unserialized in case None is passed.
|
| 205 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the response
|
| 206 |
+
message. Response goes undeserialized in case None is passed.
|
| 207 |
+
options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
|
| 208 |
+
runtime) to configure the channel.
|
| 209 |
+
channel_credentials: A credential applied to the whole channel, e.g. the
|
| 210 |
+
return value of grpc.ssl_channel_credentials() or
|
| 211 |
+
grpc.insecure_channel_credentials().
|
| 212 |
+
insecure: If True, specifies channel_credentials as
|
| 213 |
+
:term:`grpc.insecure_channel_credentials()`. This option is mutually
|
| 214 |
+
exclusive with the `channel_credentials` option.
|
| 215 |
+
call_credentials: A call credential applied to each call individually,
|
| 216 |
+
e.g. the output of grpc.metadata_call_credentials() or
|
| 217 |
+
grpc.access_token_call_credentials().
|
| 218 |
+
compression: An optional value indicating the compression method to be
|
| 219 |
+
used over the lifetime of the channel, e.g. grpc.Compression.Gzip.
|
| 220 |
+
wait_for_ready: An optional flag indicating whether the RPC should fail
|
| 221 |
+
immediately if the connection is not ready at the time the RPC is
|
| 222 |
+
invoked, or if it should wait until the connection to the server
|
| 223 |
+
becomes ready. When using this option, the user will likely also want
|
| 224 |
+
to set a timeout. Defaults to True.
|
| 225 |
+
timeout: An optional duration of time in seconds to allow for the RPC,
|
| 226 |
+
after which an exception will be raised. If timeout is unspecified,
|
| 227 |
+
defaults to a timeout controlled by the
|
| 228 |
+
GRPC_PYTHON_DEFAULT_TIMEOUT_SECONDS environment variable. If that is
|
| 229 |
+
unset, defaults to 60 seconds. Supply a value of None to indicate that
|
| 230 |
+
no timeout should be enforced.
|
| 231 |
+
metadata: Optional metadata to send to the server.
|
| 232 |
+
|
| 233 |
+
Returns:
|
| 234 |
+
The response to the RPC.
|
| 235 |
+
"""
|
| 236 |
+
channel = ChannelCache.get().get_channel(target, options,
|
| 237 |
+
channel_credentials, insecure,
|
| 238 |
+
compression)
|
| 239 |
+
multicallable = channel.unary_unary(method, request_serializer,
|
| 240 |
+
response_deserializer)
|
| 241 |
+
wait_for_ready = wait_for_ready if wait_for_ready is not None else True
|
| 242 |
+
return multicallable(request,
|
| 243 |
+
metadata=metadata,
|
| 244 |
+
wait_for_ready=wait_for_ready,
|
| 245 |
+
credentials=call_credentials,
|
| 246 |
+
timeout=timeout)
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
@experimental_api
|
| 250 |
+
def unary_stream(
|
| 251 |
+
request: RequestType,
|
| 252 |
+
target: str,
|
| 253 |
+
method: str,
|
| 254 |
+
request_serializer: Optional[Callable[[Any], bytes]] = None,
|
| 255 |
+
response_deserializer: Optional[Callable[[bytes], Any]] = None,
|
| 256 |
+
options: Sequence[Tuple[AnyStr, AnyStr]] = (),
|
| 257 |
+
channel_credentials: Optional[grpc.ChannelCredentials] = None,
|
| 258 |
+
insecure: bool = False,
|
| 259 |
+
call_credentials: Optional[grpc.CallCredentials] = None,
|
| 260 |
+
compression: Optional[grpc.Compression] = None,
|
| 261 |
+
wait_for_ready: Optional[bool] = None,
|
| 262 |
+
timeout: Optional[float] = _DEFAULT_TIMEOUT,
|
| 263 |
+
metadata: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None
|
| 264 |
+
) -> Iterator[ResponseType]:
|
| 265 |
+
"""Invokes a unary-stream RPC without an explicitly specified channel.
|
| 266 |
+
|
| 267 |
+
THIS IS AN EXPERIMENTAL API.
|
| 268 |
+
|
| 269 |
+
This is backed by a per-process cache of channels. Channels are evicted
|
| 270 |
+
from the cache after a fixed period by a background. Channels will also be
|
| 271 |
+
evicted if more than a configured maximum accumulate.
|
| 272 |
+
|
| 273 |
+
The default eviction period is 10 minutes. One may set the environment
|
| 274 |
+
variable "GRPC_PYTHON_MANAGED_CHANNEL_EVICTION_SECONDS" to configure this.
|
| 275 |
+
|
| 276 |
+
The default maximum number of channels is 256. One may set the
|
| 277 |
+
environment variable "GRPC_PYTHON_MANAGED_CHANNEL_MAXIMUM" to configure
|
| 278 |
+
this.
|
| 279 |
+
|
| 280 |
+
Args:
|
| 281 |
+
request: An iterator that yields request values for the RPC.
|
| 282 |
+
target: The server address.
|
| 283 |
+
method: The name of the RPC method.
|
| 284 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 285 |
+
message. Request goes unserialized in case None is passed.
|
| 286 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the response
|
| 287 |
+
message. Response goes undeserialized in case None is passed.
|
| 288 |
+
options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
|
| 289 |
+
runtime) to configure the channel.
|
| 290 |
+
channel_credentials: A credential applied to the whole channel, e.g. the
|
| 291 |
+
return value of grpc.ssl_channel_credentials().
|
| 292 |
+
insecure: If True, specifies channel_credentials as
|
| 293 |
+
:term:`grpc.insecure_channel_credentials()`. This option is mutually
|
| 294 |
+
exclusive with the `channel_credentials` option.
|
| 295 |
+
call_credentials: A call credential applied to each call individually,
|
| 296 |
+
e.g. the output of grpc.metadata_call_credentials() or
|
| 297 |
+
grpc.access_token_call_credentials().
|
| 298 |
+
compression: An optional value indicating the compression method to be
|
| 299 |
+
used over the lifetime of the channel, e.g. grpc.Compression.Gzip.
|
| 300 |
+
wait_for_ready: An optional flag indicating whether the RPC should fail
|
| 301 |
+
immediately if the connection is not ready at the time the RPC is
|
| 302 |
+
invoked, or if it should wait until the connection to the server
|
| 303 |
+
becomes ready. When using this option, the user will likely also want
|
| 304 |
+
to set a timeout. Defaults to True.
|
| 305 |
+
timeout: An optional duration of time in seconds to allow for the RPC,
|
| 306 |
+
after which an exception will be raised. If timeout is unspecified,
|
| 307 |
+
defaults to a timeout controlled by the
|
| 308 |
+
GRPC_PYTHON_DEFAULT_TIMEOUT_SECONDS environment variable. If that is
|
| 309 |
+
unset, defaults to 60 seconds. Supply a value of None to indicate that
|
| 310 |
+
no timeout should be enforced.
|
| 311 |
+
metadata: Optional metadata to send to the server.
|
| 312 |
+
|
| 313 |
+
Returns:
|
| 314 |
+
An iterator of responses.
|
| 315 |
+
"""
|
| 316 |
+
channel = ChannelCache.get().get_channel(target, options,
|
| 317 |
+
channel_credentials, insecure,
|
| 318 |
+
compression)
|
| 319 |
+
multicallable = channel.unary_stream(method, request_serializer,
|
| 320 |
+
response_deserializer)
|
| 321 |
+
wait_for_ready = wait_for_ready if wait_for_ready is not None else True
|
| 322 |
+
return multicallable(request,
|
| 323 |
+
metadata=metadata,
|
| 324 |
+
wait_for_ready=wait_for_ready,
|
| 325 |
+
credentials=call_credentials,
|
| 326 |
+
timeout=timeout)
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
@experimental_api
|
| 330 |
+
def stream_unary(
|
| 331 |
+
request_iterator: Iterator[RequestType],
|
| 332 |
+
target: str,
|
| 333 |
+
method: str,
|
| 334 |
+
request_serializer: Optional[Callable[[Any], bytes]] = None,
|
| 335 |
+
response_deserializer: Optional[Callable[[bytes], Any]] = None,
|
| 336 |
+
options: Sequence[Tuple[AnyStr, AnyStr]] = (),
|
| 337 |
+
channel_credentials: Optional[grpc.ChannelCredentials] = None,
|
| 338 |
+
insecure: bool = False,
|
| 339 |
+
call_credentials: Optional[grpc.CallCredentials] = None,
|
| 340 |
+
compression: Optional[grpc.Compression] = None,
|
| 341 |
+
wait_for_ready: Optional[bool] = None,
|
| 342 |
+
timeout: Optional[float] = _DEFAULT_TIMEOUT,
|
| 343 |
+
metadata: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None
|
| 344 |
+
) -> ResponseType:
|
| 345 |
+
"""Invokes a stream-unary RPC without an explicitly specified channel.
|
| 346 |
+
|
| 347 |
+
THIS IS AN EXPERIMENTAL API.
|
| 348 |
+
|
| 349 |
+
This is backed by a per-process cache of channels. Channels are evicted
|
| 350 |
+
from the cache after a fixed period by a background. Channels will also be
|
| 351 |
+
evicted if more than a configured maximum accumulate.
|
| 352 |
+
|
| 353 |
+
The default eviction period is 10 minutes. One may set the environment
|
| 354 |
+
variable "GRPC_PYTHON_MANAGED_CHANNEL_EVICTION_SECONDS" to configure this.
|
| 355 |
+
|
| 356 |
+
The default maximum number of channels is 256. One may set the
|
| 357 |
+
environment variable "GRPC_PYTHON_MANAGED_CHANNEL_MAXIMUM" to configure
|
| 358 |
+
this.
|
| 359 |
+
|
| 360 |
+
Args:
|
| 361 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 362 |
+
target: The server address.
|
| 363 |
+
method: The name of the RPC method.
|
| 364 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 365 |
+
message. Request goes unserialized in case None is passed.
|
| 366 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the response
|
| 367 |
+
message. Response goes undeserialized in case None is passed.
|
| 368 |
+
options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
|
| 369 |
+
runtime) to configure the channel.
|
| 370 |
+
channel_credentials: A credential applied to the whole channel, e.g. the
|
| 371 |
+
return value of grpc.ssl_channel_credentials().
|
| 372 |
+
call_credentials: A call credential applied to each call individually,
|
| 373 |
+
e.g. the output of grpc.metadata_call_credentials() or
|
| 374 |
+
grpc.access_token_call_credentials().
|
| 375 |
+
insecure: If True, specifies channel_credentials as
|
| 376 |
+
:term:`grpc.insecure_channel_credentials()`. This option is mutually
|
| 377 |
+
exclusive with the `channel_credentials` option.
|
| 378 |
+
compression: An optional value indicating the compression method to be
|
| 379 |
+
used over the lifetime of the channel, e.g. grpc.Compression.Gzip.
|
| 380 |
+
wait_for_ready: An optional flag indicating whether the RPC should fail
|
| 381 |
+
immediately if the connection is not ready at the time the RPC is
|
| 382 |
+
invoked, or if it should wait until the connection to the server
|
| 383 |
+
becomes ready. When using this option, the user will likely also want
|
| 384 |
+
to set a timeout. Defaults to True.
|
| 385 |
+
timeout: An optional duration of time in seconds to allow for the RPC,
|
| 386 |
+
after which an exception will be raised. If timeout is unspecified,
|
| 387 |
+
defaults to a timeout controlled by the
|
| 388 |
+
GRPC_PYTHON_DEFAULT_TIMEOUT_SECONDS environment variable. If that is
|
| 389 |
+
unset, defaults to 60 seconds. Supply a value of None to indicate that
|
| 390 |
+
no timeout should be enforced.
|
| 391 |
+
metadata: Optional metadata to send to the server.
|
| 392 |
+
|
| 393 |
+
Returns:
|
| 394 |
+
The response to the RPC.
|
| 395 |
+
"""
|
| 396 |
+
channel = ChannelCache.get().get_channel(target, options,
|
| 397 |
+
channel_credentials, insecure,
|
| 398 |
+
compression)
|
| 399 |
+
multicallable = channel.stream_unary(method, request_serializer,
|
| 400 |
+
response_deserializer)
|
| 401 |
+
wait_for_ready = wait_for_ready if wait_for_ready is not None else True
|
| 402 |
+
return multicallable(request_iterator,
|
| 403 |
+
metadata=metadata,
|
| 404 |
+
wait_for_ready=wait_for_ready,
|
| 405 |
+
credentials=call_credentials,
|
| 406 |
+
timeout=timeout)
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
@experimental_api
|
| 410 |
+
def stream_stream(
|
| 411 |
+
request_iterator: Iterator[RequestType],
|
| 412 |
+
target: str,
|
| 413 |
+
method: str,
|
| 414 |
+
request_serializer: Optional[Callable[[Any], bytes]] = None,
|
| 415 |
+
response_deserializer: Optional[Callable[[bytes], Any]] = None,
|
| 416 |
+
options: Sequence[Tuple[AnyStr, AnyStr]] = (),
|
| 417 |
+
channel_credentials: Optional[grpc.ChannelCredentials] = None,
|
| 418 |
+
insecure: bool = False,
|
| 419 |
+
call_credentials: Optional[grpc.CallCredentials] = None,
|
| 420 |
+
compression: Optional[grpc.Compression] = None,
|
| 421 |
+
wait_for_ready: Optional[bool] = None,
|
| 422 |
+
timeout: Optional[float] = _DEFAULT_TIMEOUT,
|
| 423 |
+
metadata: Optional[Sequence[Tuple[str, Union[str, bytes]]]] = None
|
| 424 |
+
) -> Iterator[ResponseType]:
|
| 425 |
+
"""Invokes a stream-stream RPC without an explicitly specified channel.
|
| 426 |
+
|
| 427 |
+
THIS IS AN EXPERIMENTAL API.
|
| 428 |
+
|
| 429 |
+
This is backed by a per-process cache of channels. Channels are evicted
|
| 430 |
+
from the cache after a fixed period by a background. Channels will also be
|
| 431 |
+
evicted if more than a configured maximum accumulate.
|
| 432 |
+
|
| 433 |
+
The default eviction period is 10 minutes. One may set the environment
|
| 434 |
+
variable "GRPC_PYTHON_MANAGED_CHANNEL_EVICTION_SECONDS" to configure this.
|
| 435 |
+
|
| 436 |
+
The default maximum number of channels is 256. One may set the
|
| 437 |
+
environment variable "GRPC_PYTHON_MANAGED_CHANNEL_MAXIMUM" to configure
|
| 438 |
+
this.
|
| 439 |
+
|
| 440 |
+
Args:
|
| 441 |
+
request_iterator: An iterator that yields request values for the RPC.
|
| 442 |
+
target: The server address.
|
| 443 |
+
method: The name of the RPC method.
|
| 444 |
+
request_serializer: Optional :term:`serializer` for serializing the request
|
| 445 |
+
message. Request goes unserialized in case None is passed.
|
| 446 |
+
response_deserializer: Optional :term:`deserializer` for deserializing the response
|
| 447 |
+
message. Response goes undeserialized in case None is passed.
|
| 448 |
+
options: An optional list of key-value pairs (:term:`channel_arguments` in gRPC Core
|
| 449 |
+
runtime) to configure the channel.
|
| 450 |
+
channel_credentials: A credential applied to the whole channel, e.g. the
|
| 451 |
+
return value of grpc.ssl_channel_credentials().
|
| 452 |
+
call_credentials: A call credential applied to each call individually,
|
| 453 |
+
e.g. the output of grpc.metadata_call_credentials() or
|
| 454 |
+
grpc.access_token_call_credentials().
|
| 455 |
+
insecure: If True, specifies channel_credentials as
|
| 456 |
+
:term:`grpc.insecure_channel_credentials()`. This option is mutually
|
| 457 |
+
exclusive with the `channel_credentials` option.
|
| 458 |
+
compression: An optional value indicating the compression method to be
|
| 459 |
+
used over the lifetime of the channel, e.g. grpc.Compression.Gzip.
|
| 460 |
+
wait_for_ready: An optional flag indicating whether the RPC should fail
|
| 461 |
+
immediately if the connection is not ready at the time the RPC is
|
| 462 |
+
invoked, or if it should wait until the connection to the server
|
| 463 |
+
becomes ready. When using this option, the user will likely also want
|
| 464 |
+
to set a timeout. Defaults to True.
|
| 465 |
+
timeout: An optional duration of time in seconds to allow for the RPC,
|
| 466 |
+
after which an exception will be raised. If timeout is unspecified,
|
| 467 |
+
defaults to a timeout controlled by the
|
| 468 |
+
GRPC_PYTHON_DEFAULT_TIMEOUT_SECONDS environment variable. If that is
|
| 469 |
+
unset, defaults to 60 seconds. Supply a value of None to indicate that
|
| 470 |
+
no timeout should be enforced.
|
| 471 |
+
metadata: Optional metadata to send to the server.
|
| 472 |
+
|
| 473 |
+
Returns:
|
| 474 |
+
An iterator of responses.
|
| 475 |
+
"""
|
| 476 |
+
channel = ChannelCache.get().get_channel(target, options,
|
| 477 |
+
channel_credentials, insecure,
|
| 478 |
+
compression)
|
| 479 |
+
multicallable = channel.stream_stream(method, request_serializer,
|
| 480 |
+
response_deserializer)
|
| 481 |
+
wait_for_ready = wait_for_ready if wait_for_ready is not None else True
|
| 482 |
+
return multicallable(request_iterator,
|
| 483 |
+
metadata=metadata,
|
| 484 |
+
wait_for_ready=wait_for_ready,
|
| 485 |
+
credentials=call_credentials,
|
| 486 |
+
timeout=timeout)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/_impl.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any
|
| 2 |
+
|
| 3 |
+
from omegaconf import MISSING, Container, DictConfig, ListConfig, Node, ValueNode
|
| 4 |
+
from omegaconf.errors import ConfigTypeError, InterpolationToMissingValueError
|
| 5 |
+
|
| 6 |
+
from ._utils import _DEFAULT_MARKER_, _get_value
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def _resolve_container_value(cfg: Container, key: Any) -> None:
|
| 10 |
+
node = cfg._get_child(key)
|
| 11 |
+
assert isinstance(node, Node)
|
| 12 |
+
if node._is_interpolation():
|
| 13 |
+
try:
|
| 14 |
+
resolved = node._dereference_node()
|
| 15 |
+
except InterpolationToMissingValueError:
|
| 16 |
+
node._set_value(MISSING)
|
| 17 |
+
else:
|
| 18 |
+
if isinstance(resolved, Container):
|
| 19 |
+
_resolve(resolved)
|
| 20 |
+
if isinstance(resolved, Container) and isinstance(node, ValueNode):
|
| 21 |
+
cfg[key] = resolved
|
| 22 |
+
else:
|
| 23 |
+
node._set_value(_get_value(resolved))
|
| 24 |
+
else:
|
| 25 |
+
_resolve(node)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def _resolve(cfg: Node) -> Node:
|
| 29 |
+
assert isinstance(cfg, Node)
|
| 30 |
+
if cfg._is_interpolation():
|
| 31 |
+
try:
|
| 32 |
+
resolved = cfg._dereference_node()
|
| 33 |
+
except InterpolationToMissingValueError:
|
| 34 |
+
cfg._set_value(MISSING)
|
| 35 |
+
else:
|
| 36 |
+
cfg._set_value(resolved._value())
|
| 37 |
+
|
| 38 |
+
if isinstance(cfg, DictConfig):
|
| 39 |
+
for k in cfg.keys():
|
| 40 |
+
_resolve_container_value(cfg, k)
|
| 41 |
+
|
| 42 |
+
elif isinstance(cfg, ListConfig):
|
| 43 |
+
for i in range(len(cfg)):
|
| 44 |
+
_resolve_container_value(cfg, i)
|
| 45 |
+
|
| 46 |
+
return cfg
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def select_value(
|
| 50 |
+
cfg: Container,
|
| 51 |
+
key: str,
|
| 52 |
+
*,
|
| 53 |
+
default: Any = _DEFAULT_MARKER_,
|
| 54 |
+
throw_on_resolution_failure: bool = True,
|
| 55 |
+
throw_on_missing: bool = False,
|
| 56 |
+
absolute_key: bool = False,
|
| 57 |
+
) -> Any:
|
| 58 |
+
node = select_node(
|
| 59 |
+
cfg=cfg,
|
| 60 |
+
key=key,
|
| 61 |
+
throw_on_resolution_failure=throw_on_resolution_failure,
|
| 62 |
+
throw_on_missing=throw_on_missing,
|
| 63 |
+
absolute_key=absolute_key,
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
node_not_found = node is None
|
| 67 |
+
if node_not_found or node._is_missing():
|
| 68 |
+
if default is not _DEFAULT_MARKER_:
|
| 69 |
+
return default
|
| 70 |
+
else:
|
| 71 |
+
return None
|
| 72 |
+
|
| 73 |
+
return _get_value(node)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def select_node(
|
| 77 |
+
cfg: Container,
|
| 78 |
+
key: str,
|
| 79 |
+
*,
|
| 80 |
+
throw_on_resolution_failure: bool = True,
|
| 81 |
+
throw_on_missing: bool = False,
|
| 82 |
+
absolute_key: bool = False,
|
| 83 |
+
) -> Any:
|
| 84 |
+
try:
|
| 85 |
+
# for non relative keys, the interpretation can be:
|
| 86 |
+
# 1. relative to cfg
|
| 87 |
+
# 2. relative to the config root
|
| 88 |
+
# This is controlled by the absolute_key flag. By default, such keys are relative to cfg.
|
| 89 |
+
if not absolute_key and not key.startswith("."):
|
| 90 |
+
key = f".{key}"
|
| 91 |
+
|
| 92 |
+
cfg, key = cfg._resolve_key_and_root(key)
|
| 93 |
+
_root, _last_key, node = cfg._select_impl(
|
| 94 |
+
key,
|
| 95 |
+
throw_on_missing=throw_on_missing,
|
| 96 |
+
throw_on_resolution_failure=throw_on_resolution_failure,
|
| 97 |
+
)
|
| 98 |
+
except ConfigTypeError:
|
| 99 |
+
return None
|
| 100 |
+
|
| 101 |
+
return node
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/errors.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any, Optional, Type
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class OmegaConfBaseException(Exception):
|
| 5 |
+
# would ideally be typed Optional[Node]
|
| 6 |
+
parent_node: Any
|
| 7 |
+
child_node: Any
|
| 8 |
+
key: Any
|
| 9 |
+
full_key: Optional[str]
|
| 10 |
+
value: Any
|
| 11 |
+
msg: Optional[str]
|
| 12 |
+
cause: Optional[Exception]
|
| 13 |
+
object_type: Optional[Type[Any]]
|
| 14 |
+
object_type_str: Optional[str]
|
| 15 |
+
ref_type: Optional[Type[Any]]
|
| 16 |
+
ref_type_str: Optional[str]
|
| 17 |
+
|
| 18 |
+
_initialized: bool = False
|
| 19 |
+
|
| 20 |
+
def __init__(self, *_args: Any, **_kwargs: Any) -> None:
|
| 21 |
+
self.parent_node = None
|
| 22 |
+
self.child_node = None
|
| 23 |
+
self.key = None
|
| 24 |
+
self.full_key = None
|
| 25 |
+
self.value = None
|
| 26 |
+
self.msg = None
|
| 27 |
+
self.object_type = None
|
| 28 |
+
self.ref_type = None
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class MissingMandatoryValue(OmegaConfBaseException):
|
| 32 |
+
"""Thrown when a variable flagged with '???' value is accessed to
|
| 33 |
+
indicate that the value was not set"""
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class KeyValidationError(OmegaConfBaseException, ValueError):
|
| 37 |
+
"""
|
| 38 |
+
Thrown when an a key of invalid type is used
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class ValidationError(OmegaConfBaseException, ValueError):
|
| 43 |
+
"""
|
| 44 |
+
Thrown when a value fails validation
|
| 45 |
+
"""
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class UnsupportedValueType(ValidationError, ValueError):
|
| 49 |
+
"""
|
| 50 |
+
Thrown when an input value is not of supported type
|
| 51 |
+
"""
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class ReadonlyConfigError(OmegaConfBaseException):
|
| 55 |
+
"""
|
| 56 |
+
Thrown when someone tries to modify a frozen config
|
| 57 |
+
"""
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class InterpolationResolutionError(OmegaConfBaseException, ValueError):
|
| 61 |
+
"""
|
| 62 |
+
Base class for exceptions raised when resolving an interpolation.
|
| 63 |
+
"""
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
class UnsupportedInterpolationType(InterpolationResolutionError):
|
| 67 |
+
"""
|
| 68 |
+
Thrown when an attempt to use an unregistered interpolation is made
|
| 69 |
+
"""
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class InterpolationKeyError(InterpolationResolutionError):
|
| 73 |
+
"""
|
| 74 |
+
Thrown when a node does not exist when resolving an interpolation.
|
| 75 |
+
"""
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
class InterpolationToMissingValueError(InterpolationResolutionError):
|
| 79 |
+
"""
|
| 80 |
+
Thrown when a node interpolation points to a node that is set to ???.
|
| 81 |
+
"""
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
class InterpolationValidationError(InterpolationResolutionError, ValidationError):
|
| 85 |
+
"""
|
| 86 |
+
Thrown when the result of an interpolation fails the validation step.
|
| 87 |
+
"""
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
class ConfigKeyError(OmegaConfBaseException, KeyError):
|
| 91 |
+
"""
|
| 92 |
+
Thrown from DictConfig when a regular dict access would have caused a KeyError.
|
| 93 |
+
"""
|
| 94 |
+
|
| 95 |
+
msg: str
|
| 96 |
+
|
| 97 |
+
def __init__(self, msg: str) -> None:
|
| 98 |
+
super().__init__(msg)
|
| 99 |
+
self.msg = msg
|
| 100 |
+
|
| 101 |
+
def __str__(self) -> str:
|
| 102 |
+
"""
|
| 103 |
+
Workaround to nasty KeyError quirk: https://bugs.python.org/issue2651
|
| 104 |
+
"""
|
| 105 |
+
return self.msg
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
class ConfigAttributeError(OmegaConfBaseException, AttributeError):
|
| 109 |
+
"""
|
| 110 |
+
Thrown from a config object when a regular access would have caused an AttributeError.
|
| 111 |
+
"""
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
class ConfigTypeError(OmegaConfBaseException, TypeError):
|
| 115 |
+
"""
|
| 116 |
+
Thrown from a config object when a regular access would have caused a TypeError.
|
| 117 |
+
"""
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
class ConfigIndexError(OmegaConfBaseException, IndexError):
|
| 121 |
+
"""
|
| 122 |
+
Thrown from a config object when a regular access would have caused an IndexError.
|
| 123 |
+
"""
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class ConfigValueError(OmegaConfBaseException, ValueError):
|
| 127 |
+
"""
|
| 128 |
+
Thrown from a config object when a regular access would have caused a ValueError.
|
| 129 |
+
"""
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
class ConfigCycleDetectedException(OmegaConfBaseException):
|
| 133 |
+
"""
|
| 134 |
+
Thrown when a cycle is detected in the graph made by config nodes.
|
| 135 |
+
"""
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class GrammarParseError(OmegaConfBaseException):
|
| 139 |
+
"""
|
| 140 |
+
Thrown when failing to parse an expression according to the ANTLR grammar.
|
| 141 |
+
"""
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/grammar_parser.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import threading
|
| 3 |
+
from typing import Any
|
| 4 |
+
|
| 5 |
+
from antlr4 import CommonTokenStream, InputStream, ParserRuleContext
|
| 6 |
+
from antlr4.error.ErrorListener import ErrorListener
|
| 7 |
+
|
| 8 |
+
from .errors import GrammarParseError
|
| 9 |
+
|
| 10 |
+
# Import from visitor in order to check the presence of generated grammar files
|
| 11 |
+
# files in a single place.
|
| 12 |
+
from .grammar_visitor import ( # type: ignore
|
| 13 |
+
OmegaConfGrammarLexer,
|
| 14 |
+
OmegaConfGrammarParser,
|
| 15 |
+
)
|
| 16 |
+
|
| 17 |
+
# Used to cache grammar objects to avoid re-creating them on each call to `parse()`.
|
| 18 |
+
# We use a per-thread cache to make it thread-safe.
|
| 19 |
+
_grammar_cache = threading.local()
|
| 20 |
+
|
| 21 |
+
# Build regex pattern to efficiently identify typical interpolations.
|
| 22 |
+
# See test `test_match_simple_interpolation_pattern` for examples.
|
| 23 |
+
_config_key = r"[$\w]+" # foo, $0, $bar, $foo_$bar123$
|
| 24 |
+
_key_maybe_brackets = f"{_config_key}|\\[{_config_key}\\]" # foo, [foo], [$bar]
|
| 25 |
+
_node_access = f"\\.{_key_maybe_brackets}" # .foo, [foo], [$bar]
|
| 26 |
+
_node_path = f"(\\.)*({_key_maybe_brackets})({_node_access})*" # [foo].bar, .foo[bar]
|
| 27 |
+
_node_inter = f"\\${{\\s*{_node_path}\\s*}}" # node interpolation ${foo.bar}
|
| 28 |
+
_id = "[a-zA-Z_]\\w*" # foo, foo_bar, abc123
|
| 29 |
+
_resolver_name = f"({_id}(\\.{_id})*)?" # foo, ns.bar3, ns_1.ns_2.b0z
|
| 30 |
+
_arg = r"[a-zA-Z_0-9/\-\+.$%*@?|]+" # string representing a resolver argument
|
| 31 |
+
_args = f"{_arg}(\\s*,\\s*{_arg})*" # list of resolver arguments
|
| 32 |
+
_resolver_inter = f"\\${{\\s*{_resolver_name}\\s*:\\s*{_args}?\\s*}}" # ${foo:bar}
|
| 33 |
+
_inter = f"({_node_inter}|{_resolver_inter})" # any kind of interpolation
|
| 34 |
+
_outer = "([^$]|\\$(?!{))+" # any character except $ (unless not followed by {)
|
| 35 |
+
SIMPLE_INTERPOLATION_PATTERN = re.compile(
|
| 36 |
+
f"({_outer})?({_inter}({_outer})?)+$", flags=re.ASCII
|
| 37 |
+
)
|
| 38 |
+
# NOTE: SIMPLE_INTERPOLATION_PATTERN must not generate false positive matches:
|
| 39 |
+
# it must not accept anything that isn't a valid interpolation (per the
|
| 40 |
+
# interpolation grammar defined in `omegaconf/grammar/*.g4`).
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
class OmegaConfErrorListener(ErrorListener): # type: ignore
|
| 44 |
+
def syntaxError(
|
| 45 |
+
self,
|
| 46 |
+
recognizer: Any,
|
| 47 |
+
offending_symbol: Any,
|
| 48 |
+
line: Any,
|
| 49 |
+
column: Any,
|
| 50 |
+
msg: Any,
|
| 51 |
+
e: Any,
|
| 52 |
+
) -> None:
|
| 53 |
+
raise GrammarParseError(str(e) if msg is None else msg) from e
|
| 54 |
+
|
| 55 |
+
def reportAmbiguity(
|
| 56 |
+
self,
|
| 57 |
+
recognizer: Any,
|
| 58 |
+
dfa: Any,
|
| 59 |
+
startIndex: Any,
|
| 60 |
+
stopIndex: Any,
|
| 61 |
+
exact: Any,
|
| 62 |
+
ambigAlts: Any,
|
| 63 |
+
configs: Any,
|
| 64 |
+
) -> None:
|
| 65 |
+
raise GrammarParseError("ANTLR error: Ambiguity") # pragma: no cover
|
| 66 |
+
|
| 67 |
+
def reportAttemptingFullContext(
|
| 68 |
+
self,
|
| 69 |
+
recognizer: Any,
|
| 70 |
+
dfa: Any,
|
| 71 |
+
startIndex: Any,
|
| 72 |
+
stopIndex: Any,
|
| 73 |
+
conflictingAlts: Any,
|
| 74 |
+
configs: Any,
|
| 75 |
+
) -> None:
|
| 76 |
+
# Note: for now we raise an error to be safe. However this is mostly a
|
| 77 |
+
# performance warning, so in the future this may be relaxed if we need
|
| 78 |
+
# to change the grammar in such a way that this warning cannot be
|
| 79 |
+
# avoided (another option would be to switch to SLL parsing mode).
|
| 80 |
+
raise GrammarParseError(
|
| 81 |
+
"ANTLR error: Attempting Full Context"
|
| 82 |
+
) # pragma: no cover
|
| 83 |
+
|
| 84 |
+
def reportContextSensitivity(
|
| 85 |
+
self,
|
| 86 |
+
recognizer: Any,
|
| 87 |
+
dfa: Any,
|
| 88 |
+
startIndex: Any,
|
| 89 |
+
stopIndex: Any,
|
| 90 |
+
prediction: Any,
|
| 91 |
+
configs: Any,
|
| 92 |
+
) -> None:
|
| 93 |
+
raise GrammarParseError("ANTLR error: ContextSensitivity") # pragma: no cover
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def parse(
|
| 97 |
+
value: str, parser_rule: str = "configValue", lexer_mode: str = "DEFAULT_MODE"
|
| 98 |
+
) -> ParserRuleContext:
|
| 99 |
+
"""
|
| 100 |
+
Parse interpolated string `value` (and return the parse tree).
|
| 101 |
+
"""
|
| 102 |
+
l_mode = getattr(OmegaConfGrammarLexer, lexer_mode)
|
| 103 |
+
istream = InputStream(value)
|
| 104 |
+
|
| 105 |
+
cached = getattr(_grammar_cache, "data", None)
|
| 106 |
+
if cached is None:
|
| 107 |
+
error_listener = OmegaConfErrorListener()
|
| 108 |
+
lexer = OmegaConfGrammarLexer(istream)
|
| 109 |
+
lexer.removeErrorListeners()
|
| 110 |
+
lexer.addErrorListener(error_listener)
|
| 111 |
+
lexer.mode(l_mode)
|
| 112 |
+
token_stream = CommonTokenStream(lexer)
|
| 113 |
+
parser = OmegaConfGrammarParser(token_stream)
|
| 114 |
+
parser.removeErrorListeners()
|
| 115 |
+
parser.addErrorListener(error_listener)
|
| 116 |
+
|
| 117 |
+
# The two lines below could be enabled in the future if we decide to switch
|
| 118 |
+
# to SLL prediction mode. Warning though, it has not been fully tested yet!
|
| 119 |
+
# from antlr4 import PredictionMode
|
| 120 |
+
# parser._interp.predictionMode = PredictionMode.SLL
|
| 121 |
+
|
| 122 |
+
# Note that although the input stream `istream` is implicitly cached within
|
| 123 |
+
# the lexer, it will be replaced by a new input next time the lexer is re-used.
|
| 124 |
+
_grammar_cache.data = lexer, token_stream, parser
|
| 125 |
+
|
| 126 |
+
else:
|
| 127 |
+
lexer, token_stream, parser = cached
|
| 128 |
+
# Replace the old input stream with the new one.
|
| 129 |
+
lexer.inputStream = istream
|
| 130 |
+
# Initialize the lexer / token stream / parser to process the new input.
|
| 131 |
+
lexer.mode(l_mode)
|
| 132 |
+
token_stream.setTokenSource(lexer)
|
| 133 |
+
parser.reset()
|
| 134 |
+
|
| 135 |
+
try:
|
| 136 |
+
return getattr(parser, parser_rule)()
|
| 137 |
+
except Exception as exc:
|
| 138 |
+
if type(exc) is Exception and str(exc) == "Empty Stack":
|
| 139 |
+
# This exception is raised by antlr when trying to pop a mode while
|
| 140 |
+
# no mode has been pushed. We convert it into an `GrammarParseError`
|
| 141 |
+
# to facilitate exception handling from the caller.
|
| 142 |
+
raise GrammarParseError("Empty Stack")
|
| 143 |
+
else:
|
| 144 |
+
raise
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/omegaconf/version.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys # pragma: no cover
|
| 2 |
+
|
| 3 |
+
__version__ = "2.2.3"
|
| 4 |
+
|
| 5 |
+
msg = """OmegaConf 2.0 and above is compatible with Python 3.6 and newer.
|
| 6 |
+
You have the following options:
|
| 7 |
+
1. Upgrade to Python 3.6 or newer.
|
| 8 |
+
This is highly recommended. new features will not be added to OmegaConf 1.4.
|
| 9 |
+
2. Continue using OmegaConf 1.4:
|
| 10 |
+
You can pip install 'OmegaConf<1.5' to do that.
|
| 11 |
+
"""
|
| 12 |
+
if sys.version_info < (3, 6):
|
| 13 |
+
raise ImportError(msg) # pragma: no cover
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3114.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley with assistance from asn1ate v.0.6.0.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# TEST Company Classification Policies
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc3114.txt
|
| 13 |
+
#
|
| 14 |
+
|
| 15 |
+
from pyasn1.type import char
|
| 16 |
+
from pyasn1.type import namedval
|
| 17 |
+
from pyasn1.type import univ
|
| 18 |
+
|
| 19 |
+
from pyasn1_modules import rfc5755
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
id_smime = univ.ObjectIdentifier((1, 2, 840, 113549, 1, 9, 16, ))
|
| 23 |
+
|
| 24 |
+
id_tsp = id_smime + (7, )
|
| 25 |
+
|
| 26 |
+
id_tsp_TEST_Amoco = id_tsp + (1, )
|
| 27 |
+
|
| 28 |
+
class Amoco_SecurityClassification(univ.Integer):
|
| 29 |
+
namedValues = namedval.NamedValues(
|
| 30 |
+
('amoco-general', 6),
|
| 31 |
+
('amoco-confidential', 7),
|
| 32 |
+
('amoco-highly-confidential', 8)
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
id_tsp_TEST_Caterpillar = id_tsp + (2, )
|
| 37 |
+
|
| 38 |
+
class Caterpillar_SecurityClassification(univ.Integer):
|
| 39 |
+
namedValues = namedval.NamedValues(
|
| 40 |
+
('caterpillar-public', 6),
|
| 41 |
+
('caterpillar-green', 7),
|
| 42 |
+
('caterpillar-yellow', 8),
|
| 43 |
+
('caterpillar-red', 9)
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
id_tsp_TEST_Whirlpool = id_tsp + (3, )
|
| 48 |
+
|
| 49 |
+
class Whirlpool_SecurityClassification(univ.Integer):
|
| 50 |
+
namedValues = namedval.NamedValues(
|
| 51 |
+
('whirlpool-public', 6),
|
| 52 |
+
('whirlpool-internal', 7),
|
| 53 |
+
('whirlpool-confidential', 8)
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
id_tsp_TEST_Whirlpool_Categories = id_tsp + (4, )
|
| 58 |
+
|
| 59 |
+
class SecurityCategoryValues(univ.SequenceOf):
|
| 60 |
+
componentType = char.UTF8String()
|
| 61 |
+
|
| 62 |
+
# Example SecurityCategoryValues: "LAW DEPARTMENT USE ONLY"
|
| 63 |
+
# Example SecurityCategoryValues: "HUMAN RESOURCES USE ONLY"
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# Also, the privacy mark in the security label can contain a string,
|
| 67 |
+
# such as: "ATTORNEY-CLIENT PRIVILEGED INFORMATION"
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
# Map of security category type OIDs to security category added
|
| 71 |
+
# to the ones that are in rfc5755.py
|
| 72 |
+
|
| 73 |
+
_securityCategoryMapUpdate = {
|
| 74 |
+
id_tsp_TEST_Whirlpool_Categories: SecurityCategoryValues(),
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
rfc5755.securityCategoryMap.update(_securityCategoryMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3281.py
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
#
|
| 3 |
+
# This file is part of pyasn1-modules software.
|
| 4 |
+
#
|
| 5 |
+
# Created by Stanisław Pitucha with asn1ate tool.
|
| 6 |
+
# Copyright (c) 2005-2019, Ilya Etingof <etingof@gmail.com>
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# An Internet Attribute Certificate Profile for Authorization
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# http://www.ietf.org/rfc/rfc3281.txt
|
| 13 |
+
#
|
| 14 |
+
from pyasn1.type import char
|
| 15 |
+
from pyasn1.type import constraint
|
| 16 |
+
from pyasn1.type import namedtype
|
| 17 |
+
from pyasn1.type import namedval
|
| 18 |
+
from pyasn1.type import tag
|
| 19 |
+
from pyasn1.type import univ
|
| 20 |
+
from pyasn1.type import useful
|
| 21 |
+
|
| 22 |
+
from pyasn1_modules import rfc3280
|
| 23 |
+
|
| 24 |
+
MAX = float('inf')
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def _buildOid(*components):
|
| 28 |
+
output = []
|
| 29 |
+
for x in tuple(components):
|
| 30 |
+
if isinstance(x, univ.ObjectIdentifier):
|
| 31 |
+
output.extend(list(x))
|
| 32 |
+
else:
|
| 33 |
+
output.append(int(x))
|
| 34 |
+
|
| 35 |
+
return univ.ObjectIdentifier(output)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
class ObjectDigestInfo(univ.Sequence):
|
| 39 |
+
pass
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
ObjectDigestInfo.componentType = namedtype.NamedTypes(
|
| 43 |
+
namedtype.NamedType('digestedObjectType', univ.Enumerated(
|
| 44 |
+
namedValues=namedval.NamedValues(('publicKey', 0), ('publicKeyCert', 1), ('otherObjectTypes', 2)))),
|
| 45 |
+
namedtype.OptionalNamedType('otherObjectTypeID', univ.ObjectIdentifier()),
|
| 46 |
+
namedtype.NamedType('digestAlgorithm', rfc3280.AlgorithmIdentifier()),
|
| 47 |
+
namedtype.NamedType('objectDigest', univ.BitString())
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
class IssuerSerial(univ.Sequence):
|
| 52 |
+
pass
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
IssuerSerial.componentType = namedtype.NamedTypes(
|
| 56 |
+
namedtype.NamedType('issuer', rfc3280.GeneralNames()),
|
| 57 |
+
namedtype.NamedType('serial', rfc3280.CertificateSerialNumber()),
|
| 58 |
+
namedtype.OptionalNamedType('issuerUID', rfc3280.UniqueIdentifier())
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class TargetCert(univ.Sequence):
|
| 63 |
+
pass
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
TargetCert.componentType = namedtype.NamedTypes(
|
| 67 |
+
namedtype.NamedType('targetCertificate', IssuerSerial()),
|
| 68 |
+
namedtype.OptionalNamedType('targetName', rfc3280.GeneralName()),
|
| 69 |
+
namedtype.OptionalNamedType('certDigestInfo', ObjectDigestInfo())
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
class Target(univ.Choice):
|
| 74 |
+
pass
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
Target.componentType = namedtype.NamedTypes(
|
| 78 |
+
namedtype.NamedType('targetName', rfc3280.GeneralName().subtype(
|
| 79 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 80 |
+
namedtype.NamedType('targetGroup', rfc3280.GeneralName().subtype(
|
| 81 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 82 |
+
namedtype.NamedType('targetCert',
|
| 83 |
+
TargetCert().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)))
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class Targets(univ.SequenceOf):
|
| 88 |
+
pass
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
Targets.componentType = Target()
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
class ProxyInfo(univ.SequenceOf):
|
| 95 |
+
pass
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
ProxyInfo.componentType = Targets()
|
| 99 |
+
|
| 100 |
+
id_at_role = _buildOid(rfc3280.id_at, 72)
|
| 101 |
+
|
| 102 |
+
id_pe_aaControls = _buildOid(rfc3280.id_pe, 6)
|
| 103 |
+
|
| 104 |
+
id_ce_targetInformation = _buildOid(rfc3280.id_ce, 55)
|
| 105 |
+
|
| 106 |
+
id_pe_ac_auditIdentity = _buildOid(rfc3280.id_pe, 4)
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
class ClassList(univ.BitString):
|
| 110 |
+
pass
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
ClassList.namedValues = namedval.NamedValues(
|
| 114 |
+
('unmarked', 0),
|
| 115 |
+
('unclassified', 1),
|
| 116 |
+
('restricted', 2),
|
| 117 |
+
('confidential', 3),
|
| 118 |
+
('secret', 4),
|
| 119 |
+
('topSecret', 5)
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
class SecurityCategory(univ.Sequence):
|
| 124 |
+
pass
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
SecurityCategory.componentType = namedtype.NamedTypes(
|
| 128 |
+
namedtype.NamedType('type', univ.ObjectIdentifier().subtype(
|
| 129 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 130 |
+
namedtype.NamedType('value', univ.Any().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class Clearance(univ.Sequence):
|
| 135 |
+
pass
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
Clearance.componentType = namedtype.NamedTypes(
|
| 139 |
+
namedtype.NamedType('policyId', univ.ObjectIdentifier().subtype(
|
| 140 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 141 |
+
namedtype.DefaultedNamedType('classList',
|
| 142 |
+
ClassList().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 143 |
+
tag.tagFormatSimple, 1)).subtype(
|
| 144 |
+
value="unclassified")),
|
| 145 |
+
namedtype.OptionalNamedType('securityCategories', univ.SetOf(componentType=SecurityCategory()).subtype(
|
| 146 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class AttCertVersion(univ.Integer):
|
| 151 |
+
pass
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
AttCertVersion.namedValues = namedval.NamedValues(
|
| 155 |
+
('v2', 1)
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
id_aca = _buildOid(rfc3280.id_pkix, 10)
|
| 159 |
+
|
| 160 |
+
id_at_clearance = _buildOid(2, 5, 1, 5, 55)
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
class AttrSpec(univ.SequenceOf):
|
| 164 |
+
pass
|
| 165 |
+
|
| 166 |
+
|
| 167 |
+
AttrSpec.componentType = univ.ObjectIdentifier()
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
class AAControls(univ.Sequence):
|
| 171 |
+
pass
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
AAControls.componentType = namedtype.NamedTypes(
|
| 175 |
+
namedtype.OptionalNamedType('pathLenConstraint',
|
| 176 |
+
univ.Integer().subtype(subtypeSpec=constraint.ValueRangeConstraint(0, MAX))),
|
| 177 |
+
namedtype.OptionalNamedType('permittedAttrs',
|
| 178 |
+
AttrSpec().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 179 |
+
namedtype.OptionalNamedType('excludedAttrs',
|
| 180 |
+
AttrSpec().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 181 |
+
namedtype.DefaultedNamedType('permitUnSpecified', univ.Boolean().subtype(value=1))
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
class AttCertValidityPeriod(univ.Sequence):
|
| 186 |
+
pass
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
AttCertValidityPeriod.componentType = namedtype.NamedTypes(
|
| 190 |
+
namedtype.NamedType('notBeforeTime', useful.GeneralizedTime()),
|
| 191 |
+
namedtype.NamedType('notAfterTime', useful.GeneralizedTime())
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
id_aca_authenticationInfo = _buildOid(id_aca, 1)
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
class V2Form(univ.Sequence):
|
| 199 |
+
pass
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
V2Form.componentType = namedtype.NamedTypes(
|
| 203 |
+
namedtype.OptionalNamedType('issuerName', rfc3280.GeneralNames()),
|
| 204 |
+
namedtype.OptionalNamedType('baseCertificateID', IssuerSerial().subtype(
|
| 205 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
|
| 206 |
+
namedtype.OptionalNamedType('objectDigestInfo', ObjectDigestInfo().subtype(
|
| 207 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
class AttCertIssuer(univ.Choice):
|
| 212 |
+
pass
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
AttCertIssuer.componentType = namedtype.NamedTypes(
|
| 216 |
+
namedtype.NamedType('v1Form', rfc3280.GeneralNames()),
|
| 217 |
+
namedtype.NamedType('v2Form',
|
| 218 |
+
V2Form().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)))
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
class Holder(univ.Sequence):
|
| 223 |
+
pass
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
Holder.componentType = namedtype.NamedTypes(
|
| 227 |
+
namedtype.OptionalNamedType('baseCertificateID', IssuerSerial().subtype(
|
| 228 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
|
| 229 |
+
namedtype.OptionalNamedType('entityName', rfc3280.GeneralNames().subtype(
|
| 230 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 231 |
+
namedtype.OptionalNamedType('objectDigestInfo', ObjectDigestInfo().subtype(
|
| 232 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2)))
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
class AttributeCertificateInfo(univ.Sequence):
|
| 237 |
+
pass
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
AttributeCertificateInfo.componentType = namedtype.NamedTypes(
|
| 241 |
+
namedtype.NamedType('version', AttCertVersion()),
|
| 242 |
+
namedtype.NamedType('holder', Holder()),
|
| 243 |
+
namedtype.NamedType('issuer', AttCertIssuer()),
|
| 244 |
+
namedtype.NamedType('signature', rfc3280.AlgorithmIdentifier()),
|
| 245 |
+
namedtype.NamedType('serialNumber', rfc3280.CertificateSerialNumber()),
|
| 246 |
+
namedtype.NamedType('attrCertValidityPeriod', AttCertValidityPeriod()),
|
| 247 |
+
namedtype.NamedType('attributes', univ.SequenceOf(componentType=rfc3280.Attribute())),
|
| 248 |
+
namedtype.OptionalNamedType('issuerUniqueID', rfc3280.UniqueIdentifier()),
|
| 249 |
+
namedtype.OptionalNamedType('extensions', rfc3280.Extensions())
|
| 250 |
+
)
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
class AttributeCertificate(univ.Sequence):
|
| 254 |
+
pass
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
AttributeCertificate.componentType = namedtype.NamedTypes(
|
| 258 |
+
namedtype.NamedType('acinfo', AttributeCertificateInfo()),
|
| 259 |
+
namedtype.NamedType('signatureAlgorithm', rfc3280.AlgorithmIdentifier()),
|
| 260 |
+
namedtype.NamedType('signatureValue', univ.BitString())
|
| 261 |
+
)
|
| 262 |
+
|
| 263 |
+
id_mod = _buildOid(rfc3280.id_pkix, 0)
|
| 264 |
+
|
| 265 |
+
id_mod_attribute_cert = _buildOid(id_mod, 12)
|
| 266 |
+
|
| 267 |
+
id_aca_accessIdentity = _buildOid(id_aca, 2)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
class RoleSyntax(univ.Sequence):
|
| 271 |
+
pass
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
RoleSyntax.componentType = namedtype.NamedTypes(
|
| 275 |
+
namedtype.OptionalNamedType('roleAuthority', rfc3280.GeneralNames().subtype(
|
| 276 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 277 |
+
namedtype.NamedType('roleName',
|
| 278 |
+
rfc3280.GeneralName().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
|
| 279 |
+
)
|
| 280 |
+
|
| 281 |
+
id_aca_chargingIdentity = _buildOid(id_aca, 3)
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
class ACClearAttrs(univ.Sequence):
|
| 285 |
+
pass
|
| 286 |
+
|
| 287 |
+
|
| 288 |
+
ACClearAttrs.componentType = namedtype.NamedTypes(
|
| 289 |
+
namedtype.NamedType('acIssuer', rfc3280.GeneralName()),
|
| 290 |
+
namedtype.NamedType('acSerial', univ.Integer()),
|
| 291 |
+
namedtype.NamedType('attrs', univ.SequenceOf(componentType=rfc3280.Attribute()))
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
id_aca_group = _buildOid(id_aca, 4)
|
| 295 |
+
|
| 296 |
+
id_pe_ac_proxying = _buildOid(rfc3280.id_pe, 10)
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
class SvceAuthInfo(univ.Sequence):
|
| 300 |
+
pass
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
SvceAuthInfo.componentType = namedtype.NamedTypes(
|
| 304 |
+
namedtype.NamedType('service', rfc3280.GeneralName()),
|
| 305 |
+
namedtype.NamedType('ident', rfc3280.GeneralName()),
|
| 306 |
+
namedtype.OptionalNamedType('authInfo', univ.OctetString())
|
| 307 |
+
)
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
class IetfAttrSyntax(univ.Sequence):
|
| 311 |
+
pass
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
IetfAttrSyntax.componentType = namedtype.NamedTypes(
|
| 315 |
+
namedtype.OptionalNamedType(
|
| 316 |
+
'policyAuthority', rfc3280.GeneralNames().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))
|
| 317 |
+
),
|
| 318 |
+
namedtype.NamedType(
|
| 319 |
+
'values', univ.SequenceOf(
|
| 320 |
+
componentType=univ.Choice(
|
| 321 |
+
componentType=namedtype.NamedTypes(
|
| 322 |
+
namedtype.NamedType('octets', univ.OctetString()),
|
| 323 |
+
namedtype.NamedType('oid', univ.ObjectIdentifier()),
|
| 324 |
+
namedtype.NamedType('string', char.UTF8String())
|
| 325 |
+
)
|
| 326 |
+
)
|
| 327 |
+
)
|
| 328 |
+
)
|
| 329 |
+
)
|
| 330 |
+
|
| 331 |
+
id_aca_encAttrs = _buildOid(id_aca, 6)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc3779.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley with assistance from asn1ate v.0.6.0.
|
| 5 |
+
# Modified by Russ Housley to add maps for use with opentypes.
|
| 6 |
+
#
|
| 7 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 8 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 9 |
+
#
|
| 10 |
+
# X.509 Extensions for IP Addresses and AS Identifiers
|
| 11 |
+
#
|
| 12 |
+
# ASN.1 source from:
|
| 13 |
+
# https://www.rfc-editor.org/rfc/rfc3779.txt
|
| 14 |
+
#
|
| 15 |
+
|
| 16 |
+
from pyasn1.type import constraint
|
| 17 |
+
from pyasn1.type import namedtype
|
| 18 |
+
from pyasn1.type import tag
|
| 19 |
+
from pyasn1.type import univ
|
| 20 |
+
|
| 21 |
+
from pyasn1_modules import rfc5280
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# IP Address Delegation Extension
|
| 25 |
+
|
| 26 |
+
id_pe_ipAddrBlocks = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.7')
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class IPAddress(univ.BitString):
|
| 30 |
+
pass
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class IPAddressRange(univ.Sequence):
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
IPAddressRange.componentType = namedtype.NamedTypes(
|
| 37 |
+
namedtype.NamedType('min', IPAddress()),
|
| 38 |
+
namedtype.NamedType('max', IPAddress())
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class IPAddressOrRange(univ.Choice):
|
| 43 |
+
pass
|
| 44 |
+
|
| 45 |
+
IPAddressOrRange.componentType = namedtype.NamedTypes(
|
| 46 |
+
namedtype.NamedType('addressPrefix', IPAddress()),
|
| 47 |
+
namedtype.NamedType('addressRange', IPAddressRange())
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
class IPAddressChoice(univ.Choice):
|
| 52 |
+
pass
|
| 53 |
+
|
| 54 |
+
IPAddressChoice.componentType = namedtype.NamedTypes(
|
| 55 |
+
namedtype.NamedType('inherit', univ.Null()),
|
| 56 |
+
namedtype.NamedType('addressesOrRanges', univ.SequenceOf(
|
| 57 |
+
componentType=IPAddressOrRange())
|
| 58 |
+
)
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class IPAddressFamily(univ.Sequence):
|
| 63 |
+
pass
|
| 64 |
+
|
| 65 |
+
IPAddressFamily.componentType = namedtype.NamedTypes(
|
| 66 |
+
namedtype.NamedType('addressFamily', univ.OctetString().subtype(
|
| 67 |
+
subtypeSpec=constraint.ValueSizeConstraint(2, 3))),
|
| 68 |
+
namedtype.NamedType('ipAddressChoice', IPAddressChoice())
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
class IPAddrBlocks(univ.SequenceOf):
|
| 73 |
+
pass
|
| 74 |
+
|
| 75 |
+
IPAddrBlocks.componentType = IPAddressFamily()
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
# Autonomous System Identifier Delegation Extension
|
| 79 |
+
|
| 80 |
+
id_pe_autonomousSysIds = univ.ObjectIdentifier('1.3.6.1.5.5.7.1.8')
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class ASId(univ.Integer):
|
| 84 |
+
pass
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
class ASRange(univ.Sequence):
|
| 88 |
+
pass
|
| 89 |
+
|
| 90 |
+
ASRange.componentType = namedtype.NamedTypes(
|
| 91 |
+
namedtype.NamedType('min', ASId()),
|
| 92 |
+
namedtype.NamedType('max', ASId())
|
| 93 |
+
)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
class ASIdOrRange(univ.Choice):
|
| 97 |
+
pass
|
| 98 |
+
|
| 99 |
+
ASIdOrRange.componentType = namedtype.NamedTypes(
|
| 100 |
+
namedtype.NamedType('id', ASId()),
|
| 101 |
+
namedtype.NamedType('range', ASRange())
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
class ASIdentifierChoice(univ.Choice):
|
| 106 |
+
pass
|
| 107 |
+
|
| 108 |
+
ASIdentifierChoice.componentType = namedtype.NamedTypes(
|
| 109 |
+
namedtype.NamedType('inherit', univ.Null()),
|
| 110 |
+
namedtype.NamedType('asIdsOrRanges', univ.SequenceOf(
|
| 111 |
+
componentType=ASIdOrRange())
|
| 112 |
+
)
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class ASIdentifiers(univ.Sequence):
|
| 117 |
+
pass
|
| 118 |
+
|
| 119 |
+
ASIdentifiers.componentType = namedtype.NamedTypes(
|
| 120 |
+
namedtype.OptionalNamedType('asnum', ASIdentifierChoice().subtype(
|
| 121 |
+
explicitTag=tag.Tag(tag.tagClassContext,
|
| 122 |
+
tag.tagFormatConstructed, 0))),
|
| 123 |
+
namedtype.OptionalNamedType('rdi', ASIdentifierChoice().subtype(
|
| 124 |
+
explicitTag=tag.Tag(tag.tagClassContext,
|
| 125 |
+
tag.tagFormatConstructed, 1)))
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
# Map of Certificate Extension OIDs to Extensions is added to the
|
| 130 |
+
# ones that are in rfc5280.py
|
| 131 |
+
|
| 132 |
+
_certificateExtensionsMapUpdate = {
|
| 133 |
+
id_pe_ipAddrBlocks: IPAddrBlocks(),
|
| 134 |
+
id_pe_autonomousSysIds: ASIdentifiers(),
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
rfc5280.certificateExtensionsMap.update(_certificateExtensionsMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5917.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# Clearance Sponsor Attribute
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc5917.txt
|
| 13 |
+
# https://www.rfc-editor.org/errata/eid4558
|
| 14 |
+
# https://www.rfc-editor.org/errata/eid5883
|
| 15 |
+
#
|
| 16 |
+
|
| 17 |
+
from pyasn1.type import char
|
| 18 |
+
from pyasn1.type import constraint
|
| 19 |
+
from pyasn1.type import namedtype
|
| 20 |
+
from pyasn1.type import univ
|
| 21 |
+
|
| 22 |
+
from pyasn1_modules import rfc5280
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# DirectoryString is the same as RFC 5280, except for two things:
|
| 26 |
+
# 1. the length is limited to 64;
|
| 27 |
+
# 2. only the 'utf8String' choice remains because the ASN.1
|
| 28 |
+
# specification says: ( WITH COMPONENTS { utf8String PRESENT } )
|
| 29 |
+
|
| 30 |
+
class DirectoryString(univ.Choice):
|
| 31 |
+
componentType = namedtype.NamedTypes(
|
| 32 |
+
namedtype.NamedType('utf8String', char.UTF8String().subtype(
|
| 33 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 64))),
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Clearance Sponsor Attribute
|
| 38 |
+
|
| 39 |
+
id_clearanceSponsor = univ.ObjectIdentifier((2, 16, 840, 1, 101, 2, 1, 5, 68))
|
| 40 |
+
|
| 41 |
+
ub_clearance_sponsor = univ.Integer(64)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
at_clearanceSponsor = rfc5280.Attribute()
|
| 45 |
+
at_clearanceSponsor['type'] = id_clearanceSponsor
|
| 46 |
+
at_clearanceSponsor['values'][0] = DirectoryString()
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# Add to the map of Attribute Type OIDs to Attributes in rfc5280.py.
|
| 50 |
+
|
| 51 |
+
_certificateAttributesMapUpdate = {
|
| 52 |
+
id_clearanceSponsor: DirectoryString(),
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
rfc5280.certificateAttributesMap.update(_certificateAttributesMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5934.py
ADDED
|
@@ -0,0 +1,786 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This file is being contributed to pyasn1-modules software.
|
| 2 |
+
#
|
| 3 |
+
# Created by Russ Housley with assistance from asn1ate v.0.6.0.
|
| 4 |
+
#
|
| 5 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 6 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 7 |
+
#
|
| 8 |
+
# Trust Anchor Format
|
| 9 |
+
#
|
| 10 |
+
# ASN.1 source from:
|
| 11 |
+
# https://www.rfc-editor.org/rfc/rfc5934.txt
|
| 12 |
+
|
| 13 |
+
from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
|
| 14 |
+
|
| 15 |
+
from pyasn1_modules import rfc2985
|
| 16 |
+
from pyasn1_modules import rfc5280
|
| 17 |
+
from pyasn1_modules import rfc5652
|
| 18 |
+
from pyasn1_modules import rfc5914
|
| 19 |
+
|
| 20 |
+
MAX = float('inf')
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def _OID(*components):
|
| 24 |
+
output = []
|
| 25 |
+
for x in tuple(components):
|
| 26 |
+
if isinstance(x, univ.ObjectIdentifier):
|
| 27 |
+
output.extend(list(x))
|
| 28 |
+
else:
|
| 29 |
+
output.append(int(x))
|
| 30 |
+
return univ.ObjectIdentifier(output)
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Imports from RFC 2985
|
| 34 |
+
|
| 35 |
+
SingleAttribute = rfc2985.SingleAttribute
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
# Imports from RFC5914
|
| 39 |
+
|
| 40 |
+
CertPathControls = rfc5914.CertPathControls
|
| 41 |
+
|
| 42 |
+
TrustAnchorChoice = rfc5914.TrustAnchorChoice
|
| 43 |
+
|
| 44 |
+
TrustAnchorTitle = rfc5914.TrustAnchorTitle
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# Imports from RFC 5280
|
| 48 |
+
|
| 49 |
+
AlgorithmIdentifier = rfc5280.AlgorithmIdentifier
|
| 50 |
+
|
| 51 |
+
AnotherName = rfc5280.AnotherName
|
| 52 |
+
|
| 53 |
+
Attribute = rfc5280.Attribute
|
| 54 |
+
|
| 55 |
+
Certificate = rfc5280.Certificate
|
| 56 |
+
|
| 57 |
+
CertificateSerialNumber = rfc5280.CertificateSerialNumber
|
| 58 |
+
|
| 59 |
+
Extension = rfc5280.Extension
|
| 60 |
+
|
| 61 |
+
Extensions = rfc5280.Extensions
|
| 62 |
+
|
| 63 |
+
KeyIdentifier = rfc5280.KeyIdentifier
|
| 64 |
+
|
| 65 |
+
Name = rfc5280.Name
|
| 66 |
+
|
| 67 |
+
SubjectPublicKeyInfo = rfc5280.SubjectPublicKeyInfo
|
| 68 |
+
|
| 69 |
+
TBSCertificate = rfc5280.TBSCertificate
|
| 70 |
+
|
| 71 |
+
Validity = rfc5280.Validity
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# Object Identifier Arc for TAMP Message Content Types
|
| 75 |
+
|
| 76 |
+
id_tamp = univ.ObjectIdentifier('2.16.840.1.101.2.1.2.77')
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
# TAMP Status Query Message
|
| 80 |
+
|
| 81 |
+
id_ct_TAMP_statusQuery = _OID(id_tamp, 1)
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
class TAMPVersion(univ.Integer):
|
| 85 |
+
pass
|
| 86 |
+
|
| 87 |
+
TAMPVersion.namedValues = namedval.NamedValues(
|
| 88 |
+
('v1', 1),
|
| 89 |
+
('v2', 2)
|
| 90 |
+
)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
class TerseOrVerbose(univ.Enumerated):
|
| 94 |
+
pass
|
| 95 |
+
|
| 96 |
+
TerseOrVerbose.namedValues = namedval.NamedValues(
|
| 97 |
+
('terse', 1),
|
| 98 |
+
('verbose', 2)
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
class HardwareSerialEntry(univ.Choice):
|
| 103 |
+
pass
|
| 104 |
+
|
| 105 |
+
HardwareSerialEntry.componentType = namedtype.NamedTypes(
|
| 106 |
+
namedtype.NamedType('all', univ.Null()),
|
| 107 |
+
namedtype.NamedType('single', univ.OctetString()),
|
| 108 |
+
namedtype.NamedType('block', univ.Sequence(componentType=namedtype.NamedTypes(
|
| 109 |
+
namedtype.NamedType('low', univ.OctetString()),
|
| 110 |
+
namedtype.NamedType('high', univ.OctetString())
|
| 111 |
+
))
|
| 112 |
+
)
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class HardwareModules(univ.Sequence):
|
| 117 |
+
pass
|
| 118 |
+
|
| 119 |
+
HardwareModules.componentType = namedtype.NamedTypes(
|
| 120 |
+
namedtype.NamedType('hwType', univ.ObjectIdentifier()),
|
| 121 |
+
namedtype.NamedType('hwSerialEntries', univ.SequenceOf(
|
| 122 |
+
componentType=HardwareSerialEntry()).subtype(
|
| 123 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, MAX)))
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
class HardwareModuleIdentifierList(univ.SequenceOf):
|
| 128 |
+
pass
|
| 129 |
+
|
| 130 |
+
HardwareModuleIdentifierList.componentType = HardwareModules()
|
| 131 |
+
HardwareModuleIdentifierList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class Community(univ.ObjectIdentifier):
|
| 135 |
+
pass
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
class CommunityIdentifierList(univ.SequenceOf):
|
| 139 |
+
pass
|
| 140 |
+
|
| 141 |
+
CommunityIdentifierList.componentType = Community()
|
| 142 |
+
CommunityIdentifierList.subtypeSpec=constraint.ValueSizeConstraint(0, MAX)
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
class TargetIdentifier(univ.Choice):
|
| 146 |
+
pass
|
| 147 |
+
|
| 148 |
+
TargetIdentifier.componentType = namedtype.NamedTypes(
|
| 149 |
+
namedtype.NamedType('hwModules', HardwareModuleIdentifierList().subtype(
|
| 150 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 151 |
+
namedtype.NamedType('communities', CommunityIdentifierList().subtype(
|
| 152 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
|
| 153 |
+
namedtype.NamedType('allModules', univ.Null().subtype(
|
| 154 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
|
| 155 |
+
namedtype.NamedType('uri', char.IA5String().subtype(
|
| 156 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))),
|
| 157 |
+
namedtype.NamedType('otherName', AnotherName().subtype(
|
| 158 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5)))
|
| 159 |
+
)
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
class SeqNumber(univ.Integer):
|
| 163 |
+
pass
|
| 164 |
+
|
| 165 |
+
SeqNumber.subtypeSpec = constraint.ValueRangeConstraint(0, 9223372036854775807)
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
class TAMPMsgRef(univ.Sequence):
|
| 169 |
+
pass
|
| 170 |
+
|
| 171 |
+
TAMPMsgRef.componentType = namedtype.NamedTypes(
|
| 172 |
+
namedtype.NamedType('target', TargetIdentifier()),
|
| 173 |
+
namedtype.NamedType('seqNum', SeqNumber())
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
class TAMPStatusQuery(univ.Sequence):
|
| 178 |
+
pass
|
| 179 |
+
|
| 180 |
+
TAMPStatusQuery.componentType = namedtype.NamedTypes(
|
| 181 |
+
namedtype.DefaultedNamedType('version', TAMPVersion().subtype(
|
| 182 |
+
implicitTag=tag.Tag(tag.tagClassContext,
|
| 183 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 184 |
+
namedtype.DefaultedNamedType('terse', TerseOrVerbose().subtype(
|
| 185 |
+
implicitTag=tag.Tag(tag.tagClassContext,
|
| 186 |
+
tag.tagFormatSimple, 1)).subtype(value='verbose')),
|
| 187 |
+
namedtype.NamedType('query', TAMPMsgRef())
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
tamp_status_query = rfc5652.ContentInfo()
|
| 192 |
+
tamp_status_query['contentType'] = id_ct_TAMP_statusQuery
|
| 193 |
+
tamp_status_query['content'] = TAMPStatusQuery()
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
# TAMP Status Response Message
|
| 197 |
+
|
| 198 |
+
id_ct_TAMP_statusResponse = _OID(id_tamp, 2)
|
| 199 |
+
|
| 200 |
+
|
| 201 |
+
class KeyIdentifiers(univ.SequenceOf):
|
| 202 |
+
pass
|
| 203 |
+
|
| 204 |
+
KeyIdentifiers.componentType = KeyIdentifier()
|
| 205 |
+
KeyIdentifiers.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
class TrustAnchorChoiceList(univ.SequenceOf):
|
| 209 |
+
pass
|
| 210 |
+
|
| 211 |
+
TrustAnchorChoiceList.componentType = TrustAnchorChoice()
|
| 212 |
+
TrustAnchorChoiceList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
class TAMPSequenceNumber(univ.Sequence):
|
| 216 |
+
pass
|
| 217 |
+
|
| 218 |
+
TAMPSequenceNumber.componentType = namedtype.NamedTypes(
|
| 219 |
+
namedtype.NamedType('keyId', KeyIdentifier()),
|
| 220 |
+
namedtype.NamedType('seqNumber', SeqNumber())
|
| 221 |
+
)
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
class TAMPSequenceNumbers(univ.SequenceOf):
|
| 225 |
+
pass
|
| 226 |
+
|
| 227 |
+
TAMPSequenceNumbers.componentType = TAMPSequenceNumber()
|
| 228 |
+
TAMPSequenceNumbers.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 229 |
+
|
| 230 |
+
|
| 231 |
+
class TerseStatusResponse(univ.Sequence):
|
| 232 |
+
pass
|
| 233 |
+
|
| 234 |
+
TerseStatusResponse.componentType = namedtype.NamedTypes(
|
| 235 |
+
namedtype.NamedType('taKeyIds', KeyIdentifiers()),
|
| 236 |
+
namedtype.OptionalNamedType('communities', CommunityIdentifierList())
|
| 237 |
+
)
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
class VerboseStatusResponse(univ.Sequence):
|
| 241 |
+
pass
|
| 242 |
+
|
| 243 |
+
VerboseStatusResponse.componentType = namedtype.NamedTypes(
|
| 244 |
+
namedtype.NamedType('taInfo', TrustAnchorChoiceList()),
|
| 245 |
+
namedtype.OptionalNamedType('continPubKeyDecryptAlg',
|
| 246 |
+
AlgorithmIdentifier().subtype(implicitTag=tag.Tag(
|
| 247 |
+
tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 248 |
+
namedtype.OptionalNamedType('communities',
|
| 249 |
+
CommunityIdentifierList().subtype(implicitTag=tag.Tag(
|
| 250 |
+
tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 251 |
+
namedtype.OptionalNamedType('tampSeqNumbers',
|
| 252 |
+
TAMPSequenceNumbers().subtype(implicitTag=tag.Tag(
|
| 253 |
+
tag.tagClassContext, tag.tagFormatSimple, 2)))
|
| 254 |
+
)
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
class StatusResponse(univ.Choice):
|
| 258 |
+
pass
|
| 259 |
+
|
| 260 |
+
StatusResponse.componentType = namedtype.NamedTypes(
|
| 261 |
+
namedtype.NamedType('terseResponse', TerseStatusResponse().subtype(
|
| 262 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
|
| 263 |
+
namedtype.NamedType('verboseResponse', VerboseStatusResponse().subtype(
|
| 264 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
class TAMPStatusResponse(univ.Sequence):
|
| 269 |
+
pass
|
| 270 |
+
|
| 271 |
+
TAMPStatusResponse.componentType = namedtype.NamedTypes(
|
| 272 |
+
namedtype.DefaultedNamedType('version', TAMPVersion().subtype(
|
| 273 |
+
implicitTag=tag.Tag(tag.tagClassContext,
|
| 274 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 275 |
+
namedtype.NamedType('query', TAMPMsgRef()),
|
| 276 |
+
namedtype.NamedType('response', StatusResponse()),
|
| 277 |
+
namedtype.DefaultedNamedType('usesApex', univ.Boolean().subtype(value=1))
|
| 278 |
+
)
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
tamp_status_response = rfc5652.ContentInfo()
|
| 282 |
+
tamp_status_response['contentType'] = id_ct_TAMP_statusResponse
|
| 283 |
+
tamp_status_response['content'] = TAMPStatusResponse()
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
# Trust Anchor Update Message
|
| 287 |
+
|
| 288 |
+
id_ct_TAMP_update = _OID(id_tamp, 3)
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
class TBSCertificateChangeInfo(univ.Sequence):
|
| 292 |
+
pass
|
| 293 |
+
|
| 294 |
+
TBSCertificateChangeInfo.componentType = namedtype.NamedTypes(
|
| 295 |
+
namedtype.OptionalNamedType('serialNumber', CertificateSerialNumber()),
|
| 296 |
+
namedtype.OptionalNamedType('signature', AlgorithmIdentifier().subtype(
|
| 297 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 298 |
+
namedtype.OptionalNamedType('issuer', Name().subtype(implicitTag=tag.Tag(
|
| 299 |
+
tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 300 |
+
namedtype.OptionalNamedType('validity', Validity().subtype(
|
| 301 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
|
| 302 |
+
namedtype.OptionalNamedType('subject', Name().subtype(implicitTag=tag.Tag(
|
| 303 |
+
tag.tagClassContext, tag.tagFormatSimple, 3))),
|
| 304 |
+
namedtype.NamedType('subjectPublicKeyInfo', SubjectPublicKeyInfo().subtype(
|
| 305 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))),
|
| 306 |
+
namedtype.OptionalNamedType('exts', Extensions().subtype(explicitTag=tag.Tag(
|
| 307 |
+
tag.tagClassContext, tag.tagFormatSimple, 5)))
|
| 308 |
+
)
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
class TrustAnchorChangeInfo(univ.Sequence):
|
| 312 |
+
pass
|
| 313 |
+
|
| 314 |
+
TrustAnchorChangeInfo.componentType = namedtype.NamedTypes(
|
| 315 |
+
namedtype.NamedType('pubKey', SubjectPublicKeyInfo()),
|
| 316 |
+
namedtype.OptionalNamedType('keyId', KeyIdentifier()),
|
| 317 |
+
namedtype.OptionalNamedType('taTitle', TrustAnchorTitle()),
|
| 318 |
+
namedtype.OptionalNamedType('certPath', CertPathControls()),
|
| 319 |
+
namedtype.OptionalNamedType('exts', Extensions().subtype(
|
| 320 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1)))
|
| 321 |
+
)
|
| 322 |
+
|
| 323 |
+
|
| 324 |
+
class TrustAnchorChangeInfoChoice(univ.Choice):
|
| 325 |
+
pass
|
| 326 |
+
|
| 327 |
+
TrustAnchorChangeInfoChoice.componentType = namedtype.NamedTypes(
|
| 328 |
+
namedtype.NamedType('tbsCertChange', TBSCertificateChangeInfo().subtype(
|
| 329 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
|
| 330 |
+
namedtype.NamedType('taChange', TrustAnchorChangeInfo().subtype(
|
| 331 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
|
| 332 |
+
)
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
class TrustAnchorUpdate(univ.Choice):
|
| 336 |
+
pass
|
| 337 |
+
|
| 338 |
+
TrustAnchorUpdate.componentType = namedtype.NamedTypes(
|
| 339 |
+
namedtype.NamedType('add', TrustAnchorChoice().subtype(
|
| 340 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 341 |
+
namedtype.NamedType('remove', SubjectPublicKeyInfo().subtype(
|
| 342 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
|
| 343 |
+
namedtype.NamedType('change', TrustAnchorChangeInfoChoice().subtype(
|
| 344 |
+
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3)))
|
| 345 |
+
)
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
class TAMPUpdate(univ.Sequence):
|
| 349 |
+
pass
|
| 350 |
+
|
| 351 |
+
TAMPUpdate.componentType = namedtype.NamedTypes(
|
| 352 |
+
namedtype.DefaultedNamedType('version',
|
| 353 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 354 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 355 |
+
namedtype.DefaultedNamedType('terse',
|
| 356 |
+
TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 357 |
+
tag.tagFormatSimple, 1)).subtype(value='verbose')),
|
| 358 |
+
namedtype.NamedType('msgRef', TAMPMsgRef()),
|
| 359 |
+
namedtype.NamedType('updates',
|
| 360 |
+
univ.SequenceOf(componentType=TrustAnchorUpdate()).subtype(
|
| 361 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
|
| 362 |
+
namedtype.OptionalNamedType('tampSeqNumbers',
|
| 363 |
+
TAMPSequenceNumbers().subtype(implicitTag=tag.Tag(
|
| 364 |
+
tag.tagClassContext, tag.tagFormatSimple, 2)))
|
| 365 |
+
)
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
tamp_update = rfc5652.ContentInfo()
|
| 369 |
+
tamp_update['contentType'] = id_ct_TAMP_update
|
| 370 |
+
tamp_update['content'] = TAMPUpdate()
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
# Trust Anchor Update Confirm Message
|
| 374 |
+
|
| 375 |
+
id_ct_TAMP_updateConfirm = _OID(id_tamp, 4)
|
| 376 |
+
|
| 377 |
+
|
| 378 |
+
class StatusCode(univ.Enumerated):
|
| 379 |
+
pass
|
| 380 |
+
|
| 381 |
+
StatusCode.namedValues = namedval.NamedValues(
|
| 382 |
+
('success', 0),
|
| 383 |
+
('decodeFailure', 1),
|
| 384 |
+
('badContentInfo', 2),
|
| 385 |
+
('badSignedData', 3),
|
| 386 |
+
('badEncapContent', 4),
|
| 387 |
+
('badCertificate', 5),
|
| 388 |
+
('badSignerInfo', 6),
|
| 389 |
+
('badSignedAttrs', 7),
|
| 390 |
+
('badUnsignedAttrs', 8),
|
| 391 |
+
('missingContent', 9),
|
| 392 |
+
('noTrustAnchor', 10),
|
| 393 |
+
('notAuthorized', 11),
|
| 394 |
+
('badDigestAlgorithm', 12),
|
| 395 |
+
('badSignatureAlgorithm', 13),
|
| 396 |
+
('unsupportedKeySize', 14),
|
| 397 |
+
('unsupportedParameters', 15),
|
| 398 |
+
('signatureFailure', 16),
|
| 399 |
+
('insufficientMemory', 17),
|
| 400 |
+
('unsupportedTAMPMsgType', 18),
|
| 401 |
+
('apexTAMPAnchor', 19),
|
| 402 |
+
('improperTAAddition', 20),
|
| 403 |
+
('seqNumFailure', 21),
|
| 404 |
+
('contingencyPublicKeyDecrypt', 22),
|
| 405 |
+
('incorrectTarget', 23),
|
| 406 |
+
('communityUpdateFailed', 24),
|
| 407 |
+
('trustAnchorNotFound', 25),
|
| 408 |
+
('unsupportedTAAlgorithm', 26),
|
| 409 |
+
('unsupportedTAKeySize', 27),
|
| 410 |
+
('unsupportedContinPubKeyDecryptAlg', 28),
|
| 411 |
+
('missingSignature', 29),
|
| 412 |
+
('resourcesBusy', 30),
|
| 413 |
+
('versionNumberMismatch', 31),
|
| 414 |
+
('missingPolicySet', 32),
|
| 415 |
+
('revokedCertificate', 33),
|
| 416 |
+
('unsupportedTrustAnchorFormat', 34),
|
| 417 |
+
('improperTAChange', 35),
|
| 418 |
+
('malformed', 36),
|
| 419 |
+
('cmsError', 37),
|
| 420 |
+
('unsupportedTargetIdentifier', 38),
|
| 421 |
+
('other', 127)
|
| 422 |
+
)
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
class StatusCodeList(univ.SequenceOf):
|
| 426 |
+
pass
|
| 427 |
+
|
| 428 |
+
StatusCodeList.componentType = StatusCode()
|
| 429 |
+
StatusCodeList.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 430 |
+
|
| 431 |
+
|
| 432 |
+
class TerseUpdateConfirm(StatusCodeList):
|
| 433 |
+
pass
|
| 434 |
+
|
| 435 |
+
|
| 436 |
+
class VerboseUpdateConfirm(univ.Sequence):
|
| 437 |
+
pass
|
| 438 |
+
|
| 439 |
+
VerboseUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 440 |
+
namedtype.NamedType('status', StatusCodeList()),
|
| 441 |
+
namedtype.NamedType('taInfo', TrustAnchorChoiceList()),
|
| 442 |
+
namedtype.OptionalNamedType('tampSeqNumbers', TAMPSequenceNumbers()),
|
| 443 |
+
namedtype.DefaultedNamedType('usesApex', univ.Boolean().subtype(value=1))
|
| 444 |
+
)
|
| 445 |
+
|
| 446 |
+
|
| 447 |
+
class UpdateConfirm(univ.Choice):
|
| 448 |
+
pass
|
| 449 |
+
|
| 450 |
+
UpdateConfirm.componentType = namedtype.NamedTypes(
|
| 451 |
+
namedtype.NamedType('terseConfirm', TerseUpdateConfirm().subtype(
|
| 452 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 453 |
+
namedtype.NamedType('verboseConfirm', VerboseUpdateConfirm().subtype(
|
| 454 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
|
| 455 |
+
)
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
class TAMPUpdateConfirm(univ.Sequence):
|
| 459 |
+
pass
|
| 460 |
+
|
| 461 |
+
TAMPUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 462 |
+
namedtype.DefaultedNamedType('version', TAMPVersion().subtype(
|
| 463 |
+
implicitTag=tag.Tag(tag.tagClassContext,
|
| 464 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 465 |
+
namedtype.NamedType('update', TAMPMsgRef()),
|
| 466 |
+
namedtype.NamedType('confirm', UpdateConfirm())
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
|
| 470 |
+
tamp_update_confirm = rfc5652.ContentInfo()
|
| 471 |
+
tamp_update_confirm['contentType'] = id_ct_TAMP_updateConfirm
|
| 472 |
+
tamp_update_confirm['content'] = TAMPUpdateConfirm()
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
# Apex Trust Anchor Update Message
|
| 476 |
+
|
| 477 |
+
id_ct_TAMP_apexUpdate = _OID(id_tamp, 5)
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
class TAMPApexUpdate(univ.Sequence):
|
| 481 |
+
pass
|
| 482 |
+
|
| 483 |
+
TAMPApexUpdate.componentType = namedtype.NamedTypes(
|
| 484 |
+
namedtype.DefaultedNamedType('version',
|
| 485 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 486 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 487 |
+
namedtype.DefaultedNamedType('terse',
|
| 488 |
+
TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 489 |
+
tag.tagFormatSimple, 1)).subtype(value='verbose')),
|
| 490 |
+
namedtype.NamedType('msgRef', TAMPMsgRef()),
|
| 491 |
+
namedtype.NamedType('clearTrustAnchors', univ.Boolean()),
|
| 492 |
+
namedtype.NamedType('clearCommunities', univ.Boolean()),
|
| 493 |
+
namedtype.OptionalNamedType('seqNumber', SeqNumber()),
|
| 494 |
+
namedtype.NamedType('apexTA', TrustAnchorChoice())
|
| 495 |
+
)
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
tamp_apex_update = rfc5652.ContentInfo()
|
| 499 |
+
tamp_apex_update['contentType'] = id_ct_TAMP_apexUpdate
|
| 500 |
+
tamp_apex_update['content'] = TAMPApexUpdate()
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
# Apex Trust Anchor Update Confirm Message
|
| 504 |
+
|
| 505 |
+
id_ct_TAMP_apexUpdateConfirm = _OID(id_tamp, 6)
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
class TerseApexUpdateConfirm(StatusCode):
|
| 509 |
+
pass
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
class VerboseApexUpdateConfirm(univ.Sequence):
|
| 513 |
+
pass
|
| 514 |
+
|
| 515 |
+
VerboseApexUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 516 |
+
namedtype.NamedType('status', StatusCode()),
|
| 517 |
+
namedtype.NamedType('taInfo', TrustAnchorChoiceList()),
|
| 518 |
+
namedtype.OptionalNamedType('communities',
|
| 519 |
+
CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 520 |
+
tag.tagFormatSimple, 0))),
|
| 521 |
+
namedtype.OptionalNamedType('tampSeqNumbers',
|
| 522 |
+
TAMPSequenceNumbers().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 523 |
+
tag.tagFormatSimple, 1)))
|
| 524 |
+
)
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
class ApexUpdateConfirm(univ.Choice):
|
| 528 |
+
pass
|
| 529 |
+
|
| 530 |
+
ApexUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 531 |
+
namedtype.NamedType('terseApexConfirm',
|
| 532 |
+
TerseApexUpdateConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 533 |
+
tag.tagFormatSimple, 0))),
|
| 534 |
+
namedtype.NamedType('verboseApexConfirm',
|
| 535 |
+
VerboseApexUpdateConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 536 |
+
tag.tagFormatConstructed, 1)))
|
| 537 |
+
)
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
class TAMPApexUpdateConfirm(univ.Sequence):
|
| 541 |
+
pass
|
| 542 |
+
|
| 543 |
+
TAMPApexUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 544 |
+
namedtype.DefaultedNamedType('version',
|
| 545 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 546 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 547 |
+
namedtype.NamedType('apexReplace', TAMPMsgRef()),
|
| 548 |
+
namedtype.NamedType('apexConfirm', ApexUpdateConfirm())
|
| 549 |
+
)
|
| 550 |
+
|
| 551 |
+
|
| 552 |
+
tamp_apex_update_confirm = rfc5652.ContentInfo()
|
| 553 |
+
tamp_apex_update_confirm['contentType'] = id_ct_TAMP_apexUpdateConfirm
|
| 554 |
+
tamp_apex_update_confirm['content'] = TAMPApexUpdateConfirm()
|
| 555 |
+
|
| 556 |
+
|
| 557 |
+
# Community Update Message
|
| 558 |
+
|
| 559 |
+
id_ct_TAMP_communityUpdate = _OID(id_tamp, 7)
|
| 560 |
+
|
| 561 |
+
|
| 562 |
+
class CommunityUpdates(univ.Sequence):
|
| 563 |
+
pass
|
| 564 |
+
|
| 565 |
+
CommunityUpdates.componentType = namedtype.NamedTypes(
|
| 566 |
+
namedtype.OptionalNamedType('remove',
|
| 567 |
+
CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 568 |
+
tag.tagFormatSimple, 1))),
|
| 569 |
+
namedtype.OptionalNamedType('add',
|
| 570 |
+
CommunityIdentifierList().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 571 |
+
tag.tagFormatSimple, 2)))
|
| 572 |
+
)
|
| 573 |
+
|
| 574 |
+
|
| 575 |
+
class TAMPCommunityUpdate(univ.Sequence):
|
| 576 |
+
pass
|
| 577 |
+
|
| 578 |
+
TAMPCommunityUpdate.componentType = namedtype.NamedTypes(
|
| 579 |
+
namedtype.DefaultedNamedType('version',
|
| 580 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 581 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 582 |
+
namedtype.DefaultedNamedType('terse',
|
| 583 |
+
TerseOrVerbose().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 584 |
+
tag.tagFormatSimple, 1)).subtype(value='verbose')),
|
| 585 |
+
namedtype.NamedType('msgRef', TAMPMsgRef()),
|
| 586 |
+
namedtype.NamedType('updates', CommunityUpdates())
|
| 587 |
+
)
|
| 588 |
+
|
| 589 |
+
|
| 590 |
+
tamp_community_update = rfc5652.ContentInfo()
|
| 591 |
+
tamp_community_update['contentType'] = id_ct_TAMP_communityUpdate
|
| 592 |
+
tamp_community_update['content'] = TAMPCommunityUpdate()
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
# Community Update Confirm Message
|
| 596 |
+
|
| 597 |
+
id_ct_TAMP_communityUpdateConfirm = _OID(id_tamp, 8)
|
| 598 |
+
|
| 599 |
+
|
| 600 |
+
class TerseCommunityConfirm(StatusCode):
|
| 601 |
+
pass
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
class VerboseCommunityConfirm(univ.Sequence):
|
| 605 |
+
pass
|
| 606 |
+
|
| 607 |
+
VerboseCommunityConfirm.componentType = namedtype.NamedTypes(
|
| 608 |
+
namedtype.NamedType('status', StatusCode()),
|
| 609 |
+
namedtype.OptionalNamedType('communities', CommunityIdentifierList())
|
| 610 |
+
)
|
| 611 |
+
|
| 612 |
+
|
| 613 |
+
class CommunityConfirm(univ.Choice):
|
| 614 |
+
pass
|
| 615 |
+
|
| 616 |
+
CommunityConfirm.componentType = namedtype.NamedTypes(
|
| 617 |
+
namedtype.NamedType('terseCommConfirm',
|
| 618 |
+
TerseCommunityConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 619 |
+
tag.tagFormatSimple, 0))),
|
| 620 |
+
namedtype.NamedType('verboseCommConfirm',
|
| 621 |
+
VerboseCommunityConfirm().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 622 |
+
tag.tagFormatConstructed, 1)))
|
| 623 |
+
)
|
| 624 |
+
|
| 625 |
+
|
| 626 |
+
class TAMPCommunityUpdateConfirm(univ.Sequence):
|
| 627 |
+
pass
|
| 628 |
+
|
| 629 |
+
TAMPCommunityUpdateConfirm.componentType = namedtype.NamedTypes(
|
| 630 |
+
namedtype.DefaultedNamedType('version',
|
| 631 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 632 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 633 |
+
namedtype.NamedType('update', TAMPMsgRef()),
|
| 634 |
+
namedtype.NamedType('commConfirm', CommunityConfirm())
|
| 635 |
+
)
|
| 636 |
+
|
| 637 |
+
|
| 638 |
+
tamp_community_update_confirm = rfc5652.ContentInfo()
|
| 639 |
+
tamp_community_update_confirm['contentType'] = id_ct_TAMP_communityUpdateConfirm
|
| 640 |
+
tamp_community_update_confirm['content'] = TAMPCommunityUpdateConfirm()
|
| 641 |
+
|
| 642 |
+
|
| 643 |
+
# Sequence Number Adjust Message
|
| 644 |
+
|
| 645 |
+
id_ct_TAMP_seqNumAdjust = _OID(id_tamp, 10)
|
| 646 |
+
|
| 647 |
+
|
| 648 |
+
|
| 649 |
+
class SequenceNumberAdjust(univ.Sequence):
|
| 650 |
+
pass
|
| 651 |
+
|
| 652 |
+
SequenceNumberAdjust.componentType = namedtype.NamedTypes(
|
| 653 |
+
namedtype.DefaultedNamedType('version',
|
| 654 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 655 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 656 |
+
namedtype.NamedType('msgRef', TAMPMsgRef())
|
| 657 |
+
)
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
tamp_sequence_number_adjust = rfc5652.ContentInfo()
|
| 661 |
+
tamp_sequence_number_adjust['contentType'] = id_ct_TAMP_seqNumAdjust
|
| 662 |
+
tamp_sequence_number_adjust['content'] = SequenceNumberAdjust()
|
| 663 |
+
|
| 664 |
+
|
| 665 |
+
# Sequence Number Adjust Confirm Message
|
| 666 |
+
|
| 667 |
+
id_ct_TAMP_seqNumAdjustConfirm = _OID(id_tamp, 11)
|
| 668 |
+
|
| 669 |
+
|
| 670 |
+
class SequenceNumberAdjustConfirm(univ.Sequence):
|
| 671 |
+
pass
|
| 672 |
+
|
| 673 |
+
SequenceNumberAdjustConfirm.componentType = namedtype.NamedTypes(
|
| 674 |
+
namedtype.DefaultedNamedType('version',
|
| 675 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 676 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 677 |
+
namedtype.NamedType('adjust', TAMPMsgRef()),
|
| 678 |
+
namedtype.NamedType('status', StatusCode())
|
| 679 |
+
)
|
| 680 |
+
|
| 681 |
+
|
| 682 |
+
tamp_sequence_number_adjust_confirm = rfc5652.ContentInfo()
|
| 683 |
+
tamp_sequence_number_adjust_confirm['contentType'] = id_ct_TAMP_seqNumAdjustConfirm
|
| 684 |
+
tamp_sequence_number_adjust_confirm['content'] = SequenceNumberAdjustConfirm()
|
| 685 |
+
|
| 686 |
+
|
| 687 |
+
# TAMP Error Message
|
| 688 |
+
|
| 689 |
+
id_ct_TAMP_error = _OID(id_tamp, 9)
|
| 690 |
+
|
| 691 |
+
|
| 692 |
+
class TAMPError(univ.Sequence):
|
| 693 |
+
pass
|
| 694 |
+
|
| 695 |
+
TAMPError.componentType = namedtype.NamedTypes(
|
| 696 |
+
namedtype.DefaultedNamedType('version',
|
| 697 |
+
TAMPVersion().subtype(implicitTag=tag.Tag(tag.tagClassContext,
|
| 698 |
+
tag.tagFormatSimple, 0)).subtype(value='v2')),
|
| 699 |
+
namedtype.NamedType('msgType', univ.ObjectIdentifier()),
|
| 700 |
+
namedtype.NamedType('status', StatusCode()),
|
| 701 |
+
namedtype.OptionalNamedType('msgRef', TAMPMsgRef())
|
| 702 |
+
)
|
| 703 |
+
|
| 704 |
+
|
| 705 |
+
tamp_error = rfc5652.ContentInfo()
|
| 706 |
+
tamp_error['contentType'] = id_ct_TAMP_error
|
| 707 |
+
tamp_error['content'] = TAMPError()
|
| 708 |
+
|
| 709 |
+
|
| 710 |
+
# Object Identifier Arc for Attributes
|
| 711 |
+
|
| 712 |
+
id_attributes = univ.ObjectIdentifier('2.16.840.1.101.2.1.5')
|
| 713 |
+
|
| 714 |
+
|
| 715 |
+
# contingency-public-key-decrypt-key unsigned attribute
|
| 716 |
+
|
| 717 |
+
id_aa_TAMP_contingencyPublicKeyDecryptKey = _OID(id_attributes, 63)
|
| 718 |
+
|
| 719 |
+
|
| 720 |
+
class PlaintextSymmetricKey(univ.OctetString):
|
| 721 |
+
pass
|
| 722 |
+
|
| 723 |
+
|
| 724 |
+
contingency_public_key_decrypt_key = Attribute()
|
| 725 |
+
contingency_public_key_decrypt_key['type'] = id_aa_TAMP_contingencyPublicKeyDecryptKey
|
| 726 |
+
contingency_public_key_decrypt_key['values'][0] = PlaintextSymmetricKey()
|
| 727 |
+
|
| 728 |
+
|
| 729 |
+
# id-pe-wrappedApexContinKey extension
|
| 730 |
+
|
| 731 |
+
id_pe_wrappedApexContinKey =univ.ObjectIdentifier('1.3.6.1.5.5.7.1.20')
|
| 732 |
+
|
| 733 |
+
|
| 734 |
+
class ApexContingencyKey(univ.Sequence):
|
| 735 |
+
pass
|
| 736 |
+
|
| 737 |
+
ApexContingencyKey.componentType = namedtype.NamedTypes(
|
| 738 |
+
namedtype.NamedType('wrapAlgorithm', AlgorithmIdentifier()),
|
| 739 |
+
namedtype.NamedType('wrappedContinPubKey', univ.OctetString())
|
| 740 |
+
)
|
| 741 |
+
|
| 742 |
+
|
| 743 |
+
wrappedApexContinKey = Extension()
|
| 744 |
+
wrappedApexContinKey['extnID'] = id_pe_wrappedApexContinKey
|
| 745 |
+
wrappedApexContinKey['critical'] = 0
|
| 746 |
+
wrappedApexContinKey['extnValue'] = univ.OctetString()
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
# Add to the map of CMS Content Type OIDs to Content Types in
|
| 750 |
+
# rfc5652.py
|
| 751 |
+
|
| 752 |
+
_cmsContentTypesMapUpdate = {
|
| 753 |
+
id_ct_TAMP_statusQuery: TAMPStatusQuery(),
|
| 754 |
+
id_ct_TAMP_statusResponse: TAMPStatusResponse(),
|
| 755 |
+
id_ct_TAMP_update: TAMPUpdate(),
|
| 756 |
+
id_ct_TAMP_updateConfirm: TAMPUpdateConfirm(),
|
| 757 |
+
id_ct_TAMP_apexUpdate: TAMPApexUpdate(),
|
| 758 |
+
id_ct_TAMP_apexUpdateConfirm: TAMPApexUpdateConfirm(),
|
| 759 |
+
id_ct_TAMP_communityUpdate: TAMPCommunityUpdate(),
|
| 760 |
+
id_ct_TAMP_communityUpdateConfirm: TAMPCommunityUpdateConfirm(),
|
| 761 |
+
id_ct_TAMP_seqNumAdjust: SequenceNumberAdjust(),
|
| 762 |
+
id_ct_TAMP_seqNumAdjustConfirm: SequenceNumberAdjustConfirm(),
|
| 763 |
+
id_ct_TAMP_error: TAMPError(),
|
| 764 |
+
}
|
| 765 |
+
|
| 766 |
+
rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate)
|
| 767 |
+
|
| 768 |
+
|
| 769 |
+
# Add to the map of CMS Attribute OIDs to Attribute Values in
|
| 770 |
+
# rfc5652.py
|
| 771 |
+
|
| 772 |
+
_cmsAttributesMapUpdate = {
|
| 773 |
+
id_aa_TAMP_contingencyPublicKeyDecryptKey: PlaintextSymmetricKey(),
|
| 774 |
+
}
|
| 775 |
+
|
| 776 |
+
rfc5652.cmsAttributesMap.update(_cmsAttributesMapUpdate)
|
| 777 |
+
|
| 778 |
+
|
| 779 |
+
# Add to the map of Certificate Extension OIDs to Extensions in
|
| 780 |
+
# rfc5280.py
|
| 781 |
+
|
| 782 |
+
_certificateExtensionsMap = {
|
| 783 |
+
id_pe_wrappedApexContinKey: ApexContingencyKey(),
|
| 784 |
+
}
|
| 785 |
+
|
| 786 |
+
rfc5280.certificateExtensionsMap.update(_certificateExtensionsMap)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc5940.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley with assistance from asn1ate v.0.6.0.
|
| 5 |
+
# Modified by Russ Housley to add map for use with opentypes.
|
| 6 |
+
#
|
| 7 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 8 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 9 |
+
#
|
| 10 |
+
# Additional CMS Revocation Information Choices
|
| 11 |
+
#
|
| 12 |
+
# ASN.1 source from:
|
| 13 |
+
# https://www.rfc-editor.org/rfc/rfc5940.txt
|
| 14 |
+
#
|
| 15 |
+
|
| 16 |
+
from pyasn1.type import namedtype
|
| 17 |
+
from pyasn1.type import tag
|
| 18 |
+
from pyasn1.type import univ
|
| 19 |
+
|
| 20 |
+
from pyasn1_modules import rfc2560
|
| 21 |
+
from pyasn1_modules import rfc5652
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# RevocationInfoChoice for OCSP response:
|
| 25 |
+
# The OID is included in otherRevInfoFormat, and
|
| 26 |
+
# signed OCSPResponse is included in otherRevInfo
|
| 27 |
+
|
| 28 |
+
id_ri_ocsp_response = univ.ObjectIdentifier('1.3.6.1.5.5.7.16.2')
|
| 29 |
+
|
| 30 |
+
OCSPResponse = rfc2560.OCSPResponse
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# RevocationInfoChoice for SCVP request/response:
|
| 34 |
+
# The OID is included in otherRevInfoFormat, and
|
| 35 |
+
# SCVPReqRes is included in otherRevInfo
|
| 36 |
+
|
| 37 |
+
id_ri_scvp = univ.ObjectIdentifier('1.3.6.1.5.5.7.16.4')
|
| 38 |
+
|
| 39 |
+
ContentInfo = rfc5652.ContentInfo
|
| 40 |
+
|
| 41 |
+
class SCVPReqRes(univ.Sequence):
|
| 42 |
+
pass
|
| 43 |
+
|
| 44 |
+
SCVPReqRes.componentType = namedtype.NamedTypes(
|
| 45 |
+
namedtype.OptionalNamedType('request',
|
| 46 |
+
ContentInfo().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 47 |
+
namedtype.NamedType('response', ContentInfo())
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
# Map of Revocation Info Format OIDs to Revocation Info Format
|
| 52 |
+
# is added to the ones that are in rfc5652.py
|
| 53 |
+
|
| 54 |
+
_otherRevInfoFormatMapUpdate = {
|
| 55 |
+
id_ri_ocsp_response: OCSPResponse(),
|
| 56 |
+
id_ri_scvp: SCVPReqRes(),
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
rfc5652.otherRevInfoFormatMap.update(_otherRevInfoFormatMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc6031.py
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley with assistance from asn1ate v.0.6.0.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# CMS Symmetric Key Package Content Type
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc6031.txt
|
| 13 |
+
#
|
| 14 |
+
|
| 15 |
+
from pyasn1.type import char
|
| 16 |
+
from pyasn1.type import constraint
|
| 17 |
+
from pyasn1.type import namedtype
|
| 18 |
+
from pyasn1.type import namedval
|
| 19 |
+
from pyasn1.type import opentype
|
| 20 |
+
from pyasn1.type import tag
|
| 21 |
+
from pyasn1.type import univ
|
| 22 |
+
from pyasn1.type import useful
|
| 23 |
+
|
| 24 |
+
from pyasn1_modules import rfc5652
|
| 25 |
+
from pyasn1_modules import rfc6019
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def _OID(*components):
|
| 29 |
+
output = []
|
| 30 |
+
for x in tuple(components):
|
| 31 |
+
if isinstance(x, univ.ObjectIdentifier):
|
| 32 |
+
output.extend(list(x))
|
| 33 |
+
else:
|
| 34 |
+
output.append(int(x))
|
| 35 |
+
return univ.ObjectIdentifier(output)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
MAX = float('inf')
|
| 39 |
+
|
| 40 |
+
id_pskc = univ.ObjectIdentifier('1.2.840.113549.1.9.16.12')
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# Symmetric Key Package Attributes
|
| 44 |
+
|
| 45 |
+
id_pskc_manufacturer = _OID(id_pskc, 1)
|
| 46 |
+
|
| 47 |
+
class at_pskc_manufacturer(char.UTF8String):
|
| 48 |
+
pass
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
id_pskc_serialNo = _OID(id_pskc, 2)
|
| 52 |
+
|
| 53 |
+
class at_pskc_serialNo(char.UTF8String):
|
| 54 |
+
pass
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
id_pskc_model = _OID(id_pskc, 3)
|
| 58 |
+
|
| 59 |
+
class at_pskc_model(char.UTF8String):
|
| 60 |
+
pass
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
id_pskc_issueNo = _OID(id_pskc, 4)
|
| 64 |
+
|
| 65 |
+
class at_pskc_issueNo(char.UTF8String):
|
| 66 |
+
pass
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
id_pskc_deviceBinding = _OID(id_pskc, 5)
|
| 70 |
+
|
| 71 |
+
class at_pskc_deviceBinding(char.UTF8String):
|
| 72 |
+
pass
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
id_pskc_deviceStartDate = _OID(id_pskc, 6)
|
| 76 |
+
|
| 77 |
+
class at_pskc_deviceStartDate(useful.GeneralizedTime):
|
| 78 |
+
pass
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
id_pskc_deviceExpiryDate = _OID(id_pskc, 7)
|
| 82 |
+
|
| 83 |
+
class at_pskc_deviceExpiryDate(useful.GeneralizedTime):
|
| 84 |
+
pass
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
id_pskc_moduleId = _OID(id_pskc, 8)
|
| 88 |
+
|
| 89 |
+
class at_pskc_moduleId(char.UTF8String):
|
| 90 |
+
pass
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
id_pskc_deviceUserId = _OID(id_pskc, 26)
|
| 94 |
+
|
| 95 |
+
class at_pskc_deviceUserId(char.UTF8String):
|
| 96 |
+
pass
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
# Symmetric Key Attributes
|
| 100 |
+
|
| 101 |
+
id_pskc_keyId = _OID(id_pskc, 9)
|
| 102 |
+
|
| 103 |
+
class at_pskc_keyUserId(char.UTF8String):
|
| 104 |
+
pass
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
id_pskc_algorithm = _OID(id_pskc, 10)
|
| 108 |
+
|
| 109 |
+
class at_pskc_algorithm(char.UTF8String):
|
| 110 |
+
pass
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
id_pskc_issuer = _OID(id_pskc, 11)
|
| 114 |
+
|
| 115 |
+
class at_pskc_issuer(char.UTF8String):
|
| 116 |
+
pass
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
id_pskc_keyProfileId = _OID(id_pskc, 12)
|
| 120 |
+
|
| 121 |
+
class at_pskc_keyProfileId(char.UTF8String):
|
| 122 |
+
pass
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
id_pskc_keyReference = _OID(id_pskc, 13)
|
| 126 |
+
|
| 127 |
+
class at_pskc_keyReference(char.UTF8String):
|
| 128 |
+
pass
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
id_pskc_friendlyName = _OID(id_pskc, 14)
|
| 132 |
+
|
| 133 |
+
class FriendlyName(univ.Sequence):
|
| 134 |
+
pass
|
| 135 |
+
|
| 136 |
+
FriendlyName.componentType = namedtype.NamedTypes(
|
| 137 |
+
namedtype.NamedType('friendlyName', char.UTF8String()),
|
| 138 |
+
namedtype.OptionalNamedType('friendlyNameLangTag', char.UTF8String())
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
class at_pskc_friendlyName(FriendlyName):
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
id_pskc_algorithmParameters = _OID(id_pskc, 15)
|
| 146 |
+
|
| 147 |
+
class Encoding(char.UTF8String):
|
| 148 |
+
pass
|
| 149 |
+
|
| 150 |
+
Encoding.namedValues = namedval.NamedValues(
|
| 151 |
+
('dec', "DECIMAL"),
|
| 152 |
+
('hex', "HEXADECIMAL"),
|
| 153 |
+
('alpha', "ALPHANUMERIC"),
|
| 154 |
+
('b64', "BASE64"),
|
| 155 |
+
('bin', "BINARY")
|
| 156 |
+
)
|
| 157 |
+
|
| 158 |
+
Encoding.subtypeSpec = constraint.SingleValueConstraint(
|
| 159 |
+
"DECIMAL", "HEXADECIMAL", "ALPHANUMERIC", "BASE64", "BINARY" )
|
| 160 |
+
|
| 161 |
+
class ChallengeFormat(univ.Sequence):
|
| 162 |
+
pass
|
| 163 |
+
|
| 164 |
+
ChallengeFormat.componentType = namedtype.NamedTypes(
|
| 165 |
+
namedtype.NamedType('encoding', Encoding()),
|
| 166 |
+
namedtype.DefaultedNamedType('checkDigit',
|
| 167 |
+
univ.Boolean().subtype(value=0)),
|
| 168 |
+
namedtype.NamedType('min', univ.Integer().subtype(
|
| 169 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX))),
|
| 170 |
+
namedtype.NamedType('max', univ.Integer().subtype(
|
| 171 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX)))
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
class ResponseFormat(univ.Sequence):
|
| 175 |
+
pass
|
| 176 |
+
|
| 177 |
+
ResponseFormat.componentType = namedtype.NamedTypes(
|
| 178 |
+
namedtype.NamedType('encoding', Encoding()),
|
| 179 |
+
namedtype.NamedType('length', univ.Integer().subtype(
|
| 180 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX))),
|
| 181 |
+
namedtype.DefaultedNamedType('checkDigit',
|
| 182 |
+
univ.Boolean().subtype(value=0))
|
| 183 |
+
)
|
| 184 |
+
|
| 185 |
+
class PSKCAlgorithmParameters(univ.Choice):
|
| 186 |
+
pass
|
| 187 |
+
|
| 188 |
+
PSKCAlgorithmParameters.componentType = namedtype.NamedTypes(
|
| 189 |
+
namedtype.NamedType('suite', char.UTF8String()),
|
| 190 |
+
namedtype.NamedType('challengeFormat', ChallengeFormat().subtype(
|
| 191 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))),
|
| 192 |
+
namedtype.NamedType('responseFormat', ResponseFormat().subtype(
|
| 193 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)))
|
| 194 |
+
)
|
| 195 |
+
|
| 196 |
+
class at_pskc_algorithmParameters(PSKCAlgorithmParameters):
|
| 197 |
+
pass
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
id_pskc_counter = _OID(id_pskc, 16)
|
| 201 |
+
|
| 202 |
+
class at_pskc_counter(univ.Integer):
|
| 203 |
+
pass
|
| 204 |
+
|
| 205 |
+
at_pskc_counter.subtypeSpec = constraint.ValueRangeConstraint(0, MAX)
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
id_pskc_time = _OID(id_pskc, 17)
|
| 209 |
+
|
| 210 |
+
class at_pskc_time(rfc6019.BinaryTime):
|
| 211 |
+
pass
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
id_pskc_timeInterval = _OID(id_pskc, 18)
|
| 215 |
+
|
| 216 |
+
class at_pskc_timeInterval(univ.Integer):
|
| 217 |
+
pass
|
| 218 |
+
|
| 219 |
+
at_pskc_timeInterval.subtypeSpec = constraint.ValueRangeConstraint(0, MAX)
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
id_pskc_timeDrift = _OID(id_pskc, 19)
|
| 223 |
+
|
| 224 |
+
class at_pskc_timeDrift(univ.Integer):
|
| 225 |
+
pass
|
| 226 |
+
|
| 227 |
+
at_pskc_timeDrift.subtypeSpec = constraint.ValueRangeConstraint(0, MAX)
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
id_pskc_valueMAC = _OID(id_pskc, 20)
|
| 231 |
+
|
| 232 |
+
class ValueMac(univ.Sequence):
|
| 233 |
+
pass
|
| 234 |
+
|
| 235 |
+
ValueMac.componentType = namedtype.NamedTypes(
|
| 236 |
+
namedtype.NamedType('macAlgorithm', char.UTF8String()),
|
| 237 |
+
namedtype.NamedType('mac', char.UTF8String())
|
| 238 |
+
)
|
| 239 |
+
|
| 240 |
+
class at_pskc_valueMAC(ValueMac):
|
| 241 |
+
pass
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
id_pskc_keyUserId = _OID(id_pskc, 27)
|
| 245 |
+
|
| 246 |
+
class at_pskc_keyId(char.UTF8String):
|
| 247 |
+
pass
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
id_pskc_keyStartDate = _OID(id_pskc, 21)
|
| 251 |
+
|
| 252 |
+
class at_pskc_keyStartDate(useful.GeneralizedTime):
|
| 253 |
+
pass
|
| 254 |
+
|
| 255 |
+
|
| 256 |
+
id_pskc_keyExpiryDate = _OID(id_pskc, 22)
|
| 257 |
+
|
| 258 |
+
class at_pskc_keyExpiryDate(useful.GeneralizedTime):
|
| 259 |
+
pass
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
id_pskc_numberOfTransactions = _OID(id_pskc, 23)
|
| 263 |
+
|
| 264 |
+
class at_pskc_numberOfTransactions(univ.Integer):
|
| 265 |
+
pass
|
| 266 |
+
|
| 267 |
+
at_pskc_numberOfTransactions.subtypeSpec = constraint.ValueRangeConstraint(0, MAX)
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
id_pskc_keyUsages = _OID(id_pskc, 24)
|
| 271 |
+
|
| 272 |
+
class PSKCKeyUsage(char.UTF8String):
|
| 273 |
+
pass
|
| 274 |
+
|
| 275 |
+
PSKCKeyUsage.namedValues = namedval.NamedValues(
|
| 276 |
+
('otp', "OTP"),
|
| 277 |
+
('cr', "CR"),
|
| 278 |
+
('encrypt', "Encrypt"),
|
| 279 |
+
('integrity', "Integrity"),
|
| 280 |
+
('verify', "Verify"),
|
| 281 |
+
('unlock', "Unlock"),
|
| 282 |
+
('decrypt', "Decrypt"),
|
| 283 |
+
('keywrap', "KeyWrap"),
|
| 284 |
+
('unwrap', "Unwrap"),
|
| 285 |
+
('derive', "Derive"),
|
| 286 |
+
('generate', "Generate")
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
PSKCKeyUsage.subtypeSpec = constraint.SingleValueConstraint(
|
| 290 |
+
"OTP", "CR", "Encrypt", "Integrity", "Verify", "Unlock",
|
| 291 |
+
"Decrypt", "KeyWrap", "Unwrap", "Derive", "Generate" )
|
| 292 |
+
|
| 293 |
+
class PSKCKeyUsages(univ.SequenceOf):
|
| 294 |
+
pass
|
| 295 |
+
|
| 296 |
+
PSKCKeyUsages.componentType = PSKCKeyUsage()
|
| 297 |
+
|
| 298 |
+
class at_pskc_keyUsage(PSKCKeyUsages):
|
| 299 |
+
pass
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
id_pskc_pinPolicy = _OID(id_pskc, 25)
|
| 303 |
+
|
| 304 |
+
class PINUsageMode(char.UTF8String):
|
| 305 |
+
pass
|
| 306 |
+
|
| 307 |
+
PINUsageMode.namedValues = namedval.NamedValues(
|
| 308 |
+
("local", "Local"),
|
| 309 |
+
("prepend", "Prepend"),
|
| 310 |
+
("append", "Append"),
|
| 311 |
+
("algorithmic", "Algorithmic")
|
| 312 |
+
)
|
| 313 |
+
|
| 314 |
+
PINUsageMode.subtypeSpec = constraint.SingleValueConstraint(
|
| 315 |
+
"Local", "Prepend", "Append", "Algorithmic" )
|
| 316 |
+
|
| 317 |
+
class PINPolicy(univ.Sequence):
|
| 318 |
+
pass
|
| 319 |
+
|
| 320 |
+
PINPolicy.componentType = namedtype.NamedTypes(
|
| 321 |
+
namedtype.OptionalNamedType('pinKeyId', char.UTF8String().subtype(
|
| 322 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 323 |
+
namedtype.NamedType('pinUsageMode', PINUsageMode().subtype(
|
| 324 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1))),
|
| 325 |
+
namedtype.OptionalNamedType('maxFailedAttempts', univ.Integer().subtype(
|
| 326 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype(
|
| 327 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))),
|
| 328 |
+
namedtype.OptionalNamedType('minLength', univ.Integer().subtype(
|
| 329 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype(
|
| 330 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))),
|
| 331 |
+
namedtype.OptionalNamedType('maxLength', univ.Integer().subtype(
|
| 332 |
+
subtypeSpec=constraint.ValueRangeConstraint(0, MAX)).subtype(
|
| 333 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 4))),
|
| 334 |
+
namedtype.OptionalNamedType('pinEncoding', Encoding().subtype(
|
| 335 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 5)))
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
class at_pskc_pinPolicy(PINPolicy):
|
| 339 |
+
pass
|
| 340 |
+
|
| 341 |
+
|
| 342 |
+
# Map of Symmetric Key Package Attribute OIDs to Attributes
|
| 343 |
+
|
| 344 |
+
sKeyPkgAttributesMap = {
|
| 345 |
+
id_pskc_manufacturer: at_pskc_manufacturer(),
|
| 346 |
+
id_pskc_serialNo: at_pskc_serialNo(),
|
| 347 |
+
id_pskc_model: at_pskc_model(),
|
| 348 |
+
id_pskc_issueNo: at_pskc_issueNo(),
|
| 349 |
+
id_pskc_deviceBinding: at_pskc_deviceBinding(),
|
| 350 |
+
id_pskc_deviceStartDate: at_pskc_deviceStartDate(),
|
| 351 |
+
id_pskc_deviceExpiryDate: at_pskc_deviceExpiryDate(),
|
| 352 |
+
id_pskc_moduleId: at_pskc_moduleId(),
|
| 353 |
+
id_pskc_deviceUserId: at_pskc_deviceUserId(),
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
# Map of Symmetric Key Attribute OIDs to Attributes
|
| 358 |
+
|
| 359 |
+
sKeyAttributesMap = {
|
| 360 |
+
id_pskc_keyId: at_pskc_keyId(),
|
| 361 |
+
id_pskc_algorithm: at_pskc_algorithm(),
|
| 362 |
+
id_pskc_issuer: at_pskc_issuer(),
|
| 363 |
+
id_pskc_keyProfileId: at_pskc_keyProfileId(),
|
| 364 |
+
id_pskc_keyReference: at_pskc_keyReference(),
|
| 365 |
+
id_pskc_friendlyName: at_pskc_friendlyName(),
|
| 366 |
+
id_pskc_algorithmParameters: at_pskc_algorithmParameters(),
|
| 367 |
+
id_pskc_counter: at_pskc_counter(),
|
| 368 |
+
id_pskc_time: at_pskc_time(),
|
| 369 |
+
id_pskc_timeInterval: at_pskc_timeInterval(),
|
| 370 |
+
id_pskc_timeDrift: at_pskc_timeDrift(),
|
| 371 |
+
id_pskc_valueMAC: at_pskc_valueMAC(),
|
| 372 |
+
id_pskc_keyUserId: at_pskc_keyUserId(),
|
| 373 |
+
id_pskc_keyStartDate: at_pskc_keyStartDate(),
|
| 374 |
+
id_pskc_keyExpiryDate: at_pskc_keyExpiryDate(),
|
| 375 |
+
id_pskc_numberOfTransactions: at_pskc_numberOfTransactions(),
|
| 376 |
+
id_pskc_keyUsages: at_pskc_keyUsage(),
|
| 377 |
+
id_pskc_pinPolicy: at_pskc_pinPolicy(),
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
# This definition replaces Attribute() from rfc5652.py; it is the same except
|
| 382 |
+
# that opentype is added with sKeyPkgAttributesMap and sKeyAttributesMap
|
| 383 |
+
|
| 384 |
+
class AttributeType(univ.ObjectIdentifier):
|
| 385 |
+
pass
|
| 386 |
+
|
| 387 |
+
|
| 388 |
+
class AttributeValue(univ.Any):
|
| 389 |
+
pass
|
| 390 |
+
|
| 391 |
+
|
| 392 |
+
class SKeyAttribute(univ.Sequence):
|
| 393 |
+
pass
|
| 394 |
+
|
| 395 |
+
SKeyAttribute.componentType = namedtype.NamedTypes(
|
| 396 |
+
namedtype.NamedType('attrType', AttributeType()),
|
| 397 |
+
namedtype.NamedType('attrValues',
|
| 398 |
+
univ.SetOf(componentType=AttributeValue()),
|
| 399 |
+
openType=opentype.OpenType('attrType', sKeyAttributesMap)
|
| 400 |
+
)
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
class SKeyPkgAttribute(univ.Sequence):
|
| 405 |
+
pass
|
| 406 |
+
|
| 407 |
+
SKeyPkgAttribute.componentType = namedtype.NamedTypes(
|
| 408 |
+
namedtype.NamedType('attrType', AttributeType()),
|
| 409 |
+
namedtype.NamedType('attrValues',
|
| 410 |
+
univ.SetOf(componentType=AttributeValue()),
|
| 411 |
+
openType=opentype.OpenType('attrType', sKeyPkgAttributesMap)
|
| 412 |
+
)
|
| 413 |
+
)
|
| 414 |
+
|
| 415 |
+
|
| 416 |
+
# Symmetric Key Package Content Type
|
| 417 |
+
|
| 418 |
+
id_ct_KP_sKeyPackage = univ.ObjectIdentifier('1.2.840.113549.1.9.16.1.25')
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
class KeyPkgVersion(univ.Integer):
|
| 422 |
+
pass
|
| 423 |
+
|
| 424 |
+
KeyPkgVersion.namedValues = namedval.NamedValues(
|
| 425 |
+
('v1', 1)
|
| 426 |
+
)
|
| 427 |
+
|
| 428 |
+
|
| 429 |
+
class OneSymmetricKey(univ.Sequence):
|
| 430 |
+
pass
|
| 431 |
+
|
| 432 |
+
OneSymmetricKey.componentType = namedtype.NamedTypes(
|
| 433 |
+
namedtype.OptionalNamedType('sKeyAttrs',
|
| 434 |
+
univ.SequenceOf(componentType=SKeyAttribute()).subtype(
|
| 435 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, MAX))),
|
| 436 |
+
namedtype.OptionalNamedType('sKey', univ.OctetString())
|
| 437 |
+
)
|
| 438 |
+
|
| 439 |
+
OneSymmetricKey.sizeSpec = univ.Sequence.sizeSpec + constraint.ValueSizeConstraint(1, 2)
|
| 440 |
+
|
| 441 |
+
|
| 442 |
+
class SymmetricKeys(univ.SequenceOf):
|
| 443 |
+
pass
|
| 444 |
+
|
| 445 |
+
SymmetricKeys.componentType = OneSymmetricKey()
|
| 446 |
+
SymmetricKeys.subtypeSpec=constraint.ValueSizeConstraint(1, MAX)
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
class SymmetricKeyPackage(univ.Sequence):
|
| 450 |
+
pass
|
| 451 |
+
|
| 452 |
+
SymmetricKeyPackage.componentType = namedtype.NamedTypes(
|
| 453 |
+
namedtype.DefaultedNamedType('version', KeyPkgVersion().subtype(value='v1')),
|
| 454 |
+
namedtype.OptionalNamedType('sKeyPkgAttrs',
|
| 455 |
+
univ.SequenceOf(componentType=SKeyPkgAttribute()).subtype(
|
| 456 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, MAX),
|
| 457 |
+
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
|
| 458 |
+
namedtype.NamedType('sKeys', SymmetricKeys())
|
| 459 |
+
)
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
# Map of Content Type OIDs to Content Types are
|
| 463 |
+
# added to the ones that are in rfc5652.py
|
| 464 |
+
|
| 465 |
+
_cmsContentTypesMapUpdate = {
|
| 466 |
+
id_ct_KP_sKeyPackage: SymmetricKeyPackage(),
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
rfc5652.cmsContentTypesMap.update(_cmsContentTypesMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7229.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# Object Identifiers for Test Certificate Policies
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc7229.txt
|
| 13 |
+
#
|
| 14 |
+
|
| 15 |
+
from pyasn1.type import univ
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7')
|
| 19 |
+
|
| 20 |
+
id_TEST = id_pkix + (13, )
|
| 21 |
+
|
| 22 |
+
id_TEST_certPolicyOne = id_TEST + (1, )
|
| 23 |
+
id_TEST_certPolicyTwo = id_TEST + (2, )
|
| 24 |
+
id_TEST_certPolicyThree = id_TEST + (3, )
|
| 25 |
+
id_TEST_certPolicyFour = id_TEST + (4, )
|
| 26 |
+
id_TEST_certPolicyFive = id_TEST + (5, )
|
| 27 |
+
id_TEST_certPolicySix = id_TEST + (6, )
|
| 28 |
+
id_TEST_certPolicySeven = id_TEST + (7, )
|
| 29 |
+
id_TEST_certPolicyEight = id_TEST + (8, )
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7585.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley with some assistance from asn1ate v.0.6.0.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# Network Access Identifier (NAI) Realm Name for Certificates
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc7585.txt
|
| 13 |
+
#
|
| 14 |
+
|
| 15 |
+
from pyasn1.type import char
|
| 16 |
+
from pyasn1.type import constraint
|
| 17 |
+
from pyasn1.type import univ
|
| 18 |
+
|
| 19 |
+
from pyasn1_modules import rfc5280
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# NAI Realm Name for Certificates
|
| 23 |
+
|
| 24 |
+
id_pkix = univ.ObjectIdentifier('1.3.6.1.5.5.7')
|
| 25 |
+
|
| 26 |
+
id_on = id_pkix + (8, )
|
| 27 |
+
|
| 28 |
+
id_on_naiRealm = id_on + (8, )
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
ub_naiRealm_length = univ.Integer(255)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class NAIRealm(char.UTF8String):
|
| 35 |
+
subtypeSpec = constraint.ValueSizeConstraint(1, ub_naiRealm_length)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
naiRealm = rfc5280.AnotherName()
|
| 39 |
+
naiRealm['type-id'] = id_on_naiRealm
|
| 40 |
+
naiRealm['value'] = NAIRealm()
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# Map of Other Name OIDs to Other Name is added to the
|
| 44 |
+
# ones that are in rfc5280.py
|
| 45 |
+
|
| 46 |
+
_anotherNameMapUpdate = {
|
| 47 |
+
id_on_naiRealm: NAIRealm(),
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
rfc5280.anotherNameMap.update(_anotherNameMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pyasn1_modules/rfc7894.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# This file is part of pyasn1-modules software.
|
| 3 |
+
#
|
| 4 |
+
# Created by Russ Housley.
|
| 5 |
+
#
|
| 6 |
+
# Copyright (c) 2019, Vigil Security, LLC
|
| 7 |
+
# License: http://snmplabs.com/pyasn1/license.html
|
| 8 |
+
#
|
| 9 |
+
# Alternative Challenge Password Attributes for EST
|
| 10 |
+
#
|
| 11 |
+
# ASN.1 source from:
|
| 12 |
+
# https://www.rfc-editor.org/rfc/rfc7894.txt
|
| 13 |
+
#
|
| 14 |
+
|
| 15 |
+
from pyasn1.type import char
|
| 16 |
+
from pyasn1.type import constraint
|
| 17 |
+
from pyasn1.type import namedtype
|
| 18 |
+
from pyasn1.type import univ
|
| 19 |
+
|
| 20 |
+
from pyasn1_modules import rfc5652
|
| 21 |
+
from pyasn1_modules import rfc6402
|
| 22 |
+
from pyasn1_modules import rfc7191
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# SingleAttribute is the same as Attribute in RFC 5652, except that the
|
| 26 |
+
# attrValues SET must have one and only one member
|
| 27 |
+
|
| 28 |
+
Attribute = rfc7191.SingleAttribute
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# DirectoryString is the same as RFC 5280, except the length is limited to 255
|
| 32 |
+
|
| 33 |
+
class DirectoryString(univ.Choice):
|
| 34 |
+
pass
|
| 35 |
+
|
| 36 |
+
DirectoryString.componentType = namedtype.NamedTypes(
|
| 37 |
+
namedtype.NamedType('teletexString', char.TeletexString().subtype(
|
| 38 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
| 39 |
+
namedtype.NamedType('printableString', char.PrintableString().subtype(
|
| 40 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
| 41 |
+
namedtype.NamedType('universalString', char.UniversalString().subtype(
|
| 42 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
| 43 |
+
namedtype.NamedType('utf8String', char.UTF8String().subtype(
|
| 44 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 255))),
|
| 45 |
+
namedtype.NamedType('bmpString', char.BMPString().subtype(
|
| 46 |
+
subtypeSpec=constraint.ValueSizeConstraint(1, 255)))
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
# OTP Challenge Attribute
|
| 51 |
+
|
| 52 |
+
id_aa_otpChallenge = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.56')
|
| 53 |
+
|
| 54 |
+
ub_aa_otpChallenge = univ.Integer(255)
|
| 55 |
+
|
| 56 |
+
otpChallenge = Attribute()
|
| 57 |
+
otpChallenge['attrType'] = id_aa_otpChallenge
|
| 58 |
+
otpChallenge['attrValues'][0] = DirectoryString()
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
# Revocation Challenge Attribute
|
| 62 |
+
|
| 63 |
+
id_aa_revocationChallenge = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.57')
|
| 64 |
+
|
| 65 |
+
ub_aa_revocationChallenge = univ.Integer(255)
|
| 66 |
+
|
| 67 |
+
revocationChallenge = Attribute()
|
| 68 |
+
revocationChallenge['attrType'] = id_aa_revocationChallenge
|
| 69 |
+
revocationChallenge['attrValues'][0] = DirectoryString()
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# EST Identity Linking Attribute
|
| 73 |
+
|
| 74 |
+
id_aa_estIdentityLinking = univ.ObjectIdentifier('1.2.840.113549.1.9.16.2.58')
|
| 75 |
+
|
| 76 |
+
ub_aa_est_identity_linking = univ.Integer(255)
|
| 77 |
+
|
| 78 |
+
estIdentityLinking = Attribute()
|
| 79 |
+
estIdentityLinking['attrType'] = id_aa_estIdentityLinking
|
| 80 |
+
estIdentityLinking['attrValues'][0] = DirectoryString()
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# Map of Attribute Type OIDs to Attributes added to the
|
| 84 |
+
# ones that are in rfc6402.py
|
| 85 |
+
|
| 86 |
+
_cmcControlAttributesMapUpdate = {
|
| 87 |
+
id_aa_otpChallenge: DirectoryString(),
|
| 88 |
+
id_aa_revocationChallenge: DirectoryString(),
|
| 89 |
+
id_aa_estIdentityLinking: DirectoryString(),
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
rfc6402.cmcControlAttributesMap.update(_cmcControlAttributesMapUpdate)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Copyright © 2006-2009 Johann C. Rocholl <johann@rocholl.net>
|
| 2 |
+
Copyright © 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
|
| 3 |
+
Copyright © 2014-2020 Ian Lee <IanLee1521@gmail.com>
|
| 4 |
+
|
| 5 |
+
Licensed under the terms of the Expat License
|
| 6 |
+
|
| 7 |
+
Permission is hereby granted, free of charge, to any person
|
| 8 |
+
obtaining a copy of this software and associated documentation files
|
| 9 |
+
(the "Software"), to deal in the Software without restriction,
|
| 10 |
+
including without limitation the rights to use, copy, modify, merge,
|
| 11 |
+
publish, distribute, sublicense, and/or sell copies of the Software,
|
| 12 |
+
and to permit persons to whom the Software is furnished to do so,
|
| 13 |
+
subject to the following conditions:
|
| 14 |
+
|
| 15 |
+
The above copyright notice and this permission notice shall be
|
| 16 |
+
included in all copies or substantial portions of the Software.
|
| 17 |
+
|
| 18 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
| 19 |
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| 20 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
| 21 |
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
| 22 |
+
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
| 23 |
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
| 24 |
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 25 |
+
SOFTWARE.
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,1063 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.1
|
| 2 |
+
Name: pycodestyle
|
| 3 |
+
Version: 2.8.0
|
| 4 |
+
Summary: Python style guide checker
|
| 5 |
+
Home-page: https://pycodestyle.pycqa.org/
|
| 6 |
+
Author: Johann C. Rocholl
|
| 7 |
+
Author-email: johann@rocholl.net
|
| 8 |
+
Maintainer: Ian Lee
|
| 9 |
+
Maintainer-email: IanLee1521@gmail.com
|
| 10 |
+
License: Expat license
|
| 11 |
+
Project-URL: Changes, https://pycodestyle.pycqa.org/en/latest/developer.html#changes
|
| 12 |
+
Keywords: pycodestyle,pep8,PEP 8,PEP-8,PEP8
|
| 13 |
+
Platform: UNKNOWN
|
| 14 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 15 |
+
Classifier: Environment :: Console
|
| 16 |
+
Classifier: Intended Audience :: Developers
|
| 17 |
+
Classifier: License :: OSI Approved :: MIT License
|
| 18 |
+
Classifier: Operating System :: OS Independent
|
| 19 |
+
Classifier: Programming Language :: Python
|
| 20 |
+
Classifier: Programming Language :: Python :: 2
|
| 21 |
+
Classifier: Programming Language :: Python :: 2.7
|
| 22 |
+
Classifier: Programming Language :: Python :: 3
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.5
|
| 24 |
+
Classifier: Programming Language :: Python :: 3.6
|
| 25 |
+
Classifier: Programming Language :: Python :: 3.7
|
| 26 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 27 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 28 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 29 |
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
| 30 |
+
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
|
| 31 |
+
License-File: LICENSE
|
| 32 |
+
|
| 33 |
+
pycodestyle (formerly called pep8) - Python style guide checker
|
| 34 |
+
===============================================================
|
| 35 |
+
|
| 36 |
+
.. image:: https://github.com/PyCQA/pycodestyle/actions/workflows/main.yml/badge.svg
|
| 37 |
+
:target: https://github.com/PyCQA/pycodestyle/actions/workflows/main.yml
|
| 38 |
+
:alt: Build status
|
| 39 |
+
|
| 40 |
+
.. image:: https://readthedocs.org/projects/pycodestyle/badge/?version=latest
|
| 41 |
+
:target: https://pycodestyle.pycqa.org
|
| 42 |
+
:alt: Documentation Status
|
| 43 |
+
|
| 44 |
+
.. image:: https://img.shields.io/pypi/wheel/pycodestyle.svg
|
| 45 |
+
:target: https://pypi.org/project/pycodestyle/
|
| 46 |
+
:alt: Wheel Status
|
| 47 |
+
|
| 48 |
+
.. image:: https://badges.gitter.im/PyCQA/pycodestyle.svg
|
| 49 |
+
:alt: Join the chat at https://gitter.im/PyCQA/pycodestyle
|
| 50 |
+
:target: https://gitter.im/PyCQA/pycodestyle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
| 51 |
+
|
| 52 |
+
pycodestyle is a tool to check your Python code against some of the style
|
| 53 |
+
conventions in `PEP 8`_.
|
| 54 |
+
|
| 55 |
+
.. _PEP 8: http://www.python.org/dev/peps/pep-0008/
|
| 56 |
+
|
| 57 |
+
.. note::
|
| 58 |
+
|
| 59 |
+
This package used to be called ``pep8`` but was renamed to ``pycodestyle``
|
| 60 |
+
to reduce confusion. Further discussion can be found `in the issue where
|
| 61 |
+
Guido requested this
|
| 62 |
+
change <https://github.com/PyCQA/pycodestyle/issues/466>`_, or in the
|
| 63 |
+
lightning talk at PyCon 2016 by @IanLee1521:
|
| 64 |
+
`slides <https://speakerdeck.com/ianlee1521/pep8-vs-pep-8>`_
|
| 65 |
+
`video <https://youtu.be/PulzIT8KYLk?t=36m>`_.
|
| 66 |
+
|
| 67 |
+
Features
|
| 68 |
+
--------
|
| 69 |
+
|
| 70 |
+
* Plugin architecture: Adding new checks is easy.
|
| 71 |
+
|
| 72 |
+
* Parseable output: Jump to error location in your editor.
|
| 73 |
+
|
| 74 |
+
* Small: Just one Python file, requires only stdlib. You can use just
|
| 75 |
+
the ``pycodestyle.py`` file for this purpose.
|
| 76 |
+
|
| 77 |
+
* Comes with a comprehensive test suite.
|
| 78 |
+
|
| 79 |
+
Installation
|
| 80 |
+
------------
|
| 81 |
+
|
| 82 |
+
You can install, upgrade, and uninstall ``pycodestyle.py`` with these commands::
|
| 83 |
+
|
| 84 |
+
$ pip install pycodestyle
|
| 85 |
+
$ pip install --upgrade pycodestyle
|
| 86 |
+
$ pip uninstall pycodestyle
|
| 87 |
+
|
| 88 |
+
There's also a package for Debian/Ubuntu, but it's not always the
|
| 89 |
+
latest version.
|
| 90 |
+
|
| 91 |
+
Example usage and output
|
| 92 |
+
------------------------
|
| 93 |
+
|
| 94 |
+
::
|
| 95 |
+
|
| 96 |
+
$ pycodestyle --first optparse.py
|
| 97 |
+
optparse.py:69:11: E401 multiple imports on one line
|
| 98 |
+
optparse.py:77:1: E302 expected 2 blank lines, found 1
|
| 99 |
+
optparse.py:88:5: E301 expected 1 blank line, found 0
|
| 100 |
+
optparse.py:222:34: W602 deprecated form of raising exception
|
| 101 |
+
optparse.py:347:31: E211 whitespace before '('
|
| 102 |
+
optparse.py:357:17: E201 whitespace after '{'
|
| 103 |
+
optparse.py:472:29: E221 multiple spaces before operator
|
| 104 |
+
optparse.py:544:21: W601 .has_key() is deprecated, use 'in'
|
| 105 |
+
|
| 106 |
+
You can also make ``pycodestyle.py`` show the source code for each error, and
|
| 107 |
+
even the relevant text from PEP 8::
|
| 108 |
+
|
| 109 |
+
$ pycodestyle --show-source --show-pep8 testsuite/E40.py
|
| 110 |
+
testsuite/E40.py:2:10: E401 multiple imports on one line
|
| 111 |
+
import os, sys
|
| 112 |
+
^
|
| 113 |
+
Imports should usually be on separate lines.
|
| 114 |
+
|
| 115 |
+
Okay: import os\nimport sys
|
| 116 |
+
E401: import sys, os
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
Or you can display how often each error was found::
|
| 120 |
+
|
| 121 |
+
$ pycodestyle --statistics -qq Python-2.5/Lib
|
| 122 |
+
232 E201 whitespace after '['
|
| 123 |
+
599 E202 whitespace before ')'
|
| 124 |
+
631 E203 whitespace before ','
|
| 125 |
+
842 E211 whitespace before '('
|
| 126 |
+
2531 E221 multiple spaces before operator
|
| 127 |
+
4473 E301 expected 1 blank line, found 0
|
| 128 |
+
4006 E302 expected 2 blank lines, found 1
|
| 129 |
+
165 E303 too many blank lines (4)
|
| 130 |
+
325 E401 multiple imports on one line
|
| 131 |
+
3615 E501 line too long (82 characters)
|
| 132 |
+
612 W601 .has_key() is deprecated, use 'in'
|
| 133 |
+
1188 W602 deprecated form of raising exception
|
| 134 |
+
|
| 135 |
+
Links
|
| 136 |
+
-----
|
| 137 |
+
|
| 138 |
+
* `Read the documentation <https://pycodestyle.pycqa.org/>`_
|
| 139 |
+
|
| 140 |
+
* `Fork me on GitHub <http://github.com/PyCQA/pycodestyle>`_
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
Changelog
|
| 144 |
+
=========
|
| 145 |
+
|
| 146 |
+
2.8.0 (2021-10-10)
|
| 147 |
+
------------------
|
| 148 |
+
|
| 149 |
+
Changes:
|
| 150 |
+
|
| 151 |
+
* Drop python 3.4. PR #982.
|
| 152 |
+
* E712: fix false negative with multiple comparisons. PR #987.
|
| 153 |
+
* E211: fix false positives with ``match``. PR #989.
|
| 154 |
+
* E772: improve performance of bare except check. PR #992.
|
| 155 |
+
* Backport tokenize performance improvement from python 3.10. PR #993.
|
| 156 |
+
* E225: fix for lambdas containing positional-only args. PR #1012.
|
| 157 |
+
* Remove ``indent_size_str`` "setting". PR #995.
|
| 158 |
+
* E402: allow ``__all__`` to be typed. PR #1019.
|
| 159 |
+
* E225: fix false positives for ``*`` in ``case``. PR #1003.
|
| 160 |
+
* E201: detect tabs as whitespace. PR #1015.
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
2.7.0 (2021-03-14)
|
| 164 |
+
------------------
|
| 165 |
+
|
| 166 |
+
Changes:
|
| 167 |
+
|
| 168 |
+
* Fix physical checks (such as W191) at end of file. PR #961.
|
| 169 |
+
* Add ``--indent-size`` option (defaulting to ``4``). PR #970.
|
| 170 |
+
* W605: fix escaped crlf false positive on windows. PR #976.
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
2.6.0 (2020-05-11)
|
| 174 |
+
------------------
|
| 175 |
+
|
| 176 |
+
Announcements:
|
| 177 |
+
|
| 178 |
+
* Anthony Sottile (@asottile) joined the team as a core developer. :tada:
|
| 179 |
+
|
| 180 |
+
Changes:
|
| 181 |
+
|
| 182 |
+
* E306: fix detection inside ``async def``. PR #929.
|
| 183 |
+
* E301: fix regression disallowing decorated one-liners. PR #927.
|
| 184 |
+
* E714: fix false positive with chained ``is not``. PR #931.
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
2.6.0a1 (2020-04-23)
|
| 188 |
+
--------------------
|
| 189 |
+
|
| 190 |
+
New checks:
|
| 191 |
+
|
| 192 |
+
* E225: require whitespace around ``and`` ``in`` ``is`` and ``or``. PR #847.
|
| 193 |
+
|
| 194 |
+
Changes:
|
| 195 |
+
|
| 196 |
+
* E117: fix indentation using tabs by treating as 8-space indents. PR #837.
|
| 197 |
+
* E721: fix false positive with names containg ``istype``. PR #850.
|
| 198 |
+
* E741: allow ``l`` as a named argument in a function call. PR #853.
|
| 199 |
+
* E302: fix false-negative with decorated functions. PR #859.
|
| 200 |
+
* W504: ellipsis (``...``) is no longer treated as a binary operator. PR #875.
|
| 201 |
+
* E402: allow ``with``, ``if``, ``elif``, ``else`` to guard imports. PR #834.
|
| 202 |
+
* Add support for assignment expressions ``:=`` (PEP 572). PR #879.
|
| 203 |
+
* Add support for positional-only arguments ``/`` (PEP 570). PR #872, #918.
|
| 204 |
+
* Add support for python 3.8.
|
| 205 |
+
* Add support for matrix multiplication operator ``@`` (PEP 465). PR #897.
|
| 206 |
+
* Support visual indent for continuation lines for ``with`` / ``assert`` /
|
| 207 |
+
``raise``. PR #912.
|
| 208 |
+
* E302: allow two blank lines after a block of one-liners. PR #913.
|
| 209 |
+
* E302: allow two-and-fewer newlines at the top of the file. PR #919.
|
| 210 |
+
|
| 211 |
+
|
| 212 |
+
2.5.0 (2019-01-29)
|
| 213 |
+
------------------
|
| 214 |
+
|
| 215 |
+
New checks:
|
| 216 |
+
|
| 217 |
+
* E117: Over-indented code blocks
|
| 218 |
+
* W505: Maximum doc-string length only when configured with --max-doc-length
|
| 219 |
+
|
| 220 |
+
Changes:
|
| 221 |
+
|
| 222 |
+
* Remove support for EOL Python 2.6 and 3.3. PR #720.
|
| 223 |
+
* Add E117 error for over-indented code blocks.
|
| 224 |
+
* Allow W605 to be silenced by `# noqa` and fix the position reported by W605
|
| 225 |
+
* Allow users to omit blank lines around one-liner definitions of classes and
|
| 226 |
+
functions
|
| 227 |
+
* Include the function return annotation (``->``) as requiring surrounding
|
| 228 |
+
whitespace only on Python 3
|
| 229 |
+
* Verify that only names can follow ``await``. Previously we allowed numbers
|
| 230 |
+
and strings.
|
| 231 |
+
* Add support for Python 3.7
|
| 232 |
+
* Fix detection of annotated argument defaults for E252
|
| 233 |
+
* Correct the position reported by W504
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
2.4.0 (2018-04-10)
|
| 237 |
+
------------------
|
| 238 |
+
|
| 239 |
+
New checks:
|
| 240 |
+
|
| 241 |
+
* Add W504 warning for checking that a break doesn't happen after a binary
|
| 242 |
+
operator. This check is ignored by default. PR #502.
|
| 243 |
+
* Add W605 warning for invalid escape sequences in string literals. PR #676.
|
| 244 |
+
* Add W606 warning for 'async' and 'await' reserved keywords being introduced
|
| 245 |
+
in Python 3.7. PR #684.
|
| 246 |
+
* Add E252 error for missing whitespace around equal sign in type annotated
|
| 247 |
+
function arguments with defaults values. PR #717.
|
| 248 |
+
|
| 249 |
+
Changes:
|
| 250 |
+
|
| 251 |
+
* An internal bisect search has replaced a linear search in order to improve
|
| 252 |
+
efficiency. PR #648.
|
| 253 |
+
* pycodestyle now uses PyPI trove classifiers in order to document supported
|
| 254 |
+
python versions on PyPI. PR #654.
|
| 255 |
+
* 'setup.cfg' '[wheel]' section has been renamed to '[bdist_wheel]', as
|
| 256 |
+
the former is legacy. PR #653.
|
| 257 |
+
* pycodestyle now handles very long lines much more efficiently for python
|
| 258 |
+
3.2+. Fixes #643. PR #644.
|
| 259 |
+
* You can now write 'pycodestyle.StyleGuide(verbose=True)' instead of
|
| 260 |
+
'pycodestyle.StyleGuide(verbose=True, paths=['-v'])' in order to achieve
|
| 261 |
+
verbosity. PR #663.
|
| 262 |
+
* The distribution of pycodestyle now includes the license text in order to
|
| 263 |
+
comply with open source licenses which require this. PR #694.
|
| 264 |
+
* 'maximum_line_length' now ignores shebang ('#!') lines. PR #736.
|
| 265 |
+
* Add configuration option for the allowed number of blank lines. It is
|
| 266 |
+
implemented as a top level dictionary which can be easily overwritten. Fixes
|
| 267 |
+
#732. PR #733.
|
| 268 |
+
|
| 269 |
+
Bugs:
|
| 270 |
+
|
| 271 |
+
* Prevent a 'DeprecationWarning', and a 'SyntaxError' in future python, caused
|
| 272 |
+
by an invalid escape sequence. PR #625.
|
| 273 |
+
* Correctly report E501 when the first line of a docstring is too long.
|
| 274 |
+
Resolves #622. PR #630.
|
| 275 |
+
* Support variable annotation when variable start by a keyword, such as class
|
| 276 |
+
variable type annotations in python 3.6. PR #640.
|
| 277 |
+
* pycodestyle internals have been changed in order to allow 'python3 -m
|
| 278 |
+
cProfile' to report correct metrics. PR #647.
|
| 279 |
+
* Fix a spelling mistake in the description of E722. PR #697.
|
| 280 |
+
* 'pycodestyle --diff' now does not break if your 'gitconfig' enables
|
| 281 |
+
'mnemonicprefix'. PR #706.
|
| 282 |
+
|
| 283 |
+
2.3.1 (2017-01-31)
|
| 284 |
+
------------------
|
| 285 |
+
|
| 286 |
+
Bugs:
|
| 287 |
+
|
| 288 |
+
* Fix regression in detection of E302 and E306; #618, #620
|
| 289 |
+
|
| 290 |
+
2.3.0 (2017-01-30)
|
| 291 |
+
------------------
|
| 292 |
+
|
| 293 |
+
New Checks:
|
| 294 |
+
|
| 295 |
+
* Add E722 warning for bare ``except`` clauses
|
| 296 |
+
* Report E704 for async function definitions (``async def``)
|
| 297 |
+
|
| 298 |
+
Bugs:
|
| 299 |
+
|
| 300 |
+
* Fix another E305 false positive for variables beginning with "class" or
|
| 301 |
+
"def"
|
| 302 |
+
* Fix detection of multiple spaces between ``async`` and ``def``
|
| 303 |
+
* Fix handling of variable annotations. Stop reporting E701 on Python 3.6 for
|
| 304 |
+
variable annotations.
|
| 305 |
+
|
| 306 |
+
2.2.0 (2016-11-14)
|
| 307 |
+
------------------
|
| 308 |
+
|
| 309 |
+
Announcements:
|
| 310 |
+
|
| 311 |
+
* Added Make target to obtain proper tarball file permissions; #599
|
| 312 |
+
|
| 313 |
+
Bugs:
|
| 314 |
+
|
| 315 |
+
* Fixed E305 regression caused by #400; #593
|
| 316 |
+
|
| 317 |
+
2.1.0 (2016-11-04)
|
| 318 |
+
------------------
|
| 319 |
+
|
| 320 |
+
Announcements:
|
| 321 |
+
|
| 322 |
+
* Change all references to the pep8 project to say pycodestyle; #530
|
| 323 |
+
|
| 324 |
+
Changes:
|
| 325 |
+
|
| 326 |
+
* Report E302 for blank lines before an "async def"; #556
|
| 327 |
+
* Update our list of tested and supported Python versions which are 2.6, 2.7,
|
| 328 |
+
3.2, 3.3, 3.4 and 3.5 as well as the nightly Python build and PyPy.
|
| 329 |
+
* Report E742 and E743 for functions and classes badly named 'l', 'O', or 'I'.
|
| 330 |
+
* Report E741 on 'global' and 'nonlocal' statements, as well as prohibited
|
| 331 |
+
single-letter variables.
|
| 332 |
+
* Deprecated use of `[pep8]` section name in favor of `[pycodestyle]`; #591
|
| 333 |
+
* Report E722 when bare except clause is used; #579
|
| 334 |
+
|
| 335 |
+
Bugs:
|
| 336 |
+
|
| 337 |
+
* Fix opt_type AssertionError when using Flake8 2.6.2 and pycodestyle; #561
|
| 338 |
+
* Require two blank lines after toplevel def, class; #536
|
| 339 |
+
* Remove accidentally quadratic computation based on the number of colons. This
|
| 340 |
+
will make pycodestyle faster in some cases; #314
|
| 341 |
+
|
| 342 |
+
2.0.0 (2016-05-31)
|
| 343 |
+
------------------
|
| 344 |
+
|
| 345 |
+
Announcements:
|
| 346 |
+
|
| 347 |
+
* Repository renamed to `pycodestyle`; Issue #466 / #481.
|
| 348 |
+
* Added joint Code of Conduct as member of PyCQA; #483
|
| 349 |
+
|
| 350 |
+
Changes:
|
| 351 |
+
|
| 352 |
+
* Added tox test support for Python 3.5 and pypy3
|
| 353 |
+
* Added check E275 for whitespace on `from ... import ...` lines; #489 / #491
|
| 354 |
+
* Added W503 to the list of codes ignored by default ignore list; #498
|
| 355 |
+
* Removed use of project level `.pep8` configuration file; #364
|
| 356 |
+
|
| 357 |
+
Bugs:
|
| 358 |
+
|
| 359 |
+
* Fixed bug with treating `~` operator as binary; #383 / #384
|
| 360 |
+
* Identify binary operators as unary; #484 / #485
|
| 361 |
+
|
| 362 |
+
1.7.0 (2016-01-12)
|
| 363 |
+
------------------
|
| 364 |
+
|
| 365 |
+
Announcements:
|
| 366 |
+
|
| 367 |
+
* Repository moved to PyCQA Organization on GitHub:
|
| 368 |
+
https://github.com/pycqa/pep8
|
| 369 |
+
|
| 370 |
+
Changes:
|
| 371 |
+
|
| 372 |
+
* Reverted the fix in #368, "options passed on command line are only ones
|
| 373 |
+
accepted" feature. This has many unintended consequences in pep8 and flake8
|
| 374 |
+
and needs to be reworked when I have more time.
|
| 375 |
+
* Added support for Python 3.5. (Issue #420 & #459)
|
| 376 |
+
* Added support for multi-line config_file option parsing. (Issue #429)
|
| 377 |
+
* Improved parameter parsing. (Issues #420 & #456)
|
| 378 |
+
|
| 379 |
+
Bugs:
|
| 380 |
+
|
| 381 |
+
* Fixed BytesWarning on Python 3. (Issue #459)
|
| 382 |
+
|
| 383 |
+
1.6.2 (2015-02-15)
|
| 384 |
+
------------------
|
| 385 |
+
|
| 386 |
+
Changes:
|
| 387 |
+
|
| 388 |
+
* Added check for breaking around a binary operator. (Issue #197, Pull #305)
|
| 389 |
+
|
| 390 |
+
Bugs:
|
| 391 |
+
|
| 392 |
+
* Restored config_file parameter in process_options(). (Issue #380)
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
1.6.1 (2015-02-08)
|
| 396 |
+
------------------
|
| 397 |
+
|
| 398 |
+
Changes:
|
| 399 |
+
|
| 400 |
+
* Assign variables before referenced. (Issue #287)
|
| 401 |
+
|
| 402 |
+
Bugs:
|
| 403 |
+
|
| 404 |
+
* Exception thrown due to unassigned ``local_dir`` variable. (Issue #377)
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
1.6.0 (2015-02-06)
|
| 408 |
+
------------------
|
| 409 |
+
|
| 410 |
+
News:
|
| 411 |
+
|
| 412 |
+
* Ian Lee <ianlee1521@gmail.com> joined the project as a maintainer.
|
| 413 |
+
|
| 414 |
+
Changes:
|
| 415 |
+
|
| 416 |
+
* Report E731 for lambda assignment. (Issue #277)
|
| 417 |
+
|
| 418 |
+
* Report E704 for one-liner def instead of E701.
|
| 419 |
+
Do not report this error in the default configuration. (Issue #277)
|
| 420 |
+
|
| 421 |
+
* Replace codes E111, E112 and E113 with codes E114, E115 and E116
|
| 422 |
+
for bad indentation of comments. (Issue #274)
|
| 423 |
+
|
| 424 |
+
* Report E266 instead of E265 when the block comment starts with
|
| 425 |
+
multiple ``#``. (Issue #270)
|
| 426 |
+
|
| 427 |
+
* Report E402 for import statements not at the top of the file. (Issue #264)
|
| 428 |
+
|
| 429 |
+
* Do not enforce whitespaces around ``**`` operator. (Issue #292)
|
| 430 |
+
|
| 431 |
+
* Strip whitespace from around paths during normalization. (Issue #339 / #343)
|
| 432 |
+
|
| 433 |
+
* Update ``--format`` documentation. (Issue #198 / Pull Request #310)
|
| 434 |
+
|
| 435 |
+
* Add ``.tox/`` to default excludes. (Issue #335)
|
| 436 |
+
|
| 437 |
+
* Do not report E121 or E126 in the default configuration. (Issues #256 / #316)
|
| 438 |
+
|
| 439 |
+
* Allow spaces around the equals sign in an annotated function. (Issue #357)
|
| 440 |
+
|
| 441 |
+
* Allow trailing backslash if in an inline comment. (Issue #374)
|
| 442 |
+
|
| 443 |
+
* If ``--config`` is used, only that configuration is processed. Otherwise,
|
| 444 |
+
merge the user and local configurations are merged. (Issue #368 / #369)
|
| 445 |
+
|
| 446 |
+
Bug fixes:
|
| 447 |
+
|
| 448 |
+
* Don't crash if Checker.build_tokens_line() returns None. (Issue #306)
|
| 449 |
+
|
| 450 |
+
* Don't crash if os.path.expanduser() throws an ImportError. (Issue #297)
|
| 451 |
+
|
| 452 |
+
* Missing space around keyword parameter equal not always reported, E251.
|
| 453 |
+
(Issue #323)
|
| 454 |
+
|
| 455 |
+
* Fix false positive E711/E712/E713. (Issues #330 and #336)
|
| 456 |
+
|
| 457 |
+
* Do not skip physical checks if the newline is escaped. (Issue #319)
|
| 458 |
+
|
| 459 |
+
* Flush sys.stdout to avoid race conditions with printing. See flake8 bug:
|
| 460 |
+
https://gitlab.com/pycqa/flake8/issues/17 for more details. (Issue #363)
|
| 461 |
+
|
| 462 |
+
|
| 463 |
+
1.5.7 (2014-05-29)
|
| 464 |
+
------------------
|
| 465 |
+
|
| 466 |
+
Bug fixes:
|
| 467 |
+
|
| 468 |
+
* Skip the traceback on "Broken pipe" signal. (Issue #275)
|
| 469 |
+
|
| 470 |
+
* Do not exit when an option in ``setup.cfg`` or ``tox.ini``
|
| 471 |
+
is not recognized.
|
| 472 |
+
|
| 473 |
+
* Check the last line even if it does not end with a newline. (Issue #286)
|
| 474 |
+
|
| 475 |
+
* Always open files in universal newlines mode in Python 2. (Issue #288)
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
1.5.6 (2014-04-14)
|
| 479 |
+
------------------
|
| 480 |
+
|
| 481 |
+
Bug fixes:
|
| 482 |
+
|
| 483 |
+
* Check the last line even if it has no end-of-line. (Issue #273)
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
1.5.5 (2014-04-10)
|
| 487 |
+
------------------
|
| 488 |
+
|
| 489 |
+
Bug fixes:
|
| 490 |
+
|
| 491 |
+
* Fix regression with E22 checks and inline comments. (Issue #271)
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
1.5.4 (2014-04-07)
|
| 495 |
+
------------------
|
| 496 |
+
|
| 497 |
+
Bug fixes:
|
| 498 |
+
|
| 499 |
+
* Fix negative offset with E303 before a multi-line docstring.
|
| 500 |
+
(Issue #269)
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
1.5.3 (2014-04-04)
|
| 504 |
+
------------------
|
| 505 |
+
|
| 506 |
+
Bug fixes:
|
| 507 |
+
|
| 508 |
+
* Fix wrong offset computation when error is on the last char
|
| 509 |
+
of a physical line. (Issue #268)
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
1.5.2 (2014-04-04)
|
| 513 |
+
------------------
|
| 514 |
+
|
| 515 |
+
Changes:
|
| 516 |
+
|
| 517 |
+
* Distribute a universal wheel file.
|
| 518 |
+
|
| 519 |
+
Bug fixes:
|
| 520 |
+
|
| 521 |
+
* Report correct line number for E303 with comments. (Issue #60)
|
| 522 |
+
|
| 523 |
+
* Do not allow newline after parameter equal. (Issue #252)
|
| 524 |
+
|
| 525 |
+
* Fix line number reported for multi-line strings. (Issue #220)
|
| 526 |
+
|
| 527 |
+
* Fix false positive E121/E126 with multi-line strings. (Issue #265)
|
| 528 |
+
|
| 529 |
+
* Fix E501 not detected in comments with Python 2.5.
|
| 530 |
+
|
| 531 |
+
* Fix caret position with ``--show-source`` when line contains tabs.
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
1.5.1 (2014-03-27)
|
| 535 |
+
------------------
|
| 536 |
+
|
| 537 |
+
Bug fixes:
|
| 538 |
+
|
| 539 |
+
* Fix a crash with E125 on multi-line strings. (Issue #263)
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
1.5 (2014-03-26)
|
| 543 |
+
----------------
|
| 544 |
+
|
| 545 |
+
Changes:
|
| 546 |
+
|
| 547 |
+
* Report E129 instead of E125 for visually indented line with same
|
| 548 |
+
indent as next logical line. (Issue #126)
|
| 549 |
+
|
| 550 |
+
* Report E265 for space before block comment. (Issue #190)
|
| 551 |
+
|
| 552 |
+
* Report E713 and E714 when operators ``not in`` and ``is not`` are
|
| 553 |
+
recommended. (Issue #236)
|
| 554 |
+
|
| 555 |
+
* Allow long lines in multiline strings and comments if they cannot
|
| 556 |
+
be wrapped. (Issue #224).
|
| 557 |
+
|
| 558 |
+
* Optionally disable physical line checks inside multiline strings,
|
| 559 |
+
using ``# noqa``. (Issue #242)
|
| 560 |
+
|
| 561 |
+
* Change text for E121 to report "continuation line under-indented
|
| 562 |
+
for hanging indent" instead of indentation not being a
|
| 563 |
+
multiple of 4.
|
| 564 |
+
|
| 565 |
+
* Report E131 instead of E121 / E126 if the hanging indent is not
|
| 566 |
+
consistent within the same continuation block. It helps when
|
| 567 |
+
error E121 or E126 is in the ``ignore`` list.
|
| 568 |
+
|
| 569 |
+
* Report E126 instead of E121 when the continuation line is hanging
|
| 570 |
+
with extra indentation, even if indentation is not a multiple of 4.
|
| 571 |
+
|
| 572 |
+
Bug fixes:
|
| 573 |
+
|
| 574 |
+
* Allow the checkers to report errors on empty files. (Issue #240)
|
| 575 |
+
|
| 576 |
+
* Fix ignoring too many checks when ``--select`` is used with codes
|
| 577 |
+
declared in a flake8 extension. (Issue #216)
|
| 578 |
+
|
| 579 |
+
* Fix regression with multiple brackets. (Issue #214)
|
| 580 |
+
|
| 581 |
+
* Fix ``StyleGuide`` to parse the local configuration if the
|
| 582 |
+
keyword argument ``paths`` is specified. (Issue #246)
|
| 583 |
+
|
| 584 |
+
* Fix a false positive E124 for hanging indent. (Issue #254)
|
| 585 |
+
|
| 586 |
+
* Fix a false positive E126 with embedded colon. (Issue #144)
|
| 587 |
+
|
| 588 |
+
* Fix a false positive E126 when indenting with tabs. (Issue #204)
|
| 589 |
+
|
| 590 |
+
* Fix behaviour when ``exclude`` is in the configuration file and
|
| 591 |
+
the current directory is not the project directory. (Issue #247)
|
| 592 |
+
|
| 593 |
+
* The logical checks can return ``None`` instead of an empty iterator.
|
| 594 |
+
(Issue #250)
|
| 595 |
+
|
| 596 |
+
* Do not report multiple E101 if only the first indentation starts
|
| 597 |
+
with a tab. (Issue #237)
|
| 598 |
+
|
| 599 |
+
* Fix a rare false positive W602. (Issue #34)
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
1.4.6 (2013-07-02)
|
| 603 |
+
------------------
|
| 604 |
+
|
| 605 |
+
Changes:
|
| 606 |
+
|
| 607 |
+
* Honor ``# noqa`` for errors E711 and E712. (Issue #180)
|
| 608 |
+
|
| 609 |
+
* When both a ``tox.ini`` and a ``setup.cfg`` are present in the project
|
| 610 |
+
directory, merge their contents. The ``tox.ini`` file takes
|
| 611 |
+
precedence (same as before). (Issue #182)
|
| 612 |
+
|
| 613 |
+
* Give priority to ``--select`` over ``--ignore``. (Issue #188)
|
| 614 |
+
|
| 615 |
+
* Compare full path when excluding a file. (Issue #186)
|
| 616 |
+
|
| 617 |
+
* New option ``--hang-closing`` to switch to the alternative style of
|
| 618 |
+
closing bracket indentation for hanging indent. Add error E133 for
|
| 619 |
+
closing bracket which is missing indentation. (Issue #103)
|
| 620 |
+
|
| 621 |
+
* Accept both styles of closing bracket indentation for hanging indent.
|
| 622 |
+
Do not report error E123 in the default configuration. (Issue #103)
|
| 623 |
+
|
| 624 |
+
Bug fixes:
|
| 625 |
+
|
| 626 |
+
* Do not crash when running AST checks and the document contains null bytes.
|
| 627 |
+
(Issue #184)
|
| 628 |
+
|
| 629 |
+
* Correctly report other E12 errors when E123 is ignored. (Issue #103)
|
| 630 |
+
|
| 631 |
+
* Fix false positive E261/E262 when the file contains a BOM. (Issue #193)
|
| 632 |
+
|
| 633 |
+
* Fix E701, E702 and E703 not detected sometimes. (Issue #196)
|
| 634 |
+
|
| 635 |
+
* Fix E122 not detected in some cases. (Issue #201 and #208)
|
| 636 |
+
|
| 637 |
+
* Fix false positive E121 with multiple brackets. (Issue #203)
|
| 638 |
+
|
| 639 |
+
|
| 640 |
+
1.4.5 (2013-03-06)
|
| 641 |
+
------------------
|
| 642 |
+
|
| 643 |
+
* When no path is specified, do not try to read from stdin. The feature
|
| 644 |
+
was added in 1.4.3, but it is not supported on Windows. Use ``-``
|
| 645 |
+
filename argument to read from stdin. This usage is supported
|
| 646 |
+
since 1.3.4. (Issue #170)
|
| 647 |
+
|
| 648 |
+
* Do not require ``setuptools`` in setup.py. It works around an issue
|
| 649 |
+
with ``pip`` and Python 3. (Issue #172)
|
| 650 |
+
|
| 651 |
+
* Add ``__pycache__`` to the ignore list.
|
| 652 |
+
|
| 653 |
+
* Change misleading message for E251. (Issue #171)
|
| 654 |
+
|
| 655 |
+
* Do not report false E302 when the source file has a coding cookie or a
|
| 656 |
+
comment on the first line. (Issue #174)
|
| 657 |
+
|
| 658 |
+
* Reorganize the tests and add tests for the API and for the command line
|
| 659 |
+
usage and options. (Issues #161 and #162)
|
| 660 |
+
|
| 661 |
+
* Ignore all checks which are not explicitly selected when ``select`` is
|
| 662 |
+
passed to the ``StyleGuide`` constructor.
|
| 663 |
+
|
| 664 |
+
|
| 665 |
+
1.4.4 (2013-02-24)
|
| 666 |
+
------------------
|
| 667 |
+
|
| 668 |
+
* Report E227 or E228 instead of E225 for whitespace around bitwise, shift
|
| 669 |
+
or modulo operators. (Issue #166)
|
| 670 |
+
|
| 671 |
+
* Change the message for E226 to make clear that it is about arithmetic
|
| 672 |
+
operators.
|
| 673 |
+
|
| 674 |
+
* Fix a false positive E128 for continuation line indentation with tabs.
|
| 675 |
+
|
| 676 |
+
* Fix regression with the ``--diff`` option. (Issue #169)
|
| 677 |
+
|
| 678 |
+
* Fix the ``TestReport`` class to print the unexpected warnings and
|
| 679 |
+
errors.
|
| 680 |
+
|
| 681 |
+
|
| 682 |
+
1.4.3 (2013-02-22)
|
| 683 |
+
------------------
|
| 684 |
+
|
| 685 |
+
* Hide the ``--doctest`` and ``--testsuite`` options when installed.
|
| 686 |
+
|
| 687 |
+
* Fix crash with AST checkers when the syntax is invalid. (Issue #160)
|
| 688 |
+
|
| 689 |
+
* Read from standard input if no path is specified.
|
| 690 |
+
|
| 691 |
+
* Initiate a graceful shutdown on ``Control+C``.
|
| 692 |
+
|
| 693 |
+
* Allow changing the ``checker_class`` for the ``StyleGuide``.
|
| 694 |
+
|
| 695 |
+
|
| 696 |
+
1.4.2 (2013-02-10)
|
| 697 |
+
------------------
|
| 698 |
+
|
| 699 |
+
* Support AST checkers provided by third-party applications.
|
| 700 |
+
|
| 701 |
+
* Register new checkers with ``register_check(func_or_cls, codes)``.
|
| 702 |
+
|
| 703 |
+
* Allow constructing a ``StyleGuide`` with a custom parser.
|
| 704 |
+
|
| 705 |
+
* Accept visual indentation without parenthesis after the ``if``
|
| 706 |
+
statement. (Issue #151)
|
| 707 |
+
|
| 708 |
+
* Fix UnboundLocalError when using ``# noqa`` with continued lines.
|
| 709 |
+
(Issue #158)
|
| 710 |
+
|
| 711 |
+
* Re-order the lines for the ``StandardReport``.
|
| 712 |
+
|
| 713 |
+
* Expand tabs when checking E12 continuation lines. (Issue #155)
|
| 714 |
+
|
| 715 |
+
* Refactor the testing class ``TestReport`` and the specific test
|
| 716 |
+
functions into a separate test module.
|
| 717 |
+
|
| 718 |
+
|
| 719 |
+
1.4.1 (2013-01-18)
|
| 720 |
+
------------------
|
| 721 |
+
|
| 722 |
+
* Allow sphinx.ext.autodoc syntax for comments. (Issue #110)
|
| 723 |
+
|
| 724 |
+
* Report E703 instead of E702 for the trailing semicolon. (Issue #117)
|
| 725 |
+
|
| 726 |
+
* Honor ``# noqa`` in addition to ``# nopep8``. (Issue #149)
|
| 727 |
+
|
| 728 |
+
* Expose the ``OptionParser`` factory for better extensibility.
|
| 729 |
+
|
| 730 |
+
|
| 731 |
+
1.4 (2012-12-22)
|
| 732 |
+
----------------
|
| 733 |
+
|
| 734 |
+
* Report E226 instead of E225 for optional whitespace around common
|
| 735 |
+
operators (``*``, ``**``, ``/``, ``+`` and ``-``). This new error
|
| 736 |
+
code is ignored in the default configuration because PEP 8 recommends
|
| 737 |
+
to "use your own judgement". (Issue #96)
|
| 738 |
+
|
| 739 |
+
* Lines with a ``# nopep8`` at the end will not issue errors on line
|
| 740 |
+
length E501 or continuation line indentation E12*. (Issue #27)
|
| 741 |
+
|
| 742 |
+
* Fix AssertionError when the source file contains an invalid line
|
| 743 |
+
ending ``"\r\r\n"``. (Issue #119)
|
| 744 |
+
|
| 745 |
+
* Read the ``[pep8]`` section of ``tox.ini`` or ``setup.cfg`` if present.
|
| 746 |
+
(Issue #93 and #141)
|
| 747 |
+
|
| 748 |
+
* Add the Sphinx-based documentation, and publish it
|
| 749 |
+
on https://pycodestyle.readthedocs.io/. (Issue #105)
|
| 750 |
+
|
| 751 |
+
|
| 752 |
+
1.3.4 (2012-12-18)
|
| 753 |
+
------------------
|
| 754 |
+
|
| 755 |
+
* Fix false positive E124 and E128 with comments. (Issue #100)
|
| 756 |
+
|
| 757 |
+
* Fix error on stdin when running with bpython. (Issue #101)
|
| 758 |
+
|
| 759 |
+
* Fix false positive E401. (Issue #104)
|
| 760 |
+
|
| 761 |
+
* Report E231 for nested dictionary in list. (Issue #142)
|
| 762 |
+
|
| 763 |
+
* Catch E271 at the beginning of the line. (Issue #133)
|
| 764 |
+
|
| 765 |
+
* Fix false positive E126 for multi-line comments. (Issue #138)
|
| 766 |
+
|
| 767 |
+
* Fix false positive E221 when operator is preceded by a comma. (Issue #135)
|
| 768 |
+
|
| 769 |
+
* Fix ``--diff`` failing on one-line hunk. (Issue #137)
|
| 770 |
+
|
| 771 |
+
* Fix the ``--exclude`` switch for directory paths. (Issue #111)
|
| 772 |
+
|
| 773 |
+
* Use ``-`` filename to read from standard input. (Issue #128)
|
| 774 |
+
|
| 775 |
+
|
| 776 |
+
1.3.3 (2012-06-27)
|
| 777 |
+
------------------
|
| 778 |
+
|
| 779 |
+
* Fix regression with continuation line checker. (Issue #98)
|
| 780 |
+
|
| 781 |
+
|
| 782 |
+
1.3.2 (2012-06-26)
|
| 783 |
+
------------------
|
| 784 |
+
|
| 785 |
+
* Revert to the previous behaviour for ``--show-pep8``:
|
| 786 |
+
do not imply ``--first``. (Issue #89)
|
| 787 |
+
|
| 788 |
+
* Add E902 for IO errors. (Issue #87)
|
| 789 |
+
|
| 790 |
+
* Fix false positive for E121, and missed E124. (Issue #92)
|
| 791 |
+
|
| 792 |
+
* Set a sensible default path for config file on Windows. (Issue #95)
|
| 793 |
+
|
| 794 |
+
* Allow ``verbose`` in the configuration file. (Issue #91)
|
| 795 |
+
|
| 796 |
+
* Show the enforced ``max-line-length`` in the error message. (Issue #86)
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
1.3.1 (2012-06-18)
|
| 800 |
+
------------------
|
| 801 |
+
|
| 802 |
+
* Explain which configuration options are expected. Accept and recommend
|
| 803 |
+
the options names with hyphen instead of underscore. (Issue #82)
|
| 804 |
+
|
| 805 |
+
* Do not read the user configuration when used as a module
|
| 806 |
+
(except if ``config_file=True`` is passed to the ``StyleGuide`` constructor).
|
| 807 |
+
|
| 808 |
+
* Fix wrong or missing cases for the E12 series.
|
| 809 |
+
|
| 810 |
+
* Fix cases where E122 was missed. (Issue #81)
|
| 811 |
+
|
| 812 |
+
|
| 813 |
+
1.3 (2012-06-15)
|
| 814 |
+
----------------
|
| 815 |
+
|
| 816 |
+
.. warning::
|
| 817 |
+
The internal API is backwards incompatible.
|
| 818 |
+
|
| 819 |
+
* Remove global configuration and refactor the library around
|
| 820 |
+
a ``StyleGuide`` class; add the ability to configure various
|
| 821 |
+
reporters. (Issue #35 and #66)
|
| 822 |
+
|
| 823 |
+
* Read user configuration from ``~/.config/pep8``
|
| 824 |
+
and local configuration from ``./.pep8``. (Issue #22)
|
| 825 |
+
|
| 826 |
+
* Fix E502 for backslash embedded in multi-line string. (Issue #68)
|
| 827 |
+
|
| 828 |
+
* Fix E225 for Python 3 iterable unpacking (PEP 3132). (Issue #72)
|
| 829 |
+
|
| 830 |
+
* Enable the new checkers from the E12 series in the default
|
| 831 |
+
configuration.
|
| 832 |
+
|
| 833 |
+
* Suggest less error-prone alternatives for E712 errors.
|
| 834 |
+
|
| 835 |
+
* Rewrite checkers to run faster (E22, E251, E27).
|
| 836 |
+
|
| 837 |
+
* Fixed a crash when parsed code is invalid (too many
|
| 838 |
+
closing brackets).
|
| 839 |
+
|
| 840 |
+
* Fix E127 and E128 for continuation line indentation. (Issue #74)
|
| 841 |
+
|
| 842 |
+
* New option ``--format`` to customize the error format. (Issue #23)
|
| 843 |
+
|
| 844 |
+
* New option ``--diff`` to check only modified code. The unified
|
| 845 |
+
diff is read from STDIN. Example: ``hg diff | pep8 --diff``
|
| 846 |
+
(Issue #39)
|
| 847 |
+
|
| 848 |
+
* Correctly report the count of failures and set the exit code to 1
|
| 849 |
+
when the ``--doctest`` or the ``--testsuite`` fails.
|
| 850 |
+
|
| 851 |
+
* Correctly detect the encoding in Python 3. (Issue #69)
|
| 852 |
+
|
| 853 |
+
* Drop support for Python 2.3, 2.4 and 3.0. (Issue #78)
|
| 854 |
+
|
| 855 |
+
|
| 856 |
+
1.2 (2012-06-01)
|
| 857 |
+
----------------
|
| 858 |
+
|
| 859 |
+
* Add E121 through E128 for continuation line indentation. These
|
| 860 |
+
checks are disabled by default. If you want to force all checks,
|
| 861 |
+
use switch ``--select=E,W``. Patch by Sam Vilain. (Issue #64)
|
| 862 |
+
|
| 863 |
+
* Add E721 for direct type comparisons. (Issue #47)
|
| 864 |
+
|
| 865 |
+
* Add E711 and E712 for comparisons to singletons. (Issue #46)
|
| 866 |
+
|
| 867 |
+
* Fix spurious E225 and E701 for function annotations. (Issue #29)
|
| 868 |
+
|
| 869 |
+
* Add E502 for explicit line join between brackets.
|
| 870 |
+
|
| 871 |
+
* Fix E901 when printing source with ``--show-source``.
|
| 872 |
+
|
| 873 |
+
* Report all errors for each checker, instead of reporting only the
|
| 874 |
+
first occurrence for each line.
|
| 875 |
+
|
| 876 |
+
* Option ``--show-pep8`` implies ``--first``.
|
| 877 |
+
|
| 878 |
+
|
| 879 |
+
1.1 (2012-05-24)
|
| 880 |
+
----------------
|
| 881 |
+
|
| 882 |
+
* Add E901 for syntax errors. (Issues #63 and #30)
|
| 883 |
+
|
| 884 |
+
* Add E271, E272, E273 and E274 for extraneous whitespace around
|
| 885 |
+
keywords. (Issue #57)
|
| 886 |
+
|
| 887 |
+
* Add ``tox.ini`` configuration file for tests. (Issue #61)
|
| 888 |
+
|
| 889 |
+
* Add ``.travis.yml`` configuration file for continuous integration.
|
| 890 |
+
(Issue #62)
|
| 891 |
+
|
| 892 |
+
|
| 893 |
+
1.0.1 (2012-04-06)
|
| 894 |
+
------------------
|
| 895 |
+
|
| 896 |
+
* Fix inconsistent version numbers.
|
| 897 |
+
|
| 898 |
+
|
| 899 |
+
1.0 (2012-04-04)
|
| 900 |
+
----------------
|
| 901 |
+
|
| 902 |
+
* Fix W602 ``raise`` to handle multi-char names. (Issue #53)
|
| 903 |
+
|
| 904 |
+
|
| 905 |
+
0.7.0 (2012-03-26)
|
| 906 |
+
------------------
|
| 907 |
+
|
| 908 |
+
* Now ``--first`` prints only the first occurrence of each error.
|
| 909 |
+
The ``--repeat`` flag becomes obsolete because it is the default
|
| 910 |
+
behaviour. (Issue #6)
|
| 911 |
+
|
| 912 |
+
* Allow specifying ``--max-line-length``. (Issue #36)
|
| 913 |
+
|
| 914 |
+
* Make the shebang more flexible. (Issue #26)
|
| 915 |
+
|
| 916 |
+
* Add testsuite to the bundle. (Issue #25)
|
| 917 |
+
|
| 918 |
+
* Fixes for Jython. (Issue #49)
|
| 919 |
+
|
| 920 |
+
* Add PyPI classifiers. (Issue #43)
|
| 921 |
+
|
| 922 |
+
* Fix the ``--exclude`` option. (Issue #48)
|
| 923 |
+
|
| 924 |
+
* Fix W602, accept ``raise`` with 3 arguments. (Issue #34)
|
| 925 |
+
|
| 926 |
+
* Correctly select all tests if ``DEFAULT_IGNORE == ''``.
|
| 927 |
+
|
| 928 |
+
|
| 929 |
+
0.6.1 (2010-10-03)
|
| 930 |
+
------------------
|
| 931 |
+
|
| 932 |
+
* Fix inconsistent version numbers. (Issue #21)
|
| 933 |
+
|
| 934 |
+
|
| 935 |
+
0.6.0 (2010-09-19)
|
| 936 |
+
------------------
|
| 937 |
+
|
| 938 |
+
* Test suite reorganized and enhanced in order to check more failures
|
| 939 |
+
with fewer test files. Read the ``run_tests`` docstring for details
|
| 940 |
+
about the syntax.
|
| 941 |
+
|
| 942 |
+
* Fix E225: accept ``print >>sys.stderr, "..."`` syntax.
|
| 943 |
+
|
| 944 |
+
* Fix E501 for lines containing multibyte encoded characters. (Issue #7)
|
| 945 |
+
|
| 946 |
+
* Fix E221, E222, E223, E224 not detected in some cases. (Issue #16)
|
| 947 |
+
|
| 948 |
+
* Fix E211 to reject ``v = dic['a'] ['b']``. (Issue #17)
|
| 949 |
+
|
| 950 |
+
* Exit code is always 1 if any error or warning is found. (Issue #10)
|
| 951 |
+
|
| 952 |
+
* ``--ignore`` checks are now really ignored, especially in
|
| 953 |
+
conjunction with ``--count``. (Issue #8)
|
| 954 |
+
|
| 955 |
+
* Blank lines with spaces yield W293 instead of W291: some developers
|
| 956 |
+
want to ignore this warning and indent the blank lines to paste their
|
| 957 |
+
code easily in the Python interpreter.
|
| 958 |
+
|
| 959 |
+
* Fix E301: do not require a blank line before an indented block. (Issue #14)
|
| 960 |
+
|
| 961 |
+
* Fix E203 to accept NumPy slice notation ``a[0, :]``. (Issue #13)
|
| 962 |
+
|
| 963 |
+
* Performance improvements.
|
| 964 |
+
|
| 965 |
+
* Fix decoding and checking non-UTF8 files in Python 3.
|
| 966 |
+
|
| 967 |
+
* Fix E225: reject ``True+False`` when running on Python 3.
|
| 968 |
+
|
| 969 |
+
* Fix an exception when the line starts with an operator.
|
| 970 |
+
|
| 971 |
+
* Allow a new line before closing ``)``, ``}`` or ``]``. (Issue #5)
|
| 972 |
+
|
| 973 |
+
|
| 974 |
+
0.5.0 (2010-02-17)
|
| 975 |
+
------------------
|
| 976 |
+
|
| 977 |
+
* Changed the ``--count`` switch to print to sys.stderr and set
|
| 978 |
+
exit code to 1 if any error or warning is found.
|
| 979 |
+
|
| 980 |
+
* E241 and E242 are removed from the standard checks. If you want to
|
| 981 |
+
include these checks, use switch ``--select=E,W``. (Issue #4)
|
| 982 |
+
|
| 983 |
+
* Blank line is not mandatory before the first class method or nested
|
| 984 |
+
function definition, even if there's a docstring. (Issue #1)
|
| 985 |
+
|
| 986 |
+
* Add the switch ``--version``.
|
| 987 |
+
|
| 988 |
+
* Fix decoding errors with Python 3. (Issue #13 [1]_)
|
| 989 |
+
|
| 990 |
+
* Add ``--select`` option which is mirror of ``--ignore``.
|
| 991 |
+
|
| 992 |
+
* Add checks E261 and E262 for spaces before inline comments.
|
| 993 |
+
|
| 994 |
+
* New check W604 warns about deprecated usage of backticks.
|
| 995 |
+
|
| 996 |
+
* New check W603 warns about the deprecated operator ``<>``.
|
| 997 |
+
|
| 998 |
+
* Performance improvement, due to rewriting of E225.
|
| 999 |
+
|
| 1000 |
+
* E225 now accepts:
|
| 1001 |
+
|
| 1002 |
+
- no whitespace after unary operator or similar. (Issue #9 [1]_)
|
| 1003 |
+
|
| 1004 |
+
- lambda function with argument unpacking or keyword defaults.
|
| 1005 |
+
|
| 1006 |
+
* Reserve "2 blank lines" for module-level logical blocks. (E303)
|
| 1007 |
+
|
| 1008 |
+
* Allow multi-line comments. (E302, issue #10 [1]_)
|
| 1009 |
+
|
| 1010 |
+
|
| 1011 |
+
0.4.2 (2009-10-22)
|
| 1012 |
+
------------------
|
| 1013 |
+
|
| 1014 |
+
* Decorators on classes and class methods are OK now.
|
| 1015 |
+
|
| 1016 |
+
|
| 1017 |
+
0.4 (2009-10-20)
|
| 1018 |
+
----------------
|
| 1019 |
+
|
| 1020 |
+
* Support for all versions of Python from 2.3 to 3.1.
|
| 1021 |
+
|
| 1022 |
+
* New and greatly expanded self tests.
|
| 1023 |
+
|
| 1024 |
+
* Added ``--count`` option to print the total number of errors and warnings.
|
| 1025 |
+
|
| 1026 |
+
* Further improvements to the handling of comments and blank lines.
|
| 1027 |
+
(Issue #1 [1]_ and others changes.)
|
| 1028 |
+
|
| 1029 |
+
* Check all py files in directory when passed a directory (Issue
|
| 1030 |
+
#2 [1]_). This also prevents an exception when traversing directories
|
| 1031 |
+
with non ``*.py`` files.
|
| 1032 |
+
|
| 1033 |
+
* E231 should allow commas to be followed by ``)``. (Issue #3 [1]_)
|
| 1034 |
+
|
| 1035 |
+
* Spaces are no longer required around the equals sign for keyword
|
| 1036 |
+
arguments or default parameter values.
|
| 1037 |
+
|
| 1038 |
+
|
| 1039 |
+
.. [1] These issues refer to the `previous issue tracker`__.
|
| 1040 |
+
.. __: http://github.com/cburroughs/pep8.py/issues
|
| 1041 |
+
|
| 1042 |
+
|
| 1043 |
+
0.3.1 (2009-09-14)
|
| 1044 |
+
------------------
|
| 1045 |
+
|
| 1046 |
+
* Fixes for comments: do not count them when checking for blank lines between
|
| 1047 |
+
items.
|
| 1048 |
+
|
| 1049 |
+
* Added setup.py for pypi upload and easy_installability.
|
| 1050 |
+
|
| 1051 |
+
|
| 1052 |
+
0.2 (2007-10-16)
|
| 1053 |
+
----------------
|
| 1054 |
+
|
| 1055 |
+
* Loads of fixes and improvements.
|
| 1056 |
+
|
| 1057 |
+
|
| 1058 |
+
0.1 (2006-10-01)
|
| 1059 |
+
----------------
|
| 1060 |
+
|
| 1061 |
+
* First release.
|
| 1062 |
+
|
| 1063 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
../../../bin/pycodestyle,sha256=YqpyFg8K_Q6SXk7DJ80K4Q6wKmZU1G06Ti8XKbcJwAA,230
|
| 2 |
+
__pycache__/pycodestyle.cpython-38.pyc,,
|
| 3 |
+
pycodestyle-2.8.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 4 |
+
pycodestyle-2.8.0.dist-info/LICENSE,sha256=93IpXoGvNHjTTojlLQdiACMOx91qOeEjvFyzWqZqva4,1254
|
| 5 |
+
pycodestyle-2.8.0.dist-info/METADATA,sha256=jLxHgy1ywol0Yu2cxoVLIw4XMOlUaUUDZijfTUFV2uY,31230
|
| 6 |
+
pycodestyle-2.8.0.dist-info/RECORD,,
|
| 7 |
+
pycodestyle-2.8.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 8 |
+
pycodestyle-2.8.0.dist-info/WHEEL,sha256=WzZ8cwjh8l0jtULNjYq1Hpr-WCqCRgPr--TX4P5I1Wo,110
|
| 9 |
+
pycodestyle-2.8.0.dist-info/entry_points.txt,sha256=6JU_7SAppC93MBSQi1_QxDwEQUyg6cgK71ab9q_Hxco,51
|
| 10 |
+
pycodestyle-2.8.0.dist-info/namespace_packages.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
| 11 |
+
pycodestyle-2.8.0.dist-info/top_level.txt,sha256=rHbIEiXmvsJ016mFcLVcF_d-dKgP3VdfOB6CWbivZug,12
|
| 12 |
+
pycodestyle.py,sha256=3-O2ixYLkFoim3-EN1XLtHL2-oJafe6BQKrY2nbkrA4,105016
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/REQUESTED
ADDED
|
File without changes
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: bdist_wheel (0.37.0)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py2-none-any
|
| 5 |
+
Tag: py3-none-any
|
| 6 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/entry_points.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[console_scripts]
|
| 2 |
+
pycodestyle = pycodestyle:_main
|
| 3 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/namespace_packages.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/pycodestyle-2.8.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pycodestyle
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/__init__.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# __
|
| 2 |
+
# /__) _ _ _ _ _/ _
|
| 3 |
+
# / ( (- (/ (/ (- _) / _)
|
| 4 |
+
# /
|
| 5 |
+
|
| 6 |
+
"""
|
| 7 |
+
Requests HTTP Library
|
| 8 |
+
~~~~~~~~~~~~~~~~~~~~~
|
| 9 |
+
|
| 10 |
+
Requests is an HTTP library, written in Python, for human beings.
|
| 11 |
+
Basic GET usage:
|
| 12 |
+
|
| 13 |
+
>>> import requests
|
| 14 |
+
>>> r = requests.get('https://www.python.org')
|
| 15 |
+
>>> r.status_code
|
| 16 |
+
200
|
| 17 |
+
>>> b'Python is a programming language' in r.content
|
| 18 |
+
True
|
| 19 |
+
|
| 20 |
+
... or POST:
|
| 21 |
+
|
| 22 |
+
>>> payload = dict(key1='value1', key2='value2')
|
| 23 |
+
>>> r = requests.post('https://httpbin.org/post', data=payload)
|
| 24 |
+
>>> print(r.text)
|
| 25 |
+
{
|
| 26 |
+
...
|
| 27 |
+
"form": {
|
| 28 |
+
"key1": "value1",
|
| 29 |
+
"key2": "value2"
|
| 30 |
+
},
|
| 31 |
+
...
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
The other HTTP methods are supported - see `requests.api`. Full documentation
|
| 35 |
+
is at <https://requests.readthedocs.io>.
|
| 36 |
+
|
| 37 |
+
:copyright: (c) 2017 by Kenneth Reitz.
|
| 38 |
+
:license: Apache 2.0, see LICENSE for more details.
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
import warnings
|
| 42 |
+
|
| 43 |
+
import urllib3
|
| 44 |
+
|
| 45 |
+
from .exceptions import RequestsDependencyWarning
|
| 46 |
+
|
| 47 |
+
try:
|
| 48 |
+
from charset_normalizer import __version__ as charset_normalizer_version
|
| 49 |
+
except ImportError:
|
| 50 |
+
charset_normalizer_version = None
|
| 51 |
+
|
| 52 |
+
try:
|
| 53 |
+
from chardet import __version__ as chardet_version
|
| 54 |
+
except ImportError:
|
| 55 |
+
chardet_version = None
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version):
|
| 59 |
+
urllib3_version = urllib3_version.split(".")
|
| 60 |
+
assert urllib3_version != ["dev"] # Verify urllib3 isn't installed from git.
|
| 61 |
+
|
| 62 |
+
# Sometimes, urllib3 only reports its version as 16.1.
|
| 63 |
+
if len(urllib3_version) == 2:
|
| 64 |
+
urllib3_version.append("0")
|
| 65 |
+
|
| 66 |
+
# Check urllib3 for compatibility.
|
| 67 |
+
major, minor, patch = urllib3_version # noqa: F811
|
| 68 |
+
major, minor, patch = int(major), int(minor), int(patch)
|
| 69 |
+
# urllib3 >= 1.21.1, <= 1.26
|
| 70 |
+
assert major == 1
|
| 71 |
+
assert minor >= 21
|
| 72 |
+
assert minor <= 26
|
| 73 |
+
|
| 74 |
+
# Check charset_normalizer for compatibility.
|
| 75 |
+
if chardet_version:
|
| 76 |
+
major, minor, patch = chardet_version.split(".")[:3]
|
| 77 |
+
major, minor, patch = int(major), int(minor), int(patch)
|
| 78 |
+
# chardet_version >= 3.0.2, < 5.0.0
|
| 79 |
+
assert (3, 0, 2) <= (major, minor, patch) < (5, 0, 0)
|
| 80 |
+
elif charset_normalizer_version:
|
| 81 |
+
major, minor, patch = charset_normalizer_version.split(".")[:3]
|
| 82 |
+
major, minor, patch = int(major), int(minor), int(patch)
|
| 83 |
+
# charset_normalizer >= 2.0.0 < 3.0.0
|
| 84 |
+
assert (2, 0, 0) <= (major, minor, patch) < (3, 0, 0)
|
| 85 |
+
else:
|
| 86 |
+
raise Exception("You need either charset_normalizer or chardet installed")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def _check_cryptography(cryptography_version):
|
| 90 |
+
# cryptography < 1.3.4
|
| 91 |
+
try:
|
| 92 |
+
cryptography_version = list(map(int, cryptography_version.split(".")))
|
| 93 |
+
except ValueError:
|
| 94 |
+
return
|
| 95 |
+
|
| 96 |
+
if cryptography_version < [1, 3, 4]:
|
| 97 |
+
warning = "Old version of cryptography ({}) may cause slowdown.".format(
|
| 98 |
+
cryptography_version
|
| 99 |
+
)
|
| 100 |
+
warnings.warn(warning, RequestsDependencyWarning)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
# Check imported dependencies for compatibility.
|
| 104 |
+
try:
|
| 105 |
+
check_compatibility(
|
| 106 |
+
urllib3.__version__, chardet_version, charset_normalizer_version
|
| 107 |
+
)
|
| 108 |
+
except (AssertionError, ValueError):
|
| 109 |
+
warnings.warn(
|
| 110 |
+
"urllib3 ({}) or chardet ({})/charset_normalizer ({}) doesn't match a supported "
|
| 111 |
+
"version!".format(
|
| 112 |
+
urllib3.__version__, chardet_version, charset_normalizer_version
|
| 113 |
+
),
|
| 114 |
+
RequestsDependencyWarning,
|
| 115 |
+
)
|
| 116 |
+
|
| 117 |
+
# Attempt to enable urllib3's fallback for SNI support
|
| 118 |
+
# if the standard library doesn't support SNI or the
|
| 119 |
+
# 'ssl' library isn't available.
|
| 120 |
+
try:
|
| 121 |
+
try:
|
| 122 |
+
import ssl
|
| 123 |
+
except ImportError:
|
| 124 |
+
ssl = None
|
| 125 |
+
|
| 126 |
+
if not getattr(ssl, "HAS_SNI", False):
|
| 127 |
+
from urllib3.contrib import pyopenssl
|
| 128 |
+
|
| 129 |
+
pyopenssl.inject_into_urllib3()
|
| 130 |
+
|
| 131 |
+
# Check cryptography version
|
| 132 |
+
from cryptography import __version__ as cryptography_version
|
| 133 |
+
|
| 134 |
+
_check_cryptography(cryptography_version)
|
| 135 |
+
except ImportError:
|
| 136 |
+
pass
|
| 137 |
+
|
| 138 |
+
# urllib3's DependencyWarnings should be silenced.
|
| 139 |
+
from urllib3.exceptions import DependencyWarning
|
| 140 |
+
|
| 141 |
+
warnings.simplefilter("ignore", DependencyWarning)
|
| 142 |
+
|
| 143 |
+
# Set default logging handler to avoid "No handler found" warnings.
|
| 144 |
+
import logging
|
| 145 |
+
from logging import NullHandler
|
| 146 |
+
|
| 147 |
+
from . import packages, utils
|
| 148 |
+
from .__version__ import (
|
| 149 |
+
__author__,
|
| 150 |
+
__author_email__,
|
| 151 |
+
__build__,
|
| 152 |
+
__cake__,
|
| 153 |
+
__copyright__,
|
| 154 |
+
__description__,
|
| 155 |
+
__license__,
|
| 156 |
+
__title__,
|
| 157 |
+
__url__,
|
| 158 |
+
__version__,
|
| 159 |
+
)
|
| 160 |
+
from .api import delete, get, head, options, patch, post, put, request
|
| 161 |
+
from .exceptions import (
|
| 162 |
+
ConnectionError,
|
| 163 |
+
ConnectTimeout,
|
| 164 |
+
FileModeWarning,
|
| 165 |
+
HTTPError,
|
| 166 |
+
JSONDecodeError,
|
| 167 |
+
ReadTimeout,
|
| 168 |
+
RequestException,
|
| 169 |
+
Timeout,
|
| 170 |
+
TooManyRedirects,
|
| 171 |
+
URLRequired,
|
| 172 |
+
)
|
| 173 |
+
from .models import PreparedRequest, Request, Response
|
| 174 |
+
from .sessions import Session, session
|
| 175 |
+
from .status_codes import codes
|
| 176 |
+
|
| 177 |
+
logging.getLogger(__name__).addHandler(NullHandler())
|
| 178 |
+
|
| 179 |
+
# FileModeWarnings go off per the default.
|
| 180 |
+
warnings.simplefilter("default", FileModeWarning, append=True)
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/__version__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# .-. .-. .-. . . .-. .-. .-. .-.
|
| 2 |
+
# |( |- |.| | | |- `-. | `-.
|
| 3 |
+
# ' ' `-' `-`.`-' `-' `-' ' `-'
|
| 4 |
+
|
| 5 |
+
__title__ = "requests"
|
| 6 |
+
__description__ = "Python HTTP for Humans."
|
| 7 |
+
__url__ = "https://requests.readthedocs.io"
|
| 8 |
+
__version__ = "2.28.0"
|
| 9 |
+
__build__ = 0x022800
|
| 10 |
+
__author__ = "Kenneth Reitz"
|
| 11 |
+
__author_email__ = "me@kennethreitz.org"
|
| 12 |
+
__license__ = "Apache 2.0"
|
| 13 |
+
__copyright__ = "Copyright 2022 Kenneth Reitz"
|
| 14 |
+
__cake__ = "\u2728 \U0001f370 \u2728"
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/_internal_utils.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
requests._internal_utils
|
| 3 |
+
~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
Provides utility functions that are consumed internally by Requests
|
| 6 |
+
which depend on extremely few external helpers (such as compat)
|
| 7 |
+
"""
|
| 8 |
+
import re
|
| 9 |
+
|
| 10 |
+
from .compat import builtin_str
|
| 11 |
+
|
| 12 |
+
_VALID_HEADER_NAME_RE_BYTE = re.compile(rb"^[^:\s][^:\r\n]*$")
|
| 13 |
+
_VALID_HEADER_NAME_RE_STR = re.compile(r"^[^:\s][^:\r\n]*$")
|
| 14 |
+
_VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$")
|
| 15 |
+
_VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$")
|
| 16 |
+
|
| 17 |
+
HEADER_VALIDATORS = {
|
| 18 |
+
bytes: (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE),
|
| 19 |
+
str: (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR),
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def to_native_string(string, encoding="ascii"):
|
| 24 |
+
"""Given a string object, regardless of type, returns a representation of
|
| 25 |
+
that string in the native string type, encoding and decoding where
|
| 26 |
+
necessary. This assumes ASCII unless told otherwise.
|
| 27 |
+
"""
|
| 28 |
+
if isinstance(string, builtin_str):
|
| 29 |
+
out = string
|
| 30 |
+
else:
|
| 31 |
+
out = string.decode(encoding)
|
| 32 |
+
|
| 33 |
+
return out
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def unicode_is_ascii(u_string):
|
| 37 |
+
"""Determine if unicode string only contains ASCII characters.
|
| 38 |
+
|
| 39 |
+
:param str u_string: unicode string to check. Must be unicode
|
| 40 |
+
and not Python 2 `str`.
|
| 41 |
+
:rtype: bool
|
| 42 |
+
"""
|
| 43 |
+
assert isinstance(u_string, str)
|
| 44 |
+
try:
|
| 45 |
+
u_string.encode("ascii")
|
| 46 |
+
return True
|
| 47 |
+
except UnicodeEncodeError:
|
| 48 |
+
return False
|
my_container_sandbox/workspace/anaconda3/lib/python3.8/site-packages/requests/adapters.py
ADDED
|
@@ -0,0 +1,584 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
requests.adapters
|
| 3 |
+
~~~~~~~~~~~~~~~~~
|
| 4 |
+
|
| 5 |
+
This module contains the transport adapters that Requests uses to define
|
| 6 |
+
and maintain connections.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import os.path
|
| 10 |
+
import socket # noqa: F401
|
| 11 |
+
|
| 12 |
+
from urllib3.exceptions import ClosedPoolError, ConnectTimeoutError
|
| 13 |
+
from urllib3.exceptions import HTTPError as _HTTPError
|
| 14 |
+
from urllib3.exceptions import InvalidHeader as _InvalidHeader
|
| 15 |
+
from urllib3.exceptions import (
|
| 16 |
+
LocationValueError,
|
| 17 |
+
MaxRetryError,
|
| 18 |
+
NewConnectionError,
|
| 19 |
+
ProtocolError,
|
| 20 |
+
)
|
| 21 |
+
from urllib3.exceptions import ProxyError as _ProxyError
|
| 22 |
+
from urllib3.exceptions import ReadTimeoutError, ResponseError
|
| 23 |
+
from urllib3.exceptions import SSLError as _SSLError
|
| 24 |
+
from urllib3.poolmanager import PoolManager, proxy_from_url
|
| 25 |
+
from urllib3.response import HTTPResponse
|
| 26 |
+
from urllib3.util import Timeout as TimeoutSauce
|
| 27 |
+
from urllib3.util import parse_url
|
| 28 |
+
from urllib3.util.retry import Retry
|
| 29 |
+
|
| 30 |
+
from .auth import _basic_auth_str
|
| 31 |
+
from .compat import basestring, urlparse
|
| 32 |
+
from .cookies import extract_cookies_to_jar
|
| 33 |
+
from .exceptions import (
|
| 34 |
+
ConnectionError,
|
| 35 |
+
ConnectTimeout,
|
| 36 |
+
InvalidHeader,
|
| 37 |
+
InvalidProxyURL,
|
| 38 |
+
InvalidSchema,
|
| 39 |
+
InvalidURL,
|
| 40 |
+
ProxyError,
|
| 41 |
+
ReadTimeout,
|
| 42 |
+
RetryError,
|
| 43 |
+
SSLError,
|
| 44 |
+
)
|
| 45 |
+
from .models import Response
|
| 46 |
+
from .structures import CaseInsensitiveDict
|
| 47 |
+
from .utils import (
|
| 48 |
+
DEFAULT_CA_BUNDLE_PATH,
|
| 49 |
+
extract_zipped_paths,
|
| 50 |
+
get_auth_from_url,
|
| 51 |
+
get_encoding_from_headers,
|
| 52 |
+
prepend_scheme_if_needed,
|
| 53 |
+
select_proxy,
|
| 54 |
+
urldefragauth,
|
| 55 |
+
)
|
| 56 |
+
|
| 57 |
+
try:
|
| 58 |
+
from urllib3.contrib.socks import SOCKSProxyManager
|
| 59 |
+
except ImportError:
|
| 60 |
+
|
| 61 |
+
def SOCKSProxyManager(*args, **kwargs):
|
| 62 |
+
raise InvalidSchema("Missing dependencies for SOCKS support.")
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
DEFAULT_POOLBLOCK = False
|
| 66 |
+
DEFAULT_POOLSIZE = 10
|
| 67 |
+
DEFAULT_RETRIES = 0
|
| 68 |
+
DEFAULT_POOL_TIMEOUT = None
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
class BaseAdapter:
|
| 72 |
+
"""The Base Transport Adapter"""
|
| 73 |
+
|
| 74 |
+
def __init__(self):
|
| 75 |
+
super().__init__()
|
| 76 |
+
|
| 77 |
+
def send(
|
| 78 |
+
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
|
| 79 |
+
):
|
| 80 |
+
"""Sends PreparedRequest object. Returns Response object.
|
| 81 |
+
|
| 82 |
+
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
|
| 83 |
+
:param stream: (optional) Whether to stream the request content.
|
| 84 |
+
:param timeout: (optional) How long to wait for the server to send
|
| 85 |
+
data before giving up, as a float, or a :ref:`(connect timeout,
|
| 86 |
+
read timeout) <timeouts>` tuple.
|
| 87 |
+
:type timeout: float or tuple
|
| 88 |
+
:param verify: (optional) Either a boolean, in which case it controls whether we verify
|
| 89 |
+
the server's TLS certificate, or a string, in which case it must be a path
|
| 90 |
+
to a CA bundle to use
|
| 91 |
+
:param cert: (optional) Any user-provided SSL certificate to be trusted.
|
| 92 |
+
:param proxies: (optional) The proxies dictionary to apply to the request.
|
| 93 |
+
"""
|
| 94 |
+
raise NotImplementedError
|
| 95 |
+
|
| 96 |
+
def close(self):
|
| 97 |
+
"""Cleans up adapter specific items."""
|
| 98 |
+
raise NotImplementedError
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
class HTTPAdapter(BaseAdapter):
|
| 102 |
+
"""The built-in HTTP Adapter for urllib3.
|
| 103 |
+
|
| 104 |
+
Provides a general-case interface for Requests sessions to contact HTTP and
|
| 105 |
+
HTTPS urls by implementing the Transport Adapter interface. This class will
|
| 106 |
+
usually be created by the :class:`Session <Session>` class under the
|
| 107 |
+
covers.
|
| 108 |
+
|
| 109 |
+
:param pool_connections: The number of urllib3 connection pools to cache.
|
| 110 |
+
:param pool_maxsize: The maximum number of connections to save in the pool.
|
| 111 |
+
:param max_retries: The maximum number of retries each connection
|
| 112 |
+
should attempt. Note, this applies only to failed DNS lookups, socket
|
| 113 |
+
connections and connection timeouts, never to requests where data has
|
| 114 |
+
made it to the server. By default, Requests does not retry failed
|
| 115 |
+
connections. If you need granular control over the conditions under
|
| 116 |
+
which we retry a request, import urllib3's ``Retry`` class and pass
|
| 117 |
+
that instead.
|
| 118 |
+
:param pool_block: Whether the connection pool should block for connections.
|
| 119 |
+
|
| 120 |
+
Usage::
|
| 121 |
+
|
| 122 |
+
>>> import requests
|
| 123 |
+
>>> s = requests.Session()
|
| 124 |
+
>>> a = requests.adapters.HTTPAdapter(max_retries=3)
|
| 125 |
+
>>> s.mount('http://', a)
|
| 126 |
+
"""
|
| 127 |
+
|
| 128 |
+
__attrs__ = [
|
| 129 |
+
"max_retries",
|
| 130 |
+
"config",
|
| 131 |
+
"_pool_connections",
|
| 132 |
+
"_pool_maxsize",
|
| 133 |
+
"_pool_block",
|
| 134 |
+
]
|
| 135 |
+
|
| 136 |
+
def __init__(
|
| 137 |
+
self,
|
| 138 |
+
pool_connections=DEFAULT_POOLSIZE,
|
| 139 |
+
pool_maxsize=DEFAULT_POOLSIZE,
|
| 140 |
+
max_retries=DEFAULT_RETRIES,
|
| 141 |
+
pool_block=DEFAULT_POOLBLOCK,
|
| 142 |
+
):
|
| 143 |
+
if max_retries == DEFAULT_RETRIES:
|
| 144 |
+
self.max_retries = Retry(0, read=False)
|
| 145 |
+
else:
|
| 146 |
+
self.max_retries = Retry.from_int(max_retries)
|
| 147 |
+
self.config = {}
|
| 148 |
+
self.proxy_manager = {}
|
| 149 |
+
|
| 150 |
+
super().__init__()
|
| 151 |
+
|
| 152 |
+
self._pool_connections = pool_connections
|
| 153 |
+
self._pool_maxsize = pool_maxsize
|
| 154 |
+
self._pool_block = pool_block
|
| 155 |
+
|
| 156 |
+
self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block)
|
| 157 |
+
|
| 158 |
+
def __getstate__(self):
|
| 159 |
+
return {attr: getattr(self, attr, None) for attr in self.__attrs__}
|
| 160 |
+
|
| 161 |
+
def __setstate__(self, state):
|
| 162 |
+
# Can't handle by adding 'proxy_manager' to self.__attrs__ because
|
| 163 |
+
# self.poolmanager uses a lambda function, which isn't pickleable.
|
| 164 |
+
self.proxy_manager = {}
|
| 165 |
+
self.config = {}
|
| 166 |
+
|
| 167 |
+
for attr, value in state.items():
|
| 168 |
+
setattr(self, attr, value)
|
| 169 |
+
|
| 170 |
+
self.init_poolmanager(
|
| 171 |
+
self._pool_connections, self._pool_maxsize, block=self._pool_block
|
| 172 |
+
)
|
| 173 |
+
|
| 174 |
+
def init_poolmanager(
|
| 175 |
+
self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs
|
| 176 |
+
):
|
| 177 |
+
"""Initializes a urllib3 PoolManager.
|
| 178 |
+
|
| 179 |
+
This method should not be called from user code, and is only
|
| 180 |
+
exposed for use when subclassing the
|
| 181 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 182 |
+
|
| 183 |
+
:param connections: The number of urllib3 connection pools to cache.
|
| 184 |
+
:param maxsize: The maximum number of connections to save in the pool.
|
| 185 |
+
:param block: Block when no free connections are available.
|
| 186 |
+
:param pool_kwargs: Extra keyword arguments used to initialize the Pool Manager.
|
| 187 |
+
"""
|
| 188 |
+
# save these values for pickling
|
| 189 |
+
self._pool_connections = connections
|
| 190 |
+
self._pool_maxsize = maxsize
|
| 191 |
+
self._pool_block = block
|
| 192 |
+
|
| 193 |
+
self.poolmanager = PoolManager(
|
| 194 |
+
num_pools=connections,
|
| 195 |
+
maxsize=maxsize,
|
| 196 |
+
block=block,
|
| 197 |
+
strict=True,
|
| 198 |
+
**pool_kwargs,
|
| 199 |
+
)
|
| 200 |
+
|
| 201 |
+
def proxy_manager_for(self, proxy, **proxy_kwargs):
|
| 202 |
+
"""Return urllib3 ProxyManager for the given proxy.
|
| 203 |
+
|
| 204 |
+
This method should not be called from user code, and is only
|
| 205 |
+
exposed for use when subclassing the
|
| 206 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 207 |
+
|
| 208 |
+
:param proxy: The proxy to return a urllib3 ProxyManager for.
|
| 209 |
+
:param proxy_kwargs: Extra keyword arguments used to configure the Proxy Manager.
|
| 210 |
+
:returns: ProxyManager
|
| 211 |
+
:rtype: urllib3.ProxyManager
|
| 212 |
+
"""
|
| 213 |
+
if proxy in self.proxy_manager:
|
| 214 |
+
manager = self.proxy_manager[proxy]
|
| 215 |
+
elif proxy.lower().startswith("socks"):
|
| 216 |
+
username, password = get_auth_from_url(proxy)
|
| 217 |
+
manager = self.proxy_manager[proxy] = SOCKSProxyManager(
|
| 218 |
+
proxy,
|
| 219 |
+
username=username,
|
| 220 |
+
password=password,
|
| 221 |
+
num_pools=self._pool_connections,
|
| 222 |
+
maxsize=self._pool_maxsize,
|
| 223 |
+
block=self._pool_block,
|
| 224 |
+
**proxy_kwargs,
|
| 225 |
+
)
|
| 226 |
+
else:
|
| 227 |
+
proxy_headers = self.proxy_headers(proxy)
|
| 228 |
+
manager = self.proxy_manager[proxy] = proxy_from_url(
|
| 229 |
+
proxy,
|
| 230 |
+
proxy_headers=proxy_headers,
|
| 231 |
+
num_pools=self._pool_connections,
|
| 232 |
+
maxsize=self._pool_maxsize,
|
| 233 |
+
block=self._pool_block,
|
| 234 |
+
**proxy_kwargs,
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
return manager
|
| 238 |
+
|
| 239 |
+
def cert_verify(self, conn, url, verify, cert):
|
| 240 |
+
"""Verify a SSL certificate. This method should not be called from user
|
| 241 |
+
code, and is only exposed for use when subclassing the
|
| 242 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 243 |
+
|
| 244 |
+
:param conn: The urllib3 connection object associated with the cert.
|
| 245 |
+
:param url: The requested URL.
|
| 246 |
+
:param verify: Either a boolean, in which case it controls whether we verify
|
| 247 |
+
the server's TLS certificate, or a string, in which case it must be a path
|
| 248 |
+
to a CA bundle to use
|
| 249 |
+
:param cert: The SSL certificate to verify.
|
| 250 |
+
"""
|
| 251 |
+
if url.lower().startswith("https") and verify:
|
| 252 |
+
|
| 253 |
+
cert_loc = None
|
| 254 |
+
|
| 255 |
+
# Allow self-specified cert location.
|
| 256 |
+
if verify is not True:
|
| 257 |
+
cert_loc = verify
|
| 258 |
+
|
| 259 |
+
if not cert_loc:
|
| 260 |
+
cert_loc = extract_zipped_paths(DEFAULT_CA_BUNDLE_PATH)
|
| 261 |
+
|
| 262 |
+
if not cert_loc or not os.path.exists(cert_loc):
|
| 263 |
+
raise OSError(
|
| 264 |
+
f"Could not find a suitable TLS CA certificate bundle, "
|
| 265 |
+
f"invalid path: {cert_loc}"
|
| 266 |
+
)
|
| 267 |
+
|
| 268 |
+
conn.cert_reqs = "CERT_REQUIRED"
|
| 269 |
+
|
| 270 |
+
if not os.path.isdir(cert_loc):
|
| 271 |
+
conn.ca_certs = cert_loc
|
| 272 |
+
else:
|
| 273 |
+
conn.ca_cert_dir = cert_loc
|
| 274 |
+
else:
|
| 275 |
+
conn.cert_reqs = "CERT_NONE"
|
| 276 |
+
conn.ca_certs = None
|
| 277 |
+
conn.ca_cert_dir = None
|
| 278 |
+
|
| 279 |
+
if cert:
|
| 280 |
+
if not isinstance(cert, basestring):
|
| 281 |
+
conn.cert_file = cert[0]
|
| 282 |
+
conn.key_file = cert[1]
|
| 283 |
+
else:
|
| 284 |
+
conn.cert_file = cert
|
| 285 |
+
conn.key_file = None
|
| 286 |
+
if conn.cert_file and not os.path.exists(conn.cert_file):
|
| 287 |
+
raise OSError(
|
| 288 |
+
f"Could not find the TLS certificate file, "
|
| 289 |
+
f"invalid path: {conn.cert_file}"
|
| 290 |
+
)
|
| 291 |
+
if conn.key_file and not os.path.exists(conn.key_file):
|
| 292 |
+
raise OSError(
|
| 293 |
+
f"Could not find the TLS key file, invalid path: {conn.key_file}"
|
| 294 |
+
)
|
| 295 |
+
|
| 296 |
+
def build_response(self, req, resp):
|
| 297 |
+
"""Builds a :class:`Response <requests.Response>` object from a urllib3
|
| 298 |
+
response. This should not be called from user code, and is only exposed
|
| 299 |
+
for use when subclassing the
|
| 300 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`
|
| 301 |
+
|
| 302 |
+
:param req: The :class:`PreparedRequest <PreparedRequest>` used to generate the response.
|
| 303 |
+
:param resp: The urllib3 response object.
|
| 304 |
+
:rtype: requests.Response
|
| 305 |
+
"""
|
| 306 |
+
response = Response()
|
| 307 |
+
|
| 308 |
+
# Fallback to None if there's no status_code, for whatever reason.
|
| 309 |
+
response.status_code = getattr(resp, "status", None)
|
| 310 |
+
|
| 311 |
+
# Make headers case-insensitive.
|
| 312 |
+
response.headers = CaseInsensitiveDict(getattr(resp, "headers", {}))
|
| 313 |
+
|
| 314 |
+
# Set encoding.
|
| 315 |
+
response.encoding = get_encoding_from_headers(response.headers)
|
| 316 |
+
response.raw = resp
|
| 317 |
+
response.reason = response.raw.reason
|
| 318 |
+
|
| 319 |
+
if isinstance(req.url, bytes):
|
| 320 |
+
response.url = req.url.decode("utf-8")
|
| 321 |
+
else:
|
| 322 |
+
response.url = req.url
|
| 323 |
+
|
| 324 |
+
# Add new cookies from the server.
|
| 325 |
+
extract_cookies_to_jar(response.cookies, req, resp)
|
| 326 |
+
|
| 327 |
+
# Give the Response some context.
|
| 328 |
+
response.request = req
|
| 329 |
+
response.connection = self
|
| 330 |
+
|
| 331 |
+
return response
|
| 332 |
+
|
| 333 |
+
def get_connection(self, url, proxies=None):
|
| 334 |
+
"""Returns a urllib3 connection for the given URL. This should not be
|
| 335 |
+
called from user code, and is only exposed for use when subclassing the
|
| 336 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 337 |
+
|
| 338 |
+
:param url: The URL to connect to.
|
| 339 |
+
:param proxies: (optional) A Requests-style dictionary of proxies used on this request.
|
| 340 |
+
:rtype: urllib3.ConnectionPool
|
| 341 |
+
"""
|
| 342 |
+
proxy = select_proxy(url, proxies)
|
| 343 |
+
|
| 344 |
+
if proxy:
|
| 345 |
+
proxy = prepend_scheme_if_needed(proxy, "http")
|
| 346 |
+
proxy_url = parse_url(proxy)
|
| 347 |
+
if not proxy_url.host:
|
| 348 |
+
raise InvalidProxyURL(
|
| 349 |
+
"Please check proxy URL. It is malformed "
|
| 350 |
+
"and could be missing the host."
|
| 351 |
+
)
|
| 352 |
+
proxy_manager = self.proxy_manager_for(proxy)
|
| 353 |
+
conn = proxy_manager.connection_from_url(url)
|
| 354 |
+
else:
|
| 355 |
+
# Only scheme should be lower case
|
| 356 |
+
parsed = urlparse(url)
|
| 357 |
+
url = parsed.geturl()
|
| 358 |
+
conn = self.poolmanager.connection_from_url(url)
|
| 359 |
+
|
| 360 |
+
return conn
|
| 361 |
+
|
| 362 |
+
def close(self):
|
| 363 |
+
"""Disposes of any internal state.
|
| 364 |
+
|
| 365 |
+
Currently, this closes the PoolManager and any active ProxyManager,
|
| 366 |
+
which closes any pooled connections.
|
| 367 |
+
"""
|
| 368 |
+
self.poolmanager.clear()
|
| 369 |
+
for proxy in self.proxy_manager.values():
|
| 370 |
+
proxy.clear()
|
| 371 |
+
|
| 372 |
+
def request_url(self, request, proxies):
|
| 373 |
+
"""Obtain the url to use when making the final request.
|
| 374 |
+
|
| 375 |
+
If the message is being sent through a HTTP proxy, the full URL has to
|
| 376 |
+
be used. Otherwise, we should only use the path portion of the URL.
|
| 377 |
+
|
| 378 |
+
This should not be called from user code, and is only exposed for use
|
| 379 |
+
when subclassing the
|
| 380 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 381 |
+
|
| 382 |
+
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
|
| 383 |
+
:param proxies: A dictionary of schemes or schemes and hosts to proxy URLs.
|
| 384 |
+
:rtype: str
|
| 385 |
+
"""
|
| 386 |
+
proxy = select_proxy(request.url, proxies)
|
| 387 |
+
scheme = urlparse(request.url).scheme
|
| 388 |
+
|
| 389 |
+
is_proxied_http_request = proxy and scheme != "https"
|
| 390 |
+
using_socks_proxy = False
|
| 391 |
+
if proxy:
|
| 392 |
+
proxy_scheme = urlparse(proxy).scheme.lower()
|
| 393 |
+
using_socks_proxy = proxy_scheme.startswith("socks")
|
| 394 |
+
|
| 395 |
+
url = request.path_url
|
| 396 |
+
if is_proxied_http_request and not using_socks_proxy:
|
| 397 |
+
url = urldefragauth(request.url)
|
| 398 |
+
|
| 399 |
+
return url
|
| 400 |
+
|
| 401 |
+
def add_headers(self, request, **kwargs):
|
| 402 |
+
"""Add any headers needed by the connection. As of v2.0 this does
|
| 403 |
+
nothing by default, but is left for overriding by users that subclass
|
| 404 |
+
the :class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 405 |
+
|
| 406 |
+
This should not be called from user code, and is only exposed for use
|
| 407 |
+
when subclassing the
|
| 408 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 409 |
+
|
| 410 |
+
:param request: The :class:`PreparedRequest <PreparedRequest>` to add headers to.
|
| 411 |
+
:param kwargs: The keyword arguments from the call to send().
|
| 412 |
+
"""
|
| 413 |
+
pass
|
| 414 |
+
|
| 415 |
+
def proxy_headers(self, proxy):
|
| 416 |
+
"""Returns a dictionary of the headers to add to any request sent
|
| 417 |
+
through a proxy. This works with urllib3 magic to ensure that they are
|
| 418 |
+
correctly sent to the proxy, rather than in a tunnelled request if
|
| 419 |
+
CONNECT is being used.
|
| 420 |
+
|
| 421 |
+
This should not be called from user code, and is only exposed for use
|
| 422 |
+
when subclassing the
|
| 423 |
+
:class:`HTTPAdapter <requests.adapters.HTTPAdapter>`.
|
| 424 |
+
|
| 425 |
+
:param proxy: The url of the proxy being used for this request.
|
| 426 |
+
:rtype: dict
|
| 427 |
+
"""
|
| 428 |
+
headers = {}
|
| 429 |
+
username, password = get_auth_from_url(proxy)
|
| 430 |
+
|
| 431 |
+
if username:
|
| 432 |
+
headers["Proxy-Authorization"] = _basic_auth_str(username, password)
|
| 433 |
+
|
| 434 |
+
return headers
|
| 435 |
+
|
| 436 |
+
def send(
|
| 437 |
+
self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None
|
| 438 |
+
):
|
| 439 |
+
"""Sends PreparedRequest object. Returns Response object.
|
| 440 |
+
|
| 441 |
+
:param request: The :class:`PreparedRequest <PreparedRequest>` being sent.
|
| 442 |
+
:param stream: (optional) Whether to stream the request content.
|
| 443 |
+
:param timeout: (optional) How long to wait for the server to send
|
| 444 |
+
data before giving up, as a float, or a :ref:`(connect timeout,
|
| 445 |
+
read timeout) <timeouts>` tuple.
|
| 446 |
+
:type timeout: float or tuple or urllib3 Timeout object
|
| 447 |
+
:param verify: (optional) Either a boolean, in which case it controls whether
|
| 448 |
+
we verify the server's TLS certificate, or a string, in which case it
|
| 449 |
+
must be a path to a CA bundle to use
|
| 450 |
+
:param cert: (optional) Any user-provided SSL certificate to be trusted.
|
| 451 |
+
:param proxies: (optional) The proxies dictionary to apply to the request.
|
| 452 |
+
:rtype: requests.Response
|
| 453 |
+
"""
|
| 454 |
+
|
| 455 |
+
try:
|
| 456 |
+
conn = self.get_connection(request.url, proxies)
|
| 457 |
+
except LocationValueError as e:
|
| 458 |
+
raise InvalidURL(e, request=request)
|
| 459 |
+
|
| 460 |
+
self.cert_verify(conn, request.url, verify, cert)
|
| 461 |
+
url = self.request_url(request, proxies)
|
| 462 |
+
self.add_headers(
|
| 463 |
+
request,
|
| 464 |
+
stream=stream,
|
| 465 |
+
timeout=timeout,
|
| 466 |
+
verify=verify,
|
| 467 |
+
cert=cert,
|
| 468 |
+
proxies=proxies,
|
| 469 |
+
)
|
| 470 |
+
|
| 471 |
+
chunked = not (request.body is None or "Content-Length" in request.headers)
|
| 472 |
+
|
| 473 |
+
if isinstance(timeout, tuple):
|
| 474 |
+
try:
|
| 475 |
+
connect, read = timeout
|
| 476 |
+
timeout = TimeoutSauce(connect=connect, read=read)
|
| 477 |
+
except ValueError:
|
| 478 |
+
raise ValueError(
|
| 479 |
+
f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, "
|
| 480 |
+
f"or a single float to set both timeouts to the same value."
|
| 481 |
+
)
|
| 482 |
+
elif isinstance(timeout, TimeoutSauce):
|
| 483 |
+
pass
|
| 484 |
+
else:
|
| 485 |
+
timeout = TimeoutSauce(connect=timeout, read=timeout)
|
| 486 |
+
|
| 487 |
+
try:
|
| 488 |
+
if not chunked:
|
| 489 |
+
resp = conn.urlopen(
|
| 490 |
+
method=request.method,
|
| 491 |
+
url=url,
|
| 492 |
+
body=request.body,
|
| 493 |
+
headers=request.headers,
|
| 494 |
+
redirect=False,
|
| 495 |
+
assert_same_host=False,
|
| 496 |
+
preload_content=False,
|
| 497 |
+
decode_content=False,
|
| 498 |
+
retries=self.max_retries,
|
| 499 |
+
timeout=timeout,
|
| 500 |
+
)
|
| 501 |
+
|
| 502 |
+
# Send the request.
|
| 503 |
+
else:
|
| 504 |
+
if hasattr(conn, "proxy_pool"):
|
| 505 |
+
conn = conn.proxy_pool
|
| 506 |
+
|
| 507 |
+
low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT)
|
| 508 |
+
|
| 509 |
+
try:
|
| 510 |
+
skip_host = "Host" in request.headers
|
| 511 |
+
low_conn.putrequest(
|
| 512 |
+
request.method,
|
| 513 |
+
url,
|
| 514 |
+
skip_accept_encoding=True,
|
| 515 |
+
skip_host=skip_host,
|
| 516 |
+
)
|
| 517 |
+
|
| 518 |
+
for header, value in request.headers.items():
|
| 519 |
+
low_conn.putheader(header, value)
|
| 520 |
+
|
| 521 |
+
low_conn.endheaders()
|
| 522 |
+
|
| 523 |
+
for i in request.body:
|
| 524 |
+
low_conn.send(hex(len(i))[2:].encode("utf-8"))
|
| 525 |
+
low_conn.send(b"\r\n")
|
| 526 |
+
low_conn.send(i)
|
| 527 |
+
low_conn.send(b"\r\n")
|
| 528 |
+
low_conn.send(b"0\r\n\r\n")
|
| 529 |
+
|
| 530 |
+
# Receive the response from the server
|
| 531 |
+
r = low_conn.getresponse()
|
| 532 |
+
|
| 533 |
+
resp = HTTPResponse.from_httplib(
|
| 534 |
+
r,
|
| 535 |
+
pool=conn,
|
| 536 |
+
connection=low_conn,
|
| 537 |
+
preload_content=False,
|
| 538 |
+
decode_content=False,
|
| 539 |
+
)
|
| 540 |
+
except Exception:
|
| 541 |
+
# If we hit any problems here, clean up the connection.
|
| 542 |
+
# Then, raise so that we can handle the actual exception.
|
| 543 |
+
low_conn.close()
|
| 544 |
+
raise
|
| 545 |
+
|
| 546 |
+
except (ProtocolError, OSError) as err:
|
| 547 |
+
raise ConnectionError(err, request=request)
|
| 548 |
+
|
| 549 |
+
except MaxRetryError as e:
|
| 550 |
+
if isinstance(e.reason, ConnectTimeoutError):
|
| 551 |
+
# TODO: Remove this in 3.0.0: see #2811
|
| 552 |
+
if not isinstance(e.reason, NewConnectionError):
|
| 553 |
+
raise ConnectTimeout(e, request=request)
|
| 554 |
+
|
| 555 |
+
if isinstance(e.reason, ResponseError):
|
| 556 |
+
raise RetryError(e, request=request)
|
| 557 |
+
|
| 558 |
+
if isinstance(e.reason, _ProxyError):
|
| 559 |
+
raise ProxyError(e, request=request)
|
| 560 |
+
|
| 561 |
+
if isinstance(e.reason, _SSLError):
|
| 562 |
+
# This branch is for urllib3 v1.22 and later.
|
| 563 |
+
raise SSLError(e, request=request)
|
| 564 |
+
|
| 565 |
+
raise ConnectionError(e, request=request)
|
| 566 |
+
|
| 567 |
+
except ClosedPoolError as e:
|
| 568 |
+
raise ConnectionError(e, request=request)
|
| 569 |
+
|
| 570 |
+
except _ProxyError as e:
|
| 571 |
+
raise ProxyError(e)
|
| 572 |
+
|
| 573 |
+
except (_SSLError, _HTTPError) as e:
|
| 574 |
+
if isinstance(e, _SSLError):
|
| 575 |
+
# This branch is for urllib3 versions earlier than v1.22
|
| 576 |
+
raise SSLError(e, request=request)
|
| 577 |
+
elif isinstance(e, ReadTimeoutError):
|
| 578 |
+
raise ReadTimeout(e, request=request)
|
| 579 |
+
elif isinstance(e, _InvalidHeader):
|
| 580 |
+
raise InvalidHeader(e, request=request)
|
| 581 |
+
else:
|
| 582 |
+
raise
|
| 583 |
+
|
| 584 |
+
return self.build_response(request, resp)
|