From 0b1c8147f430553ccdbc5b81a09026287c3076df Mon Sep 17 00:00:00 2001 From: beierlm Date: Fri, 5 Mar 2021 07:04:33 -0500 Subject: [PATCH] Adding Ansible to Firewall Fixes ansible handling Adds playbooks to add/remove port forwarding Forces public/management IP down on virtual pc after installation Signed-off-by: beierlm --- .../charms/vyos-config-src/README.md | 3 + .../charms/vyos-config-src/actions.yaml | 46 + .../charms/vyos-config-src/config.yaml | 25 + .../charms/vyos-config-src/metadata.yaml | 11 + .../playbooks/add-port-forward.yaml | 13 + .../vyos-config-src/playbooks/backup.yaml | 9 + .../playbooks/remove-port-forward.yaml | 11 + .../vyos-config-src/requirements.txt} | 0 .../charms/vyos-config-src/src/charm.py | 112 + .../charms/vyos-config/actions.yaml | 45 +- .../charms/vyos-config/config.yaml | 4 - .../charms/vyos-config/dispatch | 3 + .../charms/vyos-config/hooks/install | 98 +- .../charms/vyos-config/hooks/start | 1 + .../charms/vyos-config/hooks/upgrade-charm | 1 + .../vyos-config/lib/charms/osm/libansible.py | 70 +- .../playbooks/add-port-forward.yaml | 13 + .../charms/vyos-config/playbooks/backup.yaml | 11 +- .../playbooks/remove-port-forward.yaml | 11 + .../charms/vyos-config/src/charm.py | 79 +- .../charms/vyos-config/venv/bin/activate | 84 + .../charms/vyos-config/venv/bin/activate.csh | 55 + .../charms/vyos-config/venv/bin/activate.fish | 100 + .../charms/vyos-config/venv/bin/activate.ps1 | 60 + .../charms/vyos-config/venv/bin/activate.xsh | 46 + .../vyos-config/venv/bin/activate_this.py | 32 + .../charms/vyos-config/venv/bin/chardetect | 8 + .../vyos-config/venv/bin/chardetect-3.8 | 8 + .../charms/vyos-config/venv/bin/chardetect3 | 8 + .../charms/vyos-config/venv/bin/charmcraft | 8 + .../charms/vyos-config/venv/bin/distro | 8 + .../charms/vyos-config/venv/bin/distro-3.8 | 8 + .../charms/vyos-config/venv/bin/distro3 | 8 + .../charms/vyos-config/venv/bin/easy_install | 8 + .../vyos-config/venv/bin/easy_install-3.8 | 8 + .../charms/vyos-config/venv/bin/easy_install3 | 8 + .../charms/vyos-config/venv/bin/jsonschema | 8 + .../charms/vyos-config/venv/bin/pip | 8 + .../charms/vyos-config/venv/bin/pip-3.8 | 8 + .../charms/vyos-config/venv/bin/pip3 | 8 + .../charms/vyos-config/venv/bin/pip3.8 | 8 + .../charms/vyos-config/venv/bin/tabulate | 8 + .../charms/vyos-config/venv/bin/wheel | 8 + .../charms/vyos-config/venv/bin/wheel-3.8 | 8 + .../charms/vyos-config/venv/bin/wheel3 | 8 + .../CacheControl-0.12.6.dist-info/AUTHORS.txt | 562 ++ .../CacheControl-0.12.6.dist-info/INSTALLER | 1 + .../CacheControl-0.12.6.dist-info/LICENSE.txt | 20 + .../CacheControl-0.12.6.dist-info/METADATA | 71 + .../CacheControl-0.12.6.dist-info/RECORD | 37 + .../CacheControl-0.12.6.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../CacheControl-0.12.6.virtualenv | 0 .../Jinja2-2.11.2.dist-info/INSTALLER | 1 + .../Jinja2-2.11.2.dist-info/LICENSE.rst | 28 + .../Jinja2-2.11.2.dist-info/METADATA | 106 + .../Jinja2-2.11.2.dist-info/RECORD | 61 + .../Jinja2-2.11.2.dist-info/WHEEL | 6 + .../Jinja2-2.11.2.dist-info/entry_points.txt | 3 + .../Jinja2-2.11.2.dist-info/top_level.txt | 1 + .../MarkupSafe-1.1.1.dist-info/INSTALLER | 1 + .../MarkupSafe-1.1.1.dist-info/LICENSE.rst | 28 + .../MarkupSafe-1.1.1.dist-info/METADATA | 94 + .../MarkupSafe-1.1.1.dist-info/RECORD | 16 + .../MarkupSafe-1.1.1.dist-info/WHEEL | 5 + .../MarkupSafe-1.1.1.dist-info/top_level.txt | 1 + .../PyNaCl-1.4.0.dist-info/INSTALLER | 1 + .../PyNaCl-1.4.0.dist-info/LICENSE | 174 + .../PyNaCl-1.4.0.dist-info/METADATA | 227 + .../PyNaCl-1.4.0.dist-info/RECORD | 67 + .../PyNaCl-1.4.0.dist-info/WHEEL | 5 + .../PyNaCl-1.4.0.dist-info/top_level.txt | 2 + .../PyYAML-5.3.1.dist-info/INSTALLER | 1 + .../PyYAML-5.3.1.dist-info/LICENSE | 20 + .../PyYAML-5.3.1.dist-info/METADATA | 41 + .../PyYAML-5.3.1.dist-info/RECORD | 40 + .../PyYAML-5.3.1.dist-info/WHEEL | 5 + .../PyYAML-5.3.1.dist-info/top_level.txt | 2 + ...ffi_backend.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 893296 bytes .../site-packages/_pyrsistent_version.py | 1 + .../python3.8/site-packages/_virtualenv.pth | 1 + .../python3.8/site-packages/_virtualenv.py | 115 + .../appdirs-1.4.3.dist-info/AUTHORS.txt | 562 ++ .../appdirs-1.4.3.dist-info/INSTALLER | 1 + .../appdirs-1.4.3.dist-info/LICENSE.txt | 20 + .../appdirs-1.4.3.dist-info/METADATA | 256 + .../appdirs-1.4.3.dist-info/RECORD | 11 + .../appdirs-1.4.3.dist-info/WHEEL | 6 + .../appdirs-1.4.3.dist-info/top_level.txt | 1 + .../site-packages/appdirs-1.4.3.virtualenv | 0 .../appdirs-1.4.4.dist-info/INSTALLER | 1 + .../appdirs-1.4.4.dist-info/LICENSE.txt | 23 + .../appdirs-1.4.4.dist-info/METADATA | 264 + .../appdirs-1.4.4.dist-info/RECORD | 8 + .../appdirs-1.4.4.dist-info/WHEEL | 6 + .../appdirs-1.4.4.dist-info/top_level.txt | 1 + .../lib/python3.8/site-packages/appdirs.py | 608 ++ .../python3.8/site-packages/attr/__init__.py | 76 + .../python3.8/site-packages/attr/__init__.pyi | 433 + .../python3.8/site-packages/attr/_compat.py | 231 + .../python3.8/site-packages/attr/_config.py | 23 + .../python3.8/site-packages/attr/_funcs.py | 390 + .../lib/python3.8/site-packages/attr/_make.py | 2765 ++++++ .../python3.8/site-packages/attr/_next_gen.py | 160 + .../site-packages/attr/_version_info.py | 85 + .../site-packages/attr/_version_info.pyi | 9 + .../site-packages/attr/converters.py | 85 + .../site-packages/attr/converters.pyi | 11 + .../site-packages/attr/exceptions.py | 92 + .../site-packages/attr/exceptions.pyi | 17 + .../python3.8/site-packages/attr/filters.py | 52 + .../python3.8/site-packages/attr/filters.pyi | 5 + .../lib/python3.8/site-packages/attr/py.typed | 0 .../python3.8/site-packages/attr/setters.py | 77 + .../python3.8/site-packages/attr/setters.pyi | 18 + .../site-packages/attr/validators.py | 379 + .../site-packages/attr/validators.pyi | 66 + .../attrs-20.3.0.dist-info/AUTHORS.rst | 11 + .../attrs-20.3.0.dist-info/INSTALLER | 1 + .../attrs-20.3.0.dist-info/LICENSE | 21 + .../attrs-20.3.0.dist-info/METADATA | 241 + .../attrs-20.3.0.dist-info/RECORD | 39 + .../attrs-20.3.0.dist-info/WHEEL | 6 + .../attrs-20.3.0.dist-info/top_level.txt | 1 + .../site-packages/cachecontrol/__init__.py | 11 + .../site-packages/cachecontrol/_cmd.py | 57 + .../site-packages/cachecontrol/adapter.py | 133 + .../site-packages/cachecontrol/cache.py | 39 + .../cachecontrol/caches/__init__.py | 2 + .../cachecontrol/caches/file_cache.py | 146 + .../cachecontrol/caches/redis_cache.py | 33 + .../site-packages/cachecontrol/compat.py | 29 + .../site-packages/cachecontrol/controller.py | 376 + .../site-packages/cachecontrol/filewrapper.py | 80 + .../site-packages/cachecontrol/heuristics.py | 135 + .../site-packages/cachecontrol/serialize.py | 188 + .../site-packages/cachecontrol/wrapper.py | 29 + .../certifi-2019.11.28.dist-info/AUTHORS.txt | 562 ++ .../certifi-2019.11.28.dist-info/INSTALLER | 1 + .../certifi-2019.11.28.dist-info/LICENSE.txt | 20 + .../certifi-2019.11.28.dist-info/METADATA | 74 + .../certifi-2019.11.28.dist-info/RECORD | 17 + .../certifi-2019.11.28.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../certifi-2019.11.28.virtualenv | 0 .../site-packages/certifi/__init__.py | 3 + .../site-packages/certifi/__main__.py | 2 + .../site-packages/certifi/cacert.pem | 4602 +++++++++ .../python3.8/site-packages/certifi/core.py | 15 + .../cffi-1.14.5.dist-info/INSTALLER | 1 + .../cffi-1.14.5.dist-info/LICENSE | 26 + .../cffi-1.14.5.dist-info/METADATA | 37 + .../cffi-1.14.5.dist-info/RECORD | 45 + .../site-packages/cffi-1.14.5.dist-info/WHEEL | 5 + .../cffi-1.14.5.dist-info/entry_points.txt | 3 + .../cffi-1.14.5.dist-info/top_level.txt | 2 + .../cffi.libs/libffi-806b1a9d.so.6.0.4 | Bin 0 -> 46632 bytes .../python3.8/site-packages/cffi/__init__.py | 14 + .../site-packages/cffi/_cffi_errors.h | 147 + .../site-packages/cffi/_cffi_include.h | 385 + .../python3.8/site-packages/cffi/_embedding.h | 527 ++ .../lib/python3.8/site-packages/cffi/api.py | 965 ++ .../site-packages/cffi/backend_ctypes.py | 1121 +++ .../site-packages/cffi/cffi_opcode.py | 187 + .../site-packages/cffi/commontypes.py | 80 + .../python3.8/site-packages/cffi/cparser.py | 1006 ++ .../lib/python3.8/site-packages/cffi/error.py | 31 + .../site-packages/cffi/ffiplatform.py | 127 + .../lib/python3.8/site-packages/cffi/lock.py | 30 + .../lib/python3.8/site-packages/cffi/model.py | 617 ++ .../site-packages/cffi/parse_c_type.h | 181 + .../python3.8/site-packages/cffi/pkgconfig.py | 121 + .../site-packages/cffi/recompiler.py | 1581 ++++ .../site-packages/cffi/setuptools_ext.py | 219 + .../site-packages/cffi/vengine_cpy.py | 1076 +++ .../site-packages/cffi/vengine_gen.py | 675 ++ .../python3.8/site-packages/cffi/verifier.py | 306 + .../chardet-3.0.4.dist-info/AUTHORS.txt | 562 ++ .../chardet-3.0.4.dist-info/INSTALLER | 1 + .../chardet-3.0.4.dist-info/LICENSE.txt | 20 + .../chardet-3.0.4.dist-info/METADATA | 98 + .../chardet-3.0.4.dist-info/RECORD | 97 + .../chardet-3.0.4.dist-info/WHEEL | 6 + .../chardet-3.0.4.dist-info/entry_points.txt | 3 + .../chardet-3.0.4.dist-info/top_level.txt | 1 + .../site-packages/chardet-3.0.4.virtualenv | 0 .../site-packages/chardet/__init__.py | 39 + .../site-packages/chardet/big5freq.py | 386 + .../site-packages/chardet/big5prober.py | 47 + .../site-packages/chardet/chardistribution.py | 233 + .../chardet/charsetgroupprober.py | 106 + .../site-packages/chardet/charsetprober.py | 145 + .../site-packages/chardet/cli/__init__.py | 1 + .../site-packages/chardet/cli/chardetect.py | 85 + .../chardet/codingstatemachine.py | 88 + .../python3.8/site-packages/chardet/compat.py | 34 + .../site-packages/chardet/cp949prober.py | 49 + .../python3.8/site-packages/chardet/enums.py | 76 + .../site-packages/chardet/escprober.py | 101 + .../python3.8/site-packages/chardet/escsm.py | 246 + .../site-packages/chardet/eucjpprober.py | 92 + .../site-packages/chardet/euckrfreq.py | 195 + .../site-packages/chardet/euckrprober.py | 47 + .../site-packages/chardet/euctwfreq.py | 387 + .../site-packages/chardet/euctwprober.py | 46 + .../site-packages/chardet/gb2312freq.py | 283 + .../site-packages/chardet/gb2312prober.py | 46 + .../site-packages/chardet/hebrewprober.py | 292 + .../site-packages/chardet/jisfreq.py | 325 + .../python3.8/site-packages/chardet/jpcntx.py | 233 + .../chardet/langbulgarianmodel.py | 228 + .../chardet/langcyrillicmodel.py | 333 + .../site-packages/chardet/langgreekmodel.py | 225 + .../site-packages/chardet/langhebrewmodel.py | 200 + .../chardet/langhungarianmodel.py | 225 + .../site-packages/chardet/langthaimodel.py | 199 + .../site-packages/chardet/langturkishmodel.py | 193 + .../site-packages/chardet/latin1prober.py | 145 + .../site-packages/chardet/mbcharsetprober.py | 91 + .../site-packages/chardet/mbcsgroupprober.py | 54 + .../python3.8/site-packages/chardet/mbcssm.py | 572 ++ .../site-packages/chardet/sbcharsetprober.py | 132 + .../site-packages/chardet/sbcsgroupprober.py | 73 + .../site-packages/chardet/sjisprober.py | 92 + .../chardet/universaldetector.py | 286 + .../site-packages/chardet/utf8prober.py | 82 + .../site-packages/chardet/version.py | 9 + .../charmcraft-0.8.1.dist-info/INSTALLER | 1 + .../charmcraft-0.8.1.dist-info/LICENSE | 201 + .../charmcraft-0.8.1.dist-info/METADATA | 184 + .../charmcraft-0.8.1.dist-info/RECORD | 60 + .../charmcraft-0.8.1.dist-info/WHEEL | 5 + .../entry_points.txt | 3 + .../charmcraft-0.8.1.dist-info/top_level.txt | 1 + .../site-packages/charmcraft/__init__.py | 19 + .../site-packages/charmcraft/__main__.py | 23 + .../site-packages/charmcraft/cmdbase.py | 81 + .../charmcraft/commands/__init__.py | 17 + .../charmcraft/commands/build.py | 398 + .../site-packages/charmcraft/commands/init.py | 145 + .../site-packages/charmcraft/commands/pack.py | 104 + .../charmcraft/commands/store/__init__.py | 977 ++ .../charmcraft/commands/store/client.py | 278 + .../charmcraft/commands/store/store.py | 252 + .../charmcraft/commands/utils.py | 64 + .../charmcraft/commands/version.py | 56 + .../site-packages/charmcraft/config.py | 202 + .../site-packages/charmcraft/helptexts.py | 271 + .../site-packages/charmcraft/jujuignore.py | 228 + .../site-packages/charmcraft/logsetup.py | 121 + .../site-packages/charmcraft/main.py | 319 + .../templates/charmlibs/new_library.py.j2 | 29 + .../charmcraft/templates/init/.flake8.j2 | 9 + .../charmcraft/templates/init/.jujuignore.j2 | 3 + .../charmcraft/templates/init/LICENSE.j2 | 202 + .../charmcraft/templates/init/README.md.j2 | 25 + .../charmcraft/templates/init/actions.yaml.j2 | 14 + .../charmcraft/templates/init/config.yaml.j2 | 11 + .../templates/init/metadata.yaml.j2 | 9 + .../templates/init/requirements-dev.txt.j2 | 3 + .../templates/init/requirements.txt.j2 | 1 + .../charmcraft/templates/init/run_tests.j2 | 17 + .../charmcraft/templates/init/src/charm.py.j2 | 46 + .../templates/init/tests/__init__.py.j2 | 0 .../templates/init/tests/test_charm.py.j2 | 35 + .../site-packages/charmcraft/utils.py | 66 + .../site-packages/charmcraft/version.py | 4 + .../colorama-0.4.3.dist-info/AUTHORS.txt | 562 ++ .../colorama-0.4.3.dist-info/INSTALLER | 1 + .../colorama-0.4.3.dist-info/LICENSE.txt | 20 + .../colorama-0.4.3.dist-info/METADATA | 411 + .../colorama-0.4.3.dist-info/RECORD | 22 + .../colorama-0.4.3.dist-info/WHEEL | 6 + .../colorama-0.4.3.dist-info/top_level.txt | 1 + .../site-packages/colorama-0.4.3.virtualenv | 0 .../site-packages/colorama/__init__.py | 6 + .../python3.8/site-packages/colorama/ansi.py | 102 + .../site-packages/colorama/ansitowin32.py | 257 + .../site-packages/colorama/initialise.py | 80 + .../python3.8/site-packages/colorama/win32.py | 152 + .../site-packages/colorama/winterm.py | 169 + .../contextlib2-0.6.0.dist-info/AUTHORS.txt | 562 ++ .../contextlib2-0.6.0.dist-info/INSTALLER | 1 + .../contextlib2-0.6.0.dist-info/LICENSE.txt | 20 + .../contextlib2-0.6.0.dist-info/METADATA | 70 + .../contextlib2-0.6.0.dist-info/RECORD | 11 + .../contextlib2-0.6.0.dist-info/WHEEL | 6 + .../contextlib2-0.6.0.dist-info/top_level.txt | 1 + .../contextlib2-0.6.0.virtualenv | 0 .../python3.8/site-packages/contextlib2.py | 518 ++ .../site-packages/dateutil/__init__.py | 8 + .../site-packages/dateutil/_common.py | 43 + .../site-packages/dateutil/_version.py | 4 + .../site-packages/dateutil/easter.py | 89 + .../site-packages/dateutil/parser/__init__.py | 61 + .../site-packages/dateutil/parser/_parser.py | 1609 ++++ .../dateutil/parser/isoparser.py | 411 + .../site-packages/dateutil/relativedelta.py | 599 ++ .../python3.8/site-packages/dateutil/rrule.py | 1735 ++++ .../site-packages/dateutil/tz/__init__.py | 12 + .../site-packages/dateutil/tz/_common.py | 419 + .../site-packages/dateutil/tz/_factories.py | 80 + .../python3.8/site-packages/dateutil/tz/tz.py | 1849 ++++ .../site-packages/dateutil/tz/win.py | 370 + .../python3.8/site-packages/dateutil/tzwin.py | 2 + .../python3.8/site-packages/dateutil/utils.py | 71 + .../dateutil/zoneinfo/__init__.py | 167 + .../dateutil/zoneinfo/rebuild.py | 53 + .../distlib-0.3.0.dist-info/AUTHORS.txt | 562 ++ .../distlib-0.3.0.dist-info/INSTALLER | 1 + .../distlib-0.3.0.dist-info/LICENSE.txt | 20 + .../distlib-0.3.0.dist-info/METADATA | 31 + .../distlib-0.3.0.dist-info/RECORD | 48 + .../distlib-0.3.0.dist-info/WHEEL | 6 + .../distlib-0.3.0.dist-info/top_level.txt | 1 + .../site-packages/distlib-0.3.0.virtualenv | 0 .../site-packages/distlib/__init__.py | 23 + .../distlib/_backport/__init__.py | 6 + .../site-packages/distlib/_backport/misc.py | 41 + .../site-packages/distlib/_backport/shutil.py | 761 ++ .../distlib/_backport/sysconfig.cfg | 84 + .../distlib/_backport/sysconfig.py | 786 ++ .../distlib/_backport/tarfile.py | 2607 ++++++ .../python3.8/site-packages/distlib/compat.py | 1120 +++ .../site-packages/distlib/database.py | 1339 +++ .../python3.8/site-packages/distlib/index.py | 516 ++ .../site-packages/distlib/locators.py | 1302 +++ .../site-packages/distlib/manifest.py | 393 + .../site-packages/distlib/markers.py | 131 + .../site-packages/distlib/metadata.py | 1096 +++ .../site-packages/distlib/resources.py | 355 + .../site-packages/distlib/scripts.py | 416 + .../python3.8/site-packages/distlib/util.py | 1761 ++++ .../site-packages/distlib/version.py | 736 ++ .../python3.8/site-packages/distlib/wheel.py | 1004 ++ .../distro-1.4.0.dist-info/AUTHORS.txt | 562 ++ .../distro-1.4.0.dist-info/INSTALLER | 1 + .../distro-1.4.0.dist-info/LICENSE.txt | 20 + .../distro-1.4.0.dist-info/METADATA | 170 + .../distro-1.4.0.dist-info/RECORD | 15 + .../distro-1.4.0.dist-info/WHEEL | 6 + .../distro-1.4.0.dist-info/entry_points.txt | 3 + .../distro-1.4.0.dist-info/top_level.txt | 1 + .../site-packages/distro-1.4.0.virtualenv | 0 .../lib/python3.8/site-packages/distro.py | 1216 +++ .../python3.8/site-packages/easy_install.py | 5 + .../site-packages/google/protobuf/__init__.py | 33 + .../site-packages/google/protobuf/any_pb2.py | 78 + .../site-packages/google/protobuf/api_pb2.py | 252 + .../google/protobuf/compiler/__init__.py | 0 .../google/protobuf/compiler/plugin_pb2.py | 301 + .../google/protobuf/descriptor.py | 1165 +++ .../google/protobuf/descriptor_database.py | 177 + .../google/protobuf/descriptor_pb2.py | 2106 +++++ .../google/protobuf/descriptor_pool.py | 1271 +++ .../google/protobuf/duration_pb2.py | 78 + .../google/protobuf/empty_pb2.py | 64 + .../google/protobuf/field_mask_pb2.py | 71 + .../google/protobuf/internal/__init__.py | 30 + ...lementation.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 5504 bytes .../protobuf/internal/api_implementation.py | 158 + .../google/protobuf/internal/containers.py | 785 ++ .../google/protobuf/internal/decoder.py | 1057 +++ .../google/protobuf/internal/encoder.py | 830 ++ .../protobuf/internal/enum_type_wrapper.py | 117 + .../protobuf/internal/extension_dict.py | 213 + .../protobuf/internal/message_listener.py | 78 + .../protobuf/internal/python_message.py | 1547 ++++ .../google/protobuf/internal/type_checkers.py | 426 + .../protobuf/internal/well_known_types.py | 863 ++ .../google/protobuf/internal/wire_format.py | 268 + .../google/protobuf/json_format.py | 865 ++ .../site-packages/google/protobuf/message.py | 413 + .../google/protobuf/message_factory.py | 187 + .../google/protobuf/proto_builder.py | 130 + .../google/protobuf/pyext/__init__.py | 0 .../_message.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 2474096 bytes .../google/protobuf/pyext/cpp_message.py | 65 + .../google/protobuf/reflection.py | 95 + .../site-packages/google/protobuf/service.py | 228 + .../google/protobuf/service_reflection.py | 287 + .../google/protobuf/source_context_pb2.py | 71 + .../google/protobuf/struct_pb2.py | 287 + .../google/protobuf/symbol_database.py | 194 + .../google/protobuf/text_encoding.py | 117 + .../google/protobuf/text_format.py | 1828 ++++ .../google/protobuf/timestamp_pb2.py | 78 + .../site-packages/google/protobuf/type_pb2.py | 573 ++ .../google/protobuf/util/__init__.py | 0 .../google/protobuf/util/json_format_pb2.py | 983 ++ .../protobuf/util/json_format_proto3_pb2.py | 2031 ++++ .../google/protobuf/wrappers_pb2.py | 391 + .../html5lib-1.0.1.dist-info/AUTHORS.txt | 562 ++ .../html5lib-1.0.1.dist-info/INSTALLER | 1 + .../html5lib-1.0.1.dist-info/LICENSE.txt | 20 + .../html5lib-1.0.1.dist-info/METADATA | 526 ++ .../html5lib-1.0.1.dist-info/RECORD | 83 + .../html5lib-1.0.1.dist-info/WHEEL | 6 + .../html5lib-1.0.1.dist-info/top_level.txt | 1 + .../site-packages/html5lib-1.0.1.virtualenv | 0 .../site-packages/html5lib/__init__.py | 35 + .../site-packages/html5lib/_ihatexml.py | 288 + .../site-packages/html5lib/_inputstream.py | 923 ++ .../site-packages/html5lib/_tokenizer.py | 1721 ++++ .../site-packages/html5lib/_trie/__init__.py | 14 + .../site-packages/html5lib/_trie/_base.py | 37 + .../site-packages/html5lib/_trie/datrie.py | 44 + .../site-packages/html5lib/_trie/py.py | 67 + .../site-packages/html5lib/_utils.py | 124 + .../site-packages/html5lib/constants.py | 2947 ++++++ .../html5lib/filters/__init__.py | 0 .../filters/alphabeticalattributes.py | 29 + .../site-packages/html5lib/filters/base.py | 12 + .../html5lib/filters/inject_meta_charset.py | 73 + .../site-packages/html5lib/filters/lint.py | 93 + .../html5lib/filters/optionaltags.py | 207 + .../html5lib/filters/sanitizer.py | 896 ++ .../html5lib/filters/whitespace.py | 38 + .../site-packages/html5lib/html5parser.py | 2791 ++++++ .../site-packages/html5lib/serializer.py | 409 + .../html5lib/treeadapters/__init__.py | 30 + .../html5lib/treeadapters/genshi.py | 54 + .../html5lib/treeadapters/sax.py | 50 + .../html5lib/treebuilders/__init__.py | 88 + .../html5lib/treebuilders/base.py | 417 + .../html5lib/treebuilders/dom.py | 236 + .../html5lib/treebuilders/etree.py | 340 + .../html5lib/treebuilders/etree_lxml.py | 366 + .../html5lib/treewalkers/__init__.py | 154 + .../html5lib/treewalkers/base.py | 252 + .../site-packages/html5lib/treewalkers/dom.py | 43 + .../html5lib/treewalkers/etree.py | 130 + .../html5lib/treewalkers/etree_lxml.py | 213 + .../html5lib/treewalkers/genshi.py | 69 + .../idna-2.8.dist-info/AUTHORS.txt | 562 ++ .../idna-2.8.dist-info/INSTALLER | 1 + .../idna-2.8.dist-info/LICENSE.txt | 20 + .../site-packages/idna-2.8.dist-info/METADATA | 239 + .../site-packages/idna-2.8.dist-info/RECORD | 26 + .../site-packages/idna-2.8.dist-info/WHEEL | 6 + .../idna-2.8.dist-info/top_level.txt | 1 + .../site-packages/idna-2.8.virtualenv | 0 .../python3.8/site-packages/idna/__init__.py | 2 + .../lib/python3.8/site-packages/idna/codec.py | 118 + .../python3.8/site-packages/idna/compat.py | 12 + .../lib/python3.8/site-packages/idna/core.py | 396 + .../python3.8/site-packages/idna/idnadata.py | 1979 ++++ .../python3.8/site-packages/idna/intranges.py | 53 + .../site-packages/idna/package_data.py | 2 + .../python3.8/site-packages/idna/uts46data.py | 8205 +++++++++++++++++ .../ipaddr-2.2.0.dist-info/AUTHORS.txt | 562 ++ .../ipaddr-2.2.0.dist-info/INSTALLER | 1 + .../ipaddr-2.2.0.dist-info/LICENSE.txt | 20 + .../ipaddr-2.2.0.dist-info/METADATA | 25 + .../ipaddr-2.2.0.dist-info/RECORD | 11 + .../ipaddr-2.2.0.dist-info/WHEEL | 6 + .../ipaddr-2.2.0.dist-info/top_level.txt | 1 + .../site-packages/ipaddr-2.2.0.virtualenv | 0 .../lib/python3.8/site-packages/ipaddr.py | 1928 ++++ .../site-packages/jinja2/__init__.py | 44 + .../python3.8/site-packages/jinja2/_compat.py | 132 + .../site-packages/jinja2/_identifier.py | 6 + .../site-packages/jinja2/asyncfilters.py | 158 + .../site-packages/jinja2/asyncsupport.py | 264 + .../python3.8/site-packages/jinja2/bccache.py | 350 + .../site-packages/jinja2/compiler.py | 1843 ++++ .../site-packages/jinja2/constants.py | 21 + .../python3.8/site-packages/jinja2/debug.py | 268 + .../site-packages/jinja2/defaults.py | 44 + .../site-packages/jinja2/environment.py | 1362 +++ .../site-packages/jinja2/exceptions.py | 177 + .../lib/python3.8/site-packages/jinja2/ext.py | 704 ++ .../python3.8/site-packages/jinja2/filters.py | 1382 +++ .../site-packages/jinja2/idtracking.py | 290 + .../python3.8/site-packages/jinja2/lexer.py | 848 ++ .../python3.8/site-packages/jinja2/loaders.py | 504 + .../python3.8/site-packages/jinja2/meta.py | 101 + .../site-packages/jinja2/nativetypes.py | 94 + .../python3.8/site-packages/jinja2/nodes.py | 1088 +++ .../site-packages/jinja2/optimizer.py | 41 + .../python3.8/site-packages/jinja2/parser.py | 939 ++ .../python3.8/site-packages/jinja2/runtime.py | 1011 ++ .../python3.8/site-packages/jinja2/sandbox.py | 510 + .../python3.8/site-packages/jinja2/tests.py | 215 + .../python3.8/site-packages/jinja2/utils.py | 732 ++ .../python3.8/site-packages/jinja2/visitor.py | 81 + .../jsonschema-3.2.0.dist-info/COPYING | 19 + .../jsonschema-3.2.0.dist-info/INSTALLER | 1 + .../jsonschema-3.2.0.dist-info/METADATA | 224 + .../jsonschema-3.2.0.dist-info/RECORD | 60 + .../jsonschema-3.2.0.dist-info/WHEEL | 6 + .../entry_points.txt | 3 + .../jsonschema-3.2.0.dist-info/top_level.txt | 1 + .../site-packages/jsonschema/__init__.py | 34 + .../site-packages/jsonschema/__main__.py | 2 + .../site-packages/jsonschema/_format.py | 425 + .../jsonschema/_legacy_validators.py | 141 + .../site-packages/jsonschema/_reflect.py | 155 + .../site-packages/jsonschema/_types.py | 188 + .../site-packages/jsonschema/_utils.py | 212 + .../site-packages/jsonschema/_validators.py | 373 + .../jsonschema/benchmarks/__init__.py | 5 + .../jsonschema/benchmarks/issue232.py | 26 + .../benchmarks/json_schema_test_suite.py | 14 + .../python3.8/site-packages/jsonschema/cli.py | 90 + .../site-packages/jsonschema/compat.py | 55 + .../site-packages/jsonschema/exceptions.py | 374 + .../jsonschema/schemas/draft3.json | 199 + .../jsonschema/schemas/draft4.json | 222 + .../jsonschema/schemas/draft6.json | 153 + .../jsonschema/schemas/draft7.json | 166 + .../jsonschema/tests/__init__.py | 0 .../jsonschema/tests/_helpers.py | 5 + .../site-packages/jsonschema/tests/_suite.py | 239 + .../jsonschema/tests/test_cli.py | 151 + .../jsonschema/tests/test_exceptions.py | 462 + .../jsonschema/tests/test_format.py | 89 + .../tests/test_jsonschema_test_suite.py | 277 + .../jsonschema/tests/test_types.py | 190 + .../jsonschema/tests/test_validators.py | 1762 ++++ .../site-packages/jsonschema/validators.py | 970 ++ .../lockfile-0.12.2.dist-info/AUTHORS.txt | 562 ++ .../lockfile-0.12.2.dist-info/INSTALLER | 1 + .../lockfile-0.12.2.dist-info/LICENSE.txt | 20 + .../lockfile-0.12.2.dist-info/METADATA | 58 + .../lockfile-0.12.2.dist-info/RECORD | 23 + .../lockfile-0.12.2.dist-info/WHEEL | 6 + .../lockfile-0.12.2.dist-info/pbr.json | 1 + .../lockfile-0.12.2.dist-info/top_level.txt | 1 + .../site-packages/lockfile-0.12.2.virtualenv | 0 .../site-packages/lockfile/__init__.py | 347 + .../site-packages/lockfile/linklockfile.py | 73 + .../site-packages/lockfile/mkdirlockfile.py | 84 + .../site-packages/lockfile/pidlockfile.py | 190 + .../site-packages/lockfile/sqlitelockfile.py | 156 + .../site-packages/lockfile/symlinklockfile.py | 70 + .../AUTHORS.rst | 8 + .../macaroonbakery-1.3.1.dist-info/INSTALLER | 1 + .../macaroonbakery-1.3.1.dist-info/LICENSE | 166 + .../macaroonbakery-1.3.1.dist-info/METADATA | 67 + .../macaroonbakery-1.3.1.dist-info/RECORD | 119 + .../macaroonbakery-1.3.1.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../site-packages/macaroonbakery/__init__.py | 0 .../macaroonbakery/_utils/__init__.py | 180 + .../macaroonbakery/bakery/__init__.py | 141 + .../macaroonbakery/bakery/_authorizer.py | 106 + .../macaroonbakery/bakery/_bakery.py | 72 + .../macaroonbakery/bakery/_checker.py | 418 + .../macaroonbakery/bakery/_codec.py | 301 + .../macaroonbakery/bakery/_discharge.py | 244 + .../macaroonbakery/bakery/_error.py | 77 + .../macaroonbakery/bakery/_identity.py | 126 + .../bakery/_internal/__init__.py | 0 .../macaroonbakery/bakery/_internal/id_pb2.py | 132 + .../macaroonbakery/bakery/_keys.py | 100 + .../macaroonbakery/bakery/_macaroon.py | 430 + .../macaroonbakery/bakery/_oven.py | 289 + .../macaroonbakery/bakery/_store.py | 77 + .../macaroonbakery/bakery/_third_party.py | 57 + .../macaroonbakery/bakery/_versions.py | 9 + .../macaroonbakery/checkers/__init__.py | 82 + .../macaroonbakery/checkers/_auth_context.py | 61 + .../macaroonbakery/checkers/_caveat.py | 128 + .../macaroonbakery/checkers/_checkers.py | 249 + .../macaroonbakery/checkers/_conditions.py | 17 + .../macaroonbakery/checkers/_declared.py | 84 + .../macaroonbakery/checkers/_namespace.py | 165 + .../macaroonbakery/checkers/_operation.py | 17 + .../macaroonbakery/checkers/_time.py | 67 + .../macaroonbakery/checkers/_utils.py | 13 + .../macaroonbakery/httpbakery/__init__.py | 55 + .../macaroonbakery/httpbakery/_browser.py | 90 + .../macaroonbakery/httpbakery/_client.py | 402 + .../macaroonbakery/httpbakery/_discharge.py | 37 + .../macaroonbakery/httpbakery/_error.py | 207 + .../macaroonbakery/httpbakery/_interactor.py | 70 + .../macaroonbakery/httpbakery/_keyring.py | 60 + .../httpbakery/agent/__init__.py | 19 + .../macaroonbakery/httpbakery/agent/_agent.py | 185 + .../macaroonbakery/tests/__init__.py | 2 + .../macaroonbakery/tests/common.py | 119 + .../macaroonbakery/tests/test_agent.py | 419 + .../macaroonbakery/tests/test_authorizer.py | 136 + .../macaroonbakery/tests/test_bakery.py | 286 + .../macaroonbakery/tests/test_checker.py | 946 ++ .../macaroonbakery/tests/test_checkers.py | 354 + .../macaroonbakery/tests/test_client.py | 682 ++ .../macaroonbakery/tests/test_codec.py | 196 + .../macaroonbakery/tests/test_discharge.py | 517 ++ .../tests/test_discharge_all.py | 164 + .../macaroonbakery/tests/test_httpbakery.py | 44 + .../macaroonbakery/tests/test_keyring.py | 111 + .../macaroonbakery/tests/test_macaroon.py | 201 + .../macaroonbakery/tests/test_namespace.py | 59 + .../macaroonbakery/tests/test_oven.py | 124 + .../macaroonbakery/tests/test_store.py | 21 + .../macaroonbakery/tests/test_time.py | 136 + .../macaroonbakery/tests/test_utils.py | 96 + .../site-packages/markupsafe/__init__.py | 327 + .../site-packages/markupsafe/_compat.py | 33 + .../site-packages/markupsafe/_constants.py | 264 + .../site-packages/markupsafe/_native.py | 69 + .../site-packages/markupsafe/_speedups.c | 423 + .../_speedups.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 48016 bytes .../msgpack-0.6.2.dist-info/AUTHORS.txt | 562 ++ .../msgpack-0.6.2.dist-info/INSTALLER | 1 + .../msgpack-0.6.2.dist-info/LICENSE.txt | 20 + .../msgpack-0.6.2.dist-info/METADATA | 362 + .../msgpack-0.6.2.dist-info/RECORD | 19 + .../msgpack-0.6.2.dist-info/WHEEL | 6 + .../msgpack-0.6.2.dist-info/top_level.txt | 1 + .../site-packages/msgpack-0.6.2.virtualenv | 0 .../site-packages/msgpack/__init__.py | 65 + .../_cmsgpack.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 163216 bytes .../site-packages/msgpack/_version.py | 1 + .../site-packages/msgpack/exceptions.py | 48 + .../site-packages/msgpack/fallback.py | 1027 +++ .../python3.8/site-packages/nacl/__init__.py | 33 + .../site-packages/nacl/_sodium.abi3.so | Bin 0 -> 3270761 bytes .../site-packages/nacl/bindings/__init__.py | 423 + .../nacl/bindings/crypto_aead.py | 485 + .../site-packages/nacl/bindings/crypto_box.py | 320 + .../nacl/bindings/crypto_core.py | 368 + .../nacl/bindings/crypto_generichash.py | 242 + .../nacl/bindings/crypto_hash.py | 70 + .../site-packages/nacl/bindings/crypto_kx.py | 167 + .../nacl/bindings/crypto_pwhash.py | 507 + .../nacl/bindings/crypto_scalarmult.py | 230 + .../nacl/bindings/crypto_secretbox.py | 81 + .../nacl/bindings/crypto_secretstream.py | 323 + .../nacl/bindings/crypto_shorthash.py | 77 + .../nacl/bindings/crypto_sign.py | 319 + .../nacl/bindings/randombytes.py | 51 + .../nacl/bindings/sodium_core.py | 32 + .../site-packages/nacl/bindings/utils.py | 154 + .../python3.8/site-packages/nacl/encoding.py | 90 + .../site-packages/nacl/exceptions.py | 81 + .../lib/python3.8/site-packages/nacl/hash.py | 165 + .../python3.8/site-packages/nacl/hashlib.py | 126 + .../python3.8/site-packages/nacl/public.py | 364 + .../site-packages/nacl/pwhash/__init__.py | 75 + .../site-packages/nacl/pwhash/_argon2.py | 52 + .../site-packages/nacl/pwhash/argon2i.py | 135 + .../site-packages/nacl/pwhash/argon2id.py | 134 + .../site-packages/nacl/pwhash/scrypt.py | 185 + .../python3.8/site-packages/nacl/secret.py | 133 + .../python3.8/site-packages/nacl/signing.py | 216 + .../lib/python3.8/site-packages/nacl/utils.py | 85 + .../packaging-20.3.dist-info/AUTHORS.txt | 562 ++ .../packaging-20.3.dist-info/INSTALLER | 1 + .../packaging-20.3.dist-info/LICENSE.txt | 20 + .../packaging-20.3.dist-info/METADATA | 362 + .../packaging-20.3.dist-info/RECORD | 33 + .../packaging-20.3.dist-info/WHEEL | 6 + .../packaging-20.3.dist-info/top_level.txt | 1 + .../site-packages/packaging-20.3.virtualenv | 0 .../site-packages/packaging/__about__.py | 27 + .../site-packages/packaging/__init__.py | 26 + .../site-packages/packaging/_compat.py | 38 + .../site-packages/packaging/_structures.py | 86 + .../site-packages/packaging/_typing.py | 39 + .../site-packages/packaging/markers.py | 328 + .../site-packages/packaging/py.typed | 0 .../site-packages/packaging/requirements.py | 145 + .../site-packages/packaging/specifiers.py | 849 ++ .../python3.8/site-packages/packaging/tags.py | 739 ++ .../site-packages/packaging/utils.py | 62 + .../site-packages/packaging/version.py | 535 ++ .../pep517-0.8.2.dist-info/AUTHORS.txt | 562 ++ .../pep517-0.8.2.dist-info/INSTALLER | 1 + .../pep517-0.8.2.dist-info/LICENSE.txt | 20 + .../pep517-0.8.2.dist-info/METADATA | 15 + .../pep517-0.8.2.dist-info/RECORD | 30 + .../pep517-0.8.2.dist-info/WHEEL | 6 + .../pep517-0.8.2.dist-info/top_level.txt | 1 + .../site-packages/pep517-0.8.2.virtualenv | 0 .../site-packages/pep517/__init__.py | 4 + .../site-packages/pep517/_in_process.py | 280 + .../python3.8/site-packages/pep517/build.py | 124 + .../python3.8/site-packages/pep517/check.py | 203 + .../site-packages/pep517/colorlog.py | 115 + .../python3.8/site-packages/pep517/compat.py | 34 + .../site-packages/pep517/dirtools.py | 44 + .../site-packages/pep517/envbuild.py | 167 + .../python3.8/site-packages/pep517/meta.py | 92 + .../site-packages/pep517/wrappers.py | 308 + .../pip-20.0.2.dist-info/INSTALLER | 1 + .../pip-20.0.2.dist-info/LICENSE.txt | 20 + .../pip-20.0.2.dist-info/METADATA | 84 + .../site-packages/pip-20.0.2.dist-info/RECORD | 264 + .../site-packages/pip-20.0.2.dist-info/WHEEL | 6 + .../pip-20.0.2.dist-info/entry_points.txt | 5 + .../pip-20.0.2.dist-info/top_level.txt | 1 + .../site-packages/pip-20.0.2.virtualenv | 0 .../python3.8/site-packages/pip/__init__.py | 18 + .../python3.8/site-packages/pip/__main__.py | 19 + .../site-packages/pip/_internal/__init__.py | 18 + .../site-packages/pip/_internal/build_env.py | 221 + .../site-packages/pip/_internal/cache.py | 329 + .../pip/_internal/cli/__init__.py | 4 + .../pip/_internal/cli/autocompletion.py | 164 + .../pip/_internal/cli/base_command.py | 226 + .../pip/_internal/cli/cmdoptions.py | 957 ++ .../pip/_internal/cli/command_context.py | 36 + .../site-packages/pip/_internal/cli/main.py | 75 + .../pip/_internal/cli/main_parser.py | 99 + .../site-packages/pip/_internal/cli/parser.py | 265 + .../pip/_internal/cli/req_command.py | 333 + .../pip/_internal/cli/status_codes.py | 8 + .../pip/_internal/commands/__init__.py | 114 + .../pip/_internal/commands/check.py | 45 + .../pip/_internal/commands/completion.py | 96 + .../pip/_internal/commands/configuration.py | 233 + .../pip/_internal/commands/debug.py | 142 + .../pip/_internal/commands/download.py | 147 + .../pip/_internal/commands/freeze.py | 103 + .../pip/_internal/commands/hash.py | 58 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/install.py | 727 ++ .../pip/_internal/commands/list.py | 315 + .../pip/_internal/commands/search.py | 145 + .../pip/_internal/commands/show.py | 180 + .../pip/_internal/commands/uninstall.py | 82 + .../pip/_internal/commands/wheel.py | 197 + .../pip/_internal/configuration.py | 422 + .../pip/_internal/distributions/__init__.py | 24 + .../pip/_internal/distributions/base.py | 45 + .../pip/_internal/distributions/installed.py | 24 + .../pip/_internal/distributions/sdist.py | 104 + .../pip/_internal/distributions/wheel.py | 36 + .../site-packages/pip/_internal/exceptions.py | 308 + .../pip/_internal/index/__init__.py | 2 + .../pip/_internal/index/collector.py | 544 ++ .../pip/_internal/index/package_finder.py | 1013 ++ .../pip/_internal/legacy_resolve.py | 430 + .../site-packages/pip/_internal/locations.py | 194 + .../site-packages/pip/_internal/main.py | 16 + .../pip/_internal/models/__init__.py | 2 + .../pip/_internal/models/candidate.py | 36 + .../pip/_internal/models/format_control.py | 84 + .../pip/_internal/models/index.py | 31 + .../pip/_internal/models/link.py | 227 + .../pip/_internal/models/scheme.py | 25 + .../pip/_internal/models/search_scope.py | 114 + .../pip/_internal/models/selection_prefs.py | 47 + .../pip/_internal/models/target_python.py | 107 + .../pip/_internal/models/wheel.py | 78 + .../pip/_internal/network/__init__.py | 2 + .../pip/_internal/network/auth.py | 298 + .../pip/_internal/network/cache.py | 81 + .../pip/_internal/network/download.py | 200 + .../pip/_internal/network/session.py | 405 + .../pip/_internal/network/utils.py | 48 + .../pip/_internal/network/xmlrpc.py | 44 + .../pip/_internal/operations/__init__.py | 0 .../pip/_internal/operations/check.py | 163 + .../pip/_internal/operations/freeze.py | 265 + .../_internal/operations/install/__init__.py | 2 + .../operations/install/editable_legacy.py | 52 + .../_internal/operations/install/legacy.py | 129 + .../pip/_internal/operations/install/wheel.py | 615 ++ .../pip/_internal/operations/prepare.py | 591 ++ .../site-packages/pip/_internal/pep425tags.py | 167 + .../site-packages/pip/_internal/pyproject.py | 196 + .../pip/_internal/req/__init__.py | 92 + .../pip/_internal/req/constructors.py | 436 + .../pip/_internal/req/req_file.py | 546 ++ .../pip/_internal/req/req_install.py | 830 ++ .../pip/_internal/req/req_set.py | 209 + .../pip/_internal/req/req_tracker.py | 150 + .../pip/_internal/req/req_uninstall.py | 644 ++ .../pip/_internal/self_outdated_check.py | 242 + .../pip/_internal/utils/__init__.py | 0 .../pip/_internal/utils/appdirs.py | 41 + .../pip/_internal/utils/compat.py | 269 + .../pip/_internal/utils/deprecation.py | 104 + .../pip/_internal/utils/distutils_args.py | 48 + .../pip/_internal/utils/encoding.py | 42 + .../pip/_internal/utils/entrypoints.py | 31 + .../pip/_internal/utils/filesystem.py | 171 + .../pip/_internal/utils/filetypes.py | 16 + .../pip/_internal/utils/glibc.py | 98 + .../pip/_internal/utils/hashes.py | 131 + .../_internal/utils/inject_securetransport.py | 36 + .../pip/_internal/utils/logging.py | 398 + .../pip/_internal/utils/marker_files.py | 25 + .../site-packages/pip/_internal/utils/misc.py | 904 ++ .../pip/_internal/utils/models.py | 42 + .../pip/_internal/utils/packaging.py | 94 + .../pip/_internal/utils/pkg_resources.py | 44 + .../pip/_internal/utils/setuptools_build.py | 181 + .../pip/_internal/utils/subprocess.py | 278 + .../pip/_internal/utils/temp_dir.py | 250 + .../pip/_internal/utils/typing.py | 38 + .../site-packages/pip/_internal/utils/ui.py | 428 + .../pip/_internal/utils/unpacking.py | 272 + .../site-packages/pip/_internal/utils/urls.py | 54 + .../pip/_internal/utils/virtualenv.py | 115 + .../pip/_internal/utils/wheel.py | 225 + .../pip/_internal/vcs/__init__.py | 15 + .../site-packages/pip/_internal/vcs/bazaar.py | 120 + .../site-packages/pip/_internal/vcs/git.py | 389 + .../pip/_internal/vcs/mercurial.py | 155 + .../pip/_internal/vcs/subversion.py | 333 + .../pip/_internal/vcs/versioncontrol.py | 700 ++ .../pip/_internal/wheel_builder.py | 305 + .../site-packages/pip/_vendor/__init__.py | 117 + .../pkg_resources-0.0.0.dist-info/AUTHORS.txt | 562 ++ .../pkg_resources-0.0.0.dist-info/INSTALLER | 1 + .../pkg_resources-0.0.0.dist-info/LICENSE.txt | 20 + .../pkg_resources-0.0.0.dist-info/METADATA | 13 + .../pkg_resources-0.0.0.dist-info/RECORD | 44 + .../pkg_resources-0.0.0.dist-info/WHEEL | 6 + .../pkg_resources-0.0.0.virtualenv | 0 .../site-packages/pkg_resources/__init__.py | 3296 +++++++ .../pkg_resources/_vendor/__init__.py | 0 .../pkg_resources/_vendor/appdirs.py | 608 ++ .../_vendor/packaging/__about__.py | 21 + .../_vendor/packaging/__init__.py | 14 + .../_vendor/packaging/_compat.py | 30 + .../_vendor/packaging/_structures.py | 68 + .../_vendor/packaging/markers.py | 301 + .../_vendor/packaging/requirements.py | 127 + .../_vendor/packaging/specifiers.py | 774 ++ .../pkg_resources/_vendor/packaging/utils.py | 14 + .../_vendor/packaging/version.py | 393 + .../pkg_resources/_vendor/pyparsing.py | 5742 ++++++++++++ .../pkg_resources/_vendor/six.py | 868 ++ .../pkg_resources/extern/__init__.py | 73 + .../site-packages/pkg_resources/py31compat.py | 23 + .../progress-1.5.dist-info/AUTHORS.txt | 562 ++ .../progress-1.5.dist-info/INSTALLER | 1 + .../progress-1.5.dist-info/LICENSE.txt | 20 + .../progress-1.5.dist-info/METADATA | 173 + .../progress-1.5.dist-info/RECORD | 18 + .../progress-1.5.dist-info/WHEEL | 6 + .../progress-1.5.dist-info/top_level.txt | 1 + .../site-packages/progress-1.5.virtualenv | 0 .../site-packages/progress/__init__.py | 177 + .../python3.8/site-packages/progress/bar.py | 91 + .../site-packages/progress/counter.py | 41 + .../site-packages/progress/spinner.py | 43 + .../protobuf-3.15.4-py3.8-nspkg.pth | 1 + .../protobuf-3.15.4.dist-info/INSTALLER | 1 + .../protobuf-3.15.4.dist-info/METADATA | 26 + .../protobuf-3.15.4.dist-info/RECORD | 97 + .../protobuf-3.15.4.dist-info/WHEEL | 5 + .../namespace_packages.txt | 1 + .../protobuf-3.15.4.dist-info/top_level.txt | 1 + .../pvectorc.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 140144 bytes .../pyRFC3339-1.1.dist-info/INSTALLER | 1 + .../pyRFC3339-1.1.dist-info/METADATA | 62 + .../pyRFC3339-1.1.dist-info/RECORD | 13 + .../pyRFC3339-1.1.dist-info/WHEEL | 6 + .../pyRFC3339-1.1.dist-info/top_level.txt | 1 + .../pycparser-2.20.dist-info/INSTALLER | 1 + .../pycparser-2.20.dist-info/LICENSE | 27 + .../pycparser-2.20.dist-info/METADATA | 27 + .../pycparser-2.20.dist-info/RECORD | 41 + .../pycparser-2.20.dist-info/WHEEL | 6 + .../pycparser-2.20.dist-info/top_level.txt | 1 + .../site-packages/pycparser/__init__.py | 90 + .../site-packages/pycparser/_ast_gen.py | 338 + .../site-packages/pycparser/_build_tables.py | 37 + .../site-packages/pycparser/_c_ast.cfg | 191 + .../site-packages/pycparser/ast_transforms.py | 106 + .../site-packages/pycparser/c_ast.py | 1084 +++ .../site-packages/pycparser/c_generator.py | 444 + .../site-packages/pycparser/c_lexer.py | 514 ++ .../site-packages/pycparser/c_parser.py | 1863 ++++ .../site-packages/pycparser/lextab.py | 10 + .../site-packages/pycparser/ply/__init__.py | 5 + .../site-packages/pycparser/ply/cpp.py | 905 ++ .../site-packages/pycparser/ply/ctokens.py | 133 + .../site-packages/pycparser/ply/lex.py | 1099 +++ .../site-packages/pycparser/ply/yacc.py | 3494 +++++++ .../site-packages/pycparser/ply/ygen.py | 74 + .../site-packages/pycparser/plyparser.py | 133 + .../site-packages/pycparser/yacctab.py | 338 + .../DESCRIPTION.rst | 30 + .../pymacaroons-0.13.0.dist-info/INSTALLER | 1 + .../pymacaroons-0.13.0.dist-info/METADATA | 59 + .../pymacaroons-0.13.0.dist-info/RECORD | 51 + .../pymacaroons-0.13.0.dist-info/WHEEL | 6 + .../metadata.json | 1 + .../top_level.txt | 1 + .../site-packages/pymacaroons/__init__.py | 21 + .../pymacaroons/binders/__init__.py | 7 + .../pymacaroons/binders/base_binder.py | 17 + .../binders/hash_signatures_binder.py | 18 + .../site-packages/pymacaroons/caveat.py | 70 + .../pymacaroons/caveat_delegates/__init__.py | 20 + .../caveat_delegates/base_first_party.py | 29 + .../caveat_delegates/base_third_party.py | 40 + .../caveat_delegates/encrypted_first_party.py | 58 + .../caveat_delegates/first_party.py | 51 + .../caveat_delegates/third_party.py | 106 + .../site-packages/pymacaroons/exceptions.py | 26 + .../pymacaroons/field_encryptors/__init__.py | 7 + .../field_encryptors/base_field_encryptor.py | 22 + .../field_encryptors/secret_box_encryptor.py | 32 + .../site-packages/pymacaroons/macaroon.py | 149 + .../pymacaroons/serializers/__init__.py | 9 + .../serializers/base_serializer.py | 13 + .../serializers/binary_serializer.py | 356 + .../serializers/json_serializer.py | 181 + .../site-packages/pymacaroons/utils.py | 131 + .../site-packages/pymacaroons/verifier.py | 127 + .../pyparsing-2.4.6.dist-info/AUTHORS.txt | 562 ++ .../pyparsing-2.4.6.dist-info/INSTALLER | 1 + .../pyparsing-2.4.6.dist-info/LICENSE.txt | 20 + .../pyparsing-2.4.6.dist-info/METADATA | 104 + .../pyparsing-2.4.6.dist-info/RECORD | 11 + .../pyparsing-2.4.6.dist-info/WHEEL | 6 + .../pyparsing-2.4.6.dist-info/top_level.txt | 1 + .../site-packages/pyparsing-2.4.6.virtualenv | 0 .../lib/python3.8/site-packages/pyparsing.py | 7090 ++++++++++++++ .../site-packages/pyrfc3339/__init__.py | 20 + .../site-packages/pyrfc3339/generator.py | 67 + .../site-packages/pyrfc3339/parser.py | 87 + .../site-packages/pyrfc3339/utils.py | 143 + .../pyrsistent-0.17.3.dist-info/INSTALLER | 1 + .../pyrsistent-0.17.3.dist-info/LICENCE.mit | 22 + .../pyrsistent-0.17.3.dist-info/METADATA | 741 ++ .../pyrsistent-0.17.3.dist-info/RECORD | 44 + .../pyrsistent-0.17.3.dist-info/WHEEL | 5 + .../pyrsistent-0.17.3.dist-info/top_level.txt | 3 + .../site-packages/pyrsistent/__init__.py | 47 + .../site-packages/pyrsistent/__init__.pyi | 213 + .../pyrsistent/_checked_types.py | 539 ++ .../site-packages/pyrsistent/_field_common.py | 329 + .../site-packages/pyrsistent/_helpers.py | 81 + .../site-packages/pyrsistent/_immutable.py | 103 + .../site-packages/pyrsistent/_pbag.py | 267 + .../site-packages/pyrsistent/_pclass.py | 262 + .../site-packages/pyrsistent/_pdeque.py | 376 + .../site-packages/pyrsistent/_plist.py | 313 + .../site-packages/pyrsistent/_pmap.py | 459 + .../site-packages/pyrsistent/_precord.py | 167 + .../site-packages/pyrsistent/_pset.py | 227 + .../site-packages/pyrsistent/_pvector.py | 711 ++ .../site-packages/pyrsistent/_toolz.py | 83 + .../pyrsistent/_transformations.py | 139 + .../site-packages/pyrsistent/py.typed | 0 .../site-packages/pyrsistent/typing.py | 80 + .../site-packages/pyrsistent/typing.pyi | 292 + .../python_dateutil-2.8.1.dist-info/INSTALLER | 1 + .../python_dateutil-2.8.1.dist-info/LICENSE | 54 + .../python_dateutil-2.8.1.dist-info/METADATA | 200 + .../python_dateutil-2.8.1.dist-info/RECORD | 44 + .../python_dateutil-2.8.1.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../python_dateutil-2.8.1.dist-info/zip-safe | 1 + .../pytoml-0.1.21.dist-info/AUTHORS.txt | 562 ++ .../pytoml-0.1.21.dist-info/INSTALLER | 1 + .../pytoml-0.1.21.dist-info/LICENSE.txt | 20 + .../pytoml-0.1.21.dist-info/METADATA | 69 + .../pytoml-0.1.21.dist-info/RECORD | 22 + .../pytoml-0.1.21.dist-info/WHEEL | 6 + .../pytoml-0.1.21.dist-info/top_level.txt | 1 + .../site-packages/pytoml-0.1.21.virtualenv | 0 .../site-packages/pytoml/__init__.py | 4 + .../python3.8/site-packages/pytoml/core.py | 13 + .../python3.8/site-packages/pytoml/parser.py | 342 + .../python3.8/site-packages/pytoml/test.py | 30 + .../python3.8/site-packages/pytoml/utils.py | 67 + .../python3.8/site-packages/pytoml/writer.py | 114 + .../pytz-2021.1.dist-info/DESCRIPTION.rst | 598 ++ .../pytz-2021.1.dist-info/INSTALLER | 1 + .../pytz-2021.1.dist-info/LICENSE.txt | 19 + .../pytz-2021.1.dist-info/METADATA | 634 ++ .../pytz-2021.1.dist-info/RECORD | 620 ++ .../site-packages/pytz-2021.1.dist-info/WHEEL | 6 + .../pytz-2021.1.dist-info/metadata.json | 1 + .../pytz-2021.1.dist-info/top_level.txt | 1 + .../pytz-2021.1.dist-info/zip-safe | 1 + .../python3.8/site-packages/pytz/__init__.py | 1558 ++++ .../site-packages/pytz/exceptions.py | 59 + .../lib/python3.8/site-packages/pytz/lazy.py | 172 + .../python3.8/site-packages/pytz/reference.py | 140 + .../python3.8/site-packages/pytz/tzfile.py | 133 + .../python3.8/site-packages/pytz/tzinfo.py | 577 ++ .../pytz/zoneinfo/Africa/Abidjan | Bin 0 -> 148 bytes .../site-packages/pytz/zoneinfo/Africa/Accra | Bin 0 -> 1060 bytes .../pytz/zoneinfo/Africa/Addis_Ababa | Bin 0 -> 265 bytes .../pytz/zoneinfo/Africa/Algiers | Bin 0 -> 735 bytes .../site-packages/pytz/zoneinfo/Africa/Asmara | Bin 0 -> 265 bytes .../site-packages/pytz/zoneinfo/Africa/Asmera | Bin 0 -> 265 bytes .../site-packages/pytz/zoneinfo/Africa/Bamako | Bin 0 -> 148 bytes .../site-packages/pytz/zoneinfo/Africa/Bangui | Bin 0 -> 235 bytes .../site-packages/pytz/zoneinfo/Africa/Banjul | Bin 0 -> 148 bytes .../site-packages/pytz/zoneinfo/Africa/Bissau | Bin 0 -> 194 bytes .../pytz/zoneinfo/Africa/Blantyre | Bin 0 -> 149 bytes .../pytz/zoneinfo/Africa/Brazzaville | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/Bujumbura | Bin 0 -> 149 bytes .../site-packages/pytz/zoneinfo/Africa/Cairo | Bin 0 -> 1955 bytes .../pytz/zoneinfo/Africa/Casablanca | Bin 0 -> 2429 bytes .../site-packages/pytz/zoneinfo/Africa/Ceuta | Bin 0 -> 2036 bytes .../pytz/zoneinfo/Africa/Conakry | Bin 0 -> 148 bytes .../site-packages/pytz/zoneinfo/Africa/Dakar | Bin 0 -> 148 bytes .../pytz/zoneinfo/Africa/Dar_es_Salaam | Bin 0 -> 265 bytes .../pytz/zoneinfo/Africa/Djibouti | Bin 0 -> 265 bytes .../site-packages/pytz/zoneinfo/Africa/Douala | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/El_Aaiun | Bin 0 -> 2295 bytes .../pytz/zoneinfo/Africa/Freetown | Bin 0 -> 148 bytes .../pytz/zoneinfo/Africa/Gaborone | Bin 0 -> 149 bytes .../site-packages/pytz/zoneinfo/Africa/Harare | Bin 0 -> 149 bytes .../pytz/zoneinfo/Africa/Johannesburg | Bin 0 -> 246 bytes .../site-packages/pytz/zoneinfo/Africa/Juba | Bin 0 -> 679 bytes .../pytz/zoneinfo/Africa/Kampala | Bin 0 -> 265 bytes .../pytz/zoneinfo/Africa/Khartoum | Bin 0 -> 679 bytes .../site-packages/pytz/zoneinfo/Africa/Kigali | Bin 0 -> 149 bytes .../pytz/zoneinfo/Africa/Kinshasa | Bin 0 -> 235 bytes .../site-packages/pytz/zoneinfo/Africa/Lagos | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/Libreville | Bin 0 -> 235 bytes .../site-packages/pytz/zoneinfo/Africa/Lome | Bin 0 -> 148 bytes .../site-packages/pytz/zoneinfo/Africa/Luanda | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/Lubumbashi | Bin 0 -> 149 bytes .../site-packages/pytz/zoneinfo/Africa/Lusaka | Bin 0 -> 149 bytes .../site-packages/pytz/zoneinfo/Africa/Malabo | Bin 0 -> 235 bytes .../site-packages/pytz/zoneinfo/Africa/Maputo | Bin 0 -> 149 bytes .../site-packages/pytz/zoneinfo/Africa/Maseru | Bin 0 -> 246 bytes .../pytz/zoneinfo/Africa/Mbabane | Bin 0 -> 246 bytes .../pytz/zoneinfo/Africa/Mogadishu | Bin 0 -> 265 bytes .../pytz/zoneinfo/Africa/Monrovia | Bin 0 -> 208 bytes .../pytz/zoneinfo/Africa/Nairobi | Bin 0 -> 265 bytes .../pytz/zoneinfo/Africa/Ndjamena | Bin 0 -> 199 bytes .../site-packages/pytz/zoneinfo/Africa/Niamey | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/Nouakchott | Bin 0 -> 148 bytes .../pytz/zoneinfo/Africa/Ouagadougou | Bin 0 -> 148 bytes .../pytz/zoneinfo/Africa/Porto-Novo | Bin 0 -> 235 bytes .../pytz/zoneinfo/Africa/Sao_Tome | Bin 0 -> 254 bytes .../pytz/zoneinfo/Africa/Timbuktu | Bin 0 -> 148 bytes .../pytz/zoneinfo/Africa/Tripoli | Bin 0 -> 625 bytes .../site-packages/pytz/zoneinfo/Africa/Tunis | Bin 0 -> 689 bytes .../pytz/zoneinfo/Africa/Windhoek | Bin 0 -> 955 bytes .../site-packages/pytz/zoneinfo/America/Adak | Bin 0 -> 2356 bytes .../pytz/zoneinfo/America/Anchorage | Bin 0 -> 2371 bytes .../pytz/zoneinfo/America/Anguilla | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Antigua | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Araguaina | Bin 0 -> 884 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Argentina/Catamarca | Bin 0 -> 1076 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Argentina/Cordoba | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Argentina/Jujuy | Bin 0 -> 1048 bytes .../pytz/zoneinfo/America/Argentina/La_Rioja | Bin 0 -> 1090 bytes .../pytz/zoneinfo/America/Argentina/Mendoza | Bin 0 -> 1076 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Argentina/Salta | Bin 0 -> 1048 bytes .../pytz/zoneinfo/America/Argentina/San_Juan | Bin 0 -> 1090 bytes .../pytz/zoneinfo/America/Argentina/San_Luis | Bin 0 -> 1102 bytes .../pytz/zoneinfo/America/Argentina/Tucuman | Bin 0 -> 1104 bytes .../pytz/zoneinfo/America/Argentina/Ushuaia | Bin 0 -> 1076 bytes .../site-packages/pytz/zoneinfo/America/Aruba | Bin 0 -> 186 bytes .../pytz/zoneinfo/America/Asuncion | Bin 0 -> 2044 bytes .../pytz/zoneinfo/America/Atikokan | Bin 0 -> 336 bytes .../site-packages/pytz/zoneinfo/America/Atka | Bin 0 -> 2356 bytes .../site-packages/pytz/zoneinfo/America/Bahia | Bin 0 -> 1024 bytes .../pytz/zoneinfo/America/Bahia_Banderas | Bin 0 -> 1546 bytes .../pytz/zoneinfo/America/Barbados | Bin 0 -> 314 bytes .../site-packages/pytz/zoneinfo/America/Belem | Bin 0 -> 576 bytes .../pytz/zoneinfo/America/Belize | Bin 0 -> 1614 bytes .../pytz/zoneinfo/America/Blanc-Sablon | Bin 0 -> 298 bytes .../pytz/zoneinfo/America/Boa_Vista | Bin 0 -> 632 bytes .../pytz/zoneinfo/America/Bogota | Bin 0 -> 246 bytes .../site-packages/pytz/zoneinfo/America/Boise | Bin 0 -> 2394 bytes .../pytz/zoneinfo/America/Buenos_Aires | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Cambridge_Bay | Bin 0 -> 2084 bytes .../pytz/zoneinfo/America/Campo_Grande | Bin 0 -> 1444 bytes .../pytz/zoneinfo/America/Cancun | Bin 0 -> 782 bytes .../pytz/zoneinfo/America/Caracas | Bin 0 -> 264 bytes .../pytz/zoneinfo/America/Catamarca | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Cayenne | Bin 0 -> 198 bytes .../pytz/zoneinfo/America/Cayman | Bin 0 -> 182 bytes .../pytz/zoneinfo/America/Chicago | Bin 0 -> 3576 bytes .../pytz/zoneinfo/America/Chihuahua | Bin 0 -> 1484 bytes .../pytz/zoneinfo/America/Coral_Harbour | Bin 0 -> 336 bytes .../pytz/zoneinfo/America/Cordoba | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Costa_Rica | Bin 0 -> 316 bytes .../pytz/zoneinfo/America/Creston | Bin 0 -> 208 bytes .../pytz/zoneinfo/America/Cuiaba | Bin 0 -> 1416 bytes .../pytz/zoneinfo/America/Curacao | Bin 0 -> 186 bytes .../pytz/zoneinfo/America/Danmarkshavn | Bin 0 -> 698 bytes .../pytz/zoneinfo/America/Dawson | Bin 0 -> 1614 bytes .../pytz/zoneinfo/America/Dawson_Creek | Bin 0 -> 1050 bytes .../pytz/zoneinfo/America/Denver | Bin 0 -> 2444 bytes .../pytz/zoneinfo/America/Detroit | Bin 0 -> 2230 bytes .../pytz/zoneinfo/America/Dominica | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Edmonton | Bin 0 -> 2332 bytes .../pytz/zoneinfo/America/Eirunepe | Bin 0 -> 656 bytes .../pytz/zoneinfo/America/El_Salvador | Bin 0 -> 224 bytes .../pytz/zoneinfo/America/Ensenada | Bin 0 -> 2342 bytes .../pytz/zoneinfo/America/Fort_Nelson | Bin 0 -> 2240 bytes .../pytz/zoneinfo/America/Fort_Wayne | Bin 0 -> 1666 bytes .../pytz/zoneinfo/America/Fortaleza | Bin 0 -> 716 bytes .../pytz/zoneinfo/America/Glace_Bay | Bin 0 -> 2192 bytes .../pytz/zoneinfo/America/Godthab | Bin 0 -> 1878 bytes .../pytz/zoneinfo/America/Goose_Bay | Bin 0 -> 3210 bytes .../pytz/zoneinfo/America/Grand_Turk | Bin 0 -> 1834 bytes .../pytz/zoneinfo/America/Grenada | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Guadeloupe | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Guatemala | Bin 0 -> 280 bytes .../pytz/zoneinfo/America/Guayaquil | Bin 0 -> 246 bytes .../pytz/zoneinfo/America/Guyana | Bin 0 -> 236 bytes .../pytz/zoneinfo/America/Halifax | Bin 0 -> 3424 bytes .../pytz/zoneinfo/America/Havana | Bin 0 -> 2416 bytes .../pytz/zoneinfo/America/Hermosillo | Bin 0 -> 416 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 0 -> 1666 bytes .../pytz/zoneinfo/America/Indiana/Knox | Bin 0 -> 2428 bytes .../pytz/zoneinfo/America/Indiana/Marengo | Bin 0 -> 1722 bytes .../pytz/zoneinfo/America/Indiana/Petersburg | Bin 0 -> 1904 bytes .../pytz/zoneinfo/America/Indiana/Tell_City | Bin 0 -> 1684 bytes .../pytz/zoneinfo/America/Indiana/Vevay | Bin 0 -> 1414 bytes .../pytz/zoneinfo/America/Indiana/Vincennes | Bin 0 -> 1694 bytes .../pytz/zoneinfo/America/Indiana/Winamac | Bin 0 -> 1778 bytes .../pytz/zoneinfo/America/Indianapolis | Bin 0 -> 1666 bytes .../pytz/zoneinfo/America/Inuvik | Bin 0 -> 1894 bytes .../pytz/zoneinfo/America/Iqaluit | Bin 0 -> 2032 bytes .../pytz/zoneinfo/America/Jamaica | Bin 0 -> 482 bytes .../site-packages/pytz/zoneinfo/America/Jujuy | Bin 0 -> 1048 bytes .../pytz/zoneinfo/America/Juneau | Bin 0 -> 2353 bytes .../pytz/zoneinfo/America/Kentucky/Louisville | Bin 0 -> 2772 bytes .../pytz/zoneinfo/America/Kentucky/Monticello | Bin 0 -> 2352 bytes .../pytz/zoneinfo/America/Knox_IN | Bin 0 -> 2428 bytes .../pytz/zoneinfo/America/Kralendijk | Bin 0 -> 186 bytes .../pytz/zoneinfo/America/La_Paz | Bin 0 -> 232 bytes .../site-packages/pytz/zoneinfo/America/Lima | Bin 0 -> 406 bytes .../pytz/zoneinfo/America/Los_Angeles | Bin 0 -> 2836 bytes .../pytz/zoneinfo/America/Louisville | Bin 0 -> 2772 bytes .../pytz/zoneinfo/America/Lower_Princes | Bin 0 -> 186 bytes .../pytz/zoneinfo/America/Maceio | Bin 0 -> 744 bytes .../pytz/zoneinfo/America/Managua | Bin 0 -> 430 bytes .../pytz/zoneinfo/America/Manaus | Bin 0 -> 604 bytes .../pytz/zoneinfo/America/Marigot | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Martinique | Bin 0 -> 232 bytes .../pytz/zoneinfo/America/Matamoros | Bin 0 -> 1390 bytes .../pytz/zoneinfo/America/Mazatlan | Bin 0 -> 1526 bytes .../pytz/zoneinfo/America/Mendoza | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Menominee | Bin 0 -> 2274 bytes .../pytz/zoneinfo/America/Merida | Bin 0 -> 1422 bytes .../pytz/zoneinfo/America/Metlakatla | Bin 0 -> 1423 bytes .../pytz/zoneinfo/America/Mexico_City | Bin 0 -> 1584 bytes .../pytz/zoneinfo/America/Miquelon | Bin 0 -> 1666 bytes .../pytz/zoneinfo/America/Moncton | Bin 0 -> 3154 bytes .../pytz/zoneinfo/America/Monterrey | Bin 0 -> 1390 bytes .../pytz/zoneinfo/America/Montevideo | Bin 0 -> 1510 bytes .../pytz/zoneinfo/America/Montreal | Bin 0 -> 3494 bytes .../pytz/zoneinfo/America/Montserrat | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Nassau | Bin 0 -> 2388 bytes .../pytz/zoneinfo/America/New_York | Bin 0 -> 3536 bytes .../pytz/zoneinfo/America/Nipigon | Bin 0 -> 2122 bytes .../site-packages/pytz/zoneinfo/America/Nome | Bin 0 -> 2367 bytes .../pytz/zoneinfo/America/Noronha | Bin 0 -> 716 bytes .../pytz/zoneinfo/America/North_Dakota/Beulah | Bin 0 -> 2380 bytes .../pytz/zoneinfo/America/North_Dakota/Center | Bin 0 -> 2380 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 0 -> 2380 bytes .../site-packages/pytz/zoneinfo/America/Nuuk | Bin 0 -> 1878 bytes .../pytz/zoneinfo/America/Ojinaga | Bin 0 -> 1484 bytes .../pytz/zoneinfo/America/Panama | Bin 0 -> 182 bytes .../pytz/zoneinfo/America/Pangnirtung | Bin 0 -> 2094 bytes .../pytz/zoneinfo/America/Paramaribo | Bin 0 -> 262 bytes .../pytz/zoneinfo/America/Phoenix | Bin 0 -> 328 bytes .../pytz/zoneinfo/America/Port-au-Prince | Bin 0 -> 1434 bytes .../pytz/zoneinfo/America/Port_of_Spain | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Porto_Acre | Bin 0 -> 628 bytes .../pytz/zoneinfo/America/Porto_Velho | Bin 0 -> 576 bytes .../pytz/zoneinfo/America/Puerto_Rico | Bin 0 -> 246 bytes .../pytz/zoneinfo/America/Punta_Arenas | Bin 0 -> 1902 bytes .../pytz/zoneinfo/America/Rainy_River | Bin 0 -> 2122 bytes .../pytz/zoneinfo/America/Rankin_Inlet | Bin 0 -> 1892 bytes .../pytz/zoneinfo/America/Recife | Bin 0 -> 716 bytes .../pytz/zoneinfo/America/Regina | Bin 0 -> 980 bytes .../pytz/zoneinfo/America/Resolute | Bin 0 -> 1892 bytes .../pytz/zoneinfo/America/Rio_Branco | Bin 0 -> 628 bytes .../pytz/zoneinfo/America/Rosario | Bin 0 -> 1076 bytes .../pytz/zoneinfo/America/Santa_Isabel | Bin 0 -> 2342 bytes .../pytz/zoneinfo/America/Santarem | Bin 0 -> 602 bytes .../pytz/zoneinfo/America/Santiago | Bin 0 -> 2529 bytes .../pytz/zoneinfo/America/Santo_Domingo | Bin 0 -> 458 bytes .../pytz/zoneinfo/America/Sao_Paulo | Bin 0 -> 1444 bytes .../pytz/zoneinfo/America/Scoresbysund | Bin 0 -> 1916 bytes .../pytz/zoneinfo/America/Shiprock | Bin 0 -> 2444 bytes .../site-packages/pytz/zoneinfo/America/Sitka | Bin 0 -> 2329 bytes .../pytz/zoneinfo/America/St_Barthelemy | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/St_Johns | Bin 0 -> 3655 bytes .../pytz/zoneinfo/America/St_Kitts | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/St_Lucia | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/St_Thomas | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/St_Vincent | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Swift_Current | Bin 0 -> 560 bytes .../pytz/zoneinfo/America/Tegucigalpa | Bin 0 -> 252 bytes .../site-packages/pytz/zoneinfo/America/Thule | Bin 0 -> 1502 bytes .../pytz/zoneinfo/America/Thunder_Bay | Bin 0 -> 2202 bytes .../pytz/zoneinfo/America/Tijuana | Bin 0 -> 2342 bytes .../pytz/zoneinfo/America/Toronto | Bin 0 -> 3494 bytes .../pytz/zoneinfo/America/Tortola | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Vancouver | Bin 0 -> 2892 bytes .../pytz/zoneinfo/America/Virgin | Bin 0 -> 148 bytes .../pytz/zoneinfo/America/Whitehorse | Bin 0 -> 1614 bytes .../pytz/zoneinfo/America/Winnipeg | Bin 0 -> 2868 bytes .../pytz/zoneinfo/America/Yakutat | Bin 0 -> 2305 bytes .../pytz/zoneinfo/America/Yellowknife | Bin 0 -> 1966 bytes .../pytz/zoneinfo/Antarctica/Casey | Bin 0 -> 384 bytes .../pytz/zoneinfo/Antarctica/Davis | Bin 0 -> 297 bytes .../pytz/zoneinfo/Antarctica/DumontDUrville | Bin 0 -> 194 bytes .../pytz/zoneinfo/Antarctica/Macquarie | Bin 0 -> 2260 bytes .../pytz/zoneinfo/Antarctica/Mawson | Bin 0 -> 199 bytes .../pytz/zoneinfo/Antarctica/McMurdo | Bin 0 -> 2437 bytes .../pytz/zoneinfo/Antarctica/Palmer | Bin 0 -> 1418 bytes .../pytz/zoneinfo/Antarctica/Rothera | Bin 0 -> 164 bytes .../pytz/zoneinfo/Antarctica/South_Pole | Bin 0 -> 2437 bytes .../pytz/zoneinfo/Antarctica/Syowa | Bin 0 -> 165 bytes .../pytz/zoneinfo/Antarctica/Troll | Bin 0 -> 1162 bytes .../pytz/zoneinfo/Antarctica/Vostok | Bin 0 -> 165 bytes .../pytz/zoneinfo/Arctic/Longyearbyen | Bin 0 -> 2228 bytes .../site-packages/pytz/zoneinfo/Asia/Aden | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Almaty | Bin 0 -> 997 bytes .../site-packages/pytz/zoneinfo/Asia/Amman | Bin 0 -> 1853 bytes .../site-packages/pytz/zoneinfo/Asia/Anadyr | Bin 0 -> 1188 bytes .../site-packages/pytz/zoneinfo/Asia/Aqtau | Bin 0 -> 983 bytes .../site-packages/pytz/zoneinfo/Asia/Aqtobe | Bin 0 -> 1011 bytes .../site-packages/pytz/zoneinfo/Asia/Ashgabat | Bin 0 -> 619 bytes .../pytz/zoneinfo/Asia/Ashkhabad | Bin 0 -> 619 bytes .../site-packages/pytz/zoneinfo/Asia/Atyrau | Bin 0 -> 991 bytes .../site-packages/pytz/zoneinfo/Asia/Baghdad | Bin 0 -> 983 bytes .../site-packages/pytz/zoneinfo/Asia/Bahrain | Bin 0 -> 199 bytes .../site-packages/pytz/zoneinfo/Asia/Baku | Bin 0 -> 1227 bytes .../site-packages/pytz/zoneinfo/Asia/Bangkok | Bin 0 -> 199 bytes .../site-packages/pytz/zoneinfo/Asia/Barnaul | Bin 0 -> 1221 bytes .../site-packages/pytz/zoneinfo/Asia/Beirut | Bin 0 -> 2154 bytes .../site-packages/pytz/zoneinfo/Asia/Bishkek | Bin 0 -> 983 bytes .../site-packages/pytz/zoneinfo/Asia/Brunei | Bin 0 -> 203 bytes .../site-packages/pytz/zoneinfo/Asia/Calcutta | Bin 0 -> 285 bytes .../site-packages/pytz/zoneinfo/Asia/Chita | Bin 0 -> 1221 bytes .../pytz/zoneinfo/Asia/Choibalsan | Bin 0 -> 949 bytes .../pytz/zoneinfo/Asia/Chongqing | Bin 0 -> 561 bytes .../pytz/zoneinfo/Asia/Chungking | Bin 0 -> 561 bytes .../site-packages/pytz/zoneinfo/Asia/Colombo | Bin 0 -> 372 bytes .../site-packages/pytz/zoneinfo/Asia/Dacca | Bin 0 -> 337 bytes .../site-packages/pytz/zoneinfo/Asia/Damascus | Bin 0 -> 2294 bytes .../site-packages/pytz/zoneinfo/Asia/Dhaka | Bin 0 -> 337 bytes .../site-packages/pytz/zoneinfo/Asia/Dili | Bin 0 -> 227 bytes .../site-packages/pytz/zoneinfo/Asia/Dubai | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Dushanbe | Bin 0 -> 591 bytes .../pytz/zoneinfo/Asia/Famagusta | Bin 0 -> 2028 bytes .../site-packages/pytz/zoneinfo/Asia/Gaza | Bin 0 -> 2422 bytes .../site-packages/pytz/zoneinfo/Asia/Harbin | Bin 0 -> 561 bytes .../site-packages/pytz/zoneinfo/Asia/Hebron | Bin 0 -> 2450 bytes .../pytz/zoneinfo/Asia/Ho_Chi_Minh | Bin 0 -> 351 bytes .../pytz/zoneinfo/Asia/Hong_Kong | Bin 0 -> 1203 bytes .../site-packages/pytz/zoneinfo/Asia/Hovd | Bin 0 -> 891 bytes .../site-packages/pytz/zoneinfo/Asia/Irkutsk | Bin 0 -> 1243 bytes .../site-packages/pytz/zoneinfo/Asia/Istanbul | Bin 0 -> 1947 bytes .../site-packages/pytz/zoneinfo/Asia/Jakarta | Bin 0 -> 355 bytes .../site-packages/pytz/zoneinfo/Asia/Jayapura | Bin 0 -> 221 bytes .../pytz/zoneinfo/Asia/Jerusalem | Bin 0 -> 2388 bytes .../site-packages/pytz/zoneinfo/Asia/Kabul | Bin 0 -> 208 bytes .../pytz/zoneinfo/Asia/Kamchatka | Bin 0 -> 1166 bytes .../site-packages/pytz/zoneinfo/Asia/Karachi | Bin 0 -> 379 bytes .../site-packages/pytz/zoneinfo/Asia/Kashgar | Bin 0 -> 165 bytes .../pytz/zoneinfo/Asia/Kathmandu | Bin 0 -> 212 bytes .../site-packages/pytz/zoneinfo/Asia/Katmandu | Bin 0 -> 212 bytes .../site-packages/pytz/zoneinfo/Asia/Khandyga | Bin 0 -> 1271 bytes .../site-packages/pytz/zoneinfo/Asia/Kolkata | Bin 0 -> 285 bytes .../pytz/zoneinfo/Asia/Krasnoyarsk | Bin 0 -> 1207 bytes .../pytz/zoneinfo/Asia/Kuala_Lumpur | Bin 0 -> 383 bytes .../site-packages/pytz/zoneinfo/Asia/Kuching | Bin 0 -> 483 bytes .../site-packages/pytz/zoneinfo/Asia/Kuwait | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Macao | Bin 0 -> 1227 bytes .../site-packages/pytz/zoneinfo/Asia/Macau | Bin 0 -> 1227 bytes .../site-packages/pytz/zoneinfo/Asia/Magadan | Bin 0 -> 1222 bytes .../site-packages/pytz/zoneinfo/Asia/Makassar | Bin 0 -> 254 bytes .../site-packages/pytz/zoneinfo/Asia/Manila | Bin 0 -> 328 bytes .../site-packages/pytz/zoneinfo/Asia/Muscat | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Nicosia | Bin 0 -> 2002 bytes .../pytz/zoneinfo/Asia/Novokuznetsk | Bin 0 -> 1165 bytes .../pytz/zoneinfo/Asia/Novosibirsk | Bin 0 -> 1221 bytes .../site-packages/pytz/zoneinfo/Asia/Omsk | Bin 0 -> 1207 bytes .../site-packages/pytz/zoneinfo/Asia/Oral | Bin 0 -> 1005 bytes .../pytz/zoneinfo/Asia/Phnom_Penh | Bin 0 -> 199 bytes .../pytz/zoneinfo/Asia/Pontianak | Bin 0 -> 353 bytes .../pytz/zoneinfo/Asia/Pyongyang | Bin 0 -> 237 bytes .../site-packages/pytz/zoneinfo/Asia/Qatar | Bin 0 -> 199 bytes .../site-packages/pytz/zoneinfo/Asia/Qostanay | Bin 0 -> 1011 bytes .../pytz/zoneinfo/Asia/Qyzylorda | Bin 0 -> 1025 bytes .../site-packages/pytz/zoneinfo/Asia/Rangoon | Bin 0 -> 268 bytes .../site-packages/pytz/zoneinfo/Asia/Riyadh | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Saigon | Bin 0 -> 351 bytes .../site-packages/pytz/zoneinfo/Asia/Sakhalin | Bin 0 -> 1202 bytes .../pytz/zoneinfo/Asia/Samarkand | Bin 0 -> 577 bytes .../site-packages/pytz/zoneinfo/Asia/Seoul | Bin 0 -> 617 bytes .../site-packages/pytz/zoneinfo/Asia/Shanghai | Bin 0 -> 561 bytes .../pytz/zoneinfo/Asia/Singapore | Bin 0 -> 383 bytes .../pytz/zoneinfo/Asia/Srednekolymsk | Bin 0 -> 1208 bytes .../site-packages/pytz/zoneinfo/Asia/Taipei | Bin 0 -> 761 bytes .../site-packages/pytz/zoneinfo/Asia/Tashkent | Bin 0 -> 591 bytes .../site-packages/pytz/zoneinfo/Asia/Tbilisi | Bin 0 -> 1035 bytes .../site-packages/pytz/zoneinfo/Asia/Tehran | Bin 0 -> 2582 bytes .../site-packages/pytz/zoneinfo/Asia/Tel_Aviv | Bin 0 -> 2388 bytes .../site-packages/pytz/zoneinfo/Asia/Thimbu | Bin 0 -> 203 bytes .../site-packages/pytz/zoneinfo/Asia/Thimphu | Bin 0 -> 203 bytes .../site-packages/pytz/zoneinfo/Asia/Tokyo | Bin 0 -> 309 bytes .../site-packages/pytz/zoneinfo/Asia/Tomsk | Bin 0 -> 1221 bytes .../pytz/zoneinfo/Asia/Ujung_Pandang | Bin 0 -> 254 bytes .../pytz/zoneinfo/Asia/Ulaanbaatar | Bin 0 -> 891 bytes .../pytz/zoneinfo/Asia/Ulan_Bator | Bin 0 -> 891 bytes .../site-packages/pytz/zoneinfo/Asia/Urumqi | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Asia/Ust-Nera | Bin 0 -> 1252 bytes .../pytz/zoneinfo/Asia/Vientiane | Bin 0 -> 199 bytes .../pytz/zoneinfo/Asia/Vladivostok | Bin 0 -> 1208 bytes .../site-packages/pytz/zoneinfo/Asia/Yakutsk | Bin 0 -> 1207 bytes .../site-packages/pytz/zoneinfo/Asia/Yangon | Bin 0 -> 268 bytes .../pytz/zoneinfo/Asia/Yekaterinburg | Bin 0 -> 1243 bytes .../site-packages/pytz/zoneinfo/Asia/Yerevan | Bin 0 -> 1151 bytes .../pytz/zoneinfo/Atlantic/Azores | Bin 0 -> 3484 bytes .../pytz/zoneinfo/Atlantic/Bermuda | Bin 0 -> 2396 bytes .../pytz/zoneinfo/Atlantic/Canary | Bin 0 -> 1897 bytes .../pytz/zoneinfo/Atlantic/Cape_Verde | Bin 0 -> 270 bytes .../pytz/zoneinfo/Atlantic/Faeroe | Bin 0 -> 1815 bytes .../pytz/zoneinfo/Atlantic/Faroe | Bin 0 -> 1815 bytes .../pytz/zoneinfo/Atlantic/Jan_Mayen | Bin 0 -> 2228 bytes .../pytz/zoneinfo/Atlantic/Madeira | Bin 0 -> 3475 bytes .../pytz/zoneinfo/Atlantic/Reykjavik | Bin 0 -> 1162 bytes .../pytz/zoneinfo/Atlantic/South_Georgia | Bin 0 -> 164 bytes .../pytz/zoneinfo/Atlantic/St_Helena | Bin 0 -> 148 bytes .../pytz/zoneinfo/Atlantic/Stanley | Bin 0 -> 1214 bytes .../site-packages/pytz/zoneinfo/Australia/ACT | Bin 0 -> 2190 bytes .../pytz/zoneinfo/Australia/Adelaide | Bin 0 -> 2208 bytes .../pytz/zoneinfo/Australia/Brisbane | Bin 0 -> 419 bytes .../pytz/zoneinfo/Australia/Broken_Hill | Bin 0 -> 2229 bytes .../pytz/zoneinfo/Australia/Canberra | Bin 0 -> 2190 bytes .../pytz/zoneinfo/Australia/Currie | Bin 0 -> 2358 bytes .../pytz/zoneinfo/Australia/Darwin | Bin 0 -> 325 bytes .../pytz/zoneinfo/Australia/Eucla | Bin 0 -> 470 bytes .../pytz/zoneinfo/Australia/Hobart | Bin 0 -> 2358 bytes .../site-packages/pytz/zoneinfo/Australia/LHI | Bin 0 -> 1860 bytes .../pytz/zoneinfo/Australia/Lindeman | Bin 0 -> 475 bytes .../pytz/zoneinfo/Australia/Lord_Howe | Bin 0 -> 1860 bytes .../pytz/zoneinfo/Australia/Melbourne | Bin 0 -> 2190 bytes .../site-packages/pytz/zoneinfo/Australia/NSW | Bin 0 -> 2190 bytes .../pytz/zoneinfo/Australia/North | Bin 0 -> 325 bytes .../pytz/zoneinfo/Australia/Perth | Bin 0 -> 446 bytes .../pytz/zoneinfo/Australia/Queensland | Bin 0 -> 419 bytes .../pytz/zoneinfo/Australia/South | Bin 0 -> 2208 bytes .../pytz/zoneinfo/Australia/Sydney | Bin 0 -> 2190 bytes .../pytz/zoneinfo/Australia/Tasmania | Bin 0 -> 2358 bytes .../pytz/zoneinfo/Australia/Victoria | Bin 0 -> 2190 bytes .../pytz/zoneinfo/Australia/West | Bin 0 -> 446 bytes .../pytz/zoneinfo/Australia/Yancowinna | Bin 0 -> 2229 bytes .../site-packages/pytz/zoneinfo/Brazil/Acre | Bin 0 -> 628 bytes .../pytz/zoneinfo/Brazil/DeNoronha | Bin 0 -> 716 bytes .../site-packages/pytz/zoneinfo/Brazil/East | Bin 0 -> 1444 bytes .../site-packages/pytz/zoneinfo/Brazil/West | Bin 0 -> 604 bytes .../python3.8/site-packages/pytz/zoneinfo/CET | Bin 0 -> 2094 bytes .../site-packages/pytz/zoneinfo/CST6CDT | Bin 0 -> 2310 bytes .../pytz/zoneinfo/Canada/Atlantic | Bin 0 -> 3424 bytes .../pytz/zoneinfo/Canada/Central | Bin 0 -> 2868 bytes .../pytz/zoneinfo/Canada/Eastern | Bin 0 -> 3494 bytes .../pytz/zoneinfo/Canada/Mountain | Bin 0 -> 2332 bytes .../pytz/zoneinfo/Canada/Newfoundland | Bin 0 -> 3655 bytes .../pytz/zoneinfo/Canada/Pacific | Bin 0 -> 2892 bytes .../pytz/zoneinfo/Canada/Saskatchewan | Bin 0 -> 980 bytes .../site-packages/pytz/zoneinfo/Canada/Yukon | Bin 0 -> 1614 bytes .../pytz/zoneinfo/Chile/Continental | Bin 0 -> 2529 bytes .../pytz/zoneinfo/Chile/EasterIsland | Bin 0 -> 2233 bytes .../site-packages/pytz/zoneinfo/Cuba | Bin 0 -> 2416 bytes .../python3.8/site-packages/pytz/zoneinfo/EET | Bin 0 -> 1908 bytes .../python3.8/site-packages/pytz/zoneinfo/EST | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/EST5EDT | Bin 0 -> 2310 bytes .../site-packages/pytz/zoneinfo/Egypt | Bin 0 -> 1955 bytes .../site-packages/pytz/zoneinfo/Eire | Bin 0 -> 3492 bytes .../site-packages/pytz/zoneinfo/Etc/GMT | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+1 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+10 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+11 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+12 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+2 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+3 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+4 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+5 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+6 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+7 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+8 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+9 | Bin 0 -> 116 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-1 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-10 | Bin 0 -> 118 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-11 | Bin 0 -> 118 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-12 | Bin 0 -> 118 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-13 | Bin 0 -> 118 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-14 | Bin 0 -> 118 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-2 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-3 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-4 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-5 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-6 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-7 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-8 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-9 | Bin 0 -> 117 bytes .../site-packages/pytz/zoneinfo/Etc/GMT0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/Greenwich | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/UCT | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/UTC | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/Universal | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Etc/Zulu | Bin 0 -> 114 bytes .../pytz/zoneinfo/Europe/Amsterdam | Bin 0 -> 2910 bytes .../pytz/zoneinfo/Europe/Andorra | Bin 0 -> 1742 bytes .../pytz/zoneinfo/Europe/Astrakhan | Bin 0 -> 1165 bytes .../site-packages/pytz/zoneinfo/Europe/Athens | Bin 0 -> 2262 bytes .../pytz/zoneinfo/Europe/Belfast | Bin 0 -> 3648 bytes .../pytz/zoneinfo/Europe/Belgrade | Bin 0 -> 1920 bytes .../site-packages/pytz/zoneinfo/Europe/Berlin | Bin 0 -> 2298 bytes .../pytz/zoneinfo/Europe/Bratislava | Bin 0 -> 2301 bytes .../pytz/zoneinfo/Europe/Brussels | Bin 0 -> 2933 bytes .../pytz/zoneinfo/Europe/Bucharest | Bin 0 -> 2184 bytes .../pytz/zoneinfo/Europe/Budapest | Bin 0 -> 2368 bytes .../pytz/zoneinfo/Europe/Busingen | Bin 0 -> 1909 bytes .../pytz/zoneinfo/Europe/Chisinau | Bin 0 -> 2390 bytes .../pytz/zoneinfo/Europe/Copenhagen | Bin 0 -> 2137 bytes .../site-packages/pytz/zoneinfo/Europe/Dublin | Bin 0 -> 3492 bytes .../pytz/zoneinfo/Europe/Gibraltar | Bin 0 -> 3052 bytes .../pytz/zoneinfo/Europe/Guernsey | Bin 0 -> 3648 bytes .../pytz/zoneinfo/Europe/Helsinki | Bin 0 -> 1900 bytes .../pytz/zoneinfo/Europe/Isle_of_Man | Bin 0 -> 3648 bytes .../pytz/zoneinfo/Europe/Istanbul | Bin 0 -> 1947 bytes .../site-packages/pytz/zoneinfo/Europe/Jersey | Bin 0 -> 3648 bytes .../pytz/zoneinfo/Europe/Kaliningrad | Bin 0 -> 1493 bytes .../site-packages/pytz/zoneinfo/Europe/Kiev | Bin 0 -> 2088 bytes .../site-packages/pytz/zoneinfo/Europe/Kirov | Bin 0 -> 1153 bytes .../site-packages/pytz/zoneinfo/Europe/Lisbon | Bin 0 -> 3469 bytes .../pytz/zoneinfo/Europe/Ljubljana | Bin 0 -> 1920 bytes .../site-packages/pytz/zoneinfo/Europe/London | Bin 0 -> 3648 bytes .../pytz/zoneinfo/Europe/Luxembourg | Bin 0 -> 2946 bytes .../site-packages/pytz/zoneinfo/Europe/Madrid | Bin 0 -> 2614 bytes .../site-packages/pytz/zoneinfo/Europe/Malta | Bin 0 -> 2620 bytes .../pytz/zoneinfo/Europe/Mariehamn | Bin 0 -> 1900 bytes .../site-packages/pytz/zoneinfo/Europe/Minsk | Bin 0 -> 1321 bytes .../site-packages/pytz/zoneinfo/Europe/Monaco | Bin 0 -> 2944 bytes .../site-packages/pytz/zoneinfo/Europe/Moscow | Bin 0 -> 1535 bytes .../pytz/zoneinfo/Europe/Nicosia | Bin 0 -> 2002 bytes .../site-packages/pytz/zoneinfo/Europe/Oslo | Bin 0 -> 2228 bytes .../site-packages/pytz/zoneinfo/Europe/Paris | Bin 0 -> 2962 bytes .../pytz/zoneinfo/Europe/Podgorica | Bin 0 -> 1920 bytes .../site-packages/pytz/zoneinfo/Europe/Prague | Bin 0 -> 2301 bytes .../site-packages/pytz/zoneinfo/Europe/Riga | Bin 0 -> 2198 bytes .../site-packages/pytz/zoneinfo/Europe/Rome | Bin 0 -> 2641 bytes .../site-packages/pytz/zoneinfo/Europe/Samara | Bin 0 -> 1215 bytes .../pytz/zoneinfo/Europe/San_Marino | Bin 0 -> 2641 bytes .../pytz/zoneinfo/Europe/Sarajevo | Bin 0 -> 1920 bytes .../pytz/zoneinfo/Europe/Saratov | Bin 0 -> 1183 bytes .../pytz/zoneinfo/Europe/Simferopol | Bin 0 -> 1453 bytes .../site-packages/pytz/zoneinfo/Europe/Skopje | Bin 0 -> 1920 bytes .../site-packages/pytz/zoneinfo/Europe/Sofia | Bin 0 -> 2077 bytes .../pytz/zoneinfo/Europe/Stockholm | Bin 0 -> 1909 bytes .../pytz/zoneinfo/Europe/Tallinn | Bin 0 -> 2148 bytes .../site-packages/pytz/zoneinfo/Europe/Tirane | Bin 0 -> 2084 bytes .../pytz/zoneinfo/Europe/Tiraspol | Bin 0 -> 2390 bytes .../pytz/zoneinfo/Europe/Ulyanovsk | Bin 0 -> 1267 bytes .../pytz/zoneinfo/Europe/Uzhgorod | Bin 0 -> 2050 bytes .../site-packages/pytz/zoneinfo/Europe/Vaduz | Bin 0 -> 1909 bytes .../pytz/zoneinfo/Europe/Vatican | Bin 0 -> 2641 bytes .../site-packages/pytz/zoneinfo/Europe/Vienna | Bin 0 -> 2200 bytes .../pytz/zoneinfo/Europe/Vilnius | Bin 0 -> 2162 bytes .../pytz/zoneinfo/Europe/Volgograd | Bin 0 -> 1165 bytes .../site-packages/pytz/zoneinfo/Europe/Warsaw | Bin 0 -> 2654 bytes .../site-packages/pytz/zoneinfo/Europe/Zagreb | Bin 0 -> 1920 bytes .../pytz/zoneinfo/Europe/Zaporozhye | Bin 0 -> 2106 bytes .../site-packages/pytz/zoneinfo/Europe/Zurich | Bin 0 -> 1909 bytes .../site-packages/pytz/zoneinfo/Factory | Bin 0 -> 116 bytes .../python3.8/site-packages/pytz/zoneinfo/GB | Bin 0 -> 3648 bytes .../site-packages/pytz/zoneinfo/GB-Eire | Bin 0 -> 3648 bytes .../python3.8/site-packages/pytz/zoneinfo/GMT | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/GMT+0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/GMT-0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/GMT0 | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Greenwich | Bin 0 -> 114 bytes .../python3.8/site-packages/pytz/zoneinfo/HST | Bin 0 -> 115 bytes .../site-packages/pytz/zoneinfo/Hongkong | Bin 0 -> 1203 bytes .../site-packages/pytz/zoneinfo/Iceland | Bin 0 -> 1162 bytes .../pytz/zoneinfo/Indian/Antananarivo | Bin 0 -> 265 bytes .../site-packages/pytz/zoneinfo/Indian/Chagos | Bin 0 -> 199 bytes .../pytz/zoneinfo/Indian/Christmas | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Indian/Cocos | Bin 0 -> 174 bytes .../site-packages/pytz/zoneinfo/Indian/Comoro | Bin 0 -> 265 bytes .../pytz/zoneinfo/Indian/Kerguelen | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Indian/Mahe | Bin 0 -> 165 bytes .../pytz/zoneinfo/Indian/Maldives | Bin 0 -> 199 bytes .../pytz/zoneinfo/Indian/Mauritius | Bin 0 -> 241 bytes .../pytz/zoneinfo/Indian/Mayotte | Bin 0 -> 265 bytes .../pytz/zoneinfo/Indian/Reunion | Bin 0 -> 165 bytes .../site-packages/pytz/zoneinfo/Iran | Bin 0 -> 2582 bytes .../site-packages/pytz/zoneinfo/Israel | Bin 0 -> 2388 bytes .../site-packages/pytz/zoneinfo/Jamaica | Bin 0 -> 482 bytes .../site-packages/pytz/zoneinfo/Japan | Bin 0 -> 309 bytes .../site-packages/pytz/zoneinfo/Kwajalein | Bin 0 -> 316 bytes .../site-packages/pytz/zoneinfo/Libya | Bin 0 -> 625 bytes .../python3.8/site-packages/pytz/zoneinfo/MET | Bin 0 -> 2094 bytes .../python3.8/site-packages/pytz/zoneinfo/MST | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/MST7MDT | Bin 0 -> 2310 bytes .../pytz/zoneinfo/Mexico/BajaNorte | Bin 0 -> 2342 bytes .../pytz/zoneinfo/Mexico/BajaSur | Bin 0 -> 1526 bytes .../pytz/zoneinfo/Mexico/General | Bin 0 -> 1584 bytes .../python3.8/site-packages/pytz/zoneinfo/NZ | Bin 0 -> 2437 bytes .../site-packages/pytz/zoneinfo/NZ-CHAT | Bin 0 -> 2068 bytes .../site-packages/pytz/zoneinfo/Navajo | Bin 0 -> 2444 bytes .../python3.8/site-packages/pytz/zoneinfo/PRC | Bin 0 -> 561 bytes .../site-packages/pytz/zoneinfo/PST8PDT | Bin 0 -> 2310 bytes .../site-packages/pytz/zoneinfo/Pacific/Apia | Bin 0 -> 1097 bytes .../pytz/zoneinfo/Pacific/Auckland | Bin 0 -> 2437 bytes .../pytz/zoneinfo/Pacific/Bougainville | Bin 0 -> 268 bytes .../pytz/zoneinfo/Pacific/Chatham | Bin 0 -> 2068 bytes .../site-packages/pytz/zoneinfo/Pacific/Chuuk | Bin 0 -> 269 bytes .../pytz/zoneinfo/Pacific/Easter | Bin 0 -> 2233 bytes .../site-packages/pytz/zoneinfo/Pacific/Efate | Bin 0 -> 538 bytes .../pytz/zoneinfo/Pacific/Enderbury | Bin 0 -> 234 bytes .../pytz/zoneinfo/Pacific/Fakaofo | Bin 0 -> 200 bytes .../site-packages/pytz/zoneinfo/Pacific/Fiji | Bin 0 -> 1077 bytes .../pytz/zoneinfo/Pacific/Funafuti | Bin 0 -> 166 bytes .../pytz/zoneinfo/Pacific/Galapagos | Bin 0 -> 238 bytes .../pytz/zoneinfo/Pacific/Gambier | Bin 0 -> 164 bytes .../pytz/zoneinfo/Pacific/Guadalcanal | Bin 0 -> 166 bytes .../site-packages/pytz/zoneinfo/Pacific/Guam | Bin 0 -> 494 bytes .../pytz/zoneinfo/Pacific/Honolulu | Bin 0 -> 329 bytes .../pytz/zoneinfo/Pacific/Johnston | Bin 0 -> 329 bytes .../pytz/zoneinfo/Pacific/Kiritimati | Bin 0 -> 238 bytes .../pytz/zoneinfo/Pacific/Kosrae | Bin 0 -> 351 bytes .../pytz/zoneinfo/Pacific/Kwajalein | Bin 0 -> 316 bytes .../pytz/zoneinfo/Pacific/Majuro | Bin 0 -> 310 bytes .../pytz/zoneinfo/Pacific/Marquesas | Bin 0 -> 173 bytes .../pytz/zoneinfo/Pacific/Midway | Bin 0 -> 175 bytes .../site-packages/pytz/zoneinfo/Pacific/Nauru | Bin 0 -> 252 bytes .../site-packages/pytz/zoneinfo/Pacific/Niue | Bin 0 -> 241 bytes .../pytz/zoneinfo/Pacific/Norfolk | Bin 0 -> 880 bytes .../pytz/zoneinfo/Pacific/Noumea | Bin 0 -> 304 bytes .../pytz/zoneinfo/Pacific/Pago_Pago | Bin 0 -> 175 bytes .../site-packages/pytz/zoneinfo/Pacific/Palau | Bin 0 -> 180 bytes .../pytz/zoneinfo/Pacific/Pitcairn | Bin 0 -> 202 bytes .../pytz/zoneinfo/Pacific/Pohnpei | Bin 0 -> 303 bytes .../pytz/zoneinfo/Pacific/Ponape | Bin 0 -> 303 bytes .../pytz/zoneinfo/Pacific/Port_Moresby | Bin 0 -> 186 bytes .../pytz/zoneinfo/Pacific/Rarotonga | Bin 0 -> 577 bytes .../pytz/zoneinfo/Pacific/Saipan | Bin 0 -> 494 bytes .../site-packages/pytz/zoneinfo/Pacific/Samoa | Bin 0 -> 175 bytes .../pytz/zoneinfo/Pacific/Tahiti | Bin 0 -> 165 bytes .../pytz/zoneinfo/Pacific/Tarawa | Bin 0 -> 166 bytes .../pytz/zoneinfo/Pacific/Tongatapu | Bin 0 -> 372 bytes .../site-packages/pytz/zoneinfo/Pacific/Truk | Bin 0 -> 269 bytes .../site-packages/pytz/zoneinfo/Pacific/Wake | Bin 0 -> 166 bytes .../pytz/zoneinfo/Pacific/Wallis | Bin 0 -> 166 bytes .../site-packages/pytz/zoneinfo/Pacific/Yap | Bin 0 -> 269 bytes .../site-packages/pytz/zoneinfo/Poland | Bin 0 -> 2654 bytes .../site-packages/pytz/zoneinfo/Portugal | Bin 0 -> 3469 bytes .../python3.8/site-packages/pytz/zoneinfo/ROC | Bin 0 -> 761 bytes .../python3.8/site-packages/pytz/zoneinfo/ROK | Bin 0 -> 617 bytes .../site-packages/pytz/zoneinfo/Singapore | Bin 0 -> 383 bytes .../site-packages/pytz/zoneinfo/Turkey | Bin 0 -> 1947 bytes .../python3.8/site-packages/pytz/zoneinfo/UCT | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/US/Alaska | Bin 0 -> 2371 bytes .../site-packages/pytz/zoneinfo/US/Aleutian | Bin 0 -> 2356 bytes .../site-packages/pytz/zoneinfo/US/Arizona | Bin 0 -> 328 bytes .../site-packages/pytz/zoneinfo/US/Central | Bin 0 -> 3576 bytes .../pytz/zoneinfo/US/East-Indiana | Bin 0 -> 1666 bytes .../site-packages/pytz/zoneinfo/US/Eastern | Bin 0 -> 3536 bytes .../site-packages/pytz/zoneinfo/US/Hawaii | Bin 0 -> 329 bytes .../pytz/zoneinfo/US/Indiana-Starke | Bin 0 -> 2428 bytes .../site-packages/pytz/zoneinfo/US/Michigan | Bin 0 -> 2230 bytes .../site-packages/pytz/zoneinfo/US/Mountain | Bin 0 -> 2444 bytes .../site-packages/pytz/zoneinfo/US/Pacific | Bin 0 -> 2836 bytes .../site-packages/pytz/zoneinfo/US/Samoa | Bin 0 -> 175 bytes .../python3.8/site-packages/pytz/zoneinfo/UTC | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/Universal | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/W-SU | Bin 0 -> 1535 bytes .../python3.8/site-packages/pytz/zoneinfo/WET | Bin 0 -> 1905 bytes .../site-packages/pytz/zoneinfo/Zulu | Bin 0 -> 114 bytes .../site-packages/pytz/zoneinfo/iso3166.tab | 274 + .../site-packages/pytz/zoneinfo/leapseconds | 82 + .../site-packages/pytz/zoneinfo/tzdata.zi | 4459 +++++++++ .../site-packages/pytz/zoneinfo/zone.tab | 451 + .../site-packages/pytz/zoneinfo/zone1970.tab | 383 + .../requests-2.22.0.dist-info/AUTHORS.txt | 562 ++ .../requests-2.22.0.dist-info/INSTALLER | 1 + .../requests-2.22.0.dist-info/LICENSE.txt | 20 + .../requests-2.22.0.dist-info/METADATA | 141 + .../requests-2.22.0.dist-info/RECORD | 46 + .../requests-2.22.0.dist-info/WHEEL | 6 + .../requests-2.22.0.dist-info/top_level.txt | 1 + .../site-packages/requests-2.22.0.virtualenv | 0 .../requests-2.24.0.dist-info/DESCRIPTION.rst | 136 + .../requests-2.24.0.dist-info/INSTALLER | 1 + .../requests-2.24.0.dist-info/LICENSE.txt | 13 + .../requests-2.24.0.dist-info/METADATA | 177 + .../requests-2.24.0.dist-info/RECORD | 44 + .../requests-2.24.0.dist-info/WHEEL | 6 + .../requests-2.24.0.dist-info/metadata.json | 1 + .../requests-2.24.0.dist-info/top_level.txt | 1 + .../site-packages/requests/__init__.py | 131 + .../site-packages/requests/__version__.py | 14 + .../site-packages/requests/_internal_utils.py | 42 + .../site-packages/requests/adapters.py | 533 ++ .../python3.8/site-packages/requests/api.py | 158 + .../python3.8/site-packages/requests/auth.py | 305 + .../python3.8/site-packages/requests/certs.py | 18 + .../site-packages/requests/compat.py | 70 + .../site-packages/requests/cookies.py | 549 ++ .../site-packages/requests/exceptions.py | 126 + .../python3.8/site-packages/requests/help.py | 119 + .../python3.8/site-packages/requests/hooks.py | 34 + .../site-packages/requests/models.py | 953 ++ .../site-packages/requests/packages.py | 14 + .../site-packages/requests/sessions.py | 770 ++ .../site-packages/requests/status_codes.py | 120 + .../site-packages/requests/structures.py | 103 + .../python3.8/site-packages/requests/utils.py | 977 ++ .../AUTHORS.rst | 53 + .../INSTALLER | 1 + .../requests_toolbelt-0.9.1.dist-info/LICENSE | 13 + .../METADATA | 482 + .../requests_toolbelt-0.9.1.dist-info/RECORD | 75 + .../requests_toolbelt-0.9.1.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../requests_toolbelt/__init__.py | 34 + .../requests_toolbelt/_compat.py | 324 + .../requests_toolbelt/adapters/__init__.py | 15 + .../requests_toolbelt/adapters/appengine.py | 206 + .../requests_toolbelt/adapters/fingerprint.py | 48 + .../adapters/host_header_ssl.py | 43 + .../adapters/socket_options.py | 129 + .../requests_toolbelt/adapters/source.py | 67 + .../requests_toolbelt/adapters/ssl.py | 66 + .../requests_toolbelt/adapters/x509.py | 178 + .../requests_toolbelt/auth/__init__.py | 0 .../auth/_digest_auth_compat.py | 29 + .../requests_toolbelt/auth/guess.py | 146 + .../requests_toolbelt/auth/handler.py | 142 + .../auth/http_proxy_digest.py | 103 + .../requests_toolbelt/cookies/__init__.py | 0 .../requests_toolbelt/cookies/forgetful.py | 7 + .../downloadutils/__init__.py | 0 .../requests_toolbelt/downloadutils/stream.py | 177 + .../requests_toolbelt/downloadutils/tee.py | 123 + .../requests_toolbelt/exceptions.py | 37 + .../requests_toolbelt/multipart/__init__.py | 31 + .../requests_toolbelt/multipart/decoder.py | 156 + .../requests_toolbelt/multipart/encoder.py | 655 ++ .../requests_toolbelt/sessions.py | 70 + .../requests_toolbelt/streaming_iterator.py | 116 + .../requests_toolbelt/threaded/__init__.py | 97 + .../requests_toolbelt/threaded/pool.py | 211 + .../requests_toolbelt/threaded/thread.py | 53 + .../requests_toolbelt/utils/__init__.py | 0 .../requests_toolbelt/utils/deprecated.py | 91 + .../requests_toolbelt/utils/dump.py | 197 + .../requests_toolbelt/utils/formdata.py | 108 + .../requests_toolbelt/utils/user_agent.py | 143 + .../retrying-1.3.3.dist-info/AUTHORS.txt | 562 ++ .../retrying-1.3.3.dist-info/INSTALLER | 1 + .../retrying-1.3.3.dist-info/LICENSE.txt | 20 + .../retrying-1.3.3.dist-info/METADATA | 236 + .../retrying-1.3.3.dist-info/RECORD | 11 + .../retrying-1.3.3.dist-info/WHEEL | 6 + .../retrying-1.3.3.dist-info/top_level.txt | 1 + .../site-packages/retrying-1.3.3.virtualenv | 0 .../lib/python3.8/site-packages/retrying.py | 267 + .../setuptools-44.0.0.dist-info/AUTHORS.txt | 562 ++ .../setuptools-44.0.0.dist-info/INSTALLER | 1 + .../setuptools-44.0.0.dist-info/LICENSE.txt | 20 + .../setuptools-44.0.0.dist-info/METADATA | 82 + .../setuptools-44.0.0.dist-info/RECORD | 171 + .../setuptools-44.0.0.dist-info/WHEEL | 6 + .../dependency_links.txt | 2 + .../entry_points.txt | 68 + .../setuptools-44.0.0.dist-info/top_level.txt | 3 + .../setuptools-44.0.0.dist-info/zip-safe | 1 + .../setuptools-44.0.0.virtualenv | 0 .../site-packages/setuptools/__init__.py | 228 + .../setuptools/_deprecation_warning.py | 7 + .../site-packages/setuptools/_imp.py | 73 + .../setuptools/_vendor/__init__.py | 0 .../setuptools/_vendor/ordered_set.py | 488 + .../setuptools/_vendor/packaging/__about__.py | 27 + .../setuptools/_vendor/packaging/__init__.py | 26 + .../setuptools/_vendor/packaging/_compat.py | 31 + .../_vendor/packaging/_structures.py | 68 + .../setuptools/_vendor/packaging/markers.py | 296 + .../_vendor/packaging/requirements.py | 138 + .../_vendor/packaging/specifiers.py | 749 ++ .../setuptools/_vendor/packaging/tags.py | 404 + .../setuptools/_vendor/packaging/utils.py | 57 + .../setuptools/_vendor/packaging/version.py | 420 + .../setuptools/_vendor/pyparsing.py | 5742 ++++++++++++ .../site-packages/setuptools/_vendor/six.py | 868 ++ .../site-packages/setuptools/archive_util.py | 173 + .../site-packages/setuptools/build_meta.py | 257 + .../site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 17 + .../site-packages/setuptools/command/alias.py | 80 + .../setuptools/command/bdist_egg.py | 502 + .../setuptools/command/bdist_rpm.py | 43 + .../setuptools/command/bdist_wininst.py | 21 + .../setuptools/command/build_clib.py | 98 + .../setuptools/command/build_ext.py | 327 + .../setuptools/command/build_py.py | 270 + .../setuptools/command/develop.py | 221 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2402 +++++ .../setuptools/command/egg_info.py | 717 ++ .../setuptools/command/install.py | 125 + .../setuptools/command/install_egg_info.py | 82 + .../setuptools/command/install_lib.py | 147 + .../setuptools/command/install_scripts.py | 65 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 136 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 66 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 252 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 279 + .../setuptools/command/upload.py | 17 + .../setuptools/command/upload_docs.py | 206 + .../site-packages/setuptools/config.py | 659 ++ .../site-packages/setuptools/dep_util.py | 23 + .../site-packages/setuptools/depends.py | 176 + .../site-packages/setuptools/dist.py | 1274 +++ .../site-packages/setuptools/errors.py | 16 + .../site-packages/setuptools/extension.py | 57 + .../setuptools/extern/__init__.py | 73 + .../site-packages/setuptools/glob.py | 174 + .../site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../site-packages/setuptools/installer.py | 150 + .../site-packages/setuptools/launch.py | 35 + .../site-packages/setuptools/lib2to3_ex.py | 62 + .../site-packages/setuptools/monkey.py | 179 + .../site-packages/setuptools/msvc.py | 1679 ++++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1136 +++ .../site-packages/setuptools/py27compat.py | 60 + .../site-packages/setuptools/py31compat.py | 32 + .../site-packages/setuptools/py33compat.py | 59 + .../site-packages/setuptools/py34compat.py | 13 + .../site-packages/setuptools/sandbox.py | 491 + .../setuptools/script (dev).tmpl | 6 + .../site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/site-patch.py | 74 + .../site-packages/setuptools/ssl_support.py | 260 + .../site-packages/setuptools/unicode_utils.py | 44 + .../site-packages/setuptools/version.py | 6 + .../site-packages/setuptools/wheel.py | 220 + .../setuptools/windows_support.py | 29 + .../six-1.14.0.dist-info/AUTHORS.txt | 562 ++ .../six-1.14.0.dist-info/INSTALLER | 1 + .../six-1.14.0.dist-info/LICENSE.txt | 20 + .../six-1.14.0.dist-info/METADATA | 49 + .../site-packages/six-1.14.0.dist-info/RECORD | 11 + .../site-packages/six-1.14.0.dist-info/WHEEL | 6 + .../six-1.14.0.dist-info/top_level.txt | 1 + .../site-packages/six-1.14.0.virtualenv | 0 .../venv/lib/python3.8/site-packages/six.py | 980 ++ .../tabulate-0.8.7.dist-info/INSTALLER | 1 + .../tabulate-0.8.7.dist-info/LICENSE | 20 + .../tabulate-0.8.7.dist-info/METADATA | 764 ++ .../tabulate-0.8.7.dist-info/RECORD | 10 + .../tabulate-0.8.7.dist-info/WHEEL | 5 + .../tabulate-0.8.7.dist-info/entry_points.txt | 3 + .../tabulate-0.8.7.dist-info/top_level.txt | 1 + .../lib/python3.8/site-packages/tabulate.py | 1772 ++++ .../urllib3-1.25.8.dist-info/AUTHORS.txt | 562 ++ .../urllib3-1.25.8.dist-info/INSTALLER | 1 + .../urllib3-1.25.8.dist-info/LICENSE.txt | 20 + .../urllib3-1.25.8.dist-info/METADATA | 1238 +++ .../urllib3-1.25.8.dist-info/RECORD | 86 + .../urllib3-1.25.8.dist-info/WHEEL | 6 + .../urllib3-1.25.8.dist-info/top_level.txt | 1 + .../site-packages/urllib3-1.25.8.virtualenv | 0 .../site-packages/urllib3/__init__.py | 86 + .../site-packages/urllib3/_collections.py | 336 + .../site-packages/urllib3/connection.py | 428 + .../site-packages/urllib3/connectionpool.py | 1053 +++ .../site-packages/urllib3/contrib/__init__.py | 0 .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../contrib/_securetransport/bindings.py | 493 + .../contrib/_securetransport/low_level.py | 328 + .../urllib3/contrib/appengine.py | 314 + .../site-packages/urllib3/contrib/ntlmpool.py | 121 + .../urllib3/contrib/pyopenssl.py | 498 + .../urllib3/contrib/securetransport.py | 859 ++ .../site-packages/urllib3/contrib/socks.py | 210 + .../site-packages/urllib3/exceptions.py | 255 + .../python3.8/site-packages/urllib3/fields.py | 273 + .../site-packages/urllib3/filepost.py | 98 + .../urllib3/packages/__init__.py | 11 + .../urllib3/packages/backports/__init__.py | 0 .../urllib3/packages/backports/makefile.py | 52 + .../packages/ssl_match_hostname/__init__.py | 19 + .../ssl_match_hostname/_implementation.py | 160 + .../site-packages/urllib3/poolmanager.py | 470 + .../site-packages/urllib3/request.py | 171 + .../site-packages/urllib3/response.py | 809 ++ .../site-packages/urllib3/util/__init__.py | 46 + .../site-packages/urllib3/util/connection.py | 138 + .../site-packages/urllib3/util/queue.py | 21 + .../site-packages/urllib3/util/request.py | 135 + .../site-packages/urllib3/util/response.py | 86 + .../site-packages/urllib3/util/retry.py | 450 + .../site-packages/urllib3/util/ssl_.py | 407 + .../site-packages/urllib3/util/timeout.py | 258 + .../site-packages/urllib3/util/url.py | 430 + .../site-packages/urllib3/util/wait.py | 153 + .../webencodings-0.5.1.dist-info/AUTHORS.txt | 562 ++ .../webencodings-0.5.1.dist-info/INSTALLER | 1 + .../webencodings-0.5.1.dist-info/LICENSE.txt | 20 + .../webencodings-0.5.1.dist-info/METADATA | 54 + .../webencodings-0.5.1.dist-info/RECORD | 20 + .../webencodings-0.5.1.dist-info/WHEEL | 6 + .../top_level.txt | 1 + .../webencodings-0.5.1.virtualenv | 0 .../site-packages/webencodings/__init__.py | 342 + .../site-packages/webencodings/labels.py | 231 + .../site-packages/webencodings/mklabels.py | 59 + .../site-packages/webencodings/tests.py | 153 + .../webencodings/x_user_defined.py | 325 + .../wheel-0.34.2.dist-info/AUTHORS.txt | 562 ++ .../wheel-0.34.2.dist-info/INSTALLER | 1 + .../wheel-0.34.2.dist-info/LICENSE.txt | 20 + .../wheel-0.34.2.dist-info/METADATA | 66 + .../wheel-0.34.2.dist-info/RECORD | 43 + .../wheel-0.34.2.dist-info/WHEEL | 6 + .../wheel-0.34.2.dist-info/entry_points.txt | 6 + .../wheel-0.34.2.dist-info/top_level.txt | 1 + .../site-packages/wheel-0.34.2.virtualenv | 0 .../python3.8/site-packages/wheel/__init__.py | 1 + .../python3.8/site-packages/wheel/__main__.py | 19 + .../python3.8/site-packages/wheel/_version.py | 4 + .../site-packages/wheel/bdist_wheel.py | 403 + .../site-packages/wheel/cli/__init__.py | 88 + .../site-packages/wheel/cli/convert.py | 269 + .../python3.8/site-packages/wheel/cli/pack.py | 79 + .../site-packages/wheel/cli/unpack.py | 25 + .../site-packages/wheel/macosx_libfile.py | 341 + .../python3.8/site-packages/wheel/metadata.py | 138 + .../site-packages/wheel/pep425tags.py | 261 + .../python3.8/site-packages/wheel/pkginfo.py | 43 + .../lib/python3.8/site-packages/wheel/util.py | 46 + .../site-packages/wheel/wheelfile.py | 169 + .../python3.8/site-packages/yaml/__init__.py | 427 + .../python3.8/site-packages/yaml/composer.py | 139 + .../site-packages/yaml/constructor.py | 748 ++ .../lib/python3.8/site-packages/yaml/cyaml.py | 101 + .../python3.8/site-packages/yaml/dumper.py | 62 + .../python3.8/site-packages/yaml/emitter.py | 1137 +++ .../lib/python3.8/site-packages/yaml/error.py | 75 + .../python3.8/site-packages/yaml/events.py | 86 + .../python3.8/site-packages/yaml/loader.py | 63 + .../lib/python3.8/site-packages/yaml/nodes.py | 49 + .../python3.8/site-packages/yaml/parser.py | 589 ++ .../python3.8/site-packages/yaml/reader.py | 185 + .../site-packages/yaml/representer.py | 389 + .../python3.8/site-packages/yaml/resolver.py | 227 + .../python3.8/site-packages/yaml/scanner.py | 1435 +++ .../site-packages/yaml/serializer.py | 111 + .../python3.8/site-packages/yaml/tokens.py | 104 + .../charms/vyos-config/venv/pyvenv.cfg | 8 + .../charms/vyos-config/vyos-config.charm | Bin 0 -> 10126366 bytes .../cloud_init/vyos-userdata | 23 - .../hackfest_firewall_pnfd.yaml | 50 +- .../hackfest_firewall_pnf_nsd.yaml | 15 + .../hackfest_virtual-pc_nsd.yaml | 2 +- .../charms/virtual-pc-src/.jujuignore | 1 + .../charms/virtual-pc-src/src/charm.py | 16 +- .../templates/60-no-public-ip.yaml | 5 + .../charms/virtual-pc/src/charm.py | 16 +- .../virtual-pc/templates/60-no-public-ip.yaml | 5 + 1880 files changed, 298179 insertions(+), 237 deletions(-) create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/README.md create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/actions.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/config.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/metadata.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/playbooks/add-port-forward.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/playbooks/backup.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config-src/playbooks/remove-port-forward.yaml rename hackfest_firewall_pnf/{snmp/snmp.yml => charms/vyos-config-src/requirements.txt} (100%) create mode 100755 hackfest_firewall_pnf/charms/vyos-config-src/src/charm.py create mode 100755 hackfest_firewall_pnf/charms/vyos-config/dispatch mode change 100755 => 120000 hackfest_firewall_pnf/charms/vyos-config/hooks/install create mode 120000 hackfest_firewall_pnf/charms/vyos-config/hooks/start create mode 120000 hackfest_firewall_pnf/charms/vyos-config/hooks/upgrade-charm create mode 100644 hackfest_firewall_pnf/charms/vyos-config/playbooks/add-port-forward.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config/playbooks/remove-port-forward.yaml create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.csh create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.fish create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.ps1 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.xsh create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate_this.py create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect-3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect3 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/charmcraft create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro-3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro3 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install-3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install3 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/jsonschema create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip-3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/tabulate create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel-3.8 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel3 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/LICENSE.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/top_level.txt create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_cffi_backend.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_pyrsistent_version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_virtualenv.pth create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_virtualenv.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_config.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_funcs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_make.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_next_gen.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/py.typed create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/_cmd.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/adapter.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/cache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/file_cache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/redis_cache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/controller.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/filewrapper.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/heuristics.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/serialize.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/wrapper.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__main__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/cacert.pem create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/core.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/top_level.txt create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi.libs/libffi-806b1a9d.so.6.0.4 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_cffi_errors.h create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_cffi_include.h create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_embedding.h create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/api.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/backend_ctypes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cffi_opcode.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/commontypes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cparser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/error.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/ffiplatform.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/lock.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/model.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/parse_c_type.h create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/pkgconfig.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/recompiler.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/setuptools_ext.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_cpy.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_gen.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/verifier.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5freq.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5prober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/chardistribution.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetgroupprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/chardetect.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/codingstatemachine.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cp949prober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/enums.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escsm.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/eucjpprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrfreq.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwfreq.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312freq.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312prober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/hebrewprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jisfreq.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jpcntx.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langbulgarianmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langcyrillicmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langgreekmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhebrewmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhungarianmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langthaimodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langturkishmodel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/latin1prober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcharsetprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcsgroupprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcssm.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcharsetprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcsgroupprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sjisprober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/universaldetector.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/utf8prober.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__main__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/cmdbase.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/build.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/init.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/pack.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/client.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/store.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/config.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/helptexts.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/jujuignore.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/logsetup.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/main.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/charmlibs/new_library.py.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.flake8.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.jujuignore.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/LICENSE.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/README.md.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/actions.yaml.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/config.yaml.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/metadata.yaml.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements-dev.txt.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements.txt.j2 create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/run_tests.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/src/charm.py.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/__init__.py.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/test_charm.py.j2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansi.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansitowin32.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/initialise.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/win32.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/winterm.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_common.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/easter.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/_parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/relativedelta.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/rrule.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_common.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_factories.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/tz.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/win.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tzwin.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/misc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/shutil.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.cfg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/tarfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/database.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/index.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/locators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/manifest.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/markers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/metadata.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/resources.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/scripts.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/util.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/easy_install.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/any_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/api_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/plugin_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_database.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pool.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/duration_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/empty_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/field_mask_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/__init__.py create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/_api_implementation.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/api_implementation.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/containers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/decoder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/encoder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/enum_type_wrapper.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/extension_dict.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/message_listener.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/python_message.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/type_checkers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/well_known_types.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/wire_format.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/json_format.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message_factory.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/proto_builder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/__init__.py create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/_message.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/cpp_message.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/reflection.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/service.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/service_reflection.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/source_context_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/struct_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/symbol_database.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/text_encoding.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/text_format.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/timestamp_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/type_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_proto3_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/wrappers_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_ihatexml.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_inputstream.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_tokenizer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_trie/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_trie/_base.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_trie/datrie.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_trie/py.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/constants.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/alphabeticalattributes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/base.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/inject_meta_charset.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/lint.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/optionaltags.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/sanitizer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/filters/whitespace.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/html5parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/serializer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treeadapters/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treeadapters/genshi.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treeadapters/sax.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treebuilders/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treebuilders/base.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treebuilders/dom.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treebuilders/etree.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treebuilders/etree_lxml.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/base.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/dom.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/etree.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/etree_lxml.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib/treewalkers/genshi.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna-2.8.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/codec.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/core.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/idnadata.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/intranges.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/package_data.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/idna/uts46data.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr-2.2.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/ipaddr.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/_identifier.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/asyncfilters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/asyncsupport.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/bccache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/compiler.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/constants.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/debug.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/defaults.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/environment.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/ext.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/filters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/idtracking.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/lexer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/loaders.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/meta.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/nativetypes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/nodes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/optimizer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/runtime.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/sandbox.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/tests.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jinja2/visitor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/COPYING create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema-3.2.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/__main__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_format.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_legacy_validators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_reflect.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_types.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/_validators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/benchmarks/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/benchmarks/issue232.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/benchmarks/json_schema_test_suite.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/cli.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/schemas/draft3.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/schemas/draft4.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/schemas/draft6.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/schemas/draft7.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/_helpers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/_suite.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_cli.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_format.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_jsonschema_test_suite.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_types.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/tests/test_validators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/jsonschema/validators.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/pbr.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile-0.12.2.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/linklockfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/mkdirlockfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/pidlockfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/sqlitelockfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/lockfile/symlinklockfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/AUTHORS.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery-1.3.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/_utils/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_authorizer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_bakery.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_checker.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_codec.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_discharge.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_error.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_identity.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_internal/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_internal/id_pb2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_keys.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_macaroon.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_oven.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_store.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_third_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/bakery/_versions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_auth_context.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_caveat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_checkers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_conditions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_declared.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_namespace.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_operation.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_time.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/checkers/_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_browser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_client.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_discharge.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_error.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_interactor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/_keyring.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/agent/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/httpbakery/agent/_agent.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/common.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_agent.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_authorizer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_bakery.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_checker.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_checkers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_client.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_codec.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_discharge.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_discharge_all.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_httpbakery.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_keyring.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_macaroon.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_namespace.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_oven.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_store.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_time.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/macaroonbakery/tests/test_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/_constants.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/_native.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/_speedups.c create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack-0.6.2.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack/_cmsgpack.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack/_version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/msgpack/fallback.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/__init__.py create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/_sodium.abi3.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_aead.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_box.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_core.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_generichash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_hash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_kx.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_pwhash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_scalarmult.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_secretbox.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_secretstream.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_shorthash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/crypto_sign.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/randombytes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/sodium_core.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/bindings/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/encoding.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/hash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/hashlib.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/public.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/pwhash/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/pwhash/_argon2.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/pwhash/argon2i.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/pwhash/argon2id.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/pwhash/scrypt.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/secret.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/signing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/nacl/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging-20.3.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/__about__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/_structures.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/_typing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/markers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/py.typed create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/requirements.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/specifiers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/tags.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/packaging/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517-0.8.2.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/_in_process.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/build.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/check.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/colorlog.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/dirtools.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/envbuild.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/meta.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pep517/wrappers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip-20.0.2.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/__main__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/build_env.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/base_command.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/command_context.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/main.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/main_parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/req_command.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/cli/status_codes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/check.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/completion.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/configuration.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/debug.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/download.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/freeze.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/hash.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/help.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/install.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/list.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/search.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/show.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/uninstall.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/commands/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/configuration.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/distributions/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/distributions/base.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/distributions/installed.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/distributions/sdist.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/distributions/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/index/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/index/collector.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/index/package_finder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/legacy_resolve.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/locations.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/main.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/candidate.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/format_control.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/index.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/link.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/scheme.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/search_scope.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/target_python.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/models/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/auth.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/cache.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/download.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/session.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/check.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/freeze.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/operations/prepare.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/pep425tags.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/pyproject.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/constructors.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/req_file.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/req_install.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/req_set.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/req_tracker.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/self_outdated_check.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/appdirs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/deprecation.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/distutils_args.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/encoding.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/filesystem.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/filetypes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/glibc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/hashes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/logging.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/marker_files.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/misc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/models.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/packaging.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/pkg_resources.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/subprocess.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/typing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/ui.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/unpacking.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/urls.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/utils/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/git.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/subversion.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_internal/wheel_builder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pip/_vendor/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources-0.0.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/_vendor/six.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/extern/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pkg_resources/py31compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress-1.5.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress/bar.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress/counter.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/progress/spinner.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4-py3.8-nspkg.pth create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/namespace_packages.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/protobuf-3.15.4.dist-info/top_level.txt create mode 100755 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pvectorc.cpython-38-x86_64-linux-gnu.so create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyRFC3339-1.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyRFC3339-1.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyRFC3339-1.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyRFC3339-1.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyRFC3339-1.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser-2.20.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/_ast_gen.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/_build_tables.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/_c_ast.cfg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ast_transforms.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/c_ast.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/c_generator.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/c_lexer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/c_parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/lextab.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/cpp.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/ctokens.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/lex.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/yacc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/ply/ygen.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/plyparser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pycparser/yacctab.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/DESCRIPTION.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/metadata.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons-0.13.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/binders/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/binders/base_binder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/binders/hash_signatures_binder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/base_first_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/base_third_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/encrypted_first_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/first_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/caveat_delegates/third_party.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/field_encryptors/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/field_encryptors/base_field_encryptor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/field_encryptors/secret_box_encryptor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/macaroon.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/serializers/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/serializers/base_serializer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/serializers/binary_serializer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/serializers/json_serializer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pymacaroons/verifier.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing-2.4.6.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyparsing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrfc3339/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrfc3339/generator.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrfc3339/parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrfc3339/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/LICENCE.mit create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent-0.17.3.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/__init__.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_checked_types.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_field_common.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_helpers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_immutable.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pbag.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pclass.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pdeque.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_plist.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pmap.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_precord.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pset.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_pvector.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_toolz.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/_transformations.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/py.typed create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/typing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pyrsistent/typing.pyi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/python_dateutil-2.8.1.dist-info/zip-safe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml-0.1.21.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/core.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/test.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytoml/writer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/DESCRIPTION.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/metadata.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz-2021.1.dist-info/zip-safe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/lazy.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/reference.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/tzfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/tzinfo.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Abidjan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Accra create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Addis_Ababa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Algiers create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Asmara create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Asmera create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Bamako create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Bangui create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Banjul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Bissau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Blantyre create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Brazzaville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Bujumbura create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Cairo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Casablanca create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Ceuta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Conakry create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Dakar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Dar_es_Salaam create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Djibouti create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Douala create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/El_Aaiun create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Freetown create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Gaborone create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Harare create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Johannesburg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Juba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Kampala create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Khartoum create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Kigali create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Kinshasa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Lagos create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Libreville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Lome create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Luanda create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Lubumbashi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Lusaka create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Malabo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Maputo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Maseru create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Mbabane create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Mogadishu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Monrovia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Nairobi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Ndjamena create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Niamey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Nouakchott create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Ouagadougou create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Porto-Novo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Sao_Tome create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Timbuktu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Tripoli create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Tunis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Africa/Windhoek create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Adak create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Anchorage create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Anguilla create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Antigua create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Araguaina create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Buenos_Aires create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Catamarca create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/ComodRivadavia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Cordoba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Jujuy create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/La_Rioja create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Mendoza create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Rio_Gallegos create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Salta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/San_Juan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/San_Luis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Tucuman create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Argentina/Ushuaia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Aruba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Asuncion create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Atikokan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Atka create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Bahia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Bahia_Banderas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Barbados create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Belem create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Belize create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Blanc-Sablon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Boa_Vista create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Bogota create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Boise create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Buenos_Aires create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cambridge_Bay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Campo_Grande create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cancun create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Caracas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Catamarca create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cayenne create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cayman create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Chicago create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Chihuahua create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Coral_Harbour create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cordoba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Costa_Rica create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Creston create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Cuiaba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Curacao create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Danmarkshavn create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Dawson create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Dawson_Creek create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Denver create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Detroit create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Dominica create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Edmonton create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Eirunepe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/El_Salvador create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Ensenada create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Fort_Nelson create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Fort_Wayne create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Fortaleza create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Glace_Bay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Godthab create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Goose_Bay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Grand_Turk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Grenada create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Guadeloupe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Guatemala create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Guayaquil create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Guyana create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Halifax create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Havana create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Hermosillo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Indianapolis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Knox create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Marengo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Petersburg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Tell_City create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Vevay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Vincennes create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indiana/Winamac create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Indianapolis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Inuvik create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Iqaluit create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Jamaica create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Jujuy create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Juneau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Kentucky/Louisville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Kentucky/Monticello create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Knox_IN create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Kralendijk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/La_Paz create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Lima create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Los_Angeles create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Louisville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Lower_Princes create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Maceio create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Managua create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Manaus create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Marigot create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Martinique create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Matamoros create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Mazatlan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Mendoza create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Menominee create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Merida create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Metlakatla create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Mexico_City create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Miquelon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Moncton create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Monterrey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Montevideo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Montreal create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Montserrat create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Nassau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/New_York create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Nipigon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Nome create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Noronha create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/North_Dakota/Beulah create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/North_Dakota/Center create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/North_Dakota/New_Salem create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Nuuk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Ojinaga create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Panama create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Pangnirtung create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Paramaribo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Phoenix create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Port-au-Prince create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Port_of_Spain create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Porto_Acre create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Porto_Velho create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Puerto_Rico create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Punta_Arenas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Rainy_River create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Rankin_Inlet create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Recife create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Regina create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Resolute create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Rio_Branco create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Rosario create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Santa_Isabel create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Santarem create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Santiago create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Santo_Domingo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Sao_Paulo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Scoresbysund create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Shiprock create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Sitka create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Barthelemy create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Johns create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Kitts create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Lucia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Thomas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/St_Vincent create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Swift_Current create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Tegucigalpa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Thule create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Thunder_Bay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Tijuana create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Toronto create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Tortola create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Vancouver create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Virgin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Whitehorse create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Winnipeg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Yakutat create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/America/Yellowknife create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Casey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Davis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/DumontDUrville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Macquarie create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Mawson create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/McMurdo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Palmer create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Rothera create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/South_Pole create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Syowa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Troll create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Antarctica/Vostok create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Arctic/Longyearbyen create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Aden create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Almaty create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Amman create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Anadyr create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Aqtau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Aqtobe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ashgabat create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ashkhabad create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Atyrau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Baghdad create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Bahrain create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Baku create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Bangkok create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Barnaul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Beirut create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Bishkek create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Brunei create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Calcutta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Chita create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Choibalsan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Chongqing create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Chungking create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Colombo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Dacca create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Damascus create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Dhaka create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Dili create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Dubai create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Dushanbe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Famagusta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Gaza create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Harbin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Hebron create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ho_Chi_Minh create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Hong_Kong create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Hovd create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Irkutsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Istanbul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Jakarta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Jayapura create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Jerusalem create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kabul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kamchatka create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Karachi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kashgar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kathmandu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Katmandu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Khandyga create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kolkata create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Krasnoyarsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kuala_Lumpur create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kuching create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Kuwait create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Macao create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Macau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Magadan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Makassar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Manila create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Muscat create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Nicosia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Novokuznetsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Novosibirsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Omsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Oral create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Phnom_Penh create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Pontianak create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Pyongyang create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Qatar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Qostanay create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Qyzylorda create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Rangoon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Riyadh create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Saigon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Sakhalin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Samarkand create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Seoul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Shanghai create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Singapore create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Srednekolymsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Taipei create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tashkent create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tbilisi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tehran create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tel_Aviv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Thimbu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Thimphu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tokyo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Tomsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ujung_Pandang create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ulaanbaatar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ulan_Bator create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Urumqi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Ust-Nera create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Vientiane create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Vladivostok create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Yakutsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Yangon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Yekaterinburg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Asia/Yerevan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Azores create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Bermuda create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Canary create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Cape_Verde create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Faeroe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Faroe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Jan_Mayen create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Madeira create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Reykjavik create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/South_Georgia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/St_Helena create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Atlantic/Stanley create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/ACT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Adelaide create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Brisbane create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Broken_Hill create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Canberra create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Currie create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Darwin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Eucla create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Hobart create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/LHI create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Lindeman create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Lord_Howe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Melbourne create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/NSW create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/North create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Perth create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Queensland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/South create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Sydney create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Tasmania create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Victoria create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/West create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Australia/Yancowinna create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Brazil/Acre create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Brazil/DeNoronha create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Brazil/East create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Brazil/West create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/CET create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/CST6CDT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Atlantic create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Central create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Eastern create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Mountain create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Newfoundland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Pacific create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Saskatchewan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Canada/Yukon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Chile/Continental create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Chile/EasterIsland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Cuba create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/EET create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/EST create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/EST5EDT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Egypt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Eire create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+1 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+10 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+11 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+12 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+3 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+4 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+5 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+6 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+7 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+8 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT+9 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-1 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-10 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-11 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-12 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-13 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-14 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-2 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-3 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-4 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-5 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-6 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-7 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-8 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT-9 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/GMT0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/Greenwich create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/UCT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/UTC create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/Universal create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Etc/Zulu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Amsterdam create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Andorra create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Astrakhan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Athens create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Belfast create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Belgrade create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Berlin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Bratislava create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Brussels create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Bucharest create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Budapest create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Busingen create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Chisinau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Copenhagen create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Dublin create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Gibraltar create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Guernsey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Helsinki create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Isle_of_Man create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Istanbul create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Jersey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Kaliningrad create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Kiev create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Kirov create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Lisbon create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Ljubljana create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/London create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Luxembourg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Madrid create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Malta create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Mariehamn create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Minsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Monaco create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Moscow create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Nicosia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Oslo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Paris create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Podgorica create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Prague create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Riga create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Rome create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Samara create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/San_Marino create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Sarajevo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Saratov create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Simferopol create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Skopje create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Sofia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Stockholm create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Tallinn create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Tirane create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Tiraspol create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Ulyanovsk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Uzhgorod create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Vaduz create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Vatican create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Vienna create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Vilnius create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Volgograd create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Warsaw create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Zagreb create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Zaporozhye create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Europe/Zurich create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Factory create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GB create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GB-Eire create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GMT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GMT+0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GMT-0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/GMT0 create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Greenwich create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/HST create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Hongkong create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Iceland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Antananarivo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Chagos create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Christmas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Cocos create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Comoro create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Kerguelen create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Mahe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Maldives create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Mauritius create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Mayotte create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Indian/Reunion create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Iran create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Israel create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Jamaica create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Japan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Kwajalein create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Libya create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/MET create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/MST create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/MST7MDT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Mexico/BajaNorte create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Mexico/BajaSur create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Mexico/General create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/NZ create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/NZ-CHAT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Navajo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/PRC create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/PST8PDT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Apia create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Auckland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Bougainville create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Chatham create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Chuuk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Easter create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Efate create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Enderbury create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Fakaofo create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Fiji create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Funafuti create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Galapagos create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Gambier create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Guadalcanal create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Guam create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Honolulu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Johnston create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Kiritimati create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Kosrae create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Kwajalein create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Majuro create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Marquesas create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Midway create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Nauru create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Niue create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Norfolk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Noumea create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Pago_Pago create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Palau create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Pitcairn create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Pohnpei create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Ponape create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Port_Moresby create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Rarotonga create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Saipan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Samoa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Tahiti create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Tarawa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Tongatapu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Truk create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Wake create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Wallis create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Pacific/Yap create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Poland create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Portugal create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/ROC create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/ROK create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Singapore create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Turkey create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/UCT create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Alaska create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Aleutian create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Arizona create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Central create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/East-Indiana create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Eastern create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Hawaii create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Indiana-Starke create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Michigan create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Mountain create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Pacific create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/US/Samoa create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/UTC create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Universal create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/W-SU create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/WET create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/Zulu create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/iso3166.tab create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/leapseconds create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/tzdata.zi create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/zone.tab create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/pytz/zoneinfo/zone1970.tab create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.22.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/DESCRIPTION.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/metadata.json create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests-2.24.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/__version__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/_internal_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/adapters.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/api.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/auth.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/certs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/cookies.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/help.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/hooks.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/models.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/packages.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/sessions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/status_codes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/structures.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/AUTHORS.rst create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt-0.9.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/appengine.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/fingerprint.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/host_header_ssl.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/socket_options.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/source.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/ssl.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/adapters/x509.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/auth/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/auth/_digest_auth_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/auth/guess.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/auth/handler.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/auth/http_proxy_digest.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/cookies/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/cookies/forgetful.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/downloadutils/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/downloadutils/stream.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/downloadutils/tee.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/multipart/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/multipart/decoder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/multipart/encoder.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/sessions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/streaming_iterator.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/threaded/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/threaded/pool.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/threaded/thread.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/utils/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/utils/deprecated.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/utils/dump.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/utils/formdata.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/requests_toolbelt/utils/user_agent.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying-1.3.3.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/retrying.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/dependency_links.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.dist-info/zip-safe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools-44.0.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_deprecation_warning.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_imp.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/ordered_set.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/_compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/tags.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/_vendor/six.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/archive_util.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/build_meta.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/cli-32.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/cli-64.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/cli.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/alias.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/bdist_egg.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/bdist_rpm.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/bdist_wininst.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/build_clib.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/build_ext.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/build_py.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/develop.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/dist_info.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/easy_install.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/egg_info.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/install.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/install_egg_info.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/install_lib.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/install_scripts.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/launcher manifest.xml create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/py36compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/register.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/rotate.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/saveopts.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/sdist.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/setopt.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/test.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/upload.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/command/upload_docs.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/config.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/dep_util.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/depends.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/dist.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/errors.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/extension.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/extern/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/glob.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/gui-32.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/gui-64.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/gui.exe create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/installer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/launch.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/lib2to3_ex.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/monkey.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/msvc.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/namespaces.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/package_index.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/py27compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/py31compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/py33compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/py34compat.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/sandbox.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/script (dev).tmpl create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/script.tmpl create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/site-patch.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/ssl_support.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/unicode_utils.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/setuptools/windows_support.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six-1.14.0.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/six.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/LICENSE create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate-0.8.7.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/tabulate.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3-1.25.8.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/_collections.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/connection.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/connectionpool.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/_appengine_environ.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/_securetransport/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/_securetransport/bindings.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/_securetransport/low_level.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/appengine.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/ntlmpool.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/pyopenssl.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/securetransport.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/contrib/socks.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/exceptions.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/fields.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/filepost.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/packages/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/packages/backports/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/packages/backports/makefile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/packages/ssl_match_hostname/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/packages/ssl_match_hostname/_implementation.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/poolmanager.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/request.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/response.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/connection.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/queue.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/request.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/response.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/retry.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/ssl_.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/timeout.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/url.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/urllib3/util/wait.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings-0.5.1.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings/labels.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings/mklabels.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings/tests.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/webencodings/x_user_defined.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/AUTHORS.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/INSTALLER create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/LICENSE.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/METADATA create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/RECORD create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/WHEEL create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/entry_points.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.dist-info/top_level.txt create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel-0.34.2.virtualenv create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/__main__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/_version.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/bdist_wheel.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/cli/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/cli/convert.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/cli/pack.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/cli/unpack.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/macosx_libfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/metadata.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/pep425tags.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/pkginfo.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/util.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/wheel/wheelfile.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/__init__.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/composer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/constructor.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/cyaml.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/dumper.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/emitter.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/error.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/events.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/loader.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/nodes.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/parser.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/reader.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/representer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/resolver.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/scanner.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/serializer.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/yaml/tokens.py create mode 100644 hackfest_firewall_pnf/charms/vyos-config/venv/pyvenv.cfg create mode 100644 hackfest_firewall_pnf/charms/vyos-config/vyos-config.charm delete mode 100644 hackfest_firewall_pnf/cloud_init/vyos-userdata create mode 100644 hackfest_virtual-pc_vnfd/charms/virtual-pc-src/templates/60-no-public-ip.yaml create mode 100644 hackfest_virtual-pc_vnfd/charms/virtual-pc/templates/60-no-public-ip.yaml diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/README.md b/hackfest_firewall_pnf/charms/vyos-config-src/README.md new file mode 100644 index 00000000..2bdcab20 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/README.md @@ -0,0 +1,3 @@ +# Vyos-config + +This is a proxy charm used by Open Source Mano (OSM) to configure Vyos Router PNF, written in the [Python Operator Framwork](https://github.com/canonical/operator) diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/actions.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/actions.yaml new file mode 100644 index 00000000..80497e10 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/actions.yaml @@ -0,0 +1,46 @@ +# VyOS Action +add-port-forward: + description: "Adds a port forwarding rule" + params: + ruleNumber: + description: "Rule number, must be unique and needed to remove the rule later" + type: "string" + default: "10" + sourcePort: + description: "Source port to listen on" + type: "string" + destinationPort: + description: "Target port number on remote host to forward" + type: "string" + destinationAddress: + description: "Target host or IP address to forward traffic" + type: "string" + required: + - sourcePort + - destinationPort + - destinationAddress + +remove-port-forward: + description: "Removes a port forwarding rule by number" + params: + ruleNumber: + description: "Rule number to remove" + type: "string" + default: "10" + +# Required by charms.osm.sshproxy +run: + description: "Run an arbitrary command" + params: + command: + description: "The command to execute." + type: string + default: "" + required: + - command +generate-ssh-key: + description: "Generate a new SSH keypair for this unit. This will replace any existing previously generated keypair." +verify-ssh-credentials: + description: "Verify that this unit can authenticate with server specified by ssh-hostname and ssh-username." +get-ssh-public-key: + description: "Get the public SSH key for this unit." diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/config.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/config.yaml new file mode 100644 index 00000000..7f6d4408 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/config.yaml @@ -0,0 +1,25 @@ +options: + ssh-hostname: + type: string + default: "" + description: "The hostname or IP address of the machine to" + ssh-username: + type: string + default: "" + description: "The username to login as." + ssh-password: + type: string + default: "" + description: "The password used to authenticate." + ssh-public-key: + type: string + default: "" + description: "The public key of this unit." + ssh-key-type: + type: string + default: "rsa" + description: "The type of encryption to use for the SSH key." + ssh-key-bits: + type: int + default: 4096 + description: "The number of bits to use for the SSH key." diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/metadata.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/metadata.yaml new file mode 100644 index 00000000..c331b60d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/metadata.yaml @@ -0,0 +1,11 @@ +name: vyos-config +summary: A proxy charm to configure VyOS Router +maintainer: David García +description: | + Charm to configure VyOS PNF +series: + - xenial + - bionic +peers: + proxypeer: + interface: proxypeer diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/add-port-forward.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/add-port-forward.yaml new file mode 100644 index 00000000..5d48d758 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/add-port-forward.yaml @@ -0,0 +1,13 @@ +- hosts: vyos-routers + gather_facts: false + connection: local + tasks: + - name: backup switch (vyos) + vyos_config: + lines: + - nat destination rule {{ ruleNumber }} destination port "{{ sourcePort }}" + - nat destination rule {{ ruleNumber }} inbound-interface "eth0" + - nat destination rule {{ ruleNumber }} protocol "tcp" + - nat destination rule {{ ruleNumber }} translation port "{{ destinationPort }}" + - nat destination rule {{ ruleNumber }} translation address "{{ destinationAddress }}" + save: yes diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/backup.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/backup.yaml new file mode 100644 index 00000000..c83de083 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/backup.yaml @@ -0,0 +1,9 @@ +- hosts: vyos-routers + gather_facts: false + connection: local + tasks: + - name: backup switch (vyos) + vyos_config: + backup: yes + backup_options: + filename: "{{ backupFile }}" diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/remove-port-forward.yaml b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/remove-port-forward.yaml new file mode 100644 index 00000000..61c12f95 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/playbooks/remove-port-forward.yaml @@ -0,0 +1,11 @@ +- hosts: vyos-routers + gather_facts: false + connection: local + tasks: + - name: backup switch (vyos) + vyos_command: + commands: + - config + - delete nat destination rule {{ ruleNumber }} + - commit + - save diff --git a/hackfest_firewall_pnf/snmp/snmp.yml b/hackfest_firewall_pnf/charms/vyos-config-src/requirements.txt similarity index 100% rename from hackfest_firewall_pnf/snmp/snmp.yml rename to hackfest_firewall_pnf/charms/vyos-config-src/requirements.txt diff --git a/hackfest_firewall_pnf/charms/vyos-config-src/src/charm.py b/hackfest_firewall_pnf/charms/vyos-config-src/src/charm.py new file mode 100755 index 00000000..6f97799c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config-src/src/charm.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import subprocess +import sys +import traceback + +from charms.osm import libansible +from charms.osm.sshproxy import SSHProxyCharm +from ops.charm import CharmBase, CharmEvents +from ops.framework import StoredState, EventBase, EventSource +from ops.main import main +from ops.model import ( + ActiveStatus, + BlockedStatus, + MaintenanceStatus, + WaitingStatus, + ModelError, +) + + +sys.path.append("lib") + + +class VyosCharm(SSHProxyCharm): + def __init__(self, framework, key): + super().__init__(framework, key) + + # Register all of the events we want to observe + self.framework.observe(self.on.config_changed, self.on_config_changed) + self.framework.observe(self.on.install, self.on_install) + self.framework.observe(self.on.start, self.on_start) + self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm) + # Charm actions (primitives) + self.framework.observe( + self.on.add_port_forward_action, self.on_add_port_forward_action + ) + self.framework.observe( + self.on.remove_port_forward_action, self.on_remove_port_forward_action + ) + + def on_config_changed(self, event): + """Handle changes in configuration""" + super().on_config_changed(event) + + def on_install(self, event): + """Called when the charm is being installed""" + super().on_install(event) + self.unit.status = MaintenanceStatus("Installing Ansible") + libansible.install_ansible_support() + self.unit.status = ActiveStatus() + + def on_start(self, event): + """Called when the charm is being started""" + super().on_start(event) + + def on_add_port_forward_action(self, event): + """Adds a port forward rule.""" + self._run_playbook( + event, + "add-port-forward.yaml", + { + "sourcePort": event.params["sourcePort"], + "destinationPort": event.params["destinationPort"], + "destinationAddress": event.params["destinationAddress"], + "ruleNumber": event.params["ruleNumber"], + }) + + def on_remove_port_forward_action(self, event): + """Remove a port forward rule.""" + self._run_playbook( + event, + "remove-port-forward.yaml", + { + "ruleNumber": event.params["ruleNumber"], + }) + + def on_upgrade_charm(self, event): + """Upgrade the charm.""" + + def _run_playbook(self, event, playbook, variables): + try: + config = self.model.config + result = libansible.execute_playbook( + playbook, + config["ssh-hostname"], + config["ssh-username"], + config["ssh-password"], + variables, + ) + event.set_results({"output": result}) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + err = traceback.format_exception(exc_type, exc_value, exc_traceback) + event.fail(message="Playbook " + playbook + " failed: " + str(err)) + + +if __name__ == "__main__": + main(VyosCharm) diff --git a/hackfest_firewall_pnf/charms/vyos-config/actions.yaml b/hackfest_firewall_pnf/charms/vyos-config/actions.yaml index ea522049..80497e10 100644 --- a/hackfest_firewall_pnf/charms/vyos-config/actions.yaml +++ b/hackfest_firewall_pnf/charms/vyos-config/actions.yaml @@ -1,29 +1,32 @@ # VyOS Action -configure-remote: - description: "Add firewall rule to VyOS PNF." +add-port-forward: + description: "Adds a port forwarding rule" params: - magmaIP: - description: "Magma AGW allowed IP" - type: "string" - default: "0.0.0.0" + ruleNumber: + description: "Rule number, must be unique and needed to remove the rule later" + type: "string" + default: "10" + sourcePort: + description: "Source port to listen on" + type: "string" + destinationPort: + description: "Target port number on remote host to forward" + type: "string" + destinationAddress: + description: "Target host or IP address to forward traffic" + type: "string" required: - - magmaIP + - sourcePort + - destinationPort + - destinationAddress -backup: - description: "Backup the current firewall configuration" +remove-port-forward: + description: "Removes a port forwarding rule by number" params: - backupFile: - description: "Filename to store the backup into" - type: "string" - default: "backup.cfg" - -restore: - description: "Backup the current firewall configuration" - params: - backupFile: - description: "Filename to restore the backup from" - type: "string" - default: "backup.cfg" + ruleNumber: + description: "Rule number to remove" + type: "string" + default: "10" # Required by charms.osm.sshproxy run: diff --git a/hackfest_firewall_pnf/charms/vyos-config/config.yaml b/hackfest_firewall_pnf/charms/vyos-config/config.yaml index 5b908ae0..7f6d4408 100644 --- a/hackfest_firewall_pnf/charms/vyos-config/config.yaml +++ b/hackfest_firewall_pnf/charms/vyos-config/config.yaml @@ -11,10 +11,6 @@ options: type: string default: "" description: "The password used to authenticate." - # ssh-private-key: - # type: string - # default: "" - # description: "DEPRECATED. The private ssh key to be used to authenticate." ssh-public-key: type: string default: "" diff --git a/hackfest_firewall_pnf/charms/vyos-config/dispatch b/hackfest_firewall_pnf/charms/vyos-config/dispatch new file mode 100755 index 00000000..fe31c056 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/dispatch @@ -0,0 +1,3 @@ +#!/bin/sh + +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py diff --git a/hackfest_firewall_pnf/charms/vyos-config/hooks/install b/hackfest_firewall_pnf/charms/vyos-config/hooks/install deleted file mode 100755 index b110e1c9..00000000 --- a/hackfest_firewall_pnf/charms/vyos-config/hooks/install +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2020 Canonical Ltd. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys - -sys.path.append("lib") - -from ops.charm import CharmBase, CharmEvents -from ops.framework import StoredState, EventBase, EventSource -from ops.main import main -from ops.model import ( - ActiveStatus, - BlockedStatus, - MaintenanceStatus, - WaitingStatus, - ModelError, -) -import os -import subprocess -import traceback - -from charms.osm.sshproxy import SSHProxyCharm -from charms.osm import libansible - - -class VyosCharm(SSHProxyCharm): - def __init__(self, framework, key): - super().__init__(framework, key) - - # Register all of the events we want to observe - self.framework.observe(self.on.config_changed, self.on_config_changed) - self.framework.observe(self.on.install, self.on_install) - self.framework.observe(self.on.start, self.on_start) - self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm) - # Charm actions (primitives) - self.framework.observe( - self.on.configure_remote_action, self.on_configure_remote_action - ) - - def on_config_changed(self, event): - """Handle changes in configuration""" - super().on_config_changed(event) - - def on_install(self, event): - """Called when the charm is being installed""" - super().on_install(event) - self.unit.status = MaintenanceStatus("Installing Ansible") - libansible.install_ansible_support() - self.unit.status = ActiveStatus() - - def on_start(self, event): - """Called when the charm is being started""" - super().on_start(event) - - def on_configure_remote_action(self, event): - """Configure remote.""" - - if self.unit.is_leader(): - try: - config = self.model.config - magmaIP = event.params["magmaIP"] - dict_vars = {"MAGMA_AGW_IP": magmaIP} - result = libansible.execute_playbook( - "configure-remote.yaml", - config["ssh-hostname"], - config["ssh-username"], - config["ssh-password"], - dict_vars, - ) - event.set_results({"output": result}) - except: - exc_type, exc_value, exc_traceback = sys.exc_info() - err = traceback.format_exception(exc_type, exc_value, exc_traceback) - event.fail(message="configure-remote failed: " + str(err)) - - else: - event.fail("Unit is not leader") - return - - def on_upgrade_charm(self, event): - """Upgrade the charm.""" - - -if __name__ == "__main__": - main(VyosCharm) diff --git a/hackfest_firewall_pnf/charms/vyos-config/hooks/install b/hackfest_firewall_pnf/charms/vyos-config/hooks/install new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/hooks/install @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/hooks/start b/hackfest_firewall_pnf/charms/vyos-config/hooks/start new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/hooks/start @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/hooks/upgrade-charm b/hackfest_firewall_pnf/charms/vyos-config/hooks/upgrade-charm new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/hooks/upgrade-charm @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/lib/charms/osm/libansible.py b/hackfest_firewall_pnf/charms/vyos-config/lib/charms/osm/libansible.py index 32fd26ae..811ec444 100644 --- a/hackfest_firewall_pnf/charms/vyos-config/lib/charms/osm/libansible.py +++ b/hackfest_firewall_pnf/charms/vyos-config/lib/charms/osm/libansible.py @@ -1,5 +1,5 @@ ## -# Copyright 2020 Canonical Ltd. +# Copyright ETSI OSM # All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -17,14 +17,16 @@ import fnmatch import os -import yaml import subprocess import sys +import yaml -sys.path.append("lib") import charmhelpers.fetch +sys.path.append("lib") + + ansible_hosts_path = "/etc/ansible/hosts" @@ -50,21 +52,24 @@ def install_ansible_support(from_ppa=True, ppa_location="ppa:ansible/ansible"): def create_hosts(hostname, username, password, hosts): inventory_path = "/etc/ansible/hosts" - - with open(inventory_path, "w") as f: - f.write("[{}]\n".format(hosts)) - h1 = "host ansible_host={0} ansible_user={1} ansible_password={2}\n".format( - hostname, username, password - ) + with open(inventory_path, 'w') as f: + f.write('[{}]\n'.format(hosts)) + h1 = '{0} ansible_connection=network_cli ansible_network_os=vyos ' \ + 'ansible_ssh_user={1} ansible_ssh_pass={2} ' \ + 'ansible_python_interpreter=/usr/bin/python\n'.format(hostname, username, password) f.write(h1) def create_ansible_cfg(): ansible_config_path = "/etc/ansible/ansible.cfg" - - with open(ansible_config_path, "w") as f: - f.write("[defaults]\n") - f.write("host_key_checking = False\n") + with open(ansible_config_path, 'w') as f: + f.write('[defaults]\n') + f.write('host_key_checking = False\n') + # logs playbook execution attempts to the specified path + f.write('log_path = /var/log/ansible.log\n') + f.write('[ssh_connection]\n') + f.write('control_path=%(directory)s/%%h-%%r\n') + f.write('control_path_dir=~/.ansible/cp\n') # Function to find the playbook path @@ -78,31 +83,26 @@ def find(pattern, path): def execute_playbook(playbook_file, hostname, user, password, vars_dict=None): - playbook_path = find(playbook_file, "/var/lib/juju/agents/") - - with open(playbook_path, "r") as f: - playbook_data = yaml.load(f) - - hosts = "all" - if "hosts" in playbook_data[0].keys() and playbook_data[0]["hosts"]: - hosts = playbook_data[0]["hosts"] - + playbook_path = find(playbook_file, '/var/lib/juju/agents/') + print("Playbook " + playbook_file + " is " + playbook_path) + with open(playbook_path, 'r') as f: + playbook_data = yaml.load(f, Loader=yaml.SafeLoader) + hosts = 'all' + if 'hosts' in playbook_data[0].keys() and playbook_data[0]['hosts']: + hosts = playbook_data[0]['hosts'] create_ansible_cfg() create_hosts(hostname, user, password, hosts) - - call = "ansible-playbook {} ".format(playbook_path) - + call = 'ansible-playbook -vvvv %s ' % playbook_path if vars_dict and isinstance(vars_dict, dict) and len(vars_dict) > 0: - call += "--extra-vars " - - string_var = "" - for k,v in vars_dict.items(): - string_var += "{}={} ".format(k, v) - + call += '--extra-vars ' + string_var = '' + for v in vars_dict.items(): + string_var += '%s=%s ' % v string_var = string_var.strip() - call += '"{}"'.format(string_var) - + call += '"%s"' % string_var call = call.strip() + print(call) result = subprocess.check_output(call, shell=True) - - return result + lastline = result.decode('utf-8').splitlines()[-2] + print("Result is " + lastline) + return lastline diff --git a/hackfest_firewall_pnf/charms/vyos-config/playbooks/add-port-forward.yaml b/hackfest_firewall_pnf/charms/vyos-config/playbooks/add-port-forward.yaml new file mode 100644 index 00000000..5d48d758 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/playbooks/add-port-forward.yaml @@ -0,0 +1,13 @@ +- hosts: vyos-routers + gather_facts: false + connection: local + tasks: + - name: backup switch (vyos) + vyos_config: + lines: + - nat destination rule {{ ruleNumber }} destination port "{{ sourcePort }}" + - nat destination rule {{ ruleNumber }} inbound-interface "eth0" + - nat destination rule {{ ruleNumber }} protocol "tcp" + - nat destination rule {{ ruleNumber }} translation port "{{ destinationPort }}" + - nat destination rule {{ ruleNumber }} translation address "{{ destinationAddress }}" + save: yes diff --git a/hackfest_firewall_pnf/charms/vyos-config/playbooks/backup.yaml b/hackfest_firewall_pnf/charms/vyos-config/playbooks/backup.yaml index a98eebf1..c83de083 100644 --- a/hackfest_firewall_pnf/charms/vyos-config/playbooks/backup.yaml +++ b/hackfest_firewall_pnf/charms/vyos-config/playbooks/backup.yaml @@ -1,8 +1,9 @@ - hosts: vyos-routers + gather_facts: false connection: local tasks: - - name: Performs a backup of the current configuration - vyos_config: - lines: - - save "/home/osm/{{ backupFile }}" - + - name: backup switch (vyos) + vyos_config: + backup: yes + backup_options: + filename: "{{ backupFile }}" diff --git a/hackfest_firewall_pnf/charms/vyos-config/playbooks/remove-port-forward.yaml b/hackfest_firewall_pnf/charms/vyos-config/playbooks/remove-port-forward.yaml new file mode 100644 index 00000000..61c12f95 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/playbooks/remove-port-forward.yaml @@ -0,0 +1,11 @@ +- hosts: vyos-routers + gather_facts: false + connection: local + tasks: + - name: backup switch (vyos) + vyos_command: + commands: + - config + - delete nat destination rule {{ ruleNumber }} + - commit + - save diff --git a/hackfest_firewall_pnf/charms/vyos-config/src/charm.py b/hackfest_firewall_pnf/charms/vyos-config/src/charm.py index b110e1c9..6f97799c 100755 --- a/hackfest_firewall_pnf/charms/vyos-config/src/charm.py +++ b/hackfest_firewall_pnf/charms/vyos-config/src/charm.py @@ -13,10 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os +import subprocess import sys +import traceback -sys.path.append("lib") - +from charms.osm import libansible +from charms.osm.sshproxy import SSHProxyCharm from ops.charm import CharmBase, CharmEvents from ops.framework import StoredState, EventBase, EventSource from ops.main import main @@ -27,12 +30,9 @@ from ops.model import ( WaitingStatus, ModelError, ) -import os -import subprocess -import traceback -from charms.osm.sshproxy import SSHProxyCharm -from charms.osm import libansible + +sys.path.append("lib") class VyosCharm(SSHProxyCharm): @@ -46,7 +46,10 @@ class VyosCharm(SSHProxyCharm): self.framework.observe(self.on.upgrade_charm, self.on_upgrade_charm) # Charm actions (primitives) self.framework.observe( - self.on.configure_remote_action, self.on_configure_remote_action + self.on.add_port_forward_action, self.on_add_port_forward_action + ) + self.framework.observe( + self.on.remove_port_forward_action, self.on_remove_port_forward_action ) def on_config_changed(self, event): @@ -64,34 +67,46 @@ class VyosCharm(SSHProxyCharm): """Called when the charm is being started""" super().on_start(event) - def on_configure_remote_action(self, event): - """Configure remote.""" - - if self.unit.is_leader(): - try: - config = self.model.config - magmaIP = event.params["magmaIP"] - dict_vars = {"MAGMA_AGW_IP": magmaIP} - result = libansible.execute_playbook( - "configure-remote.yaml", - config["ssh-hostname"], - config["ssh-username"], - config["ssh-password"], - dict_vars, - ) - event.set_results({"output": result}) - except: - exc_type, exc_value, exc_traceback = sys.exc_info() - err = traceback.format_exception(exc_type, exc_value, exc_traceback) - event.fail(message="configure-remote failed: " + str(err)) - - else: - event.fail("Unit is not leader") - return + def on_add_port_forward_action(self, event): + """Adds a port forward rule.""" + self._run_playbook( + event, + "add-port-forward.yaml", + { + "sourcePort": event.params["sourcePort"], + "destinationPort": event.params["destinationPort"], + "destinationAddress": event.params["destinationAddress"], + "ruleNumber": event.params["ruleNumber"], + }) + + def on_remove_port_forward_action(self, event): + """Remove a port forward rule.""" + self._run_playbook( + event, + "remove-port-forward.yaml", + { + "ruleNumber": event.params["ruleNumber"], + }) def on_upgrade_charm(self, event): """Upgrade the charm.""" + def _run_playbook(self, event, playbook, variables): + try: + config = self.model.config + result = libansible.execute_playbook( + playbook, + config["ssh-hostname"], + config["ssh-username"], + config["ssh-password"], + variables, + ) + event.set_results({"output": result}) + except: + exc_type, exc_value, exc_traceback = sys.exc_info() + err = traceback.format_exception(exc_type, exc_value, exc_traceback) + event.fail(message="Playbook " + playbook + " failed: " + str(err)) + if __name__ == "__main__": main(VyosCharm) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate new file mode 100644 index 00000000..3b8d0b29 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate @@ -0,0 +1,84 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV='/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv' +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1-}" + if [ "x" != x ] ; then + PS1="${PS1-}" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true + +pydoc () { + python -m pydoc "$@" +} + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.csh b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.csh new file mode 100644 index 00000000..823028c0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.csh @@ -0,0 +1,55 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . + +set newline='\ +' + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH:q" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT:q" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV '/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv' + +set _OLD_VIRTUAL_PATH="$PATH:q" +setenv PATH "$VIRTUAL_ENV:q/bin:$PATH:q" + + + +if ('' != "") then + set env_name = '' +else + set env_name = '('"$VIRTUAL_ENV:t:q"') ' +endif + +if ( $?VIRTUAL_ENV_DISABLE_PROMPT ) then + if ( $VIRTUAL_ENV_DISABLE_PROMPT == "" ) then + set do_prompt = "1" + else + set do_prompt = "0" + endif +else + set do_prompt = "1" +endif + +if ( $do_prompt == "1" ) then + # Could be in a non-interactive environment, + # in which case, $prompt is undefined and we wouldn't + # care about the prompt anyway. + if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt:q" + if ( "$prompt:q" =~ *"$newline:q"* ) then + : + else + set prompt = "$env_name:q$prompt:q" + endif + endif +endif + +unset env_name +unset do_prompt + +alias pydoc python -m pydoc + +rehash diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.fish b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.fish new file mode 100644 index 00000000..5c50244a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.fish @@ -0,0 +1,100 @@ +# This file must be used using `source bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function _bashify_path -d "Converts a fish path to something bash can recognize" + set fishy_path $argv + set bashy_path $fishy_path[1] + for path_part in $fishy_path[2..-1] + set bashy_path "$bashy_path:$path_part" + end + echo $bashy_path +end + +function _fishify_path -d "Converts a bash path to something fish can recognize" + echo $argv | tr ':' '\n' +end + +function deactivate -d 'Exit virtualenv mode and return to the normal environment.' + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + # https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling + if test (echo $FISH_VERSION | head -c 1) -lt 3 + set -gx PATH (_fishify_path "$_OLD_VIRTUAL_PATH") + else + set -gx PATH "$_OLD_VIRTUAL_PATH" + end + set -e _OLD_VIRTUAL_PATH + end + + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME "$_OLD_VIRTUAL_PYTHONHOME" + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + and functions -q _old_fish_prompt + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + functions -e _bashify_path + functions -e _fishify_path + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV '/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv' + +# https://github.com/fish-shell/fish-shell/issues/436 altered PATH handling +if test (echo $FISH_VERSION | head -c 1) -lt 3 + set -gx _OLD_VIRTUAL_PATH (_bashify_path $PATH) +else + set -gx _OLD_VIRTUAL_PATH "$PATH" +end +set -gx PATH "$VIRTUAL_ENV"'/bin' $PATH + +# Unset `$PYTHONHOME` if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Run the user's prompt first; it might depend on (pipe)status. + set -l prompt (_old_fish_prompt) + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n '' + printf '%s%s' '' (set_color normal) + else + printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") + end + + string join -- \n $prompt # handle multi-line prompts + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.ps1 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.ps1 new file mode 100644 index 00000000..95504d39 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.ps1 @@ -0,0 +1,60 @@ +$script:THIS_PATH = $myinvocation.mycommand.path +$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent + +function global:deactivate([switch] $NonDestructive) { + if (Test-Path variable:_OLD_VIRTUAL_PATH) { + $env:PATH = $variable:_OLD_VIRTUAL_PATH + Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global + } + + if (Test-Path function:_old_virtual_prompt) { + $function:prompt = $function:_old_virtual_prompt + Remove-Item function:\_old_virtual_prompt + } + + if ($env:VIRTUAL_ENV) { + Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue + } + + if (!$NonDestructive) { + # Self destruct! + Remove-Item function:deactivate + Remove-Item function:pydoc + } +} + +function global:pydoc { + python -m pydoc $args +} + +# unset irrelevant variables +deactivate -nondestructive + +$VIRTUAL_ENV = $BASE_DIR +$env:VIRTUAL_ENV = $VIRTUAL_ENV + +New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH + +$env:PATH = "$env:VIRTUAL_ENV/bin:" + $env:PATH +if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) { + function global:_old_virtual_prompt { + "" + } + $function:_old_virtual_prompt = $function:prompt + + if ("" -ne "") { + function global:prompt { + # Add the custom prefix to the existing prompt + $previous_prompt_value = & $function:_old_virtual_prompt + ("" + $previous_prompt_value) + } + } + else { + function global:prompt { + # Add a prefix to the current prompt, but don't discard it. + $previous_prompt_value = & $function:_old_virtual_prompt + $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) " + ($new_prompt_value + $previous_prompt_value) + } + } +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.xsh b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.xsh new file mode 100644 index 00000000..9f6d4105 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate.xsh @@ -0,0 +1,46 @@ +"""Xonsh activate script for virtualenv""" +from xonsh.tools import get_sep as _get_sep + +def _deactivate(args): + if "pydoc" in aliases: + del aliases["pydoc"] + + if ${...}.get("_OLD_VIRTUAL_PATH", ""): + $PATH = $_OLD_VIRTUAL_PATH + del $_OLD_VIRTUAL_PATH + + if ${...}.get("_OLD_VIRTUAL_PYTHONHOME", ""): + $PYTHONHOME = $_OLD_VIRTUAL_PYTHONHOME + del $_OLD_VIRTUAL_PYTHONHOME + + if "VIRTUAL_ENV" in ${...}: + del $VIRTUAL_ENV + + if "VIRTUAL_ENV_PROMPT" in ${...}: + del $VIRTUAL_ENV_PROMPT + + if "nondestructive" not in args: + # Self destruct! + del aliases["deactivate"] + + +# unset irrelevant variables +_deactivate(["nondestructive"]) +aliases["deactivate"] = _deactivate + +$VIRTUAL_ENV = r"/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv" + +$_OLD_VIRTUAL_PATH = $PATH +$PATH = $PATH[:] +$PATH.add($VIRTUAL_ENV + _get_sep() + "bin", front=True, replace=True) + +if ${...}.get("PYTHONHOME", ""): + # unset PYTHONHOME if set + $_OLD_VIRTUAL_PYTHONHOME = $PYTHONHOME + del $PYTHONHOME + +$VIRTUAL_ENV_PROMPT = "" +if not $VIRTUAL_ENV_PROMPT: + del $VIRTUAL_ENV_PROMPT + +aliases["pydoc"] = ["python", "-m", "pydoc"] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate_this.py b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate_this.py new file mode 100644 index 00000000..44799869 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/activate_this.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +"""Activate virtualenv for current interpreter: + +Use exec(open(this_file).read(), {'__file__': this_file}). + +This can be used when you must use an existing Python interpreter, not the virtualenv bin/python. +""" +import os +import site +import sys + +try: + abs_file = os.path.abspath(__file__) +except NameError: + raise AssertionError("You must use exec(open(this_file).read(), {'__file__': this_file}))") + +bin_dir = os.path.dirname(abs_file) +base = bin_dir[: -len("bin") - 1] # strip away the bin part from the __file__, plus the path separator + +# prepend bin to PATH (this file is inside the bin directory) +os.environ["PATH"] = os.pathsep.join([bin_dir] + os.environ.get("PATH", "").split(os.pathsep)) +os.environ["VIRTUAL_ENV"] = base # virtual env is right above bin directory + +# add the virtual environments libraries to the host python import mechanism +prev_length = len(sys.path) +for lib in "../lib/python3.8/site-packages".split(os.pathsep): + path = os.path.realpath(os.path.join(bin_dir, lib)) + site.addsitedir(path.decode("utf-8") if "" else path) +sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length] + +sys.real_prefix = sys.prefix +sys.prefix = base diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect new file mode 100755 index 00000000..ddb8412a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from chardet.cli.chardetect import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect-3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect-3.8 new file mode 100755 index 00000000..ddb8412a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect-3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from chardet.cli.chardetect import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect3 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect3 new file mode 100755 index 00000000..ddb8412a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/chardetect3 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from chardet.cli.chardetect import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/charmcraft b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/charmcraft new file mode 100755 index 00000000..ee6460bc --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/charmcraft @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from charmcraft.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro new file mode 100755 index 00000000..06e85815 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from distro import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro-3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro-3.8 new file mode 100755 index 00000000..06e85815 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro-3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from distro import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro3 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro3 new file mode 100755 index 00000000..06e85815 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/distro3 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from distro import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install new file mode 100755 index 00000000..5dd7f111 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install-3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install-3.8 new file mode 100755 index 00000000..5dd7f111 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install-3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install3 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install3 new file mode 100755 index 00000000..5dd7f111 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/easy_install3 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from setuptools.command.easy_install import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/jsonschema b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/jsonschema new file mode 100755 index 00000000..5de42465 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/jsonschema @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from jsonschema.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip new file mode 100755 index 00000000..24b60186 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip-3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip-3.8 new file mode 100755 index 00000000..24b60186 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip-3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3 new file mode 100755 index 00000000..24b60186 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3.8 new file mode 100755 index 00000000..24b60186 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/pip3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/tabulate b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/tabulate new file mode 100755 index 00000000..5316dda6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/tabulate @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from tabulate import _main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(_main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel new file mode 100755 index 00000000..06e0d032 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel-3.8 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel-3.8 new file mode 100755 index 00000000..06e0d032 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel-3.8 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel3 b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel3 new file mode 100755 index 00000000..06e0d032 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/bin/wheel3 @@ -0,0 +1,8 @@ +#!/home/mark/git/GitLab/osm-packages/hackfest_firewall_pnf/charms/vyos-config-src/venv/bin/python +# -*- coding: utf-8 -*- +import re +import sys +from wheel.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/METADATA new file mode 100644 index 00000000..3119fa91 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/METADATA @@ -0,0 +1,71 @@ +Metadata-Version: 2.1 +Name: CacheControl +Version: 0.12.6 +Summary: httplib2 caching for requests +Home-page: https://github.com/ionrock/cachecontrol +Author: Eric Larson +Author-email: eric@ionrock.org +License: UNKNOWN +Keywords: requests http caching web +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Internet :: WWW/HTTP +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Provides-Extra: filecache +Requires-Dist: lockfile (>=0.9) ; extra == 'filecache' +Provides-Extra: redis +Requires-Dist: redis (>=2.10.5) ; extra == 'redis' + +============== + CacheControl +============== + +.. image:: https://img.shields.io/pypi/v/cachecontrol.svg + :target: https://pypi.python.org/pypi/cachecontrol + :alt: Latest Version + +.. image:: https://travis-ci.org/ionrock/cachecontrol.png?branch=master + :target: https://travis-ci.org/ionrock/cachecontrol + +CacheControl is a port of the caching algorithms in httplib2_ for use with +requests_ session object. + +It was written because httplib2's better support for caching is often +mitigated by its lack of thread safety. The same is true of requests in +terms of caching. + + +Quickstart +========== + +.. code-block:: python + + import requests + + from cachecontrol import CacheControl + + + sess = requests.session() + cached_sess = CacheControl(sess) + + response = cached_sess.get('http://google.com') + +If the URL contains any caching based headers, it will cache the +result in a simple dictionary. + +For more info, check out the docs_ + +.. _docs: http://cachecontrol.readthedocs.org/en/latest/ +.. _httplib2: https://github.com/jcgregorio/httplib2 +.. _requests: http://docs.python-requests.org/ + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/RECORD new file mode 100644 index 00000000..80e6a585 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/RECORD @@ -0,0 +1,37 @@ +cachecontrol/__init__.py,sha256=pJtAaUxOsMPnytI1A3juAJkXYDr8krdSnsg4Yg3OBEg,302 +cachecontrol/_cmd.py,sha256=88j4P3JlJGqg6xAXR4btN9fYruXUH4CE-M93Sie5IB8,1242 +cachecontrol/adapter.py,sha256=ctnbSXDOj0V0NaxJP2jFauOYRDHaNYMP9QCE8kB4kfk,4870 +cachecontrol/cache.py,sha256=1fc4wJP8HYt1ycnJXeEw5pCpeBL2Cqxx6g9Fb0AYDWQ,805 +cachecontrol/compat.py,sha256=Fn_aYzqNbN0bK9gUn8SQUzMLxQ_ruGnsEMvryYDFh3o,647 +cachecontrol/controller.py,sha256=fpLmIvxce2mKVFmtDFiiyydqU_pPbCucYLC9qP-LqvY,14137 +cachecontrol/filewrapper.py,sha256=vACKO8Llzu_ZWyjV1Fxn1MA4TGU60N5N3GSrAFdAY2Q,2533 +cachecontrol/heuristics.py,sha256=BFGHJ3yQcxvZizfo90LLZ04T_Z5XSCXvFotrp7Us0sc,4070 +cachecontrol/serialize.py,sha256=Jms7OS4GB2JFUzuMPlmQtuCDzcjjE-2ijrHpUXC2BV0,7062 +cachecontrol/wrapper.py,sha256=5LX0uJwkNQUtYSEw3aGmGu9WY8wGipd81mJ8lG0d0M4,690 +cachecontrol/caches/__init__.py,sha256=-gHNKYvaeD0kOk5M74eOrsSgIKUtC6i6GfbmugGweEo,86 +cachecontrol/caches/file_cache.py,sha256=nYVKsJtXh6gJXvdn1iWyrhxvkwpQrK-eKoMRzuiwkKk,4153 +cachecontrol/caches/redis_cache.py,sha256=yZP1PoUgAvxEZZrCVwImZ-5pFKU41v5HYJf1rfbXYmM,844 +CacheControl-0.12.6.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +CacheControl-0.12.6.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +CacheControl-0.12.6.dist-info/METADATA,sha256=DzDqga-Bw7B7ylVrJanU_-imHV1od8Ok64qr5ugT-5A,2107 +CacheControl-0.12.6.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +CacheControl-0.12.6.dist-info/top_level.txt,sha256=vGYWzpbe3h6gkakV4f7iCK2x3KyK3oMkV5pe5v25-d4,13 +CacheControl-0.12.6.dist-info/RECORD,, +cachecontrol/compat.cpython-38.pyc,, +CacheControl-0.12.6.dist-info/__pycache__,, +CacheControl-0.12.6.virtualenv,, +cachecontrol/caches/file_cache.cpython-38.pyc,, +cachecontrol/caches/__init__.cpython-38.pyc,, +cachecontrol/__init__.cpython-38.pyc,, +cachecontrol/controller.cpython-38.pyc,, +cachecontrol/serialize.cpython-38.pyc,, +cachecontrol/caches/__pycache__,, +cachecontrol/caches/redis_cache.cpython-38.pyc,, +CacheControl-0.12.6.dist-info/INSTALLER,, +cachecontrol/wrapper.cpython-38.pyc,, +cachecontrol/adapter.cpython-38.pyc,, +cachecontrol/heuristics.cpython-38.pyc,, +cachecontrol/filewrapper.cpython-38.pyc,, +cachecontrol/__pycache__,, +cachecontrol/cache.cpython-38.pyc,, +cachecontrol/_cmd.cpython-38.pyc,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/top_level.txt new file mode 100644 index 00000000..af37ac62 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.dist-info/top_level.txt @@ -0,0 +1 @@ +cachecontrol diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/CacheControl-0.12.6.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/LICENSE.rst b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/LICENSE.rst new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/METADATA new file mode 100644 index 00000000..55c0f826 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/METADATA @@ -0,0 +1,106 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 2.11.2 +Summary: A very fast and expressive template engine. +Home-page: https://palletsprojects.com/p/jinja/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Code, https://github.com/pallets/jinja +Project-URL: Issue tracker, https://github.com/pallets/jinja/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* +Description-Content-Type: text/x-rst +Requires-Dist: MarkupSafe (>=0.23) +Provides-Extra: i18n +Requires-Dist: Babel (>=0.8) ; extra == 'i18n' + +Jinja +===== + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Jinja2 + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +In A Nutshell +------------- + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} + + {% endblock %} + + +Links +----- + +- Website: https://palletsprojects.com/p/jinja/ +- Documentation: https://jinja.palletsprojects.com/ +- Releases: https://pypi.org/project/Jinja2/ +- Code: https://github.com/pallets/jinja +- Issue tracker: https://github.com/pallets/jinja/issues +- Test status: https://dev.azure.com/pallets/jinja/_build +- Official chat: https://discord.gg/t6rrQZH + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/RECORD new file mode 100644 index 00000000..413fef4b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/RECORD @@ -0,0 +1,61 @@ +Jinja2-2.11.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Jinja2-2.11.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Jinja2-2.11.2.dist-info/METADATA,sha256=5ZHRZoIRAMHsJPnqhlJ622_dRPsYePYJ-9EH4-Ry7yI,3535 +Jinja2-2.11.2.dist-info/RECORD,, +Jinja2-2.11.2.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +Jinja2-2.11.2.dist-info/entry_points.txt,sha256=Qy_DkVo6Xj_zzOtmErrATe8lHZhOqdjpt3e4JJAGyi8,61 +Jinja2-2.11.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=0QCM_jKKDM10yzSdHRVV4mQbCbDqf0GN0GirAqibn9Y,1549 +jinja2/__pycache__/__init__.cpython-38.pyc,, +jinja2/__pycache__/_compat.cpython-38.pyc,, +jinja2/__pycache__/_identifier.cpython-38.pyc,, +jinja2/__pycache__/asyncfilters.cpython-38.pyc,, +jinja2/__pycache__/asyncsupport.cpython-38.pyc,, +jinja2/__pycache__/bccache.cpython-38.pyc,, +jinja2/__pycache__/compiler.cpython-38.pyc,, +jinja2/__pycache__/constants.cpython-38.pyc,, +jinja2/__pycache__/debug.cpython-38.pyc,, +jinja2/__pycache__/defaults.cpython-38.pyc,, +jinja2/__pycache__/environment.cpython-38.pyc,, +jinja2/__pycache__/exceptions.cpython-38.pyc,, +jinja2/__pycache__/ext.cpython-38.pyc,, +jinja2/__pycache__/filters.cpython-38.pyc,, +jinja2/__pycache__/idtracking.cpython-38.pyc,, +jinja2/__pycache__/lexer.cpython-38.pyc,, +jinja2/__pycache__/loaders.cpython-38.pyc,, +jinja2/__pycache__/meta.cpython-38.pyc,, +jinja2/__pycache__/nativetypes.cpython-38.pyc,, +jinja2/__pycache__/nodes.cpython-38.pyc,, +jinja2/__pycache__/optimizer.cpython-38.pyc,, +jinja2/__pycache__/parser.cpython-38.pyc,, +jinja2/__pycache__/runtime.cpython-38.pyc,, +jinja2/__pycache__/sandbox.cpython-38.pyc,, +jinja2/__pycache__/tests.cpython-38.pyc,, +jinja2/__pycache__/utils.cpython-38.pyc,, +jinja2/__pycache__/visitor.cpython-38.pyc,, +jinja2/_compat.py,sha256=B6Se8HjnXVpzz9-vfHejn-DV2NjaVK-Iewupc5kKlu8,3191 +jinja2/_identifier.py,sha256=EdgGJKi7O1yvr4yFlvqPNEqV6M1qHyQr8Gt8GmVTKVM,1775 +jinja2/asyncfilters.py,sha256=XJtYXTxFvcJ5xwk6SaDL4S0oNnT0wPYvXBCSzc482fI,4250 +jinja2/asyncsupport.py,sha256=ZBFsDLuq3Gtji3Ia87lcyuDbqaHZJRdtShZcqwpFnSQ,7209 +jinja2/bccache.py,sha256=3Pmp4jo65M9FQuIxdxoDBbEDFwe4acDMQf77nEJfrHA,12139 +jinja2/compiler.py,sha256=Ta9W1Lit542wItAHXlDcg0sEOsFDMirCdlFPHAurg4o,66284 +jinja2/constants.py,sha256=RR1sTzNzUmKco6aZicw4JpQpJGCuPuqm1h1YmCNUEFY,1458 +jinja2/debug.py,sha256=neR7GIGGjZH3_ILJGVUYy3eLQCCaWJMXOb7o0kGInWc,8529 +jinja2/defaults.py,sha256=85B6YUUCyWPSdrSeVhcqFVuu_bHUAQXeey--FIwSeVQ,1126 +jinja2/environment.py,sha256=XDSLKc4SqNLMOwTSq3TbWEyA5WyXfuLuVD0wAVjEFwM,50629 +jinja2/exceptions.py,sha256=VjNLawcmf2ODffqVMCQK1cRmvFaUfQWF4u8ouP3QPcE,5425 +jinja2/ext.py,sha256=AtwL5O5enT_L3HR9-oBvhGyUTdGoyaqG_ICtnR_EVd4,26441 +jinja2/filters.py,sha256=_RpPgAlgIj7ExvyDzcHAC3B36cocfWK-1TEketbNeM0,41415 +jinja2/idtracking.py,sha256=J3O4VHsrbf3wzwiBc7Cro26kHb6_5kbULeIOzocchIU,9211 +jinja2/lexer.py,sha256=nUFLRKhhKmmEWkLI65nQePgcQs7qsRdjVYZETMt_v0g,30331 +jinja2/loaders.py,sha256=C-fST_dmFjgWkp0ZuCkrgICAoOsoSIF28wfAFink0oU,17666 +jinja2/meta.py,sha256=QjyYhfNRD3QCXjBJpiPl9KgkEkGXJbAkCUq4-Ur10EQ,4131 +jinja2/nativetypes.py,sha256=Ul__gtVw4xH-0qvUvnCNHedQeNDwmEuyLJztzzSPeRg,2753 +jinja2/nodes.py,sha256=Mk1oJPVgIjnQw9WOqILvcu3rLepcFZ0ahxQm2mbwDwc,31095 +jinja2/optimizer.py,sha256=gQLlMYzvQhluhzmAIFA1tXS0cwgWYOjprN-gTRcHVsc,1457 +jinja2/parser.py,sha256=fcfdqePNTNyvosIvczbytVA332qpsURvYnCGcjDHSkA,35660 +jinja2/runtime.py,sha256=0y-BRyIEZ9ltByL2Id6GpHe1oDRQAwNeQvI0SKobNMw,30618 +jinja2/sandbox.py,sha256=knayyUvXsZ-F0mk15mO2-ehK9gsw04UhB8td-iUOtLc,17127 +jinja2/tests.py,sha256=iO_Y-9Vo60zrVe1lMpSl5sKHqAxe2leZHC08OoZ8K24,4799 +jinja2/utils.py,sha256=OoVMlQe9S2-lWT6jJbTu9tDuDvGNyWUhHDcE51i5_Do,22522 +jinja2/visitor.py,sha256=DUHupl0a4PGp7nxRtZFttUzAi1ccxzqc2hzetPYUz8U,3240 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/entry_points.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/entry_points.txt new file mode 100644 index 00000000..3619483f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract [i18n] + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/top_level.txt new file mode 100644 index 00000000..7f7afbf3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/Jinja2-2.11.2.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.rst b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.rst new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/METADATA new file mode 100644 index 00000000..e4a7b90f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/METADATA @@ -0,0 +1,94 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 1.1.1 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: The Pallets Team +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Code, https://github.com/pallets/markupsafe +Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +Description-Content-Type: text/x-rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/quickstart/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + >>> # escape replaces special characters and wraps in Markup + >>> escape('') + Markup(u'<script>alert(document.cookie);</script>') + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup('Hello') + Markup('hello') + >>> escape(Markup('Hello')) + Markup('hello') + >>> # Markup is a text subclass (str on Python 3, unicode on Python 2) + >>> # methods and operators escape their arguments + >>> template = Markup("Hello %s") + >>> template % '"World"' + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +libraries that use it. In order to grow the community of contributors +and users, and allow the maintainers to devote more time to the +projects, `please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +* Website: https://palletsprojects.com/p/markupsafe/ +* Documentation: https://markupsafe.palletsprojects.com/ +* Releases: https://pypi.org/project/MarkupSafe/ +* Code: https://github.com/pallets/markupsafe +* Issue tracker: https://github.com/pallets/markupsafe/issues +* Test status: https://dev.azure.com/pallets/markupsafe/_build +* Official chat: https://discord.gg/t6rrQZH + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/RECORD new file mode 100644 index 00000000..6d958240 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/RECORD @@ -0,0 +1,16 @@ +MarkupSafe-1.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-1.1.1.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-1.1.1.dist-info/METADATA,sha256=-XXnVvCxQP2QbHutIQq_7Pk9OATy-x0NC7gN_3_SCRE,3167 +MarkupSafe-1.1.1.dist-info/RECORD,, +MarkupSafe-1.1.1.dist-info/WHEEL,sha256=RIeRBYNNiNK3sXfnenIjXDrR2Tzyz05xCMpKF2hJ1iA,111 +MarkupSafe-1.1.1.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=oTblO5f9KFM-pvnq9bB0HgElnqkJyqHnFN1Nx2NIvnY,10126 +markupsafe/__pycache__/__init__.cpython-38.pyc,, +markupsafe/__pycache__/_compat.cpython-38.pyc,, +markupsafe/__pycache__/_constants.cpython-38.pyc,, +markupsafe/__pycache__/_native.cpython-38.pyc,, +markupsafe/_compat.py,sha256=uEW1ybxEjfxIiuTbRRaJpHsPFf4yQUMMKaPgYEC5XbU,558 +markupsafe/_constants.py,sha256=zo2ajfScG-l1Sb_52EP3MlDCqO7Y1BVHUXXKRsVDRNk,4690 +markupsafe/_native.py,sha256=d-8S_zzYt2y512xYcuSxq0NeG2DUUvG80wVdTn-4KI8,1873 +markupsafe/_speedups.c,sha256=k0fzEIK3CP6MmMqeY0ob43TP90mVN0DTyn7BAl3RqSg,9884 +markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so,sha256=t037yzhfsUaStpvo6eqDVYeK-dHfWmgB4cVL9nkY2-k,48016 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL new file mode 100644 index 00000000..b1fcc33c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.36.2) +Root-Is-Purelib: false +Tag: cp38-cp38-manylinux2010_x86_64 + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/MarkupSafe-1.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/LICENSE b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/LICENSE new file mode 100644 index 00000000..91e18a62 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/LICENSE @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/METADATA new file mode 100644 index 00000000..0ef3ef0d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/METADATA @@ -0,0 +1,227 @@ +Metadata-Version: 2.1 +Name: PyNaCl +Version: 1.4.0 +Summary: Python binding to the Networking and Cryptography (NaCl) library +Home-page: https://github.com/pyca/pynacl/ +Author: The PyNaCl developers +Author-email: cryptography-dev@python.org +License: Apache License 2.0 +Platform: UNKNOWN +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Requires-Dist: six +Requires-Dist: cffi (>=1.4.1) +Provides-Extra: docs +Requires-Dist: sphinx (>=1.6.5) ; extra == 'docs' +Requires-Dist: sphinx-rtd-theme ; extra == 'docs' +Provides-Extra: tests +Requires-Dist: pytest (!=3.3.0,>=3.2.1) ; extra == 'tests' +Requires-Dist: hypothesis (>=3.27.0) ; extra == 'tests' + +=============================================== +PyNaCl: Python binding to the libsodium library +=============================================== + +.. image:: https://img.shields.io/pypi/v/pynacl.svg + :target: https://pypi.org/project/PyNaCl/ + :alt: Latest Version + +.. image:: https://travis-ci.org/pyca/pynacl.svg?branch=master + :target: https://travis-ci.org/pyca/pynacl + +.. image:: https://codecov.io/github/pyca/pynacl/coverage.svg?branch=master + :target: https://codecov.io/github/pyca/pynacl?branch=master + +.. image:: https://img.shields.io/pypi/pyversions/pynacl.svg + :target: https://pypi.org/project/PyNaCl/ + :alt: Compatible Python Versions + +PyNaCl is a Python binding to `libsodium`_, which is a fork of the +`Networking and Cryptography library`_. These libraries have a stated goal of +improving usability, security and speed. It supports Python 2.7 and 3.5+ as +well as PyPy 2.6+. + +.. _libsodium: https://github.com/jedisct1/libsodium +.. _Networking and Cryptography library: https://nacl.cr.yp.to/ + +Features +-------- + +* Digital signatures +* Secret-key encryption +* Public-key encryption +* Hashing and message authentication +* Password based key derivation and password hashing + +`Changelog`_ +------------ + +.. _Changelog: https://pynacl.readthedocs.io/en/stable/changelog/ + +Installation +============ + +Binary wheel install +-------------------- + +PyNaCl ships as a binary wheel on macOS, Windows and Linux ``manylinux1`` [#many]_ , +so all dependencies are included. Make sure you have an up-to-date pip +and run: + +.. code-block:: console + + $ pip install pynacl + +Linux source build +------------------ + +PyNaCl relies on `libsodium`_, a portable C library. A copy is bundled +with PyNaCl so to install you can run: + +.. code-block:: console + + $ pip install pynacl + +If you'd prefer to use the version of ``libsodium`` provided by your +distribution, you can disable the bundled copy during install by running: + +.. code-block:: console + + $ SODIUM_INSTALL=system pip install pynacl + +.. warning:: Usage of the legacy ``easy_install`` command provided by setuptools + is generally discouraged, and is completely unsupported in PyNaCl's case. + +.. _libsodium: https://github.com/jedisct1/libsodium + +.. [#many] `manylinux1 wheels `_ + are built on a baseline linux environment based on Centos 5.11 + and should work on most x86 and x86_64 glibc based linux environments. + +Changelog +========= + +1.4.0 (2020-05-25) +------------------ + +* Update ``libsodium`` to 1.0.18. +* **BACKWARDS INCOMPATIBLE:** We no longer distribute 32-bit ``manylinux1`` + wheels. Continuing to produce them was a maintenance burden. +* Added support for Python 3.8, and removed support for Python 3.4. +* Add low level bindings for extracting the seed and the public key + from crypto_sign_ed25519 secret key +* Add low level bindings for deterministic random generation. +* Add ``wheel`` and ``setuptools`` setup_requirements in ``setup.py`` (#485) +* Fix checks on very slow builders (#481, #495) +* Add low-level bindings to ed25519 arithmetic functions +* Update low-level blake2b state implementation +* Fix wrong short-input behavior of SealedBox.decrypt() (#517) +* Raise CryptPrefixError exception instead of InvalidkeyError when trying + to check a password against a verifier stored in a unknown format (#519) +* Add support for minimal builds of libsodium. Trying to call functions + not available in a minimal build will raise an UnavailableError + exception. To compile a minimal build of the bundled libsodium, set + the SODIUM_INSTALL_MINIMAL environment variable to any non-empty + string (e.g. ``SODIUM_INSTALL_MINIMAL=1``) for setup. + +1.3.0 2018-09-26 +---------------- + +* Added support for Python 3.7. +* Update ``libsodium`` to 1.0.16. +* Run and test all code examples in PyNaCl docs through sphinx's + doctest builder. +* Add low-level bindings for chacha20-poly1305 AEAD constructions. +* Add low-level bindings for the chacha20-poly1305 secretstream constructions. +* Add low-level bindings for ed25519ph pre-hashed signing construction. +* Add low-level bindings for constant-time increment and addition + on fixed-precision big integers represented as little-endian + byte sequences. +* Add low-level bindings for the ISO/IEC 7816-4 compatible padding API. +* Add low-level bindings for libsodium's crypto_kx... key exchange + construction. +* Set hypothesis deadline to None in tests/test_pwhash.py to avoid + incorrect test failures on slower processor architectures. GitHub + issue #370 + +1.2.1 - 2017-12-04 +------------------ + +* Update hypothesis minimum allowed version. +* Infrastructure: add proper configuration for readthedocs builder + runtime environment. + +1.2.0 - 2017-11-01 +------------------ + +* Update ``libsodium`` to 1.0.15. +* Infrastructure: add jenkins support for automatic build of + ``manylinux1`` binary wheels +* Added support for ``SealedBox`` construction. +* Added support for ``argon2i`` and ``argon2id`` password hashing constructs + and restructured high-level password hashing implementation to expose + the same interface for all hashers. +* Added support for 128 bit ``siphashx24`` variant of ``siphash24``. +* Added support for ``from_seed`` APIs for X25519 keypair generation. +* Dropped support for Python 3.3. + +1.1.2 - 2017-03-31 +------------------ + +* reorder link time library search path when using bundled + libsodium + +1.1.1 - 2017-03-15 +------------------ + +* Fixed a circular import bug in ``nacl.utils``. + +1.1.0 - 2017-03-14 +------------------ + +* Dropped support for Python 2.6. +* Added ``shared_key()`` method on ``Box``. +* You can now pass ``None`` to ``nonce`` when encrypting with ``Box`` or + ``SecretBox`` and it will automatically generate a random nonce. +* Added support for ``siphash24``. +* Added support for ``blake2b``. +* Added support for ``scrypt``. +* Update ``libsodium`` to 1.0.11. +* Default to the bundled ``libsodium`` when compiling. +* All raised exceptions are defined mixing-in + ``nacl.exceptions.CryptoError`` + +1.0.1 - 2016-01-24 +------------------ + +* Fix an issue with absolute paths that prevented the creation of wheels. + +1.0 - 2016-01-23 +---------------- + +* PyNaCl has been ported to use the new APIs available in cffi 1.0+. + Due to this change we no longer support PyPy releases older than 2.6. +* Python 3.2 support has been dropped. +* Functions to convert between Ed25519 and Curve25519 keys have been added. + +0.3.0 - 2015-03-04 +------------------ + +* The low-level API (`nacl.c.*`) has been changed to match the + upstream NaCl C/C++ conventions (as well as those of other NaCl bindings). + The order of arguments and return values has changed significantly. To + avoid silent failures, `nacl.c` has been removed, and replaced with + `nacl.bindings` (with the new argument ordering). If you have code which + calls these functions (e.g. `nacl.c.crypto_box_keypair()`), you must review + the new docstrings and update your code/imports to match the new + conventions. + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/RECORD new file mode 100644 index 00000000..cb46b478 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/RECORD @@ -0,0 +1,67 @@ +PyNaCl-1.4.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +PyNaCl-1.4.0.dist-info/LICENSE,sha256=0xdK1j5yHUydzLitQyCEiZLTFDabxGMZcgtYAskVP-k,9694 +PyNaCl-1.4.0.dist-info/METADATA,sha256=VXYKfhj8GTj_EfH7PT_oGHgxCAF7YonQtvn0ApWLbmY,8114 +PyNaCl-1.4.0.dist-info/RECORD,, +PyNaCl-1.4.0.dist-info/WHEEL,sha256=HAbUOEaMuGu1vSI8bKL7nQShDuU2XC9f79bOtOydX1A,108 +PyNaCl-1.4.0.dist-info/top_level.txt,sha256=wfdEOI_G2RIzmzsMyhpqP17HUh6Jcqi99to9aHLEslo,13 +nacl/__init__.py,sha256=F4fZFkZq5_reCDDlQb3NVH_Lc1-K3JmsAQaOnJZPzXc,1170 +nacl/__pycache__/__init__.cpython-38.pyc,, +nacl/__pycache__/encoding.cpython-38.pyc,, +nacl/__pycache__/exceptions.cpython-38.pyc,, +nacl/__pycache__/hash.cpython-38.pyc,, +nacl/__pycache__/hashlib.cpython-38.pyc,, +nacl/__pycache__/public.cpython-38.pyc,, +nacl/__pycache__/secret.cpython-38.pyc,, +nacl/__pycache__/signing.cpython-38.pyc,, +nacl/__pycache__/utils.cpython-38.pyc,, +nacl/_sodium.abi3.so,sha256=yoqlIcLJfPPPBpIaFDUQ_kricoapUJ1dzMU-00JRB1A,3270761 +nacl/bindings/__init__.py,sha256=c8Wn3gTCAZSdLMGxVnOuRChvh-8L7DrgBieAUFRqQ8Q,16883 +nacl/bindings/__pycache__/__init__.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_aead.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_box.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_core.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_generichash.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_hash.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_kx.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_pwhash.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_scalarmult.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_secretbox.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_secretstream.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_shorthash.cpython-38.pyc,, +nacl/bindings/__pycache__/crypto_sign.cpython-38.pyc,, +nacl/bindings/__pycache__/randombytes.cpython-38.pyc,, +nacl/bindings/__pycache__/sodium_core.cpython-38.pyc,, +nacl/bindings/__pycache__/utils.cpython-38.pyc,, +nacl/bindings/crypto_aead.py,sha256=DE5zdi09GeHZxvmrhHtxVuTqF61y1cs8trTGh_6uP8Q,17335 +nacl/bindings/crypto_box.py,sha256=VVBRvAACrEARLEZDHOFEp4g0meQWwWXTiCW0npPt0HU,9958 +nacl/bindings/crypto_core.py,sha256=7zOeRHS2oBWwI_KB1E4-sRq_ITZGWSUqxI0aT-evPGw,13433 +nacl/bindings/crypto_generichash.py,sha256=a0h-yxZR8fD7AkzaTcXj48pgFrCKVa7Mmer1wj8Az2A,8949 +nacl/bindings/crypto_hash.py,sha256=7Xp4mpXr4cpn-hAOU66KlYVUCVHP6deT0v_eW4UZZXo,2243 +nacl/bindings/crypto_kx.py,sha256=2Gjxu5c7IKAwW2MOJa9zEn1EgpIVQ0tbZQs33REZb38,6937 +nacl/bindings/crypto_pwhash.py,sha256=TH-oXgrzwnNnBCNR_iPw7TtakVBzmW1kIkJciF8MVdM,18696 +nacl/bindings/crypto_scalarmult.py,sha256=8w9CIMSar2eGR2nwmqQlQdN3z_o7L-P4unGnm9gwkVU,8208 +nacl/bindings/crypto_secretbox.py,sha256=luvzB3lwBwXxKm63e9nA2neGtOXeeG8R9SyWEckIqdI,2864 +nacl/bindings/crypto_secretstream.py,sha256=FLICuAI6kRM5qNIZbDetZVzLV-7y2dv5Vd1LTpUEhmo,10475 +nacl/bindings/crypto_shorthash.py,sha256=PK_h7X2WH_QRKJoSHbsQdhc19TIpFFqXy_wkzRPvpnY,2587 +nacl/bindings/crypto_sign.py,sha256=bQc_2VQ4CGttdi9s1hvD5PcqPXFo4ca44dRG-W2kRkc,10617 +nacl/bindings/randombytes.py,sha256=r93-dAfODRnXAUacx9MXsop-WVZ5xMJJB3xyPkHjQr4,1597 +nacl/bindings/sodium_core.py,sha256=52z0K7y6Ge6IlXcysWDVN7UdYcTOij6v0Cb0OLo8_Qc,1079 +nacl/bindings/utils.py,sha256=jOKsDbsjxN9v_HI8DOib72chyU3byqbynXxbiV909-g,4420 +nacl/encoding.py,sha256=tOiyIQVVpGU6A4Lzr0tMuqomhc_Aj0V_c1t56a-ZtPw,1928 +nacl/exceptions.py,sha256=6-hSnpjbUREnrmI1tZT2XqOBterZ0qoBsMvhCm1W5KQ,2128 +nacl/hash.py,sha256=83tVxKjG_DAZUsHKaKl-_kli7K0wNrV20cZxm4vY620,6164 +nacl/hashlib.py,sha256=R2uAL8lfdm_wGwEUcNI92YLyUcFKz9568xZFus7Msps,4197 +nacl/public.py,sha256=-nwQof5ov-wSSdvvoXh-FavTtjfpRnYykZkatNKyLd0,13442 +nacl/pwhash/__init__.py,sha256=_GxfRAjUCQlztdDHOUBbDINC3aJPIha8I-j3HIZE7eU,2720 +nacl/pwhash/__pycache__/__init__.cpython-38.pyc,, +nacl/pwhash/__pycache__/_argon2.cpython-38.pyc,, +nacl/pwhash/__pycache__/argon2i.cpython-38.pyc,, +nacl/pwhash/__pycache__/argon2id.cpython-38.pyc,, +nacl/pwhash/__pycache__/scrypt.cpython-38.pyc,, +nacl/pwhash/_argon2.py,sha256=Eu3-juLws3_v1gNy5aeSVPEwuRVFdGOrfeF0wPH9VHA,1878 +nacl/pwhash/argon2i.py,sha256=EpheK0UHJvZYca_EMhhOcX5GXaOr0xCjFDTIgmSCSDo,4598 +nacl/pwhash/argon2id.py,sha256=IqNm5RQNEd1Z9F-bEWT-_Y9noU26QoTR5YdWONg1uuI,4610 +nacl/pwhash/scrypt.py,sha256=mpx0A2ocNkUiHVMy1qiW4UfSyI3RKxLraqkMXjbg6NI,6731 +nacl/secret.py,sha256=jf4WuUjnnXTekZ2elGgQozZl6zGzxGY_0Nw0fwehUlg,5430 +nacl/signing.py,sha256=jtPBhqfiY6JOZ-HlllRjIQ-8w3a0PFe1AyKVRBLlesg,7339 +nacl/utils.py,sha256=2rL0bIijNgEe7DOMk1-ClaZfoJCQ1NqkksrXP7bDWYU,2166 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/WHEEL new file mode 100644 index 00000000..b3b8cbbb --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: false +Tag: cp35-abi3-manylinux1_x86_64 + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/top_level.txt new file mode 100644 index 00000000..f52507f0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyNaCl-1.4.0.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_sodium +nacl diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/LICENSE b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/LICENSE new file mode 100644 index 00000000..3d82c281 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2017-2020 Ingy döt Net +Copyright (c) 2006-2016 Kirill Simonov + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/METADATA new file mode 100644 index 00000000..a70dd202 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/METADATA @@ -0,0 +1,41 @@ +Metadata-Version: 2.1 +Name: PyYAML +Version: 5.3.1 +Summary: YAML parser and emitter for Python +Home-page: https://github.com/yaml/pyyaml +Author: Kirill Simonov +Author-email: xi@resolvent.net +License: MIT +Download-URL: https://pypi.org/project/PyYAML/ +Platform: Any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Cython +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* + +YAML is a data serialization format designed for human readability +and interaction with scripting languages. PyYAML is a YAML parser +and emitter for Python. + +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle +support, capable extension API, and sensible error messages. PyYAML +supports standard YAML tags and provides Python-specific tags that +allow to represent an arbitrary Python object. + +PyYAML is applicable for a broad range of tasks from complex +configuration files to object serialization and persistence. + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/RECORD new file mode 100644 index 00000000..cae61d97 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/RECORD @@ -0,0 +1,40 @@ +PyYAML-5.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +PyYAML-5.3.1.dist-info/LICENSE,sha256=xAESRJ8lS5dTBFklJIMT6ScO-jbSJrItgtTMbEPFfyk,1101 +PyYAML-5.3.1.dist-info/METADATA,sha256=xTsZFjd8T4M-5rC2M3BHgx_KTTpEPy5vFDIXrbzRXPQ,1758 +PyYAML-5.3.1.dist-info/RECORD,, +PyYAML-5.3.1.dist-info/WHEEL,sha256=TpFVeXF_cAlV118WSIPWtjqW7nPvzoOw-49FmS3fDKQ,103 +PyYAML-5.3.1.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11 +yaml/__init__.py,sha256=XFUNbKTg4afAd0BETjGQ1mKQ97_g5jbE1C0WoKc74dc,13170 +yaml/__pycache__/__init__.cpython-38.pyc,, +yaml/__pycache__/composer.cpython-38.pyc,, +yaml/__pycache__/constructor.cpython-38.pyc,, +yaml/__pycache__/cyaml.cpython-38.pyc,, +yaml/__pycache__/dumper.cpython-38.pyc,, +yaml/__pycache__/emitter.cpython-38.pyc,, +yaml/__pycache__/error.cpython-38.pyc,, +yaml/__pycache__/events.cpython-38.pyc,, +yaml/__pycache__/loader.cpython-38.pyc,, +yaml/__pycache__/nodes.cpython-38.pyc,, +yaml/__pycache__/parser.cpython-38.pyc,, +yaml/__pycache__/reader.cpython-38.pyc,, +yaml/__pycache__/representer.cpython-38.pyc,, +yaml/__pycache__/resolver.cpython-38.pyc,, +yaml/__pycache__/scanner.cpython-38.pyc,, +yaml/__pycache__/serializer.cpython-38.pyc,, +yaml/__pycache__/tokens.cpython-38.pyc,, +yaml/composer.py,sha256=_Ko30Wr6eDWUeUpauUGT3Lcg9QPBnOPVlTnIMRGJ9FM,4883 +yaml/constructor.py,sha256=O3Uaf0_J_5GQBoeI9ZNhpJAhtdagr_X2HzDgGbZOMnw,28627 +yaml/cyaml.py,sha256=LiMkvchNonfoy1F6ec9L2BiUz3r0bwF4hympASJX1Ic,3846 +yaml/dumper.py,sha256=PLctZlYwZLp7XmeUdwRuv4nYOZ2UBnDIUy8-lKfLF-o,2837 +yaml/emitter.py,sha256=jghtaU7eFwg31bG0B7RZea_29Adi9CKmXq_QjgQpCkQ,43006 +yaml/error.py,sha256=Ah9z-toHJUbE9j-M8YpxgSRM5CgLCcwVzJgLLRF2Fxo,2533 +yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445 +yaml/loader.py,sha256=UVa-zIqmkFSCIYq_PgSGm4NSJttHY2Rf_zQ4_b1fHN0,2061 +yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440 +yaml/parser.py,sha256=ilWp5vvgoHFGzvOZDItFoGjD6D42nhlZrZyjAwa0oJo,25495 +yaml/reader.py,sha256=0dmzirOiDG4Xo41RnuQS7K9rkY3xjHiVasfDMNTqCNw,6794 +yaml/representer.py,sha256=82UM3ZxUQKqsKAF4ltWOxCS6jGPIFtXpGs7mvqyv4Xs,14184 +yaml/resolver.py,sha256=DJCjpQr8YQCEYYjKEYqTl0GrsZil2H4aFOI9b0Oe-U4,8970 +yaml/scanner.py,sha256=KeQIKGNlSyPE8QDwionHxy9CgbqE5teJEz05FR9-nAg,51277 +yaml/serializer.py,sha256=ChuFgmhU01hj4xgI8GaKv6vfM2Bujwa9i7d2FAHj7cA,4165 +yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/WHEEL new file mode 100644 index 00000000..d193dea9 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: false +Tag: cp38-cp38-linux_x86_64 + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/top_level.txt new file mode 100644 index 00000000..e6475e91 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/PyYAML-5.3.1.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_yaml +yaml diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_cffi_backend.cpython-38-x86_64-linux-gnu.so b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/_cffi_backend.cpython-38-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..297c22e69ccbaa0d47386c02711d4ce45df5959f GIT binary patch literal 893296 zcmeFad3+Q_8b91QMgoF8A}rC>WyGlQo~T(9B|3owdT=7c9XT|LV!WfyXaI%5NtU#| zOQ@82)%XEXi% zcJ)(LPd)Y2Q%ARpD+A-Qv$8bjUygRZMyPHfXMEy@`>Vm?O4EE=i8c^_kJpZ2XSI=_^b{!yJMzZy}V zns-JK4a|Ri=Q5~uT+V-;at;6_8UO1!C$*E0Q%)y8t!4;M;yte4Z|CtGI=`BDkmS(+ zTN?RuEz|gO&Tj#KOmluIE&U^HFnz{Fel;RL=a&-DKk+Nn)TbBie>_)rIDgFfb;?B#`qw$6#rYiP zu$Gjpe+ucw|KU=8hF?33^Xuf75%Ry%<@6=#|12TSI49D0LWg&LoyU1v{@3CD+i$i; zIcCyjuAJ1I$&`!uU#49hONJLeaj^L)PBc|Nt` zT%*Hlf{!SC^M$-lO$xtJ@NtFL0zCaPh4%@*S>fNA&C{<`_)i7jsqnv_!qeLdpAzY{ zcSo@bI`!Hs_QUay40@0!f{ zjS8OZozvL-Xr)Dg)bC*P~nRNU#svZitnZlnd_*R7< zEBFqDA0zmr!UqK3qwp6B-u+&GJxmjPp~6oUyiegT5q!16&k=l`!e1x&CWXIN@XZRp zQ1B}ieu3aS75*;4+X`@STF+sPOLzzDwah6@1?N{q^vP;5`ceh2TpRewW~b3cpkEO$zVWe_Y`m z|F%rw9skp;@Q(j!QFzB6wko{imsTpg<0lge@A#_@g?IdCr@}jaY@@68|CUgA$G>$byyM?G72ff08x`L1Z%KuB{F|-t zj(_V?c*kG$D7@pZwEy(C|Gx2E;hpi_t?H zQ~UhC*DFuqKNE7?3h&g{qwwE|^o0r^?4~!lG|i{*t(Wq884CY`kP}q+{erJi_}tlC zPOZXw5Ab{=3V+5Vp1w)pM+iA_g?GxcOyQmKBoy9}-=Xj)3i+K1Uo7~f!aH(og&!x< zYg_ua_!{euT0-Fu6Z+{;_^vjdzEk0w*K>ZO z!bfi4<@9XrU*Bg%zbjODEy3-iMBzR4T#irSe-`yJ6h8SNms73qk)>Qtjl#Pw;e4&a zcRkGORj=@#I-WkF@UP9}e3Qa={>00(OyLtkKg|k1LfAu#!Z#1)@>eQ+WHILx3hx&6 z>QMN|W1_uO{yHuvsqpzij;-+C54oHkh4);~{UI`_2r`=PA5r5!X+?!q?ow z(|Z(tq$p3J!uyu;@{}liGQ{Qh6n>7dLqp+fR&zPk3ZJ-%%c)WLH$=T^6~3#U*Q;LP zwcEIyh{B&D>eZz1o)j<7GKEjh<8qo6zF5d;N#TPVd3ly8yyr?Tr&-~z7IIn?zHT8e&q{^Ynz)>V!hbZK^BoG`HHFLBsPNhy zJbhB(>m2)0c<(wcr$^zFzvFT=F)wlK=T1?cJcSQl#O35Gyta_bsaE*gM0x5IKJkdq zv%*IjIp3-9t*;9`D7>~))Jx@`=5h+Z8pST0dO730t?)iKm(!*2+5jP6;e$gtuZg(B zk?%W{^LYwiGmP_Yh4&2Pe7?eW9>#f(!UtWPFI4#@yuMzAZym_?&R&%~i;k|8KPQAkWe&&2c;p2C5zDeN| z_i#S0@R48fe3vP_`%}(0D|}=F=UWusy`J-}3h(`r=ettnU*~*6;nQNA?NIon7>|+) zzgNt2ZG~^$#pP??^tb=>r*M17Q+Vwsp5CMIQ$+egh4+c{K8626^mjwyYld+B)F}K_ zqWrZA-~2f*PekFTi}Xzj-@J*ZZ&vv49RIBFU4P-_Nhtio)m%Rv3Lkucr%x*UH6os| z6~6N-o?f&2>;FAxTvqrxjpyr8cqhIsRQNj4uYC&d#MOqvH~%Q~ukg;ipjP4IVqOqY zcxSw8Quxj-LjMZyj7KdB-}($spHTP<#Q5H!@V@7T{uRDO^cP# zQ+Ow?GZfy5>uMDKbVvUR-+33;PekEM9sMi3N2G67c(+(zYEk&+$A$hC{!C$?9SYxU z@$^ZBj|aHluoXTj{J$sNU;i6Ke<@V>uK#fPK80T`;y^>;Jt8ixQTT_1f2&n^-yUuc z5rx0p(Wk9u z3ja?br(WTm{gH^m2U~f);tKz+kkhR2y9M8(@SY}a4=WXZn@HcG@P8A2vQy!cFYxjt z75+ydr%U1gEadbkeDZlNC$Fo2`yO7y+a+J&tA!ko!n=i@y$XMVkmFPMdxRWA;p3t_ z)e2uKPhh4%?LEebzX$Vn=EM4aoh6+ZEAuIDa= z*GjoPXy5hMe?*Lf9+emJOBB9Y*r!k76Jow;D7^PsUY?-BN6z8pS*G%$zO4!${3DlB zvZsIf|02={72cQ2<##H4XMo$=Muqp>!R33t?=Rok?`~1})&o5KMuo2v^1Bq?`#YY# zzPrDCQ_PRz3h#THr_bNpKYhG~^M=BEw(@k<3h(TfG%39MelBO3!uwtp`HJ%b&brEl zqQ83;zNVR{uU7b0v5sUbyb}+t6#My({8pj2PKDQm-Xi<@>%m>g+qe3s{`|GV9_kdn za}6(Ni^4m0->UFVe@iO7(|@`YzPTxzWzeJWanX-7ao)kHZ?J)vCr{yh|KxnV!h5!I zzDMEzDeCL~xxXHKVm@A?@JW$xT;ZL5u}tAL(Jz`6J|W~JRbHGAS$3d*c{Yf0wkmwh zXS`k;6~5EQ+t=IMUyf7G5{37Pe&JL2)^%KdMB$zDDkb9FiqkGTMLB~C-}SL*7nK)r zW?bQ&xU*B?o$`Bxo}7FgKeJKc54nunRhPoYh5qxik7EUM!6@DP0@S12xTj8C! zxkuqO5m)7Z#QTMttEKO6q2LbzliSB?npfiKp7XCn;+;CvJ)gvjR}|PIhQy0c1T#J; z@xvIy|5Qu-uOz-k;zvk)t;GLE;_D>-M2WAL_%kFvBJm{>-z4#+5+9fN^CfzC+?CNqnco&y@I$5~8P}ZVxmX2p7rtuI~TN z$3@(zruT|CP~|&C+@KJ#A& zz=IpP-YCx@lAJt=KTP7?5-*Qo`4T@=O7D^QBP701;)hGTSK{*}zC_}Wlz5-SA0_dI z#Q$32gA#wV#8*rFF%n-R@gpU^R^mMpUnlX$N_@S}-4cI}#OF)A_)k-?yB>)@PfA}X@uMZ) zEAeF#Un21rNW4$teG+d-{8)((N_?fnS4;eOiLa4(zr@!{`~-=wllTiIzFy+1Bt9bX z7fF1R#0MolF7cBkewoBik@#kbpDOV!5M0TjDR1(sxPxJ|Xd9 zs?6?oNPI*}-zo7?iQg#k4HBP}_(qAhCH{93-zD))65k{7zn6GzQ^x*d5}zmWcT2om z;{PD=`4S(Oc#p*YQQ`|F{vL_rJ691UQH%t8E65k^6PfC2N z#6KnRD<%GK5}%Ox7K!hW_@^blQ{tbK_>B_(yu>FZ{soD*C4RZYcS(G!#P>-2ixRJW zma+erBtB2#{~_^iiT|g>=S%zwiT6nSc8M>P_?IQ#EAcBOzC_|*k$9iPzbf&D#J?u- zL5Y7|;;SY8UlLy<@oz|ct;D}6@pTfPkobCuUoG(wiC-h}O%lIO;^PwEF7eAGzC+@h zCH^gmZ;|-7CB9YS-;wy0692BmCnWyg65k>5?@4^8#CJ;kMu~r4;*%1;LE>$R|Bu9X zN&E*A-y`uKO1!o?WB(sXe4fN_lz6wqe=70$62D2}Jre(!#1~5ZW{LMo{O1y1BJo=! z-Y4-%i8myEtIS7tCJ^@PtN+{*AO!eV7m_Az`H;qwT48NQS7Xu=+b7Z5HZ z>}L38!sip#7`}$^1%$hPV(m}ZM>xswOv2@aI~kr#cnskL!xIRPCEUvJ7{V2Vn;AZr za3$e5!)Fp6M>xXp$%Mxfu48x)H0*v;^6!WR+N7~W2JBH^xmto;cG2`3r;l<*|NoeXavJehEU;q`>45N>6772&Cb zn;CwU@HE14hF>B)op6NVX9&+AT*vTZgsTbHF#I6liwOrAzK8Hk!aj!YB0P(*m*G1J z&nE0)cmd%#gxw6^O!yMQ8pGERzLap+kF5O(*APxJJd^NcggY6YO!#ub35F*So=dou z;W31-Al%IGxrDDI9B24U!t)467(SWsRfOvp9z~c2pi~XRM-jf7aFF4lgs&m&V|WnZ zYYBT9&L(^vVGqOm<^o?&*v;^6!Z#4s7~W3!M#5b^to;es5l%AvDdC$4cQU+z@Xdr1 z46i4A3*lCVR}l^oZf5vZ!ePR3hF>ClE8z&k&k(+ia2>;s5w0g(!|;QI=MxSxd=KFT zgnbO(MR*}$FT-~dzMZg#;RS^6Ana!NX2OdIYYbmQcroFwy{!ESM+hewo=JEK;ZBAp z6TXvhg5e2-ql8--9z(c+a5KZ_5^f|MXZTFQzat!B_+-LM3D+?^if|L*8itP|Y!VJK zJe2TVgnbMTB5V=%GMr8L_k=wR@4Fm0M%c~pZo+pH))?MS_z#4;x>@@ZjuTEY{3+o- z67FPp1L1oJCm3E&_)mme8D2&BUc$``ze@N%!f}RQBK&8<5r&^3d_Unjh94umjBpLZ z4-$TWaFF492tP>J$M9W*A0q5!_)fxqA?#sz0pY(Ab~Ai4;fD!p3|~X|5yD+Ru=Xe1 zOgPE#Ou~;6?qql};l~Ik7@k1*al)+(k0Ja7;bw-w-a7Y zxa)h?{)AfzCxH#b%ZBB;Z`LTyXiS8%dplX+JWn4e^~ zi1r+ITlSpQc33M*2_gV(B;F$4TGTlVg~xjJE9;7+Iah`#oXy@bLRt zt{XzT=NRU?-fi@Jr0fAar-e^6qGd~Q8zRiFLW3#)>QS1#86llri)zeS=c+@(tUase z(ZAFC${Q^!4C1lS2`JnMQLCe-;rXGUA*;7@PHF}O=p!Rkztn}e&O9DBtnv8}nUQBL z_84ZD(b$VZm>*Fk*>gpS)%wT^O)H=3H$Olbf0$yJKN;5Id`dZxQhwN&2p?-$3q3^% z;(j&DFztZ(^_=qAy~&LHS-}1C8}BvD?+mLxkDkgSNn7=i+W*S06@{(pF&z-G@l6@cvVxqI|e6FCF$h)-+m z-E>_+-lAU@B|dQlk>@9E(L`2h&&IbtS--L4^X=hpH*X{p?`t1@#ejJ^J%gEs@=mz6iP3AmEe`CPa2{N12D?dW_ zl@!w|si}w92BL;;N@q4L{m(MA` zr2Nv=aU#u)5<|U3YG2gP-90Ag3H{2j#u#wP^)6;7@Jofbz_JGS*VCvs72oi17MNAl zhE-COuqj?N+7px|bK=Y&v-IQhx+64%m5AJ}CkjrJW%!uAf}QuM2Sf z+q?fjJcsvMs$HMEBtG6n)(X99cPm+FqSH2Z4)_V~r0!t>?m@|E7CQ1YUf{+mH}* zy-PoOMNeulOX|~F+_?Gr2U%KpM~erSYv^)o_nK^6KZC^K4_kb=e1b05w~(Yie}>C9 zyVqpldd_=HYD`E?xAfTqnaZnKP@Op%w(|9xD2iq;#lT7pxq4ol{QvhDUT)|$8h6qd zpx;ezWEb@oC73_cUp{+m>~5`4)8;Mtu{YkCp}0hrQEG=b z!20!uHe?YnlW+9)x-~Z5w%grQ%N0RS_bQLxNUUxD-NyZ9h5qv33ys*Y zftC8pZI!XOR@mEHzGPo7I?-)ojndQ|=Og1Ivh|mDFWIGirfEwKuv>-YW@q`5t#oZf z+p@}+B3v3l5#VMMq2&>lag zu7dF~yE8vW2YNFbWu=sgb<-s+0cO|C*k)3H*_@FkiIJan1wh(gS_|#Xb~#`s0j!nD3K2Got&l^hTN` zkmE8}MYkOt*_RtSHnJ}-G`htT@{;$MVT5a}Z1WJ?1vujkGB@-U4(HRDj0ZF2rTgji5{?y*X-AV#Gnwzf>CZwtWgIES7aAYN z!M29qw1E3=^v~gI>-jbL_akrP*W}-?5A$pC?~h)~uEV1ZYdXfDN$${ONJ2oH2wiPN zOSDCIAkk;HQlem9xX!SAg+^3^SHMDhpFZI0f4m4uV#O=*Wf}N-`x)3>UylOg`h?%V za~V~`8M_*GQ>ye!xc^6f{~5ZE=dWSUr3;J-`82=zVfoZ)Qw(bn z!iYWgA=EXaJ+QE~dIQZZ$uR6LG6}GLbB*4xhq10Tlv(LmxYbud1WLcs|3Gh~`K@to zD;R{o4IdNT=GGg^i9BhC-@IO{GOx^Y25`hHJN2gVxasuTOZ=rDEV|qvvvMuwHA$e@ zaE5%~d+0k>(Kkf@v^P;v8xwlN#WZYNuCsW7kR{E@;nzg)AmU@cbx|St-$$W-PwE;x z1iD^S-8PA8I&bz!9NS5oGy{=vr9v&)MM>DByA` zAUAEdqJQ`-1pR~UHQ)61BC;Ngm`{w4Yux=COXw>${3Pm!vEps$Icz*cO~;|a{5ja{ z+|P}+FI=cZt&wvndiCuHw?hT6<8OMW!=oE%^gkhCk_&Ce$FMp=HDJb`3x)ohhOQl2n+1OiuguMbfB@T>Z7gL~@bQn0t*_00oT|hww;I!fz(+*U?+yFsiNGf|fiA zVyChMjU&i(?rA0qGS6&rhcOA9GK;o&oE+Dt$|o&f@1&jsbnK1_DB@YTve24+@Lqm3Rl3oveh38 z6;zWDGu&*y0VM>iO4MXsz-$kgl`ZzOpe~Ay_WI{y>SI{pX1}@CADcMRh;HpNPI||P z%`VW5=oeiu40|Hf>Yp1Zmz+H1Ua?PzaPFiIj zjT-^;06qOa^~~6n8)rGQg*k{X;nFZVnLn{P!DRTrh1X#jq#G51X~V9qDHywQvJC6O ze8a5v7}m`Qw0Ve&pFjQ{ zzLJ6}`oA0>(0uB>^68c4I!vj|cPaeck5WB}aRg1lr&b2cH_x8T%ZTo$H>9Zve z%v!WAEPP&tSvx9V*5~7*&Vxn|HjOQy#?K>*u%D!cKyQA28!Ae(F~j^682;RTkmOnr zQEsm77bS$wGpwAxAmfOTud;DxeTbey-?rzHB*fU~!|tIfc?w2xslDe55-U9)h8=CO zKLed!A&tM3v;8ahR$9=qT%!%9yu0z)P43@cL-C3>r5_OXOvVQlp_|jd9KAr(n`o`L zXp^`fU7cmj{mCC4yjkhyC1F?1}IefAo4SE9BuLEq7YzQ_%Vv%w%mr%!>!$Eb>q%jI|$OlCmjn^^gB( zDE*;)Y9LndA&RL@gV!|7pNo2_{Q367q(tsg7a{WZU{nj3yX+ZgEx4YfnCqJ$7LpNZK{l3qaXXiUt%#)zJh6~_A87CV3v zuz7@42^m4ugGKVwwD7C&gR~%%XBRS~VW!k4*YO{a!4u^;iBebdLDU)F%6|MSde|D) z!gERtQY%*OQq^n_MEQ5*zk%Ui^EKUGfT#(7>?Ue8nhvt@Z(=@`soT)~>x|O%hJMj{ zqqM^?|83|K+l-Ue89504&Gyt3JcRV$Mte^4zwgV1$JjLJN-GHKDeI!aTbv@6yFjtHMXH|)*u`A2iVJ5QgH zC`!O0v0S5{KGv;2n9wV1YJGC5h^MSu+}3nV6!P?j!{8#8pxU{b-bfpim_7N>!}6m& zxuHv=J$ZVg4R*Kg9@JlI2N#-tn*4{krD&(U4kc(z`1JeMQckl>yDv^NtUDtl8ddH@ zl~Z}lE%~rk?H;7hd@KE=V~^T zcfXRQ{R@)OpGxc$3X>Wn@hiM=IvvksToXD#n4pvT4*VoY&*5-bJkzEwQrtXkcT^>Q>5Nx z_edX9f0iB_5UCbMJN?CVwU5UG0)d*icw@}a`6f{1?UhpZZ4P%Ox zHC+IA_cnxCN0?-}+N{;MKeO+CE!}^X?nmgZnS=YxQJjM$Q4L`s&5Zl|lPUI5ea{!t z^Vj0}cC5LfP3NwppINDVsr(ekx_(%JqQ{0r5Nq&omiKZ5txI;~GiweN)EZcaufukc zVKx**AjgQ^ThPUR8w#+Brv+laFK7l1#Kisfh5}YAN&_EQO#%#hDoKpxdjEXr4T+io znJwTx);R7h=%o9&(TZRCN7o5<#joi;{UfPC`s1TNUi#yqKZpSN!;~XD-@WW5dwMnHl#{0Jy z)C3SI*G!BR{B~mO)U*9XnV`e@p<+SA7f@^4zQp9OlZFr7D=;!dV3~rW&De6IVrBm z)ik~^wqy-;5@#ZhT^PfHBB0+I{MMLJI*egh|KN5_qf?UU_y%_o7UXv>Ii{hv-8~x_1}xsQ0@xI*sVv%56+3nNytv<5K>jj6U|r>wR9sjUt0?G|^!yXk zGqbFYaE`ZvYltR-6Vk#4ZwupQ>_Z!c$uN6XvG^HIiL{2ncSJy4ET zMIGWPTm;OGup8KkKNdJ7KYc+Q`4m*>D;6A&b}uX^Q%~ks4D2DQSNt9Torh~ zWNu>5E8UFob7E}v(Y^lYsyu(Rt+1+eJJ$6MkforZ1LiHY=CgEi22GFUOYUx1r}{Tl z&8l%<7(4X}qwOmkR`}Mw99|eVS?@wz`!hA2VPaa+Zr=}+!`=(`5dn1IBzqp64+6en z>p^}*XXrC1#yV6kh^}EA8;I2wqDNAz!5^##bsYOUiur?bb9xt27Jxn;_o>w=$%*Xm z3039|wv+68`&ZZ&^~Wk)S$=a|kH7TWFyau@u)=(t91*HlPt_w2%Bn~4H&w67{L1kP z4H&gq?XW=Ffpd~%maJ~CK{V|v1p{zvBmv77U*Sh9dW+&^zcqCrYb|}n&AhLF&H8#5 zaPL6+i?xiYRa)EEc>}x5iYm-`+wzRkAH(Ym^VtZ*pp0~Qh{{Kf9AyY$LlF~(J2$ct z=?&vi90Q$!-Hv8s_VuS$dcus-_(&D4HP|e&0^=PX#}*pRDTy|t36TUNVYCC+SZv#m zV~}vlJRTrRhe42q=hJVcdGXPeX1OPIBsFlth`!E;HN9ai9>XZOsRW}SN)sW$vEr!> zEb75nvjOgj$2|`rrM>z;4*WfTaQitd?AQ}!57>`?fGFxZ+*0BJjOzyC0E*ga5$Yoh zX#aW*k3@I)ko)n-J%B|vPXPTLK41Lt(3RH!hf$S{d~2XR=mM=q99#%IYuWTx%9~c; z%+FEc8k86cLvVxjgIL*%7~kRH%ysto4OCTmO%yI}jSnk7h-cRLXbs5G9|BLxJI`Lt zp5c)gQabl(`e83cM%LI8l;<#n;$GUcbJ>%j0B3&&dnL4)N85V8!BwHyv$>IE($wr3kkj$sWMNiCkBL#iV}RE{8Eaqc+D%Ik_bk4Zg3yHM+%n>?i^Imz=VoqdqYp4dM};LG=AI?RyBL> z`*;LtND0#Uo<4g#i<%C`4~N49IeLo~FU2RKSy=Al9wsw?Uk<`a7e%a&@k6X9|C7&g zYVasmSiWIywYQ+IXy^+KD;H~()iCT$v@Kmv&FH08vhQG)guCb_R;|aLgHmH^brR|` zlj=jBiY<0Y?TYmxR7sS>PLn=qC2O_a`XN=RY`(=5@$qxi7+C4}1YLO=Mj$lv-{Ux^ zQ;xl+*zgn2MJhx~E2;fnp$P?gcB+ax68`n=fA*!{Q_9j;7A5);dytrfSraMbfYa#0 zU4s^<+f%u?$JR?|{zgmg#Wg4o-QH$*pwduFL3DJ%2z@EVa2A=5D~<`MF?U!TXLF=; zb5#G#`aR6Tgq8I5XZu;+&MXPpd93VW+)ravji641KY@2if1JU7!tEKHLP(o_IfLIK z{I?7?3E!W=R})^E!KJ{d5XJ^p-&k1+`KPYP;8zGw&EN+JS7h+jgwM`kKjDH5K8f(K z3?4{0H-p((*zYkovHa1`&qPaEC8@2T;;8>yu-eoI&iz=~1BBOP@ci$9|B=BL)BPth zxRmg{8GIz+1_xWNq9T@`-S%&?u~YzeB>RDz$ZLd!h6*}q0=AJ3P$g+dXrJ5VAXK<9D=&kZsroVZ}{`5%h=gr;Gb$NlT4c5@c4dr^p z`#5fr)mi#uNRJ*k<5ny(ukuF|dFie3Jy_wC*Sq@W!_gh^K(2o^q3kp}`+#z$sFh-u z-G+X$YZY$o)-QJL{sLC{+OyB_f4FsO7Yjqp;%0hSU*1LMJ@L8M0?xG3L86*Mq55Heo z^d%15(F6_SUk6wO)LC!$_Ewm->1v{Z$0|M?rL8cN(0K6)xJ*3`Lql;-p>opbxUDF` z#n?+RTwnt+=UNZ-rv8`*&6dZ%NNAbl1B^aIFpNI?B39! z>?Ca*=e@#*vO_<7e8jpE_A~2Q63nD=*tUOsrkwA6vjw#!aeYU8#~IdZtqzIZ5_ayl z2qX(uDWyYVwS6J>i0SFW<-@=%&JZIzJ5P-BWVDl(IZr$Y1uO6U00RkZoF9S$wTn~7 zPyofn4ux1WL=sT~&KPIpO8y_Be_;C!_G52}=3b2e9Fv+cG$vzwv0U-f&_1!^=dfyw z2IkvZUoz7^B?}Q9M#{{1g@MjqNe#@|c=SM4=#=Pz?9l1a1G%B1=z+Wtonva8pQQ!u z_ukEnw-!JDiu0@(`h1%HGXDkLuRXiRPs$3Nj6+z38pdtQ_2sG5GqfycyaaVP6_-;! zT+sO!*J->8hfo!;gn0t$3KgM@>Uv!F_@Fm5h*lSw2)2HQ=XX*zvEoV|SJ_{qhX4I} zan{B)1L?(C%8RG*Yl@(rpTe(cohoZGzoxS`#Rj_$yYalcUwwG_|9J}TV_*GoUjBLi zJAX>w*j+!vIPbRnJ0@WvweP6s(Kwyy&I%9LS4{Sxg6^habTpiFKTxJ!|=lpt> z4+4w*=)%msab?A!i&uD>-M8_weA+Hjr2h^%IDsL~zT*%E`kJ%u9y%RcVCELR;X;H1 zcK14p5cH;t03aAWbPE}L>cCnj&Ts6-3P%lJH>as}!x!jNeygD%!ul3G`Ubi%vFwfG zI|e`H$`aB#6=tOcdEIyN-HrxY?comT61YIWH5e_yb{qW&Yq1%E2WVHAO=I?>1T1V! z(IlDn!;9ZPiP~mw=n8u|>=m63r~7cqFE-pG8umO~heX4kf$NS*ykW6FH~eUN%K(Nj z0@uND>{@R;1;udU3u`R)Z-Uq@_!UUX&-E7N7b~7C+Ij(WCF)12Vva!?e+8BLVhzbe zJG!>==byQix6irsJn5M0NPXTKelbr!i1H&H7}mMAiyorrIrT0L_i}za@>n0lJZ-V3 zsM}shDG}{q-;TwyWK9&O!A`i`cOK*AcnO-#*c%-61`$7Ud3Zl#v4?L-77CGP^@)`7 zw_KNTx%EQsOjYi?{o-5n2b4DwV)9Ymx2b_qUh;8d)2X{K4E2+r#pRC_^7lcpnR1gq z$;jj7trsFsazvg3k$vs!da;nT=N&I{Jv`G-9@FJftnOHMgW6`eQ~BuK&U{Vyuj{#t z`>=0D{%c-F1{k6(cA-5x{Z07E}DlHzs(G?D>NMjIdUR5&I!1_ zrHWslkL$mU<=1BhEFVID*EuIr4W`h{@*iP7-m^p7Th=>A%9xA5sj_&$x)EW)wbdBl zt72DHW302UMsuRqObe8zakkuYrA{De#W#mY(pFkRW5VwFg)kBC7V-3-B7I-tE0LHE z0g;_O!0&IrB@0LKk}MbzA}{!b$TvAqxH#SR46_M}b>nrSd7F$qp+d8G<>jmdT zBh7d=%RcW-aCB(PDE&`p2!$ILgJH8=$34=!6;3>0KZ^!1VyA`h5<|JU#(te(>1lTW z;#5s|Qo7!WXJ>jaSYpVUfTIwb=x7vHr{Ofmi1>I6J9(}*(0{K8TAvC5_Kno>QG%u9 zu<$#Qgj;1LxW_%i`FQyPr{i=GM(OtOgSh!?dhoY+&?@W1%M|vtFhEwvwV{yx!W#_W zxS8JY7^w>9yRb%M|B8D=ECT2a^eQO2&kKL0?yw3g4WfWPR=|K+>%k_8Vb&JfHQ0PL zth0>1?d;Gz9Dk@X%sE-;jYkcU%LH6(rA?SS_%S1EeeX8J zPo-&QGq+=bo5VhnNPj^7cW-B#JrWO2#6oA62TQT2K;$*Hp=j6RmmQkq6_ySIu8!NY zkReR#`;q@$DG+xV#HE)z{oxc!kGb!05Sn`7faBMos7Dg|ibSfum->zd{4m3{efU0x ztNZZ13>zHd%yx8tj(%?SGM=-2GfOzf8GSA%E~UpMyP%)NT!cMP;=>y3N)Rj%IX!lUNM-CM%m1`J=%)f^v`H#+cn}cLBIHiHE%EO zbZ`W?v2VHFdDq8zxyQVvuzhSvD^?=bjSb@elW_cEUVPmEEp0)c)CJqK=b7UVpcr~X z7)nTg0ls|z%LZ>Mp^SP1X*c~Jc6<*6}#cQixSvj zvp;)RqqhnQA!pQYU2VgCmjvkNA#|XrBFsjUXZfr^B``gEPs2%*~ zCEhA?QHdRrD}=0p+mqW#l0GB_HQcKxc>K^b<6HOZ}Raa|)ff$GGw;mFEsffa2Nl ztbXGkU)Cveg`AM#P$V~S?ijwxYeehw(Q$l*lymsEh$Q}X3&|ex6#cLe1?M!`c}>^j zL|J980LuSs`Uh2mC75PgRd$M7|dc#rl_l=xb z@Xg4+BX6A%3qC@>6GvYfx)3j1j2HfWv?p{_Eckt7U)HTdM-K`eMz4nb9N9NeZ`_6g zK_yuk8Ak{ihvNAGqc089I!k+{Cx?2IImgZFVYFA$@`RQ?OvItlRZ#9Uygr+IM9g?I z^5c=W?uZ$W(C?QJlSFYoi`w4N18@CMUy&2FFC9JNwz;r~=bpfenJW^;+}tHbR$K2@ zyujvyV~3V-bx7C;qwo0>1rS^8Phh@irvWGmZSLXD!|^QbRh)NXw_oMA55w)lNhN*z zjTBPFW5G_;_O@Ew%@y@O1K-6yn>gl@m%jovYBKusoewMx`GoKxOdg!3YK^q%bQzq+F*^sjHt#+!KJV?{9riNrH`VhWs67xBa>Mg>p2_HHhD zGaLfB+S7PqiUd-}^2CSejU#yCTZN&tip2EYG?aM|CI0?rQNe~ES);uyZ0mln`6!<*#!Xru=dNPDRus`@S~}$iK_` z@0M%ea2lhEv#&(uY5aSU&8yyb=Gm^)Fn0f?EBO5f`TZC9{VDb!Dh4}mn~#L{tiMC^ z)WDhZuz8@Icm?M%Vr4T%Q($s@9EZf&eujN3WTGk*Rh{4*rNBVh?}&wS^rFzVTUmW* z{8`P{+putk_g`^50ejzWioXhhC(({Nu4%o#(aWyG9)qGDvxkN-xObn{T^{s?w`cqp z;(_muVD&vy)b|w)gzpE@nf|B>n?bC2~2?Oj-81a z>!J1!m~*|b#S*)OS;$5x11Cg&VSg30FIoKM=_mtzGzSa!huPiCqu@13wrgqCm(Zr$ zVTi0sNH9Bh^eYy-LS*0ckF}?rex7C$Xe<#QBZU*z(0E?7DRmPK6_#u0P}a<+%;jdi z`UO%r`?Qd}-a+x6eH-MNu!c zjeXIxNJW!4yuiGaYGM_?O{>>*Xq7%0g@v!zfYZKA`RPr@Z|t=&!g7Sd{a$cmh4~4E zsl*1-*?3E?5brmVu+U{RUA~EmNu8=aRBA*Ev+(|rb%$m@h~CKiTKF-4^wff^&{#)7 zScbEo#Z&2zGWkQQJ%BnK7ae|*_k&q;uumzLkEkC}A?xrcddlB_p}%v`oY0?F=r5nN zVBLa7?GDk3s8I_QwC9`x1=!cItQM941M;TEc^!Nf02bgVdjQo;X@ETt+KmI^*xAK? zs-27G{BP}Hzm0V17o_@8e;$u7&xj3Y>^rz_bdxd8z_B)Lk(k(Ej-H$qDiht2*B|@P zpGdupD=^?k3ARpp#9Tt@$?23gM*+lLb!d>+!JqM(uZvV=DW1AR!DCU zqf^l<#PIyM!rqvHRT)5B*%Kgzzfwt7^ExSsZPVZUH27HACKImWw|(6f%fpRdVu&C! z`qth>R!U#?_@-!s{YL^gMu-RKUA+wi(Y>+J{y8ldtzs5Ud1F}z>#Qh>eZxygLsxQZ z%zuWH>DP;tD}ScUd}(mb-k0ZGOUnbt)9 z1-Ed}#BXl24@EeXx{fNz<*`{EzKIkYvXvcI=`k#9NtCV+Rf4+vET{(8m*IL9If~Nt z;VWTrkY0y%7~u|`!)u)s4qC1khajP|xyRmZ@`k)iw$Z0xLP_@3huH8i6Nb+~yq9hj z^L2dlWF!=l{+BaAv(c@_3H>7Hzjs8>Sg)%7;++F z{rcixtY2ShpNX>Y^=sduh-;$Epv$I0DgBnQVSCmH6em1{EumlcH@<`pBf=}OSdV;- zx+_d_Io1iF-ET7EehOlt-RsjeP;~fz(Xa=YW@R{0tqZLl_yxy#ol0==y40pGn(;xSm5!v(~U0Ba|L3JsSZLUhWf% zx3r#03x)gxURj|_Xo4{grqKWV>@C7z=m#lg%}H&5ePaDYoHqzPApC{px|nJeE8cS_ zx0^wvB7RmN{VJ_zmGb-B#r^Hnd^oEsJ}l;V#UsKo_vY!gD|``1%5~s~{~{c0r%C zztBB4Nd7ri7A1*RZN8Cn9cDWpQg6dE!&sDOf;OwMM&R>6n{XE5gfQBlt|@#$Y!_ko zQ2#uppA%6in$K)U<>0s0_v!CQet*Hm{Qi1={~3N?%*W`=HPr}?b~*;YF*PWR-tae; z`AV9kzEQey(F7xBj+?DKQsW=_I4wS| zLCH%HL-mb?JRYzubZ{Ju!}HDxqf*7cLvpGFJ1B59ANBiH774ND2YZ0?2~#xT*Ny!KUZK+` zcA>Z8=YVn20VC%Qx4r#QrY^RqOW$k5P&fl!l6QRUoYL7IY;^w?=J<%{o+sma51k-G z_xug6$J1#rTo1+dLfS>d$aKA94;Xtf!rlh4HSF>Ap=(itf3U}Qhc3ljD-VwcN>_!Z z1Y$!*YzP@0$*4=oCyaPy(b%U#GA!!nz; zB6Hr}G-1UY)T1|Ur)TMNAf@a1zKvCmAy04E$M~DjNVocEqHy>7jKI4Gr_iA{oYy0D1WT@^64q!#Ho^HL$tZkZG?l7fxlLys;O+En(M?eYu9s8_?1HSqY@EFO_axh_Bn6 zgfHXZyEd_D_@>DQyPWwm8ji$vH~RwSFUEt|@I2In-m>7YKw-D$4r-|#h2ov3t@c&0 zM6wSy<&7@HB1pqOm=O;v*o(a@m|SSF{Svtr`Z^!Q=l1u6NF{i`jfD`_(FGVQJmJ%! zx*6!4_Dj^z|A!$0vkdnB(?Ua=|F&Vxg8w_ZAl>GS6PSi5<3?6Cv$H|dsPwCzylYj`V!AziP>61 z-~J;8oWA9o=pwh~ob=WkiddJtB;Ppin2(UP-r!-x6q++sG0(O>RFCUNPey)lP1oW2 zheCc`gKIyX1_Mu?^A6f;#I=FFsZTUq)4;&nDOP;t?d**ZYpA^fK9?GdKEq8z*4JbT zvVmek<4LWfyKI#SlOPQH#e4Db2I!)mJsrA&{JR&yH^zIsR8<_X>hke=vffZn<&Tx^ zL24K*of7Z03m!xcwBWbao==(K(+Cugk^j1ym9u!;6uDi7q4mi>6m6mipudSSzaf|F zB3`Z}Iv)(?9V2#3F&H{b??E2;*e97B_R({~1ET-VrkS^$OXVRI*hqk_LVSIe9l9ZH zRC8@GKN`ht`zlnJsRtoc=z3J`x0r%qOLRH)ex^3EfxOTdf2^|FFsGn{&V@O``-*il zyjFUP7hM)%!%n^7WadWk-5R}dBwb<(I{YE{v7wAVIV+6A;~(4EpzwY%TfsT95}`D< zi1*sh{RQ^AiC&-K_DbtA8&Q|^W@o%}eRtqksK0pD0>^ecP@mM_;pFVonY(I((ogMW ziLRhTCcafd?y#BCSx6`OKRUIDRllF`O_MA-hmFJfw4GRjFg2f~ja{u&2cAI{E^QlL&v0{kMg>(0>axOVYiTyJ=X-~wd_n$~ z@%$gF;`txN@=slYWXNCIA7=BQlEB=*(fhg9QhHGu@i!U3$A3n}gfqo*1PtC@!zmho zXy&Ik)N%efhsRL?EIK2Kqqm6{ADO<@DQ8vw1T*(Xyc?ZWRl0xCr2#Ca<2%(x4xc(g zL8Xtd+`=CeZSqG?$0>%5C<*(#RTw7vt?frGY0iZ2Yrw{7-Q`=mm^j3-YDdNLQ#3Pbw8Wn z=cOB2JVSl19#jC!M^$^Nv3OVNjr+)}LX|U#jIJTIVivg{ij~)6 z+5Q1~f6J}ps%gX_4@&O@ZnG1pI=MXBeF|6w%yh0p-6~?W6tEmiYewc;L>~0bu$;dl z8|K@vO#gq6SM0MO$cQbh#(5zhltZui8uZ&fHW=}t$>L} z*0qIL|G)}WX6^D%>_OM5bTr#M?RfT6sip4|@q~Q~?x&YRO*f;T+E1dB@_3i8@6q>i z_;;|Uw+!H~FyQk!m&0Yy$A;cR#WBhBVL^*Np@Vk|(3b3jLp1hdH;I36Xan0k$7hW2 z!J$=p#VTrLXWmO5X)(_J+=pL!OUCIR-D`3~Ur5_j{G1TBs`SRK$Q82PY|DziXavcf z3$jD^vutPxf&FHRg^o#V@Nw#h*jN@wk0_e$j?ag-n+7 z{UR!KYBm}@XFo&FDgt?V?$_p*1#qAVU7cw%Kg8n_-N%2hrcffnrlm0Oto^Mm*F>I>OF`U=^9 z4{MH7@zzP%6G--o8@T*+9}e!~H0YkE^!r!o_asVI>5XjOhb}iBHdYa&77#Zt-=_D2A++e1M?50DhkE5Gc@GgSF_eJQAJ)kIiZbsQ% zR2N?AgnrMelREV`5;(9~dE}SnOTMI+4a=9T@%gYHeKwkf#xooZmbQc9()hdeST=@Y zeGBhD;S43ssL}4j&EN3r3S4idGhg6KaDDg@{Q6W}el8Is3Qwk^<>#5kn^ICvn4T zky=aupgcsTeE*hWRFn`wAX`fND_WgQ6kQEP#P%)UvZaq0)BYj7N5wwPeGez{iazywIrzi>SgCw0E_23GzaBZ=nB@kzrk3*n&DBKfU2{(hdq^9!eLi*+f}V zH-ZuV*^eO|HgJ>Mx;2O$%D(ezR8hy?(Ra88jrO&8vKKx(y{zx~>k10lf1y#>Da{aL z#b1rb+YtGbF@Gd=C9eC8x0rPe{~LM;7Ebx1qE(3nr%r6i#)f|@ddq3J9!sYX!5@q3 z`_XQ6Jsj6>>--uotlBsyLSDpjy|9N=>a};pkTaGXF%`kQ!R9njFiz3*FYI=j{t6f_n*L>WBUXGo($F(lHfCXK5bI!h z>v9XU?j>}<6r&Ss=a}m{W*=>#t8h>`!Bo_Sb;+1(7z?l4Xg|Zf zc6cSJPk&iUf8zKjd{}{fZ2mE%?)S0ziU>}DoQNH&Dg1--;kj0J8D*d^jgw?#qrc2P z#R5NoWK(%EeE)`jS3bQN`T&2l;PZ)35ADm>z^l@6gb4J#`SgoUc`42Pl0DP+=3kO< ztaw8$s*D}qg#9gi8&)Lp_^aA0ue79JZb$BpyMt-b8#%LuwtSF*8}`(KQwSUAHGU)qIr7SCzr+-*-HS3=I}eCDjs z+xz~r4VU2|lghdJ)Me%O=UJd&VLplR(u5x z_0nW)5DFk%G5)(F#dm^6Kcb?!Q2^-6%p-r&w8C0%^Ekj% z;9C6cv1HWt8F%3Z`^w!k_7KviwxF@3`8tLecG}Fs`=E$|tq4t~;Agc%!WHzB7e1bT zuFOBJ#8QdATxo-rz30YTvZ{jGh@WI)^J{lA}= zk7mw3XJ6J{d+oK>UVH7evlkD-1vj{S6RsaEDmU%vN*;~ zFy<=%PB#F_{WJieM=u$o$Btl#IB(4ix}Bj8Vs?i8y*TQ8Rx_ouKBc;B&D^uep7=X8 z4E4`rL~?I#HDCI?fszo+me6Wyfuqim#y}tp+dMO?oc|EuY7WWsvnkV3X-B3x$qhhp z?b$$2q5)<3t-a+qS?0hwg2Ze~wUYCk)_Kg(T{CO~EkJ7D%&m1&Lp&cFftW6-`^f*NMrx~A$_+*(^Q>e6Gxk!8 zS_=Ar_e_5Tt5-!>*^2+s{k=~w9sJx^7@rK&!!0K z__jTWk!dv6*Gu1{dx!}6mnY^Uoe!W>#94NS{&SEXyPqE-i96UYM_whqWzG39)aFg! z0D=Yo#O;5uDcbXSzJSZTD+dRC-;c*S+(vQ}^*25XRGB*ZHn}*4(QNe6+KYns^$!di6uEF}hZYufHsfmjh*hi8TMhAa~YeEBA%ZT35 zmeE+uTC1b!Mrlc$dWdwC5+x_GzHDmGwwIX9ucRAC`G=~G^s00tk=ItcGZSpQ_${)L z7Yb^Jr;Z+Rj`gqKcFLTt=jhjs^eb0QM|plr&oZR({LhbgE_cuS>wSrPuF5AuJ|k?-JGj`;}qZ>Y;+!JlE|Bd{29mH#G|b4&*%E@5G6)6E@WsM;|ltOGNR zO*H!OngK$lu~nbuqHB&MTsSR52&8ww&>y+k5GIvV_r3Vz1~zvK1m zZ`7<$H$H~ou&tbp@O37{1h)SDza$I`#>YP7y+6tc124IVR4j7>XG>eOXsS6!#0?rp zkKt_@zvKCZphlm?FT*kVLVlsA(G&TF-mY(>Z60Cx*SEXJp*+rTj}abkagR}=Mt1PX zLSXbRECl}dps}Hbuj(KBPz)V*e%uFry7f0MB<*s{*81M0%-q~ zk-&1;;SX_r=U5i@Z(jN%Bx7U>YQ#@K2mx&#%Q&`)+J#j6bQfzlKHsd*=}~MGjhAda z7X_ZHHcYNaRm@C&jI~*Q5Q80If5!lZvkivEyP7j+Miglnm4Q}gVdAG+qB?O|MO9IJ zM>qe74P1P5V)!RTt>4HtKRd~E5sSBTp#CEyA+cE;tsfuFdwzMzGu4C${uex$mZZay ztt8IQ3-1xa!p0(lnyV^`fRa+3e^na+27tl?M|0uOTYVKKvArABz*k^ z6-q2{N?4+CNwLf|$%ll?n+29+Fq^~okd3MVayGo_OlSYU!Wwi=(%+ zO)4JqllZPw#Myf4s9&^gCD)jhHDxCjtDMxjcL824wXn0fo3(?s2j*8Hu+`4=f_9oS z=U1~K6^Dy_RfFsu}zQMb4HVG zv?l&AZ3VM5Tl3l}OigswL(~+7u~CIldz=G~TW1t|xyLusgnZ_uck4j|@$3~8YgrmA z-i2+`+*+5V2VZ+ChxNw4S$X7rZ2GI&MCum43{s)FNun z{o6o|1osz&HzExpJP)PzG-mjOFluL)A`26QFWJNv!qv zpylj^J&}E{;Yh9BXWXA=LA4=o_(Zt)0i~rtVG+9ge_xI+hl;61ZZvx|G>9sE4!XlD z=@G|ATTVFMzfvSG&6QlmbG@g4Aez05xB&FG@%Z}viA)kN9aA4TI~`AMX9?G2YN=$m zB_hQ08`bYK%(f!-Dl7S6gqzY;ge`{w=$n5v#!b*?e#sV4rGQ^@-`+bmt}p!5jqAxk zjwSRJCm(rQ==RG>FSC3W4|tKwi!M44)<>SZ!}(T!Qd4#+%*n3Mn~w{t8FcIlqJG@9 z%hXG}SBW~=yz9Rao;`Wmb$McbPdIP3^cJ!=ar=pX^JVfvM z*h6#w|6mx#Qqz{hK(tvKhD2wNa3t1=+}ub6Clrf03-F5nUiW)~ln#90qN+BkG8MH`Z}i^W5hG%ViX*mshH;%A(e%I!fYmMcT!!&!oRp)Vv1m zFPYF=EGq^vrv$>5@lb6wQt^Z<{oP3_ zZFW^HHO6=QYxz4l>6ZLj6p24pd30Fa%;f`$yktKO9_I>4$SC%FYkpkYXIp0WP1ZDO z;*Qiz&74W3`$<)rxp+6SFyDY&kbj;+!9?Il*BB7u=jnGei94n+R}dx<_6~A7Ktm{h zUp}ZCu)=#O*^>q@Ggriq{I_4X#tAj*W~vUwSjeNZBIvMDH?6onS8zdZZ0Yd*)T*KW zPh}=eEEpe-PjLRmKZof9vxv9oW4LqEZTAg%&Jj@cJ7PN#>qYJy=BdrI#q%{~Eiyno@K-OBeEo^rNtVwlQm`L#q}va%d%yGhAr+^Z{=8KCAr+6w z!H{ht_CqR4>+v=8M0nFl?YtO2ow`ym!z z#P&ljkCeFmkW5k6zry_o1)8?~5bZZ@u^%#A`yqR=p>cHKMn|T{7WMPFDfk?<{f;9X zK6zgiysxzPyM=h>zLp+c&xZUk*bm7a8Q{;-Pxa{bA7=mKSdE?Se~95=lrd*FS0DZ) z7ES$vq0!7ZR)9wir5kAVM-H-I^rx*(ob4|5-F@P0;6z7`zuNM|S=8An(ek!9akc|W z`c@~-hF#37L~x)X0-&q?YF-gL!^wFJg#DD(kwy59j=v2pIB#|>3|Nf-zB_OBAxpBt z^Jcd#hT6~1(`jh9z@aL1rD1_B?vY;0LBsyh^pGn5Qo)oNJw9`rR@+#R8frhVV~A5u zIU-xaG14K#>-ac5cW!R4hU{>Z3MNMVtDBo!)^dGH=`opsoJ1#H@NdkHw?}>3qyr(1 zr1*1tZn`3+ep^q zb|%~J9hGSqR6czBc**d+T1Pr2OR0wRrjRSuk0YMYnA{p!%QK}n z|C7mGp2Uou0w z%RvWbssjQrTay7Yw>-Qb63>s9`OoC#5xX~XRc7Coe_rzECV0$Kc_1|f_tY`rU_|!> zOo@9ZE7oqL8JN;VJRdFh2c9SJeCK-i%sybnYoEJk&aago{12X;LvKwdvzd!(qZzvI z??7i{hOnJHdVZKA0`tsu``=J@PHrZ7e!={yq@5ZHB!K~GFZ|3mz)QNC9W3wF9HJXS@>DU=bwH}(AFHXUooSEmw?%D&$!gdpYLy6 zbkA$SbDxR%f8)c7jTVI%;e z?mT=i{Pyl4kI4B$%Y?5ll>5-dmDs&FenU6U6wN!U$H{tR0^bGOfPN6jZ-(^F-q314 zO4+XN^Hg^)v;J-`Ag!+x8HL==RN}uYMq+mDw_T>bWXjvMM=75ixwhP&3|s;t<^f4m zVOX1aLB4-3m34da^$>KTt@H}#{HTM@TQTeN!J%W;7T{8K4yA6v ztbeKYw(?WW3e~z=#chK|=*&m{L|*3ak%nKNrSyZ{<66kC-!|4-z^`kXgtqW}u2T=|em!@u(98;OSst)EUS40^kr4?>IN9sZu@0<_a>YMx)pxP+%4`$7=@okmh# zYFnG9HZ6O*=@&$I;W9Qi1-;~pMnDx0t)mh-Qa|g`->nJKa?@a%4*WDoi#r=3$qy-- zNwrxTqWrxc7^9^ahNHnDM0Ca$1Wb3x=iABTXqKLx^=FN2!R;c1(h83%_BJ9w-gNEl zSwm**Q{B@b=NCL(2nW%rq^r7!o_VqNx1E{XA%FzmA@zE%0Hv>!l$dljuu9! zx#Im-texK}U#JRZLvV6OQ!Vq~T)5!X1*0`YqxA$ss?q8#)RSKDYg%FXJ8h$kqg-Fd zdw0z*;7ZPCYI>=?aQv$H?yrD;sl>(Kacs3I9Ivm0=4{0u!twgRr9TPB>ou1i{tcCC zJm-Zg7LHQwDGfDPYqoDG%NO4a@)XZB0S2W9kX!KvBHSmyMP;g zKbB7CdTovW_g@BtY|R6^7t`)g|4=X$Y|8snG{@Cr#cc8~bgB4QQ&V%V@D6{Na9j^p zy`)QPU45^y>!$iXrqQlP^8BB3VD9@1!S@$55^k(>szakQQt!-K8NVJr@2|Q*@3Fj> z4za?0rW{4(*_xQE14)!b*^zPBON|TaI2~zj@$e+j^Yr$g=;H=*7t+U{&QgmDokCu_ z(7T%TZ8w2L=vhtfCGfTdeLM$a-ikg3hV&57$E1)R0{VDK&UqUDfIj-mv#fwVnzSGJ z|B61YV-N7Z(Z|7b`up@TSN&uax@)nG=Wbvsq>s}y{nX=?qK{E771D>c`+kT%c6Igr zwb9l00*!7#AK$)c?L82De?TL#6@BchcLnsZNMgb0qpwxo=QmL*&(`ek>VQ7Z5Cv^P zA4mM^{||k{$z4bv$q8!F_y-K+2l>bIFVK%I=;KZ%&{p)(JEVtzK28nkA)t?kzNC@@ z`uOhiARX|Jfo#nFKckNe?)>lc;nC^u)5qQFC;b0M#YP|Ng&F76;~(bcalk(Yxl~9W z|A~Km`@Ge6Juc+p9}iI97WDC!`+iOE{TgeplUctx&p)=&y8`;SS3J$=<7+G2=S(aw zz}(B#0ev)xg0`TKz0t_N&p&XZsJmtDfTB5a?AF?~pMRMux5m8W|Eb;X&s07b>)M!0 zE;##)MI%l{y&PfoPE2Y=N5Im{sDAN?<4gGQ&pIP$V4=<#mhR3;6QcI~&ODeuixR-k zzY6LE1np{Uc{TjRs18yU%JT5G_%NPIrY>d`u><>=KgFb^?u%#pO@2G8{oQHY^lFU8 z`Rn3$)@|`CoFmHm7TVSdR6<*4K7)00;HR=Y{A_WbX0Xb_&LQP0N!KLl>Ym4S+`mD* zgJ4w}1N2=xn<+i&hxD&}e2HHzhEl>AHczOkvkq(#U*dsq2K`peWh>T)GiaJiAGMlF zSOB&1?GC3+S$v6Q+O*^S|4n>}Reuvs3N)zr#Q}CqvoTHaB4)!6#+UeZ5e;W+uD4-^ z{)Irt|6F{Dx7_z@g74QDg8yrLiIecrE*zqeox(-8Uhf7=OLGdw*p}CMz0~OlK&0MR z3kz^QU0TuePIRUSi9iO^YJc{H;m%8r)w^uPRSw5qve~6y54F}hm)`f2Ape0bed5X> zZSzT5k@T-Ztw{PbBpAf`U>_RkM1}&*XeZ0Td8}tqezF~H8f|8Wd|E?C*b|Dplr&%H zydnLeKj@dRzd#|p>PFr}_x=^kRHl}f61}p&drp`(KL>P`-%~1_{yO<5edTAGkH&A3 zLRYp=FS#&gYi>P^A6ujSLlO*HZ#{!v;H>EXbv$hD$1_OzWB3+8473460O(zf{GikV zyF1+ixfRG)h0-+r>*)n*vSzev%l|d-&88eCEw?_t)qOvT@Ab2%3SziygL)B2S=AKI z&;OMkKA2By;T$x2c-o1|LVDOY9RGkGE(ym!poc}F797ySE+12=q+UP|BjvEB^#22T zIO=J`Zc*F+N)MIe96d7<_KG?(g zF?v`aiB(7s_nelehbZ5m2SFUr0}%b6)5HDq)MU*F*Oq@W@NGd4Y4`n5zSqy*3_*w< zhNu_+H}vq@Tv`k1;ST1Ye?OfU!hUNr)cC_L;rO4aciD;w;rO56(lc{ZqVaBY>1}Wy zvviG1|Lol$y^qr34@2~jNr58Lta^=K6!M4tEkgl+*jq2stLwET)8;GQW2|`L|H2`5 z7#rB=V=M`bB>Yp{^!HKfe8%Xq zL-{d!ctSE?^bimD!}X^^5BrKg1P~uW4v|B#Tckh_0_ti6;Fc^RkjMFTnq5$oUk|aQ zN_Pr`njgEi{X>D*(Z?*uFV1$~cjG(sv3c`U(MMnPDxi1?t7_EK-E*O{89 zpQD|SGD^U{e;sHLWhh>LAUVDZXMV6A%CCO{efJMr=)0U>`jARRDfg%j?vHvqNMEnC zD8uX@1(ad->2Av49@avsArqd|o~kG5-}l5t>+bqi#92?m)aU5`#Ns0jr25 zzT+gmKSC1-m2AQ+dTKFYwz7lp-SO*Q!V8wip~V_|{~6WZ8S-DoCpX8w|33Ksd%lO5 zm!;5+um2kSg7&z{I$N`6EmZ;7vA;!yHFYaL-r9c%9BYE3$7AX(gxH{}U+L=sco0TD-B5LpzHbi~8tIdgLIl9W|S9rJWNmqd{wIu6I>6 z7^XATvFuSjSjQ}GI8>_-3LHa$VH6Oe7nci7>&zL%GGHOGWJdy< zd&$MBx#gAm>^Rm0B`>RFV%@-2LZ7ZRe`bw^O2%vJi-vJl$m=2rX!Y<09Hbu=& z@V#w)pVoVWntOIVOv`zEQ3^UEkH6F1jw*$TXv=auO#U@^xgbofcXV5y__Wyn7}ur#8|9ts2b#@X4pJB zd~Yv#0#DjMX>Z~|xH*JIx1zG?G!oJ?zNGYKYnlsaZC{jW(Hil;0`m8gd;jO`Yq6#p zX>R&1&v1o^TI*M?E^&^-w=!OlG3(~?HDx}BkE-s{bGal6ogK}M{WnI&=%al z#To9Jg6&_`MnSW;FD`jwN1oa7f#yzR19YulPFW~H6otLGQsk36AZWLV%eQ-LsQJ=6 zHuobuPG9NSlpa2hRjyT#+lJEkSHc_AcC_UMYxos_XrOW8kzJIjGe&U3_mNhw3Hk*l zLmYQ2b65rQ`ZRE*=ll2G;ixEAMkB#`d2X!dG5xx>5BK$%Ox{eUL1p~w>_uO5eOU1& zU2W^Pi?2$*o>;Y!bg%ew@w?Pl>(LJB?Qzs8NOCLPi^f5p`iF(>oXJ1!Bn=|9e>N6)nRB)M7iB7bN#agPf2_Kw(UVAme+oV{ExcxEHOPh*`*K<^P+qc_? zFiol&3YkSP!EZjU3>kfiqLmEN>`b2yaNTq2ab017)ug%$9Q;ECULs4|w|n8D55T#Fdb2wOgbIK+hCmLoWY;sjxlY6#6W!5CFf4t zAY;FmlmNHY^N`AIg zB}q!jAA>GU}|ACs-gg=`fjjuCwv{q1$vEt5Lc{cMh0Zt$fD+D=(LJ{6o@5Xm_@nH3D2TJeGw;3u@rXramD+8@$Ema4c{P#5Q zpU2_LLBYhkxDXDokYm$5pgT(UgZH4$RjDE~A%i>pvc+DM88e*a7(K?>qJit^ruU^A z_&gop+;)f=6?i=j!KzJ|+xk~G#agg|`$+i`VkVgjc3G2KR(=kRMKdK;c>ELPC;1eR zG}eCOWjlFjNPpFJAN1%D_Zk2@yxIyTH$R^iKGxl|1wICJaCR{Z8~=}1>$u8X&M8T5Jf>|B*?7r8|Fz~v!k{|JQ8ihqdiXHeImLCpz~-mIi;X$n8U4G_FM6D7|Eo9Pi57CT+86T9#4pD;Xv3@lMbAQ{lBkW@_#RLk{#$~{Xme34 zGmt|wtNn{(jwmxUBjDR6fn_gw1!LD(` zYq|9*&I|nv`H#AZmmEiy+ZNW83h&^hvR2sP<(~)8yWZ;E05v@% zXj*W7&e@+vjjVT9qr-wCU1Z6f8x+~zOWvk=2FSg=)QJV9-&JYEf6?q}mEP!P zW%A*IEa@;y9 z`4i{~UU~`%$&310#lP{g&mn*6)9>ak;C(E!S99i9<#YN`MKh8+nqiInerD8APFGj@ z?~OKUX+Mt=(H2Co@#pPxskJ61kn{hJBFNG2oS-ic1bsDvo(nYkWg@s{ac~S>pus{% zen~Up>pB|MQ2btA)Wb=eTRuBF+wd@o>X3!xLeMCD1#A|W1}@SAy2NU~PlG^e9bhcR zSZsWc#@esFtU|>#q=!^>-Rb1~Wx2-egyOENC0V8@H}z2Cv<=!e#A=A+ac>TW51khu zrNtTx*9#;l4n#UDcXg=3;m?WZ--VUAso!YmVE|>icv24C*_uzQ7)069{2PxnxcbM~ z>T61eth-n4 zEP&VxYU&r}%tQQla>}yzJQl^(Up|6Id35coTnilU6#V^S*-Hoc%}6$^g%i4mcgNhl zKrno$ms}0h!^d${MZZ7uQd-@K5O?sBm+?xE@Qb(fHkb$F_XQuuFZLHw+D1BVGl+F$ z?l0sEwPw!N1KWSrG_EcRG>z@Z7PRx5f_7H0E#%t4@x93J7qqj4EV-ES8I-BR3X0sR zA|_6LtRf#aI?!%ZkzES%9jJVWr=r=K6aMTV-+9XS8FU|Z^-AS4KC`Ft-5BI+RK7(8 z`6ehIOQoXO`zqggLB2hd?+)d2SiHWVh%c%#EFPdDhXzGHCQI&|f_xt;pLJ;;<=ZL9 zH&6LSC?8eB9fuYac|%1E>itw?h0P}7PO3^Gbaz{S6G%jryk48E8z%!xqY{Njb1KWU0Y@;0n;n`jc@-N5$HGYiyeJ(^R=5=~! z`3z56UreF+Po}Mx@;nReW3#TQp~C0^sybWqJD`l}?01@AWa-~jvf_$bd~(?Y$~n<} zX=3wFFF7IsUrg>z9f{4Gyd?Gs9yW5@tsuyh`hOZwlwMD5Ct7U^$=nCFsyRdetiW$H zTl(#t17L?MQ1af?2GDFd1hhT_#Mz3&Ht;E3@~^N!1b$W*do6G$@(+efP{blQ*#6c3 z!3n@q>Q!^;HvNn77y3``L~I5H&P3hE@Q7!)+;1MsFlp)Az28(9`wk$pH9Ku$I1g0q z^o}DGu786&iI#f^1#sM{bQ$Y6lCgx0`1X8hI!@g-?#re6@^QqzyvY~jOA!CF;`n9O zNZ%iKpRbc^{wIU%oPlC5RmRfq2PYf+djqOkWCH;^Za~Wym(w}ALBvUCq+$g2bCL!B4rAAJNbk&hgf2UqdNN3Ld&D!~YXaA=vtNdD zxrx6$;M>?v48#jsrI*?+X5 z`r~)juD=`5TPz%Bx6YK-+xO-%(98~b*uDm@xp6cT+OspI11z8QVP97l6X+%7TMcda z^XSEd8D^+dr* z6%0IS#j~h5TV7~9pTYC(tVZ+u|x)I!@2~^Gr{B zxSo~;J^d^FXTC5r(-x>Nc|Z6g2e6LPq_IrjypXx>TO;ONYL2 z|G9&m>EP0_B|+cXUHaBVt`Caq{`bGRXZm?+Rpc3(r0#e9T^tJA=a3Hiw8Fo8n8WK; z%4FO*^F$tsh~I-U+LS(&Z0hzQ`puLk?xF=bDHe3IK^27kyw<9tpU8qJ&vXG$Bq1VQ zx6Gi1x#G9nPP}I^rH1;KgHAZnLTF0Oy?CfK^Cy?-fgsZfWODQiBpqa-#O0b4x``xH zdWp+Dl{0H!{Eo`doa$?mx=0*0Yxh80CbpN?rXwkYKn~+eN4kj-4uXYT{KNb*7I*tlWo19*XNZ$zjl+r-9<=t3j8~A7J~#+pQO$;VI$<&IPN`uB4(Uok_z<2)t2 z;h&Q4gWM%j7me5TJ??x(VosT8*`1#tK2-&<#48I^|Wzgk12|wS9Zu`G~fcTn1SiaNxmaCf! zrnD$Y3g-ZE7^Af)#~N%l^tjo75M&W}H2luJQt$s^fZZ#lB@c)4DxnFNmuuqvKOAn8 zuwBH=J@Z=DkcBVg@(&iLf#Y$v)CExa3@W0r{fXM9iBqp(*$Qyxmt81TV|hwXql9bA zjlvFryxF3!0bOC%CeAD!=~@IIb7W)mL1>nb{C|9hx{st;#*8XFpOHHn0xdYN!5D`3 zPgd(LLyu*B>&f@q292GgTC*VHr9NYs($U$vv*PYvVeU|#t>ksRRt zKi+7@SyVKfqK@L$;T=7^)Z2_jM;Z4=O}O91h<{OaWkyC^e0bWk`0(p^Ab$I{eq6&e zOa7N9M&!|AcdIAX6E|-?1$D!DvR;L_7d?3k57PVApq_k3ceQ`rL590%Q%yjCl>1mI zYb~n$+6GHK!n--tSL7f6GXx>Bvs=C%OqFxs8vd@1!h)L+23Q{IJ*_hLImph-;{eXv z3_RLf7Q)%f!Kr&a>iVGi`eO`6N1uvkk1<|&peG-y%sTX~?|1+Y$Li|kZTss0`ZvQ+Rumtq zm^n*GCN_iPM|psbJ88i5^1Z%MT6%e_tG-GwSUrAEX140z(bd2FU>L-5V#_^?5rf$d zo5GVL`PIhFo0kv70>Op1y7KiISzneTME$>l1UaU^N)Ey2%{d&{TJQ6JO;fpN?JfNv zKK{1cFP-bM7ZLJ3cR1Ji=J)>q*YJVF%Uwkt(!T)wuFryT@wXpBb?5TM!R^gF+~Vuy z=YPxLT~`}^N?*N2c(qXHMg2m&PIA)kfDj(6@<4&h5%O$Ya$9R8lLxk*(W_sqP=h^AGT2H;boz za+eL*xbn=1;5G)rgS2_6lc1hpni*fsOl6Vwu3rRTOj%Ri-zJMhOMe@N`F3KowN{+u z@}DyE4i51H2S}M7W7pcPnGx`VY+Wh)xDdwh!PLn?NDX$o>dZ89SK>aOaN`5o0-9AP zi>XSCK)9T}=bx{xWm@60bst-fxg4IAL|Zh*|8kJN75exOLx)ih^K4(^l;Hj=FMS>; z<$l&`D!Pt}0OYSK&MiwEDKvU=$0_>x53;zDg{j}xl{tDqFM={pm7-cx?|@#;0e4aI zZzVv{cx*hVxgRydj~p(aSkK1*m(ojdw?rzeGCN+hCiq62_mAR}{3U?EVobSltp6=T zE&r0!nLwAPlPX9gx7)hQY%4Kxe@GW}Rmg?l1498jhI0Bf zelN@98r80aH1PjApqxMcoOhXv8Ow@h1Du#Li(pE114+?=z3ISK$7j5xY>mjof^#hy z+r@oy4s(xtyr`{Dui5tOrNoyY<6_i`hYiJ}0nM(^o%X&9o`0{swySr&_FIFx0pSJw z2L#P2W5L6%2W>GQr&jy>6?DhW`7#k+LjYKJINqJDI8DxgRFE5JGEi|F2!1#eC>KPk^V64QuI+Hwb^kAWI(0P!Sfoofk1w1^+rQ;j}Tv(VdGO z9bB(4PI1(k0|O2DUxeqSYbKelO!`@2SGT|61e$zFG?2MSz@Hz97Uzh56u-iTihCL| zBk(7JZf%(DR0VKKlZdDk`?l>9t@u&gx$wN#ex)j|{kxaFg}2PFqx*IJsgS>4)XzUs z_OZh1BKTjxri@4#%gz2iN(IsTTT>jxE+?$O5u@zJS2tc9e7`4%e?3vk7m*Ag(%V6` z`K>kqbrb&H*Iq$&LB5V4Uo@Q~>qW|X6CwD;6Dk-mS~pgDk70%@Ch1yovLzb(>As=o z29Yq^F@c4~N9=CNb2Tftnoej|z=iq#ZjhLDQAs6OQO>E( zJ)jJk(*1u&*=)_;@3>wB@*kd)`$id{<^BF@RWe;;EbHLlzot`A(%F0u`Zj1gn8uyZ zL$1@+`rvP^*5s#!wN6p3@`8w^m*iIQJ0r^VSedCfWlZcB-z) zCzk9y-8%bL7@q~1@SDF4uv;Sni{(%)N!Lb3NdsjflzBJIZK{1w_k7gc_lzj`^Y{@w zYd=`eKjZn>r`$95q1GfGcF%hzpN}60R$iMy+L7JRP+(Yik`ZAet^XwJKNIUq?TS|D z%)9y^X@c3(5B4Z7!cRHe#Ww#(U2CBbPqFl8ihmtbw5U%35WN#RZOYd50LZ4=b-{gx z**?b^pi8(l)V`Pgai+e*MYW#crqyK+Db07;R^^?q=u@iiX?<5kkLiPQ+-GkndWSvm z=0-iFUq@~h2P77YTUDZ^>h>W22y_WwG=wx}I#U|G)uc#vul$jsm=d z@&nHZ?%_&U(t}~4D z#8eZdyQQa=#{-srkRRfBIKOwD=cV^A~bI_bPV|1!Ug{a+_+gA!8|K#QJ;) zas{~E?@AcZnkV(0;O`}T2ia#ns5IX#nwZ2WLE*5W^lp+B+e>M?8Ka535uspP(KS@{ z^QZiT@NZ$RCes>hxyPUCT-4}4Q#$xM@bcSGAC&||yH!n`FrbGzQba{L~hV$~QqyS-wvo+hY7J_XAJn&X@3cMHP5-8?z zIkj}X64FPgFO*4NSUb{YtCze9mLyHcfA|aQqA3PW4T>N|Dz37*ur$uS7#07rp<2qh zkZi?443n%dF`lpdt9!2FdFK7@d9VywXG==y+%0Nl_sK$cuiiU2heFKkZeZ%w`qG`O zz? zvtGFS)(OTM$V;Mj!634IzOx=NLrp$r`!qeF%1A$GD8fiAMXJL{+T`VF$V=G!;`mAa zh1zy06l)E-N5xC-queOe?WbC?BaoAwY^v7IpS&&oYwXwcgzmp}cR7^!&dRA!F(iyNhlx3us#fEV=@)m z{WzGXRh!s{99P!`^Kja52vRbizUsZz7z+=;@`ND&n^!PJCkor5Q2mG_q#JV8y2=R^O5<^ynyS z+?JtN3jpiUH|#K2sHJ|6^7Hs7-v5iiQg51SlDQ+ib#D+AnpH*m7KVf#{+>d(>GAQu zXs%D+m-P3i8apYg{fiiiu6=EmFa9(bmCK-+Xr|BM0*R3*4~`=L0jg8c9XF_gaE&mW!xB^Y(Zn6Vy7kpLEqaTNh9D)W|Dd9tPR=mn=0A z&Vy~|J2af8%y0VDuNgV2B)&IZ-cX>-VHZpFF>}~o+!Oe}PEV)|mty3COf1;DR)(?6 zF;JD7Og-PEI{=V#vxzSwluAe6UzMb0)nsOPs->rRF6Y5^W z#K!HttH+Tk?Z;aBCYy>^ZeA%ov)iaKZhl;7ktn{0?gB&nG?SVx8t{eXLR7J`7LceoZ~u#spRGasx+kwD#1hK~t}X&Z6AsTA=pK__E$BZ!GdF9G_`jXz{+2 z`_ggvrEOy80~=fYUs--A!e5CQr;GC|lZn?3LFBG9{#mc|T0RBw%Im$Sc(F<^eo2NI z_1;XIJ$gI>`+-~3b1Hok}G2;^IFYpS~!KcODOzyECI59gN!ev`Ah zwTp{wId*yeC@#0;6TSy-00u4Z{;e`;ML>Eysrgqk3(e8-+O$n~g+9ueO0>fN6)>=T zdYhyifX9%uqZEdf*~|jXB=EAm@*7@2qt0rP058m}FGz%VxpCpzcXIEUAwm5v{T~D1 z7nn|J=DbH$#_&r3LMt}am?=HT!MF}V#b^H`2Tv0pV;L_Wn(9ZbeFWaqd#Q{u2)ySr zrC%hhgV(sa1Ht|$xES@z`>>;IHk1XgXcEL4=-IvUU6N0o0bb$;^wZ6`eR!3}FYz2J z-uw#_6H-_fPzY zH*B4pGGDPg%lrvJ4mM!Q;%}q<(5>Utt>8NPN*Z3aBE;Pi#+G=-bBupei*vRJ^p#BM z`&X)<-FLs}pJACBT$yX?x#dOtd4ZOf#-D$m<|$jTphvNSr&zzh?GN5&`O1$Si~cDy zDA+0C65p;N6B|{(X70AF=U}ciJFWBsn`vGO*;d3&x=HPm09?eW1dnJ+vXimM z#zVUwO{!XoL+WwMd1=1_^Yc{NH?%35pOc66Yv*bzw_eLhan>GZh=*gQ_>OAO&%Ac{ zGVRsVo{j}AB2}Mwzl8mE6A~l!6@qTXhl0$5V3WG5uF^{$$0IkOq?UQfBgH(Ib@j3N znrXNZ2RH7S;h)RrBiNz-jR0ZeRB4SVLL+CP+C}sZL{mBY>mv!CJ&5umK z*>A%4@V17~=w52N;W)sK1?7@vRK14`A`4{hCAAyX+Kp*W9bT{s_K)6^d@#EGKL$-rUgJu$HTq9zh6Ow^sjA?KOC|P= zC*CntLsawj=5Tmgjk3fOPqNG_{L#Au(@`V_ud#l_k8=G7Zr6v_uX7Oq;lc$Dj<1PV zIeHXbWSXFn=lT8~+($6pr@93G;AOd&csF=WuGA2hj~`u`*i;rDme^F@da*pN%0T3o z-i{?z{6Q7*CkS%wFGaIglsOO4(R!6wP#O4HP4N15Qj(wN?bN{p?_^d!C%^TTw`1Qb z{&3vTuPmsg#B%w4c-1uv#pEB$(c$jg3(jZ%y7fo2f3)}bUa0l)LztNHM)oA-uTuA_ zikwRk@u5ijkSd$0+Bbd*{taxpe`!LR_e>y|%_{#+-gm7sJnD5x@VZ^EgZTPUeNgw6 z{{nrOxy5?K+1q02joP&T2m3_dh-XdA95X8YV&Vfx`dO%L?Ods8UUI7H$sC~-`#kZb;Rzf?hDeebEV^d4$@z#4D3)2RLcK>rE9*vl{Bw6^0oGJEW`$)MJdglK%96k zMO-kk+dm7-oTG;|9Lr7JOdA4^ec}cl*UUwhzQ%*h{5ol*kOcvp109_4pVL^|y#@pO zr@;Rw_q-R+)eg4!&ODzgxPUYDBK4tvnp44=$Z;^$r+MQ%2B4fu+nGdVT3*feWToGi zamz)G2;1n2E0-BHYVACSI&r6Htsg%nGjUXUeXkeR&MPXaENX3PTUG8jBGadcr4bRPk3Eixb?Ye3aa_o_*LJKdjA@>x_ z!Szo&m7fDNcf6O*LUZ*phX5FTLo(7N)i<)GPMuu>2<0rb|F!~1BdzJfNW(i2FYTz*2x>wU$Pa~Dg9WGHm>KoQSQ3&PDzzf z?CBsmcavpnAVkB5^nDP-B}Cmv2fNv2nZI^dH`=M4#LP3T5!UMBrR7}VBdD%sb2E1| zRcX?3;Ynpt-VtmJ2nvhnT|AQS@14> zU|4^tUZnUSJo-I@vPm75$?eJ? z{hBg4EKZwawXAEo6%s&T8xd@JUi&j7`k=g*pJ z*@}_j@MvFw^iARLq+EK{?ZNQ0y7VqL1nDzL|G;qFbg2#3!7qoy)yUNJX8@O&O6oxd z!G$e*r3qt}wKb&{|=mBe>P!rD3|z6%`Y zxMgsdQbxz=A1yMpW2j73Q)g~9m~!vEIeh5)5c`aN-zjJf6ctU-c=&tKT-SAQQn>R( zxO3`skx;8JE5_k~V*(Ue?k{LFcN#-f@X<+T)%BXbMl^sj)vq~X6cn+u1`)oGoGY^- zguina_XOB8p$&M`O_v3wuGJ)^6r61uk0uo|&>CePBAvT|KQKi&i8>-Z$GDu}H2RRL zgNDQO@(&YG7p3NBj{oCYOwWmf|o>jl%K^E!J`iVm3KyB@&Y%Z$HGaNz z6Bk<{tbtfEGr2R`yrp#2Ow<%y4RRDr>Zl~n0kN%W*lz zQAM=t_wMI?tGH{92o|cXxvNX&Ex(gKnncSTY9#GGCfvt+@*iKa$yoQe=GDV}p)LO9 z_1$nk*D049Su9JxWG}b$_ZN#tXd7h|Bg3W5JA%d->c8J_2k;lFAP;Il^V=wA1=}c3 z{y~M81bSn(Pw8zz`frv!*hcxcgo|@K$Zw;>wd6@o;R{mL-)IMz78LFPJAFX|)?3B3 zuQJ){>E2iIvTyLl@d@p(+}7P+|HYjEUJJ}4jS3oB&tHfEl=H~`WBQbyH_PaQy_T!A z&%y`0_ae}DXfOVtjDFGw#U7pC!9KgdX}I$qJlVd=q^pBGLxMbRKW9?~*{*SV05eN# zrQ5U;6FhfA-!jI^E0rUGjS=maX@gL#u^P_|riLwi+2CFy^!6N!r}SbknG;I0rAHWw zNx$XNzcWpl^z$yg@@5SI>8D+Kr|Cf&i$zgA$2dyjy=CFWWjEQT5r>)Y3Aq5AxkV^o zf-FZs$Dl><)SmSoC8zG6o5fGaucY98Kswr!6__qyj}BvJ$V=Y9J8G=o{D#%X&hAR( zvg^0C*V&idV#O~C!?N$v`Xrm(bicpmoHoNzMXN;6;)=I!6iKw~Vshv}AwDL!b6OBcN4?y3j>`wKyn>R`Y> zdPT3qIBGzQyOrS>|FUv7f;V=0GdtJ5nUfhW&%gas+}GAusq5zjbzQ8w@EW)3R_zR3 zJSw^n)|YHgs$AC@MXSm9Cb-niM83&si zIVm$TFzf}OW{nPr{lSl5F}sn?qAdvN?6TV!l=gRZee*&gV5=F2+(ZZY?k_>bQLWn2$ejD8X+6;0sd^&tCw?iRVxF8&NeRdCT@lfR zY9MkVR$X@v;rJ?qZbMZMs+ngbp=$KBRW*~0isK+bS7xK1u6B#C%k@6}u~V-7d+CGb z&KdSrp|0g=G9!3eFg zYU)6tu#RgBzd>(G z-*Vrd3BF&$_uM#!NJDxaRp%x$i?l2puf!!Jf_rriwb5PeNA;c!YBX&*cx`c+_(USB zRYcR1Zy_!ct5N3CoOL4c*CXD{*Yh4%-SReY*x*j+TR1zXTQCW9=g-`QqLM54EncH) zU?%gj!i0JDEI=Ca)--{0c&J~)EXEGwqmJvOA@>1Jjud(A^Lwcp6o4t)YO-+cbhc(P zJcyx?dl&1*&HimDE3r(o?gIQm!kfDQ?I@qS3-BUp)Lnph4sG(6%4{4!^?N>;zrtWp zbzy{?t}AsP;2bT|7rXla{m(IKh7;W)KxFFnn8(=Y?&~zZ!s9FbJ|f7#EV~^2)J+6M z$T250br%ORx@f}0OWsZ%H;&xZEZ2Z=_c9+hUWlB#smy<^ztA=x-}zwN3lYp^?*4HV zLJl|voBL8NH?e2`hl?xcHxm$`zHOt2>oRcE&th(|%m~&S4cuR>NR-)g&ej~4 z_r~UK<~rf^(^hiswa82U4^^6}XcP||cKzvGqsrZJMM6GS^wD4rtb%7efGQ@b_GJll zx;%%vBf5&FzlhHLmXL>Yo3m8}f$3khWY#Mp$xno3M==Q&bNi4Jf2NCC09QO;ygHXlytpb?r)e!&;*eCPOOzoeJZ@$i9|Q`vLy zW|kbnNqB(y)b6YAi>hIxyvDFFxs83H8C-SNnEnPS{z^aA9k(=O#v=uBSW7qF)mZz9 zH~nhzHl|mN$d(*L_Pel*b-)R(b z`S})Yd7dvXm*xJ&63*tu+9(q(YQy`c`kF1R{u{%aDOqRzU!ZsLi^XXC28vO)TsZs8 z0Y%1zvo#OQxcO{O~`ZH6v*KEy9^o%wB@kkveWjYD=x@G2PpjVzDa(yxgWDWOH zn<=ikUg2}@OV!n~DcyRP{|YR_z=V*J>O!XVE)E9L_0*dBY(ot(>$)Jkru3P2HKixd zXiR^?1>T&RgLH4{+Rf;xKCytQeA-UpHniD7MH$pt6BeX-pH1 zz%Bl-`&oIdH=3FLvo(S6OrF7rIy&w^Y3)afVahblhz@IP_fiXK#4iUOiWwtj7ZVx$ z@PJOSx#;Ts{&1hbR}-wV6-&6S@@KKgHfAkuWrqwTRFhxWiovlDsKB@qvrNHh(*2j_ zPR8grVFq_i=CJE;o~66A17W|Y@$sSwc7^@B63V&T)`@(Q;sA_1n}I)3Z~i#j@PMBR z?SR1TWJJ^z;OVb&n*9;c4TjbJp@Kp2OQM<5 z6HhlG_uRbh>2<(15XLcl_ID)XjNDzI)!&9kH}1KMNNdu3MLbF7ckXV|)O4+@>Cdd4 zZKC=gsF^jGqQK8|*IK#DGdQ2;IptZVJj-)0@}qh)N$P_aJR7EI$2qD&(f(wm>`Kv0 z-L$7QJG=ZC5I3h=hnljLOHeN0+{i%HxGSv?K$h@v?|mNKpW8rAt%4t!fD_x>8PviyZIR`?ImnXY@f`4#>h zE%R_i9=OPkAq0Xu9?A51952*q-%5*^dNRR+Ir5zDa|iFzuOb8dDvmZJ4$P7kBaBzZ zYWr8k_mepQPAY{n8QU==eTZ#93w4RjspoIG$vlTmM zBtDkGCbAX3!evFzRXjg?wR`TzvxlFU-uLEt#3XxeMbcr@lCKSYvCH0#|B#~?gAch| zZ|CGd7qP6`XdCfTcO3hf^>#|?N#;oX+PCm4$d;b}9v{7iH;9MPl-=VzQoDApU7C2W z1(!juVR2$Z@vdvu5^A|6wVd<{yi6|kl8Seb?8FK3DDrzLtPn+!bM=mVXWn^2`~*oI>gX zefnGO;elp>9H`sC3ESADb3^&VP2#ybRCju{;nhC}!5{-Y(c!ry6N8o*5g`JqftK^0 zvm^#5j+HHBkaCPk&-0_Ad4t|dvc#sYdBKW%PlTzIPmZmUgEJo|6vaJ>(I1fw2<1hM zpft1CAHUt?%wj8KF~k}Gd1%SI9bo1*(1gK9cgZ8F;*av$ zNqiEO4;0}**gDX-;AZ8&3@ebdc^Ue&b@ek$C(yRSuX25`75-!P6%Wk@Z|091lmCt% z;D19$xB|C}4V@7ZZ1$~%r}_H6JzkIt)-)VZT-mxpmEA{I3?W!2kDxMtrWGI5)n^8; zz2rf>!+G^6Z_e?`48Lp%l^>NI@?(Fybs?=ezb%Vu z9c?+`_-Ixa8LVhZzwFP1D@9uxkJmgO9}3Y0fs4R>rrB z!H?<}HI!CXV`D0V{gl-&Dz4O9A(=4R>w(GtCFLj+FFj&W$E}NA8h_!S{;B8fNz&EfL zSH}Cyk{ouI`F8zY_j_OsngNY=wTJS)UdKd^gipDPCBK5ss&zWdd`%t|F=Z>-lT1$e zp4{ouZ(bRsuXE|@X+e6bOOMg+B&SX;4vl50HSWV+a_v(^(-~uJ`!Rnz@!El%-N_G4 zy#}v?5A47;1i{N4`^lDGr;k_w;Y5EpnJSDE9S7|jCnEAeaOx2~PDc?lM~zxDw=zC3 znzZ0W5gp`e`BLz~hcg|AL;nAI6)NQkh0I_srEuqX|~VV%nsWtTbifZ($5{o z?nzbDxQC@`#;~#sN%nSj^F*>S1b3!%)k#!gRQm@;+^BX;o@(0+Hq2(UzQ;r62YW6T zbdMM{sDYQ2Ua}vvSo?N)z@#0!=wMkeX`C5i*p+OG4n}ZlMF-R7)j`%vuYDv1=G4=U zu>bUzPH3#*C9Ral&)GUU*i^otc#N7npvd3dwP1oo+Pap=SkSN@tQMs;rO&HoeK!ab zLZ$U1-Pq5+`YW4ZWAaBJyZuX>GUq5h7`8z{lNk}QjrVST)RcMH%@?ES^EqJ~cJERH zs&qNbC|I_S;Y~<~$3J3pm_<4L4|KRUDu?JWH(68_@;^fCbyR$;_BVT(ZANpZI~eWYSFBx`Xy!J;6ZU z&b8%V$*?fL-Z#yFdQ0!O??*${HJ9Y!ITd(v7nqD_GkkOZmE|+Ir^B%w+(XDmZP$l- zhW}%LAKW=3$NhlTiHixQLL*HMh~qdiLqUHdxh(L44va-$54pG$30T#SC2yp|Y{{yk z0>WSQh^bNkQ^2NrYG*jGxR{^5lqeh2x2VZ(@eTJ9`&PyKNQv4L?BwK{1(H!o`upR6 z5kAwu>-|DT@%%wnGrYn}{)OBIYVIYT7!UYE%RF(0aK(}M1O+xU7d`^8nLa}w2v;87 zb@H3E)yKwkpGw}l)yKWQRv#W|XS$T$EDNF8k8EczTY4N)&DW?nR1m-SAKqMy}vLfb0m8; zlOIbrF4+fgia8I1CA`249?FyKrDLL*aR@cobL(Bv^w%q5?Hb+4C9q0f?ck<0ru#^xfuzDln#Hu33kK0S?f z&)&0{&-<}U+_zC|T3u1RsArWwQ!_Vn=92nM->O(*K}q(?&6_rDTDxq((tX z$p7R{L|G8`cX)ANzs#1jg<*f2GD8SL&^ikMmuR81$0y>&t+gZChVNSxKf>&oa@pgG zCmjQg(3{4`ApRxM?1f|fW67NxqT$Kg1222Y3|Xzl5zv1ck>TwRQ3FQs&ZeGfsj;KE zWkUa0%aqF4+<%ug^&DUBZ_~vv1S_0}!I|!$VFphBis!-0#ghBAt>3Xe{RR<*V6tuN zcjo*94~?v3P?%B zSX~E&xju(Zwmz0#l6bEN&W5`#ORQ|0Hm@DzD8({+9|)z0a~tepCq@k@@*0W7`7zR- z1~(ua3|Qk&I{~j5>yD%uhU77=T;8ppcFd@v2rOms$Z9Go^4G8zR6lLPsLjuTOFM{; zJQttA5-18FQWc45<3~};rclANjiFG>OSJ}kvvG-E&FE$tm*jLekAb2M(bfKr8uU!* z%43W@+_;n`y_sxENX(T2wc$1Qpp$F$Kms=|w-j_GC;~bh=P%AdhYwM^;$!9CpXNWR z_lk9{=KlC`SmnPk%Swdky1X3cN$qoj1pGSpE-irfFJ1u+kBU2BLDUXiV#(&*-4xtf z|Kt9@@JzXsKK5irb+81j1JM>rO-qfY%+yL-aVjx*v;QMMAa~ZUIuk-0DD9X~|E$ai zHCEMVTDtkHJmg;}jpcl0Pozyh^u4kv{e@Z2SNW>|R14o{^<@}(BkN>sYum=A+hT7) zoNHQ~W?PN)pUL4L_Nh83XO+w$(d;o~V2!g~E5!bWeLo)rY8GLV;3P1M4S-DH4KDVL zlDw{91sTAl^OW(Qu$=6AyD3w*rkUxL*tWRq6@LWwZV6Q^F~=qyZcX+7I@t$Vv;rC&*8d~fsA&F6Z$-@60fAh{Iil;rOGYWq&E zAHq|4apOyo2n{{jh@Fykmat zarWH|i>UP>VOjegT_)a2}qnM=oLWBnulDEbAV z8oPRj7TgH1oBzH#8N%e$ezp}N);8GsHnSr)CVo$p=Fs!9bv2g_C@PSsxQ+F|%J>2T zHSt!@rv1Oo*0YFcp2h8U=|$0WW2gT$qAi3%S{ft7+2ejZv1<{j41Na%zeDxwS2BW` z=9e&9cgmlHa0L+!9KTWhGN3#fgH0bj%70wMlWCrnKKgjOMbGKsYexJc;w5qW<47(m zxoIYeN+-|N`1Y0=^x21iz-xe*OFLo`UQ6YeWK46ZW;5J6zAg6tYNsdT9)ACausLmF zfQJJohOx1CF6f|KZobz$>+qHxJe&|fTlZ@5h*6P9ImKPih?zYy*3`IY#HobO);=bf z+vDeV5;0|&L2xm9Fq{2dFihq=Uijw<3vRSiBk8qKG(9i9rZenv#Uu&POkJ_)E?aXs zHgF*TDX~KO$Kmkz=;G2>?ifI0QWtUu@+OqWp}%Tys9vF}6~q(&%}Otcb1yy#XL#3L zS*#XVmS->Gs=R>Hl1G;(l^b|iB)#bi$)D%Hrg>0=9X9riDZP$r%>%PqRj~>)qDhxj z`D^Je3(X5Nw_QsOEL|IFznXGpefn*7nuoX`uOEMJml-XMo!*6XxwqP-n4I~TqnE8T z9j&5m_yI-nV;gJNPT8$7{ax2zZ5~~=x-okxcY%ID6H{+T9wz7wW``>yqv!(jZBnOx%;~)!DtL4HJutZh z^c>L$dW^qZXyR@GTOZwnH=i7p%HfKB0{|)t3|6F$A}srFhe>xs*`9}T8$o$nG+VN; zj6ODJCY0G$^B6=xQ}KJ;Mv1JRTunT6nP{eu1x<~EpLhB<;fS6!w2c(n^7Mg8^)&Ez zNk8IUfIo>8LT2F*+hhvO|3}@M$5&Nd{r?FNj04_SL1RTd*dU<-LN%3$(L@5?Xrfpr zS_cRjAQ}=(?v1Cs=O91v%5Kx^e(qs0+$o&-CQP8opos%%g6M#)GATR5iS zmSA~gothd<<`}M^wA@bINV)0Q=t}>1&X`0alR4J-)xgMA-%ze1)ke;{FIgS$L6Wps zCBOSsq~<_(dwm`0_(V;%f7!nxRob67pWzMWC`(mp>HwZFu3vNC2T~*F>qQiC^)+wf^*0W+wNG@{eEv$cIy zUVT~Q@)JIa7Jt(6VP*C!RmH1g))~%7c13V9R3$GjtSU}NI`0NOWCqC|kUx1mV)aeWt4~bHeMqJRKlZSrY6eMpB?Ryl0!3O|Vx+;hGcc7T zdL6Il45fayETq(a{7V1Alta#|^aSz#>UREMii)Np_!JcQFb~Fi|B(b z&M93>1IbBK+>J$0)kv)*=ck=52(Omi}y=xzspZ>yD1*_6W0gN90 z?{(iLZVx=WrbswR-;8O5JcTgLl&<6+9VyF5hn86E6BS|j{*#0(E24=LiD&Q6+mlj* zK^S-Uh}5EqvvZB_dE@!R>0Dta{<#Qu17?E8xUnVQPAjtgUMPLizJ0f7z?lx{kMf-c( z8K}3*a+TRf3m#S3N89Xe=5$rjbz&YfU|ayfqgw;Q*{wm?41&e7l+Pk}tjvtXCM$3 zH&6|QcB_An1|@~Yvh`GZ`G^J>G(`N7{|uIws%V;6!5nV62PDhNP2MLg_$9B(c45OZ z()lzkAY-6wf|gQk{rr923Ywqnxx9YSnn$eC_3QzOCpv@!t|Rv>5-Ks7AguvJc@SWb zsP`6pf7}Z5f1k11bf@U~N6@0O;+(M-9k>E3hybeMm6vbC{O_N%woyGV9;|7*H5+yj zt8b!L-unm`My^|t&Fl`_ok%*?#i!)4JV?#!7ey`EM&^P8q`yyLIF&20{VLbyS}(=h zEBu`FcCh0>dE_;-HvE+~( z6;!?$*@!NTpiz0a>nI&^=hM}BbZt^m(QKFi}fpJllc%fV|CD>kz+_Kv9tWsqPx zId>kbq1nF1S-05)0o1t|c_tmh`-+mSQCtv-k7HxmciBC4(T>Er&SzqOqkeiqrv7o6 z`a^r_V~1sB$H>csQ5R=(;w?XtMsS@R?Y^&Pyugpx-<-M&Xp6&k@k4;3KLXI=q8S;j z*^cndP0s}GnRQCe7uIjlJBT+Swaq&^Yj|`8-Y6Hj%xQ?aYh@p)mXefj{gXO%gs>LejCKXaHld{ z|6$QA*-4#ZS-mvag+B%{2Q?hPAKIwGuLW5xzDW`|vkSkwK0*nAc0Wzg49=(U-`VWK z76Uj`_SyHoUA;<@t%=nG&Hb69ZJoq$iP+Mu&3;43)5;zWc~C=*jIP zcQ5UQpTsu1_%~dC;?YPGij1Ck%bz3piF_&SyJb}fpvhJKjln^tcj#7o27?ZJaJrmpk_lvui7m03EDk9m-+6zk@>QgvVjpq-&1@%unVm z+m{^^{VH8n&aY*;T-~#R)+3#NRmopicUo1Ip%&ZMg`cB*(KM1LOi8R<^mb_}?(Hx1 zFIl}Pm{^JIDW`XGk}R}u`jqm=a|e1_AjDE_ z{ijCTRAVe(NKniur|5lU;&bh;l^4v>$0>ZQlJ}`RxbcS{V^yp|%A=!TAwN}a6Mt#^ zR{l_f#ybiY+u!wWYp|nW8IS3G`Z4ujzr)RIF{ob-zQs*Ft9?q6Vz;WCb$EdCP>Q)xYg%E8Ab{+1Q5DT|!4hIm6h ztl-76e)0V$b#7?;4$jz)NjWlhHbib&!3l*Sl(>}=<;CmDB9$u{yq;VVLP~rO1X325 zltvamLQm25hYd1Wk;GVb`=ZHv4el7jM7iH)ZzkhMeG>Qa<1~a6doFU#@w_ijJhAOn z1>z^3sv7pS`tMjE+Pc>UXa_+$hw?%e+Q_%dQv?2IVrs8`R3O9s{6qMj8{4C-eG?aq zHb7bxHP5lY9k;P6b?o4(#MkB7&nI4M|NCw$zw95a*-(-Fa{GH6v|YKWfBDGu9O)XC?4RJudGb7#VMb zIWW@k1AT2@0U?$bumOX6_ZB)rH&$kEj~1_uMygnHKs8uX5Rp*3)Ih>3@&ST|9_qKC zz?{|S11+c9(Dq0F(1gh)1Vcbxo2Y0af#0G``>mV{$z#{4m4$rQYI}~l%GDc3gr@U9 zK$?l|udqT7yIHkgUJ4Q~!d~5aA}g8ERN2J$&K2_xjRFxoUygDk9kVDC;+@#DAM;3v zXb4gN8GPJPi;!7!6hjVVLRG396Dd{X-K>F)4~}rpK#yv0AK6G^1+(y=7V?`S12yuo znKJSyq+zL15j9XYCcu81dS%0yx((#?y;S_XpKqOKAF0Kk{AL&Wu?#3 z29&My)Uz-uh8F-iVCv~Eo;GgBxJ3tx8NrnH#)2vRgiL6Rw?bv=+`Jv-i6^(c2607) zJzr7tLfN+0qp9*d-2E>^hpi|1$WEM_)h`4XC+M`3n}OD?;Gz;@6cQn{6*hM#Mk|ZI zitUT21clzc)Y;moQO;=FPN^_SC6=d z;MmEZ;2x3FS(3^VZZd%z=OE0zCUVQ6!YRgCqDLAzqhPwRPe{5t-F}tdo?_@{=M_)v4S*2MZ4zSAiCu%>M{bh96lYs-c zGIeaf#MLJHB_~Gy!hTkaT$6rPu8WLRz>xNHAT+?M36w^z(V?1vr?)yOnjJejR2A;J z^FFn^o(*a{8SGlQWkp(k0f?xgcugd=2#{CQNG*a`nwR_jM7?Fue`}{UAcYJJE0U$9%%pAqitMgTXNb%6`E*p3*gS4U=IzGx zNd^cf>(cY+l=D65#h|6U*g-3D_0KSPz~dCe@{1aH`Qc8RrkBZP0t}+E%qSR*_}f%i zzbp%MqPuccOb^&@7LJ&c|4P#jax%g{_YJoKUKcQmcoZF(_9-k`G+sm$jdocbTECSa z*umRg!7$u^2Mf$$YeS(zvOGj>tNwAS zpSah7H}SDuw2~3xpg9U`vlQFt?g+E1v;b2@Vte{!h{e_g4ldiUIU$!E~{!VFp zFe^+?E6fAWNe^d=CTB@EoL?2{pqUy96_&d|BAqbKk+R;5=nWMxZ+>*!yi$CR{wM1gU8<;CQKfhwIlOQy zcX~2jJiW2WL9YEbcFwh5nP@HSF6@Cn_qjfIoiJso9h=;YX~Fru&mqD#JVq4SDO2*w zBacl#G<&R2e$Z?nVz3uES9Fc`(b4-?_RFc zklptLM4O&tR?vlB`aRV7QvCCH`G(vlFAxcF*!df`LUB^#?W)bn6s!DR_fqfuq%+6X z3KK~Z-w_|FICwZI6K)=hb#B007dua3Rz(81WBW*lG&KjK{B>OcA6~)N`t~-D#lZ*G zA_?SSNwVa}W&*TZ7)>c2lp_V8;7V2r8tf&=(c9t1x=*^|8^kvgBESaYKY;N-uOL?A^~s6YF$! zG~5qUoh31l%vs_(Xbw8qyhcv0?%&(E-tzqyB+nK!3J`X9)94~6+f}-mJywnCFIFkI z?0`2pZ;!B1&-l6f{&V+T+jg%0O85N_!S@#TeYE@T|1|(|=Xc!@uXUyKgWk$r=^aoT zUEQva%Gf;KpRihEx67o&M;UpGu(cy*{`=5?WhPxxXyPrNpE*SK)>>LKf#t6AWLJpH z9weYzB06x}U=4xX;lLsLftT;;6vga(9z-yeMlkcGCy>)XUFT1K3IF<-3uHeh?sn4BM+4-!3ow83o6B`d7$ z`CfXg;btL^!f&=~=4R8j;Jva^-#!lsi-{6)9`~9LW+zZNy0AC9bPgzX`W5T9zm&Lu+{#4N_5OcjNkrXl3&-~m?p4<#{E*gzS8gRGMrRWXEj!qiEcH;u zo@rI~x60WNuc&#sJi(6aUS#&-o};RTWX2(wjq1Hww?w&-fOFhH9H$siAjrzO<(*G@^LW(Yhw=bKb58S8d}8xKrVBD z7LqwH5&jk=NckO1MQ3(qa9bkhVZQh$KA__T_wdslFF2JlRTI!a>{y=8Z(QV`ody|L zc0bHD<~SKjE@{400ccwh?7v5Q641^dov)nuRUI-Y<75G-O8Z4f3q2IN{jWFSGyEN4 zo)qw;G>G+IyBqjOX;_(&>Spw4@-%QXjy+HI)N_-aqVI~t*{0*7QrY3m(=TIR1i-p%PJ##c%!ah>)TLGxtv6nnJ@aK9CR5w-4_ zCCL8w!#rYMjHFJuPdN4wIBZoe1WWRjB>Mkk;OZaCFCckjwL})Zh7(FwP?y+a9;gVj(vPDh$ze)`%u|j&VE$YY^zxLUd}1WQDbFs zj(f=L(SynsUN#zH>^Kd=n^e4c!Tvhzaen~cc^^(n&CI5U%YScOq7tXux@XJ)gnK1ZOzBx@A_Xb_0` zuXE7BXre1dfMhA1X&*{GA_2KUBHw=vJ>hNviqa^arlVvD_6=@FyG%IPsBzA30oC#i z=pJ}r8aN8z6xw;=Zh2_$+4&cWAzK=W)XM%`SMa4y`25&|=PKNN_dlw+715djS4FeC zc5HSqhNgqVERQ^4!)LV?ySXAYAO2kH7hfSpMtZpeTe649T(Vg*8>7bTF|+b^ZtJ2< zTP|M#-M`7cX+?5&u3v;64Zw7VLC089J)oBoM6AulOrMrdxQ-|8tw=N%b}tHGDI%PO zL4~tcxsUt@ghb=xzei}2xf3;ZC_H{mfhhHynCHto@?cGz*%O1UY(dCQ~ z85ZA;$P(p#$6U>Y)vkrr{GU0P!^|Wg5NyaZwc|`c!f}8tCO73R4b#>ClXw!tyX6FS zUtkcl>p%Sw!I!VCJJq3m`!Xo_@=ow2pU7K3AGZn+wJVH-eVh8dnlbtMi?Ihr^l)g0 zC_3=WAwA~yN1w{TC5NM*9?&!N_s}stF1rvYO4lhrw3bGrCI*-f77^0ez4l~ zNkA;;wOHG~Y!EtE60wPtC}s-j*X1#VKpQ2ak|jm1+|O|oxPxVbRp@>S`Fk)k#^W+@ zX(%PRRyZn0XbFI!$@c&nWfGL%={$@JizW;XL-!l}SKQJ0AUpwYONI=?GiM^`2qr*#49}v2V#v9<%)8HM3;S z(gT7b9W??OzOw z9TH7W@c)dyHVhn3VdBm>-SnaoCMO0whhp?9i~k;f5?iF^bKBe6=3m5ELD=Fvij%}L zozLi&`g;cBVR@2^{or5vU@#J-kPZbR#+Phks;P-Pl<2N16&v7n@0an9RkW}1s)|43 zq7TaG{!IV7Zdf8O=*_99$v}dk#ts!{yHnP!W^J?`YN<>g6zuk4eBE~|M~MWU{|;%J zs1tw6N+1T`^0xpbchJ%@-3xH9^9tB1XR=?aUXnRC>=&T_XuUk#UJ`!akBNn34URv% z!Dv!kbB|gj!K~e7B*Wn<*XTBQTlspn@E3E9V%)bEobMAy1s)1{ul(`=8B0DvZEA(dsj_>d$cJq644-Az!W#o6=8&Jw%S_~Xur_&MynCBc|=;|wk z!0e}$bKBi9vE)A9R3$I_00n(w#;0+m0{AAo24%7>{=OS8ru!Ug@*LD_D;f@;#x!0i zM7EDlqsx36PYp4__@{*$#dv=>5D)mIC;BTmoj?(x>McJHFE|9eBv-(cZ_9%|1N{P= z0NN%3MIEI5zaAYx`0?0XpnE{+u&k>7P5J&gqIcvNmz8NDxe9(clR?TcigPDpMd&U> zC{c;rE_Akp%l5h{?fBD6CMQVWLJppBoXY=!uAujM2 zidrvprAJ-v05MdhxA7^M7bPlOi6+rg0FCd=(Z@ERnX-D-0t zX>@AHZ^tojMFtvvCgfBzE*GQA$ByIdW9%q?zoNiN^6wP#dlVL@eh=mMLTnBF#(_QL zUhUY?Sm&XJ?1_0>OHae0ZrF7yD*Zg{z0{w8)L>kZ&Q+%Ta}L~>io`{;DIvmo>TaNM zhx?S}K7A1Y>d$Vm#Pk5#0U|l5 zERRE1?B*ofVAG@hDSz$}8ZSsDad?gM?Q~>_d7KbuDP6`s57PYC6|$h>3<@{OMSab^&m+i4-l(pye>L8OxM z0QG1d9sP0twm*WL0B(q+#aF>(jiSS1vl-ll5QD!~NF+p#)SiKZN6U;!Af$$2T?k)J z^o+ZdH;D5JA#1M3;4yO!Hh66xFa@|o=x@$9bYU4i#f%xx9kQfur58k&Kb|w>Xj(d- zoJZ#g0El7_75zZd^J~hI1CexPfu8TAisIQiPcmWfmLJoRWEYFs`9s5&-8*y+KV^Ys z_NOwr`)rScGc}ncIX{=QObxj(V1Tjwek@=B#n0|L-WUKGMgG1Yy5EYQy>XQNj&pP3 zdBo3djQ!Y5Hl$JS(Ugmj>+C8>pkV+$r?=QQ!0^q8 zV5p_+FMt*CCdr%|0TD?HbK^I$0L#OLmm%Xx`4mVE`TjvFFa>&^YjCK7o}$xIYas4-|;*7 zC-eB}{FAahDkl(Bh0UV426xlpMSnCD1zhnjw_0VS-Dh@?v9Mf{BtPmnZ-_RrJ?pfq0jZ!BIq~W%hxH=wl(H#XeQ0 z($DP@V4z&Gw>5Hm6JHGegJptjv0W>==>A7de&jml-N4kBS&L?6+mu1Jt-?=|{j_nh5 z?zbL(3zS>VHNhQ&c`l<2?iZ(@{cbjFffXM2E&eUI39zmh@#9<_72G3<6pJQC75IlD z7P=qtHwIL+>2H8%NB19hUSIXe_ps=LWx_3I18{2_K#C%NPGW9P^7RbyZ6LD8cGd>O~(W(Y3$aX1Q0ZTJnwASYyH=O zm6^z<#h38G!f;2ct4$h$TAynKFdua2@IPl}D&-VOOhVb$u^YOBOmgz9=lBcmu;oo` zA7^!UoI*1W51hl4S;)b+=^lUC+1L$w#>}u&aD+PcLpM3kWrezx-Qlk8G&hxBAovqHTD*imu(L&Lald;bVp}}pFr>w{t zkQM8%bx?7$5jqP6bR366m99{u@N{Wc)`I;Q9x9YT7$q+!xZ3ki6p)f9aw$hnEx3tv z{F1hnm~FZ&r77BqF4fra`mxp}0e~fV#7PRnDa0k;{~SaqnsuxqeQ2F`nX>+3VV+mh zrH&wKJAp!LIyDq2AN27akT@DFQa6z{MH}@~F5MMK-{lO@5WXTdjzK=gx7fkr zZqFvds!r=DxrJ{sbt)%Xdm;9b)(L*0s~y~vnfiqb%}w1~un@9i6QW>_Uu5GKj2Pl{ zG{gXT^67x#!p~KSkNp$A)GUI^1VE}X!8)hURYBU&NT2YBsuXAbI3vYf1o2#vX7u-t zYRGnB?<7f&;+?#zO7*hCKa3~Z80dB*5YHb5e4zO~{0? z0*y(J@tDsey36RWy=Lm`O@mHnKwWgf>GxYXm@f(4HUQX%#^2*@lbaP`2H7#%i3*_(c%WvRg zMo(xxT#Qdi0dtSPB&T?%vk_3$ft&qR+l! z!RrwV7yXwYy-TrB5h;J#jM^@Ky~x^`Kc72MaFs}B27;8ALtNcR$0(k5O-Z9{#Dcby179x|74^u0FZ^S+YS{lG2TpEP!HgUj ztWsE`d-r&2%D}#?e8d13d5G~h`=fa$UyHi}=MbJ~Vz9sV7HX$T?jHbwd}*|YKn<8V zdsoa%*T)u^tH{4ZGQnBmb{EyZz{hXH=`EhDMuEeV)i`?P?*0(=U0TU{;QCvMbNCdd zqnSwO3!-*Lg$tuc5ymN^mwmWodhpV5$+sCU`Al3gk&noc^kyFTyKCr6epMy~{gBHC zU3!(^+J}w5@R!r1B~4iB{JC=Gl9LJl+6lxW)WbVVCGQjym^D!QU1vo(khw+7A26ofT z2Yh#@06A|X;Q>97XNXqh+9XJi+w4~mwU8(=^~n(OWh|HTtNDTNJk^3?53GJ2FU&4?2F{!E8R7dkt?@RL%-Rp zyy{@eE_z>)mH5F1Bwnsx^v;g{E4S=XPb~E7^^2a(dZj*b=C}2U`Cr>kSn;~}a@Sr@ z4h#nmK+!+m!t&^C9L08?9mcIVAp7=6(5K6P-S2|?pMmiL7WUx#s5kLsfkvRs>XlkyPfoa*I zP23lk6`KRuEVyvt}C(EObytt`#aEaWH|{0y0VYu+Yx*tf;|2~_i?@K z@6?cY(KL2A-}YCF=aP@g1zi|ImF@V%!ivb^d4IaqYaPu0X) z`#pCo{Y96RVk2#{uw@|YMLITssLIsYteQ`Za(0UAnMi@8Q`t{OmM9z`#B^LVeQ>z1GDQBm-N$- zeS7YfypWeAtx2x;5R-gX3UcjGO$Kemw=oRKvJZ*zHz$uA+o+o{3Z-Ff>R-tJ*a91i43d;NJC# z6NWJc7rRBS zES4xW5_$p>>MzD#q&JB!tYgle@*X%{UNly zDzBn=``m|nFn_4#asRQCdt-iY_ih0b?m_$)On`!V*@O3YdtUaS{n?(EJy?GzcnODs z@RhW(M`X$G?d1SEKVdImcs-BYZ7>x8o_wKLd5amG8 z)B^p6T>nqnID0p8j5 zdlW8bO0#1`6PHsU;cj!>?Ehsxz`0&Z z2Mwn)y;vH>1T5p4J_%dti3Kl2ai8m!Jo2X!u>3`|czdLCAf24^0RLoR)t(oPoVvEB zejZtAR99`Zf6! z>O2Nn<&T4vB)Of9faumi$jI`uyu|v@w20qqw@wo_jY61=@|a9E9O;e~TIejfOd>Dw zCAy=>f4k_|h0-5UWrB;GNHzvM(`59(NAz;KQXK^TJobIQ^u*bRHc*;fgdhEi;dHH_ z$PTB|PuM%t% zFINIZf5FZ4i9^erKV?9@j03RQ@k=6)oqnjhW+Cxh#q;ltdxG3Mte8HFTyqnJDvF6fqqNkF?BnFcsMsxj<)vc5f6Y%8Sze{J zPQ|b_(QO;#2~}y%LRRkn&f+tIE8_iTQ2>>Dj4|bIGkS{L|8MIf2510#BFi5`1BeL5 z5aQL}2;GUQI@p*Cgv+`1+3|lcCL7SU4d26@;4aAB-?1hKsL72$gC+~DPH8xYpnNn_ z!A?0@ZYTdvSAzwW&Wk9dgq&XfwZE`&;6>9K5|ICm*6~dFC*2f$U}KKpXx?@C^{%ja zDQ@K*o7##MJj4}MlmUC!UH-E5zkDn#Bm>XuQjLL zyWNl02kVxe=br}jh-rAkUq`Q6 z+}`R)B}Tr)GlLU5L}MuukP|x-!D{!Pm(tIRZD^2R0?a}hLSQ^Sua~cT=(Tc6^~fJ! z=ccx=_B?P^Yih9r2nmQCNL%;SVJIt1Bh*Lu-Ya;t?Q!id_QWelJ$(+^{|EWeh9jQ7 zbviK8Q6~{#ICZMVL_3KMd99!Qs>nUejYvoFOf-P54InvQyimb~OZMiaBG0Fr$A%xJ zA|8PJN@e0JNM|XR-^TOPXHm@YVO8>CYHoG=G-X>S;~4nhqwTRqH1dl>^?qG!I=@FA z=zdF6pQlYi-bYyyp?LNxP`+!1@4o=7;PS-;U;&J?SW(-gp3|L{i&rs-XyTdZ$d|Z! zg~TB|R!oR2APf@U#v1bGU0hgEOp3mUAiwj)yLREMT}whxuV49F>*tyz{rQ(W{)-<9 zG1PnpLR`|s>&>;IUAVoWCB5vQiN*4o4LRFl^@bmm{Z!^aMwWS5`{6NFb>Vg`RO+43 z6ldc^rendRu-Y4)(lQnqs*GTU&Po)xB0>zE=LaZEfU3VZ6msHUy`={Ab7+ioXk(G* zA01$*cUxE56PYli`(usxW_x2JUhC%tBh~@^wC?0EyC7#CC5_TF z(4n4n{^>5br;GUgPEMa zwG<0;EEeVyQ3wZ>^=Fz!o*(3IzeYN1i?389u7On?WL>W|SV^qOAGaZVEZymTYce8< zZgf;A;nD~u;!9oR$_etgxMLa7_Idft{p^9fAy?T@tT(^*r^ZCw6ldk!sS<%YS?Uo* zx76I|o$T}O@LxqmIMhTr?h{$Or`4E9vD4|cQ&w*@yh`_dw&BR|$gPRm`{KTGtH>ps ziH{;3)5WaCA9D}A2AwKeKTSi-d3B3)yiUlhno5d1s!9~KtJj{)hrzv!Y~B(c-SMc{ zI;oJ2rI{=z*|EbJI6V=ru_HE!YbmbxPXWYu;jiB*)1BaoC6k9x?EW7o@2phs?g->9 zz1k*j#_cN@S8S&)297^q{y6x@ZLD;;7t_CEI-&dm5&{}~i?0-xar6!+MdJO~mc+L(@9BR^&|ReG>xU&q(HjT@&o4d6!0$`m(RR&b-G-AMk{ zxUH3mo2LsihcLj(r2V$@RR63>99)U~)?X5x1+9_vHcrHc-M+Tly;;jYgCAX||CL zr9h^gsTxs=NWw&?enu0y>A%xrfX8A8DOGgyc|i2)Ta4T1FZO>ZIuOw9JPl4tKFCg* zzc7oXYjEYKOA!eTEi^e`NgFMDBgqwQ71kAJ`9EnP(J70``+TTY&8Z=mD*7`u=mi%P zH(F6$sgnBLc}e8jlKx<}GI^f^D%Fy+mv#>~KP7v`{Ub|;2rm}!Q2r*p=y>NVktI*_ zmN-i|Qd!?4TO1dG|PquNgy=%AlAKN#3F+!(GJ)#Ce zdJGUH^5$NiX#c5&{_cnyOmhFXSL!c*!;-tZy)6F|K|2r_@KI9MER)bl#EX#AZ?;fO^edXtfw=B`|+tFs@3UX8k{0*hz|llP}Q1DxXeEQ z0;{as@JsRMX8uqr&y`A?qq&avSJDR`7uv^8lM1Q2TTx>9{(i<0*E!MYs3Wl%^L6KJ zsQx#1I5XlKd5V++^^Y`ab6hQ(a;Fx+)-wOepo$DJB|ug7Q%+szQUD--Y=@Lie4fN3 zqB6ZNqx1I%dFfx%MTV{Y0eW=^D$n9|lQ~DdF9@8DgQqC{6Pq70`YqThJwrotVA`Bk zp`t070*_Jv5X`3t64S1i22RsmvFg*T9sdTA4nzAbQ%et~XrFktz#s9A<<>>}T3`>` zs2nVqzBq(Mq(kxe7K3=8Nzt4R_EdGsK=;cAD>nkL!3&4p+t=VRd%wr9O`nL9C!hnj zFi8#h`E;n)Hn8&IM>6IQ+?Xe2ruKI!2U>ana>~Scn~}VbejwD%ewMJDSk=7(d1Aqg zTBu&S4seM`S4TQerfT;?<}dJDDXg{cp6wx59^k{3=K>TIP|_MLBP`0I1=p4lxoF{n zr2OMQ|4eGJ%z+R{ z>!%|c8$O~ezh}{R5%pYjaPf)6x4i7OJ@_~Wa>`4XK~%569FL1XdSVwXt8r?`76ox5 z31`R}Bt7RPv%qL-P|E%cxnriDir$IxhZb3`<&2o2-{Gx;b2fVnTE@j;02@naotYnDjo+mtnTUM+%`)6Hc6S`F9)_sHS_yi;0~Y=*$j zcBJD7li_hB=Qe-yI>Q9$jU^r%D|}riHck~Cr(nlK7YO#RT^L{sw~B7eQLvLGJgNe$ zc@-?1JSq}L$rT1wiMbpNVb$c!@#6PcBGH{`Y&-y@Sx?4^mLl#6neR6sdJvLsiY{trQ{Vq^i~6qA27hER3WlqtfUARBZ*X;zriUslJ+}D|b_LK{ zgUu?Ewahj9Fl60>l+NWxFMow=D-HA@;8N)Guge%<(A05AJDANZxKB0iRL)&!=-|G@ zeW)XT2aF{J#4Ll5^Cqj%E~6?xLE2bUW9c9V&a z75&yTmUM~qlRLMY@7MlJfY!1lKeAYw3%sSL8&J3Sb0uLJ6yEzw3*|xN)DZ+Vh0e14 zV~%qw=FfspvK1%wrMg!2^mbYgKxZfB65Q!!_!%jYWas2gqXd^evk_1y0{ac!*-1O( zothXys5s`BV7`7E$W5PW zO>Gv{`)AXf@YbC`xC80ds4h%h$)PkGG3V}dnlAla{y7~n_JEu)mfVA8%a9T>{XXE1 ztISb_#M}P9rWj+*q(9EfinaNzA|0g+HlM?Nj*wzx5ypAzPM3E1kvf5{Z32SrYRw8m z4wW$WoYj62<&_jGnRB>4Bu_S0_2~bumG7tqLHntq+l#`& zF$$A%<<`)@M&uJS!ZXj#4A-r24HN4t*b#yteH3Z-Ne=2CVRMRf%;iJngyB97$MU3^ z_6t6^b(EHJvpmZ+jVG~`iy@Tdf4y88tmOt5`1j8bAj_d&kj-V1rJfxIkZkpD02`GP zihfG#k&eqnMeXy6x~)r2nu7foD`84o-)2gwqC-x#>G*dn$edetC!c>wEg|J!{qTT$ zFV?L2y83DzrCc2D?%_e;rHad8Wu=|;MKy+vKVi_$sgnpGKmGe$-JyK?Z~CpMxr$^Y z2tuw%>>tP1%?z19uBMliBjR8C7xns=nH6&$f@f(ob@o(da`TTglbnM!FC*X=L?AnF z1&9w&W0b$n%1_DfellZkX2$)*499>U8@F!r=gBw@qJ+n5ezyH!zIv(HJb$~S_I`}U z+IPo})z<8NXS(ljYI@Bc$h{YxqzqjC! z^2Ddz5B2DSdGAk3)w_HFX3vOUu@+0pb?P)#H2X9WntvGPlD-gp3~fb|cr64*HlJ)# z{UROZu#8b;Uk51Jez&&WB?Bd|D*GE9BwzUD$oQ{K?y}(+^Md57J#7t)?ma1Iss2xXYJwJ!#g@p0h}nUUjbJ?IgTf@tm0aYM4SO*pI5x`BKGkYJn>5I966>hj#8=m^w}e|H4JYog)7^TkkH#Ry=+^3p&7Kmt^Y@ zT5Q@R4xcQRFH-qsp!7e!38hQEbt2a$Co!4 zZ3Yb?GoLFEt;a5Z9`ec1D&iHMBb}#8b;>^CO1{3RXW^Pdyt-0))m#RpqX%Fyr|k`3=9G*gx8W*Jo!KBt<@zp__<Zqv%$d4?eJGa9VN_L5(bdpXZC; zBq)kaA)FtG48RoFB;U7C2_9Jn=4Y;|?s8YCLC3r2h=er^uxAQ{F4Wl=RJceAwD3uH>g^uqujRqe8&E=sudpve!v=|t~PDGZG2xGoP zqmEj+yR+Q^TJ$NR#@PB;5w0J5|(l6$^0q#u_$oT{1oAG3(Y8vHQqTFwqKb1J+958}{XMejD^Muev_t6o_p+(>^PZW$U_}o) zZLDL>4&R<7oBn$TG?d6WnlJta<`v4OG5^=H$>=yW!zoI23XmBh#{-F?55 z>nkm0i{It++ZKNv&)plHKJYKSo$ASh&N#wNzLQNmmRB|cq1|K0rn zPND>FRz07cAEk;;8Rph+nV$2boZM{XOy#91CqIgO%N0n?e{rKU_qb8URu+H4fewvu zB3oC9H+6wiYv@J!hyT5^ot6G~O^;iB0%a#!azQ^%{;5u7vI+kQQ(8#>=0B+%on;P` zv>YfuvlbR;wR9K-oCAdoVniKdh!N3=0F(ozkwof$d{f=Z;4E!x0hj^A0zlazZh$oT zN(SZfTwJ<5fYX}T2^Fm2BOM0=Vb^-1jmsN9aVeTANvg~->5$%ncGHjruS!|JbA}?e z4{0bO6zZ|Bk%HVK@Df0_Y=}#>vnh#)#KYh5&v!#4wGlQnk)5S)0$)d38%6j!e6j*7 zwq^F|DQTz#%@)U1~(_fY$qS$+MP6^RdoPaW(> zwK`5TAs^}71Okj5&tfbJ8|m?ALcE_qn;}1rHAb=|BST&TZ(_*r+#BLLc9mns6_RbK zqK2;+6MGqn$Nfhyv@*5~`3s#mr=|{oCh9n3KgnYRG&UcPW;6O!XSK0%j1w=UOP&3m zg2UpySdPxU@m1+vy8T~ao}rTxdxPx2K+o1sMs@6LaQB(vZlM~tdKreC#2EgSA#G`D z!Ht$u#4)7vXo?|wJerMoG!NVuG9(^N+{kz|1=-#%%}D2Z(N${5-B)OK==&}HyMGBF zfhBaNzM4~02BJAN2k^tm^}wIW65sf+GI>|Vp4#F!^%8EInH~1jMu|SNr@o_R<$g?- zoKkpmsh?$g9VPdGSaih{g8_COtmPYno_1SpIC1r6?b!p`*^!a38xd)*zDl1Kp+X zrEIt##2L~^=kItSsq*Fpj9E@i=5;9Z3jCPUO4Y5T%G0!)j=KUswgN>h!-F~d_rMM5 zpXg&?+Fe6)X4-XzeoWTs{uj#(=5kthPNH;rIRAw9bx(c=+<$IMCV4i=*~Ouej%PG~ zyNzb?Y6Ata;i*AwUocWdD%}nF^Sn-RfO@{gJ?C!?p09Dwvpx%+FL%$^Ywu6xn|W@3 zCyz~N+>?r!j&y#_E4R?#at8`RJG{#kTd^67Rj%RdFl3PN;IOn=s& zJ7ouV+c9oU5!z>4SFs|$gC@4FV%@HF=fd|01U@{MMmdw;X*KI&qoSCi7h)g zwdMAM#_L70G*~8sw_(B*Td14;qi@yXjG-wy;w%+kw>s<{A7b}C_k2x=-Iv_+TOWCj zbl1A)$mZaAxt_VCJDNI~rD)MxYz-limOja66GM{)LdQ;FY=iudRFOk+BpuXfMBSB#xR%4P2P^DV)1qkA6yUhsUbo|ASYMa+oAQI1c?mz~NJ zEfYm4Ehh@`PiX=H`Rsgt_JaMjNX}X`4zz$>Hf>!6TjKzcymn6P3bfJ!Q+{CMe0@ok_ z$f4SfHN03xmX|Z5>}99U9GmR-Ni_2PkLdKMf^?J?GybMG*tXH~pPdq=!Z8l@bFyE?E)4cc#wjU2P4-) zRjH!aj)#1a2d~k4G&pzEr7;>ku0Y~1Qkb95vq@-kI$4s7;t%`3Ka!~a&1DQUkn!pz&z`?(4t6YCy#RW<2sQe_q}`%ftH62P1Yf_}6D5MrQv|y9HPMXHBf!Fdw0G zbGM}z{Zx2C4vi1iFF_2(cop)O57qibuH#Jn#q(s3a6`o%25woq1e3TEuva99BKJXJ#$8#FPGtsNwj#c-SZgfYLqribM=masU`Um${lLrehdD~-&?Yk6e0Y8D65=d{ z<;1l8CUSI@FXJAAp){~8H`a#U8i2)hkecS`joF@xKR4TR2S1>GdDpL=hVSb7qf>A00AMta6j(6<{v3D%3tC|IaT=)8~JF7;DAS^raM ziC^fz8HVSFu&LlHaFRk9IVt%Xzb8%ZfuCBO5WXzT1Ql8=EX^P*Ivg- z)BzMEZa7johi|0$_8pkdmX|r1(|?7RmG}~xnQ@>-C9Zsci6Dtiq5Gx&$pMm#1SVLe1k{zE`5>oNE(%l{0zPAdrl1F9?-8V>6T zjqGk}f#NTAr(7lF_&q$r?^1r3v42#uHxn^OgZ%w@{&-MkDn;ngg%4Y=xQjkG+F*1{ zgu;F(7wW}NAa6E|jZ{=l?#@G0K2G95nDP$)2LaX|L>&y(!pzVo29m4gNXKq`5~e$p37H`D;i$vaRjy|CqtZ;`y0% z@Hh;6-gdJu)?4}06_ROtMlXGOd+crqDc1mA^zk?~CnDNS7;axf7Rk&8Cr-7G2Wy?D zK#tDAsIJ+)>Bu`e)}>({&V=Xebc;5v$CfWk7&+CC(wP_ z1JVZ%j^Uq&j^rOVoHjwX?{H|WgYTHlB@N_(&5Abw=RL~+@t#5`+Li;KC0F^@ayIW# zAO4iH9AMa#6t+GurTFV1Znd*Sl`~wG5*c??IVh+yiLYyOz9o=O5#Xz-Ndu+-cK!unkBWDqu`7Ct-x3sm*?o!e#m-5qsps*U zs;R%ZZ?k%TyFd7Li+ww2&I6tR`UZ389vsq5`)X8GD}=BW?^DgbYI31foA+)St3e}~ zLw%-I48r^u5XnGsKk#$W->kVTjZ^F2v$g((1jQ1aqpWJq5bCh8d6@gNzgqYXEl`BF zg*+l3k^cTSKMCr61|u&lc>~W{7Kg&xOa3Y>Mmq8-RGHY6ewoky^h^sE^EJ{bc256| zF9cw(A##}1VUyUIu*HR3_*(vsdc$?lajnWFaxPPZaWd!k`onlTwDX4M_XmXKF0^u8 ze(T1dqR#IDg^B;5iPbE3D$5a6T~+3G(frZK4f9AYECxV|S#&U=l~q>65$ zn8@-poABch}sxOAFy0PY4nxI{&&Xt6IJv3so z08)Fn5!|TuEr!-#_anYaOgw~`z);)Ezw!(-)b{FL2Cm8+`Cj2R!Td|0(zIfZ0n;-2 z_R|hTk&b&<2s4{sNlAdx=NPU7-Au3*=~P&9`f6K#mr~#@-=mlGRS@jjoLbmCJFTS| zt=0-0zr#9kwdd_E!0U?L^afX8F5Z|&5p`Mqd5(TmEk1VC;2mLIIQ%q5QiYSB_bB% zqSHy9UyoQ~u$*FwblCY5x4|w3m_P$c=~tQfyw43aP9`6u<`bi@95gH|{j@{OcWKxE zhxj>h;dmEj_eM7xX&(^7wQ=9**=ww8 zDjb>B(9{rXsBUbyq^`xQZ*K8wT)CQA)h#2u+40txH>1w0_GZkB)wQY_YR!zz^2Uv# ziI_Kh%n!znZB_Tjx{j=a8S(mhnxm*U{E}L)zNL9KJzLQcUh|9#>S|(O)cv=MdjGL} zUE3V0*VQtn5!PkcqBpmJaq(7I^uEvQcuWIss+&7)R&`TtV_o6MQQk}jtubcRR5xh? z@zy#UU#5uH+~l2dW@V)}r@5giR@V}av%bDzj0VTL zH>bL_l@VGCtzN9zn_1m5qk3lD7_Xw6;4lF99Y zJ_68ycWb1sRxr@~Cer@wISq~AwzYa*YY$GDP~AoG>PF3Vcw8rPmX>I{7z`Huu(A-3Sn%uOO>bcYE8=I?R(?rF`cr&V@ zCOvzt5Uhs9JY#h;>spR*uWOo{F0N~7r3tUTnt|44+55tgz54+*eD9%GYbTg=4QTNu zPp%jb#I@N%`smApR+(4E{Y;<$|=*EVoIxoP`?B?2dV=qRFH(l7& zJh#aUhc$eTbr;f~NW~jb4|qlx0gGryFox!u5w2VY4)LbehM7%uwY@+Q%)JK~R0(*G zW+^?pt_i3bB?R2iQr$GureLh?O8uX(x5hgn2L1)#7)&)2L|t6xHN|JofE>VkI6gOQ z@Uly}BKgxJRYWTyfL^%x5A~|&%&DtxX|)M~L;8e7MM*sbC*jrVRfDhE2FW1Jzp!Rj zUCo6;V9cA>9JjCPv~JAIG2ZNkwuYveUVKik3c_qdQ){dmY`2O>^xuCN7t~+V+|mNy zxq-~B^Jdn?Jm|$FNE3W9yP#C7CEpLhg;$T*H99E=Q!VX#jSVweXw|+P1DD&Vv$Bj<#UxS{Ep@SYOB3`INEH+HUZI4p z8}i8iSUwQBjwVb>J3c#R=XptjhVrl4yQF#cjE0aegCUp}Qz@8sPW46cI60c!+ zbskzS-sGf=V+)1u^C-x6~O? zq0M{AO^NEpy0%{8B6#D(MesmJy(I81BqOv0T4y)I>$Pg$Jqg`@fop}>YCo72->ObEt%YS!ZC&wprd0< z*P-T2Vt};RTk<|G$fE)PTN&8sK!_W$T72wQs}+ep%4e{LI^yWVIxzP8ccN{ zZZ(p?PLn+Cu`|?=S!tox$*9S!-t7CY_Crl$GjyhQ>*Gx|Qo*9FaIXAxl<(L&L}f2) zs;Ax&|Ca)!wy}AR3{fvueW66RSC88EnyP0TpJt3XXTkN73~neB%drbio!bN{oH%jX z88UH=BH~TqAf4S?-&j4Mx<0{_``@tM8kiMQH-M*YB*(q?HE&?u2fjgpggxZ-iRz`h8U|L z4^wg)=G!H8(_;UTUXJ|1{|kBv`5ZFd$ufXmnwpzNhsGr)p9GthO~DE-v`6aeuxLP( zsk??4f~TcnW`oR~5kRmvGcjq<7Vj1}cTCE{A4rG%$}?sz7J<* z0CbD!CQ4=mpwVcdQANh6WyR$ND)X_i5yPXWJzH_XWTQ>|xnloov%#{?#*k@K@cqy2 zfSKA!Ns%0h6*P4+>Ln7Jwm$Yb|*A%O6^G2v6Tbx?GF=NJfZEbB6SaW5j-NW9r z5vV`a+DY#BwdMlt9U7H%7#i0IgKELwB)T)2G`+0e_1#)#%$SkRqQD%{nmQEYxNy{- znV>;G*oUI{IQ|f8jDG@q3BYLW&#Hs? zo(S2L=DZ8n&$X=aY@Ns8n&QkgRMsYxdK!ao`uao6*JZvj2aU{d%smo%N3gSc{6xK6 zRmY)dn3jOgf~pmd1zhyM+R~a}rk{VMuRfGzqq51E2kGBhc6}Fg8QG}u^)~r3D>n2$ zyjci|^_U_~I(5=Ba6p(6bBv+MO8-6h&MEvec5B}ND9~1u|B1fhNgPCk?;dMn-?MNoP!Wd za}D;9^GQL+)2Gui?h3EfyVR3IyYTz+Ov-aJvM~HKa)LL1#0VOj(#NL+(Tcp~f-(!o z3szZx?>S z>Y=Fl35R;Hzb4rzc~jp|hv^*%4r^BMpbs!In+2(A*CX^A0K6N>G_5|S&49q`nre>` zl&4uE)3jv80|VHC)x`)8BT$w-g41m>>}2k0+;eR&rk6q6yFRcFoL8Y}>uoMOXQMW9 zu=udYddgr8X_2E@2FA5lh`;E<>J~Zkj^VS`sF~1%x-uqLcsnxJm4QHjA<$#uuC8T_7^iUL z;l19p!WOMal^QMUT!Y}Pnq|pMi4(U-gdOQEus1^b3E@6MI;5@^CJOzwtmxeiUyp0Q zu^Q1Of^hoVZO36EI_fco4ciNZrZq7GpgSCdUV?z!cHWVqg_EW4;$}M)ORVD^rq}wZS%9)~Ulz9d_BNO$`kV$Al7V znxmO%%`MYxH^3U+l^@8tOTzswoMcXSOYI1iPMNu3WjT$5lpiDQDo(?O&%BjJ|NotQX4ZbLz4zK{t-bcz`n2&D_N&3vUFOG2TjxNL_&vz z+RKcU-Z|bhTW!pHG4Ty*DBQ(9SF8h01;Gyk)Bmh3lHQ+a?P4p%l4*HM#weexa+%#5 z>PZ)JA;<*R6FIBXM(wy|F2x`*?r*0Vv$o3Na@3o(vMQ3PUP!a&b(WazpVguEXi}_( ze66sxwO$4zIf5?SRznZrb~_ruXiF;dy{jkFwr@+WWWCT0SQfpX82fe62I zP-2;fJXwj21)uMHRlB4{AQA>6SuaegbrHKsvr&MaA}6wfT5$%e_4{D+2@@K{hU>o%i_;?jfun^0$bPIeK82hs+&+`xy18|>Q{@S!cvDerRE4wiPsao;~cG` zc{=QQm299^Em=IF$l#Ep2#%tM*lQU>aP_-A%&<;)Plh3f1Y+_U%jqn04lFHJjTQv5 zZ@Z**g`6lj#m){;))T`R_DtJep)p;~DyEanOq%OA;*afBFC|_MCYsAC*789`I8jn> z88d3lTD1>T^Vd`vUm0+$m))LoEB-w#x;kM$+d0dWUfpFZb~BxFyF?tqD=$N`uxTVQvyzylLAG&n|7eZ5grvLpzfW%(ABIz$$}n=o zCC0t=2N1w=H3^oVM;Yd(teHKl60wDmNT&cf8aDS7tXm_uT(~0iT|wnf_$t>C>AY4^ zhottqRgaiM_ROqOmPf6ixfB1ew_4qE31%#M@l031(16EBY0uQmzSgYuR@U|KKIejl zBGztLQZxNw{~&FajtrHFmN(~b?0;kf`L2eITa{!x;3U&ja6SU==*cImoY2GEU9sKH zImUdKa#r{EebI-3uGMGW>aMeIPPRPPWDTO@yiRrQq^1(ba?Yo`M<*U0E%f(6jKC73|kbZLfZ`{(v`7@0J?6a*y z$@A>BO+$vUEmbPkt?ezA2k&S$vxp-(u+=lbY-Vdr+V=si6hAZVs8uOV0ONR6gozSKc zQ&PD}JU!>oxLi@S>C7eOq+C00>mqY<`(<)9*WP)IHjQlQSYQS=JhEvLR+sz8at)5@ z$_#*RMn;G_;i#+A^f^42^~B`!>?-S>?uoxV-(~Q#rZ!ETeD>7(No0nCL!^nj7P<^c zbIux~dFj^qFaBXl|J0 z_}y|4Ph!izvV*e_y%lQ?8@*xe?WCXL>6VVmu>rI1K06wCYdcqTmWw~b{!M^ayo%X;D#goTPHfoy>oxhT z<#z4t*=-Z#{<&(Cm8;Ay%Sx17eYP59c9|!-S|%ZThRg|L+XOQ@St-3S9jjI@8q>L? zeJPiYTDw+vdd;o#CV0b+$L=~_^qY2H?7`6SwiLZ&2E7D-YDZ^VrzeWfj#I>P75B{B zu=2yoSw^bf_-C77#iAeW^>ldKo4Rx1_6& z(t@%#7j+sgG`_PI(G{LeusTLltc$H>`s|j5=}l9;j7||QiTcrS?X8$#Z$?1z)t$?o zOqsgk_Rh$z-G%8z2Rv%5i>=((^yHL9ubF6nLKSGcGd_~8cA@Farm^lx^i-?U zt2n;WOC1lf%{X-iED|Qmil8`PY|{CnM=tPcM#)CXaf--)rGD4C;dcg?KUV_p~QhGVcCYsYL z^JC5$-HthI8T%-_2_;TN*rAiBNmq1@9q-vKsfnF9&cpzcH@@0{8qZv#^E$e4wxDk% z>yp+r29oAoCJ0Qd#W?&xDMebA;`~!gHp4|ELvh;-7m*BC+n}n+U?PaZ;mjk)ZnMlR zcC_Jh>+*9n%c^0^S$B*nWLDTdi_7wBi*bsE`O8|usj@yZ1zHzmb0PQq&Go9&hRMQ& zKzrh8Xj`^gPN4K2kt^@bp1mR?BgQ$M<>?fWGq>yo1IBq*OV`R4yQ=H0$JB7op5S`J zkXEzohPRAl0ngm65wG;H&PkrV@r$XNl_xnSQ`8`8j&84*V6Pj%P3CS=woBWs$Idtx zKd~*1e#X#2=gSf-yQCI(kA@U)DjBo*lf3uIH2}vuV^vn1FF+?jaa0W*)>^ zHA+saMpdn8;A5OB#tRe@PWC6cr0Wy~uDU{|*J_1|PP3r1*r{-Gsmk~x!^1w+iFO*) zFRc+_J2bepK1|$IuKTa_QUFSuw$QlH|UXjz)dk+2gUp>{{8y-pI&8c0zc(lzkT9 z9MkSJW`vcv3DRfh5?3QyWj!NPId-R6_*n@IX<15ULszy~EXytCCle1G(OdFGM-Z3;kmvu96mwv^N|skU;56MM7gN8#jd;6poyj_2kWl$~9I9^3@Zn$uL@ z(lq&f=XocNt{HuDWbc_9Wsa=n0Nt%JoMa4AE(W)7Hcz%XJ;=wPZ>gW!F!`LOIW3c? zOgHhm`l)qItaQeFZNXjGvIxD_CFk$%Nl2_k<39Jy#*v-!N)P)<_Oh1X9%~~?)RX6Y zyv|jNOh9fSu@T642U@UTSK7_8`qZG8b!TN|b(rT>Tf%A6xGER5;#*{f%&g)7YHwwO zA)76a=K^5qwl40*F2VLQmuPSg@$6rVxn*tlCu(S!dpDjVj@M!jc{)9Jcx&_*QPG?L zkvCy{f_gOuYeKDWqm45$bA>w-75gtYW~>%#!Q&UOS57>85jhh#HU<~@o%>wP6jH?0 zs8J}7ewYNg({BRft2JN^4Oh?^Dmj^9C1;elTro?+n$||i&dSuYhK=T78fgfIAf)CK zA@@{*=o8TtM%Arcn#CR7;&!tS0?Kne_Ik5j%FUd%m`7+CxjeMnVjRgv2bhWJ^l&T5 zqh?qd?xAh7hZ7bRJxfzoVdl!t=q64Cb2iDNWzTEG?~K{!+Q77?*;6JrsZ7qUbHOua z*W;O(Gu4%DnmxJRhU=$JZJsjyjC#`<*)7`zL>zXa#~g!&w*%xVnAtCSa{I-G7)OUb zG43r})B$^vB}0J!BnYxgR<3X6mw_uDPEk%H6Ib za&q6fylrWh3CK-b`|y)I5`gwJz6NKnbgdjI>f0SWu@uYmje4(z40Cp;`kJV<1$5ah`EKUh&9{T^0=~_BYx!33P4V^ldVKeTYcJp3e0TD_ znwMXc@&=C@z7>3vd^eKz`UT+Tr4#P^5b^8yF64VsR$ekI{2#o3#g&i31&Zqq%3Q+t z_MNoLSKx_!w`f@6BQ#CYF7 z!8k9@DnC)fZ)urA;_c7%r04T(;yaOVz;`X*TVL);Z{oX_Z#&=le4F@A(>4AE@fQC7$ftR= z{(JpS)$%7OJVfCG=U5yLUz5hS&#~z)f40U8fW}j#sxb6AE##>d&${+{39crbg;tZ( z0{37jTG8B#>`X0}n?9V8%SJ>VL~#$y*#{rQx5w(iL*qr(%_mz=dwQ6)O_Kve?vl#| z67!lD`!KfgbBooCWz3#;agi~bE^A%2xN~$-kvaHskBpmom1a{Vo>g{aEGuHy+CFhW zVi%W+$`MpOVBl%;{k%mOpl-Io6U>B=eFDed#9hJTX|2nI z-ZHbHt@OR(7<3p0_NxcN;0=nL$!Y#6YSr5lwA+tt#s}n#0Nq9)#3dnPW9f9J%`~&$+g@ zcAQ$&YVKbctVVWl<1SnxR>ZO@B$QOD&-Hlj)|j6+K#SuP`4w#Oh3%{FVmk)>zH z)-2K^wb4a9PSeTLsYu7)LSb$!nClfen2N06GC9JG# zwR6-cp1I+mni~Re83zxMR|*xa;Id*buckf0v5wQ`YMCgPqZy>ewT;_cPRn=6zImI&&-o2?JHMaY&@1iLVcdOf)zoe zpi<8u5FdLP)U1StiW9Ua36B-1{d6W%k7*0=J{ zScM_XJyfgkjDi(cr$@3@VOqe5j?_WUT7gp3#$Pu;H7ZR;?xpcW}NZhkiq1F8CR|4aON;Vc zJBze%s?iO?w_IzsVfCtxDAE(K%jEu_c{~(L%RW{SL6XX2DHTNMry9i^e7{+Csc0!DaC_9bOMNLcykFTN2Me-pAB-@MJ`LUZo%OiFtVL3&OIQO`Yk#;>NG}KX}QI_{rOYy@ashM@e%q}*!tjU;o zc6+EhOF2aq^2*Uu7q5)bWri6R{iz2+MHTWqvRSy~`DpuuKSMyIa5wVmNPY6Y{qjn4 zAK$%P%o4S;D9frcN2n=YHOZ!;ORRU~j+-qhGjN(WPXSqD6I}so$jf{#UQ#r|G&S1% zVnpy#kkyxT$aDSDfp?vPx>j@K>8?w0H&xyxD2t;Cq3tCUo24&H73N7DFM~K<$y222 z-x-YLv-?G0!k3B40}WxNh_YR>hJ`bC!yEEl1dXU9YY1D_%?A9ECDzQoxxwKoQE2)OrmsFHDt)^Tgr-X%)%IqXDae%iW<+`I@khVLP=b7M4uvE)K} zGjen9TBb~dR%KQy=Xe(SA~Y}B(N8#jyFn4%lv!-V&Jj-vR#*6}oLe%xK9PWWr1G!X9=j^0H1@HI1?} zrw8WY?!~Nx#v)|%YHYdIB4_iO^~~%lNAMC3=7e*K%p*xcAzKv-#l9g|UI1W+n2$-C zf?@apzS$^wN&G!^ufSrXlHc)?-zzn5g2yqxVLS zz=hn_hvxG9x|FpV*fy^3oiqjIL<7f6C#wXO79*E!k=Z1&o&k(UBE#c-muwkxHjgz+}@NwBQ?t?hUp4H9(yl2vVs;BdCcC^ch7o7cH? zcC3`G5!&1we8~i|1<#rh`eC!Ahj|Hfj(ORM7$deI)Ty(}k{%1JV_JS3xw@N{O}AY4m!+bg@Fl9wbw zr8#=dJx44j7+14326)K^h8fzy+^VWPf5HXt-X}fh&gqs8NqskLk}NW##Il`5t}d@c zz>_1kB&LRNoN+fX9nPEdE=0jwfUHATS?IE9V{e!&&1zg`Ig125fW#Vtofx6T`Gx}L zw_RWqDDR@+MX2(8TZNM3f?WGd*CsogM*ZdvpL-b2m!K0%AEwhU(~O}>W|p1Yi&hYW z&ps(ALTgBo86Q+Ck|`a<04|X?###LVA%No8gNHR@XuOjxI zT=*Jc?}gw+40~d_p2MIkteDHR;m>h3^zy9PK*+P%mUQpJ-q{0Jw#W=N^8z(XTe32Ljh z>xzuZ6(_%a`G3|shONRHVUMXsC>z-rvRNc8z)tQhx9So!OI2v*(w2Dd`c#_Ecmjs@ zlk6Ya^vQXTc`u5*b0q88K(o5%xXr~-pi)I;k$4QTy6yffbc|rk@`?`DSocD8V`J;P z)}0%`9Eh1_jRe|lr*-HFwTuFi+0r`>mhWK>M`5veG2V-2nFsu)$~ImUnAwmornELk zQWUjbkAPJAzW1WscBZh6p_1|2tB*%jOxSnf-O%q-7q0Eb9|v0dR(YBh*PuD1Sb=6m z4dEDYIHa>~uZ?zHD2-}=vdJaR!4L}`9pl}Uy0Y0(S?KGcmLaUXngSMWU{!Wq5&GIa zaL%EiYaQfxHW3-KK+E}u{=)-v6O2@`aAjjj->?rjOfYU(-RSdfEVB)~j3Xrbh9Kiv zFm+jEGO{$;Jvo;xE4`l2&-mrkSjqP2X4{+Q8LTNs^3g|`{wC>PQnou3? zwq&AM;dOO9${VD@*D={mgL^H6ZX#GA>o~TOos}@IvA|%EOph+WJXj%p5^a@5_^?;4 z?!d-AO<M|sRt-p{0*Y|IYx zR-Y`?`hu0ry8$uQox+qCrWx6^>QaqLn`Ary43S4m@f-4mQ_UHm)xkyT`6((o*Zq4B zJE<_WUj1|qrDbxSrHeo(hi+DOGKAnjmcwq*O1vuofm+4OQaI%|n!Ycbas`X0gz(!h zZ{xLeON&GhGb>frmK8KOy5NA&%Vbsq=r4XCX~p@$S}!XyE*PbWApp%}e8$vK9~q&H zbJbDPYK!}h2NY>{inyKO%+-)oU*AjX#{Vd%k!l2F%c6`+Sti#H z!W&iOe?PEv!G^RebPG3K8P#A`sb*gNZ?|(Q`F6fVSF2r{C6z*V+*Q1W!t5-hPmwLX zSm&W^WI547D^L#@MM7lbEk=`VIMOe-gq~%u(#u$}{#LVDg5%u3{>ZVPodpoCWv(xx zTisYN53I=8My(x~G4$N=r)xc2zoq^Efz~qZzSodg3E4ZE^I#drFLDqa5}r%iCl~DO*dChMaRxvUXE$vfoYjeSCQBjiloTI|vU!t`{TO$SIlvc& zK)6wcGWuoan9my4f;g<)ws=ig-LgG>$Tp?Jk~DK#3YSTkV5*v=lvv*Kau8t@@d9#C z>ZY*U1uX2Y75Jma8g%(#wGrz;0k8 za0_q?a5r!Va33)F`a9`Vf64=EfEB=IU=46Nuo2h|Tn^j<+z8wb+ydMM+y>kW+yOiQ z+y(S`Nz6WA1@Hi{7FfzZ&6@|D2kZc@0d53t1a1ZH0PX4BQ3m04Cq2Kfpb}ZIb>Dcz`?7(6xkm z9`{gz8-d$^H8Jj*0(SvD{( z;{@&kb^!Mr)05r-tT>kYx4zgX!0B`UBhu+$?Ye<$-G|p-U;_IG*tW z8-dG#dw|;nj%0jCkUpCJ0@qYgAGi;=9k^{Q`A5j*eLPwj0?E&WX2EN0o(&j z)-e8~zyquR9so81mrtNQ;5Ohcfv19(|6|-Zk$DF00?q^OJB@q85}!ml;KtLL4`59# z^KlIQ1y%u*Qy2$uO&$FN&a0;!@W52)cP#Z9X-^>kl6*gK*9`h|9PwH78@La+1(=)- zoq&6qxlf&H~LthyDWhJq#U26W_)7$Ivc!yc>a~Kcao$4&W|e|5`iZ2!!@L4((u@;0uOOZFtI6+| zPOkxO;coK*U`=s4z2GGJTar$11uh?$PVWF#`04as;2NMeo^}sSr<;Kl$5Bq=z+J#S zL(=JaCo>;I`Nz+|r!cNl)9DU@lhWz!z-_1VPhADp zQ+@*UX-ua#0=Lahr}qPsXOVs?__+_g71+pq>I1-v^BKoP$^mx(w=ASQFu9oioJPNv zr_=JELASM~(|dsX_~+8|_z#dZD~SV_zdxO>I-P!W(r;k$QqqB?m#5Pewbc6{_<=PW zp#v~^HRUJMKCls(yq5n}3zQFP)qG+fILnKz@nc5~I4HR}=6Q&PhidS){t8>5m_Ui& zP*OT$VDV+iZtwIXPd)y`p-7&sUk}{&;ydYnlAs^KJD=}X(osp_hiUV=_)7Vyk~*ct z-xRMeDcw*|Uy@pvXe}x!omS#cDM>aJPcA8)Y=RUMe0THRnFrq^r0@C%@V!mFz0^wp z-ACF982=v9lP*!x_>LrfH|f!F){`#n3z^(U%FicV`pc3Rek8q1%O4)5TKt<7e^Dg; z4lO@0lKzn5kETCG`i?yPe3|s^qz{VVNyPJ)KbmwYe?+8wwU&qV!;g%siFBc7DonNG zT1@&r(g#G+*J^oGZTJy9H9qw@N>bM(rj}G}>Q`Smr9~w* z4JB2RODZTarKFS^u``}J{BkB(2# zNn?VBA4z|Pbf5Ggk_w)470(-_S47Iocm^QYRiqofFymxzvqO5clixx96Otc)u*5&RBsrAedeSRieJA~bq|5xTqS}n&`TW*9owAs$yD7Jy za(~eIyH@z~nu4h%sZ9yEa6`YzB~|MR;};c`R7}p|$jQa=g^{Fb#VfN@>V@5;ao*>} zHz;K7eC?g|7bF3$)^?_c?ZDpa3hPU1Rv4E$d4B$s$;1SQaJRSS<7L5cQhbvwl?SA)E0z zP^_`oFw;nqo*{oH`M;KYgLm%1h38yXaBbq6ewzx{9Tfj6i=E{0k$D(!5c9*{biE{) z`Hwe)aa!>*ekT{#2{VZ7R#R>d1m7Km*O33D<|}^)Rcb?g z%D{r}Dau!{=QsVDS>iJ;tO=N$Jjs89Kn?k;1)uclYzj;-o+AY&k`$n5#dmNM>xAvU z;m2tuse;y67C*)p+ty(WCqAATKlKmbOZcqfx9VJ&v#Gd|-{xZEQ3+tiPx`>q>!DD_0$tz$1+K8l%&p0>5=ZL)t_peKc7Q^ODF~hXX`rRn~Ox3xlUCk_CjHE-G!Sj~3vmt)ASs{MYKgAE%nfa&Q z9_p1#J^e`fGo?RClKuwi2S}GbxsTC*1Bl^UdQ=CB3V}pAQ#H`g+pmkJ-u@^d+p!(t^{9?M1^c4Ax`1XFL`hSzGryC0D zgx{x?RI!qz7>H%}nZ*T1pwlw^KhyAkmN>kR+{R3CX_JriVk9B!4aWRR{N^XK6lbJ=T&?#p1t}`~_M0Vofz^zR>L<@;8$| zS?Vvgbem7`Dbjb5ew>b9?Ux82##z-fcG5I4Fg_efnOY17=aez?Rn3NLV@XeXy0nX3 zD?OI+G?BiO^r?~#J!DxqQ~Ntoiju#d{J%&(8gt@OBdb-fAb+d=^MiSIQ|y9 zM-`XaDMIg&KK-G*)Rpnc{$-*BN#8^Ib&`%;_Of4KI+n`b#tOyT`L3sa#i2dvzvdYy z{of$=&$_}HCA(vowzB$U+nWu=@#lJvb4u~Ky^G4=MbEuKdpi#6Nna%GF%ImFUocg5 z#qkD!RYXl>9W4tgzU^|=XV-~7>$M+LJFhl=LtZ;i^_uWUJNWhv>PfF4tm~WzgQ2j< z?I!Z82KS`DCHc@XyS>PIEX!64?e*ShPAi_5w;z_Rtp2B+jkFWpFAX4JGwEi(jQ($C zer2wQlD>uXUnPhbzIA+3a3VaWj55V2aN&nJly5w`C;d&rS^U7PZD74sdseq3C>llz zXKMe1PB&727xnYmEz+O+$=^eMv*O*?lm4*guOPpn_yhb-E}l=?Q1Z8tzgYS6n)n4`Pn+?mecloObi{a`iSCH-{M2G> zzzWoGIOuw_k691?9mn>harG%*bQ&EfQQ^Zo$lpW$80()G@-{E;M>TV$)^M#^9ld2W3Wv!fs!8}>~fZ3{0h+P5;CV1f5`M{BKg(i zFDL)-kRE1#0mp>%+Z_LGgdVC#Wd6FSFK05pB%H-h(=ZG!4%ta94(ZPwls`cE`=mVm ziJxz#Mq-AaA0dCske>9HOp5)HcAg=@oDh}gU8yJ*neHrdxUz+Ih(pIoDXVe%uttPEfl#zQgty$(~Ux8*}MCk?F

N!^Dq4e{^g+fEDp9+&N>* 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

fiu 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%0D_!X!Mbeavz9$|vnJj=X_d?a1QGuf7d*D?H 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%0A_2?e+tO>+3c|Aeg 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

m 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 (3, 4): + # https://docs.python.org/3/library/importlib.html#setting-up-an-importer + from importlib.abc import MetaPathFinder + from importlib.util import find_spec + from threading import Lock + from functools import partial + + class _Finder(MetaPathFinder): + """A meta path finder that allows patching the imported distutils modules""" + + fullname = None + lock = Lock() + + def find_spec(self, fullname, path, target=None): + if fullname in _DISTUTILS_PATCH and self.fullname is None: + with self.lock: + self.fullname = fullname + try: + spec = find_spec(fullname, path) + if spec is not None: + # https://www.python.org/dev/peps/pep-0451/#how-loading-will-work + is_new_api = hasattr(spec.loader, "exec_module") + func_name = "exec_module" if is_new_api else "load_module" + old = getattr(spec.loader, func_name) + func = self.exec_module if is_new_api else self.load_module + if old is not func: + try: + setattr(spec.loader, func_name, partial(func, old)) + except AttributeError: + pass # C-Extension loaders are r/o such as zipimporter with +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/METADATA new file mode 100644 index 00000000..56a3d6ea --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/METADATA @@ -0,0 +1,256 @@ +Metadata-Version: 2.1 +Name: appdirs +Version: 1.4.3 +Summary: A small Python module for determining appropriate platform-specific dirs, e.g. a "user data dir". +Home-page: http://github.com/ActiveState/appdirs +Author: Trent Mick +Author-email: trentm@gmail.com +Maintainer: Trent Mick; Sridhar Ratnakumar; Jeff Rouse +Maintainer-email: trentm@gmail.com; github@srid.name; jr@its.to +License: MIT +Keywords: application directory log cache user +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Topic :: Software Development :: Libraries :: Python Modules + + +.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png + :target: http://travis-ci.org/ActiveState/appdirs + +the problem +=========== + +What directory should your app use for storing user data? If running on Mac OS X, you +should use:: + + ~/Library/Application Support/ + +If on Windows (at least English Win XP) that should be:: + + C:\Documents and Settings\\Application Data\Local Settings\\ + +or possibly:: + + C:\Documents and Settings\\Application Data\\ + +for `roaming profiles `_ but that is another story. + +On Linux (and other Unices) the dir, according to the `XDG +spec `_, is:: + + ~/.local/share/ + + +``appdirs`` to the rescue +========================= + +This kind of thing is what the ``appdirs`` module is for. ``appdirs`` will +help you choose an appropriate: + +- user data dir (``user_data_dir``) +- user config dir (``user_config_dir``) +- user cache dir (``user_cache_dir``) +- site data dir (``site_data_dir``) +- site config dir (``site_config_dir``) +- user log dir (``user_log_dir``) + +and also: + +- is a single module so other Python packages can include their own private copy +- is slightly opinionated on the directory names used. Look for "OPINION" in + documentation and code for when an opinion is being applied. + + +some example output +=================== + +On Mac OS X:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + '/Users/trentm/Library/Application Support/SuperApp' + >>> site_data_dir(appname, appauthor) + '/Library/Application Support/SuperApp' + >>> user_cache_dir(appname, appauthor) + '/Users/trentm/Library/Caches/SuperApp' + >>> user_log_dir(appname, appauthor) + '/Users/trentm/Library/Logs/SuperApp' + +On Windows 7:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp' + >>> user_data_dir(appname, appauthor, roaming=True) + 'C:\\Users\\trentm\\AppData\\Roaming\\Acme\\SuperApp' + >>> user_cache_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Cache' + >>> user_log_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Logs' + +On Linux:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + '/home/trentm/.local/share/SuperApp + >>> site_data_dir(appname, appauthor) + '/usr/local/share/SuperApp' + >>> site_data_dir(appname, appauthor, multipath=True) + '/usr/local/share/SuperApp:/usr/share/SuperApp' + >>> user_cache_dir(appname, appauthor) + '/home/trentm/.cache/SuperApp' + >>> user_log_dir(appname, appauthor) + '/home/trentm/.cache/SuperApp/log' + >>> user_config_dir(appname) + '/home/trentm/.config/SuperApp' + >>> site_config_dir(appname) + '/etc/xdg/SuperApp' + >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc' + >>> site_config_dir(appname, multipath=True) + '/etc/SuperApp:/usr/local/etc/SuperApp' + + +``AppDirs`` for convenience +=========================== + +:: + + >>> from appdirs import AppDirs + >>> dirs = AppDirs("SuperApp", "Acme") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp' + >>> dirs.site_data_dir + '/Library/Application Support/SuperApp' + >>> dirs.user_cache_dir + '/Users/trentm/Library/Caches/SuperApp' + >>> dirs.user_log_dir + '/Users/trentm/Library/Logs/SuperApp' + + + +Per-version isolation +===================== + +If you have multiple versions of your app in use that you want to be +able to run side-by-side, then you may want version-isolation for these +dirs:: + + >>> from appdirs import AppDirs + >>> dirs = AppDirs("SuperApp", "Acme", version="1.0") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp/1.0' + >>> dirs.site_data_dir + '/Library/Application Support/SuperApp/1.0' + >>> dirs.user_cache_dir + '/Users/trentm/Library/Caches/SuperApp/1.0' + >>> dirs.user_log_dir + '/Users/trentm/Library/Logs/SuperApp/1.0' + + + +appdirs Changelog +================= + +appdirs 1.4.3 +------------- +- [PR #76] Python 3.6 invalid escape sequence deprecation fixes +- Fix for Python 3.6 support + +appdirs 1.4.2 +------------- +- [PR #84] Allow installing without setuptools +- [PR #86] Fix string delimiters in setup.py description +- Add Python 3.6 support + +appdirs 1.4.1 +------------- +- [issue #38] Fix _winreg import on Windows Py3 +- [issue #55] Make appname optional + +appdirs 1.4.0 +------------- +- [PR #42] AppAuthor is now optional on Windows +- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows + support requires `JNA `_. +- [PR #44] Fix incorrect behaviour of the site_config_dir method + +appdirs 1.3.0 +------------- +- [Unix, issue 16] Conform to XDG standard, instead of breaking it for + everybody +- [Unix] Removes gratuitous case mangling of the case, since \*nix-es are + usually case sensitive, so mangling is not wise +- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result + based on XDG_DATA_DIRS and make room for respecting the standard which + specifies XDG_DATA_DIRS is a multiple-value variable +- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to + XDG specs; on Windows and Mac return the corresponding ``*_data_dir`` + +appdirs 1.2.0 +------------- + +- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more + typical. +- [issue 9] Make ``unicode`` work on py3k. + +appdirs 1.1.0 +------------- + +- [issue 4] Add ``AppDirs.user_log_dir``. +- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec + `_. +- [Mac, issue 5] Fix ``site_data_dir()`` on Mac. +- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports + Python3 now. +- [Windows] Append "Cache" to ``user_cache_dir`` on Windows by default. Use + ``opinion=False`` option to disable this. +- Add ``appdirs.AppDirs`` convenience class. Usage: + + >>> dirs = AppDirs("SuperApp", "Acme", version="1.0") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp/1.0' + +- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short + paths if there are high bit chars. +- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g. + "~/.superapp/cache". +- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only) + and change the default ``user_data_dir`` behaviour to use a *non*-roaming + profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because + a large roaming profile can cause login speed issues. The "only syncs on + logout" behaviour can cause surprises in appdata info. + + +appdirs 1.0.1 (never released) +------------------------------ + +Started this changelog 27 July 2010. Before that this module originated in the +`Komodo `_ product as ``applib.py`` and then +as `applib/location.py +`_ (used by +`PyPM `_ in `ActivePython +`_). This is basically a fork of +applib.py 1.0.1 and applib/location.py 1.0.1. + + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/RECORD new file mode 100644 index 00000000..2a398ff7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/RECORD @@ -0,0 +1,11 @@ +appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 +appdirs-1.4.3.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +appdirs-1.4.3.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +appdirs-1.4.3.dist-info/METADATA,sha256=CYv_MUT9ndNhXtkeyXnWjTM6jW_z6fsu8wqD6Yxfn0k,8831 +appdirs-1.4.3.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +appdirs-1.4.3.dist-info/top_level.txt,sha256=nKncE8CUqZERJ6VuQWL4_bkunSPDNfn7KZqb4Tr5YEM,8 +appdirs-1.4.3.dist-info/RECORD,, +appdirs.cpython-38.pyc,, +appdirs-1.4.3.dist-info/__pycache__,, +appdirs-1.4.3.virtualenv,, +appdirs-1.4.3.dist-info/INSTALLER,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/top_level.txt new file mode 100644 index 00000000..d64bc321 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.dist-info/top_level.txt @@ -0,0 +1 @@ +appdirs diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.3.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/LICENSE.txt new file mode 100644 index 00000000..107c6140 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/LICENSE.txt @@ -0,0 +1,23 @@ +# This is the MIT license + +Copyright (c) 2010 ActiveState Software Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/METADATA new file mode 100644 index 00000000..f9507310 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/METADATA @@ -0,0 +1,264 @@ +Metadata-Version: 2.1 +Name: appdirs +Version: 1.4.4 +Summary: A small Python module for determining appropriate platform-specific dirs, e.g. a "user data dir". +Home-page: http://github.com/ActiveState/appdirs +Author: Trent Mick +Author-email: trentm@gmail.com +Maintainer: Jeff Rouse +Maintainer-email: jr@its.to +License: MIT +Keywords: application directory log cache user +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Topic :: Software Development :: Libraries :: Python Modules + + +.. image:: https://secure.travis-ci.org/ActiveState/appdirs.png + :target: http://travis-ci.org/ActiveState/appdirs + +the problem +=========== + +What directory should your app use for storing user data? If running on Mac OS X, you +should use:: + + ~/Library/Application Support/ + +If on Windows (at least English Win XP) that should be:: + + C:\Documents and Settings\\Application Data\Local Settings\\ + +or possibly:: + + C:\Documents and Settings\\Application Data\\ + +for `roaming profiles `_ but that is another story. + +On Linux (and other Unices) the dir, according to the `XDG +spec `_, is:: + + ~/.local/share/ + + +``appdirs`` to the rescue +========================= + +This kind of thing is what the ``appdirs`` module is for. ``appdirs`` will +help you choose an appropriate: + +- user data dir (``user_data_dir``) +- user config dir (``user_config_dir``) +- user cache dir (``user_cache_dir``) +- site data dir (``site_data_dir``) +- site config dir (``site_config_dir``) +- user log dir (``user_log_dir``) + +and also: + +- is a single module so other Python packages can include their own private copy +- is slightly opinionated on the directory names used. Look for "OPINION" in + documentation and code for when an opinion is being applied. + + +some example output +=================== + +On Mac OS X:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + '/Users/trentm/Library/Application Support/SuperApp' + >>> site_data_dir(appname, appauthor) + '/Library/Application Support/SuperApp' + >>> user_cache_dir(appname, appauthor) + '/Users/trentm/Library/Caches/SuperApp' + >>> user_log_dir(appname, appauthor) + '/Users/trentm/Library/Logs/SuperApp' + +On Windows 7:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp' + >>> user_data_dir(appname, appauthor, roaming=True) + 'C:\\Users\\trentm\\AppData\\Roaming\\Acme\\SuperApp' + >>> user_cache_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Cache' + >>> user_log_dir(appname, appauthor) + 'C:\\Users\\trentm\\AppData\\Local\\Acme\\SuperApp\\Logs' + +On Linux:: + + >>> from appdirs import * + >>> appname = "SuperApp" + >>> appauthor = "Acme" + >>> user_data_dir(appname, appauthor) + '/home/trentm/.local/share/SuperApp + >>> site_data_dir(appname, appauthor) + '/usr/local/share/SuperApp' + >>> site_data_dir(appname, appauthor, multipath=True) + '/usr/local/share/SuperApp:/usr/share/SuperApp' + >>> user_cache_dir(appname, appauthor) + '/home/trentm/.cache/SuperApp' + >>> user_log_dir(appname, appauthor) + '/home/trentm/.cache/SuperApp/log' + >>> user_config_dir(appname) + '/home/trentm/.config/SuperApp' + >>> site_config_dir(appname) + '/etc/xdg/SuperApp' + >>> os.environ['XDG_CONFIG_DIRS'] = '/etc:/usr/local/etc' + >>> site_config_dir(appname, multipath=True) + '/etc/SuperApp:/usr/local/etc/SuperApp' + + +``AppDirs`` for convenience +=========================== + +:: + + >>> from appdirs import AppDirs + >>> dirs = AppDirs("SuperApp", "Acme") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp' + >>> dirs.site_data_dir + '/Library/Application Support/SuperApp' + >>> dirs.user_cache_dir + '/Users/trentm/Library/Caches/SuperApp' + >>> dirs.user_log_dir + '/Users/trentm/Library/Logs/SuperApp' + + + +Per-version isolation +===================== + +If you have multiple versions of your app in use that you want to be +able to run side-by-side, then you may want version-isolation for these +dirs:: + + >>> from appdirs import AppDirs + >>> dirs = AppDirs("SuperApp", "Acme", version="1.0") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp/1.0' + >>> dirs.site_data_dir + '/Library/Application Support/SuperApp/1.0' + >>> dirs.user_cache_dir + '/Users/trentm/Library/Caches/SuperApp/1.0' + >>> dirs.user_log_dir + '/Users/trentm/Library/Logs/SuperApp/1.0' + + + +appdirs Changelog +================= + +appdirs 1.4.4 +------------- +- [PR #92] Don't import appdirs from setup.py + +Project officially classified as Stable which is important +for inclusion in other distros such as ActivePython. + +First of several incremental releases to catch up on maintenance. + +appdirs 1.4.3 +------------- +- [PR #76] Python 3.6 invalid escape sequence deprecation fixes +- Fix for Python 3.6 support + +appdirs 1.4.2 +------------- +- [PR #84] Allow installing without setuptools +- [PR #86] Fix string delimiters in setup.py description +- Add Python 3.6 support + +appdirs 1.4.1 +------------- +- [issue #38] Fix _winreg import on Windows Py3 +- [issue #55] Make appname optional + +appdirs 1.4.0 +------------- +- [PR #42] AppAuthor is now optional on Windows +- [issue 41] Support Jython on Windows, Mac, and Unix-like platforms. Windows + support requires `JNA `_. +- [PR #44] Fix incorrect behaviour of the site_config_dir method + +appdirs 1.3.0 +------------- +- [Unix, issue 16] Conform to XDG standard, instead of breaking it for + everybody +- [Unix] Removes gratuitous case mangling of the case, since \*nix-es are + usually case sensitive, so mangling is not wise +- [Unix] Fixes the utterly wrong behaviour in ``site_data_dir``, return result + based on XDG_DATA_DIRS and make room for respecting the standard which + specifies XDG_DATA_DIRS is a multiple-value variable +- [Issue 6] Add ``*_config_dir`` which are distinct on nix-es, according to + XDG specs; on Windows and Mac return the corresponding ``*_data_dir`` + +appdirs 1.2.0 +------------- + +- [Unix] Put ``user_log_dir`` under the *cache* dir on Unix. Seems to be more + typical. +- [issue 9] Make ``unicode`` work on py3k. + +appdirs 1.1.0 +------------- + +- [issue 4] Add ``AppDirs.user_log_dir``. +- [Unix, issue 2, issue 7] appdirs now conforms to `XDG base directory spec + `_. +- [Mac, issue 5] Fix ``site_data_dir()`` on Mac. +- [Mac] Drop use of 'Carbon' module in favour of hardcoded paths; supports + Python3 now. +- [Windows] Append "Cache" to ``user_cache_dir`` on Windows by default. Use + ``opinion=False`` option to disable this. +- Add ``appdirs.AppDirs`` convenience class. Usage: + + >>> dirs = AppDirs("SuperApp", "Acme", version="1.0") + >>> dirs.user_data_dir + '/Users/trentm/Library/Application Support/SuperApp/1.0' + +- [Windows] Cherry-pick Komodo's change to downgrade paths to the Windows short + paths if there are high bit chars. +- [Linux] Change default ``user_cache_dir()`` on Linux to be singular, e.g. + "~/.superapp/cache". +- [Windows] Add ``roaming`` option to ``user_data_dir()`` (for use on Windows only) + and change the default ``user_data_dir`` behaviour to use a *non*-roaming + profile dir (``CSIDL_LOCAL_APPDATA`` instead of ``CSIDL_APPDATA``). Why? Because + a large roaming profile can cause login speed issues. The "only syncs on + logout" behaviour can cause surprises in appdata info. + + +appdirs 1.0.1 (never released) +------------------------------ + +Started this changelog 27 July 2010. Before that this module originated in the +`Komodo `_ product as ``applib.py`` and then +as `applib/location.py +`_ (used by +`PyPM `_ in `ActivePython +`_). This is basically a fork of +applib.py 1.0.1 and applib/location.py 1.0.1. + + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/RECORD new file mode 100644 index 00000000..56589537 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/RECORD @@ -0,0 +1,8 @@ +__pycache__/appdirs.cpython-38.pyc,, +appdirs-1.4.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +appdirs-1.4.4.dist-info/LICENSE.txt,sha256=Nt200KdFqTqyAyA9cZCBSxuJcn0lTK_0jHp6-71HAAs,1097 +appdirs-1.4.4.dist-info/METADATA,sha256=k5TVfXMNKGHTfp2wm6EJKTuGwGNuoQR5TqQgH8iwG8M,8981 +appdirs-1.4.4.dist-info/RECORD,, +appdirs-1.4.4.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +appdirs-1.4.4.dist-info/top_level.txt,sha256=nKncE8CUqZERJ6VuQWL4_bkunSPDNfn7KZqb4Tr5YEM,8 +appdirs.py,sha256=g99s2sXhnvTEm79oj4bWI0Toapc-_SmKKNXvOXHkVic,24720 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/top_level.txt new file mode 100644 index 00000000..d64bc321 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs-1.4.4.dist-info/top_level.txt @@ -0,0 +1 @@ +appdirs diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs.py new file mode 100644 index 00000000..ae67001a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/appdirs.py @@ -0,0 +1,608 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2005-2010 ActiveState Software Inc. +# Copyright (c) 2013 Eddy Petrișor + +"""Utilities for determining application-specific dirs. + +See for details and usage. +""" +# Dev Notes: +# - MSDN on where to store app data files: +# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120 +# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html +# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + +__version_info__ = (1, 4, 3) +__version__ = '.'.join(map(str, __version_info__)) + + +import sys +import os + +PY3 = sys.version_info[0] == 3 + +if PY3: + unicode = str + +if sys.platform.startswith('java'): + import platform + os_name = platform.java_ver()[3][0] + if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc. + system = 'win32' + elif os_name.startswith('Mac'): # "Mac OS X", etc. + system = 'darwin' + else: # "Linux", "SunOS", "FreeBSD", etc. + # Setting this to "linux2" is not ideal, but only Windows or Mac + # are actually checked for and the rest of the module expects + # *sys.platform* style strings. + system = 'linux2' +else: + system = sys.platform + + + +def user_data_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user data directories are: + Mac OS X: ~/Library/Application Support/ + Unix: ~/.local/share/ # or in $XDG_DATA_HOME, if defined + Win XP (not roaming): C:\Documents and Settings\\Application Data\\ + Win XP (roaming): C:\Documents and Settings\\Local Settings\Application Data\\ + Win 7 (not roaming): C:\Users\\AppData\Local\\ + Win 7 (roaming): C:\Users\\AppData\Roaming\\ + + For Unix, we follow the XDG spec and support $XDG_DATA_HOME. + That means, by default "~/.local/share/". + """ + if system == "win32": + if appauthor is None: + appauthor = appname + const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA" + path = os.path.normpath(_get_win_folder(const)) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('~/Library/Application Support/') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_data_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of data dirs should be + returned. By default, the first item from XDG_DATA_DIRS is + returned, or '/usr/local/share/', + if XDG_DATA_DIRS is not set + + Typical site data directories are: + Mac OS X: /Library/Application Support/ + Unix: /usr/local/share/ or /usr/share/ + Win XP: C:\Documents and Settings\All Users\Application Data\\ + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + Win 7: C:\ProgramData\\ # Hidden, but writeable on Win 7. + + For Unix, this is using the $XDG_DATA_DIRS[0] default. + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + elif system == 'darwin': + path = os.path.expanduser('/Library/Application Support') + if appname: + path = os.path.join(path, appname) + else: + # XDG default for $XDG_DATA_DIRS + # only first, if multipath is False + path = os.getenv('XDG_DATA_DIRS', + os.pathsep.join(['/usr/local/share', '/usr/share'])) + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + if appname and version: + path = os.path.join(path, version) + return path + + +def user_config_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific config dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user config directories are: + Mac OS X: same as user_data_dir + Unix: ~/.config/ # or in $XDG_CONFIG_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME. + That means, by default "~/.config/". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def site_config_dir(appname=None, appauthor=None, version=None, multipath=False): + r"""Return full path to the user-shared data dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "multipath" is an optional parameter only applicable to *nix + which indicates that the entire list of config dirs should be + returned. By default, the first item from XDG_CONFIG_DIRS is + returned, or '/etc/xdg/', if XDG_CONFIG_DIRS is not set + + Typical site config directories are: + Mac OS X: same as site_data_dir + Unix: /etc/xdg/ or $XDG_CONFIG_DIRS[i]/ for each value in + $XDG_CONFIG_DIRS + Win *: same as site_data_dir + Vista: (Fail! "C:\ProgramData" is a hidden *system* directory on Vista.) + + For Unix, this is using the $XDG_CONFIG_DIRS[0] default, if multipath=False + + WARNING: Do not use this on Windows. See the Vista-Fail note above for why. + """ + if system in ["win32", "darwin"]: + path = site_data_dir(appname, appauthor) + if appname and version: + path = os.path.join(path, version) + else: + # XDG default for $XDG_CONFIG_DIRS + # only first, if multipath is False + path = os.getenv('XDG_CONFIG_DIRS', '/etc/xdg') + pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)] + if appname: + if version: + appname = os.path.join(appname, version) + pathlist = [os.sep.join([x, appname]) for x in pathlist] + + if multipath: + path = os.pathsep.join(pathlist) + else: + path = pathlist[0] + return path + + +def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific cache dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Cache" to the base app data dir for Windows. See + discussion below. + + Typical user cache directories are: + Mac OS X: ~/Library/Caches/ + Unix: ~/.cache/ (XDG default) + Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Cache + Vista: C:\Users\\AppData\Local\\\Cache + + On Windows the only suggestion in the MSDN docs is that local settings go in + the `CSIDL_LOCAL_APPDATA` directory. This is identical to the non-roaming + app data dir (the default returned by `user_data_dir` above). Apps typically + put cache data somewhere *under* the given dir here. Some examples: + ...\Mozilla\Firefox\Profiles\\Cache + ...\Acme\SuperApp\Cache\1.0 + OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value. + This can be disabled with the `opinion=False` option. + """ + if system == "win32": + if appauthor is None: + appauthor = appname + path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA")) + if appname: + if appauthor is not False: + path = os.path.join(path, appauthor, appname) + else: + path = os.path.join(path, appname) + if opinion: + path = os.path.join(path, "Cache") + elif system == 'darwin': + path = os.path.expanduser('~/Library/Caches') + if appname: + path = os.path.join(path, appname) + else: + path = os.getenv('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_state_dir(appname=None, appauthor=None, version=None, roaming=False): + r"""Return full path to the user-specific state dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "roaming" (boolean, default False) can be set True to use the Windows + roaming appdata directory. That means that for users on a Windows + network setup for roaming profiles, this user data will be + sync'd on login. See + + for a discussion of issues. + + Typical user state directories are: + Mac OS X: same as user_data_dir + Unix: ~/.local/state/ # or in $XDG_STATE_HOME, if defined + Win *: same as user_data_dir + + For Unix, we follow this Debian proposal + to extend the XDG spec and support $XDG_STATE_HOME. + + That means, by default "~/.local/state/". + """ + if system in ["win32", "darwin"]: + path = user_data_dir(appname, appauthor, None, roaming) + else: + path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state")) + if appname: + path = os.path.join(path, appname) + if appname and version: + path = os.path.join(path, version) + return path + + +def user_log_dir(appname=None, appauthor=None, version=None, opinion=True): + r"""Return full path to the user-specific log dir for this application. + + "appname" is the name of application. + If None, just the system directory is returned. + "appauthor" (only used on Windows) is the name of the + appauthor or distributing body for this application. Typically + it is the owning company name. This falls back to appname. You may + pass False to disable it. + "version" is an optional version path element to append to the + path. You might want to use this if you want multiple versions + of your app to be able to run independently. If used, this + would typically be ".". + Only applied when appname is present. + "opinion" (boolean) can be False to disable the appending of + "Logs" to the base app data dir for Windows, and "log" to the + base cache dir for Unix. See discussion below. + + Typical user log directories are: + Mac OS X: ~/Library/Logs/ + Unix: ~/.cache//log # or under $XDG_CACHE_HOME if defined + Win XP: C:\Documents and Settings\\Local Settings\Application Data\\\Logs + Vista: C:\Users\\AppData\Local\\\Logs + + On Windows the only suggestion in the MSDN docs is that local settings + go in the `CSIDL_LOCAL_APPDATA` directory. (Note: I'm interested in + examples of what some windows apps use for a logs dir.) + + OPINION: This function appends "Logs" to the `CSIDL_LOCAL_APPDATA` + value for Windows and appends "log" to the user cache dir for Unix. + This can be disabled with the `opinion=False` option. + """ + if system == "darwin": + path = os.path.join( + os.path.expanduser('~/Library/Logs'), + appname) + elif system == "win32": + path = user_data_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "Logs") + else: + path = user_cache_dir(appname, appauthor, version) + version = False + if opinion: + path = os.path.join(path, "log") + if appname and version: + path = os.path.join(path, version) + return path + + +class AppDirs(object): + """Convenience wrapper for getting application dirs.""" + def __init__(self, appname=None, appauthor=None, version=None, + roaming=False, multipath=False): + self.appname = appname + self.appauthor = appauthor + self.version = version + self.roaming = roaming + self.multipath = multipath + + @property + def user_data_dir(self): + return user_data_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_data_dir(self): + return site_data_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_config_dir(self): + return user_config_dir(self.appname, self.appauthor, + version=self.version, roaming=self.roaming) + + @property + def site_config_dir(self): + return site_config_dir(self.appname, self.appauthor, + version=self.version, multipath=self.multipath) + + @property + def user_cache_dir(self): + return user_cache_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_state_dir(self): + return user_state_dir(self.appname, self.appauthor, + version=self.version) + + @property + def user_log_dir(self): + return user_log_dir(self.appname, self.appauthor, + version=self.version) + + +#---- internal support stuff + +def _get_win_folder_from_registry(csidl_name): + """This is a fallback technique at best. I'm not sure if using the + registry for this guarantees us the correct answer for all CSIDL_* + names. + """ + if PY3: + import winreg as _winreg + else: + import _winreg + + shell_folder_name = { + "CSIDL_APPDATA": "AppData", + "CSIDL_COMMON_APPDATA": "Common AppData", + "CSIDL_LOCAL_APPDATA": "Local AppData", + }[csidl_name] + + key = _winreg.OpenKey( + _winreg.HKEY_CURRENT_USER, + r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" + ) + dir, type = _winreg.QueryValueEx(key, shell_folder_name) + return dir + + +def _get_win_folder_with_pywin32(csidl_name): + from win32com.shell import shellcon, shell + dir = shell.SHGetFolderPath(0, getattr(shellcon, csidl_name), 0, 0) + # Try to make this a unicode path because SHGetFolderPath does + # not return unicode strings when there is unicode data in the + # path. + try: + dir = unicode(dir) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + try: + import win32api + dir = win32api.GetShortPathName(dir) + except ImportError: + pass + except UnicodeError: + pass + return dir + + +def _get_win_folder_with_ctypes(csidl_name): + import ctypes + + csidl_const = { + "CSIDL_APPDATA": 26, + "CSIDL_COMMON_APPDATA": 35, + "CSIDL_LOCAL_APPDATA": 28, + }[csidl_name] + + buf = ctypes.create_unicode_buffer(1024) + ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in buf: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf2 = ctypes.create_unicode_buffer(1024) + if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): + buf = buf2 + + return buf.value + +def _get_win_folder_with_jna(csidl_name): + import array + from com.sun import jna + from com.sun.jna.platform import win32 + + buf_size = win32.WinDef.MAX_PATH * 2 + buf = array.zeros('c', buf_size) + shell = win32.Shell32.INSTANCE + shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf) + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + # Downgrade to short path name if have highbit chars. See + # . + has_high_char = False + for c in dir: + if ord(c) > 255: + has_high_char = True + break + if has_high_char: + buf = array.zeros('c', buf_size) + kernel = win32.Kernel32.INSTANCE + if kernel.GetShortPathName(dir, buf, buf_size): + dir = jna.Native.toString(buf.tostring()).rstrip("\0") + + return dir + +if system == "win32": + try: + import win32com.shell + _get_win_folder = _get_win_folder_with_pywin32 + except ImportError: + try: + from ctypes import windll + _get_win_folder = _get_win_folder_with_ctypes + except ImportError: + try: + import com.sun.jna + _get_win_folder = _get_win_folder_with_jna + except ImportError: + _get_win_folder = _get_win_folder_from_registry + + +#---- self test code + +if __name__ == "__main__": + appname = "MyApp" + appauthor = "MyCompany" + + props = ("user_data_dir", + "user_config_dir", + "user_cache_dir", + "user_state_dir", + "user_log_dir", + "site_data_dir", + "site_config_dir") + + print("-- app dirs %s --" % __version__) + + print("-- app dirs (with optional 'version')") + dirs = AppDirs(appname, appauthor, version="1.0") + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'version')") + dirs = AppDirs(appname, appauthor) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (without optional 'appauthor')") + dirs = AppDirs(appname) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) + + print("\n-- app dirs (with disabled 'appauthor')") + dirs = AppDirs(appname, appauthor=False) + for prop in props: + print("%s: %s" % (prop, getattr(dirs, prop))) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.py new file mode 100644 index 00000000..bf329cad --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.py @@ -0,0 +1,76 @@ +from __future__ import absolute_import, division, print_function + +import sys + +from functools import partial + +from . import converters, exceptions, filters, setters, validators +from ._config import get_run_validators, set_run_validators +from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types +from ._make import ( + NOTHING, + Attribute, + Factory, + attrib, + attrs, + fields, + fields_dict, + make_class, + validate, +) +from ._version_info import VersionInfo + + +__version__ = "20.3.0" +__version_info__ = VersionInfo._from_version_string(__version__) + +__title__ = "attrs" +__description__ = "Classes Without Boilerplate" +__url__ = "https://www.attrs.org/" +__uri__ = __url__ +__doc__ = __description__ + " <" + __uri__ + ">" + +__author__ = "Hynek Schlawack" +__email__ = "hs@ox.cx" + +__license__ = "MIT" +__copyright__ = "Copyright (c) 2015 Hynek Schlawack" + + +s = attributes = attrs +ib = attr = attrib +dataclass = partial(attrs, auto_attribs=True) # happy Easter ;) + +__all__ = [ + "Attribute", + "Factory", + "NOTHING", + "asdict", + "assoc", + "astuple", + "attr", + "attrib", + "attributes", + "attrs", + "converters", + "evolve", + "exceptions", + "fields", + "fields_dict", + "filters", + "get_run_validators", + "has", + "ib", + "make_class", + "resolve_types", + "s", + "set_run_validators", + "setters", + "validate", + "validators", +] + +if sys.version_info[:2] >= (3, 6): + from ._next_gen import define, field, frozen, mutable + + __all__.extend((define, field, frozen, mutable)) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.pyi new file mode 100644 index 00000000..442d6e77 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/__init__.pyi @@ -0,0 +1,433 @@ +from typing import ( + Any, + Callable, + Dict, + Generic, + List, + Optional, + Sequence, + Mapping, + Tuple, + Type, + TypeVar, + Union, + overload, +) + +# `import X as X` is required to make these public +from . import exceptions as exceptions +from . import filters as filters +from . import converters as converters +from . import setters as setters +from . import validators as validators + +from ._version_info import VersionInfo + +__version__: str +__version_info__: VersionInfo +__title__: str +__description__: str +__url__: str +__uri__: str +__author__: str +__email__: str +__license__: str +__copyright__: str + +_T = TypeVar("_T") +_C = TypeVar("_C", bound=type) + +_ValidatorType = Callable[[Any, Attribute[_T], _T], Any] +_ConverterType = Callable[[Any], Any] +_FilterType = Callable[[Attribute[_T], _T], bool] +_ReprType = Callable[[Any], str] +_ReprArgType = Union[bool, _ReprType] +_OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any] +_OnSetAttrArgType = Union[ + _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType +] +_FieldTransformer = Callable[[type, List[Attribute]], List[Attribute]] +# FIXME: in reality, if multiple validators are passed they must be in a list +# or tuple, but those are invariant and so would prevent subtypes of +# _ValidatorType from working when passed in a list or tuple. +_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] + +# _make -- + +NOTHING: object + +# NOTE: Factory lies about its return type to make this possible: +# `x: List[int] # = Factory(list)` +# Work around mypy issue #4554 in the common case by using an overload. +@overload +def Factory(factory: Callable[[], _T]) -> _T: ... +@overload +def Factory( + factory: Union[Callable[[Any], _T], Callable[[], _T]], + takes_self: bool = ..., +) -> _T: ... + +class Attribute(Generic[_T]): + name: str + default: Optional[_T] + validator: Optional[_ValidatorType[_T]] + repr: _ReprArgType + cmp: bool + eq: bool + order: bool + hash: Optional[bool] + init: bool + converter: Optional[_ConverterType] + metadata: Dict[Any, Any] + type: Optional[Type[_T]] + kw_only: bool + on_setattr: _OnSetAttrType + +# NOTE: We had several choices for the annotation to use for type arg: +# 1) Type[_T] +# - Pros: Handles simple cases correctly +# - Cons: Might produce less informative errors in the case of conflicting +# TypeVars e.g. `attr.ib(default='bad', type=int)` +# 2) Callable[..., _T] +# - Pros: Better error messages than #1 for conflicting TypeVars +# - Cons: Terrible error messages for validator checks. +# e.g. attr.ib(type=int, validator=validate_str) +# -> error: Cannot infer function type argument +# 3) type (and do all of the work in the mypy plugin) +# - Pros: Simple here, and we could customize the plugin with our own errors. +# - Cons: Would need to write mypy plugin code to handle all the cases. +# We chose option #1. + +# `attr` lies about its return type to make the following possible: +# attr() -> Any +# attr(8) -> int +# attr(validator=) -> Whatever the callable expects. +# This makes this type of assignments possible: +# x: int = attr(8) +# +# This form catches explicit None or no default but with no other arguments +# returns Any. +@overload +def attrib( + default: None = ..., + validator: None = ..., + repr: _ReprArgType = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: None = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def attrib( + default: None = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def attrib( + default: _T, + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def attrib( + default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: object = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... +@overload +def field( + *, + default: None = ..., + validator: None = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def field( + *, + default: None = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def field( + *, + default: _T, + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def field( + *, + default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: _ReprArgType = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + converter: Optional[_ConverterType] = ..., + factory: Optional[Callable[[], _T]] = ..., + kw_only: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., +) -> Any: ... +@overload +def attrs( + maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + collect_by_mro: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> _C: ... +@overload +def attrs( + maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + collect_by_mro: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> Callable[[_C], _C]: ... +@overload +def define( + maybe_cls: _C, + *, + these: Optional[Dict[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> _C: ... +@overload +def define( + maybe_cls: None = ..., + *, + these: Optional[Dict[str, Any]] = ..., + repr: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + auto_detect: bool = ..., + getstate_setstate: Optional[bool] = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> Callable[[_C], _C]: ... + +mutable = define +frozen = define # they differ only in their defaults + +# TODO: add support for returning NamedTuple from the mypy plugin +class _Fields(Tuple[Attribute[Any], ...]): + def __getattr__(self, name: str) -> Attribute[Any]: ... + +def fields(cls: type) -> _Fields: ... +def fields_dict(cls: type) -> Dict[str, Attribute[Any]]: ... +def validate(inst: Any) -> None: ... +def resolve_types( + cls: _C, + globalns: Optional[Dict[str, Any]] = ..., + localns: Optional[Dict[str, Any]] = ..., +) -> _C: ... + +# TODO: add support for returning a proper attrs class from the mypy plugin +# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', +# [attr.ib()])` is valid +def make_class( + name: str, + attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], + bases: Tuple[type, ...] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: Optional[bool] = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: Optional[bool] = ..., + order: Optional[bool] = ..., + collect_by_mro: bool = ..., + on_setattr: Optional[_OnSetAttrArgType] = ..., + field_transformer: Optional[_FieldTransformer] = ..., +) -> type: ... + +# _funcs -- + +# TODO: add support for returning TypedDict from the mypy plugin +# FIXME: asdict/astuple do not honor their factory args. Waiting on one of +# these: +# https://github.com/python/mypy/issues/4236 +# https://github.com/python/typing/issues/253 +def asdict( + inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + dict_factory: Type[Mapping[Any, Any]] = ..., + retain_collection_types: bool = ..., + value_serializer: Optional[Callable[[type, Attribute, Any], Any]] = ..., +) -> Dict[str, Any]: ... + +# TODO: add support for returning NamedTuple from the mypy plugin +def astuple( + inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType[Any]] = ..., + tuple_factory: Type[Sequence[Any]] = ..., + retain_collection_types: bool = ..., +) -> Tuple[Any, ...]: ... +def has(cls: type) -> bool: ... +def assoc(inst: _T, **changes: Any) -> _T: ... +def evolve(inst: _T, **changes: Any) -> _T: ... + +# _config -- + +def set_run_validators(run: bool) -> None: ... +def get_run_validators() -> bool: ... + +# aliases -- + +s = attributes = attrs +ib = attr = attrib +dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_compat.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_compat.py new file mode 100644 index 00000000..b0ead6e1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_compat.py @@ -0,0 +1,231 @@ +from __future__ import absolute_import, division, print_function + +import platform +import sys +import types +import warnings + + +PY2 = sys.version_info[0] == 2 +PYPY = platform.python_implementation() == "PyPy" + + +if PYPY or sys.version_info[:2] >= (3, 6): + ordered_dict = dict +else: + from collections import OrderedDict + + ordered_dict = OrderedDict + + +if PY2: + from collections import Mapping, Sequence + + from UserDict import IterableUserDict + + # We 'bundle' isclass instead of using inspect as importing inspect is + # fairly expensive (order of 10-15 ms for a modern machine in 2016) + def isclass(klass): + return isinstance(klass, (type, types.ClassType)) + + # TYPE is used in exceptions, repr(int) is different on Python 2 and 3. + TYPE = "type" + + def iteritems(d): + return d.iteritems() + + # Python 2 is bereft of a read-only dict proxy, so we make one! + class ReadOnlyDict(IterableUserDict): + """ + Best-effort read-only dict wrapper. + """ + + def __setitem__(self, key, val): + # We gently pretend we're a Python 3 mappingproxy. + raise TypeError( + "'mappingproxy' object does not support item assignment" + ) + + def update(self, _): + # We gently pretend we're a Python 3 mappingproxy. + raise AttributeError( + "'mappingproxy' object has no attribute 'update'" + ) + + def __delitem__(self, _): + # We gently pretend we're a Python 3 mappingproxy. + raise TypeError( + "'mappingproxy' object does not support item deletion" + ) + + def clear(self): + # We gently pretend we're a Python 3 mappingproxy. + raise AttributeError( + "'mappingproxy' object has no attribute 'clear'" + ) + + def pop(self, key, default=None): + # We gently pretend we're a Python 3 mappingproxy. + raise AttributeError( + "'mappingproxy' object has no attribute 'pop'" + ) + + def popitem(self): + # We gently pretend we're a Python 3 mappingproxy. + raise AttributeError( + "'mappingproxy' object has no attribute 'popitem'" + ) + + def setdefault(self, key, default=None): + # We gently pretend we're a Python 3 mappingproxy. + raise AttributeError( + "'mappingproxy' object has no attribute 'setdefault'" + ) + + def __repr__(self): + # Override to be identical to the Python 3 version. + return "mappingproxy(" + repr(self.data) + ")" + + def metadata_proxy(d): + res = ReadOnlyDict() + res.data.update(d) # We blocked update, so we have to do it like this. + return res + + def just_warn(*args, **kw): # pragma: no cover + """ + We only warn on Python 3 because we are not aware of any concrete + consequences of not setting the cell on Python 2. + """ + + +else: # Python 3 and later. + from collections.abc import Mapping, Sequence # noqa + + def just_warn(*args, **kw): + """ + We only warn on Python 3 because we are not aware of any concrete + consequences of not setting the cell on Python 2. + """ + warnings.warn( + "Running interpreter doesn't sufficiently support code object " + "introspection. Some features like bare super() or accessing " + "__class__ will not work with slotted classes.", + RuntimeWarning, + stacklevel=2, + ) + + def isclass(klass): + return isinstance(klass, type) + + TYPE = "class" + + def iteritems(d): + return d.items() + + def metadata_proxy(d): + return types.MappingProxyType(dict(d)) + + +def make_set_closure_cell(): + """Return a function of two arguments (cell, value) which sets + the value stored in the closure cell `cell` to `value`. + """ + # pypy makes this easy. (It also supports the logic below, but + # why not do the easy/fast thing?) + if PYPY: + + def set_closure_cell(cell, value): + cell.__setstate__((value,)) + + return set_closure_cell + + # Otherwise gotta do it the hard way. + + # Create a function that will set its first cellvar to `value`. + def set_first_cellvar_to(value): + x = value + return + + # This function will be eliminated as dead code, but + # not before its reference to `x` forces `x` to be + # represented as a closure cell rather than a local. + def force_x_to_be_a_cell(): # pragma: no cover + return x + + try: + # Extract the code object and make sure our assumptions about + # the closure behavior are correct. + if PY2: + co = set_first_cellvar_to.func_code + else: + co = set_first_cellvar_to.__code__ + if co.co_cellvars != ("x",) or co.co_freevars != (): + raise AssertionError # pragma: no cover + + # Convert this code object to a code object that sets the + # function's first _freevar_ (not cellvar) to the argument. + if sys.version_info >= (3, 8): + # CPython 3.8+ has an incompatible CodeType signature + # (added a posonlyargcount argument) but also added + # CodeType.replace() to do this without counting parameters. + set_first_freevar_code = co.replace( + co_cellvars=co.co_freevars, co_freevars=co.co_cellvars + ) + else: + args = [co.co_argcount] + if not PY2: + args.append(co.co_kwonlyargcount) + args.extend( + [ + co.co_nlocals, + co.co_stacksize, + co.co_flags, + co.co_code, + co.co_consts, + co.co_names, + co.co_varnames, + co.co_filename, + co.co_name, + co.co_firstlineno, + co.co_lnotab, + # These two arguments are reversed: + co.co_cellvars, + co.co_freevars, + ] + ) + set_first_freevar_code = types.CodeType(*args) + + def set_closure_cell(cell, value): + # Create a function using the set_first_freevar_code, + # whose first closure cell is `cell`. Calling it will + # change the value of that cell. + setter = types.FunctionType( + set_first_freevar_code, {}, "setter", (), (cell,) + ) + # And call it to set the cell. + setter(value) + + # Make sure it works on this interpreter: + def make_func_with_cell(): + x = None + + def func(): + return x # pragma: no cover + + return func + + if PY2: + cell = make_func_with_cell().func_closure[0] + else: + cell = make_func_with_cell().__closure__[0] + set_closure_cell(cell, 100) + if cell.cell_contents != 100: + raise AssertionError # pragma: no cover + + except Exception: + return just_warn + else: + return set_closure_cell + + +set_closure_cell = make_set_closure_cell() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_config.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_config.py new file mode 100644 index 00000000..8ec92096 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_config.py @@ -0,0 +1,23 @@ +from __future__ import absolute_import, division, print_function + + +__all__ = ["set_run_validators", "get_run_validators"] + +_run_validators = True + + +def set_run_validators(run): + """ + Set whether or not validators are run. By default, they are run. + """ + if not isinstance(run, bool): + raise TypeError("'run' must be bool.") + global _run_validators + _run_validators = run + + +def get_run_validators(): + """ + Return whether or not validators are run. + """ + return _run_validators diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_funcs.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_funcs.py new file mode 100644 index 00000000..e6c930cb --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_funcs.py @@ -0,0 +1,390 @@ +from __future__ import absolute_import, division, print_function + +import copy + +from ._compat import iteritems +from ._make import NOTHING, _obj_setattr, fields +from .exceptions import AttrsAttributeNotFoundError + + +def asdict( + inst, + recurse=True, + filter=None, + dict_factory=dict, + retain_collection_types=False, + value_serializer=None, +): + """ + Return the ``attrs`` attribute values of *inst* as a dict. + + Optionally recurse into other ``attrs``-decorated classes. + + :param inst: Instance of an ``attrs``-decorated class. + :param bool recurse: Recurse into classes that are also + ``attrs``-decorated. + :param callable filter: A callable whose return code determines whether an + attribute or element is included (``True``) or dropped (``False``). Is + called with the `attr.Attribute` as the first argument and the + value as the second argument. + :param callable dict_factory: A callable to produce dictionaries from. For + example, to produce ordered dictionaries instead of normal Python + dictionaries, pass in ``collections.OrderedDict``. + :param bool retain_collection_types: Do not convert to ``list`` when + encountering an attribute whose type is ``tuple`` or ``set``. Only + meaningful if ``recurse`` is ``True``. + :param Optional[callable] value_serializer: A hook that is called for every + attribute or dict key/value. It receives the current instance, field + and value and must return the (updated) value. The hook is run *after* + the optional *filter* has been applied. + + :rtype: return type of *dict_factory* + + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 16.0.0 *dict_factory* + .. versionadded:: 16.1.0 *retain_collection_types* + .. versionadded:: 20.3.0 *value_serializer* + """ + attrs = fields(inst.__class__) + rv = dict_factory() + for a in attrs: + v = getattr(inst, a.name) + if filter is not None and not filter(a, v): + continue + + if value_serializer is not None: + v = value_serializer(inst, a, v) + + if recurse is True: + if has(v.__class__): + rv[a.name] = asdict( + v, + True, + filter, + dict_factory, + retain_collection_types, + value_serializer, + ) + elif isinstance(v, (tuple, list, set, frozenset)): + cf = v.__class__ if retain_collection_types is True else list + rv[a.name] = cf( + [ + _asdict_anything( + i, + filter, + dict_factory, + retain_collection_types, + value_serializer, + ) + for i in v + ] + ) + elif isinstance(v, dict): + df = dict_factory + rv[a.name] = df( + ( + _asdict_anything( + kk, + filter, + df, + retain_collection_types, + value_serializer, + ), + _asdict_anything( + vv, + filter, + df, + retain_collection_types, + value_serializer, + ), + ) + for kk, vv in iteritems(v) + ) + else: + rv[a.name] = v + else: + rv[a.name] = v + return rv + + +def _asdict_anything( + val, + filter, + dict_factory, + retain_collection_types, + value_serializer, +): + """ + ``asdict`` only works on attrs instances, this works on anything. + """ + if getattr(val.__class__, "__attrs_attrs__", None) is not None: + # Attrs class. + rv = asdict( + val, + True, + filter, + dict_factory, + retain_collection_types, + value_serializer, + ) + elif isinstance(val, (tuple, list, set, frozenset)): + cf = val.__class__ if retain_collection_types is True else list + rv = cf( + [ + _asdict_anything( + i, + filter, + dict_factory, + retain_collection_types, + value_serializer, + ) + for i in val + ] + ) + elif isinstance(val, dict): + df = dict_factory + rv = df( + ( + _asdict_anything( + kk, filter, df, retain_collection_types, value_serializer + ), + _asdict_anything( + vv, filter, df, retain_collection_types, value_serializer + ), + ) + for kk, vv in iteritems(val) + ) + else: + rv = val + if value_serializer is not None: + rv = value_serializer(None, None, rv) + + return rv + + +def astuple( + inst, + recurse=True, + filter=None, + tuple_factory=tuple, + retain_collection_types=False, +): + """ + Return the ``attrs`` attribute values of *inst* as a tuple. + + Optionally recurse into other ``attrs``-decorated classes. + + :param inst: Instance of an ``attrs``-decorated class. + :param bool recurse: Recurse into classes that are also + ``attrs``-decorated. + :param callable filter: A callable whose return code determines whether an + attribute or element is included (``True``) or dropped (``False``). Is + called with the `attr.Attribute` as the first argument and the + value as the second argument. + :param callable tuple_factory: A callable to produce tuples from. For + example, to produce lists instead of tuples. + :param bool retain_collection_types: Do not convert to ``list`` + or ``dict`` when encountering an attribute which type is + ``tuple``, ``dict`` or ``set``. Only meaningful if ``recurse`` is + ``True``. + + :rtype: return type of *tuple_factory* + + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 16.2.0 + """ + attrs = fields(inst.__class__) + rv = [] + retain = retain_collection_types # Very long. :/ + for a in attrs: + v = getattr(inst, a.name) + if filter is not None and not filter(a, v): + continue + if recurse is True: + if has(v.__class__): + rv.append( + astuple( + v, + recurse=True, + filter=filter, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + ) + elif isinstance(v, (tuple, list, set, frozenset)): + cf = v.__class__ if retain is True else list + rv.append( + cf( + [ + astuple( + j, + recurse=True, + filter=filter, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(j.__class__) + else j + for j in v + ] + ) + ) + elif isinstance(v, dict): + df = v.__class__ if retain is True else dict + rv.append( + df( + ( + astuple( + kk, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(kk.__class__) + else kk, + astuple( + vv, + tuple_factory=tuple_factory, + retain_collection_types=retain, + ) + if has(vv.__class__) + else vv, + ) + for kk, vv in iteritems(v) + ) + ) + else: + rv.append(v) + else: + rv.append(v) + + return rv if tuple_factory is list else tuple_factory(rv) + + +def has(cls): + """ + Check whether *cls* is a class with ``attrs`` attributes. + + :param type cls: Class to introspect. + :raise TypeError: If *cls* is not a class. + + :rtype: bool + """ + return getattr(cls, "__attrs_attrs__", None) is not None + + +def assoc(inst, **changes): + """ + Copy *inst* and apply *changes*. + + :param inst: Instance of a class with ``attrs`` attributes. + :param changes: Keyword changes in the new copy. + + :return: A copy of inst with *changes* incorporated. + + :raise attr.exceptions.AttrsAttributeNotFoundError: If *attr_name* couldn't + be found on *cls*. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. deprecated:: 17.1.0 + Use `evolve` instead. + """ + import warnings + + warnings.warn( + "assoc is deprecated and will be removed after 2018/01.", + DeprecationWarning, + stacklevel=2, + ) + new = copy.copy(inst) + attrs = fields(inst.__class__) + for k, v in iteritems(changes): + a = getattr(attrs, k, NOTHING) + if a is NOTHING: + raise AttrsAttributeNotFoundError( + "{k} is not an attrs attribute on {cl}.".format( + k=k, cl=new.__class__ + ) + ) + _obj_setattr(new, k, v) + return new + + +def evolve(inst, **changes): + """ + Create a new instance, based on *inst* with *changes* applied. + + :param inst: Instance of a class with ``attrs`` attributes. + :param changes: Keyword changes in the new copy. + + :return: A copy of inst with *changes* incorporated. + + :raise TypeError: If *attr_name* couldn't be found in the class + ``__init__``. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + .. versionadded:: 17.1.0 + """ + cls = inst.__class__ + attrs = fields(cls) + for a in attrs: + if not a.init: + continue + attr_name = a.name # To deal with private attributes. + init_name = attr_name if attr_name[0] != "_" else attr_name[1:] + if init_name not in changes: + changes[init_name] = getattr(inst, attr_name) + + return cls(**changes) + + +def resolve_types(cls, globalns=None, localns=None): + """ + Resolve any strings and forward annotations in type annotations. + + This is only required if you need concrete types in `Attribute`'s *type* + field. In other words, you don't need to resolve your types if you only + use them for static type checking. + + With no arguments, names will be looked up in the module in which the class + was created. If this is not what you want, e.g. if the name only exists + inside a method, you may pass *globalns* or *localns* to specify other + dictionaries in which to look up these names. See the docs of + `typing.get_type_hints` for more details. + + :param type cls: Class to resolve. + :param Optional[dict] globalns: Dictionary containing global variables. + :param Optional[dict] localns: Dictionary containing local variables. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + :raise NameError: If types cannot be resolved because of missing variables. + + :returns: *cls* so you can use this function also as a class decorator. + Please note that you have to apply it **after** `attr.s`. That means + the decorator has to come in the line **before** `attr.s`. + + .. versionadded:: 20.1.0 + """ + try: + # Since calling get_type_hints is expensive we cache whether we've + # done it already. + cls.__attrs_types_resolved__ + except AttributeError: + import typing + + hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) + for field in fields(cls): + if field.name in hints: + # Since fields have been frozen we must work around it. + _obj_setattr(field, "type", hints[field.name]) + cls.__attrs_types_resolved__ = True + + # Return the class so you can use it as a decorator too. + return cls diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_make.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_make.py new file mode 100644 index 00000000..49484f93 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_make.py @@ -0,0 +1,2765 @@ +from __future__ import absolute_import, division, print_function + +import copy +import linecache +import sys +import threading +import uuid +import warnings + +from operator import itemgetter + +from . import _config, setters +from ._compat import ( + PY2, + PYPY, + isclass, + iteritems, + metadata_proxy, + ordered_dict, + set_closure_cell, +) +from .exceptions import ( + DefaultAlreadySetError, + FrozenInstanceError, + NotAnAttrsClassError, + PythonTooOldError, + UnannotatedAttributeError, +) + + +# This is used at least twice, so cache it here. +_obj_setattr = object.__setattr__ +_init_converter_pat = "__attr_converter_%s" +_init_factory_pat = "__attr_factory_{}" +_tuple_property_pat = ( + " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" +) +_classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar") +# we don't use a double-underscore prefix because that triggers +# name mangling when trying to create a slot for the field +# (when slots=True) +_hash_cache_field = "_attrs_cached_hash" + +_empty_metadata_singleton = metadata_proxy({}) + +# Unique object for unequivocal getattr() defaults. +_sentinel = object() + + +class _Nothing(object): + """ + Sentinel class to indicate the lack of a value when ``None`` is ambiguous. + + ``_Nothing`` is a singleton. There is only ever one of it. + """ + + _singleton = None + + def __new__(cls): + if _Nothing._singleton is None: + _Nothing._singleton = super(_Nothing, cls).__new__(cls) + return _Nothing._singleton + + def __repr__(self): + return "NOTHING" + + +NOTHING = _Nothing() +""" +Sentinel to indicate the lack of a value when ``None`` is ambiguous. +""" + + +class _CacheHashWrapper(int): + """ + An integer subclass that pickles / copies as None + + This is used for non-slots classes with ``cache_hash=True``, to avoid + serializing a potentially (even likely) invalid hash value. Since ``None`` + is the default value for uncalculated hashes, whenever this is copied, + the copy's value for the hash should automatically reset. + + See GH #613 for more details. + """ + + if PY2: + # For some reason `type(None)` isn't callable in Python 2, but we don't + # actually need a constructor for None objects, we just need any + # available function that returns None. + def __reduce__(self, _none_constructor=getattr, _args=(0, "", None)): + return _none_constructor, _args + + else: + + def __reduce__(self, _none_constructor=type(None), _args=()): + return _none_constructor, _args + + +def attrib( + default=NOTHING, + validator=None, + repr=True, + cmp=None, + hash=None, + init=True, + metadata=None, + type=None, + converter=None, + factory=None, + kw_only=False, + eq=None, + order=None, + on_setattr=None, +): + """ + Create a new attribute on a class. + + .. warning:: + + Does *not* do anything unless the class is also decorated with + `attr.s`! + + :param default: A value that is used if an ``attrs``-generated ``__init__`` + is used and no value is passed while instantiating or the attribute is + excluded using ``init=False``. + + If the value is an instance of `Factory`, its callable will be + used to construct a new value (useful for mutable data types like lists + or dicts). + + If a default is not set (or set manually to `attr.NOTHING`), a value + *must* be supplied when instantiating; otherwise a `TypeError` + will be raised. + + The default can also be set using decorator notation as shown below. + + :type default: Any value + + :param callable factory: Syntactic sugar for + ``default=attr.Factory(factory)``. + + :param validator: `callable` that is called by ``attrs``-generated + ``__init__`` methods after the instance has been initialized. They + receive the initialized instance, the `Attribute`, and the + passed value. + + The return value is *not* inspected so the validator has to throw an + exception itself. + + If a `list` is passed, its items are treated as validators and must + all pass. + + Validators can be globally disabled and re-enabled using + `get_run_validators`. + + The validator can also be set using decorator notation as shown below. + + :type validator: `callable` or a `list` of `callable`\\ s. + + :param repr: Include this attribute in the generated ``__repr__`` + method. If ``True``, include the attribute; if ``False``, omit it. By + default, the built-in ``repr()`` function is used. To override how the + attribute value is formatted, pass a ``callable`` that takes a single + value and returns a string. Note that the resulting string is used + as-is, i.e. it will be used directly *instead* of calling ``repr()`` + (the default). + :type repr: a `bool` or a `callable` to use a custom function. + :param bool eq: If ``True`` (default), include this attribute in the + generated ``__eq__`` and ``__ne__`` methods that check two instances + for equality. + :param bool order: If ``True`` (default), include this attributes in the + generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. + :param bool cmp: Setting to ``True`` is equivalent to setting ``eq=True, + order=True``. Deprecated in favor of *eq* and *order*. + :param Optional[bool] hash: Include this attribute in the generated + ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This + is the correct behavior according the Python spec. Setting this value + to anything else than ``None`` is *discouraged*. + :param bool init: Include this attribute in the generated ``__init__`` + method. It is possible to set this to ``False`` and set a default + value. In that case this attributed is unconditionally initialized + with the specified default value or factory. + :param callable converter: `callable` that is called by + ``attrs``-generated ``__init__`` methods to convert attribute's value + to the desired format. It is given the passed-in value, and the + returned value will be used as the new value of the attribute. The + value is converted before being passed to the validator, if any. + :param metadata: An arbitrary mapping, to be used by third-party + components. See `extending_metadata`. + :param type: The type of the attribute. In Python 3.6 or greater, the + preferred method to specify the type is using a variable annotation + (see `PEP 526 `_). + This argument is provided for backward compatibility. + Regardless of the approach used, the type will be stored on + ``Attribute.type``. + + Please note that ``attrs`` doesn't do anything with this metadata by + itself. You can use it as part of your own code or for + `static type checking `. + :param kw_only: Make this attribute keyword-only (Python 3+) + in the generated ``__init__`` (if ``init`` is ``False``, this + parameter is ignored). + :param on_setattr: Allows to overwrite the *on_setattr* setting from + `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used. + Set to `attr.setters.NO_OP` to run **no** `setattr` hooks for this + attribute -- regardless of the setting in `attr.s`. + :type on_setattr: `callable`, or a list of callables, or `None`, or + `attr.setters.NO_OP` + + .. versionadded:: 15.2.0 *convert* + .. versionadded:: 16.3.0 *metadata* + .. versionchanged:: 17.1.0 *validator* can be a ``list`` now. + .. versionchanged:: 17.1.0 + *hash* is ``None`` and therefore mirrors *eq* by default. + .. versionadded:: 17.3.0 *type* + .. deprecated:: 17.4.0 *convert* + .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated + *convert* to achieve consistency with other noun-based arguments. + .. versionadded:: 18.1.0 + ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. + .. versionadded:: 18.2.0 *kw_only* + .. versionchanged:: 19.2.0 *convert* keyword argument removed + .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. + .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. + .. versionadded:: 19.2.0 *eq* and *order* + .. versionadded:: 20.1.0 *on_setattr* + .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 + """ + eq, order = _determine_eq_order(cmp, eq, order, True) + + if hash is not None and hash is not True and hash is not False: + raise TypeError( + "Invalid value for hash. Must be True, False, or None." + ) + + if factory is not None: + if default is not NOTHING: + raise ValueError( + "The `default` and `factory` arguments are mutually " + "exclusive." + ) + if not callable(factory): + raise ValueError("The `factory` argument must be a callable.") + default = Factory(factory) + + if metadata is None: + metadata = {} + + # Apply syntactic sugar by auto-wrapping. + if isinstance(on_setattr, (list, tuple)): + on_setattr = setters.pipe(*on_setattr) + + if validator and isinstance(validator, (list, tuple)): + validator = and_(*validator) + + if converter and isinstance(converter, (list, tuple)): + converter = pipe(*converter) + + return _CountingAttr( + default=default, + validator=validator, + repr=repr, + cmp=None, + hash=hash, + init=init, + converter=converter, + metadata=metadata, + type=type, + kw_only=kw_only, + eq=eq, + order=order, + on_setattr=on_setattr, + ) + + +def _make_attr_tuple_class(cls_name, attr_names): + """ + Create a tuple subclass to hold `Attribute`s for an `attrs` class. + + The subclass is a bare tuple with properties for names. + + class MyClassAttributes(tuple): + __slots__ = () + x = property(itemgetter(0)) + """ + attr_class_name = "{}Attributes".format(cls_name) + attr_class_template = [ + "class {}(tuple):".format(attr_class_name), + " __slots__ = ()", + ] + if attr_names: + for i, attr_name in enumerate(attr_names): + attr_class_template.append( + _tuple_property_pat.format(index=i, attr_name=attr_name) + ) + else: + attr_class_template.append(" pass") + globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} + eval(compile("\n".join(attr_class_template), "", "exec"), globs) + + return globs[attr_class_name] + + +# Tuple class for extracted attributes from a class definition. +# `base_attrs` is a subset of `attrs`. +_Attributes = _make_attr_tuple_class( + "_Attributes", + [ + # all attributes to build dunder methods for + "attrs", + # attributes that have been inherited + "base_attrs", + # map inherited attributes to their originating classes + "base_attrs_map", + ], +) + + +def _is_class_var(annot): + """ + Check whether *annot* is a typing.ClassVar. + + The string comparison hack is used to avoid evaluating all string + annotations which would put attrs-based classes at a performance + disadvantage compared to plain old classes. + """ + return str(annot).startswith(_classvar_prefixes) + + +def _has_own_attribute(cls, attrib_name): + """ + Check whether *cls* defines *attrib_name* (and doesn't just inherit it). + + Requires Python 3. + """ + attr = getattr(cls, attrib_name, _sentinel) + if attr is _sentinel: + return False + + for base_cls in cls.__mro__[1:]: + a = getattr(base_cls, attrib_name, None) + if attr is a: + return False + + return True + + +def _get_annotations(cls): + """ + Get annotations for *cls*. + """ + if _has_own_attribute(cls, "__annotations__"): + return cls.__annotations__ + + return {} + + +def _counter_getter(e): + """ + Key function for sorting to avoid re-creating a lambda for every class. + """ + return e[1].counter + + +def _collect_base_attrs(cls, taken_attr_names): + """ + Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. + """ + base_attrs = [] + base_attr_map = {} # A dictionary of base attrs to their classes. + + # Traverse the MRO and collect attributes. + for base_cls in reversed(cls.__mro__[1:-1]): + for a in getattr(base_cls, "__attrs_attrs__", []): + if a.inherited or a.name in taken_attr_names: + continue + + a = a.evolve(inherited=True) + base_attrs.append(a) + base_attr_map[a.name] = base_cls + + # For each name, only keep the freshest definition i.e. the furthest at the + # back. base_attr_map is fine because it gets overwritten with every new + # instance. + filtered = [] + seen = set() + for a in reversed(base_attrs): + if a.name in seen: + continue + filtered.insert(0, a) + seen.add(a.name) + + return filtered, base_attr_map + + +def _collect_base_attrs_broken(cls, taken_attr_names): + """ + Collect attr.ibs from base classes of *cls*, except *taken_attr_names*. + + N.B. *taken_attr_names* will be mutated. + + Adhere to the old incorrect behavior. + + Notably it collects from the front and considers inherited attributes which + leads to the buggy behavior reported in #428. + """ + base_attrs = [] + base_attr_map = {} # A dictionary of base attrs to their classes. + + # Traverse the MRO and collect attributes. + for base_cls in cls.__mro__[1:-1]: + for a in getattr(base_cls, "__attrs_attrs__", []): + if a.name in taken_attr_names: + continue + + a = a.evolve(inherited=True) + taken_attr_names.add(a.name) + base_attrs.append(a) + base_attr_map[a.name] = base_cls + + return base_attrs, base_attr_map + + +def _transform_attrs( + cls, these, auto_attribs, kw_only, collect_by_mro, field_transformer +): + """ + Transform all `_CountingAttr`s on a class into `Attribute`s. + + If *these* is passed, use that and don't look for them on the class. + + *collect_by_mro* is True, collect them in the correct MRO order, otherwise + use the old -- incorrect -- order. See #428. + + Return an `_Attributes`. + """ + cd = cls.__dict__ + anns = _get_annotations(cls) + + if these is not None: + ca_list = [(name, ca) for name, ca in iteritems(these)] + + if not isinstance(these, ordered_dict): + ca_list.sort(key=_counter_getter) + elif auto_attribs is True: + ca_names = { + name + for name, attr in cd.items() + if isinstance(attr, _CountingAttr) + } + ca_list = [] + annot_names = set() + for attr_name, type in anns.items(): + if _is_class_var(type): + continue + annot_names.add(attr_name) + a = cd.get(attr_name, NOTHING) + + if not isinstance(a, _CountingAttr): + if a is NOTHING: + a = attrib() + else: + a = attrib(default=a) + ca_list.append((attr_name, a)) + + unannotated = ca_names - annot_names + if len(unannotated) > 0: + raise UnannotatedAttributeError( + "The following `attr.ib`s lack a type annotation: " + + ", ".join( + sorted(unannotated, key=lambda n: cd.get(n).counter) + ) + + "." + ) + else: + ca_list = sorted( + ( + (name, attr) + for name, attr in cd.items() + if isinstance(attr, _CountingAttr) + ), + key=lambda e: e[1].counter, + ) + + own_attrs = [ + Attribute.from_counting_attr( + name=attr_name, ca=ca, type=anns.get(attr_name) + ) + for attr_name, ca in ca_list + ] + + if collect_by_mro: + base_attrs, base_attr_map = _collect_base_attrs( + cls, {a.name for a in own_attrs} + ) + else: + base_attrs, base_attr_map = _collect_base_attrs_broken( + cls, {a.name for a in own_attrs} + ) + + attr_names = [a.name for a in base_attrs + own_attrs] + + AttrsClass = _make_attr_tuple_class(cls.__name__, attr_names) + + if kw_only: + own_attrs = [a.evolve(kw_only=True) for a in own_attrs] + base_attrs = [a.evolve(kw_only=True) for a in base_attrs] + + attrs = AttrsClass(base_attrs + own_attrs) + + # Mandatory vs non-mandatory attr order only matters when they are part of + # the __init__ signature and when they aren't kw_only (which are moved to + # the end and can be mandatory or non-mandatory in any order, as they will + # be specified as keyword args anyway). Check the order of those attrs: + had_default = False + for a in (a for a in attrs if a.init is not False and a.kw_only is False): + if had_default is True and a.default is NOTHING: + raise ValueError( + "No mandatory attributes allowed after an attribute with a " + "default value or factory. Attribute in question: %r" % (a,) + ) + + if had_default is False and a.default is not NOTHING: + had_default = True + + if field_transformer is not None: + attrs = field_transformer(cls, attrs) + return _Attributes((attrs, base_attrs, base_attr_map)) + + +if PYPY: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + if isinstance(self, BaseException) and name in ( + "__cause__", + "__context__", + ): + BaseException.__setattr__(self, name, value) + return + + raise FrozenInstanceError() + + +else: + + def _frozen_setattrs(self, name, value): + """ + Attached to frozen classes as __setattr__. + """ + raise FrozenInstanceError() + + +def _frozen_delattrs(self, name): + """ + Attached to frozen classes as __delattr__. + """ + raise FrozenInstanceError() + + +class _ClassBuilder(object): + """ + Iteratively build *one* class. + """ + + __slots__ = ( + "_attr_names", + "_attrs", + "_base_attr_map", + "_base_names", + "_cache_hash", + "_cls", + "_cls_dict", + "_delete_attribs", + "_frozen", + "_has_post_init", + "_is_exc", + "_on_setattr", + "_slots", + "_weakref_slot", + "_has_own_setattr", + "_has_custom_setattr", + ) + + def __init__( + self, + cls, + these, + slots, + frozen, + weakref_slot, + getstate_setstate, + auto_attribs, + kw_only, + cache_hash, + is_exc, + collect_by_mro, + on_setattr, + has_custom_setattr, + field_transformer, + ): + attrs, base_attrs, base_map = _transform_attrs( + cls, + these, + auto_attribs, + kw_only, + collect_by_mro, + field_transformer, + ) + + self._cls = cls + self._cls_dict = dict(cls.__dict__) if slots else {} + self._attrs = attrs + self._base_names = set(a.name for a in base_attrs) + self._base_attr_map = base_map + self._attr_names = tuple(a.name for a in attrs) + self._slots = slots + self._frozen = frozen + self._weakref_slot = weakref_slot + self._cache_hash = cache_hash + self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) + self._delete_attribs = not bool(these) + self._is_exc = is_exc + self._on_setattr = on_setattr + + self._has_custom_setattr = has_custom_setattr + self._has_own_setattr = False + + self._cls_dict["__attrs_attrs__"] = self._attrs + + if frozen: + self._cls_dict["__setattr__"] = _frozen_setattrs + self._cls_dict["__delattr__"] = _frozen_delattrs + + self._has_own_setattr = True + + if getstate_setstate: + ( + self._cls_dict["__getstate__"], + self._cls_dict["__setstate__"], + ) = self._make_getstate_setstate() + + def __repr__(self): + return "<_ClassBuilder(cls={cls})>".format(cls=self._cls.__name__) + + def build_class(self): + """ + Finalize class based on the accumulated configuration. + + Builder cannot be used after calling this method. + """ + if self._slots is True: + return self._create_slots_class() + else: + return self._patch_original_class() + + def _patch_original_class(self): + """ + Apply accumulated methods and return the class. + """ + cls = self._cls + base_names = self._base_names + + # Clean class of attribute definitions (`attr.ib()`s). + if self._delete_attribs: + for name in self._attr_names: + if ( + name not in base_names + and getattr(cls, name, _sentinel) is not _sentinel + ): + try: + delattr(cls, name) + except AttributeError: + # This can happen if a base class defines a class + # variable and we want to set an attribute with the + # same name by using only a type annotation. + pass + + # Attach our dunder methods. + for name, value in self._cls_dict.items(): + setattr(cls, name, value) + + # If we've inherited an attrs __setattr__ and don't write our own, + # reset it to object's. + if not self._has_own_setattr and getattr( + cls, "__attrs_own_setattr__", False + ): + cls.__attrs_own_setattr__ = False + + if not self._has_custom_setattr: + cls.__setattr__ = object.__setattr__ + + return cls + + def _create_slots_class(self): + """ + Build and return a new class with a `__slots__` attribute. + """ + base_names = self._base_names + cd = { + k: v + for k, v in iteritems(self._cls_dict) + if k not in tuple(self._attr_names) + ("__dict__", "__weakref__") + } + + # If our class doesn't have its own implementation of __setattr__ + # (either from the user or by us), check the bases, if one of them has + # an attrs-made __setattr__, that needs to be reset. We don't walk the + # MRO because we only care about our immediate base classes. + # XXX: This can be confused by subclassing a slotted attrs class with + # XXX: a non-attrs class and subclass the resulting class with an attrs + # XXX: class. See `test_slotted_confused` for details. For now that's + # XXX: OK with us. + if not self._has_own_setattr: + cd["__attrs_own_setattr__"] = False + + if not self._has_custom_setattr: + for base_cls in self._cls.__bases__: + if base_cls.__dict__.get("__attrs_own_setattr__", False): + cd["__setattr__"] = object.__setattr__ + break + + # Traverse the MRO to check for an existing __weakref__. + weakref_inherited = False + for base_cls in self._cls.__mro__[1:-1]: + if base_cls.__dict__.get("__weakref__", None) is not None: + weakref_inherited = True + break + + names = self._attr_names + if ( + self._weakref_slot + and "__weakref__" not in getattr(self._cls, "__slots__", ()) + and "__weakref__" not in names + and not weakref_inherited + ): + names += ("__weakref__",) + + # We only add the names of attributes that aren't inherited. + # Setting __slots__ to inherited attributes wastes memory. + slot_names = [name for name in names if name not in base_names] + if self._cache_hash: + slot_names.append(_hash_cache_field) + cd["__slots__"] = tuple(slot_names) + + qualname = getattr(self._cls, "__qualname__", None) + if qualname is not None: + cd["__qualname__"] = qualname + + # Create new class based on old class and our methods. + cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd) + + # The following is a fix for + # https://github.com/python-attrs/attrs/issues/102. On Python 3, + # if a method mentions `__class__` or uses the no-arg super(), the + # compiler will bake a reference to the class in the method itself + # as `method.__closure__`. Since we replace the class with a + # clone, we rewrite these references so it keeps working. + for item in cls.__dict__.values(): + if isinstance(item, (classmethod, staticmethod)): + # Class- and staticmethods hide their functions inside. + # These might need to be rewritten as well. + closure_cells = getattr(item.__func__, "__closure__", None) + else: + closure_cells = getattr(item, "__closure__", None) + + if not closure_cells: # Catch None or the empty list. + continue + for cell in closure_cells: + try: + match = cell.cell_contents is self._cls + except ValueError: # ValueError: Cell is empty + pass + else: + if match: + set_closure_cell(cell, cls) + + return cls + + def add_repr(self, ns): + self._cls_dict["__repr__"] = self._add_method_dunders( + _make_repr(self._attrs, ns=ns) + ) + return self + + def add_str(self): + repr = self._cls_dict.get("__repr__") + if repr is None: + raise ValueError( + "__str__ can only be generated if a __repr__ exists." + ) + + def __str__(self): + return self.__repr__() + + self._cls_dict["__str__"] = self._add_method_dunders(__str__) + return self + + def _make_getstate_setstate(self): + """ + Create custom __setstate__ and __getstate__ methods. + """ + # __weakref__ is not writable. + state_attr_names = tuple( + an for an in self._attr_names if an != "__weakref__" + ) + + def slots_getstate(self): + """ + Automatically created by attrs. + """ + return tuple(getattr(self, name) for name in state_attr_names) + + hash_caching_enabled = self._cache_hash + + def slots_setstate(self, state): + """ + Automatically created by attrs. + """ + __bound_setattr = _obj_setattr.__get__(self, Attribute) + for name, value in zip(state_attr_names, state): + __bound_setattr(name, value) + + # The hash code cache is not included when the object is + # serialized, but it still needs to be initialized to None to + # indicate that the first call to __hash__ should be a cache + # miss. + if hash_caching_enabled: + __bound_setattr(_hash_cache_field, None) + + return slots_getstate, slots_setstate + + def make_unhashable(self): + self._cls_dict["__hash__"] = None + return self + + def add_hash(self): + self._cls_dict["__hash__"] = self._add_method_dunders( + _make_hash( + self._cls, + self._attrs, + frozen=self._frozen, + cache_hash=self._cache_hash, + ) + ) + + return self + + def add_init(self): + self._cls_dict["__init__"] = self._add_method_dunders( + _make_init( + self._cls, + self._attrs, + self._has_post_init, + self._frozen, + self._slots, + self._cache_hash, + self._base_attr_map, + self._is_exc, + self._on_setattr is not None + and self._on_setattr is not setters.NO_OP, + ) + ) + + return self + + def add_eq(self): + cd = self._cls_dict + + cd["__eq__"] = self._add_method_dunders( + _make_eq(self._cls, self._attrs) + ) + cd["__ne__"] = self._add_method_dunders(_make_ne()) + + return self + + def add_order(self): + cd = self._cls_dict + + cd["__lt__"], cd["__le__"], cd["__gt__"], cd["__ge__"] = ( + self._add_method_dunders(meth) + for meth in _make_order(self._cls, self._attrs) + ) + + return self + + def add_setattr(self): + if self._frozen: + return self + + sa_attrs = {} + for a in self._attrs: + on_setattr = a.on_setattr or self._on_setattr + if on_setattr and on_setattr is not setters.NO_OP: + sa_attrs[a.name] = a, on_setattr + + if not sa_attrs: + return self + + if self._has_custom_setattr: + # We need to write a __setattr__ but there already is one! + raise ValueError( + "Can't combine custom __setattr__ with on_setattr hooks." + ) + + # docstring comes from _add_method_dunders + def __setattr__(self, name, val): + try: + a, hook = sa_attrs[name] + except KeyError: + nval = val + else: + nval = hook(self, a, val) + + _obj_setattr(self, name, nval) + + self._cls_dict["__attrs_own_setattr__"] = True + self._cls_dict["__setattr__"] = self._add_method_dunders(__setattr__) + self._has_own_setattr = True + + return self + + def _add_method_dunders(self, method): + """ + Add __module__ and __qualname__ to a *method* if possible. + """ + try: + method.__module__ = self._cls.__module__ + except AttributeError: + pass + + try: + method.__qualname__ = ".".join( + (self._cls.__qualname__, method.__name__) + ) + except AttributeError: + pass + + try: + method.__doc__ = "Method generated by attrs for class %s." % ( + self._cls.__qualname__, + ) + except AttributeError: + pass + + return method + + +_CMP_DEPRECATION = ( + "The usage of `cmp` is deprecated and will be removed on or after " + "2021-06-01. Please use `eq` and `order` instead." +) + + +def _determine_eq_order(cmp, eq, order, default_eq): + """ + Validate the combination of *cmp*, *eq*, and *order*. Derive the effective + values of eq and order. If *eq* is None, set it to *default_eq*. + """ + if cmp is not None and any((eq is not None, order is not None)): + raise ValueError("Don't mix `cmp` with `eq' and `order`.") + + # cmp takes precedence due to bw-compatibility. + if cmp is not None: + warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=3) + + return cmp, cmp + + # If left None, equality is set to the specified default and ordering + # mirrors equality. + if eq is None: + eq = default_eq + + if order is None: + order = eq + + if eq is False and order is True: + raise ValueError("`order` can only be True if `eq` is True too.") + + return eq, order + + +def _determine_whether_to_implement( + cls, flag, auto_detect, dunders, default=True +): + """ + Check whether we should implement a set of methods for *cls*. + + *flag* is the argument passed into @attr.s like 'init', *auto_detect* the + same as passed into @attr.s and *dunders* is a tuple of attribute names + whose presence signal that the user has implemented it themselves. + + Return *default* if no reason for either for or against is found. + + auto_detect must be False on Python 2. + """ + if flag is True or flag is False: + return flag + + if flag is None and auto_detect is False: + return default + + # Logically, flag is None and auto_detect is True here. + for dunder in dunders: + if _has_own_attribute(cls, dunder): + return False + + return default + + +def attrs( + maybe_cls=None, + these=None, + repr_ns=None, + repr=None, + cmp=None, + hash=None, + init=None, + slots=False, + frozen=False, + weakref_slot=True, + str=False, + auto_attribs=False, + kw_only=False, + cache_hash=False, + auto_exc=False, + eq=None, + order=None, + auto_detect=False, + collect_by_mro=False, + getstate_setstate=None, + on_setattr=None, + field_transformer=None, +): + r""" + A class decorator that adds `dunder + `_\ -methods according to the + specified attributes using `attr.ib` or the *these* argument. + + :param these: A dictionary of name to `attr.ib` mappings. This is + useful to avoid the definition of your attributes within the class body + because you can't (e.g. if you want to add ``__repr__`` methods to + Django models) or don't want to. + + If *these* is not ``None``, ``attrs`` will *not* search the class body + for attributes and will *not* remove any attributes from it. + + If *these* is an ordered dict (`dict` on Python 3.6+, + `collections.OrderedDict` otherwise), the order is deduced from + the order of the attributes inside *these*. Otherwise the order + of the definition of the attributes is used. + + :type these: `dict` of `str` to `attr.ib` + + :param str repr_ns: When using nested classes, there's no way in Python 2 + to automatically detect that. Therefore it's possible to set the + namespace explicitly for a more meaningful ``repr`` output. + :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*, + *order*, and *hash* arguments explicitly, assume they are set to + ``True`` **unless any** of the involved methods for one of the + arguments is implemented in the *current* class (i.e. it is *not* + inherited from some base class). + + So for example by implementing ``__eq__`` on a class yourself, + ``attrs`` will deduce ``eq=False`` and won't create *neither* + ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible + ``__ne__`` by default, so it *should* be enough to only implement + ``__eq__`` in most cases). + + .. warning:: + + If you prevent ``attrs`` from creating the ordering methods for you + (``order=False``, e.g. by implementing ``__le__``), it becomes + *your* responsibility to make sure its ordering is sound. The best + way is to use the `functools.total_ordering` decorator. + + + Passing ``True`` or ``False`` to *init*, *repr*, *eq*, *order*, + *cmp*, or *hash* overrides whatever *auto_detect* would determine. + + *auto_detect* requires Python 3. Setting it ``True`` on Python 2 raises + a `PythonTooOldError`. + + :param bool repr: Create a ``__repr__`` method with a human readable + representation of ``attrs`` attributes.. + :param bool str: Create a ``__str__`` method that is identical to + ``__repr__``. This is usually not necessary except for + `Exception`\ s. + :param Optional[bool] eq: If ``True`` or ``None`` (default), add ``__eq__`` + and ``__ne__`` methods that check two instances for equality. + + They compare the instances as if they were tuples of their ``attrs`` + attributes if and only if the types of both classes are *identical*! + :param Optional[bool] order: If ``True``, add ``__lt__``, ``__le__``, + ``__gt__``, and ``__ge__`` methods that behave like *eq* above and + allow instances to be ordered. If ``None`` (default) mirror value of + *eq*. + :param Optional[bool] cmp: Setting to ``True`` is equivalent to setting + ``eq=True, order=True``. Deprecated in favor of *eq* and *order*, has + precedence over them for backward-compatibility though. Must not be + mixed with *eq* or *order*. + :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method + is generated according how *eq* and *frozen* are set. + + 1. If *both* are True, ``attrs`` will generate a ``__hash__`` for you. + 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to + None, marking it unhashable (which it is). + 3. If *eq* is False, ``__hash__`` will be left untouched meaning the + ``__hash__`` method of the base class will be used (if base class is + ``object``, this means it will fall back to id-based hashing.). + + Although not recommended, you can decide for yourself and force + ``attrs`` to create one (e.g. if the class is immutable even though you + didn't freeze it programmatically) by passing ``True`` or not. Both of + these cases are rather special and should be used carefully. + + See our documentation on `hashing`, Python's documentation on + `object.__hash__`, and the `GitHub issue that led to the default \ + behavior `_ for more + details. + :param bool init: Create a ``__init__`` method that initializes the + ``attrs`` attributes. Leading underscores are stripped for the + argument name. If a ``__attrs_post_init__`` method exists on the + class, it will be called after the class is fully initialized. + :param bool slots: Create a `slotted class ` that's more + memory-efficient. Slotted classes are generally superior to the default + dict classes, but have some gotchas you should know about, so we + encourage you to read the `glossary entry `. + :param bool frozen: Make instances immutable after initialization. If + someone attempts to modify a frozen instance, + `attr.exceptions.FrozenInstanceError` is raised. + + .. note:: + + 1. This is achieved by installing a custom ``__setattr__`` method + on your class, so you can't implement your own. + + 2. True immutability is impossible in Python. + + 3. This *does* have a minor a runtime performance `impact + ` when initializing new instances. In other words: + ``__init__`` is slightly slower with ``frozen=True``. + + 4. If a class is frozen, you cannot modify ``self`` in + ``__attrs_post_init__`` or a self-written ``__init__``. You can + circumvent that limitation by using + ``object.__setattr__(self, "attribute_name", value)``. + + 5. Subclasses of a frozen class are frozen too. + + :param bool weakref_slot: Make instances weak-referenceable. This has no + effect unless ``slots`` is also enabled. + :param bool auto_attribs: If ``True``, collect `PEP 526`_-annotated + attributes (Python 3.6 and later only) from the class body. + + In this case, you **must** annotate every field. If ``attrs`` + encounters a field that is set to an `attr.ib` but lacks a type + annotation, an `attr.exceptions.UnannotatedAttributeError` is + raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't + want to set a type. + + If you assign a value to those attributes (e.g. ``x: int = 42``), that + value becomes the default value like if it were passed using + ``attr.ib(default=42)``. Passing an instance of `Factory` also + works as expected. + + Attributes annotated as `typing.ClassVar`, and attributes that are + neither annotated nor set to an `attr.ib` are **ignored**. + + .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/ + :param bool kw_only: Make all attributes keyword-only (Python 3+) + in the generated ``__init__`` (if ``init`` is ``False``, this + parameter is ignored). + :param bool cache_hash: Ensure that the object's hash code is computed + only once and stored on the object. If this is set to ``True``, + hashing must be either explicitly or implicitly enabled for this + class. If the hash code is cached, avoid any reassignments of + fields involved in hash code computation or mutations of the objects + those fields point to after object creation. If such changes occur, + the behavior of the object's hash code is undefined. + :param bool auto_exc: If the class subclasses `BaseException` + (which implicitly includes any subclass of any exception), the + following happens to behave like a well-behaved Python exceptions + class: + + - the values for *eq*, *order*, and *hash* are ignored and the + instances compare and hash by the instance's ids (N.B. ``attrs`` will + *not* remove existing implementations of ``__hash__`` or the equality + methods. It just won't add own ones.), + - all attributes that are either passed into ``__init__`` or have a + default value are additionally available as a tuple in the ``args`` + attribute, + - the value of *str* is ignored leaving ``__str__`` to base classes. + :param bool collect_by_mro: Setting this to `True` fixes the way ``attrs`` + collects attributes from base classes. The default behavior is + incorrect in certain cases of multiple inheritance. It should be on by + default but is kept off for backward-compatability. + + See issue `#428 `_ for + more details. + + :param Optional[bool] getstate_setstate: + .. note:: + This is usually only interesting for slotted classes and you should + probably just set *auto_detect* to `True`. + + If `True`, ``__getstate__`` and + ``__setstate__`` are generated and attached to the class. This is + necessary for slotted classes to be pickleable. If left `None`, it's + `True` by default for slotted classes and ``False`` for dict classes. + + If *auto_detect* is `True`, and *getstate_setstate* is left `None`, + and **either** ``__getstate__`` or ``__setstate__`` is detected directly + on the class (i.e. not inherited), it is set to `False` (this is usually + what you want). + + :param on_setattr: A callable that is run whenever the user attempts to set + an attribute (either by assignment like ``i.x = 42`` or by using + `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments + as validators: the instance, the attribute that is being modified, and + the new value. + + If no exception is raised, the attribute is set to the return value of + the callable. + + If a list of callables is passed, they're automatically wrapped in an + `attr.setters.pipe`. + + :param Optional[callable] field_transformer: + A function that is called with the original class object and all + fields right before ``attrs`` finalizes the class. You can use + this, e.g., to automatically add converters or validators to + fields based on their types. See `transform-fields` for more details. + + .. versionadded:: 16.0.0 *slots* + .. versionadded:: 16.1.0 *frozen* + .. versionadded:: 16.3.0 *str* + .. versionadded:: 16.3.0 Support for ``__attrs_post_init__``. + .. versionchanged:: 17.1.0 + *hash* supports ``None`` as value which is also the default now. + .. versionadded:: 17.3.0 *auto_attribs* + .. versionchanged:: 18.1.0 + If *these* is passed, no attributes are deleted from the class body. + .. versionchanged:: 18.1.0 If *these* is ordered, the order is retained. + .. versionadded:: 18.2.0 *weakref_slot* + .. deprecated:: 18.2.0 + ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now raise a + `DeprecationWarning` if the classes compared are subclasses of + each other. ``__eq`` and ``__ne__`` never tried to compared subclasses + to each other. + .. versionchanged:: 19.2.0 + ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` now do not consider + subclasses comparable anymore. + .. versionadded:: 18.2.0 *kw_only* + .. versionadded:: 18.2.0 *cache_hash* + .. versionadded:: 19.1.0 *auto_exc* + .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. + .. versionadded:: 19.2.0 *eq* and *order* + .. versionadded:: 20.1.0 *auto_detect* + .. versionadded:: 20.1.0 *collect_by_mro* + .. versionadded:: 20.1.0 *getstate_setstate* + .. versionadded:: 20.1.0 *on_setattr* + .. versionadded:: 20.3.0 *field_transformer* + """ + if auto_detect and PY2: + raise PythonTooOldError( + "auto_detect only works on Python 3 and later." + ) + + eq_, order_ = _determine_eq_order(cmp, eq, order, None) + hash_ = hash # work around the lack of nonlocal + + if isinstance(on_setattr, (list, tuple)): + on_setattr = setters.pipe(*on_setattr) + + def wrap(cls): + + if getattr(cls, "__class__", None) is None: + raise TypeError("attrs only works with new-style classes.") + + is_frozen = frozen or _has_frozen_base_class(cls) + is_exc = auto_exc is True and issubclass(cls, BaseException) + has_own_setattr = auto_detect and _has_own_attribute( + cls, "__setattr__" + ) + + if has_own_setattr and is_frozen: + raise ValueError("Can't freeze a class with a custom __setattr__.") + + builder = _ClassBuilder( + cls, + these, + slots, + is_frozen, + weakref_slot, + _determine_whether_to_implement( + cls, + getstate_setstate, + auto_detect, + ("__getstate__", "__setstate__"), + default=slots, + ), + auto_attribs, + kw_only, + cache_hash, + is_exc, + collect_by_mro, + on_setattr, + has_own_setattr, + field_transformer, + ) + if _determine_whether_to_implement( + cls, repr, auto_detect, ("__repr__",) + ): + builder.add_repr(repr_ns) + if str is True: + builder.add_str() + + eq = _determine_whether_to_implement( + cls, eq_, auto_detect, ("__eq__", "__ne__") + ) + if not is_exc and eq is True: + builder.add_eq() + if not is_exc and _determine_whether_to_implement( + cls, order_, auto_detect, ("__lt__", "__le__", "__gt__", "__ge__") + ): + builder.add_order() + + builder.add_setattr() + + if ( + hash_ is None + and auto_detect is True + and _has_own_attribute(cls, "__hash__") + ): + hash = False + else: + hash = hash_ + if hash is not True and hash is not False and hash is not None: + # Can't use `hash in` because 1 == True for example. + raise TypeError( + "Invalid value for hash. Must be True, False, or None." + ) + elif hash is False or (hash is None and eq is False) or is_exc: + # Don't do anything. Should fall back to __object__'s __hash__ + # which is by id. + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " hashing must be either explicitly or implicitly " + "enabled." + ) + elif hash is True or ( + hash is None and eq is True and is_frozen is True + ): + # Build a __hash__ if told so, or if it's safe. + builder.add_hash() + else: + # Raise TypeError on attempts to hash. + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " hashing must be either explicitly or implicitly " + "enabled." + ) + builder.make_unhashable() + + if _determine_whether_to_implement( + cls, init, auto_detect, ("__init__",) + ): + builder.add_init() + else: + if cache_hash: + raise TypeError( + "Invalid value for cache_hash. To use hash caching," + " init must be True." + ) + + return builder.build_class() + + # maybe_cls's type depends on the usage of the decorator. It's a class + # if it's used as `@attrs` but ``None`` if used as `@attrs()`. + if maybe_cls is None: + return wrap + else: + return wrap(maybe_cls) + + +_attrs = attrs +""" +Internal alias so we can use it in functions that take an argument called +*attrs*. +""" + + +if PY2: + + def _has_frozen_base_class(cls): + """ + Check whether *cls* has a frozen ancestor by looking at its + __setattr__. + """ + return ( + getattr(cls.__setattr__, "__module__", None) + == _frozen_setattrs.__module__ + and cls.__setattr__.__name__ == _frozen_setattrs.__name__ + ) + + +else: + + def _has_frozen_base_class(cls): + """ + Check whether *cls* has a frozen ancestor by looking at its + __setattr__. + """ + return cls.__setattr__ == _frozen_setattrs + + +def _attrs_to_tuple(obj, attrs): + """ + Create a tuple of all values of *obj*'s *attrs*. + """ + return tuple(getattr(obj, a.name) for a in attrs) + + +def _generate_unique_filename(cls, func_name): + """ + Create a "filename" suitable for a function being generated. + """ + unique_id = uuid.uuid4() + extra = "" + count = 1 + + while True: + unique_filename = "".format( + func_name, + cls.__module__, + getattr(cls, "__qualname__", cls.__name__), + extra, + ) + # To handle concurrency we essentially "reserve" our spot in + # the linecache with a dummy line. The caller can then + # set this value correctly. + cache_line = (1, None, (str(unique_id),), unique_filename) + if ( + linecache.cache.setdefault(unique_filename, cache_line) + == cache_line + ): + return unique_filename + + # Looks like this spot is taken. Try again. + count += 1 + extra = "-{0}".format(count) + + +def _make_hash(cls, attrs, frozen, cache_hash): + attrs = tuple( + a for a in attrs if a.hash is True or (a.hash is None and a.eq is True) + ) + + tab = " " + + unique_filename = _generate_unique_filename(cls, "hash") + type_hash = hash(unique_filename) + + hash_def = "def __hash__(self" + hash_func = "hash((" + closing_braces = "))" + if not cache_hash: + hash_def += "):" + else: + if not PY2: + hash_def += ", *" + + hash_def += ( + ", _cache_wrapper=" + + "__import__('attr._make')._make._CacheHashWrapper):" + ) + hash_func = "_cache_wrapper(" + hash_func + closing_braces += ")" + + method_lines = [hash_def] + + def append_hash_computation_lines(prefix, indent): + """ + Generate the code for actually computing the hash code. + Below this will either be returned directly or used to compute + a value which is then cached, depending on the value of cache_hash + """ + + method_lines.extend( + [ + indent + prefix + hash_func, + indent + " %d," % (type_hash,), + ] + ) + + for a in attrs: + method_lines.append(indent + " self.%s," % a.name) + + method_lines.append(indent + " " + closing_braces) + + if cache_hash: + method_lines.append(tab + "if self.%s is None:" % _hash_cache_field) + if frozen: + append_hash_computation_lines( + "object.__setattr__(self, '%s', " % _hash_cache_field, tab * 2 + ) + method_lines.append(tab * 2 + ")") # close __setattr__ + else: + append_hash_computation_lines( + "self.%s = " % _hash_cache_field, tab * 2 + ) + method_lines.append(tab + "return self.%s" % _hash_cache_field) + else: + append_hash_computation_lines("return ", tab) + + script = "\n".join(method_lines) + globs = {} + locs = {} + bytecode = compile(script, unique_filename, "exec") + eval(bytecode, globs, locs) + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + linecache.cache[unique_filename] = ( + len(script), + None, + script.splitlines(True), + unique_filename, + ) + + return locs["__hash__"] + + +def _add_hash(cls, attrs): + """ + Add a hash method to *cls*. + """ + cls.__hash__ = _make_hash(cls, attrs, frozen=False, cache_hash=False) + return cls + + +def _make_ne(): + """ + Create __ne__ method. + """ + + def __ne__(self, other): + """ + Check equality and either forward a NotImplemented or + return the result negated. + """ + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + + return not result + + return __ne__ + + +def _make_eq(cls, attrs): + """ + Create __eq__ method for *cls* with *attrs*. + """ + attrs = [a for a in attrs if a.eq] + + unique_filename = _generate_unique_filename(cls, "eq") + lines = [ + "def __eq__(self, other):", + " if other.__class__ is not self.__class__:", + " return NotImplemented", + ] + # We can't just do a big self.x = other.x and... clause due to + # irregularities like nan == nan is false but (nan,) == (nan,) is true. + if attrs: + lines.append(" return (") + others = [" ) == ("] + for a in attrs: + lines.append(" self.%s," % (a.name,)) + others.append(" other.%s," % (a.name,)) + + lines += others + [" )"] + else: + lines.append(" return True") + + script = "\n".join(lines) + globs = {} + locs = {} + bytecode = compile(script, unique_filename, "exec") + eval(bytecode, globs, locs) + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + linecache.cache[unique_filename] = ( + len(script), + None, + script.splitlines(True), + unique_filename, + ) + return locs["__eq__"] + + +def _make_order(cls, attrs): + """ + Create ordering methods for *cls* with *attrs*. + """ + attrs = [a for a in attrs if a.order] + + def attrs_to_tuple(obj): + """ + Save us some typing. + """ + return _attrs_to_tuple(obj, attrs) + + def __lt__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) < attrs_to_tuple(other) + + return NotImplemented + + def __le__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) <= attrs_to_tuple(other) + + return NotImplemented + + def __gt__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) > attrs_to_tuple(other) + + return NotImplemented + + def __ge__(self, other): + """ + Automatically created by attrs. + """ + if other.__class__ is self.__class__: + return attrs_to_tuple(self) >= attrs_to_tuple(other) + + return NotImplemented + + return __lt__, __le__, __gt__, __ge__ + + +def _add_eq(cls, attrs=None): + """ + Add equality methods to *cls* with *attrs*. + """ + if attrs is None: + attrs = cls.__attrs_attrs__ + + cls.__eq__ = _make_eq(cls, attrs) + cls.__ne__ = _make_ne() + + return cls + + +_already_repring = threading.local() + + +def _make_repr(attrs, ns): + """ + Make a repr method that includes relevant *attrs*, adding *ns* to the full + name. + """ + + # Figure out which attributes to include, and which function to use to + # format them. The a.repr value can be either bool or a custom callable. + attr_names_with_reprs = tuple( + (a.name, repr if a.repr is True else a.repr) + for a in attrs + if a.repr is not False + ) + + def __repr__(self): + """ + Automatically created by attrs. + """ + try: + working_set = _already_repring.working_set + except AttributeError: + working_set = set() + _already_repring.working_set = working_set + + if id(self) in working_set: + return "..." + real_cls = self.__class__ + if ns is None: + qualname = getattr(real_cls, "__qualname__", None) + if qualname is not None: + class_name = qualname.rsplit(">.", 1)[-1] + else: + class_name = real_cls.__name__ + else: + class_name = ns + "." + real_cls.__name__ + + # Since 'self' remains on the stack (i.e.: strongly referenced) for the + # duration of this call, it's safe to depend on id(...) stability, and + # not need to track the instance and therefore worry about properties + # like weakref- or hash-ability. + working_set.add(id(self)) + try: + result = [class_name, "("] + first = True + for name, attr_repr in attr_names_with_reprs: + if first: + first = False + else: + result.append(", ") + result.extend( + (name, "=", attr_repr(getattr(self, name, NOTHING))) + ) + return "".join(result) + ")" + finally: + working_set.remove(id(self)) + + return __repr__ + + +def _add_repr(cls, ns=None, attrs=None): + """ + Add a repr method to *cls*. + """ + if attrs is None: + attrs = cls.__attrs_attrs__ + + cls.__repr__ = _make_repr(attrs, ns) + return cls + + +def fields(cls): + """ + Return the tuple of ``attrs`` attributes for a class. + + The tuple also allows accessing the fields by their names (see below for + examples). + + :param type cls: Class to introspect. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + :rtype: tuple (with name accessors) of `attr.Attribute` + + .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields + by name. + """ + if not isclass(cls): + raise TypeError("Passed object must be a class.") + attrs = getattr(cls, "__attrs_attrs__", None) + if attrs is None: + raise NotAnAttrsClassError( + "{cls!r} is not an attrs-decorated class.".format(cls=cls) + ) + return attrs + + +def fields_dict(cls): + """ + Return an ordered dictionary of ``attrs`` attributes for a class, whose + keys are the attribute names. + + :param type cls: Class to introspect. + + :raise TypeError: If *cls* is not a class. + :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` + class. + + :rtype: an ordered dict where keys are attribute names and values are + `attr.Attribute`\\ s. This will be a `dict` if it's + naturally ordered like on Python 3.6+ or an + :class:`~collections.OrderedDict` otherwise. + + .. versionadded:: 18.1.0 + """ + if not isclass(cls): + raise TypeError("Passed object must be a class.") + attrs = getattr(cls, "__attrs_attrs__", None) + if attrs is None: + raise NotAnAttrsClassError( + "{cls!r} is not an attrs-decorated class.".format(cls=cls) + ) + return ordered_dict(((a.name, a) for a in attrs)) + + +def validate(inst): + """ + Validate all attributes on *inst* that have a validator. + + Leaves all exceptions through. + + :param inst: Instance of a class with ``attrs`` attributes. + """ + if _config._run_validators is False: + return + + for a in fields(inst.__class__): + v = a.validator + if v is not None: + v(inst, a, getattr(inst, a.name)) + + +def _is_slot_cls(cls): + return "__slots__" in cls.__dict__ + + +def _is_slot_attr(a_name, base_attr_map): + """ + Check if the attribute name comes from a slot class. + """ + return a_name in base_attr_map and _is_slot_cls(base_attr_map[a_name]) + + +def _make_init( + cls, + attrs, + post_init, + frozen, + slots, + cache_hash, + base_attr_map, + is_exc, + has_global_on_setattr, +): + if frozen and has_global_on_setattr: + raise ValueError("Frozen classes can't use on_setattr.") + + needs_cached_setattr = cache_hash or frozen + filtered_attrs = [] + attr_dict = {} + for a in attrs: + if not a.init and a.default is NOTHING: + continue + + filtered_attrs.append(a) + attr_dict[a.name] = a + + if a.on_setattr is not None: + if frozen is True: + raise ValueError("Frozen classes can't use on_setattr.") + + needs_cached_setattr = True + elif ( + has_global_on_setattr and a.on_setattr is not setters.NO_OP + ) or _is_slot_attr(a.name, base_attr_map): + needs_cached_setattr = True + + unique_filename = _generate_unique_filename(cls, "init") + + script, globs, annotations = _attrs_to_init_script( + filtered_attrs, + frozen, + slots, + post_init, + cache_hash, + base_attr_map, + is_exc, + needs_cached_setattr, + has_global_on_setattr, + ) + locs = {} + bytecode = compile(script, unique_filename, "exec") + globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) + + if needs_cached_setattr: + # Save the lookup overhead in __init__ if we need to circumvent + # setattr hooks. + globs["_cached_setattr"] = _obj_setattr + + eval(bytecode, globs, locs) + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + linecache.cache[unique_filename] = ( + len(script), + None, + script.splitlines(True), + unique_filename, + ) + + __init__ = locs["__init__"] + __init__.__annotations__ = annotations + + return __init__ + + +def _setattr(attr_name, value_var, has_on_setattr): + """ + Use the cached object.setattr to set *attr_name* to *value_var*. + """ + return "_setattr('%s', %s)" % (attr_name, value_var) + + +def _setattr_with_converter(attr_name, value_var, has_on_setattr): + """ + Use the cached object.setattr to set *attr_name* to *value_var*, but run + its converter first. + """ + return "_setattr('%s', %s(%s))" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + +def _assign(attr_name, value, has_on_setattr): + """ + Unless *attr_name* has an on_setattr hook, use normal assignment. Otherwise + relegate to _setattr. + """ + if has_on_setattr: + return _setattr(attr_name, value, True) + + return "self.%s = %s" % (attr_name, value) + + +def _assign_with_converter(attr_name, value_var, has_on_setattr): + """ + Unless *attr_name* has an on_setattr hook, use normal assignment after + conversion. Otherwise relegate to _setattr_with_converter. + """ + if has_on_setattr: + return _setattr_with_converter(attr_name, value_var, True) + + return "self.%s = %s(%s)" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + +if PY2: + + def _unpack_kw_only_py2(attr_name, default=None): + """ + Unpack *attr_name* from _kw_only dict. + """ + if default is not None: + arg_default = ", %s" % default + else: + arg_default = "" + return "%s = _kw_only.pop('%s'%s)" % ( + attr_name, + attr_name, + arg_default, + ) + + def _unpack_kw_only_lines_py2(kw_only_args): + """ + Unpack all *kw_only_args* from _kw_only dict and handle errors. + + Given a list of strings "{attr_name}" and "{attr_name}={default}" + generates list of lines of code that pop attrs from _kw_only dict and + raise TypeError similar to builtin if required attr is missing or + extra key is passed. + + >>> print("\n".join(_unpack_kw_only_lines_py2(["a", "b=42"]))) + try: + a = _kw_only.pop('a') + b = _kw_only.pop('b', 42) + except KeyError as _key_error: + raise TypeError( + ... + if _kw_only: + raise TypeError( + ... + """ + lines = ["try:"] + lines.extend( + " " + _unpack_kw_only_py2(*arg.split("=")) + for arg in kw_only_args + ) + lines += """\ +except KeyError as _key_error: + raise TypeError( + '__init__() missing required keyword-only argument: %s' % _key_error + ) +if _kw_only: + raise TypeError( + '__init__() got an unexpected keyword argument %r' + % next(iter(_kw_only)) + ) +""".split( + "\n" + ) + return lines + + +def _attrs_to_init_script( + attrs, + frozen, + slots, + post_init, + cache_hash, + base_attr_map, + is_exc, + needs_cached_setattr, + has_global_on_setattr, +): + """ + Return a script of an initializer for *attrs* and a dict of globals. + + The globals are expected by the generated script. + + If *frozen* is True, we cannot set the attributes directly so we use + a cached ``object.__setattr__``. + """ + lines = [] + if needs_cached_setattr: + lines.append( + # Circumvent the __setattr__ descriptor to save one lookup per + # assignment. + # Note _setattr will be used again below if cache_hash is True + "_setattr = _cached_setattr.__get__(self, self.__class__)" + ) + + if frozen is True: + if slots is True: + fmt_setter = _setattr + fmt_setter_with_converter = _setattr_with_converter + else: + # Dict frozen classes assign directly to __dict__. + # But only if the attribute doesn't come from an ancestor slot + # class. + # Note _inst_dict will be used again below if cache_hash is True + lines.append("_inst_dict = self.__dict__") + + def fmt_setter(attr_name, value_var, has_on_setattr): + if _is_slot_attr(attr_name, base_attr_map): + return _setattr(attr_name, value_var, has_on_setattr) + + return "_inst_dict['%s'] = %s" % (attr_name, value_var) + + def fmt_setter_with_converter( + attr_name, value_var, has_on_setattr + ): + if has_on_setattr or _is_slot_attr(attr_name, base_attr_map): + return _setattr_with_converter( + attr_name, value_var, has_on_setattr + ) + + return "_inst_dict['%s'] = %s(%s)" % ( + attr_name, + _init_converter_pat % (attr_name,), + value_var, + ) + + else: + # Not frozen. + fmt_setter = _assign + fmt_setter_with_converter = _assign_with_converter + + args = [] + kw_only_args = [] + attrs_to_validate = [] + + # This is a dictionary of names to validator and converter callables. + # Injecting this into __init__ globals lets us avoid lookups. + names_for_globals = {} + annotations = {"return": None} + + for a in attrs: + if a.validator: + attrs_to_validate.append(a) + + attr_name = a.name + has_on_setattr = a.on_setattr is not None or ( + a.on_setattr is not setters.NO_OP and has_global_on_setattr + ) + arg_name = a.name.lstrip("_") + + has_factory = isinstance(a.default, Factory) + if has_factory and a.default.takes_self: + maybe_self = "self" + else: + maybe_self = "" + + if a.init is False: + if has_factory: + init_factory_name = _init_factory_pat.format(a.name) + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, + init_factory_name + "(%s)" % (maybe_self,), + has_on_setattr, + ) + ) + conv_name = _init_converter_pat % (a.name,) + names_for_globals[conv_name] = a.converter + else: + lines.append( + fmt_setter( + attr_name, + init_factory_name + "(%s)" % (maybe_self,), + has_on_setattr, + ) + ) + names_for_globals[init_factory_name] = a.default.factory + else: + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, + "attr_dict['%s'].default" % (attr_name,), + has_on_setattr, + ) + ) + conv_name = _init_converter_pat % (a.name,) + names_for_globals[conv_name] = a.converter + else: + lines.append( + fmt_setter( + attr_name, + "attr_dict['%s'].default" % (attr_name,), + has_on_setattr, + ) + ) + elif a.default is not NOTHING and not has_factory: + arg = "%s=attr_dict['%s'].default" % (arg_name, attr_name) + if a.kw_only: + kw_only_args.append(arg) + else: + args.append(arg) + + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) + + elif has_factory: + arg = "%s=NOTHING" % (arg_name,) + if a.kw_only: + kw_only_args.append(arg) + else: + args.append(arg) + lines.append("if %s is not NOTHING:" % (arg_name,)) + + init_factory_name = _init_factory_pat.format(a.name) + if a.converter is not None: + lines.append( + " " + + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + lines.append("else:") + lines.append( + " " + + fmt_setter_with_converter( + attr_name, + init_factory_name + "(" + maybe_self + ")", + has_on_setattr, + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append( + " " + fmt_setter(attr_name, arg_name, has_on_setattr) + ) + lines.append("else:") + lines.append( + " " + + fmt_setter( + attr_name, + init_factory_name + "(" + maybe_self + ")", + has_on_setattr, + ) + ) + names_for_globals[init_factory_name] = a.default.factory + else: + if a.kw_only: + kw_only_args.append(arg_name) + else: + args.append(arg_name) + + if a.converter is not None: + lines.append( + fmt_setter_with_converter( + attr_name, arg_name, has_on_setattr + ) + ) + names_for_globals[ + _init_converter_pat % (a.name,) + ] = a.converter + else: + lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) + + if a.init is True and a.converter is None and a.type is not None: + annotations[arg_name] = a.type + + if attrs_to_validate: # we can skip this if there are no validators. + names_for_globals["_config"] = _config + lines.append("if _config._run_validators is True:") + for a in attrs_to_validate: + val_name = "__attr_validator_" + a.name + attr_name = "__attr_" + a.name + lines.append( + " %s(self, %s, self.%s)" % (val_name, attr_name, a.name) + ) + names_for_globals[val_name] = a.validator + names_for_globals[attr_name] = a + + if post_init: + lines.append("self.__attrs_post_init__()") + + # because this is set only after __attrs_post_init is called, a crash + # will result if post-init tries to access the hash code. This seemed + # preferable to setting this beforehand, in which case alteration to + # field values during post-init combined with post-init accessing the + # hash code would result in silent bugs. + if cache_hash: + if frozen: + if slots: + # if frozen and slots, then _setattr defined above + init_hash_cache = "_setattr('%s', %s)" + else: + # if frozen and not slots, then _inst_dict defined above + init_hash_cache = "_inst_dict['%s'] = %s" + else: + init_hash_cache = "self.%s = %s" + lines.append(init_hash_cache % (_hash_cache_field, "None")) + + # For exceptions we rely on BaseException.__init__ for proper + # initialization. + if is_exc: + vals = ",".join("self." + a.name for a in attrs if a.init) + + lines.append("BaseException.__init__(self, %s)" % (vals,)) + + args = ", ".join(args) + if kw_only_args: + if PY2: + lines = _unpack_kw_only_lines_py2(kw_only_args) + lines + + args += "%s**_kw_only" % (", " if args else "",) # leading comma + else: + args += "%s*, %s" % ( + ", " if args else "", # leading comma + ", ".join(kw_only_args), # kw_only args + ) + return ( + """\ +def __init__(self, {args}): + {lines} +""".format( + args=args, lines="\n ".join(lines) if lines else "pass" + ), + names_for_globals, + annotations, + ) + + +class Attribute(object): + """ + *Read-only* representation of an attribute. + + Instances of this class are frequently used for introspection purposes + like: + + - `fields` returns a tuple of them. + - Validators get them passed as the first argument. + - The *field transformer* hook receives a list of them. + + :attribute name: The name of the attribute. + :attribute inherited: Whether or not that attribute has been inherited from + a base class. + + Plus *all* arguments of `attr.ib` (except for ``factory`` + which is only syntactic sugar for ``default=Factory(...)``. + + .. versionadded:: 20.1.0 *inherited* + .. versionadded:: 20.1.0 *on_setattr* + .. versionchanged:: 20.2.0 *inherited* is not taken into account for + equality checks and hashing anymore. + + For the full version history of the fields, see `attr.ib`. + """ + + __slots__ = ( + "name", + "default", + "validator", + "repr", + "eq", + "order", + "hash", + "init", + "metadata", + "type", + "converter", + "kw_only", + "inherited", + "on_setattr", + ) + + def __init__( + self, + name, + default, + validator, + repr, + cmp, # XXX: unused, remove along with other cmp code. + hash, + init, + inherited, + metadata=None, + type=None, + converter=None, + kw_only=False, + eq=None, + order=None, + on_setattr=None, + ): + eq, order = _determine_eq_order(cmp, eq, order, True) + + # Cache this descriptor here to speed things up later. + bound_setattr = _obj_setattr.__get__(self, Attribute) + + # Despite the big red warning, people *do* instantiate `Attribute` + # themselves. + bound_setattr("name", name) + bound_setattr("default", default) + bound_setattr("validator", validator) + bound_setattr("repr", repr) + bound_setattr("eq", eq) + bound_setattr("order", order) + bound_setattr("hash", hash) + bound_setattr("init", init) + bound_setattr("converter", converter) + bound_setattr( + "metadata", + ( + metadata_proxy(metadata) + if metadata + else _empty_metadata_singleton + ), + ) + bound_setattr("type", type) + bound_setattr("kw_only", kw_only) + bound_setattr("inherited", inherited) + bound_setattr("on_setattr", on_setattr) + + def __setattr__(self, name, value): + raise FrozenInstanceError() + + @classmethod + def from_counting_attr(cls, name, ca, type=None): + # type holds the annotated value. deal with conflicts: + if type is None: + type = ca.type + elif ca.type is not None: + raise ValueError( + "Type annotation and type argument cannot both be present" + ) + inst_dict = { + k: getattr(ca, k) + for k in Attribute.__slots__ + if k + not in ( + "name", + "validator", + "default", + "type", + "inherited", + ) # exclude methods and deprecated alias + } + return cls( + name=name, + validator=ca._validator, + default=ca._default, + type=type, + cmp=None, + inherited=False, + **inst_dict + ) + + @property + def cmp(self): + """ + Simulate the presence of a cmp attribute and warn. + """ + warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=2) + + return self.eq and self.order + + # Don't use attr.evolve since fields(Attribute) doesn't work + def evolve(self, **changes): + """ + Copy *self* and apply *changes*. + + This works similarly to `attr.evolve` but that function does not work + with ``Attribute``. + + It is mainly meant to be used for `transform-fields`. + + .. versionadded:: 20.3.0 + """ + new = copy.copy(self) + + new._setattrs(changes.items()) + + return new + + # Don't use _add_pickle since fields(Attribute) doesn't work + def __getstate__(self): + """ + Play nice with pickle. + """ + return tuple( + getattr(self, name) if name != "metadata" else dict(self.metadata) + for name in self.__slots__ + ) + + def __setstate__(self, state): + """ + Play nice with pickle. + """ + self._setattrs(zip(self.__slots__, state)) + + def _setattrs(self, name_values_pairs): + bound_setattr = _obj_setattr.__get__(self, Attribute) + for name, value in name_values_pairs: + if name != "metadata": + bound_setattr(name, value) + else: + bound_setattr( + name, + metadata_proxy(value) + if value + else _empty_metadata_singleton, + ) + + +_a = [ + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + eq=True, + order=False, + hash=(name != "metadata"), + init=True, + inherited=False, + ) + for name in Attribute.__slots__ +] + +Attribute = _add_hash( + _add_eq( + _add_repr(Attribute, attrs=_a), + attrs=[a for a in _a if a.name != "inherited"], + ), + attrs=[a for a in _a if a.hash and a.name != "inherited"], +) + + +class _CountingAttr(object): + """ + Intermediate representation of attributes that uses a counter to preserve + the order in which the attributes have been defined. + + *Internal* data structure of the attrs library. Running into is most + likely the result of a bug like a forgotten `@attr.s` decorator. + """ + + __slots__ = ( + "counter", + "_default", + "repr", + "eq", + "order", + "hash", + "init", + "metadata", + "_validator", + "converter", + "type", + "kw_only", + "on_setattr", + ) + __attrs_attrs__ = tuple( + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + hash=True, + init=True, + kw_only=False, + eq=True, + order=False, + inherited=False, + on_setattr=None, + ) + for name in ( + "counter", + "_default", + "repr", + "eq", + "order", + "hash", + "init", + "on_setattr", + ) + ) + ( + Attribute( + name="metadata", + default=None, + validator=None, + repr=True, + cmp=None, + hash=False, + init=True, + kw_only=False, + eq=True, + order=False, + inherited=False, + on_setattr=None, + ), + ) + cls_counter = 0 + + def __init__( + self, + default, + validator, + repr, + cmp, # XXX: unused, remove along with cmp + hash, + init, + converter, + metadata, + type, + kw_only, + eq, + order, + on_setattr, + ): + _CountingAttr.cls_counter += 1 + self.counter = _CountingAttr.cls_counter + self._default = default + self._validator = validator + self.converter = converter + self.repr = repr + self.eq = eq + self.order = order + self.hash = hash + self.init = init + self.metadata = metadata + self.type = type + self.kw_only = kw_only + self.on_setattr = on_setattr + + def validator(self, meth): + """ + Decorator that adds *meth* to the list of validators. + + Returns *meth* unchanged. + + .. versionadded:: 17.1.0 + """ + if self._validator is None: + self._validator = meth + else: + self._validator = and_(self._validator, meth) + return meth + + def default(self, meth): + """ + Decorator that allows to set the default for an attribute. + + Returns *meth* unchanged. + + :raises DefaultAlreadySetError: If default has been set before. + + .. versionadded:: 17.1.0 + """ + if self._default is not NOTHING: + raise DefaultAlreadySetError() + + self._default = Factory(meth, takes_self=True) + + return meth + + +_CountingAttr = _add_eq(_add_repr(_CountingAttr)) + + +@attrs(slots=True, init=False, hash=True) +class Factory(object): + """ + Stores a factory callable. + + If passed as the default value to `attr.ib`, the factory is used to + generate a new value. + + :param callable factory: A callable that takes either none or exactly one + mandatory positional argument depending on *takes_self*. + :param bool takes_self: Pass the partially initialized instance that is + being initialized as a positional argument. + + .. versionadded:: 17.1.0 *takes_self* + """ + + factory = attrib() + takes_self = attrib() + + def __init__(self, factory, takes_self=False): + """ + `Factory` is part of the default machinery so if we want a default + value here, we have to implement it ourselves. + """ + self.factory = factory + self.takes_self = takes_self + + +def make_class(name, attrs, bases=(object,), **attributes_arguments): + """ + A quick way to create a new class called *name* with *attrs*. + + :param str name: The name for the new class. + + :param attrs: A list of names or a dictionary of mappings of names to + attributes. + + If *attrs* is a list or an ordered dict (`dict` on Python 3.6+, + `collections.OrderedDict` otherwise), the order is deduced from + the order of the names or attributes inside *attrs*. Otherwise the + order of the definition of the attributes is used. + :type attrs: `list` or `dict` + + :param tuple bases: Classes that the new class will subclass. + + :param attributes_arguments: Passed unmodified to `attr.s`. + + :return: A new class with *attrs*. + :rtype: type + + .. versionadded:: 17.1.0 *bases* + .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. + """ + if isinstance(attrs, dict): + cls_dict = attrs + elif isinstance(attrs, (list, tuple)): + cls_dict = dict((a, attrib()) for a in attrs) + else: + raise TypeError("attrs argument must be a dict or a list.") + + post_init = cls_dict.pop("__attrs_post_init__", None) + type_ = type( + name, + bases, + {} if post_init is None else {"__attrs_post_init__": post_init}, + ) + # For pickling to work, the __module__ variable needs to be set to the + # frame where the class is created. Bypass this step in environments where + # sys._getframe is not defined (Jython for example) or sys._getframe is not + # defined for arguments greater than 0 (IronPython). + try: + type_.__module__ = sys._getframe(1).f_globals.get( + "__name__", "__main__" + ) + except (AttributeError, ValueError): + pass + + # We do it here for proper warnings with meaningful stacklevel. + cmp = attributes_arguments.pop("cmp", None) + ( + attributes_arguments["eq"], + attributes_arguments["order"], + ) = _determine_eq_order( + cmp, + attributes_arguments.get("eq"), + attributes_arguments.get("order"), + True, + ) + + return _attrs(these=cls_dict, **attributes_arguments)(type_) + + +# These are required by within this module so we define them here and merely +# import into .validators / .converters. + + +@attrs(slots=True, hash=True) +class _AndValidator(object): + """ + Compose many validators to a single one. + """ + + _validators = attrib() + + def __call__(self, inst, attr, value): + for v in self._validators: + v(inst, attr, value) + + +def and_(*validators): + """ + A validator that composes multiple validators into one. + + When called on a value, it runs all wrapped validators. + + :param callables validators: Arbitrary number of validators. + + .. versionadded:: 17.1.0 + """ + vals = [] + for validator in validators: + vals.extend( + validator._validators + if isinstance(validator, _AndValidator) + else [validator] + ) + + return _AndValidator(tuple(vals)) + + +def pipe(*converters): + """ + A converter that composes multiple converters into one. + + When called on a value, it runs all wrapped converters, returning the + *last* value. + + :param callables converters: Arbitrary number of converters. + + .. versionadded:: 20.1.0 + """ + + def pipe_converter(val): + for converter in converters: + val = converter(val) + + return val + + return pipe_converter diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_next_gen.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_next_gen.py new file mode 100644 index 00000000..2b5565c5 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_next_gen.py @@ -0,0 +1,160 @@ +""" +This is a Python 3.6 and later-only, keyword-only, and **provisional** API that +calls `attr.s` with different default values. + +Provisional APIs that shall become "import attrs" one glorious day. +""" + +from functools import partial + +from attr.exceptions import UnannotatedAttributeError + +from . import setters +from ._make import NOTHING, _frozen_setattrs, attrib, attrs + + +def define( + maybe_cls=None, + *, + these=None, + repr=None, + hash=None, + init=None, + slots=True, + frozen=False, + weakref_slot=True, + str=False, + auto_attribs=None, + kw_only=False, + cache_hash=False, + auto_exc=True, + eq=None, + order=False, + auto_detect=True, + getstate_setstate=None, + on_setattr=None, + field_transformer=None, +): + r""" + The only behavioral differences are the handling of the *auto_attribs* + option: + + :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves + exactly like `attr.s`. If left `None`, `attr.s` will try to guess: + + 1. If all attributes are annotated and no `attr.ib` is found, it assumes + *auto_attribs=True*. + 2. Otherwise it assumes *auto_attribs=False* and tries to collect + `attr.ib`\ s. + + and that mutable classes (``frozen=False``) validate on ``__setattr__``. + + .. versionadded:: 20.1.0 + """ + + def do_it(cls, auto_attribs): + return attrs( + maybe_cls=cls, + these=these, + repr=repr, + hash=hash, + init=init, + slots=slots, + frozen=frozen, + weakref_slot=weakref_slot, + str=str, + auto_attribs=auto_attribs, + kw_only=kw_only, + cache_hash=cache_hash, + auto_exc=auto_exc, + eq=eq, + order=order, + auto_detect=auto_detect, + collect_by_mro=True, + getstate_setstate=getstate_setstate, + on_setattr=on_setattr, + field_transformer=field_transformer, + ) + + def wrap(cls): + """ + Making this a wrapper ensures this code runs during class creation. + + We also ensure that frozen-ness of classes is inherited. + """ + nonlocal frozen, on_setattr + + had_on_setattr = on_setattr not in (None, setters.NO_OP) + + # By default, mutable classes validate on setattr. + if frozen is False and on_setattr is None: + on_setattr = setters.validate + + # However, if we subclass a frozen class, we inherit the immutability + # and disable on_setattr. + for base_cls in cls.__bases__: + if base_cls.__setattr__ is _frozen_setattrs: + if had_on_setattr: + raise ValueError( + "Frozen classes can't use on_setattr " + "(frozen-ness was inherited)." + ) + + on_setattr = setters.NO_OP + break + + if auto_attribs is not None: + return do_it(cls, auto_attribs) + + try: + return do_it(cls, True) + except UnannotatedAttributeError: + return do_it(cls, False) + + # maybe_cls's type depends on the usage of the decorator. It's a class + # if it's used as `@attrs` but ``None`` if used as `@attrs()`. + if maybe_cls is None: + return wrap + else: + return wrap(maybe_cls) + + +mutable = define +frozen = partial(define, frozen=True, on_setattr=None) + + +def field( + *, + default=NOTHING, + validator=None, + repr=True, + hash=None, + init=True, + metadata=None, + converter=None, + factory=None, + kw_only=False, + eq=None, + order=None, + on_setattr=None, +): + """ + Identical to `attr.ib`, except keyword-only and with some arguments + removed. + + .. versionadded:: 20.1.0 + """ + return attrib( + default=default, + validator=validator, + repr=repr, + hash=hash, + init=init, + metadata=metadata, + converter=converter, + factory=factory, + kw_only=kw_only, + eq=eq, + order=order, + on_setattr=on_setattr, + ) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.py new file mode 100644 index 00000000..014e78a1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.py @@ -0,0 +1,85 @@ +from __future__ import absolute_import, division, print_function + +from functools import total_ordering + +from ._funcs import astuple +from ._make import attrib, attrs + + +@total_ordering +@attrs(eq=False, order=False, slots=True, frozen=True) +class VersionInfo(object): + """ + A version object that can be compared to tuple of length 1--4: + + >>> attr.VersionInfo(19, 1, 0, "final") <= (19, 2) + True + >>> attr.VersionInfo(19, 1, 0, "final") < (19, 1, 1) + True + >>> vi = attr.VersionInfo(19, 2, 0, "final") + >>> vi < (19, 1, 1) + False + >>> vi < (19,) + False + >>> vi == (19, 2,) + True + >>> vi == (19, 2, 1) + False + + .. versionadded:: 19.2 + """ + + year = attrib(type=int) + minor = attrib(type=int) + micro = attrib(type=int) + releaselevel = attrib(type=str) + + @classmethod + def _from_version_string(cls, s): + """ + Parse *s* and return a _VersionInfo. + """ + v = s.split(".") + if len(v) == 3: + v.append("final") + + return cls( + year=int(v[0]), minor=int(v[1]), micro=int(v[2]), releaselevel=v[3] + ) + + def _ensure_tuple(self, other): + """ + Ensure *other* is a tuple of a valid length. + + Returns a possibly transformed *other* and ourselves as a tuple of + the same length as *other*. + """ + + if self.__class__ is other.__class__: + other = astuple(other) + + if not isinstance(other, tuple): + raise NotImplementedError + + if not (1 <= len(other) <= 4): + raise NotImplementedError + + return astuple(self)[: len(other)], other + + def __eq__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + return us == them + + def __lt__(self, other): + try: + us, them = self._ensure_tuple(other) + except NotImplementedError: + return NotImplemented + + # Since alphabetically "dev0" < "final" < "post1" < "post2", we don't + # have to do anything special with releaselevel for now. + return us < them diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.pyi new file mode 100644 index 00000000..45ced086 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/_version_info.pyi @@ -0,0 +1,9 @@ +class VersionInfo: + @property + def year(self) -> int: ... + @property + def minor(self) -> int: ... + @property + def micro(self) -> int: ... + @property + def releaselevel(self) -> str: ... diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.py new file mode 100644 index 00000000..715ce178 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.py @@ -0,0 +1,85 @@ +""" +Commonly useful converters. +""" + +from __future__ import absolute_import, division, print_function + +from ._make import NOTHING, Factory, pipe + + +__all__ = [ + "pipe", + "optional", + "default_if_none", +] + + +def optional(converter): + """ + A converter that allows an attribute to be optional. An optional attribute + is one which can be set to ``None``. + + :param callable converter: the converter that is used for non-``None`` + values. + + .. versionadded:: 17.1.0 + """ + + def optional_converter(val): + if val is None: + return None + return converter(val) + + return optional_converter + + +def default_if_none(default=NOTHING, factory=None): + """ + A converter that allows to replace ``None`` values by *default* or the + result of *factory*. + + :param default: Value to be used if ``None`` is passed. Passing an instance + of `attr.Factory` is supported, however the ``takes_self`` option + is *not*. + :param callable factory: A callable that takes not parameters whose result + is used if ``None`` is passed. + + :raises TypeError: If **neither** *default* or *factory* is passed. + :raises TypeError: If **both** *default* and *factory* are passed. + :raises ValueError: If an instance of `attr.Factory` is passed with + ``takes_self=True``. + + .. versionadded:: 18.2.0 + """ + if default is NOTHING and factory is None: + raise TypeError("Must pass either `default` or `factory`.") + + if default is not NOTHING and factory is not None: + raise TypeError( + "Must pass either `default` or `factory` but not both." + ) + + if factory is not None: + default = Factory(factory) + + if isinstance(default, Factory): + if default.takes_self: + raise ValueError( + "`takes_self` is not supported by default_if_none." + ) + + def default_if_none_converter(val): + if val is not None: + return val + + return default.factory() + + else: + + def default_if_none_converter(val): + if val is not None: + return val + + return default + + return default_if_none_converter diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.pyi new file mode 100644 index 00000000..7b0caa14 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/converters.pyi @@ -0,0 +1,11 @@ +from typing import TypeVar, Optional, Callable, overload +from . import _ConverterType + +_T = TypeVar("_T") + +def pipe(*validators: _ConverterType) -> _ConverterType: ... +def optional(converter: _ConverterType) -> _ConverterType: ... +@overload +def default_if_none(default: _T) -> _ConverterType: ... +@overload +def default_if_none(*, factory: Callable[[], _T]) -> _ConverterType: ... diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.py new file mode 100644 index 00000000..fcd89106 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.py @@ -0,0 +1,92 @@ +from __future__ import absolute_import, division, print_function + + +class FrozenError(AttributeError): + """ + A frozen/immutable instance or attribute haave been attempted to be + modified. + + It mirrors the behavior of ``namedtuples`` by using the same error message + and subclassing `AttributeError`. + + .. versionadded:: 20.1.0 + """ + + msg = "can't set attribute" + args = [msg] + + +class FrozenInstanceError(FrozenError): + """ + A frozen instance has been attempted to be modified. + + .. versionadded:: 16.1.0 + """ + + +class FrozenAttributeError(FrozenError): + """ + A frozen attribute has been attempted to be modified. + + .. versionadded:: 20.1.0 + """ + + +class AttrsAttributeNotFoundError(ValueError): + """ + An ``attrs`` function couldn't find an attribute that the user asked for. + + .. versionadded:: 16.2.0 + """ + + +class NotAnAttrsClassError(ValueError): + """ + A non-``attrs`` class has been passed into an ``attrs`` function. + + .. versionadded:: 16.2.0 + """ + + +class DefaultAlreadySetError(RuntimeError): + """ + A default has been set using ``attr.ib()`` and is attempted to be reset + using the decorator. + + .. versionadded:: 17.1.0 + """ + + +class UnannotatedAttributeError(RuntimeError): + """ + A class with ``auto_attribs=True`` has an ``attr.ib()`` without a type + annotation. + + .. versionadded:: 17.3.0 + """ + + +class PythonTooOldError(RuntimeError): + """ + It was attempted to use an ``attrs`` feature that requires a newer Python + version. + + .. versionadded:: 18.2.0 + """ + + +class NotCallableError(TypeError): + """ + A ``attr.ib()`` requiring a callable has been set with a value + that is not callable. + + .. versionadded:: 19.2.0 + """ + + def __init__(self, msg, value): + super(TypeError, self).__init__(msg, value) + self.msg = msg + self.value = value + + def __str__(self): + return str(self.msg) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.pyi new file mode 100644 index 00000000..f2680118 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/exceptions.pyi @@ -0,0 +1,17 @@ +from typing import Any + +class FrozenError(AttributeError): + msg: str = ... + +class FrozenInstanceError(FrozenError): ... +class FrozenAttributeError(FrozenError): ... +class AttrsAttributeNotFoundError(ValueError): ... +class NotAnAttrsClassError(ValueError): ... +class DefaultAlreadySetError(RuntimeError): ... +class UnannotatedAttributeError(RuntimeError): ... +class PythonTooOldError(RuntimeError): ... + +class NotCallableError(TypeError): + msg: str = ... + value: Any = ... + def __init__(self, msg: str, value: Any) -> None: ... diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.py new file mode 100644 index 00000000..dc47e8fa --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.py @@ -0,0 +1,52 @@ +""" +Commonly useful filters for `attr.asdict`. +""" + +from __future__ import absolute_import, division, print_function + +from ._compat import isclass +from ._make import Attribute + + +def _split_what(what): + """ + Returns a tuple of `frozenset`s of classes and attributes. + """ + return ( + frozenset(cls for cls in what if isclass(cls)), + frozenset(cls for cls in what if isinstance(cls, Attribute)), + ) + + +def include(*what): + """ + Whitelist *what*. + + :param what: What to whitelist. + :type what: `list` of `type` or `attr.Attribute`\\ s + + :rtype: `callable` + """ + cls, attrs = _split_what(what) + + def include_(attribute, value): + return value.__class__ in cls or attribute in attrs + + return include_ + + +def exclude(*what): + """ + Blacklist *what*. + + :param what: What to blacklist. + :type what: `list` of classes or `attr.Attribute`\\ s. + + :rtype: `callable` + """ + cls, attrs = _split_what(what) + + def exclude_(attribute, value): + return value.__class__ not in cls and attribute not in attrs + + return exclude_ diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.pyi new file mode 100644 index 00000000..68368fe2 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/filters.pyi @@ -0,0 +1,5 @@ +from typing import Union, Any +from . import Attribute, _FilterType + +def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... +def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/py.typed b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.py new file mode 100644 index 00000000..240014b3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.py @@ -0,0 +1,77 @@ +""" +Commonly used hooks for on_setattr. +""" + +from __future__ import absolute_import, division, print_function + +from . import _config +from .exceptions import FrozenAttributeError + + +def pipe(*setters): + """ + Run all *setters* and return the return value of the last one. + + .. versionadded:: 20.1.0 + """ + + def wrapped_pipe(instance, attrib, new_value): + rv = new_value + + for setter in setters: + rv = setter(instance, attrib, rv) + + return rv + + return wrapped_pipe + + +def frozen(_, __, ___): + """ + Prevent an attribute to be modified. + + .. versionadded:: 20.1.0 + """ + raise FrozenAttributeError() + + +def validate(instance, attrib, new_value): + """ + Run *attrib*'s validator on *new_value* if it has one. + + .. versionadded:: 20.1.0 + """ + if _config._run_validators is False: + return new_value + + v = attrib.validator + if not v: + return new_value + + v(instance, attrib, new_value) + + return new_value + + +def convert(instance, attrib, new_value): + """ + Run *attrib*'s converter -- if it has one -- on *new_value* and return the + result. + + .. versionadded:: 20.1.0 + """ + c = attrib.converter + if c: + return c(new_value) + + return new_value + + +NO_OP = object() +""" +Sentinel for disabling class-wide *on_setattr* hooks for certain attributes. + +Does not work in `pipe` or within lists. + +.. versionadded:: 20.1.0 +""" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.pyi new file mode 100644 index 00000000..19bc33fd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/setters.pyi @@ -0,0 +1,18 @@ +from . import _OnSetAttrType, Attribute +from typing import TypeVar, Any, NewType, NoReturn, cast + +_T = TypeVar("_T") + +def frozen( + instance: Any, attribute: Attribute, new_value: Any +) -> NoReturn: ... +def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ... +def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ... + +# convert is allowed to return Any, because they can be chained using pipe. +def convert( + instance: Any, attribute: Attribute[Any], new_value: Any +) -> Any: ... + +_NoOpType = NewType("_NoOpType", object) +NO_OP: _NoOpType diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.py new file mode 100644 index 00000000..b9a73054 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.py @@ -0,0 +1,379 @@ +""" +Commonly useful validators. +""" + +from __future__ import absolute_import, division, print_function + +import re + +from ._make import _AndValidator, and_, attrib, attrs +from .exceptions import NotCallableError + + +__all__ = [ + "and_", + "deep_iterable", + "deep_mapping", + "in_", + "instance_of", + "is_callable", + "matches_re", + "optional", + "provides", +] + + +@attrs(repr=False, slots=True, hash=True) +class _InstanceOfValidator(object): + type = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not isinstance(value, self.type): + raise TypeError( + "'{name}' must be {type!r} (got {value!r} that is a " + "{actual!r}).".format( + name=attr.name, + type=self.type, + actual=value.__class__, + value=value, + ), + attr, + self.type, + value, + ) + + def __repr__(self): + return "".format( + type=self.type + ) + + +def instance_of(type): + """ + A validator that raises a `TypeError` if the initializer is called + with a wrong type for this particular attribute (checks are performed using + `isinstance` therefore it's also valid to pass a tuple of types). + + :param type: The type to check for. + :type type: type or tuple of types + + :raises TypeError: With a human readable error message, the attribute + (of type `attr.Attribute`), the expected type, and the value it + got. + """ + return _InstanceOfValidator(type) + + +@attrs(repr=False, frozen=True, slots=True) +class _MatchesReValidator(object): + regex = attrib() + flags = attrib() + match_func = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.match_func(value): + raise ValueError( + "'{name}' must match regex {regex!r}" + " ({value!r} doesn't)".format( + name=attr.name, regex=self.regex.pattern, value=value + ), + attr, + self.regex, + value, + ) + + def __repr__(self): + return "".format( + regex=self.regex + ) + + +def matches_re(regex, flags=0, func=None): + r""" + A validator that raises `ValueError` if the initializer is called + with a string that doesn't match *regex*. + + :param str regex: a regex string to match against + :param int flags: flags that will be passed to the underlying re function + (default 0) + :param callable func: which underlying `re` function to call (options + are `re.fullmatch`, `re.search`, `re.match`, default + is ``None`` which means either `re.fullmatch` or an emulation of + it on Python 2). For performance reasons, they won't be used directly + but on a pre-`re.compile`\ ed pattern. + + .. versionadded:: 19.2.0 + """ + fullmatch = getattr(re, "fullmatch", None) + valid_funcs = (fullmatch, None, re.search, re.match) + if func not in valid_funcs: + raise ValueError( + "'func' must be one of %s." + % ( + ", ".join( + sorted( + e and e.__name__ or "None" for e in set(valid_funcs) + ) + ), + ) + ) + + pattern = re.compile(regex, flags) + if func is re.match: + match_func = pattern.match + elif func is re.search: + match_func = pattern.search + else: + if fullmatch: + match_func = pattern.fullmatch + else: + pattern = re.compile(r"(?:{})\Z".format(regex), flags) + match_func = pattern.match + + return _MatchesReValidator(pattern, flags, match_func) + + +@attrs(repr=False, slots=True, hash=True) +class _ProvidesValidator(object): + interface = attrib() + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not self.interface.providedBy(value): + raise TypeError( + "'{name}' must provide {interface!r} which {value!r} " + "doesn't.".format( + name=attr.name, interface=self.interface, value=value + ), + attr, + self.interface, + value, + ) + + def __repr__(self): + return "".format( + interface=self.interface + ) + + +def provides(interface): + """ + A validator that raises a `TypeError` if the initializer is called + with an object that does not provide the requested *interface* (checks are + performed using ``interface.providedBy(value)`` (see `zope.interface + `_). + + :param interface: The interface to check for. + :type interface: ``zope.interface.Interface`` + + :raises TypeError: With a human readable error message, the attribute + (of type `attr.Attribute`), the expected interface, and the + value it got. + """ + return _ProvidesValidator(interface) + + +@attrs(repr=False, slots=True, hash=True) +class _OptionalValidator(object): + validator = attrib() + + def __call__(self, inst, attr, value): + if value is None: + return + + self.validator(inst, attr, value) + + def __repr__(self): + return "".format( + what=repr(self.validator) + ) + + +def optional(validator): + """ + A validator that makes an attribute optional. An optional attribute is one + which can be set to ``None`` in addition to satisfying the requirements of + the sub-validator. + + :param validator: A validator (or a list of validators) that is used for + non-``None`` values. + :type validator: callable or `list` of callables. + + .. versionadded:: 15.1.0 + .. versionchanged:: 17.1.0 *validator* can be a list of validators. + """ + if isinstance(validator, list): + return _OptionalValidator(_AndValidator(validator)) + return _OptionalValidator(validator) + + +@attrs(repr=False, slots=True, hash=True) +class _InValidator(object): + options = attrib() + + def __call__(self, inst, attr, value): + try: + in_options = value in self.options + except TypeError: # e.g. `1 in "abc"` + in_options = False + + if not in_options: + raise ValueError( + "'{name}' must be in {options!r} (got {value!r})".format( + name=attr.name, options=self.options, value=value + ) + ) + + def __repr__(self): + return "".format( + options=self.options + ) + + +def in_(options): + """ + A validator that raises a `ValueError` if the initializer is called + with a value that does not belong in the options provided. The check is + performed using ``value in options``. + + :param options: Allowed options. + :type options: list, tuple, `enum.Enum`, ... + + :raises ValueError: With a human readable error message, the attribute (of + type `attr.Attribute`), the expected options, and the value it + got. + + .. versionadded:: 17.1.0 + """ + return _InValidator(options) + + +@attrs(repr=False, slots=False, hash=True) +class _IsCallableValidator(object): + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if not callable(value): + message = ( + "'{name}' must be callable " + "(got {value!r} that is a {actual!r})." + ) + raise NotCallableError( + msg=message.format( + name=attr.name, value=value, actual=value.__class__ + ), + value=value, + ) + + def __repr__(self): + return "" + + +def is_callable(): + """ + A validator that raises a `attr.exceptions.NotCallableError` if the + initializer is called with a value for this particular attribute + that is not callable. + + .. versionadded:: 19.1.0 + + :raises `attr.exceptions.NotCallableError`: With a human readable error + message containing the attribute (`attr.Attribute`) name, + and the value it got. + """ + return _IsCallableValidator() + + +@attrs(repr=False, slots=True, hash=True) +class _DeepIterable(object): + member_validator = attrib(validator=is_callable()) + iterable_validator = attrib( + default=None, validator=optional(is_callable()) + ) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.iterable_validator is not None: + self.iterable_validator(inst, attr, value) + + for member in value: + self.member_validator(inst, attr, member) + + def __repr__(self): + iterable_identifier = ( + "" + if self.iterable_validator is None + else " {iterable!r}".format(iterable=self.iterable_validator) + ) + return ( + "" + ).format( + iterable_identifier=iterable_identifier, + member=self.member_validator, + ) + + +def deep_iterable(member_validator, iterable_validator=None): + """ + A validator that performs deep validation of an iterable. + + :param member_validator: Validator to apply to iterable members + :param iterable_validator: Validator to apply to iterable itself + (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + return _DeepIterable(member_validator, iterable_validator) + + +@attrs(repr=False, slots=True, hash=True) +class _DeepMapping(object): + key_validator = attrib(validator=is_callable()) + value_validator = attrib(validator=is_callable()) + mapping_validator = attrib(default=None, validator=optional(is_callable())) + + def __call__(self, inst, attr, value): + """ + We use a callable class to be able to change the ``__repr__``. + """ + if self.mapping_validator is not None: + self.mapping_validator(inst, attr, value) + + for key in value: + self.key_validator(inst, attr, key) + self.value_validator(inst, attr, value[key]) + + def __repr__(self): + return ( + "" + ).format(key=self.key_validator, value=self.value_validator) + + +def deep_mapping(key_validator, value_validator, mapping_validator=None): + """ + A validator that performs deep validation of a dictionary. + + :param key_validator: Validator to apply to dictionary keys + :param value_validator: Validator to apply to dictionary values + :param mapping_validator: Validator to apply to top-level mapping + attribute (optional) + + .. versionadded:: 19.1.0 + + :raises TypeError: if any sub-validators fail + """ + return _DeepMapping(key_validator, value_validator, mapping_validator) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.pyi b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.pyi new file mode 100644 index 00000000..9a22abb1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attr/validators.pyi @@ -0,0 +1,66 @@ +from typing import ( + Container, + List, + Union, + TypeVar, + Type, + Any, + Optional, + Tuple, + Iterable, + Mapping, + Callable, + Match, + AnyStr, + overload, +) +from . import _ValidatorType + +_T = TypeVar("_T") +_T1 = TypeVar("_T1") +_T2 = TypeVar("_T2") +_T3 = TypeVar("_T3") +_I = TypeVar("_I", bound=Iterable) +_K = TypeVar("_K") +_V = TypeVar("_V") +_M = TypeVar("_M", bound=Mapping) + +# To be more precise on instance_of use some overloads. +# If there are more than 3 items in the tuple then we fall back to Any +@overload +def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... +@overload +def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ... +@overload +def instance_of( + type: Tuple[Type[_T1], Type[_T2]] +) -> _ValidatorType[Union[_T1, _T2]]: ... +@overload +def instance_of( + type: Tuple[Type[_T1], Type[_T2], Type[_T3]] +) -> _ValidatorType[Union[_T1, _T2, _T3]]: ... +@overload +def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ... +def provides(interface: Any) -> _ValidatorType[Any]: ... +def optional( + validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]] +) -> _ValidatorType[Optional[_T]]: ... +def in_(options: Container[_T]) -> _ValidatorType[_T]: ... +def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... +def matches_re( + regex: AnyStr, + flags: int = ..., + func: Optional[ + Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]] + ] = ..., +) -> _ValidatorType[AnyStr]: ... +def deep_iterable( + member_validator: _ValidatorType[_T], + iterable_validator: Optional[_ValidatorType[_I]] = ..., +) -> _ValidatorType[_I]: ... +def deep_mapping( + key_validator: _ValidatorType[_K], + value_validator: _ValidatorType[_V], + mapping_validator: Optional[_ValidatorType[_M]] = ..., +) -> _ValidatorType[_M]: ... +def is_callable() -> _ValidatorType[_T]: ... diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst new file mode 100644 index 00000000..f14ef6c6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/AUTHORS.rst @@ -0,0 +1,11 @@ +Credits +======= + +``attrs`` is written and maintained by `Hynek Schlawack `_. + +The development is kindly supported by `Variomedia AG `_. + +A full list of contributors can be found in `GitHub's overview `_. + +It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions. +Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay? diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/LICENSE b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/LICENSE new file mode 100644 index 00000000..7ae3df93 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Hynek Schlawack + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/METADATA new file mode 100644 index 00000000..a92cacb0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/METADATA @@ -0,0 +1,241 @@ +Metadata-Version: 2.1 +Name: attrs +Version: 20.3.0 +Summary: Classes Without Boilerplate +Home-page: https://www.attrs.org/ +Author: Hynek Schlawack +Author-email: hs@ox.cx +Maintainer: Hynek Schlawack +Maintainer-email: hs@ox.cx +License: MIT +Project-URL: Documentation, https://www.attrs.org/ +Project-URL: Bug Tracker, https://github.com/python-attrs/attrs/issues +Project-URL: Source Code, https://github.com/python-attrs/attrs +Project-URL: Funding, https://github.com/sponsors/hynek +Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi +Keywords: class,attribute,boilerplate +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Natural Language :: English +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Description-Content-Type: text/x-rst +Provides-Extra: dev +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'dev' +Requires-Dist: hypothesis ; extra == 'dev' +Requires-Dist: pympler ; extra == 'dev' +Requires-Dist: pytest (>=4.3.0) ; extra == 'dev' +Requires-Dist: six ; extra == 'dev' +Requires-Dist: zope.interface ; extra == 'dev' +Requires-Dist: furo ; extra == 'dev' +Requires-Dist: sphinx ; extra == 'dev' +Requires-Dist: pre-commit ; extra == 'dev' +Provides-Extra: docs +Requires-Dist: furo ; extra == 'docs' +Requires-Dist: sphinx ; extra == 'docs' +Requires-Dist: zope.interface ; extra == 'docs' +Provides-Extra: tests +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests' +Requires-Dist: hypothesis ; extra == 'tests' +Requires-Dist: pympler ; extra == 'tests' +Requires-Dist: pytest (>=4.3.0) ; extra == 'tests' +Requires-Dist: six ; extra == 'tests' +Requires-Dist: zope.interface ; extra == 'tests' +Provides-Extra: tests_no_zope +Requires-Dist: coverage[toml] (>=5.0.2) ; extra == 'tests_no_zope' +Requires-Dist: hypothesis ; extra == 'tests_no_zope' +Requires-Dist: pympler ; extra == 'tests_no_zope' +Requires-Dist: pytest (>=4.3.0) ; extra == 'tests_no_zope' +Requires-Dist: six ; extra == 'tests_no_zope' + +.. image:: https://www.attrs.org/en/latest/_static/attrs_logo.png + :alt: attrs Logo + +====================================== +``attrs``: Classes Without Boilerplate +====================================== + +.. image:: https://readthedocs.org/projects/attrs/badge/?version=stable + :target: https://www.attrs.org/en/stable/?badge=stable + :alt: Documentation Status + +.. image:: https://github.com/python-attrs/attrs/workflows/CI/badge.svg?branch=master + :target: https://github.com/python-attrs/attrs/actions?workflow=CI + :alt: CI Status + +.. image:: https://codecov.io/github/python-attrs/attrs/branch/master/graph/badge.svg + :target: https://codecov.io/github/python-attrs/attrs + :alt: Test Coverage + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + :alt: Code style: black + +.. teaser-begin + +``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). + +Its main goal is to help you to write **concise** and **correct** software without slowing down your code. + +.. teaser-end + +For that, it gives you a class decorator and a way to declaratively define the attributes on that class: + +.. -code-begin- + +.. code-block:: pycon + + >>> import attr + + >>> @attr.s + ... class SomeClass(object): + ... a_number = attr.ib(default=42) + ... list_of_numbers = attr.ib(factory=list) + ... + ... def hard_math(self, another_number): + ... return self.a_number + sum(self.list_of_numbers) * another_number + + + >>> sc = SomeClass(1, [1, 2, 3]) + >>> sc + SomeClass(a_number=1, list_of_numbers=[1, 2, 3]) + + >>> sc.hard_math(3) + 19 + >>> sc == SomeClass(1, [1, 2, 3]) + True + >>> sc != SomeClass(2, [3, 2, 1]) + True + + >>> attr.asdict(sc) + {'a_number': 1, 'list_of_numbers': [1, 2, 3]} + + >>> SomeClass() + SomeClass(a_number=42, list_of_numbers=[]) + + >>> C = attr.make_class("C", ["a", "b"]) + >>> C("foo", "bar") + C(a='foo', b='bar') + + +After *declaring* your attributes ``attrs`` gives you: + +- a concise and explicit overview of the class's attributes, +- a nice human-readable ``__repr__``, +- a complete set of comparison methods (equality and ordering), +- an initializer, +- and much more, + +*without* writing dull boilerplate code again and again and *without* runtime performance penalties. + +On Python 3.6 and later, you can often even drop the calls to ``attr.ib()`` by using `type annotations `_. + +This gives you the power to use actual classes with actual types in your code instead of confusing ``tuple``\ s or `confusingly behaving `_ ``namedtuple``\ s. +Which in turn encourages you to write *small classes* that do `one thing well `_. +Never again violate the `single responsibility principle `_ just because implementing ``__init__`` et al is a painful drag. + + +.. -getting-help- + +Getting Help +============ + +Please use the ``python-attrs`` tag on `StackOverflow `_ to get help. + +Answering questions of your fellow developers is also a great way to help the project! + + +.. -project-information- + +Project Information +=================== + +``attrs`` is released under the `MIT `_ license, +its documentation lives at `Read the Docs `_, +the code on `GitHub `_, +and the latest release on `PyPI `_. +It’s rigorously tested on Python 2.7, 3.5+, and PyPy. + +We collect information on **third-party extensions** in our `wiki `_. +Feel free to browse and add your own! + +If you'd like to contribute to ``attrs`` you're most welcome and we've written `a little guide `_ to get you started! + + +``attrs`` for Enterprise +------------------------ + +Available as part of the Tidelift Subscription. + +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. +Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. +`Learn more. `_ + + +Release Information +=================== + +20.3.0 (2020-11-05) +------------------- + +Backward-incompatible Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- ``attr.define()``, ``attr.frozen()``, ``attr.mutable()``, and ``attr.field()`` remain **provisional**. + + This release does **not** change change anything about them and they are already used widely in production though. + + If you wish to use them together with mypy, you can simply drop `this plugin `_ into your project. + + Feel free to provide feedback to them in the linked issue #668. + + We will release the ``attrs`` namespace once we have the feeling that the APIs have properly settled. + `#668 `_ + + +Changes +^^^^^^^ + +- ``attr.s()`` now has a *field_transformer* hook that is called for all ``Attribute``\ s and returns a (modified or updated) list of ``Attribute`` instances. + ``attr.asdict()`` has a *value_serializer* hook that can change the way values are converted. + Both hooks are meant to help with data (de-)serialization workflows. + `#653 `_ +- ``kw_only=True`` now works on Python 2. + `#700 `_ +- ``raise from`` now works on frozen classes on PyPy. + `#703 `_, + `#712 `_ +- ``attr.asdict()`` and ``attr.astuple()`` now treat ``frozenset``\ s like ``set``\ s with regards to the *retain_collection_types* argument. + `#704 `_ +- The type stubs for ``attr.s()`` and ``attr.make_class()`` are not missing the *collect_by_mro* argument anymore. + `#711 `_ + +`Full changelog `_. + +Credits +======= + +``attrs`` is written and maintained by `Hynek Schlawack `_. + +The development is kindly supported by `Variomedia AG `_. + +A full list of contributors can be found in `GitHub's overview `_. + +It’s the spiritual successor of `characteristic `_ and aspires to fix some of it clunkiness and unfortunate decisions. +Both were inspired by Twisted’s `FancyEqMixin `_ but both are implemented using class decorators because `subclassing is bad for you `_, m’kay? + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/RECORD new file mode 100644 index 00000000..2a564f97 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/RECORD @@ -0,0 +1,39 @@ +attr/__init__.py,sha256=70KmZOgz2sUvtRTC_IuXEeN2ttOyBWHn4XA59aqGXPs,1568 +attr/__init__.pyi,sha256=ca_4sg7z0e_EL7ehy-flXVGAju5PBX2hVo51dUmPMi0,12986 +attr/__pycache__/__init__.cpython-38.pyc,, +attr/__pycache__/_compat.cpython-38.pyc,, +attr/__pycache__/_config.cpython-38.pyc,, +attr/__pycache__/_funcs.cpython-38.pyc,, +attr/__pycache__/_make.cpython-38.pyc,, +attr/__pycache__/_next_gen.cpython-38.pyc,, +attr/__pycache__/_version_info.cpython-38.pyc,, +attr/__pycache__/converters.cpython-38.pyc,, +attr/__pycache__/exceptions.cpython-38.pyc,, +attr/__pycache__/filters.cpython-38.pyc,, +attr/__pycache__/setters.cpython-38.pyc,, +attr/__pycache__/validators.cpython-38.pyc,, +attr/_compat.py,sha256=rZhpP09xbyWSzMv796XQbryIr21oReJFvA70G3lrHxg,7308 +attr/_config.py,sha256=_KvW0mQdH2PYjHc0YfIUaV_o2pVfM7ziMEYTxwmEhOA,514 +attr/_funcs.py,sha256=PvFQlflEswO_qIR2sUr4a4x8ggQpEoDKe3YKM2rLJu4,13081 +attr/_make.py,sha256=61XB4-SHQpFbWbStGWotTTbzVT2m49DUovRgnxpMqmU,88313 +attr/_next_gen.py,sha256=x6TU2rVOXmFmrNNvkfshJsxyRbAAK0wDI4SJV2OI97c,4138 +attr/_version_info.py,sha256=azMi1lNelb3cJvvYUMXsXVbUANkRzbD5IEiaXVpeVr4,2162 +attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209 +attr/converters.py,sha256=CaK6iLtEMmemrqU8LQ1D2nWtbo9dGPAv4UaZ0rFzhOA,2214 +attr/converters.pyi,sha256=fVGSfawF3NMy2EBApkC7dAwMuujWCHnGEnnAgsbkVpg,380 +attr/exceptions.py,sha256=gmlET97ikqdQVvy7Ff9p7zVvqc2SsNtTd-r30pva1GE,1950 +attr/exceptions.pyi,sha256=zZq8bCUnKAy9mDtBEw42ZhPhAUIHoTKedDQInJD883M,539 +attr/filters.py,sha256=weDxwATsa69T_0bPVjiM1fGsciAMQmwhY5G8Jm5BxuI,1098 +attr/filters.pyi,sha256=xDpmKQlFdssgxGa5tsl1ADh_3zwAwAT4vUhd8h-8-Tk,214 +attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +attr/setters.py,sha256=0ElzHwdVK3dsYcQi2CXkFvhx8fNxUI5OVhw8SWeaKmA,1434 +attr/setters.pyi,sha256=SYr6adhx4f0dSkmmBICg6eK8WMev5jT-KJQJTdul078,567 +attr/validators.py,sha256=6DBx1jt4oZxx1ppvx6JWqm9-UAsYpXC4HTwxJilCeRg,11497 +attr/validators.pyi,sha256=vZgsJqUwrJevh4v_Hd7_RSXqDrBctE6-3AEZ7uYKodo,1868 +attrs-20.3.0.dist-info/AUTHORS.rst,sha256=wsqCNbGz_mklcJrt54APIZHZpoTIJLkXqEhhn4Nd8hc,752 +attrs-20.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +attrs-20.3.0.dist-info/LICENSE,sha256=v2WaKLSSQGAvVrvfSQy-LsUJsVuY-Z17GaUsdA4yeGM,1082 +attrs-20.3.0.dist-info/METADATA,sha256=2XTmALrRRbIZj9J8pJgpKYnyATu_NAL8vfUnqRFpE5w,10220 +attrs-20.3.0.dist-info/RECORD,, +attrs-20.3.0.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 +attrs-20.3.0.dist-info/top_level.txt,sha256=tlRYMddkRlKPqJ96wP2_j9uEsmcNHgD2SbuWd4CzGVU,5 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/WHEEL new file mode 100644 index 00000000..6d38aa06 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.35.1) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/top_level.txt new file mode 100644 index 00000000..66a062d8 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/attrs-20.3.0.dist-info/top_level.txt @@ -0,0 +1 @@ +attr diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/__init__.py new file mode 100644 index 00000000..a1bbbbe3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/__init__.py @@ -0,0 +1,11 @@ +"""CacheControl import Interface. + +Make it easy to import from cachecontrol without long namespaces. +""" +__author__ = "Eric Larson" +__email__ = "eric@ionrock.org" +__version__ = "0.12.6" + +from .wrapper import CacheControl +from .adapter import CacheControlAdapter +from .controller import CacheController diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/_cmd.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/_cmd.py new file mode 100644 index 00000000..ee8d60d1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/_cmd.py @@ -0,0 +1,57 @@ +import logging + +import requests + +from cachecontrol.adapter import CacheControlAdapter +from cachecontrol.cache import DictCache +from cachecontrol.controller import logger + +from argparse import ArgumentParser + + +def setup_logging(): + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + logger.addHandler(handler) + + +def get_session(): + adapter = CacheControlAdapter( + DictCache(), cache_etags=True, serializer=None, heuristic=None + ) + sess = requests.Session() + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + sess.cache_controller = adapter.controller + return sess + + +def get_args(): + parser = ArgumentParser() + parser.add_argument("url", help="The URL to try and cache") + return parser.parse_args() + + +def main(args=None): + args = get_args() + sess = get_session() + + # Make a request to get a response + resp = sess.get(args.url) + + # Turn on logging + setup_logging() + + # try setting the cache + sess.cache_controller.cache_response(resp.request, resp.raw) + + # Now try to get it + if sess.cache_controller.cached_request(resp.request): + print("Cached!") + else: + print("Not cached :(") + + +if __name__ == "__main__": + main() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/adapter.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/adapter.py new file mode 100644 index 00000000..de50006a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/adapter.py @@ -0,0 +1,133 @@ +import types +import functools +import zlib + +from requests.adapters import HTTPAdapter + +from .controller import CacheController +from .cache import DictCache +from .filewrapper import CallbackFileWrapper + + +class CacheControlAdapter(HTTPAdapter): + invalidating_methods = {"PUT", "DELETE"} + + def __init__( + self, + cache=None, + cache_etags=True, + controller_class=None, + serializer=None, + heuristic=None, + cacheable_methods=None, + *args, + **kw + ): + super(CacheControlAdapter, self).__init__(*args, **kw) + self.cache = DictCache() if cache is None else cache + self.heuristic = heuristic + self.cacheable_methods = cacheable_methods or ("GET",) + + controller_factory = controller_class or CacheController + self.controller = controller_factory( + self.cache, cache_etags=cache_etags, serializer=serializer + ) + + def send(self, request, cacheable_methods=None, **kw): + """ + Send a request. Use the request information to see if it + exists in the cache and cache the response if we need to and can. + """ + cacheable = cacheable_methods or self.cacheable_methods + if request.method in cacheable: + try: + cached_response = self.controller.cached_request(request) + except zlib.error: + cached_response = None + if cached_response: + return self.build_response(request, cached_response, from_cache=True) + + # check for etags and add headers if appropriate + request.headers.update(self.controller.conditional_headers(request)) + + resp = super(CacheControlAdapter, self).send(request, **kw) + + return resp + + def build_response( + self, request, response, from_cache=False, cacheable_methods=None + ): + """ + Build a response by making a request or using the cache. + + This will end up calling send and returning a potentially + cached response + """ + cacheable = cacheable_methods or self.cacheable_methods + if not from_cache and request.method in cacheable: + # Check for any heuristics that might update headers + # before trying to cache. + if self.heuristic: + response = self.heuristic.apply(response) + + # apply any expiration heuristics + if response.status == 304: + # We must have sent an ETag request. This could mean + # that we've been expired already or that we simply + # have an etag. In either case, we want to try and + # update the cache if that is the case. + cached_response = self.controller.update_cached_response( + request, response + ) + + if cached_response is not response: + from_cache = True + + # We are done with the server response, read a + # possible response body (compliant servers will + # not return one, but we cannot be 100% sure) and + # release the connection back to the pool. + response.read(decode_content=False) + response.release_conn() + + response = cached_response + + # We always cache the 301 responses + elif response.status == 301: + self.controller.cache_response(request, response) + else: + # Wrap the response file with a wrapper that will cache the + # response when the stream has been consumed. + response._fp = CallbackFileWrapper( + response._fp, + functools.partial( + self.controller.cache_response, request, response + ), + ) + if response.chunked: + super_update_chunk_length = response._update_chunk_length + + def _update_chunk_length(self): + super_update_chunk_length() + if self.chunk_left == 0: + self._fp._close() + + response._update_chunk_length = types.MethodType( + _update_chunk_length, response + ) + + resp = super(CacheControlAdapter, self).build_response(request, response) + + # See if we should invalidate the cache. + if request.method in self.invalidating_methods and resp.ok: + cache_url = self.controller.cache_url(request.url) + self.cache.delete(cache_url) + + # Give the request a from_cache attr to let people use it + resp.from_cache = from_cache + + return resp + + def close(self): + self.cache.close() + super(CacheControlAdapter, self).close() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/cache.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/cache.py new file mode 100644 index 00000000..94e07732 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/cache.py @@ -0,0 +1,39 @@ +""" +The cache object API for implementing caches. The default is a thread +safe in-memory dictionary. +""" +from threading import Lock + + +class BaseCache(object): + + def get(self, key): + raise NotImplementedError() + + def set(self, key, value): + raise NotImplementedError() + + def delete(self, key): + raise NotImplementedError() + + def close(self): + pass + + +class DictCache(BaseCache): + + def __init__(self, init_dict=None): + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key): + return self.data.get(key, None) + + def set(self, key, value): + with self.lock: + self.data.update({key: value}) + + def delete(self, key): + with self.lock: + if key in self.data: + self.data.pop(key) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/__init__.py new file mode 100644 index 00000000..0e1658fa --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/__init__.py @@ -0,0 +1,2 @@ +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/file_cache.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/file_cache.py new file mode 100644 index 00000000..607b9452 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/file_cache.py @@ -0,0 +1,146 @@ +import hashlib +import os +from textwrap import dedent + +from ..cache import BaseCache +from ..controller import CacheController + +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = (IOError, OSError) + + +def _secure_open_write(filename, fmode): + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except (IOError, OSError): + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise + + +class FileCache(BaseCache): + + def __init__( + self, + directory, + forever=False, + filemode=0o0600, + dirmode=0o0700, + use_dir_lock=None, + lock_class=None, + ): + + if use_dir_lock is not None and lock_class is not None: + raise ValueError("Cannot use use_dir_lock and lock_class together") + + try: + from lockfile import LockFile + from lockfile.mkdirlockfile import MkdirLockFile + except ImportError: + notice = dedent( + """ + NOTE: In order to use the FileCache you must have + lockfile installed. You can install it via pip: + pip install lockfile + """ + ) + raise ImportError(notice) + + else: + if use_dir_lock: + lock_class = MkdirLockFile + + elif lock_class is None: + lock_class = LockFile + + self.directory = directory + self.forever = forever + self.filemode = filemode + self.dirmode = dirmode + self.lock_class = lock_class + + @staticmethod + def encode(x): + return hashlib.sha224(x.encode()).hexdigest() + + def _fn(self, name): + # NOTE: This method should not change as some may depend on it. + # See: https://github.com/ionrock/cachecontrol/issues/63 + hashed = self.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key): + name = self._fn(key) + try: + with open(name, "rb") as fh: + return fh.read() + + except FileNotFoundError: + return None + + def set(self, key, value): + name = self._fn(key) + + # Make sure the directory exists + try: + os.makedirs(os.path.dirname(name), self.dirmode) + except (IOError, OSError): + pass + + with self.lock_class(name) as lock: + # Write our actual file + with _secure_open_write(lock.path, self.filemode) as fh: + fh.write(value) + + def delete(self, key): + name = self._fn(key) + if not self.forever: + try: + os.remove(name) + except FileNotFoundError: + pass + + +def url_to_file_path(url, filecache): + """Return the file cache path based on the URL. + + This does not ensure the file exists! + """ + key = CacheController.cache_url(url) + return filecache._fn(key) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/redis_cache.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/redis_cache.py new file mode 100644 index 00000000..16da0aed --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/caches/redis_cache.py @@ -0,0 +1,33 @@ +from __future__ import division + +from datetime import datetime +from cachecontrol.cache import BaseCache + + +class RedisCache(BaseCache): + + def __init__(self, conn): + self.conn = conn + + def get(self, key): + return self.conn.get(key) + + def set(self, key, value, expires=None): + if not expires: + self.conn.set(key, value) + else: + expires = expires - datetime.utcnow() + self.conn.setex(key, int(expires.total_seconds()), value) + + def delete(self, key): + self.conn.delete(key) + + def clear(self): + """Helper for clearing all the keys in a database. Use with + caution!""" + for key in self.conn.keys(): + self.conn.delete(key) + + def close(self): + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/compat.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/compat.py new file mode 100644 index 00000000..143c8ab0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/compat.py @@ -0,0 +1,29 @@ +try: + from urllib.parse import urljoin +except ImportError: + from urlparse import urljoin + + +try: + import cPickle as pickle +except ImportError: + import pickle + + +# Handle the case where the requests module has been patched to not have +# urllib3 bundled as part of its source. +try: + from requests.packages.urllib3.response import HTTPResponse +except ImportError: + from urllib3.response import HTTPResponse + +try: + from requests.packages.urllib3.util import is_fp_closed +except ImportError: + from urllib3.util import is_fp_closed + +# Replicate some six behaviour +try: + text_type = unicode +except NameError: + text_type = str diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/controller.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/controller.py new file mode 100644 index 00000000..c5c4a508 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/controller.py @@ -0,0 +1,376 @@ +""" +The httplib2 algorithms ported for use with requests. +""" +import logging +import re +import calendar +import time +from email.utils import parsedate_tz + +from requests.structures import CaseInsensitiveDict + +from .cache import DictCache +from .serialize import Serializer + + +logger = logging.getLogger(__name__) + +URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") + + +def parse_uri(uri): + """Parses a URI using the regex given in Appendix B of RFC 3986. + + (scheme, authority, path, query, fragment) = parse_uri(uri) + """ + groups = URI.match(uri).groups() + return (groups[1], groups[3], groups[4], groups[6], groups[8]) + + +class CacheController(object): + """An interface to see if request should cached or not. + """ + + def __init__( + self, cache=None, cache_etags=True, serializer=None, status_codes=None + ): + self.cache = DictCache() if cache is None else cache + self.cache_etags = cache_etags + self.serializer = serializer or Serializer() + self.cacheable_status_codes = status_codes or (200, 203, 300, 301) + + @classmethod + def _urlnorm(cls, uri): + """Normalize the URL to create a safe key for the cache""" + (scheme, authority, path, query, fragment) = parse_uri(uri) + if not scheme or not authority: + raise Exception("Only absolute URIs are allowed. uri = %s" % uri) + + scheme = scheme.lower() + authority = authority.lower() + + if not path: + path = "/" + + # Could do syntax based normalization of the URI before + # computing the digest. See Section 6.2.2 of Std 66. + request_uri = query and "?".join([path, query]) or path + defrag_uri = scheme + "://" + authority + request_uri + + return defrag_uri + + @classmethod + def cache_url(cls, uri): + return cls._urlnorm(uri) + + def parse_cache_control(self, headers): + known_directives = { + # https://tools.ietf.org/html/rfc7234#section-5.2 + "max-age": (int, True), + "max-stale": (int, False), + "min-fresh": (int, True), + "no-cache": (None, False), + "no-store": (None, False), + "no-transform": (None, False), + "only-if-cached": (None, False), + "must-revalidate": (None, False), + "public": (None, False), + "private": (None, False), + "proxy-revalidate": (None, False), + "s-maxage": (int, True), + } + + cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) + + retval = {} + + for cc_directive in cc_headers.split(","): + if not cc_directive.strip(): + continue + + parts = cc_directive.split("=", 1) + directive = parts[0].strip() + + try: + typ, required = known_directives[directive] + except KeyError: + logger.debug("Ignoring unknown cache-control directive: %s", directive) + continue + + if not typ or not required: + retval[directive] = None + if typ: + try: + retval[directive] = typ(parts[1].strip()) + except IndexError: + if required: + logger.debug( + "Missing value for cache-control " "directive: %s", + directive, + ) + except ValueError: + logger.debug( + "Invalid value for cache-control directive " "%s, must be %s", + directive, + typ.__name__, + ) + + return retval + + def cached_request(self, request): + """ + Return a cached response if it exists in the cache, otherwise + return False. + """ + cache_url = self.cache_url(request.url) + logger.debug('Looking up "%s" in the cache', cache_url) + cc = self.parse_cache_control(request.headers) + + # Bail out if the request insists on fresh data + if "no-cache" in cc: + logger.debug('Request header has "no-cache", cache bypassed') + return False + + if "max-age" in cc and cc["max-age"] == 0: + logger.debug('Request header has "max_age" as 0, cache bypassed') + return False + + # Request allows serving from the cache, let's see if we find something + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return False + + # Check whether it can be deserialized + resp = self.serializer.loads(request, cache_data) + if not resp: + logger.warning("Cache entry deserialization failed, entry ignored") + return False + + # If we have a cached 301, return it immediately. We don't + # need to test our response for other headers b/c it is + # intrinsically "cacheable" as it is Permanent. + # See: + # https://tools.ietf.org/html/rfc7231#section-6.4.2 + # + # Client can try to refresh the value by repeating the request + # with cache busting headers as usual (ie no-cache). + if resp.status == 301: + msg = ( + 'Returning cached "301 Moved Permanently" response ' + "(ignoring date and etag information)" + ) + logger.debug(msg) + return resp + + headers = CaseInsensitiveDict(resp.headers) + if not headers or "date" not in headers: + if "etag" not in headers: + # Without date or etag, the cached response can never be used + # and should be deleted. + logger.debug("Purging cached response: no date or etag") + self.cache.delete(cache_url) + logger.debug("Ignoring cached response: no date") + return False + + now = time.time() + date = calendar.timegm(parsedate_tz(headers["date"])) + current_age = max(0, now - date) + logger.debug("Current age based on date: %i", current_age) + + # TODO: There is an assumption that the result will be a + # urllib3 response object. This may not be best since we + # could probably avoid instantiating or constructing the + # response until we know we need it. + resp_cc = self.parse_cache_control(headers) + + # determine freshness + freshness_lifetime = 0 + + # Check the max-age pragma in the cache control header + if "max-age" in resp_cc: + freshness_lifetime = resp_cc["max-age"] + logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) + + # If there isn't a max-age, check for an expires header + elif "expires" in headers: + expires = parsedate_tz(headers["expires"]) + if expires is not None: + expire_time = calendar.timegm(expires) - date + freshness_lifetime = max(0, expire_time) + logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) + + # Determine if we are setting freshness limit in the + # request. Note, this overrides what was in the response. + if "max-age" in cc: + freshness_lifetime = cc["max-age"] + logger.debug( + "Freshness lifetime from request max-age: %i", freshness_lifetime + ) + + if "min-fresh" in cc: + min_fresh = cc["min-fresh"] + # adjust our current age by our min fresh + current_age += min_fresh + logger.debug("Adjusted current age from min-fresh: %i", current_age) + + # Return entry if it is fresh enough + if freshness_lifetime > current_age: + logger.debug('The response is "fresh", returning cached response') + logger.debug("%i > %i", freshness_lifetime, current_age) + return resp + + # we're not fresh. If we don't have an Etag, clear it out + if "etag" not in headers: + logger.debug('The cached response is "stale" with no etag, purging') + self.cache.delete(cache_url) + + # return the original handler + return False + + def conditional_headers(self, request): + cache_url = self.cache_url(request.url) + resp = self.serializer.loads(request, self.cache.get(cache_url)) + new_headers = {} + + if resp: + headers = CaseInsensitiveDict(resp.headers) + + if "etag" in headers: + new_headers["If-None-Match"] = headers["ETag"] + + if "last-modified" in headers: + new_headers["If-Modified-Since"] = headers["Last-Modified"] + + return new_headers + + def cache_response(self, request, response, body=None, status_codes=None): + """ + Algorithm for caching requests. + + This assumes a requests Response object. + """ + # From httplib2: Don't cache 206's since we aren't going to + # handle byte range requests + cacheable_status_codes = status_codes or self.cacheable_status_codes + if response.status not in cacheable_status_codes: + logger.debug( + "Status code %s not in %s", response.status, cacheable_status_codes + ) + return + + response_headers = CaseInsensitiveDict(response.headers) + + # If we've been given a body, our response has a Content-Length, that + # Content-Length is valid then we can check to see if the body we've + # been given matches the expected size, and if it doesn't we'll just + # skip trying to cache it. + if ( + body is not None + and "content-length" in response_headers + and response_headers["content-length"].isdigit() + and int(response_headers["content-length"]) != len(body) + ): + return + + cc_req = self.parse_cache_control(request.headers) + cc = self.parse_cache_control(response_headers) + + cache_url = self.cache_url(request.url) + logger.debug('Updating cache with response from "%s"', cache_url) + + # Delete it from the cache if we happen to have it stored there + no_store = False + if "no-store" in cc: + no_store = True + logger.debug('Response header has "no-store"') + if "no-store" in cc_req: + no_store = True + logger.debug('Request header has "no-store"') + if no_store and self.cache.get(cache_url): + logger.debug('Purging existing cache entry to honor "no-store"') + self.cache.delete(cache_url) + if no_store: + return + + # https://tools.ietf.org/html/rfc7234#section-4.1: + # A Vary header field-value of "*" always fails to match. + # Storing such a response leads to a deserialization warning + # during cache lookup and is not allowed to ever be served, + # so storing it can be avoided. + if "*" in response_headers.get("vary", ""): + logger.debug('Response header has "Vary: *"') + return + + # If we've been given an etag, then keep the response + if self.cache_etags and "etag" in response_headers: + logger.debug("Caching due to etag") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # Add to the cache any 301s. We do this before looking that + # the Date headers. + elif response.status == 301: + logger.debug("Caching permanant redirect") + self.cache.set(cache_url, self.serializer.dumps(request, response)) + + # Add to the cache if the response headers demand it. If there + # is no date header then we can't do anything about expiring + # the cache. + elif "date" in response_headers: + # cache when there is a max-age > 0 + if "max-age" in cc and cc["max-age"] > 0: + logger.debug("Caching b/c date exists and max-age > 0") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + # If the request can expire, it means we should cache it + # in the meantime. + elif "expires" in response_headers: + if response_headers["expires"]: + logger.debug("Caching b/c of expires header") + self.cache.set( + cache_url, self.serializer.dumps(request, response, body=body) + ) + + def update_cached_response(self, request, response): + """On a 304 we will get a new set of headers that we want to + update our cached value with, assuming we have one. + + This should only ever be called when we've sent an ETag and + gotten a 304 as the response. + """ + cache_url = self.cache_url(request.url) + + cached_response = self.serializer.loads(request, self.cache.get(cache_url)) + + if not cached_response: + # we didn't have a cached response + return response + + # Lets update our headers with the headers from the new request: + # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 + # + # The server isn't supposed to send headers that would make + # the cached body invalid. But... just in case, we'll be sure + # to strip out ones we know that might be problmatic due to + # typical assumptions. + excluded_headers = ["content-length"] + + cached_response.headers.update( + dict( + (k, v) + for k, v in response.headers.items() + if k.lower() not in excluded_headers + ) + ) + + # we want a 200 b/c we have content via the cache + cached_response.status = 200 + + # update our cache + self.cache.set(cache_url, self.serializer.dumps(request, cached_response)) + + return cached_response diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/filewrapper.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/filewrapper.py new file mode 100644 index 00000000..30ed4c5a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/filewrapper.py @@ -0,0 +1,80 @@ +from io import BytesIO + + +class CallbackFileWrapper(object): + """ + Small wrapper around a fp object which will tee everything read into a + buffer, and when that file is closed it will execute a callback with the + contents of that buffer. + + All attributes are proxied to the underlying file object. + + This class uses members with a double underscore (__) leading prefix so as + not to accidentally shadow an attribute. + """ + + def __init__(self, fp, callback): + self.__buf = BytesIO() + self.__fp = fp + self.__callback = callback + + def __getattr__(self, name): + # The vaguaries of garbage collection means that self.__fp is + # not always set. By using __getattribute__ and the private + # name[0] allows looking up the attribute value and raising an + # AttributeError when it doesn't exist. This stop thigns from + # infinitely recursing calls to getattr in the case where + # self.__fp hasn't been set. + # + # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers + fp = self.__getattribute__("_CallbackFileWrapper__fp") + return getattr(fp, name) + + def __is_fp_closed(self): + try: + return self.__fp.fp is None + + except AttributeError: + pass + + try: + return self.__fp.closed + + except AttributeError: + pass + + # We just don't cache it then. + # TODO: Add some logging here... + return False + + def _close(self): + if self.__callback: + self.__callback(self.__buf.getvalue()) + + # We assign this to None here, because otherwise we can get into + # really tricky problems where the CPython interpreter dead locks + # because the callback is holding a reference to something which + # has a __del__ method. Setting this to None breaks the cycle + # and allows the garbage collector to do it's thing normally. + self.__callback = None + + def read(self, amt=None): + data = self.__fp.read(amt) + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data + + def _safe_read(self, amt): + data = self.__fp._safe_read(amt) + if amt == 2 and data == b"\r\n": + # urllib executes this read to toss the CRLF at the end + # of the chunk. + return data + + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/heuristics.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/heuristics.py new file mode 100644 index 00000000..6c0e9790 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/heuristics.py @@ -0,0 +1,135 @@ +import calendar +import time + +from email.utils import formatdate, parsedate, parsedate_tz + +from datetime import datetime, timedelta + +TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" + + +def expire_after(delta, date=None): + date = date or datetime.utcnow() + return date + delta + + +def datetime_to_header(dt): + return formatdate(calendar.timegm(dt.timetuple())) + + +class BaseHeuristic(object): + + def warning(self, response): + """ + Return a valid 1xx warning header value describing the cache + adjustments. + + The response is provided too allow warnings like 113 + http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need + to explicitly say response is over 24 hours old. + """ + return '110 - "Response is Stale"' + + def update_headers(self, response): + """Update the response headers with any new headers. + + NOTE: This SHOULD always include some Warning header to + signify that the response was cached by the client, not + by way of the provided headers. + """ + return {} + + def apply(self, response): + updated_headers = self.update_headers(response) + + if updated_headers: + response.headers.update(updated_headers) + warning_header_value = self.warning(response) + if warning_header_value is not None: + response.headers.update({"Warning": warning_header_value}) + + return response + + +class OneDayCache(BaseHeuristic): + """ + Cache the response by providing an expires 1 day in the + future. + """ + + def update_headers(self, response): + headers = {} + + if "expires" not in response.headers: + date = parsedate(response.headers["date"]) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) + headers["expires"] = datetime_to_header(expires) + headers["cache-control"] = "public" + return headers + + +class ExpiresAfter(BaseHeuristic): + """ + Cache **all** requests for a defined time period. + """ + + def __init__(self, **kw): + self.delta = timedelta(**kw) + + def update_headers(self, response): + expires = expire_after(self.delta) + return {"expires": datetime_to_header(expires), "cache-control": "public"} + + def warning(self, response): + tmpl = "110 - Automatically cached for %s. Response might be stale" + return tmpl % self.delta + + +class LastModified(BaseHeuristic): + """ + If there is no Expires header already, fall back on Last-Modified + using the heuristic from + http://tools.ietf.org/html/rfc7234#section-4.2.2 + to calculate a reasonable value. + + Firefox also does something like this per + https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ + http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 + Unlike mozilla we limit this to 24-hr. + """ + cacheable_by_default_statuses = { + 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 + } + + def update_headers(self, resp): + headers = resp.headers + + if "expires" in headers: + return {} + + if "cache-control" in headers and headers["cache-control"] != "public": + return {} + + if resp.status not in self.cacheable_by_default_statuses: + return {} + + if "date" not in headers or "last-modified" not in headers: + return {} + + date = calendar.timegm(parsedate_tz(headers["date"])) + last_modified = parsedate(headers["last-modified"]) + if date is None or last_modified is None: + return {} + + now = time.time() + current_age = max(0, now - date) + delta = date - calendar.timegm(last_modified) + freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) + if freshness_lifetime <= current_age: + return {} + + expires = date + freshness_lifetime + return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} + + def warning(self, resp): + return None diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/serialize.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/serialize.py new file mode 100644 index 00000000..572cf0e6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/serialize.py @@ -0,0 +1,188 @@ +import base64 +import io +import json +import zlib + +import msgpack +from requests.structures import CaseInsensitiveDict + +from .compat import HTTPResponse, pickle, text_type + + +def _b64_decode_bytes(b): + return base64.b64decode(b.encode("ascii")) + + +def _b64_decode_str(s): + return _b64_decode_bytes(s).decode("utf8") + + +class Serializer(object): + + def dumps(self, request, response, body=None): + response_headers = CaseInsensitiveDict(response.headers) + + if body is None: + body = response.read(decode_content=False) + + # NOTE: 99% sure this is dead code. I'm only leaving it + # here b/c I don't have a test yet to prove + # it. Basically, before using + # `cachecontrol.filewrapper.CallbackFileWrapper`, + # this made an effort to reset the file handle. The + # `CallbackFileWrapper` short circuits this code by + # setting the body as the content is consumed, the + # result being a `body` argument is *always* passed + # into cache_response, and in turn, + # `Serializer.dump`. + response._fp = io.BytesIO(body) + + # NOTE: This is all a bit weird, but it's really important that on + # Python 2.x these objects are unicode and not str, even when + # they contain only ascii. The problem here is that msgpack + # understands the difference between unicode and bytes and we + # have it set to differentiate between them, however Python 2 + # doesn't know the difference. Forcing these to unicode will be + # enough to have msgpack know the difference. + data = { + u"response": { + u"body": body, + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() + ), + u"status": response.status, + u"version": response.version, + u"reason": text_type(response.reason), + u"strict": response.strict, + u"decode_content": response.decode_content, + } + } + + # Construct our vary headers + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u"vary"].split(",") + for header in varied_headers: + header = text_type(header).strip() + header_value = request.headers.get(header, None) + if header_value is not None: + header_value = text_type(header_value) + data[u"vary"][header] = header_value + + return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) + + def loads(self, request, data): + # Short circuit if we've been given an empty set of data + if not data: + return + + # Determine what version of the serializer the data was serialized + # with + try: + ver, data = data.split(b",", 1) + except ValueError: + ver = b"cc=0" + + # Make sure that our "ver" is actually a version and isn't a false + # positive from a , being in the data stream. + if ver[:3] != b"cc=": + data = ver + data + ver = b"cc=0" + + # Get the version number out of the cc=N + ver = ver.split(b"=", 1)[-1].decode("ascii") + + # Dispatch to the actual load method for the given version + try: + return getattr(self, "_loads_v{}".format(ver))(request, data) + + except AttributeError: + # This is a version we don't have a loads function for, so we'll + # just treat it as a miss and return None + return + + def prepare_response(self, request, cached): + """Verify our vary headers match and construct a real urllib3 + HTTPResponse object. + """ + # Special case the '*' Vary value as it means we cannot actually + # determine if the cached response is suitable for this request. + # This case is also handled in the controller code when creating + # a cache entry, but is left here for backwards compatibility. + if "*" in cached.get("vary", {}): + return + + # Ensure that the Vary headers for the cached response match our + # request + for header, value in cached.get("vary", {}).items(): + if request.headers.get(header, None) != value: + return + + body_raw = cached["response"].pop("body") + + headers = CaseInsensitiveDict(data=cached["response"]["headers"]) + if headers.get("transfer-encoding", "") == "chunked": + headers.pop("transfer-encoding") + + cached["response"]["headers"] = headers + + try: + body = io.BytesIO(body_raw) + except TypeError: + # This can happen if cachecontrol serialized to v1 format (pickle) + # using Python 2. A Python 2 str(byte string) will be unpickled as + # a Python 3 str (unicode string), which will cause the above to + # fail with: + # + # TypeError: 'str' does not support the buffer interface + body = io.BytesIO(body_raw.encode("utf8")) + + return HTTPResponse(body=body, preload_content=False, **cached["response"]) + + def _loads_v0(self, request, data): + # The original legacy cache data. This doesn't contain enough + # information to construct everything we need, so we'll treat this as + # a miss. + return + + def _loads_v1(self, request, data): + try: + cached = pickle.loads(data) + except ValueError: + return + + return self.prepare_response(request, cached) + + def _loads_v2(self, request, data): + try: + cached = json.loads(zlib.decompress(data).decode("utf8")) + except (ValueError, zlib.error): + return + + # We need to decode the items that we've base64 encoded + cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) + cached["response"]["headers"] = dict( + (_b64_decode_str(k), _b64_decode_str(v)) + for k, v in cached["response"]["headers"].items() + ) + cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) + cached["vary"] = dict( + (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) + for k, v in cached["vary"].items() + ) + + return self.prepare_response(request, cached) + + def _loads_v3(self, request, data): + # Due to Python 2 encoding issues, it's impossible to know for sure + # exactly how to load v3 entries, thus we'll treat these as a miss so + # that they get rewritten out as v4 entries. + return + + def _loads_v4(self, request, data): + try: + cached = msgpack.loads(data, raw=False) + except ValueError: + return + + return self.prepare_response(request, cached) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/wrapper.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/wrapper.py new file mode 100644 index 00000000..d8e6fc6a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cachecontrol/wrapper.py @@ -0,0 +1,29 @@ +from .adapter import CacheControlAdapter +from .cache import DictCache + + +def CacheControl( + sess, + cache=None, + cache_etags=True, + serializer=None, + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None, +): + + cache = DictCache() if cache is None else cache + adapter_class = adapter_class or CacheControlAdapter + adapter = adapter_class( + cache, + cache_etags=cache_etags, + serializer=serializer, + heuristic=heuristic, + controller_class=controller_class, + cacheable_methods=cacheable_methods, + ) + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + return sess diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/METADATA new file mode 100644 index 00000000..e897b3d8 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/METADATA @@ -0,0 +1,74 @@ +Metadata-Version: 2.1 +Name: certifi +Version: 2019.11.28 +Summary: Python package for providing Mozilla's CA Bundle. +Home-page: https://certifi.io/ +Author: Kenneth Reitz +Author-email: me@kennethreitz.com +License: MPL-2.0 +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) +Classifier: Natural Language :: English +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 + +Certifi: Python SSL Certificates +================================ + +`Certifi`_ is a carefully curated collection of Root Certificates for +validating the trustworthiness of SSL certificates while verifying the identity +of TLS hosts. It has been extracted from the `Requests`_ project. + +Installation +------------ + +``certifi`` is available on PyPI. Simply install it with ``pip``:: + + $ pip install certifi + +Usage +----- + +To reference the installed certificate authority (CA) bundle, you can use the +built-in function:: + + >>> import certifi + + >>> certifi.where() + '/usr/local/lib/python2.7/site-packages/certifi/cacert.pem' + +Or from the command line:: + + $ python -m certifi + /usr/local/lib/python2.7/site-packages/certifi/cacert.pem + +Enjoy! + +1024-bit Root Certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Browsers and certificate authorities have concluded that 1024-bit keys are +unacceptably weak for certificates, particularly root certificates. For this +reason, Mozilla has removed any weak (i.e. 1024-bit key) certificate from its +bundle, replacing it with an equivalent strong (i.e. 2048-bit or greater key) +certificate from the same CA. Because Mozilla removed these certificates from +its bundle, ``certifi`` removed them as well. + +In previous versions, ``certifi`` provided the ``certifi.old_where()`` function +to intentionally re-add the 1024-bit roots back into your bundle. This was not +recommended in production and therefore was removed at the end of 2018. + +.. _`Certifi`: https://certifi.io/en/latest/ +.. _`Requests`: http://docs.python-requests.org/en/latest/ + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/RECORD new file mode 100644 index 00000000..1d4830a1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/RECORD @@ -0,0 +1,17 @@ +certifi/__init__.py,sha256=JVwzDhkMttyVVtfNDrU_i0v2a-WmtEBXq0Z8oz4Ghzk,52 +certifi/__main__.py,sha256=FiOYt1Fltst7wk9DRa6GCoBr8qBUxlNQu_MKJf04E6s,41 +certifi/cacert.pem,sha256=cyvv5Jx1gHACNEj2GaOrsIj0Tk8FmSvHR42uhzvlatg,281457 +certifi/core.py,sha256=u_450edAVoiZrgqi6k3Sekcvs-B1zD_hTeE6UJ2OcQ4,225 +certifi-2019.11.28.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +certifi-2019.11.28.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +certifi-2019.11.28.dist-info/METADATA,sha256=K6ioZZT9N0bRETHmncjK-UJKAFIVF26h1F31dfDaV5k,2523 +certifi-2019.11.28.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +certifi-2019.11.28.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 +certifi-2019.11.28.dist-info/RECORD,, +certifi-2019.11.28.dist-info/__pycache__,, +certifi-2019.11.28.virtualenv,, +certifi/__init__.cpython-38.pyc,, +certifi/core.cpython-38.pyc,, +certifi-2019.11.28.dist-info/INSTALLER,, +certifi/__main__.cpython-38.pyc,, +certifi/__pycache__,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/top_level.txt new file mode 100644 index 00000000..963eac53 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.dist-info/top_level.txt @@ -0,0 +1 @@ +certifi diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi-2019.11.28.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__init__.py new file mode 100644 index 00000000..0d59a056 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import where + +__version__ = "2019.11.28" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__main__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__main__.py new file mode 100644 index 00000000..5f1da0dd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/__main__.py @@ -0,0 +1,2 @@ +from certifi import where +print(where()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/cacert.pem b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/cacert.pem new file mode 100644 index 00000000..a4758ef3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/cacert.pem @@ -0,0 +1,4602 @@ + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only +# Label: "Verisign Class 3 Public Primary Certification Authority - G3" +# Serial: 206684696279472310254277870180966723415 +# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09 +# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6 +# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44 +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl +cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu +LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT +aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD +VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ +bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu +IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b +N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t +KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu +kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm +CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ +Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu +imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te +2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe +DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p +F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt +TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network +# Label: "AddTrust External Root" +# Serial: 1 +# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f +# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68 +# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2 +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. +# Label: "GeoTrust Global CA" +# Serial: 144470 +# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 +# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 +# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. +# Label: "GeoTrust Universal CA" +# Serial: 1 +# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 +# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 +# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy +c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 +IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV +VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 +cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT +QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh +F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v +c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w +mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd +VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX +teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ +f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe +Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ +nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB +/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY +MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG +9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX +IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn +ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z +uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN +Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja +QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW +koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 +ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt +DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm +bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. +# Label: "GeoTrust Universal CA 2" +# Serial: 1 +# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 +# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 +# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW +MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy +c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD +VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 +c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 +WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG +FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq +XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL +se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb +KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd +IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 +y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt +hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc +QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 +Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV +HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ +KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ +L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr +Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo +ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY +T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz +GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m +1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV +OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH +6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX +QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority +# Label: "QuoVadis Root CA" +# Serial: 985026699 +# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 +# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 +# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz +MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw +IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR +dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp +li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D +rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ +WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug +F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU +xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC +Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv +dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw +ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl +IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh +c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy +ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI +KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T +KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq +y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p +dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD +VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL +MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk +fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 +7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R +cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y +mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW +xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK +SnQ2+Q== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=Sonera Class2 CA O=Sonera +# Subject: CN=Sonera Class2 CA O=Sonera +# Label: "Sonera Class 2 Root CA" +# Serial: 29 +# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb +# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 +# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP +MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx +MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV +BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o +Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt +5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s +3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej +vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu +8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw +DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG +MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil +zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ +3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD +FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 +Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 +ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +# Issuer: O=Government Root Certification Authority +# Subject: O=Government Root Certification Authority +# Label: "Taiwan GRCA" +# Serial: 42023070807708724159991140556527066870 +# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e +# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9 +# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3 +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ +MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow +PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR +IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q +gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy +yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts +F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 +jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx +ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC +VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK +YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH +EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN +Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud +DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE +MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK +UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf +qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK +ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE +JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 +hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 +EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm +nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX +udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz +ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe +LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl +pYYsfPQS +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. +# Label: "GeoTrust Primary Certification Authority" +# Serial: 32798226551256963324313806436981982369 +# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf +# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 +# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo +R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx +MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 +AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA +ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 +7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W +kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI +mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ +KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 +6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl +4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K +oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj +UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU +AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA" +# Serial: 69529181992039203566298953787712940909 +# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 +# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 +# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB +qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV +BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw +NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j +LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG +A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs +W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta +3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk +6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 +Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J +NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP +r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU +DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz +YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 +/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ +LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 +jVaMaA== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" +# Serial: 33037644167568058970164719475676101450 +# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c +# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 +# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GA CA" +# Serial: 86718877871133159090080555911823548314 +# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93 +# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9 +# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5 +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB +ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly +aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w +NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G +A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX +SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR +VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 +w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF +mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg +4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 +4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw +EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx +SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 +ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 +vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi +Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ +/L7fCg0= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G3" +# Serial: 28809105769928564313984085209975885599 +# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 +# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd +# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB +mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT +MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 +BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz ++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm +hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn +5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W +JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL +DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC +huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB +AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB +zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN +kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH +SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G +spki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G2" +# Serial: 71758320672825410020661621085256472406 +# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f +# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 +# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp +IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi +BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw +MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig +YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v +dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ +BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 +papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K +DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 +KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox +XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only +# Label: "thawte Primary Root CA - G3" +# Serial: 127614157056681299805556476275995414779 +# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 +# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 +# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB +rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf +Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw +MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV +BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa +Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl +LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u +MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm +gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 +YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf +b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 +9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S +zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk +OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA +2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW +oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c +KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM +m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu +MdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only +# Label: "GeoTrust Primary Certification Authority - G2" +# Serial: 80682863203381065782177908751794619243 +# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a +# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 +# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj +KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 +MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw +NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV +BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH +MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL +So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal +tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG +CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT +qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz +rD6ogRLQy7rQkgu2npaqBA+K +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Universal Root Certification Authority" +# Serial: 85209574734084581917763752644031726877 +# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 +# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 +# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB +vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W +ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX +MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 +IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y +IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh +bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF +9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH +H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H +LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN +/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT +rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw +WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs +exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 +sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ +seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz +4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ +BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR +lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 +7M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only +# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" +# Serial: 63143484348153506665311985501458640051 +# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 +# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a +# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp +U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg +SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln +biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm +GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve +fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ +aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj +aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW +kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC +4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga +FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G2" +# Serial: 10000012 +# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a +# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16 +# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f +-----BEGIN CERTIFICATE----- +MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX +DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 +qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp +uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU +Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE +pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp +5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M +UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN +GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy +5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv +6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK +eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 +B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ +BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov +L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG +SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS +CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen +5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 +IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK +gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL ++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL +vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm +bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk +N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC +Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z +ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. +# Label: "Chambers of Commerce Root - 2008" +# Serial: 11806822484801597146 +# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 +# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c +# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz +IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz +MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj +dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw +EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp +MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 +28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq +VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q +DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR +5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL +ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a +Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl +UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s ++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 +Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx +hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV +HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 ++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN +YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t +L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy +ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt +IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV +HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w +DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW +PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF +5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 +glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH +FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 +pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD +xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG +tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq +jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De +fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ +d0jQ +-----END CERTIFICATE----- + +# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. +# Label: "Global Chambersign Root - 2008" +# Serial: 14541511773111788494 +# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 +# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c +# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD +VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 +IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 +MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx +MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy +cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG +A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl +BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed +KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 +G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 +zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 +ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG +HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 +Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V +yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e +beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r +6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog +zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW +BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr +ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp +ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk +cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt +YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC +CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow +KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI +hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ +UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz +X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x +fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz +a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd +Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd +SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O +AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso +M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge +v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: O=Trustis Limited OU=Trustis FPS Root CA +# Subject: O=Trustis Limited OU=Trustis FPS Root CA +# Label: "Trustis FPS Root CA" +# Serial: 36053640375399034304724988975563710553 +# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d +# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 +# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL +ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx +MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc +MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ +AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH +iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj +vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA +0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB +OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ +BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E +FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 +GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW +zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 +1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE +f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F +jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN +ZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus +# Label: "EE Certification Centre Root CA" +# Serial: 112324828676200291871926431888494945866 +# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f +# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7 +# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76 +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 +MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 +czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG +CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy +MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl +ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS +b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy +euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO +bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw +WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d +MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE +1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ +zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB +BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF +BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV +v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG +E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW +iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v +GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Label: "TeliaSonera Root CA v1" +# Serial: 199041966741090107964904287217786801558 +# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c +# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 +# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Label: "E-Tugra Certification Authority" +# Serial: 7667447206703254355 +# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 +# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 +# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 2" +# Serial: 1 +# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a +# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 +# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot 2011 O=Atos +# Subject: CN=Atos TrustedRoot 2011 O=Atos +# Label: "Atos TrustedRoot 2011" +# Serial: 6643877497813316402 +# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 +# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 +# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 1 G3" +# Serial: 687049649626669250736271037606554624078720034195 +# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab +# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 +# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2 G3" +# Serial: 390156079458959257446133169266079962026824725800 +# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 +# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 +# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3 G3" +# Serial: 268090761170461462463995952157327242137089239581 +# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 +# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d +# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G2" +# Serial: 15385348160840213938643033620894905419 +# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d +# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f +# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G3" +# Serial: 15459312981008553731928384953135426796 +# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb +# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 +# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G2" +# Serial: 4293743540046975378534879503202253541 +# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 +# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 +# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G3" +# Serial: 7089244469030293291760083333884364146 +# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca +# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e +# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Trusted Root G4" +# Serial: 7451500558977370777930084869016614236 +# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 +# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 +# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Label: "COMODO RSA Certification Authority" +# Serial: 101909084537582093308941363524873193117 +# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 +# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 +# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Label: "USERTrust RSA Certification Authority" +# Serial: 2645093764781058787591871645665788717 +# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 +# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e +# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Label: "USERTrust ECC Certification Authority" +# Serial: 123013823720199481456569720443997572134 +# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 +# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 +# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 14367148294922964480859022125800977897474 +# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e +# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb +# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Label: "GlobalSign ECC Root CA - R5" +# Serial: 32785792099990507226680698011560947931244 +# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 +# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa +# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden +# Label: "Staat der Nederlanden Root CA - G3" +# Serial: 10003001 +# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 +# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc +# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX +DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl +ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv +b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP +cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW +IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX +xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy +KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR +9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az +5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 +6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 +Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP +bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt +BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt +XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd +INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD +U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp +LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 +Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp +gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh +/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw +0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A +fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq +4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR +1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ +QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM +94B7IWcnMFk= +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden EV Root CA" +# Serial: 10000013 +# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba +# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb +# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Label: "IdenTrust Commercial Root CA 1" +# Serial: 13298821034946342390520003877796839426 +# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 +# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 +# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Label: "IdenTrust Public Sector Root CA 1" +# Serial: 13298821034946342390521976156843933698 +# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba +# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd +# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G2" +# Serial: 1246989352 +# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 +# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 +# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - EC1" +# Serial: 51543124481930649114116133369 +# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc +# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 +# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority +# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority +# Label: "CFCA EV ROOT" +# Serial: 407555286 +# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 +# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 +# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GB CA" +# Serial: 157768595616588414422159278966750757568 +# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d +# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed +# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Label: "SZAFIR ROOT CA2" +# Serial: 357043034767186914217277344587386743377558296292 +# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 +# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de +# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA 2" +# Serial: 44979900017204383099463764357512596969 +# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 +# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 +# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce +# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 +# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef +# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 +# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X1 O=Internet Security Research Group +# Subject: CN=ISRG Root X1 O=Internet Security Research Group +# Label: "ISRG Root X1" +# Serial: 172886928669790476064670243504169061120 +# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e +# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 +# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Label: "AC RAIZ FNMT-RCM" +# Serial: 485876308206448804701554682760554759 +# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d +# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 +# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 1 O=Amazon +# Subject: CN=Amazon Root CA 1 O=Amazon +# Label: "Amazon Root CA 1" +# Serial: 143266978916655856878034712317230054538369994 +# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 +# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 +# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 2 O=Amazon +# Subject: CN=Amazon Root CA 2 O=Amazon +# Label: "Amazon Root CA 2" +# Serial: 143266982885963551818349160658925006970653239 +# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 +# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a +# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 3 O=Amazon +# Subject: CN=Amazon Root CA 3 O=Amazon +# Label: "Amazon Root CA 3" +# Serial: 143266986699090766294700635381230934788665930 +# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 +# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e +# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 4 O=Amazon +# Subject: CN=Amazon Root CA 4 O=Amazon +# Label: "Amazon Root CA 4" +# Serial: 143266989758080763974105200630763877849284878 +# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd +# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be +# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +# Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A. +# Label: "LuxTrust Global Root 2" +# Serial: 59914338225734147123941058376788110305822489521 +# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c +# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f +# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# Serial: 1 +# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 +# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca +# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Label: "GDCA TrustAUTH R5 ROOT" +# Serial: 9009899650740120186 +# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 +# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 +# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-1" +# Serial: 15752444095811006489 +# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 +# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a +# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-2" +# Serial: 2711694510199101698 +# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 +# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 +# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor ECA-1" +# Serial: 9548242946988625984 +# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c +# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd +# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Label: "SSL.com Root Certification Authority RSA" +# Serial: 8875640296558310041 +# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 +# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb +# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority RSA R2" +# Serial: 6248227494352943350 +# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 +# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a +# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority ECC" +# Serial: 3182246526754555285 +# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 +# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d +# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 146587175971765017618439757810265552097 +# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85 +# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8 +# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 146587176055767053814479386953112547951 +# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b +# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d +# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 146587176140553309517047991083707763997 +# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25 +# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5 +# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5 +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 146587176229350439916519468929765261721 +# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26 +# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb +# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign Root CA - G1" +# Serial: 235931866688319308814040 +# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac +# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c +# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign ECC Root CA - G3" +# Serial: 287880440101571086945156 +# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 +# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 +# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Label: "emSign Root CA - C1" +# Serial: 825510296613316004955058 +# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 +# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 +# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Label: "emSign ECC Root CA - C3" +# Serial: 582948710642506000014504 +# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 +# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 +# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Label: "Hongkong Post Root CA 3" +# Serial: 46170865288971385588281144162979347873371282084 +# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 +# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 +# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 +-----BEGIN CERTIFICATE----- +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 +mpv0 +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G4" +# Serial: 289383649854506086828220374796556676440 +# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88 +# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01 +# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/core.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/core.py new file mode 100644 index 00000000..53404e13 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/certifi/core.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem. +""" +import os + + +def where(): + f = os.path.dirname(__file__) + + return '/etc/ssl/certs/ca-certificates.crt' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/LICENSE b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/LICENSE new file mode 100644 index 00000000..29225eee --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/LICENSE @@ -0,0 +1,26 @@ + +Except when otherwise stated (look for LICENSE files in directories or +information at the beginning of each file) all software and +documentation is licensed as follows: + + The MIT License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/METADATA new file mode 100644 index 00000000..417da722 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/METADATA @@ -0,0 +1,37 @@ +Metadata-Version: 2.1 +Name: cffi +Version: 1.14.5 +Summary: Foreign Function Interface for Python calling C code. +Home-page: http://cffi.readthedocs.org +Author: Armin Rigo, Maciej Fijalkowski +Author-email: python-cffi@googlegroups.com +License: MIT +Platform: UNKNOWN +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: License :: OSI Approved :: MIT License +Requires-Dist: pycparser + + +CFFI +==== + +Foreign Function Interface for Python calling C code. +Please see the `Documentation `_. + +Contact +------- + +`Mailing list `_ + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/RECORD new file mode 100644 index 00000000..187f18b0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/RECORD @@ -0,0 +1,45 @@ +_cffi_backend.cpython-38-x86_64-linux-gnu.so,sha256=xaT4emFoLaKFKgxsPR-DzE_RnqPMEWbaY2DtdmdQrmQ,893296 +cffi-1.14.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +cffi-1.14.5.dist-info/LICENSE,sha256=BLgPWwd7vtaICM_rreteNSPyqMmpZJXFh72W3x6sKjM,1294 +cffi-1.14.5.dist-info/METADATA,sha256=9cQJcfX8MjM9nlAXlHcCe-YmRy7Ez9IsA3eSoOdYYWY,1191 +cffi-1.14.5.dist-info/RECORD,, +cffi-1.14.5.dist-info/WHEEL,sha256=Dh4w5P6PPWbqyqoE6MHlzbFQwZXlM-voWJDf2WUsS2g,108 +cffi-1.14.5.dist-info/entry_points.txt,sha256=Q9f5C9IpjYxo0d2PK9eUcnkgxHc9pHWwjEMaANPKNCI,76 +cffi-1.14.5.dist-info/top_level.txt,sha256=rE7WR3rZfNKxWI9-jn6hsHCAl7MDkB-FmuQbxWjFehQ,19 +cffi.libs/libffi-806b1a9d.so.6.0.4,sha256=0MxSFdTpPwKsulw1XmWPRPVreyFK3AIBBg7i6a3-rWY,46632 +cffi/__init__.py,sha256=xTe6YZU3-T1_hzu4x7LMs6afwrbhtwYaQ4oYCYTfy3M,513 +cffi/__pycache__/__init__.cpython-38.pyc,, +cffi/__pycache__/api.cpython-38.pyc,, +cffi/__pycache__/backend_ctypes.cpython-38.pyc,, +cffi/__pycache__/cffi_opcode.cpython-38.pyc,, +cffi/__pycache__/commontypes.cpython-38.pyc,, +cffi/__pycache__/cparser.cpython-38.pyc,, +cffi/__pycache__/error.cpython-38.pyc,, +cffi/__pycache__/ffiplatform.cpython-38.pyc,, +cffi/__pycache__/lock.cpython-38.pyc,, +cffi/__pycache__/model.cpython-38.pyc,, +cffi/__pycache__/pkgconfig.cpython-38.pyc,, +cffi/__pycache__/recompiler.cpython-38.pyc,, +cffi/__pycache__/setuptools_ext.cpython-38.pyc,, +cffi/__pycache__/vengine_cpy.cpython-38.pyc,, +cffi/__pycache__/vengine_gen.cpython-38.pyc,, +cffi/__pycache__/verifier.cpython-38.pyc,, +cffi/_cffi_errors.h,sha256=6nFQ-4dRQI1bXRoSeqdvyKU33TmutQJB_2fAhWSzdl8,3856 +cffi/_cffi_include.h,sha256=tKnA1rdSoPHp23FnDL1mDGwFo-Uj6fXfA6vA6kcoEUc,14800 +cffi/_embedding.h,sha256=vXP95nMKN_jwCGWenL3XugNPwa2Ko-yqqp0lA-Nh5-I,17581 +cffi/api.py,sha256=yxJalIePbr1mz_WxAHokSwyP5CVYde44m-nolHnbJNo,42064 +cffi/backend_ctypes.py,sha256=h5ZIzLc6BFVXnGyc9xPqZWUS7qGy7yFSDqXe68Sa8z4,42454 +cffi/cffi_opcode.py,sha256=v9RdD_ovA8rCtqsC95Ivki5V667rAOhGgs3fb2q9xpM,5724 +cffi/commontypes.py,sha256=QS4uxCDI7JhtTyjh1hlnCA-gynmaszWxJaRRLGkJa1A,2689 +cffi/cparser.py,sha256=rO_1pELRw1gI1DE1m4gi2ik5JMfpxouAACLXpRPlVEA,44231 +cffi/error.py,sha256=v6xTiS4U0kvDcy4h_BDRo5v39ZQuj-IMRYLv5ETddZs,877 +cffi/ffiplatform.py,sha256=HMXqR8ks2wtdsNxGaWpQ_PyqIvtiuos_vf1qKCy-cwg,4046 +cffi/lock.py,sha256=l9TTdwMIMpi6jDkJGnQgE9cvTIR7CAntIJr8EGHt3pY,747 +cffi/model.py,sha256=_GH_UF1Rn9vC4AvmgJm6qj7RUXXG3eqKPc8bPxxyBKE,21768 +cffi/parse_c_type.h,sha256=OdwQfwM9ktq6vlCB43exFQmxDBtj2MBNdK8LYl15tjw,5976 +cffi/pkgconfig.py,sha256=LP1w7vmWvmKwyqLaU1Z243FOWGNQMrgMUZrvgFuOlco,4374 +cffi/recompiler.py,sha256=7OBdKr0dAzRnEbgQvjCAikoFAygjTvitaJHdRGc1k24,64568 +cffi/setuptools_ext.py,sha256=RUR17N5f8gpiQBBlXL34P9FtOu1mhHIaAf3WJlg5S4I,8931 +cffi/vengine_cpy.py,sha256=YglN8YS-UaHEv2k2cxgotNWE87dHX20-68EyKoiKUYA,43320 +cffi/vengine_gen.py,sha256=5dX7s1DU6pTBOMI6oTVn_8Bnmru_lj932B6b4v29Hlg,26684 +cffi/verifier.py,sha256=J9Enz2rbJb9CHPqWlWQ5uQESoyr0uc7MNWugchjXBv4,11207 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/WHEEL new file mode 100644 index 00000000..69d594f0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.36.2) +Root-Is-Purelib: false +Tag: cp38-cp38-manylinux1_x86_64 + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/entry_points.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/entry_points.txt new file mode 100644 index 00000000..eee7e0fb --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[distutils.setup_keywords] +cffi_modules = cffi.setuptools_ext:cffi_modules + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/top_level.txt new file mode 100644 index 00000000..f6457795 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi-1.14.5.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_cffi_backend +cffi diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi.libs/libffi-806b1a9d.so.6.0.4 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi.libs/libffi-806b1a9d.so.6.0.4 new file mode 100755 index 0000000000000000000000000000000000000000..7e0b3012805ee9dd64076988820be79345407832 GIT binary patch literal 46632 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 z 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 3 + bi = PyImport_ImportModule("builtins"); +#else + bi = PyImport_ImportModule("__builtin__"); +#endif + if (bi == NULL) + goto error; + PyDict_SetItemString(result, "__builtins__", bi); + Py_DECREF(bi); + + x = PyRun_String( + "import sys\n" + "class FileLike:\n" + " def write(self, x):\n" + " try:\n" + " of.write(x)\n" + " except: pass\n" + " self.buf += x\n" + "fl = FileLike()\n" + "fl.buf = ''\n" + "of = sys.stderr\n" + "sys.stderr = fl\n" + "def done():\n" + " sys.stderr = of\n" + " return fl.buf\n", /* make sure the returned value stays alive */ + Py_file_input, + result, result); + Py_XDECREF(x); + + error: + if (PyErr_Occurred()) + { + PyErr_WriteUnraisable(Py_None); + PyErr_Clear(); + } + return result; +} + +#pragma comment(lib, "user32.lib") + +static DWORD WINAPI _cffi_bootstrap_dialog(LPVOID ignored) +{ + Sleep(666); /* may be interrupted if the whole process is closing */ +#if PY_MAJOR_VERSION >= 3 + MessageBoxW(NULL, (wchar_t *)_cffi_bootstrap_text, + L"Python-CFFI error", + MB_OK | MB_ICONERROR); +#else + MessageBoxA(NULL, (char *)_cffi_bootstrap_text, + "Python-CFFI error", + MB_OK | MB_ICONERROR); +#endif + _cffi_bootstrap_text = NULL; + return 0; +} + +static void _cffi_stop_error_capture(PyObject *ecap) +{ + PyObject *s; + void *text; + + if (ecap == (PyObject *)1) + return; + + if (ecap == NULL) + goto error; + + s = PyRun_String("done()", Py_eval_input, ecap, ecap); + if (s == NULL) + goto error; + + /* Show a dialog box, but in a background thread, and + never show multiple dialog boxes at once. */ +#if PY_MAJOR_VERSION >= 3 + text = PyUnicode_AsWideCharString(s, NULL); +#else + text = PyString_AsString(s); +#endif + + _cffi_bootstrap_text = text; + + if (text != NULL) + { + HANDLE h; + h = CreateThread(NULL, 0, _cffi_bootstrap_dialog, + NULL, 0, NULL); + if (h != NULL) + CloseHandle(h); + } + /* decref the string, but it should stay alive as 'fl.buf' + in the small module above. It will really be freed only if + we later get another similar error. So it's a leak of at + most one copy of the small module. That's fine for this + situation which is usually a "fatal error" anyway. */ + Py_DECREF(s); + PyErr_Clear(); + return; + + error: + _cffi_bootstrap_text = NULL; + PyErr_Clear(); +} + +#else + +static PyObject *_cffi_start_error_capture(void) { return NULL; } +static void _cffi_stop_error_capture(PyObject *ecap) { } + +#endif diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_cffi_include.h b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_cffi_include.h new file mode 100644 index 00000000..e4c0a672 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_cffi_include.h @@ -0,0 +1,385 @@ +#define _CFFI_ + +/* We try to define Py_LIMITED_API before including Python.h. + + Mess: we can only define it if Py_DEBUG, Py_TRACE_REFS and + Py_REF_DEBUG are not defined. This is a best-effort approximation: + we can learn about Py_DEBUG from pyconfig.h, but it is unclear if + the same works for the other two macros. Py_DEBUG implies them, + but not the other way around. + + The implementation is messy (issue #350): on Windows, with _MSC_VER, + we have to define Py_LIMITED_API even before including pyconfig.h. + In that case, we guess what pyconfig.h will do to the macros above, + and check our guess after the #include. + + Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv + version >= 16.0.0. With older versions of either, you don't get a + copy of PYTHON3.DLL in the virtualenv. We can't check the version of + CPython *before* we even include pyconfig.h. ffi.set_source() puts + a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is + running on Windows < 3.5, as an attempt at fixing it, but that's + arguably wrong because it may not be the target version of Python. + Still better than nothing I guess. As another workaround, you can + remove the definition of Py_LIMITED_API here. + + See also 'py_limited_api' in cffi/setuptools_ext.py. +*/ +#if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) +# ifdef _MSC_VER +# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# include + /* sanity-check: Py_LIMITED_API will cause crashes if any of these + are also defined. Normally, the Python file PC/pyconfig.h does not + cause any of these to be defined, with the exception that _DEBUG + causes Py_DEBUG. Double-check that. */ +# ifdef Py_LIMITED_API +# if defined(Py_DEBUG) +# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set" +# endif +# if defined(Py_TRACE_REFS) +# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set" +# endif +# if defined(Py_REF_DEBUG) +# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set" +# endif +# endif +# else +# include +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API) +# define Py_LIMITED_API +# endif +# endif +#endif + +#include +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "parse_c_type.h" + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#ifdef __GNUC__ +# define _CFFI_UNUSED_FN __attribute__((unused)) +#else +# define _CFFI_UNUSED_FN /* nothing */ +#endif + +#ifdef __cplusplus +# ifndef _Bool + typedef bool _Bool; /* semi-hackish: C++ has no _Bool; bool is builtin */ +# endif +#endif + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, struct _cffi_ctypedescr *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + not used any more +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, struct _cffi_ctypedescr *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((_cffi_wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(_cffi_wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(struct _cffi_ctypedescr *, \ + PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, struct _cffi_ctypedescr *, PyObject *))_cffi_exports[24]) +#define _CFFI_CPIDX 25 +#define _cffi_call_python \ + ((void(*)(struct _cffi_externpy_s *, char *))_cffi_exports[_CFFI_CPIDX]) +#define _cffi_to_c_wchar3216_t \ + ((int(*)(PyObject *))_cffi_exports[26]) +#define _cffi_from_c_wchar3216_t \ + ((PyObject *(*)(int))_cffi_exports[27]) +#define _CFFI_NUM_EXPORTS 28 + +struct _cffi_ctypedescr; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; + +#define _cffi_type(index) ( \ + assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ + (struct _cffi_ctypedescr *)_cffi_types[index]) + +static PyObject *_cffi_init(const char *module_name, Py_ssize_t version, + const struct _cffi_type_context_s *ctx) +{ + PyObject *module, *o_arg, *new_module; + void *raw[] = { + (void *)module_name, + (void *)version, + (void *)_cffi_exports, + (void *)ctx, + }; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + o_arg = PyLong_FromVoidPtr((void *)raw); + if (o_arg == NULL) + goto failure; + + new_module = PyObject_CallMethod( + module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg); + + Py_DECREF(o_arg); + Py_DECREF(module); + return new_module; + + failure: + Py_XDECREF(module); + return NULL; +} + + +#ifdef HAVE_WCHAR_H +typedef wchar_t _cffi_wchar_t; +#else +typedef uint16_t _cffi_wchar_t; /* same random pick as _cffi_backend.c */ +#endif + +_CFFI_UNUSED_FN static uint16_t _cffi_to_c_char16_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 2) + return (uint16_t)_cffi_to_c_wchar_t(o); + else + return (uint16_t)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) +{ + if (sizeof(_cffi_wchar_t) == 2) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +_CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) +{ + if (sizeof(_cffi_wchar_t) == 4) + return (int)_cffi_to_c_wchar_t(o); + else + return (int)_cffi_to_c_wchar3216_t(o); +} + +_CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(unsigned int x) +{ + if (sizeof(_cffi_wchar_t) == 4) + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); + else + return _cffi_from_c_wchar3216_t((int)x); +} + +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +_CFFI_UNUSED_FN static int +_cffi_convert_array_argument(struct _cffi_ctypedescr *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +_CFFI_UNUSED_FN static void +_cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + +/********** end CPython-specific section **********/ +#else +_CFFI_UNUSED_FN +static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *); +# define _cffi_call_python _cffi_call_python_org +#endif + + +#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) + +#define _cffi_prim_int(size, sign) \ + ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ + (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ + (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ + (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ + _CFFI__UNKNOWN_PRIM) + +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + +#define _cffi_check_int(got, got_nonpos, expected) \ + ((got_nonpos) == (expected <= 0) && \ + (got) == (unsigned long long)expected) + +#ifdef MS_WIN32 +# define _cffi_stdcall __stdcall +#else +# define _cffi_stdcall /* nothing */ +#endif + +#ifdef __cplusplus +} +#endif diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_embedding.h b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_embedding.h new file mode 100644 index 00000000..c36d7934 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/_embedding.h @@ -0,0 +1,527 @@ + +/***** Support code for embedding *****/ + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(_WIN32) +# define CFFI_DLLEXPORT __declspec(dllexport) +#elif defined(__GNUC__) +# define CFFI_DLLEXPORT __attribute__((visibility("default"))) +#else +# define CFFI_DLLEXPORT /* nothing */ +#endif + + +/* There are two global variables of type _cffi_call_python_fnptr: + + * _cffi_call_python, which we declare just below, is the one called + by ``extern "Python"`` implementations. + + * _cffi_call_python_org, which on CPython is actually part of the + _cffi_exports[] array, is the function pointer copied from + _cffi_backend. + + After initialization is complete, both are equal. However, the + first one remains equal to &_cffi_start_and_call_python until the + very end of initialization, when we are (or should be) sure that + concurrent threads also see a completely initialized world, and + only then is it changed. +*/ +#undef _cffi_call_python +typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); +static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); +static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; + + +#ifndef _MSC_VER + /* --- Assuming a GCC not infinitely old --- */ +# define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) +# define cffi_write_barrier() __sync_synchronize() +# if !defined(__amd64__) && !defined(__x86_64__) && \ + !defined(__i386__) && !defined(__i386) +# define cffi_read_barrier() __sync_synchronize() +# else +# define cffi_read_barrier() (void)0 +# endif +#else + /* --- Windows threads version --- */ +# include +# define cffi_compare_and_swap(l,o,n) \ + (InterlockedCompareExchangePointer(l,n,o) == (o)) +# define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) +# define cffi_read_barrier() (void)0 +static volatile LONG _cffi_dummy; +#endif + +#ifdef WITH_THREAD +# ifndef _MSC_VER +# include + static pthread_mutex_t _cffi_embed_startup_lock; +# else + static CRITICAL_SECTION _cffi_embed_startup_lock; +# endif + static char _cffi_embed_startup_lock_ready = 0; +#endif + +static void _cffi_acquire_reentrant_mutex(void) +{ + static void *volatile lock = NULL; + + while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: pthread_mutex_init() should be very fast, and + this is only run at start-up anyway. */ + } + +#ifdef WITH_THREAD + if (!_cffi_embed_startup_lock_ready) { +# ifndef _MSC_VER + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&_cffi_embed_startup_lock, &attr); +# else + InitializeCriticalSection(&_cffi_embed_startup_lock); +# endif + _cffi_embed_startup_lock_ready = 1; + } +#endif + + while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) + ; + +#ifndef _MSC_VER + pthread_mutex_lock(&_cffi_embed_startup_lock); +#else + EnterCriticalSection(&_cffi_embed_startup_lock); +#endif +} + +static void _cffi_release_reentrant_mutex(void) +{ +#ifndef _MSC_VER + pthread_mutex_unlock(&_cffi_embed_startup_lock); +#else + LeaveCriticalSection(&_cffi_embed_startup_lock); +#endif +} + + +/********** CPython-specific section **********/ +#ifndef PYPY_VERSION + +#include "_cffi_errors.h" + + +#define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] + +PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */ + +static void _cffi_py_initialize(void) +{ + /* XXX use initsigs=0, which "skips initialization registration of + signal handlers, which might be useful when Python is + embedded" according to the Python docs. But review and think + if it should be a user-controllable setting. + + XXX we should also give a way to write errors to a buffer + instead of to stderr. + + XXX if importing 'site' fails, CPython (any version) calls + exit(). Should we try to work around this behavior here? + */ + Py_InitializeEx(0); +} + +static int _cffi_initialize_python(void) +{ + /* This initializes Python, imports _cffi_backend, and then the + present .dll/.so is set up as a CPython C extension module. + */ + int result; + PyGILState_STATE state; + PyObject *pycode=NULL, *global_dict=NULL, *x; + PyObject *builtins; + + state = PyGILState_Ensure(); + + /* Call the initxxx() function from the present module. It will + create and initialize us as a CPython extension module, instead + of letting the startup Python code do it---it might reimport + the same .dll/.so and get maybe confused on some platforms. + It might also have troubles locating the .dll/.so again for all + I know. + */ + (void)_CFFI_PYTHON_STARTUP_FUNC(); + if (PyErr_Occurred()) + goto error; + + /* Now run the Python code provided to ffi.embedding_init_code(). + */ + pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, + "", + Py_file_input); + if (pycode == NULL) + goto error; + global_dict = PyDict_New(); + if (global_dict == NULL) + goto error; + builtins = PyEval_GetBuiltins(); + if (builtins == NULL) + goto error; + if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) + goto error; + x = PyEval_EvalCode( +#if PY_MAJOR_VERSION < 3 + (PyCodeObject *) +#endif + pycode, global_dict, global_dict); + if (x == NULL) + goto error; + Py_DECREF(x); + + /* Done! Now if we've been called from + _cffi_start_and_call_python() in an ``extern "Python"``, we can + only hope that the Python code did correctly set up the + corresponding @ffi.def_extern() function. Otherwise, the + general logic of ``extern "Python"`` functions (inside the + _cffi_backend module) will find that the reference is still + missing and print an error. + */ + result = 0; + done: + Py_XDECREF(pycode); + Py_XDECREF(global_dict); + PyGILState_Release(state); + return result; + + error:; + { + /* Print as much information as potentially useful. + Debugging load-time failures with embedding is not fun + */ + PyObject *ecap; + PyObject *exception, *v, *tb, *f, *modules, *mod; + PyErr_Fetch(&exception, &v, &tb); + ecap = _cffi_start_error_capture(); + f = PySys_GetObject((char *)"stderr"); + if (f != NULL && f != Py_None) { + PyFile_WriteString( + "Failed to initialize the Python-CFFI embedding logic:\n\n", f); + } + + if (exception != NULL) { + PyErr_NormalizeException(&exception, &v, &tb); + PyErr_Display(exception, v, tb); + } + Py_XDECREF(exception); + Py_XDECREF(v); + Py_XDECREF(tb); + + if (f != NULL && f != Py_None) { + PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME + "\ncompiled with cffi version: 1.14.5" + "\n_cffi_backend module: ", f); + modules = PyImport_GetModuleDict(); + mod = PyDict_GetItemString(modules, "_cffi_backend"); + if (mod == NULL) { + PyFile_WriteString("not loaded", f); + } + else { + v = PyObject_GetAttrString(mod, "__file__"); + PyFile_WriteObject(v, f, 0); + Py_XDECREF(v); + } + PyFile_WriteString("\nsys.path: ", f); + PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); + PyFile_WriteString("\n\n", f); + } + _cffi_stop_error_capture(ecap); + } + result = -1; + goto done; +} + +#if PY_VERSION_HEX < 0x03080000 +PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */ +#endif + +static int _cffi_carefully_make_gil(void) +{ + /* This does the basic initialization of Python. It can be called + completely concurrently from unrelated threads. It assumes + that we don't hold the GIL before (if it exists), and we don't + hold it afterwards. + + (What it really does used to be completely different in Python 2 + and Python 3, with the Python 2 solution avoiding the spin-lock + around the Py_InitializeEx() call. However, after recent changes + to CPython 2.7 (issue #358) it no longer works. So we use the + Python 3 solution everywhere.) + + This initializes Python by calling Py_InitializeEx(). + Important: this must not be called concurrently at all. + So we use a global variable as a simple spin lock. This global + variable must be from 'libpythonX.Y.so', not from this + cffi-based extension module, because it must be shared from + different cffi-based extension modules. + + In Python < 3.8, we choose + _PyParser_TokenNames[0] as a completely arbitrary pointer value + that is never written to. The default is to point to the + string "ENDMARKER". We change it temporarily to point to the + next character in that string. (Yes, I know it's REALLY + obscure.) + + In Python >= 3.8, this string array is no longer writable, so + instead we pick PyCapsuleType.tp_version_tag. We can't change + Python < 3.8 because someone might use a mixture of cffi + embedded modules, some of which were compiled before this file + changed. + */ + +#ifdef WITH_THREAD +# if PY_VERSION_HEX < 0x03080000 + char *volatile *lock = (char *volatile *)_PyParser_TokenNames; + char *old_value, *locked_value; + + while (1) { /* spin loop */ + old_value = *lock; + locked_value = old_value + 1; + if (old_value[0] == 'E') { + assert(old_value[1] == 'N'); + if (cffi_compare_and_swap(lock, old_value, locked_value)) + break; + } + else { + assert(old_value[0] == 'N'); + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: PyEval_InitThreads() should be very fast, and + this is only run at start-up anyway. */ + } + } +# else + int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; + int old_value, locked_value; + assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); + + while (1) { /* spin loop */ + old_value = *lock; + locked_value = -42; + if (old_value == 0) { + if (cffi_compare_and_swap(lock, old_value, locked_value)) + break; + } + else { + assert(old_value == locked_value); + /* should ideally do a spin loop instruction here, but + hard to do it portably and doesn't really matter I + think: PyEval_InitThreads() should be very fast, and + this is only run at start-up anyway. */ + } + } +# endif +#endif + + /* call Py_InitializeEx() */ + if (!Py_IsInitialized()) { + _cffi_py_initialize(); +#if PY_VERSION_HEX < 0x03070000 + PyEval_InitThreads(); +#endif + PyEval_SaveThread(); /* release the GIL */ + /* the returned tstate must be the one that has been stored into the + autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */ + } + else { +#if PY_VERSION_HEX < 0x03070000 + /* PyEval_InitThreads() is always a no-op from CPython 3.7 */ + PyGILState_STATE state = PyGILState_Ensure(); + PyEval_InitThreads(); + PyGILState_Release(state); +#endif + } + +#ifdef WITH_THREAD + /* release the lock */ + while (!cffi_compare_and_swap(lock, locked_value, old_value)) + ; +#endif + + return 0; +} + +/********** end CPython-specific section **********/ + + +#else + + +/********** PyPy-specific section **********/ + +PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */ + +static struct _cffi_pypy_init_s { + const char *name; + void *func; /* function pointer */ + const char *code; +} _cffi_pypy_init = { + _CFFI_MODULE_NAME, + _CFFI_PYTHON_STARTUP_FUNC, + _CFFI_PYTHON_STARTUP_CODE, +}; + +extern int pypy_carefully_make_gil(const char *); +extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); + +static int _cffi_carefully_make_gil(void) +{ + return pypy_carefully_make_gil(_CFFI_MODULE_NAME); +} + +static int _cffi_initialize_python(void) +{ + return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); +} + +/********** end PyPy-specific section **********/ + + +#endif + + +#ifdef __GNUC__ +__attribute__((noinline)) +#endif +static _cffi_call_python_fnptr _cffi_start_python(void) +{ + /* Delicate logic to initialize Python. This function can be + called multiple times concurrently, e.g. when the process calls + its first ``extern "Python"`` functions in multiple threads at + once. It can also be called recursively, in which case we must + ignore it. We also have to consider what occurs if several + different cffi-based extensions reach this code in parallel + threads---it is a different copy of the code, then, and we + can't have any shared global variable unless it comes from + 'libpythonX.Y.so'. + + Idea: + + * _cffi_carefully_make_gil(): "carefully" call + PyEval_InitThreads() (possibly with Py_InitializeEx() first). + + * then we use a (local) custom lock to make sure that a call to this + cffi-based extension will wait if another call to the *same* + extension is running the initialization in another thread. + It is reentrant, so that a recursive call will not block, but + only one from a different thread. + + * then we grab the GIL and (Python 2) we call Py_InitializeEx(). + At this point, concurrent calls to Py_InitializeEx() are not + possible: we have the GIL. + + * do the rest of the specific initialization, which may + temporarily release the GIL but not the custom lock. + Only release the custom lock when we are done. + */ + static char called = 0; + + if (_cffi_carefully_make_gil() != 0) + return NULL; + + _cffi_acquire_reentrant_mutex(); + + /* Here the GIL exists, but we don't have it. We're only protected + from concurrency by the reentrant mutex. */ + + /* This file only initializes the embedded module once, the first + time this is called, even if there are subinterpreters. */ + if (!called) { + called = 1; /* invoke _cffi_initialize_python() only once, + but don't set '_cffi_call_python' right now, + otherwise concurrent threads won't call + this function at all (we need them to wait) */ + if (_cffi_initialize_python() == 0) { + /* now initialization is finished. Switch to the fast-path. */ + + /* We would like nobody to see the new value of + '_cffi_call_python' without also seeing the rest of the + data initialized. However, this is not possible. But + the new value of '_cffi_call_python' is the function + 'cffi_call_python()' from _cffi_backend. So: */ + cffi_write_barrier(); + /* ^^^ we put a write barrier here, and a corresponding + read barrier at the start of cffi_call_python(). This + ensures that after that read barrier, we see everything + done here before the write barrier. + */ + + assert(_cffi_call_python_org != NULL); + _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; + } + else { + /* initialization failed. Reset this to NULL, even if it was + already set to some other value. Future calls to + _cffi_start_python() are still forced to occur, and will + always return NULL from now on. */ + _cffi_call_python_org = NULL; + } + } + + _cffi_release_reentrant_mutex(); + + return (_cffi_call_python_fnptr)_cffi_call_python_org; +} + +static +void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) +{ + _cffi_call_python_fnptr fnptr; + int current_err = errno; +#ifdef _MSC_VER + int current_lasterr = GetLastError(); +#endif + fnptr = _cffi_start_python(); + if (fnptr == NULL) { + fprintf(stderr, "function %s() called, but initialization code " + "failed. Returning 0.\n", externpy->name); + memset(args, 0, externpy->size_of_result); + } +#ifdef _MSC_VER + SetLastError(current_lasterr); +#endif + errno = current_err; + + if (fnptr != NULL) + fnptr(externpy, args); +} + + +/* The cffi_start_python() function makes sure Python is initialized + and our cffi module is set up. It can be called manually from the + user C code. The same effect is obtained automatically from any + dll-exported ``extern "Python"`` function. This function returns + -1 if initialization failed, 0 if all is OK. */ +_CFFI_UNUSED_FN +static int cffi_start_python(void) +{ + if (_cffi_call_python == &_cffi_start_and_call_python) { + if (_cffi_start_python() == NULL) + return -1; + } + cffi_read_barrier(); + return 0; +} + +#undef cffi_compare_and_swap +#undef cffi_write_barrier +#undef cffi_read_barrier + +#ifdef __cplusplus +} +#endif diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/api.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/api.py new file mode 100644 index 00000000..999a8aef --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/api.py @@ -0,0 +1,965 @@ +import sys, types +from .lock import allocate_lock +from .error import CDefError +from . import model + +try: + callable +except NameError: + # Python 3.1 + from collections import Callable + callable = lambda x: isinstance(x, Callable) + +try: + basestring +except NameError: + # Python 3.x + basestring = str + +_unspecified = object() + + + +class FFI(object): + r''' + The main top-level class that you instantiate once, or once per module. + + Example usage: + + ffi = FFI() + ffi.cdef(""" + int printf(const char *, ...); + """) + + C = ffi.dlopen(None) # standard library + -or- + C = ffi.verify() # use a C compiler: verify the decl above is right + + C.printf("hello, %s!\n", ffi.new("char[]", "world")) + ''' + + def __init__(self, backend=None): + """Create an FFI instance. The 'backend' argument is used to + select a non-default backend, mostly for tests. + """ + if backend is None: + # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with + # _cffi_backend.so compiled. + import _cffi_backend as backend + from . import __version__ + if backend.__version__ != __version__: + # bad version! Try to be as explicit as possible. + if hasattr(backend, '__file__'): + # CPython + raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. When we import the top-level '_cffi_backend' extension module, we get version %s, located in %r. The two versions should be equal; check your installation." % ( + __version__, __file__, + backend.__version__, backend.__file__)) + else: + # PyPy + raise Exception("Version mismatch: this is the 'cffi' package version %s, located in %r. This interpreter comes with a built-in '_cffi_backend' module, which is version %s. The two versions should be equal; check your installation." % ( + __version__, __file__, backend.__version__)) + # (If you insist you can also try to pass the option + # 'backend=backend_ctypes.CTypesBackend()', but don't + # rely on it! It's probably not going to work well.) + + from . import cparser + self._backend = backend + self._lock = allocate_lock() + self._parser = cparser.Parser() + self._cached_btypes = {} + self._parsed_types = types.ModuleType('parsed_types').__dict__ + self._new_types = types.ModuleType('new_types').__dict__ + self._function_caches = [] + self._libraries = [] + self._cdefsources = [] + self._included_ffis = [] + self._windows_unicode = None + self._init_once_cache = {} + self._cdef_version = None + self._embedding = None + self._typecache = model.get_typecache(backend) + if hasattr(backend, 'set_ffi'): + backend.set_ffi(self) + for name in list(backend.__dict__): + if name.startswith('RTLD_'): + setattr(self, name, getattr(backend, name)) + # + with self._lock: + self.BVoidP = self._get_cached_btype(model.voidp_type) + self.BCharA = self._get_cached_btype(model.char_array_type) + if isinstance(backend, types.ModuleType): + # _cffi_backend: attach these constants to the class + if not hasattr(FFI, 'NULL'): + FFI.NULL = self.cast(self.BVoidP, 0) + FFI.CData, FFI.CType = backend._get_types() + else: + # ctypes backend: attach these constants to the instance + self.NULL = self.cast(self.BVoidP, 0) + self.CData, self.CType = backend._get_types() + self.buffer = backend.buffer + + def cdef(self, csource, override=False, packed=False, pack=None): + """Parse the given C source. This registers all declared functions, + types, and global variables. The functions and global variables can + then be accessed via either 'ffi.dlopen()' or 'ffi.verify()'. + The types can be used in 'ffi.new()' and other functions. + If 'packed' is specified as True, all structs declared inside this + cdef are packed, i.e. laid out without any field alignment at all. + Alternatively, 'pack' can be a small integer, and requests for + alignment greater than that are ignored (pack=1 is equivalent to + packed=True). + """ + self._cdef(csource, override=override, packed=packed, pack=pack) + + def embedding_api(self, csource, packed=False, pack=None): + self._cdef(csource, packed=packed, pack=pack, dllexport=True) + if self._embedding is None: + self._embedding = '' + + def _cdef(self, csource, override=False, **options): + if not isinstance(csource, str): # unicode, on Python 2 + if not isinstance(csource, basestring): + raise TypeError("cdef() argument must be a string") + csource = csource.encode('ascii') + with self._lock: + self._cdef_version = object() + self._parser.parse(csource, override=override, **options) + self._cdefsources.append(csource) + if override: + for cache in self._function_caches: + cache.clear() + finishlist = self._parser._recomplete + if finishlist: + self._parser._recomplete = [] + for tp in finishlist: + tp.finish_backend_type(self, finishlist) + + def dlopen(self, name, flags=0): + """Load and return a dynamic library identified by 'name'. + The standard C library can be loaded by passing None. + Note that functions and types declared by 'ffi.cdef()' are not + linked to a particular library, just like C headers; in the + library we only look for the actual (untyped) symbols. + """ + if not (isinstance(name, basestring) or + name is None or + isinstance(name, self.CData)): + raise TypeError("dlopen(name): name must be a file name, None, " + "or an already-opened 'void *' handle") + with self._lock: + lib, function_cache = _make_ffi_library(self, name, flags) + self._function_caches.append(function_cache) + self._libraries.append(lib) + return lib + + def dlclose(self, lib): + """Close a library obtained with ffi.dlopen(). After this call, + access to functions or variables from the library will fail + (possibly with a segmentation fault). + """ + type(lib).__cffi_close__(lib) + + def _typeof_locked(self, cdecl): + # call me with the lock! + key = cdecl + if key in self._parsed_types: + return self._parsed_types[key] + # + if not isinstance(cdecl, str): # unicode, on Python 2 + cdecl = cdecl.encode('ascii') + # + type = self._parser.parse_type(cdecl) + really_a_function_type = type.is_raw_function + if really_a_function_type: + type = type.as_function_pointer() + btype = self._get_cached_btype(type) + result = btype, really_a_function_type + self._parsed_types[key] = result + return result + + def _typeof(self, cdecl, consider_function_as_funcptr=False): + # string -> ctype object + try: + result = self._parsed_types[cdecl] + except KeyError: + with self._lock: + result = self._typeof_locked(cdecl) + # + btype, really_a_function_type = result + if really_a_function_type and not consider_function_as_funcptr: + raise CDefError("the type %r is a function type, not a " + "pointer-to-function type" % (cdecl,)) + return btype + + def typeof(self, cdecl): + """Parse the C type given as a string and return the + corresponding object. + It can also be used on 'cdata' instance to get its C type. + """ + if isinstance(cdecl, basestring): + return self._typeof(cdecl) + if isinstance(cdecl, self.CData): + return self._backend.typeof(cdecl) + if isinstance(cdecl, types.BuiltinFunctionType): + res = _builtin_function_type(cdecl) + if res is not None: + return res + if (isinstance(cdecl, types.FunctionType) + and hasattr(cdecl, '_cffi_base_type')): + with self._lock: + return self._get_cached_btype(cdecl._cffi_base_type) + raise TypeError(type(cdecl)) + + def sizeof(self, cdecl): + """Return the size in bytes of the argument. It can be a + string naming a C type, or a 'cdata' instance. + """ + if isinstance(cdecl, basestring): + BType = self._typeof(cdecl) + return self._backend.sizeof(BType) + else: + return self._backend.sizeof(cdecl) + + def alignof(self, cdecl): + """Return the natural alignment size in bytes of the C type + given as a string. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.alignof(cdecl) + + def offsetof(self, cdecl, *fields_or_indexes): + """Return the offset of the named field inside the given + structure or array, which must be given as a C type name. + You can give several field names in case of nested structures. + You can also give numeric values which correspond to array + items, in case of an array type. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._typeoffsetof(cdecl, *fields_or_indexes)[1] + + def new(self, cdecl, init=None): + """Allocate an instance according to the specified C type and + return a pointer to it. The specified C type must be either a + pointer or an array: ``new('X *')`` allocates an X and returns + a pointer to it, whereas ``new('X[n]')`` allocates an array of + n X'es and returns an array referencing it (which works + mostly like a pointer, like in C). You can also use + ``new('X[]', n)`` to allocate an array of a non-constant + length n. + + The memory is initialized following the rules of declaring a + global variable in C: by default it is zero-initialized, but + an explicit initializer can be given which can be used to + fill all or part of the memory. + + When the returned object goes out of scope, the memory + is freed. In other words the returned object has + ownership of the value of type 'cdecl' that it points to. This + means that the raw data can be used as long as this object is + kept alive, but must not be used for a longer time. Be careful + about that when copying the pointer to the memory somewhere + else, e.g. into another structure. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.newp(cdecl, init) + + def new_allocator(self, alloc=None, free=None, + should_clear_after_alloc=True): + """Return a new allocator, i.e. a function that behaves like ffi.new() + but uses the provided low-level 'alloc' and 'free' functions. + + 'alloc' is called with the size as argument. If it returns NULL, a + MemoryError is raised. 'free' is called with the result of 'alloc' + as argument. Both can be either Python function or directly C + functions. If 'free' is None, then no free function is called. + If both 'alloc' and 'free' are None, the default is used. + + If 'should_clear_after_alloc' is set to False, then the memory + returned by 'alloc' is assumed to be already cleared (or you are + fine with garbage); otherwise CFFI will clear it. + """ + compiled_ffi = self._backend.FFI() + allocator = compiled_ffi.new_allocator(alloc, free, + should_clear_after_alloc) + def allocate(cdecl, init=None): + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return allocator(cdecl, init) + return allocate + + def cast(self, cdecl, source): + """Similar to a C cast: returns an instance of the named C + type initialized with the given 'source'. The source is + casted between integers or pointers of any type. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.cast(cdecl, source) + + def string(self, cdata, maxlen=-1): + """Return a Python string (or unicode string) from the 'cdata'. + If 'cdata' is a pointer or array of characters or bytes, returns + the null-terminated string. The returned string extends until + the first null character, or at most 'maxlen' characters. If + 'cdata' is an array then 'maxlen' defaults to its length. + + If 'cdata' is a pointer or array of wchar_t, returns a unicode + string following the same rules. + + If 'cdata' is a single character or byte or a wchar_t, returns + it as a string or unicode string. + + If 'cdata' is an enum, returns the value of the enumerator as a + string, or 'NUMBER' if the value is out of range. + """ + return self._backend.string(cdata, maxlen) + + def unpack(self, cdata, length): + """Unpack an array of C data of the given length, + returning a Python string/unicode/list. + + If 'cdata' is a pointer to 'char', returns a byte string. + It does not stop at the first null. This is equivalent to: + ffi.buffer(cdata, length)[:] + + If 'cdata' is a pointer to 'wchar_t', returns a unicode string. + 'length' is measured in wchar_t's; it is not the size in bytes. + + If 'cdata' is a pointer to anything else, returns a list of + 'length' items. This is a faster equivalent to: + [cdata[i] for i in range(length)] + """ + return self._backend.unpack(cdata, length) + + #def buffer(self, cdata, size=-1): + # """Return a read-write buffer object that references the raw C data + # pointed to by the given 'cdata'. The 'cdata' must be a pointer or + # an array. Can be passed to functions expecting a buffer, or directly + # manipulated with: + # + # buf[:] get a copy of it in a regular string, or + # buf[idx] as a single character + # buf[:] = ... + # buf[idx] = ... change the content + # """ + # note that 'buffer' is a type, set on this instance by __init__ + + def from_buffer(self, cdecl, python_buffer=_unspecified, + require_writable=False): + """Return a cdata of the given type pointing to the data of the + given Python object, which must support the buffer interface. + Note that this is not meant to be used on the built-in types + str or unicode (you can build 'char[]' arrays explicitly) + but only on objects containing large quantities of raw data + in some other format, like 'array.array' or numpy arrays. + + The first argument is optional and default to 'char[]'. + """ + if python_buffer is _unspecified: + cdecl, python_buffer = self.BCharA, cdecl + elif isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + return self._backend.from_buffer(cdecl, python_buffer, + require_writable) + + def memmove(self, dest, src, n): + """ffi.memmove(dest, src, n) copies n bytes of memory from src to dest. + + Like the C function memmove(), the memory areas may overlap; + apart from that it behaves like the C function memcpy(). + + 'src' can be any cdata ptr or array, or any Python buffer object. + 'dest' can be any cdata ptr or array, or a writable Python buffer + object. The size to copy, 'n', is always measured in bytes. + + Unlike other methods, this one supports all Python buffer including + byte strings and bytearrays---but it still does not support + non-contiguous buffers. + """ + return self._backend.memmove(dest, src, n) + + def callback(self, cdecl, python_callable=None, error=None, onerror=None): + """Return a callback object or a decorator making such a + callback object. 'cdecl' must name a C function pointer type. + The callback invokes the specified 'python_callable' (which may + be provided either directly or via a decorator). Important: the + callback object must be manually kept alive for as long as the + callback may be invoked from the C level. + """ + def callback_decorator_wrap(python_callable): + if not callable(python_callable): + raise TypeError("the 'python_callable' argument " + "is not callable") + return self._backend.callback(cdecl, python_callable, + error, onerror) + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl, consider_function_as_funcptr=True) + if python_callable is None: + return callback_decorator_wrap # decorator mode + else: + return callback_decorator_wrap(python_callable) # direct mode + + def getctype(self, cdecl, replace_with=''): + """Return a string giving the C type 'cdecl', which may be itself + a string or a object. If 'replace_with' is given, it gives + extra text to append (or insert for more complicated C types), like + a variable name, or '*' to get actually the C type 'pointer-to-cdecl'. + """ + if isinstance(cdecl, basestring): + cdecl = self._typeof(cdecl) + replace_with = replace_with.strip() + if (replace_with.startswith('*') + and '&[' in self._backend.getcname(cdecl, '&')): + replace_with = '(%s)' % replace_with + elif replace_with and not replace_with[0] in '[(': + replace_with = ' ' + replace_with + return self._backend.getcname(cdecl, replace_with) + + def gc(self, cdata, destructor, size=0): + """Return a new cdata object that points to the same + data. Later, when this new cdata object is garbage-collected, + 'destructor(old_cdata_object)' will be called. + + The optional 'size' gives an estimate of the size, used to + trigger the garbage collection more eagerly. So far only used + on PyPy. It tells the GC that the returned object keeps alive + roughly 'size' bytes of external memory. + """ + return self._backend.gcp(cdata, destructor, size) + + def _get_cached_btype(self, type): + assert self._lock.acquire(False) is False + # call me with the lock! + try: + BType = self._cached_btypes[type] + except KeyError: + finishlist = [] + BType = type.get_cached_btype(self, finishlist) + for type in finishlist: + type.finish_backend_type(self, finishlist) + return BType + + def verify(self, source='', tmpdir=None, **kwargs): + """Verify that the current ffi signatures compile on this + machine, and return a dynamic library object. The dynamic + library can be used to call functions and access global + variables declared in this 'ffi'. The library is compiled + by the C compiler: it gives you C-level API compatibility + (including calling macros). This is unlike 'ffi.dlopen()', + which requires binary compatibility in the signatures. + """ + from .verifier import Verifier, _caller_dir_pycache + # + # If set_unicode(True) was called, insert the UNICODE and + # _UNICODE macro declarations + if self._windows_unicode: + self._apply_windows_unicode(kwargs) + # + # Set the tmpdir here, and not in Verifier.__init__: it picks + # up the caller's directory, which we want to be the caller of + # ffi.verify(), as opposed to the caller of Veritier(). + tmpdir = tmpdir or _caller_dir_pycache() + # + # Make a Verifier() and use it to load the library. + self.verifier = Verifier(self, source, tmpdir, **kwargs) + lib = self.verifier.load_library() + # + # Save the loaded library for keep-alive purposes, even + # if the caller doesn't keep it alive itself (it should). + self._libraries.append(lib) + return lib + + def _get_errno(self): + return self._backend.get_errno() + def _set_errno(self, errno): + self._backend.set_errno(errno) + errno = property(_get_errno, _set_errno, None, + "the value of 'errno' from/to the C calls") + + def getwinerror(self, code=-1): + return self._backend.getwinerror(code) + + def _pointer_to(self, ctype): + with self._lock: + return model.pointer_cache(self, ctype) + + def addressof(self, cdata, *fields_or_indexes): + """Return the address of a . + If 'fields_or_indexes' are given, returns the address of that + field or array item in the structure or array, recursively in + case of nested structures. + """ + try: + ctype = self._backend.typeof(cdata) + except TypeError: + if '__addressof__' in type(cdata).__dict__: + return type(cdata).__addressof__(cdata, *fields_or_indexes) + raise + if fields_or_indexes: + ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes) + else: + if ctype.kind == "pointer": + raise TypeError("addressof(pointer)") + offset = 0 + ctypeptr = self._pointer_to(ctype) + return self._backend.rawaddressof(ctypeptr, cdata, offset) + + def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes): + ctype, offset = self._backend.typeoffsetof(ctype, field_or_index) + for field1 in fields_or_indexes: + ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1) + offset += offset1 + return ctype, offset + + def include(self, ffi_to_include): + """Includes the typedefs, structs, unions and enums defined + in another FFI instance. Usage is similar to a #include in C, + where a part of the program might include types defined in + another part for its own usage. Note that the include() + method has no effect on functions, constants and global + variables, which must anyway be accessed directly from the + lib object returned by the original FFI instance. + """ + if not isinstance(ffi_to_include, FFI): + raise TypeError("ffi.include() expects an argument that is also of" + " type cffi.FFI, not %r" % ( + type(ffi_to_include).__name__,)) + if ffi_to_include is self: + raise ValueError("self.include(self)") + with ffi_to_include._lock: + with self._lock: + self._parser.include(ffi_to_include._parser) + self._cdefsources.append('[') + self._cdefsources.extend(ffi_to_include._cdefsources) + self._cdefsources.append(']') + self._included_ffis.append(ffi_to_include) + + def new_handle(self, x): + return self._backend.newp_handle(self.BVoidP, x) + + def from_handle(self, x): + return self._backend.from_handle(x) + + def release(self, x): + self._backend.release(x) + + def set_unicode(self, enabled_flag): + """Windows: if 'enabled_flag' is True, enable the UNICODE and + _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR + to be (pointers to) wchar_t. If 'enabled_flag' is False, + declare these types to be (pointers to) plain 8-bit characters. + This is mostly for backward compatibility; you usually want True. + """ + if self._windows_unicode is not None: + raise ValueError("set_unicode() can only be called once") + enabled_flag = bool(enabled_flag) + if enabled_flag: + self.cdef("typedef wchar_t TBYTE;" + "typedef wchar_t TCHAR;" + "typedef const wchar_t *LPCTSTR;" + "typedef const wchar_t *PCTSTR;" + "typedef wchar_t *LPTSTR;" + "typedef wchar_t *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + else: + self.cdef("typedef char TBYTE;" + "typedef char TCHAR;" + "typedef const char *LPCTSTR;" + "typedef const char *PCTSTR;" + "typedef char *LPTSTR;" + "typedef char *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + self._windows_unicode = enabled_flag + + def _apply_windows_unicode(self, kwds): + defmacros = kwds.get('define_macros', ()) + if not isinstance(defmacros, (list, tuple)): + raise TypeError("'define_macros' must be a list or tuple") + defmacros = list(defmacros) + [('UNICODE', '1'), + ('_UNICODE', '1')] + kwds['define_macros'] = defmacros + + def _apply_embedding_fix(self, kwds): + # must include an argument like "-lpython2.7" for the compiler + def ensure(key, value): + lst = kwds.setdefault(key, []) + if value not in lst: + lst.append(value) + # + if '__pypy__' in sys.builtin_module_names: + import os + if sys.platform == "win32": + # we need 'libpypy-c.lib'. Current distributions of + # pypy (>= 4.1) contain it as 'libs/python27.lib'. + pythonlib = "python{0[0]}{0[1]}".format(sys.version_info) + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'libs')) + else: + # we need 'libpypy-c.{so,dylib}', which should be by + # default located in 'sys.prefix/bin' for installed + # systems. + if sys.version_info < (3,): + pythonlib = "pypy-c" + else: + pythonlib = "pypy3-c" + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'bin')) + # On uninstalled pypy's, the libpypy-c is typically found in + # .../pypy/goal/. + if hasattr(sys, 'prefix'): + ensure('library_dirs', os.path.join(sys.prefix, 'pypy', 'goal')) + else: + if sys.platform == "win32": + template = "python%d%d" + if hasattr(sys, 'gettotalrefcount'): + template += '_d' + else: + try: + import sysconfig + except ImportError: # 2.6 + from distutils import sysconfig + template = "python%d.%d" + if sysconfig.get_config_var('DEBUG_EXT'): + template += sysconfig.get_config_var('DEBUG_EXT') + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + if hasattr(sys, 'abiflags'): + pythonlib += sys.abiflags + ensure('libraries', pythonlib) + if sys.platform == "win32": + ensure('extra_link_args', '/MANIFEST') + + def set_source(self, module_name, source, source_extension='.c', **kwds): + import os + if hasattr(self, '_assigned_source'): + raise ValueError("set_source() cannot be called several times " + "per ffi object") + if not isinstance(module_name, basestring): + raise TypeError("'module_name' must be a string") + if os.sep in module_name or (os.altsep and os.altsep in module_name): + raise ValueError("'module_name' must not contain '/': use a dotted " + "name to make a 'package.module' location") + self._assigned_source = (str(module_name), source, + source_extension, kwds) + + def set_source_pkgconfig(self, module_name, pkgconfig_libs, source, + source_extension='.c', **kwds): + from . import pkgconfig + if not isinstance(pkgconfig_libs, list): + raise TypeError("the pkgconfig_libs argument must be a list " + "of package names") + kwds2 = pkgconfig.flags_from_pkgconfig(pkgconfig_libs) + pkgconfig.merge_flags(kwds, kwds2) + self.set_source(module_name, source, source_extension, **kwds) + + def distutils_extension(self, tmpdir='build', verbose=True): + from distutils.dir_util import mkpath + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored + return self.verifier.get_extension() + raise ValueError("set_source() must be called before" + " distutils_extension()") + module_name, source, source_extension, kwds = self._assigned_source + if source is None: + raise TypeError("distutils_extension() is only for C extension " + "modules, not for dlopen()-style pure Python " + "modules") + mkpath(tmpdir) + ext, updated = recompile(self, module_name, + source, tmpdir=tmpdir, extradir=tmpdir, + source_extension=source_extension, + call_c_compiler=False, **kwds) + if verbose: + if updated: + sys.stderr.write("regenerated: %r\n" % (ext.sources[0],)) + else: + sys.stderr.write("not modified: %r\n" % (ext.sources[0],)) + return ext + + def emit_c_code(self, filename): + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before emit_c_code()") + module_name, source, source_extension, kwds = self._assigned_source + if source is None: + raise TypeError("emit_c_code() is only for C extension modules, " + "not for dlopen()-style pure Python modules") + recompile(self, module_name, source, + c_file=filename, call_c_compiler=False, **kwds) + + def emit_python_code(self, filename): + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before emit_c_code()") + module_name, source, source_extension, kwds = self._assigned_source + if source is not None: + raise TypeError("emit_python_code() is only for dlopen()-style " + "pure Python modules, not for C extension modules") + recompile(self, module_name, source, + c_file=filename, call_c_compiler=False, **kwds) + + def compile(self, tmpdir='.', verbose=0, target=None, debug=None): + """The 'target' argument gives the final file name of the + compiled DLL. Use '*' to force distutils' choice, suitable for + regular CPython C API modules. Use a file name ending in '.*' + to ask for the system's default extension for dynamic libraries + (.so/.dll/.dylib). + + The default is '*' when building a non-embedded C API extension, + and (module_name + '.*') when building an embedded library. + """ + from .recompiler import recompile + # + if not hasattr(self, '_assigned_source'): + raise ValueError("set_source() must be called before compile()") + module_name, source, source_extension, kwds = self._assigned_source + return recompile(self, module_name, source, tmpdir=tmpdir, + target=target, source_extension=source_extension, + compiler_verbose=verbose, debug=debug, **kwds) + + def init_once(self, func, tag): + # Read _init_once_cache[tag], which is either (False, lock) if + # we're calling the function now in some thread, or (True, result). + # Don't call setdefault() in most cases, to avoid allocating and + # immediately freeing a lock; but still use setdefaut() to avoid + # races. + try: + x = self._init_once_cache[tag] + except KeyError: + x = self._init_once_cache.setdefault(tag, (False, allocate_lock())) + # Common case: we got (True, result), so we return the result. + if x[0]: + return x[1] + # Else, it's a lock. Acquire it to serialize the following tests. + with x[1]: + # Read again from _init_once_cache the current status. + x = self._init_once_cache[tag] + if x[0]: + return x[1] + # Call the function and store the result back. + result = func() + self._init_once_cache[tag] = (True, result) + return result + + def embedding_init_code(self, pysource): + if self._embedding: + raise ValueError("embedding_init_code() can only be called once") + # fix 'pysource' before it gets dumped into the C file: + # - remove empty lines at the beginning, so it starts at "line 1" + # - dedent, if all non-empty lines are indented + # - check for SyntaxErrors + import re + match = re.match(r'\s*\n', pysource) + if match: + pysource = pysource[match.end():] + lines = pysource.splitlines() or [''] + prefix = re.match(r'\s*', lines[0]).group() + for i in range(1, len(lines)): + line = lines[i] + if line.rstrip(): + while not line.startswith(prefix): + prefix = prefix[:-1] + i = len(prefix) + lines = [line[i:]+'\n' for line in lines] + pysource = ''.join(lines) + # + compile(pysource, "cffi_init", "exec") + # + self._embedding = pysource + + def def_extern(self, *args, **kwds): + raise ValueError("ffi.def_extern() is only available on API-mode FFI " + "objects") + + def list_types(self): + """Returns the user type names known to this FFI instance. + This returns a tuple containing three lists of names: + (typedef_names, names_of_structs, names_of_unions) + """ + typedefs = [] + structs = [] + unions = [] + for key in self._parser._declarations: + if key.startswith('typedef '): + typedefs.append(key[8:]) + elif key.startswith('struct '): + structs.append(key[7:]) + elif key.startswith('union '): + unions.append(key[6:]) + typedefs.sort() + structs.sort() + unions.sort() + return (typedefs, structs, unions) + + +def _load_backend_lib(backend, name, flags): + import os + if not isinstance(name, basestring): + if sys.platform != "win32" or name is not None: + return backend.load_library(name, flags) + name = "c" # Windows: load_library(None) fails, but this works + # on Python 2 (backward compatibility hack only) + first_error = None + if '.' in name or '/' in name or os.sep in name: + try: + return backend.load_library(name, flags) + except OSError as e: + first_error = e + import ctypes.util + path = ctypes.util.find_library(name) + if path is None: + if name == "c" and sys.platform == "win32" and sys.version_info >= (3,): + raise OSError("dlopen(None) cannot work on Windows for Python 3 " + "(see http://bugs.python.org/issue23606)") + msg = ("ctypes.util.find_library() did not manage " + "to locate a library called %r" % (name,)) + if first_error is not None: + msg = "%s. Additionally, %s" % (first_error, msg) + raise OSError(msg) + return backend.load_library(path, flags) + +def _make_ffi_library(ffi, libname, flags): + backend = ffi._backend + backendlib = _load_backend_lib(backend, libname, flags) + # + def accessor_function(name): + key = 'function ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + value = backendlib.load_function(BType, name) + library.__dict__[name] = value + # + def accessor_variable(name): + key = 'variable ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + read_variable = backendlib.read_variable + write_variable = backendlib.write_variable + setattr(FFILibrary, name, property( + lambda self: read_variable(BType, name), + lambda self, value: write_variable(BType, name, value))) + # + def addressof_var(name): + try: + return addr_variables[name] + except KeyError: + with ffi._lock: + if name not in addr_variables: + key = 'variable ' + name + tp, _ = ffi._parser._declarations[key] + BType = ffi._get_cached_btype(tp) + if BType.kind != 'array': + BType = model.pointer_cache(ffi, BType) + p = backendlib.load_function(BType, name) + addr_variables[name] = p + return addr_variables[name] + # + def accessor_constant(name): + raise NotImplementedError("non-integer constant '%s' cannot be " + "accessed from a dlopen() library" % (name,)) + # + def accessor_int_constant(name): + library.__dict__[name] = ffi._parser._int_constants[name] + # + accessors = {} + accessors_version = [False] + addr_variables = {} + # + def update_accessors(): + if accessors_version[0] is ffi._cdef_version: + return + # + for key, (tp, _) in ffi._parser._declarations.items(): + if not isinstance(tp, model.EnumType): + tag, name = key.split(' ', 1) + if tag == 'function': + accessors[name] = accessor_function + elif tag == 'variable': + accessors[name] = accessor_variable + elif tag == 'constant': + accessors[name] = accessor_constant + else: + for i, enumname in enumerate(tp.enumerators): + def accessor_enum(name, tp=tp, i=i): + tp.check_not_partial() + library.__dict__[name] = tp.enumvalues[i] + accessors[enumname] = accessor_enum + for name in ffi._parser._int_constants: + accessors.setdefault(name, accessor_int_constant) + accessors_version[0] = ffi._cdef_version + # + def make_accessor(name): + with ffi._lock: + if name in library.__dict__ or name in FFILibrary.__dict__: + return # added by another thread while waiting for the lock + if name not in accessors: + update_accessors() + if name not in accessors: + raise AttributeError(name) + accessors[name](name) + # + class FFILibrary(object): + def __getattr__(self, name): + make_accessor(name) + return getattr(self, name) + def __setattr__(self, name, value): + try: + property = getattr(self.__class__, name) + except AttributeError: + make_accessor(name) + setattr(self, name, value) + else: + property.__set__(self, value) + def __dir__(self): + with ffi._lock: + update_accessors() + return accessors.keys() + def __addressof__(self, name): + if name in library.__dict__: + return library.__dict__[name] + if name in FFILibrary.__dict__: + return addressof_var(name) + make_accessor(name) + if name in library.__dict__: + return library.__dict__[name] + if name in FFILibrary.__dict__: + return addressof_var(name) + raise AttributeError("cffi library has no function or " + "global variable named '%s'" % (name,)) + def __cffi_close__(self): + backendlib.close_lib() + self.__dict__.clear() + # + if isinstance(libname, basestring): + try: + if not isinstance(libname, str): # unicode, on Python 2 + libname = libname.encode('utf-8') + FFILibrary.__name__ = 'FFILibrary_%s' % libname + except UnicodeError: + pass + library = FFILibrary() + return library, library.__dict__ + +def _builtin_function_type(func): + # a hack to make at least ffi.typeof(builtin_function) work, + # if the builtin function was obtained by 'vengine_cpy'. + import sys + try: + module = sys.modules[func.__module__] + ffi = module._cffi_original_ffi + types_of_builtin_funcs = module._cffi_types_of_builtin_funcs + tp = types_of_builtin_funcs[func] + except (KeyError, AttributeError, TypeError): + return None + else: + with ffi._lock: + return ffi._get_cached_btype(tp) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/backend_ctypes.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/backend_ctypes.py new file mode 100644 index 00000000..e7956a79 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/backend_ctypes.py @@ -0,0 +1,1121 @@ +import ctypes, ctypes.util, operator, sys +from . import model + +if sys.version_info < (3,): + bytechr = chr +else: + unicode = str + long = int + xrange = range + bytechr = lambda num: bytes([num]) + +class CTypesType(type): + pass + +class CTypesData(object): + __metaclass__ = CTypesType + __slots__ = ['__weakref__'] + __name__ = '' + + def __init__(self, *args): + raise TypeError("cannot instantiate %r" % (self.__class__,)) + + @classmethod + def _newp(cls, init): + raise TypeError("expected a pointer or array ctype, got '%s'" + % (cls._get_c_name(),)) + + @staticmethod + def _to_ctypes(value): + raise TypeError + + @classmethod + def _arg_to_ctypes(cls, *value): + try: + ctype = cls._ctype + except AttributeError: + raise TypeError("cannot create an instance of %r" % (cls,)) + if value: + res = cls._to_ctypes(*value) + if not isinstance(res, ctype): + res = cls._ctype(res) + else: + res = cls._ctype() + return res + + @classmethod + def _create_ctype_obj(cls, init): + if init is None: + return cls._arg_to_ctypes() + else: + return cls._arg_to_ctypes(init) + + @staticmethod + def _from_ctypes(ctypes_value): + raise TypeError + + @classmethod + def _get_c_name(cls, replace_with=''): + return cls._reftypename.replace(' &', replace_with) + + @classmethod + def _fix_class(cls): + cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) + cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) + cls.__module__ = 'ffi' + + def _get_own_repr(self): + raise NotImplementedError + + def _addr_repr(self, address): + if address == 0: + return 'NULL' + else: + if address < 0: + address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) + return '0x%x' % address + + def __repr__(self, c_name=None): + own = self._get_own_repr() + return '' % (c_name or self._get_c_name(), own) + + def _convert_to_address(self, BClass): + if BClass is None: + raise TypeError("cannot convert %r to an address" % ( + self._get_c_name(),)) + else: + raise TypeError("cannot convert %r to %r" % ( + self._get_c_name(), BClass._get_c_name())) + + @classmethod + def _get_size(cls): + return ctypes.sizeof(cls._ctype) + + def _get_size_of_instance(self): + return ctypes.sizeof(self._ctype) + + @classmethod + def _cast_from(cls, source): + raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) + + def _cast_to_integer(self): + return self._convert_to_address(None) + + @classmethod + def _alignment(cls): + return ctypes.alignment(cls._ctype) + + def __iter__(self): + raise TypeError("cdata %r does not support iteration" % ( + self._get_c_name()),) + + def _make_cmp(name): + cmpfunc = getattr(operator, name) + def cmp(self, other): + v_is_ptr = not isinstance(self, CTypesGenericPrimitive) + w_is_ptr = (isinstance(other, CTypesData) and + not isinstance(other, CTypesGenericPrimitive)) + if v_is_ptr and w_is_ptr: + return cmpfunc(self._convert_to_address(None), + other._convert_to_address(None)) + elif v_is_ptr or w_is_ptr: + return NotImplemented + else: + if isinstance(self, CTypesGenericPrimitive): + self = self._value + if isinstance(other, CTypesGenericPrimitive): + other = other._value + return cmpfunc(self, other) + cmp.func_name = name + return cmp + + __eq__ = _make_cmp('__eq__') + __ne__ = _make_cmp('__ne__') + __lt__ = _make_cmp('__lt__') + __le__ = _make_cmp('__le__') + __gt__ = _make_cmp('__gt__') + __ge__ = _make_cmp('__ge__') + + def __hash__(self): + return hash(self._convert_to_address(None)) + + def _to_string(self, maxlen): + raise TypeError("string(): %r" % (self,)) + + +class CTypesGenericPrimitive(CTypesData): + __slots__ = [] + + def __hash__(self): + return hash(self._value) + + def _get_own_repr(self): + return repr(self._from_ctypes(self._value)) + + +class CTypesGenericArray(CTypesData): + __slots__ = [] + + @classmethod + def _newp(cls, init): + return cls(init) + + def __iter__(self): + for i in xrange(len(self)): + yield self[i] + + def _get_own_repr(self): + return self._addr_repr(ctypes.addressof(self._blob)) + + +class CTypesGenericPtr(CTypesData): + __slots__ = ['_address', '_as_ctype_ptr'] + _automatic_casts = False + kind = "pointer" + + @classmethod + def _newp(cls, init): + return cls(init) + + @classmethod + def _cast_from(cls, source): + if source is None: + address = 0 + elif isinstance(source, CTypesData): + address = source._cast_to_integer() + elif isinstance(source, (int, long)): + address = source + else: + raise TypeError("bad type for cast to %r: %r" % + (cls, type(source).__name__)) + return cls._new_pointer_at(address) + + @classmethod + def _new_pointer_at(cls, address): + self = cls.__new__(cls) + self._address = address + self._as_ctype_ptr = ctypes.cast(address, cls._ctype) + return self + + def _get_own_repr(self): + try: + return self._addr_repr(self._address) + except AttributeError: + return '???' + + def _cast_to_integer(self): + return self._address + + def __nonzero__(self): + return bool(self._address) + __bool__ = __nonzero__ + + @classmethod + def _to_ctypes(cls, value): + if not isinstance(value, CTypesData): + raise TypeError("unexpected %s object" % type(value).__name__) + address = value._convert_to_address(cls) + return ctypes.cast(address, cls._ctype) + + @classmethod + def _from_ctypes(cls, ctypes_ptr): + address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 + return cls._new_pointer_at(address) + + @classmethod + def _initialize(cls, ctypes_ptr, value): + if value: + ctypes_ptr.contents = cls._to_ctypes(value).contents + + def _convert_to_address(self, BClass): + if (BClass in (self.__class__, None) or BClass._automatic_casts + or self._automatic_casts): + return self._address + else: + return CTypesData._convert_to_address(self, BClass) + + +class CTypesBaseStructOrUnion(CTypesData): + __slots__ = ['_blob'] + + @classmethod + def _create_ctype_obj(cls, init): + # may be overridden + raise TypeError("cannot instantiate opaque type %s" % (cls,)) + + def _get_own_repr(self): + return self._addr_repr(ctypes.addressof(self._blob)) + + @classmethod + def _offsetof(cls, fieldname): + return getattr(cls._ctype, fieldname).offset + + def _convert_to_address(self, BClass): + if getattr(BClass, '_BItem', None) is self.__class__: + return ctypes.addressof(self._blob) + else: + return CTypesData._convert_to_address(self, BClass) + + @classmethod + def _from_ctypes(cls, ctypes_struct_or_union): + self = cls.__new__(cls) + self._blob = ctypes_struct_or_union + return self + + @classmethod + def _to_ctypes(cls, value): + return value._blob + + def __repr__(self, c_name=None): + return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) + + +class CTypesBackend(object): + + PRIMITIVE_TYPES = { + 'char': ctypes.c_char, + 'short': ctypes.c_short, + 'int': ctypes.c_int, + 'long': ctypes.c_long, + 'long long': ctypes.c_longlong, + 'signed char': ctypes.c_byte, + 'unsigned char': ctypes.c_ubyte, + 'unsigned short': ctypes.c_ushort, + 'unsigned int': ctypes.c_uint, + 'unsigned long': ctypes.c_ulong, + 'unsigned long long': ctypes.c_ulonglong, + 'float': ctypes.c_float, + 'double': ctypes.c_double, + '_Bool': ctypes.c_bool, + } + + for _name in ['unsigned long long', 'unsigned long', + 'unsigned int', 'unsigned short', 'unsigned char']: + _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) + PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_void_p): + PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_size_t): + PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] + + for _name in ['long long', 'long', 'int', 'short', 'signed char']: + _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) + PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_void_p): + PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] + PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] + if _size == ctypes.sizeof(ctypes.c_size_t): + PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] + + + def __init__(self): + self.RTLD_LAZY = 0 # not supported anyway by ctypes + self.RTLD_NOW = 0 + self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL + self.RTLD_LOCAL = ctypes.RTLD_LOCAL + + def set_ffi(self, ffi): + self.ffi = ffi + + def _get_types(self): + return CTypesData, CTypesType + + def load_library(self, path, flags=0): + cdll = ctypes.CDLL(path, flags) + return CTypesLibrary(self, cdll) + + def new_void_type(self): + class CTypesVoid(CTypesData): + __slots__ = [] + _reftypename = 'void &' + @staticmethod + def _from_ctypes(novalue): + return None + @staticmethod + def _to_ctypes(novalue): + if novalue is not None: + raise TypeError("None expected, got %s object" % + (type(novalue).__name__,)) + return None + CTypesVoid._fix_class() + return CTypesVoid + + def new_primitive_type(self, name): + if name == 'wchar_t': + raise NotImplementedError(name) + ctype = self.PRIMITIVE_TYPES[name] + if name == 'char': + kind = 'char' + elif name in ('float', 'double'): + kind = 'float' + else: + if name in ('signed char', 'unsigned char'): + kind = 'byte' + elif name == '_Bool': + kind = 'bool' + else: + kind = 'int' + is_signed = (ctype(-1).value == -1) + # + def _cast_source_to_int(source): + if isinstance(source, (int, long, float)): + source = int(source) + elif isinstance(source, CTypesData): + source = source._cast_to_integer() + elif isinstance(source, bytes): + source = ord(source) + elif source is None: + source = 0 + else: + raise TypeError("bad type for cast to %r: %r" % + (CTypesPrimitive, type(source).__name__)) + return source + # + kind1 = kind + class CTypesPrimitive(CTypesGenericPrimitive): + __slots__ = ['_value'] + _ctype = ctype + _reftypename = '%s &' % name + kind = kind1 + + def __init__(self, value): + self._value = value + + @staticmethod + def _create_ctype_obj(init): + if init is None: + return ctype() + return ctype(CTypesPrimitive._to_ctypes(init)) + + if kind == 'int' or kind == 'byte': + @classmethod + def _cast_from(cls, source): + source = _cast_source_to_int(source) + source = ctype(source).value # cast within range + return cls(source) + def __int__(self): + return self._value + + if kind == 'bool': + @classmethod + def _cast_from(cls, source): + if not isinstance(source, (int, long, float)): + source = _cast_source_to_int(source) + return cls(bool(source)) + def __int__(self): + return int(self._value) + + if kind == 'char': + @classmethod + def _cast_from(cls, source): + source = _cast_source_to_int(source) + source = bytechr(source & 0xFF) + return cls(source) + def __int__(self): + return ord(self._value) + + if kind == 'float': + @classmethod + def _cast_from(cls, source): + if isinstance(source, float): + pass + elif isinstance(source, CTypesGenericPrimitive): + if hasattr(source, '__float__'): + source = float(source) + else: + source = int(source) + else: + source = _cast_source_to_int(source) + source = ctype(source).value # fix precision + return cls(source) + def __int__(self): + return int(self._value) + def __float__(self): + return self._value + + _cast_to_integer = __int__ + + if kind == 'int' or kind == 'byte' or kind == 'bool': + @staticmethod + def _to_ctypes(x): + if not isinstance(x, (int, long)): + if isinstance(x, CTypesData): + x = int(x) + else: + raise TypeError("integer expected, got %s" % + type(x).__name__) + if ctype(x).value != x: + if not is_signed and x < 0: + raise OverflowError("%s: negative integer" % name) + else: + raise OverflowError("%s: integer out of bounds" + % name) + return x + + if kind == 'char': + @staticmethod + def _to_ctypes(x): + if isinstance(x, bytes) and len(x) == 1: + return x + if isinstance(x, CTypesPrimitive): # > + return x._value + raise TypeError("character expected, got %s" % + type(x).__name__) + def __nonzero__(self): + return ord(self._value) != 0 + else: + def __nonzero__(self): + return self._value != 0 + __bool__ = __nonzero__ + + if kind == 'float': + @staticmethod + def _to_ctypes(x): + if not isinstance(x, (int, long, float, CTypesData)): + raise TypeError("float expected, got %s" % + type(x).__name__) + return ctype(x).value + + @staticmethod + def _from_ctypes(value): + return getattr(value, 'value', value) + + @staticmethod + def _initialize(blob, init): + blob.value = CTypesPrimitive._to_ctypes(init) + + if kind == 'char': + def _to_string(self, maxlen): + return self._value + if kind == 'byte': + def _to_string(self, maxlen): + return chr(self._value & 0xff) + # + CTypesPrimitive._fix_class() + return CTypesPrimitive + + def new_pointer_type(self, BItem): + getbtype = self.ffi._get_cached_btype + if BItem is getbtype(model.PrimitiveType('char')): + kind = 'charp' + elif BItem in (getbtype(model.PrimitiveType('signed char')), + getbtype(model.PrimitiveType('unsigned char'))): + kind = 'bytep' + elif BItem is getbtype(model.void_type): + kind = 'voidp' + else: + kind = 'generic' + # + class CTypesPtr(CTypesGenericPtr): + __slots__ = ['_own'] + if kind == 'charp': + __slots__ += ['__as_strbuf'] + _BItem = BItem + if hasattr(BItem, '_ctype'): + _ctype = ctypes.POINTER(BItem._ctype) + _bitem_size = ctypes.sizeof(BItem._ctype) + else: + _ctype = ctypes.c_void_p + if issubclass(BItem, CTypesGenericArray): + _reftypename = BItem._get_c_name('(* &)') + else: + _reftypename = BItem._get_c_name(' * &') + + def __init__(self, init): + ctypeobj = BItem._create_ctype_obj(init) + if kind == 'charp': + self.__as_strbuf = ctypes.create_string_buffer( + ctypeobj.value + b'\x00') + self._as_ctype_ptr = ctypes.cast( + self.__as_strbuf, self._ctype) + else: + self._as_ctype_ptr = ctypes.pointer(ctypeobj) + self._address = ctypes.cast(self._as_ctype_ptr, + ctypes.c_void_p).value + self._own = True + + def __add__(self, other): + if isinstance(other, (int, long)): + return self._new_pointer_at(self._address + + other * self._bitem_size) + else: + return NotImplemented + + def __sub__(self, other): + if isinstance(other, (int, long)): + return self._new_pointer_at(self._address - + other * self._bitem_size) + elif type(self) is type(other): + return (self._address - other._address) // self._bitem_size + else: + return NotImplemented + + def __getitem__(self, index): + if getattr(self, '_own', False) and index != 0: + raise IndexError + return BItem._from_ctypes(self._as_ctype_ptr[index]) + + def __setitem__(self, index, value): + self._as_ctype_ptr[index] = BItem._to_ctypes(value) + + if kind == 'charp' or kind == 'voidp': + @classmethod + def _arg_to_ctypes(cls, *value): + if value and isinstance(value[0], bytes): + return ctypes.c_char_p(value[0]) + else: + return super(CTypesPtr, cls)._arg_to_ctypes(*value) + + if kind == 'charp' or kind == 'bytep': + def _to_string(self, maxlen): + if maxlen < 0: + maxlen = sys.maxsize + p = ctypes.cast(self._as_ctype_ptr, + ctypes.POINTER(ctypes.c_char)) + n = 0 + while n < maxlen and p[n] != b'\x00': + n += 1 + return b''.join([p[i] for i in range(n)]) + + def _get_own_repr(self): + if getattr(self, '_own', False): + return 'owning %d bytes' % ( + ctypes.sizeof(self._as_ctype_ptr.contents),) + return super(CTypesPtr, self)._get_own_repr() + # + if (BItem is self.ffi._get_cached_btype(model.void_type) or + BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): + CTypesPtr._automatic_casts = True + # + CTypesPtr._fix_class() + return CTypesPtr + + def new_array_type(self, CTypesPtr, length): + if length is None: + brackets = ' &[]' + else: + brackets = ' &[%d]' % length + BItem = CTypesPtr._BItem + getbtype = self.ffi._get_cached_btype + if BItem is getbtype(model.PrimitiveType('char')): + kind = 'char' + elif BItem in (getbtype(model.PrimitiveType('signed char')), + getbtype(model.PrimitiveType('unsigned char'))): + kind = 'byte' + else: + kind = 'generic' + # + class CTypesArray(CTypesGenericArray): + __slots__ = ['_blob', '_own'] + if length is not None: + _ctype = BItem._ctype * length + else: + __slots__.append('_ctype') + _reftypename = BItem._get_c_name(brackets) + _declared_length = length + _CTPtr = CTypesPtr + + def __init__(self, init): + if length is None: + if isinstance(init, (int, long)): + len1 = init + init = None + elif kind == 'char' and isinstance(init, bytes): + len1 = len(init) + 1 # extra null + else: + init = tuple(init) + len1 = len(init) + self._ctype = BItem._ctype * len1 + self._blob = self._ctype() + self._own = True + if init is not None: + self._initialize(self._blob, init) + + @staticmethod + def _initialize(blob, init): + if isinstance(init, bytes): + init = [init[i:i+1] for i in range(len(init))] + else: + if isinstance(init, CTypesGenericArray): + if (len(init) != len(blob) or + not isinstance(init, CTypesArray)): + raise TypeError("length/type mismatch: %s" % (init,)) + init = tuple(init) + if len(init) > len(blob): + raise IndexError("too many initializers") + addr = ctypes.cast(blob, ctypes.c_void_p).value + PTR = ctypes.POINTER(BItem._ctype) + itemsize = ctypes.sizeof(BItem._ctype) + for i, value in enumerate(init): + p = ctypes.cast(addr + i * itemsize, PTR) + BItem._initialize(p.contents, value) + + def __len__(self): + return len(self._blob) + + def __getitem__(self, index): + if not (0 <= index < len(self._blob)): + raise IndexError + return BItem._from_ctypes(self._blob[index]) + + def __setitem__(self, index, value): + if not (0 <= index < len(self._blob)): + raise IndexError + self._blob[index] = BItem._to_ctypes(value) + + if kind == 'char' or kind == 'byte': + def _to_string(self, maxlen): + if maxlen < 0: + maxlen = len(self._blob) + p = ctypes.cast(self._blob, + ctypes.POINTER(ctypes.c_char)) + n = 0 + while n < maxlen and p[n] != b'\x00': + n += 1 + return b''.join([p[i] for i in range(n)]) + + def _get_own_repr(self): + if getattr(self, '_own', False): + return 'owning %d bytes' % (ctypes.sizeof(self._blob),) + return super(CTypesArray, self)._get_own_repr() + + def _convert_to_address(self, BClass): + if BClass in (CTypesPtr, None) or BClass._automatic_casts: + return ctypes.addressof(self._blob) + else: + return CTypesData._convert_to_address(self, BClass) + + @staticmethod + def _from_ctypes(ctypes_array): + self = CTypesArray.__new__(CTypesArray) + self._blob = ctypes_array + return self + + @staticmethod + def _arg_to_ctypes(value): + return CTypesPtr._arg_to_ctypes(value) + + def __add__(self, other): + if isinstance(other, (int, long)): + return CTypesPtr._new_pointer_at( + ctypes.addressof(self._blob) + + other * ctypes.sizeof(BItem._ctype)) + else: + return NotImplemented + + @classmethod + def _cast_from(cls, source): + raise NotImplementedError("casting to %r" % ( + cls._get_c_name(),)) + # + CTypesArray._fix_class() + return CTypesArray + + def _new_struct_or_union(self, kind, name, base_ctypes_class): + # + class struct_or_union(base_ctypes_class): + pass + struct_or_union.__name__ = '%s_%s' % (kind, name) + kind1 = kind + # + class CTypesStructOrUnion(CTypesBaseStructOrUnion): + __slots__ = ['_blob'] + _ctype = struct_or_union + _reftypename = '%s &' % (name,) + _kind = kind = kind1 + # + CTypesStructOrUnion._fix_class() + return CTypesStructOrUnion + + def new_struct_type(self, name): + return self._new_struct_or_union('struct', name, ctypes.Structure) + + def new_union_type(self, name): + return self._new_struct_or_union('union', name, ctypes.Union) + + def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, + totalsize=-1, totalalignment=-1, sflags=0, + pack=0): + if totalsize >= 0 or totalalignment >= 0: + raise NotImplementedError("the ctypes backend of CFFI does not support " + "structures completed by verify(); please " + "compile and install the _cffi_backend module.") + struct_or_union = CTypesStructOrUnion._ctype + fnames = [fname for (fname, BField, bitsize) in fields] + btypes = [BField for (fname, BField, bitsize) in fields] + bitfields = [bitsize for (fname, BField, bitsize) in fields] + # + bfield_types = {} + cfields = [] + for (fname, BField, bitsize) in fields: + if bitsize < 0: + cfields.append((fname, BField._ctype)) + bfield_types[fname] = BField + else: + cfields.append((fname, BField._ctype, bitsize)) + bfield_types[fname] = Ellipsis + if sflags & 8: + struct_or_union._pack_ = 1 + elif pack: + struct_or_union._pack_ = pack + struct_or_union._fields_ = cfields + CTypesStructOrUnion._bfield_types = bfield_types + # + @staticmethod + def _create_ctype_obj(init): + result = struct_or_union() + if init is not None: + initialize(result, init) + return result + CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj + # + def initialize(blob, init): + if is_union: + if len(init) > 1: + raise ValueError("union initializer: %d items given, but " + "only one supported (use a dict if needed)" + % (len(init),)) + if not isinstance(init, dict): + if isinstance(init, (bytes, unicode)): + raise TypeError("union initializer: got a str") + init = tuple(init) + if len(init) > len(fnames): + raise ValueError("too many values for %s initializer" % + CTypesStructOrUnion._get_c_name()) + init = dict(zip(fnames, init)) + addr = ctypes.addressof(blob) + for fname, value in init.items(): + BField, bitsize = name2fieldtype[fname] + assert bitsize < 0, \ + "not implemented: initializer with bit fields" + offset = CTypesStructOrUnion._offsetof(fname) + PTR = ctypes.POINTER(BField._ctype) + p = ctypes.cast(addr + offset, PTR) + BField._initialize(p.contents, value) + is_union = CTypesStructOrUnion._kind == 'union' + name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) + # + for fname, BField, bitsize in fields: + if fname == '': + raise NotImplementedError("nested anonymous structs/unions") + if hasattr(CTypesStructOrUnion, fname): + raise ValueError("the field name %r conflicts in " + "the ctypes backend" % fname) + if bitsize < 0: + def getter(self, fname=fname, BField=BField, + offset=CTypesStructOrUnion._offsetof(fname), + PTR=ctypes.POINTER(BField._ctype)): + addr = ctypes.addressof(self._blob) + p = ctypes.cast(addr + offset, PTR) + return BField._from_ctypes(p.contents) + def setter(self, value, fname=fname, BField=BField): + setattr(self._blob, fname, BField._to_ctypes(value)) + # + if issubclass(BField, CTypesGenericArray): + setter = None + if BField._declared_length == 0: + def getter(self, fname=fname, BFieldPtr=BField._CTPtr, + offset=CTypesStructOrUnion._offsetof(fname), + PTR=ctypes.POINTER(BField._ctype)): + addr = ctypes.addressof(self._blob) + p = ctypes.cast(addr + offset, PTR) + return BFieldPtr._from_ctypes(p) + # + else: + def getter(self, fname=fname, BField=BField): + return BField._from_ctypes(getattr(self._blob, fname)) + def setter(self, value, fname=fname, BField=BField): + # xxx obscure workaround + value = BField._to_ctypes(value) + oldvalue = getattr(self._blob, fname) + setattr(self._blob, fname, value) + if value != getattr(self._blob, fname): + setattr(self._blob, fname, oldvalue) + raise OverflowError("value too large for bitfield") + setattr(CTypesStructOrUnion, fname, property(getter, setter)) + # + CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) + for fname in fnames: + if hasattr(CTypesPtr, fname): + raise ValueError("the field name %r conflicts in " + "the ctypes backend" % fname) + def getter(self, fname=fname): + return getattr(self[0], fname) + def setter(self, value, fname=fname): + setattr(self[0], fname, value) + setattr(CTypesPtr, fname, property(getter, setter)) + + def new_function_type(self, BArgs, BResult, has_varargs): + nameargs = [BArg._get_c_name() for BArg in BArgs] + if has_varargs: + nameargs.append('...') + nameargs = ', '.join(nameargs) + # + class CTypesFunctionPtr(CTypesGenericPtr): + __slots__ = ['_own_callback', '_name'] + _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), + *[BArg._ctype for BArg in BArgs], + use_errno=True) + _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) + + def __init__(self, init, error=None): + # create a callback to the Python callable init() + import traceback + assert not has_varargs, "varargs not supported for callbacks" + if getattr(BResult, '_ctype', None) is not None: + error = BResult._from_ctypes( + BResult._create_ctype_obj(error)) + else: + error = None + def callback(*args): + args2 = [] + for arg, BArg in zip(args, BArgs): + args2.append(BArg._from_ctypes(arg)) + try: + res2 = init(*args2) + res2 = BResult._to_ctypes(res2) + except: + traceback.print_exc() + res2 = error + if issubclass(BResult, CTypesGenericPtr): + if res2: + res2 = ctypes.cast(res2, ctypes.c_void_p).value + # .value: http://bugs.python.org/issue1574593 + else: + res2 = None + #print repr(res2) + return res2 + if issubclass(BResult, CTypesGenericPtr): + # The only pointers callbacks can return are void*s: + # http://bugs.python.org/issue5710 + callback_ctype = ctypes.CFUNCTYPE( + ctypes.c_void_p, + *[BArg._ctype for BArg in BArgs], + use_errno=True) + else: + callback_ctype = CTypesFunctionPtr._ctype + self._as_ctype_ptr = callback_ctype(callback) + self._address = ctypes.cast(self._as_ctype_ptr, + ctypes.c_void_p).value + self._own_callback = init + + @staticmethod + def _initialize(ctypes_ptr, value): + if value: + raise NotImplementedError("ctypes backend: not supported: " + "initializers for function pointers") + + def __repr__(self): + c_name = getattr(self, '_name', None) + if c_name: + i = self._reftypename.index('(* &)') + if self._reftypename[i-1] not in ' )*': + c_name = ' ' + c_name + c_name = self._reftypename.replace('(* &)', c_name) + return CTypesData.__repr__(self, c_name) + + def _get_own_repr(self): + if getattr(self, '_own_callback', None) is not None: + return 'calling %r' % (self._own_callback,) + return super(CTypesFunctionPtr, self)._get_own_repr() + + def __call__(self, *args): + if has_varargs: + assert len(args) >= len(BArgs) + extraargs = args[len(BArgs):] + args = args[:len(BArgs)] + else: + assert len(args) == len(BArgs) + ctypes_args = [] + for arg, BArg in zip(args, BArgs): + ctypes_args.append(BArg._arg_to_ctypes(arg)) + if has_varargs: + for i, arg in enumerate(extraargs): + if arg is None: + ctypes_args.append(ctypes.c_void_p(0)) # NULL + continue + if not isinstance(arg, CTypesData): + raise TypeError( + "argument %d passed in the variadic part " + "needs to be a cdata object (got %s)" % + (1 + len(BArgs) + i, type(arg).__name__)) + ctypes_args.append(arg._arg_to_ctypes(arg)) + result = self._as_ctype_ptr(*ctypes_args) + return BResult._from_ctypes(result) + # + CTypesFunctionPtr._fix_class() + return CTypesFunctionPtr + + def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): + assert isinstance(name, str) + reverse_mapping = dict(zip(reversed(enumvalues), + reversed(enumerators))) + # + class CTypesEnum(CTypesInt): + __slots__ = [] + _reftypename = '%s &' % name + + def _get_own_repr(self): + value = self._value + try: + return '%d: %s' % (value, reverse_mapping[value]) + except KeyError: + return str(value) + + def _to_string(self, maxlen): + value = self._value + try: + return reverse_mapping[value] + except KeyError: + return str(value) + # + CTypesEnum._fix_class() + return CTypesEnum + + def get_errno(self): + return ctypes.get_errno() + + def set_errno(self, value): + ctypes.set_errno(value) + + def string(self, b, maxlen=-1): + return b._to_string(maxlen) + + def buffer(self, bptr, size=-1): + raise NotImplementedError("buffer() with ctypes backend") + + def sizeof(self, cdata_or_BType): + if isinstance(cdata_or_BType, CTypesData): + return cdata_or_BType._get_size_of_instance() + else: + assert issubclass(cdata_or_BType, CTypesData) + return cdata_or_BType._get_size() + + def alignof(self, BType): + assert issubclass(BType, CTypesData) + return BType._alignment() + + def newp(self, BType, source): + if not issubclass(BType, CTypesData): + raise TypeError + return BType._newp(source) + + def cast(self, BType, source): + return BType._cast_from(source) + + def callback(self, BType, source, error, onerror): + assert onerror is None # XXX not implemented + return BType(source, error) + + _weakref_cache_ref = None + + def gcp(self, cdata, destructor, size=0): + if self._weakref_cache_ref is None: + import weakref + class MyRef(weakref.ref): + def __eq__(self, other): + myref = self() + return self is other or ( + myref is not None and myref is other()) + def __ne__(self, other): + return not (self == other) + def __hash__(self): + try: + return self._hash + except AttributeError: + self._hash = hash(self()) + return self._hash + self._weakref_cache_ref = {}, MyRef + weak_cache, MyRef = self._weakref_cache_ref + + if destructor is None: + try: + del weak_cache[MyRef(cdata)] + except KeyError: + raise TypeError("Can remove destructor only on a object " + "previously returned by ffi.gc()") + return None + + def remove(k): + cdata, destructor = weak_cache.pop(k, (None, None)) + if destructor is not None: + destructor(cdata) + + new_cdata = self.cast(self.typeof(cdata), cdata) + assert new_cdata is not cdata + weak_cache[MyRef(new_cdata, remove)] = (cdata, destructor) + return new_cdata + + typeof = type + + def getcname(self, BType, replace_with): + return BType._get_c_name(replace_with) + + def typeoffsetof(self, BType, fieldname, num=0): + if isinstance(fieldname, str): + if num == 0 and issubclass(BType, CTypesGenericPtr): + BType = BType._BItem + if not issubclass(BType, CTypesBaseStructOrUnion): + raise TypeError("expected a struct or union ctype") + BField = BType._bfield_types[fieldname] + if BField is Ellipsis: + raise TypeError("not supported for bitfields") + return (BField, BType._offsetof(fieldname)) + elif isinstance(fieldname, (int, long)): + if issubclass(BType, CTypesGenericArray): + BType = BType._CTPtr + if not issubclass(BType, CTypesGenericPtr): + raise TypeError("expected an array or ptr ctype") + BItem = BType._BItem + offset = BItem._get_size() * fieldname + if offset > sys.maxsize: + raise OverflowError + return (BItem, offset) + else: + raise TypeError(type(fieldname)) + + def rawaddressof(self, BTypePtr, cdata, offset=None): + if isinstance(cdata, CTypesBaseStructOrUnion): + ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) + elif isinstance(cdata, CTypesGenericPtr): + if offset is None or not issubclass(type(cdata)._BItem, + CTypesBaseStructOrUnion): + raise TypeError("unexpected cdata type") + ptr = type(cdata)._to_ctypes(cdata) + elif isinstance(cdata, CTypesGenericArray): + ptr = type(cdata)._to_ctypes(cdata) + else: + raise TypeError("expected a ") + if offset: + ptr = ctypes.cast( + ctypes.c_void_p( + ctypes.cast(ptr, ctypes.c_void_p).value + offset), + type(ptr)) + return BTypePtr._from_ctypes(ptr) + + +class CTypesLibrary(object): + + def __init__(self, backend, cdll): + self.backend = backend + self.cdll = cdll + + def load_function(self, BType, name): + c_func = getattr(self.cdll, name) + funcobj = BType._from_ctypes(c_func) + funcobj._name = name + return funcobj + + def read_variable(self, BType, name): + try: + ctypes_obj = BType._ctype.in_dll(self.cdll, name) + except AttributeError as e: + raise NotImplementedError(e) + return BType._from_ctypes(ctypes_obj) + + def write_variable(self, BType, name, value): + new_ctypes_obj = BType._to_ctypes(value) + ctypes_obj = BType._ctype.in_dll(self.cdll, name) + ctypes.memmove(ctypes.addressof(ctypes_obj), + ctypes.addressof(new_ctypes_obj), + ctypes.sizeof(BType._ctype)) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cffi_opcode.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cffi_opcode.py new file mode 100644 index 00000000..a0df98d1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cffi_opcode.py @@ -0,0 +1,187 @@ +from .error import VerificationError + +class CffiOp(object): + def __init__(self, op, arg): + self.op = op + self.arg = arg + + def as_c_expr(self): + if self.op is None: + assert isinstance(self.arg, str) + return '(_cffi_opcode_t)(%s)' % (self.arg,) + classname = CLASS_NAME[self.op] + return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) + + def as_python_bytes(self): + if self.op is None and self.arg.isdigit(): + value = int(self.arg) # non-negative: '-' not in self.arg + if value >= 2**31: + raise OverflowError("cannot emit %r: limited to 2**31-1" + % (self.arg,)) + return format_four_bytes(value) + if isinstance(self.arg, str): + raise VerificationError("cannot emit to Python: %r" % (self.arg,)) + return format_four_bytes((self.arg << 8) | self.op) + + def __str__(self): + classname = CLASS_NAME.get(self.op, self.op) + return '(%s %s)' % (classname, self.arg) + +def format_four_bytes(num): + return '\\x%02X\\x%02X\\x%02X\\x%02X' % ( + (num >> 24) & 0xFF, + (num >> 16) & 0xFF, + (num >> 8) & 0xFF, + (num ) & 0xFF) + +OP_PRIMITIVE = 1 +OP_POINTER = 3 +OP_ARRAY = 5 +OP_OPEN_ARRAY = 7 +OP_STRUCT_UNION = 9 +OP_ENUM = 11 +OP_FUNCTION = 13 +OP_FUNCTION_END = 15 +OP_NOOP = 17 +OP_BITFIELD = 19 +OP_TYPENAME = 21 +OP_CPYTHON_BLTN_V = 23 # varargs +OP_CPYTHON_BLTN_N = 25 # noargs +OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) +OP_CONSTANT = 29 +OP_CONSTANT_INT = 31 +OP_GLOBAL_VAR = 33 +OP_DLOPEN_FUNC = 35 +OP_DLOPEN_CONST = 37 +OP_GLOBAL_VAR_F = 39 +OP_EXTERN_PYTHON = 41 + +PRIM_VOID = 0 +PRIM_BOOL = 1 +PRIM_CHAR = 2 +PRIM_SCHAR = 3 +PRIM_UCHAR = 4 +PRIM_SHORT = 5 +PRIM_USHORT = 6 +PRIM_INT = 7 +PRIM_UINT = 8 +PRIM_LONG = 9 +PRIM_ULONG = 10 +PRIM_LONGLONG = 11 +PRIM_ULONGLONG = 12 +PRIM_FLOAT = 13 +PRIM_DOUBLE = 14 +PRIM_LONGDOUBLE = 15 + +PRIM_WCHAR = 16 +PRIM_INT8 = 17 +PRIM_UINT8 = 18 +PRIM_INT16 = 19 +PRIM_UINT16 = 20 +PRIM_INT32 = 21 +PRIM_UINT32 = 22 +PRIM_INT64 = 23 +PRIM_UINT64 = 24 +PRIM_INTPTR = 25 +PRIM_UINTPTR = 26 +PRIM_PTRDIFF = 27 +PRIM_SIZE = 28 +PRIM_SSIZE = 29 +PRIM_INT_LEAST8 = 30 +PRIM_UINT_LEAST8 = 31 +PRIM_INT_LEAST16 = 32 +PRIM_UINT_LEAST16 = 33 +PRIM_INT_LEAST32 = 34 +PRIM_UINT_LEAST32 = 35 +PRIM_INT_LEAST64 = 36 +PRIM_UINT_LEAST64 = 37 +PRIM_INT_FAST8 = 38 +PRIM_UINT_FAST8 = 39 +PRIM_INT_FAST16 = 40 +PRIM_UINT_FAST16 = 41 +PRIM_INT_FAST32 = 42 +PRIM_UINT_FAST32 = 43 +PRIM_INT_FAST64 = 44 +PRIM_UINT_FAST64 = 45 +PRIM_INTMAX = 46 +PRIM_UINTMAX = 47 +PRIM_FLOATCOMPLEX = 48 +PRIM_DOUBLECOMPLEX = 49 +PRIM_CHAR16 = 50 +PRIM_CHAR32 = 51 + +_NUM_PRIM = 52 +_UNKNOWN_PRIM = -1 +_UNKNOWN_FLOAT_PRIM = -2 +_UNKNOWN_LONG_DOUBLE = -3 + +_IO_FILE_STRUCT = -1 + +PRIMITIVE_TO_INDEX = { + 'char': PRIM_CHAR, + 'short': PRIM_SHORT, + 'int': PRIM_INT, + 'long': PRIM_LONG, + 'long long': PRIM_LONGLONG, + 'signed char': PRIM_SCHAR, + 'unsigned char': PRIM_UCHAR, + 'unsigned short': PRIM_USHORT, + 'unsigned int': PRIM_UINT, + 'unsigned long': PRIM_ULONG, + 'unsigned long long': PRIM_ULONGLONG, + 'float': PRIM_FLOAT, + 'double': PRIM_DOUBLE, + 'long double': PRIM_LONGDOUBLE, + 'float _Complex': PRIM_FLOATCOMPLEX, + 'double _Complex': PRIM_DOUBLECOMPLEX, + '_Bool': PRIM_BOOL, + 'wchar_t': PRIM_WCHAR, + 'char16_t': PRIM_CHAR16, + 'char32_t': PRIM_CHAR32, + 'int8_t': PRIM_INT8, + 'uint8_t': PRIM_UINT8, + 'int16_t': PRIM_INT16, + 'uint16_t': PRIM_UINT16, + 'int32_t': PRIM_INT32, + 'uint32_t': PRIM_UINT32, + 'int64_t': PRIM_INT64, + 'uint64_t': PRIM_UINT64, + 'intptr_t': PRIM_INTPTR, + 'uintptr_t': PRIM_UINTPTR, + 'ptrdiff_t': PRIM_PTRDIFF, + 'size_t': PRIM_SIZE, + 'ssize_t': PRIM_SSIZE, + 'int_least8_t': PRIM_INT_LEAST8, + 'uint_least8_t': PRIM_UINT_LEAST8, + 'int_least16_t': PRIM_INT_LEAST16, + 'uint_least16_t': PRIM_UINT_LEAST16, + 'int_least32_t': PRIM_INT_LEAST32, + 'uint_least32_t': PRIM_UINT_LEAST32, + 'int_least64_t': PRIM_INT_LEAST64, + 'uint_least64_t': PRIM_UINT_LEAST64, + 'int_fast8_t': PRIM_INT_FAST8, + 'uint_fast8_t': PRIM_UINT_FAST8, + 'int_fast16_t': PRIM_INT_FAST16, + 'uint_fast16_t': PRIM_UINT_FAST16, + 'int_fast32_t': PRIM_INT_FAST32, + 'uint_fast32_t': PRIM_UINT_FAST32, + 'int_fast64_t': PRIM_INT_FAST64, + 'uint_fast64_t': PRIM_UINT_FAST64, + 'intmax_t': PRIM_INTMAX, + 'uintmax_t': PRIM_UINTMAX, + } + +F_UNION = 0x01 +F_CHECK_FIELDS = 0x02 +F_PACKED = 0x04 +F_EXTERNAL = 0x08 +F_OPAQUE = 0x10 + +G_FLAGS = dict([('_CFFI_' + _key, globals()[_key]) + for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED', + 'F_EXTERNAL', 'F_OPAQUE']]) + +CLASS_NAME = {} +for _name, _value in list(globals().items()): + if _name.startswith('OP_') and isinstance(_value, int): + CLASS_NAME[_value] = _name[3:] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/commontypes.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/commontypes.py new file mode 100644 index 00000000..8ec97c75 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/commontypes.py @@ -0,0 +1,80 @@ +import sys +from . import model +from .error import FFIError + + +COMMON_TYPES = {} + +try: + # fetch "bool" and all simple Windows types + from _cffi_backend import _get_common_types + _get_common_types(COMMON_TYPES) +except ImportError: + pass + +COMMON_TYPES['FILE'] = model.unknown_type('FILE', '_IO_FILE') +COMMON_TYPES['bool'] = '_Bool' # in case we got ImportError above + +for _type in model.PrimitiveType.ALL_PRIMITIVE_TYPES: + if _type.endswith('_t'): + COMMON_TYPES[_type] = _type +del _type + +_CACHE = {} + +def resolve_common_type(parser, commontype): + try: + return _CACHE[commontype] + except KeyError: + cdecl = COMMON_TYPES.get(commontype, commontype) + if not isinstance(cdecl, str): + result, quals = cdecl, 0 # cdecl is already a BaseType + elif cdecl in model.PrimitiveType.ALL_PRIMITIVE_TYPES: + result, quals = model.PrimitiveType(cdecl), 0 + elif cdecl == 'set-unicode-needed': + raise FFIError("The Windows type %r is only available after " + "you call ffi.set_unicode()" % (commontype,)) + else: + if commontype == cdecl: + raise FFIError( + "Unsupported type: %r. Please look at " + "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations " + "and file an issue if you think this type should really " + "be supported." % (commontype,)) + result, quals = parser.parse_type_and_quals(cdecl) # recursive + + assert isinstance(result, model.BaseTypeByIdentity) + _CACHE[commontype] = result, quals + return result, quals + + +# ____________________________________________________________ +# extra types for Windows (most of them are in commontypes.c) + + +def win_common_types(): + return { + "UNICODE_STRING": model.StructType( + "_UNICODE_STRING", + ["Length", + "MaximumLength", + "Buffer"], + [model.PrimitiveType("unsigned short"), + model.PrimitiveType("unsigned short"), + model.PointerType(model.PrimitiveType("wchar_t"))], + [-1, -1, -1]), + "PUNICODE_STRING": "UNICODE_STRING *", + "PCUNICODE_STRING": "const UNICODE_STRING *", + + "TBYTE": "set-unicode-needed", + "TCHAR": "set-unicode-needed", + "LPCTSTR": "set-unicode-needed", + "PCTSTR": "set-unicode-needed", + "LPTSTR": "set-unicode-needed", + "PTSTR": "set-unicode-needed", + "PTBYTE": "set-unicode-needed", + "PTCHAR": "set-unicode-needed", + } + +if sys.platform == 'win32': + COMMON_TYPES.update(win_common_types()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cparser.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cparser.py new file mode 100644 index 00000000..74830e91 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/cparser.py @@ -0,0 +1,1006 @@ +from . import model +from .commontypes import COMMON_TYPES, resolve_common_type +from .error import FFIError, CDefError +try: + from . import _pycparser as pycparser +except ImportError: + import pycparser +import weakref, re, sys + +try: + if sys.version_info < (3,): + import thread as _thread + else: + import _thread + lock = _thread.allocate_lock() +except ImportError: + lock = None + +def _workaround_for_static_import_finders(): + # Issue #392: packaging tools like cx_Freeze can not find these + # because pycparser uses exec dynamic import. This is an obscure + # workaround. This function is never called. + import pycparser.yacctab + import pycparser.lextab + +CDEF_SOURCE_STRING = "" +_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", + re.DOTALL | re.MULTILINE) +_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" + r"\b((?:[^\n\\]|\\.)*?)$", + re.DOTALL | re.MULTILINE) +_r_line_directive = re.compile(r"^[ \t]*#[ \t]*(?:line|\d+)\b.*$", re.MULTILINE) +_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") +_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") +_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") +_r_words = re.compile(r"\w+|\S") +_parser_cache = None +_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE) +_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b") +_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b") +_r_cdecl = re.compile(r"\b__cdecl\b") +_r_extern_python = re.compile(r'\bextern\s*"' + r'(Python|Python\s*\+\s*C|C\s*\+\s*Python)"\s*.') +_r_star_const_space = re.compile( # matches "* const " + r"[*]\s*((const|volatile|restrict)\b\s*)+") +_r_int_dotdotdot = re.compile(r"(\b(int|long|short|signed|unsigned|char)\s*)+" + r"\.\.\.") +_r_float_dotdotdot = re.compile(r"\b(double|float)\s*\.\.\.") + +def _get_parser(): + global _parser_cache + if _parser_cache is None: + _parser_cache = pycparser.CParser() + return _parser_cache + +def _workaround_for_old_pycparser(csource): + # Workaround for a pycparser issue (fixed between pycparser 2.10 and + # 2.14): "char*const***" gives us a wrong syntax tree, the same as + # for "char***(*const)". This means we can't tell the difference + # afterwards. But "char(*const(***))" gives us the right syntax + # tree. The issue only occurs if there are several stars in + # sequence with no parenthesis inbetween, just possibly qualifiers. + # Attempt to fix it by adding some parentheses in the source: each + # time we see "* const" or "* const *", we add an opening + # parenthesis before each star---the hard part is figuring out where + # to close them. + parts = [] + while True: + match = _r_star_const_space.search(csource) + if not match: + break + #print repr(''.join(parts)+csource), '=>', + parts.append(csource[:match.start()]) + parts.append('('); closing = ')' + parts.append(match.group()) # e.g. "* const " + endpos = match.end() + if csource.startswith('*', endpos): + parts.append('('); closing += ')' + level = 0 + i = endpos + while i < len(csource): + c = csource[i] + if c == '(': + level += 1 + elif c == ')': + if level == 0: + break + level -= 1 + elif c in ',;=': + if level == 0: + break + i += 1 + csource = csource[endpos:i] + closing + csource[i:] + #print repr(''.join(parts)+csource) + parts.append(csource) + return ''.join(parts) + +def _preprocess_extern_python(csource): + # input: `extern "Python" int foo(int);` or + # `extern "Python" { int foo(int); }` + # output: + # void __cffi_extern_python_start; + # int foo(int); + # void __cffi_extern_python_stop; + # + # input: `extern "Python+C" int foo(int);` + # output: + # void __cffi_extern_python_plus_c_start; + # int foo(int); + # void __cffi_extern_python_stop; + parts = [] + while True: + match = _r_extern_python.search(csource) + if not match: + break + endpos = match.end() - 1 + #print + #print ''.join(parts)+csource + #print '=>' + parts.append(csource[:match.start()]) + if 'C' in match.group(1): + parts.append('void __cffi_extern_python_plus_c_start; ') + else: + parts.append('void __cffi_extern_python_start; ') + if csource[endpos] == '{': + # grouping variant + closing = csource.find('}', endpos) + if closing < 0: + raise CDefError("'extern \"Python\" {': no '}' found") + if csource.find('{', endpos + 1, closing) >= 0: + raise NotImplementedError("cannot use { } inside a block " + "'extern \"Python\" { ... }'") + parts.append(csource[endpos+1:closing]) + csource = csource[closing+1:] + else: + # non-grouping variant + semicolon = csource.find(';', endpos) + if semicolon < 0: + raise CDefError("'extern \"Python\": no ';' found") + parts.append(csource[endpos:semicolon+1]) + csource = csource[semicolon+1:] + parts.append(' void __cffi_extern_python_stop;') + #print ''.join(parts)+csource + #print + parts.append(csource) + return ''.join(parts) + +def _warn_for_string_literal(csource): + if '"' not in csource: + return + for line in csource.splitlines(): + if '"' in line and not line.lstrip().startswith('#'): + import warnings + warnings.warn("String literal found in cdef() or type source. " + "String literals are ignored here, but you should " + "remove them anyway because some character sequences " + "confuse pre-parsing.") + break + +def _warn_for_non_extern_non_static_global_variable(decl): + if not decl.storage: + import warnings + warnings.warn("Global variable '%s' in cdef(): for consistency " + "with C it should have a storage class specifier " + "(usually 'extern')" % (decl.name,)) + +def _remove_line_directives(csource): + # _r_line_directive matches whole lines, without the final \n, if they + # start with '#line' with some spacing allowed, or '#NUMBER'. This + # function stores them away and replaces them with exactly the string + # '#line@N', where N is the index in the list 'line_directives'. + line_directives = [] + def replace(m): + i = len(line_directives) + line_directives.append(m.group()) + return '#line@%d' % i + csource = _r_line_directive.sub(replace, csource) + return csource, line_directives + +def _put_back_line_directives(csource, line_directives): + def replace(m): + s = m.group() + if not s.startswith('#line@'): + raise AssertionError("unexpected #line directive " + "(should have been processed and removed") + return line_directives[int(s[6:])] + return _r_line_directive.sub(replace, csource) + +def _preprocess(csource): + # First, remove the lines of the form '#line N "filename"' because + # the "filename" part could confuse the rest + csource, line_directives = _remove_line_directives(csource) + # Remove comments. NOTE: this only work because the cdef() section + # should not contain any string literals (except in line directives)! + def replace_keeping_newlines(m): + return ' ' + m.group().count('\n') * '\n' + csource = _r_comment.sub(replace_keeping_newlines, csource) + # Remove the "#define FOO x" lines + macros = {} + for match in _r_define.finditer(csource): + macroname, macrovalue = match.groups() + macrovalue = macrovalue.replace('\\\n', '').strip() + macros[macroname] = macrovalue + csource = _r_define.sub('', csource) + # + if pycparser.__version__ < '2.14': + csource = _workaround_for_old_pycparser(csource) + # + # BIG HACK: replace WINAPI or __stdcall with "volatile const". + # It doesn't make sense for the return type of a function to be + # "volatile volatile const", so we abuse it to detect __stdcall... + # Hack number 2 is that "int(volatile *fptr)();" is not valid C + # syntax, so we place the "volatile" before the opening parenthesis. + csource = _r_stdcall2.sub(' volatile volatile const(', csource) + csource = _r_stdcall1.sub(' volatile volatile const ', csource) + csource = _r_cdecl.sub(' ', csource) + # + # Replace `extern "Python"` with start/end markers + csource = _preprocess_extern_python(csource) + # + # Now there should not be any string literal left; warn if we get one + _warn_for_string_literal(csource) + # + # Replace "[...]" with "[__dotdotdotarray__]" + csource = _r_partial_array.sub('[__dotdotdotarray__]', csource) + # + # Replace "...}" with "__dotdotdotNUM__}". This construction should + # occur only at the end of enums; at the end of structs we have "...;}" + # and at the end of vararg functions "...);". Also replace "=...[,}]" + # with ",__dotdotdotNUM__[,}]": this occurs in the enums too, when + # giving an unknown value. + matches = list(_r_partial_enum.finditer(csource)) + for number, match in enumerate(reversed(matches)): + p = match.start() + if csource[p] == '=': + p2 = csource.find('...', p, match.end()) + assert p2 > p + csource = '%s,__dotdotdot%d__ %s' % (csource[:p], number, + csource[p2+3:]) + else: + assert csource[p:p+3] == '...' + csource = '%s __dotdotdot%d__ %s' % (csource[:p], number, + csource[p+3:]) + # Replace "int ..." or "unsigned long int..." with "__dotdotdotint__" + csource = _r_int_dotdotdot.sub(' __dotdotdotint__ ', csource) + # Replace "float ..." or "double..." with "__dotdotdotfloat__" + csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource) + # Replace all remaining "..." with the same name, "__dotdotdot__", + # which is declared with a typedef for the purpose of C parsing. + csource = csource.replace('...', ' __dotdotdot__ ') + # Finally, put back the line directives + csource = _put_back_line_directives(csource, line_directives) + return csource, macros + +def _common_type_names(csource): + # Look in the source for what looks like usages of types from the + # list of common types. A "usage" is approximated here as the + # appearance of the word, minus a "definition" of the type, which + # is the last word in a "typedef" statement. Approximative only + # but should be fine for all the common types. + look_for_words = set(COMMON_TYPES) + look_for_words.add(';') + look_for_words.add(',') + look_for_words.add('(') + look_for_words.add(')') + look_for_words.add('typedef') + words_used = set() + is_typedef = False + paren = 0 + previous_word = '' + for word in _r_words.findall(csource): + if word in look_for_words: + if word == ';': + if is_typedef: + words_used.discard(previous_word) + look_for_words.discard(previous_word) + is_typedef = False + elif word == 'typedef': + is_typedef = True + paren = 0 + elif word == '(': + paren += 1 + elif word == ')': + paren -= 1 + elif word == ',': + if is_typedef and paren == 0: + words_used.discard(previous_word) + look_for_words.discard(previous_word) + else: # word in COMMON_TYPES + words_used.add(word) + previous_word = word + return words_used + + +class Parser(object): + + def __init__(self): + self._declarations = {} + self._included_declarations = set() + self._anonymous_counter = 0 + self._structnode2type = weakref.WeakKeyDictionary() + self._options = {} + self._int_constants = {} + self._recomplete = [] + self._uses_new_feature = None + + def _parse(self, csource): + csource, macros = _preprocess(csource) + # XXX: for more efficiency we would need to poke into the + # internals of CParser... the following registers the + # typedefs, because their presence or absence influences the + # parsing itself (but what they are typedef'ed to plays no role) + ctn = _common_type_names(csource) + typenames = [] + for name in sorted(self._declarations): + if name.startswith('typedef '): + name = name[8:] + typenames.append(name) + ctn.discard(name) + typenames += sorted(ctn) + # + csourcelines = [] + csourcelines.append('# 1 ""') + for typename in typenames: + csourcelines.append('typedef int %s;' % typename) + csourcelines.append('typedef int __dotdotdotint__, __dotdotdotfloat__,' + ' __dotdotdot__;') + # this forces pycparser to consider the following in the file + # called from line 1 + csourcelines.append('# 1 "%s"' % (CDEF_SOURCE_STRING,)) + csourcelines.append(csource) + fullcsource = '\n'.join(csourcelines) + if lock is not None: + lock.acquire() # pycparser is not thread-safe... + try: + ast = _get_parser().parse(fullcsource) + except pycparser.c_parser.ParseError as e: + self.convert_pycparser_error(e, csource) + finally: + if lock is not None: + lock.release() + # csource will be used to find buggy source text + return ast, macros, csource + + def _convert_pycparser_error(self, e, csource): + # xxx look for ":NUM:" at the start of str(e) + # and interpret that as a line number. This will not work if + # the user gives explicit ``# NUM "FILE"`` directives. + line = None + msg = str(e) + match = re.match(r"%s:(\d+):" % (CDEF_SOURCE_STRING,), msg) + if match: + linenum = int(match.group(1), 10) + csourcelines = csource.splitlines() + if 1 <= linenum <= len(csourcelines): + line = csourcelines[linenum-1] + return line + + def convert_pycparser_error(self, e, csource): + line = self._convert_pycparser_error(e, csource) + + msg = str(e) + if line: + msg = 'cannot parse "%s"\n%s' % (line.strip(), msg) + else: + msg = 'parse error\n%s' % (msg,) + raise CDefError(msg) + + def parse(self, csource, override=False, packed=False, pack=None, + dllexport=False): + if packed: + if packed != True: + raise ValueError("'packed' should be False or True; use " + "'pack' to give another value") + if pack: + raise ValueError("cannot give both 'pack' and 'packed'") + pack = 1 + elif pack: + if pack & (pack - 1): + raise ValueError("'pack' must be a power of two, not %r" % + (pack,)) + else: + pack = 0 + prev_options = self._options + try: + self._options = {'override': override, + 'packed': pack, + 'dllexport': dllexport} + self._internal_parse(csource) + finally: + self._options = prev_options + + def _internal_parse(self, csource): + ast, macros, csource = self._parse(csource) + # add the macros + self._process_macros(macros) + # find the first "__dotdotdot__" and use that as a separator + # between the repeated typedefs and the real csource + iterator = iter(ast.ext) + for decl in iterator: + if decl.name == '__dotdotdot__': + break + else: + assert 0 + current_decl = None + # + try: + self._inside_extern_python = '__cffi_extern_python_stop' + for decl in iterator: + current_decl = decl + if isinstance(decl, pycparser.c_ast.Decl): + self._parse_decl(decl) + elif isinstance(decl, pycparser.c_ast.Typedef): + if not decl.name: + raise CDefError("typedef does not declare any name", + decl) + quals = 0 + if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType) and + decl.type.type.names[-1].startswith('__dotdotdot')): + realtype = self._get_unknown_type(decl) + elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and + isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and + isinstance(decl.type.type.type, + pycparser.c_ast.IdentifierType) and + decl.type.type.type.names[-1].startswith('__dotdotdot')): + realtype = self._get_unknown_ptr_type(decl) + else: + realtype, quals = self._get_type_and_quals( + decl.type, name=decl.name, partial_length_ok=True, + typedef_example="*(%s *)0" % (decl.name,)) + self._declare('typedef ' + decl.name, realtype, quals=quals) + elif decl.__class__.__name__ == 'Pragma': + pass # skip pragma, only in pycparser 2.15 + else: + raise CDefError("unexpected <%s>: this construct is valid " + "C but not valid in cdef()" % + decl.__class__.__name__, decl) + except CDefError as e: + if len(e.args) == 1: + e.args = e.args + (current_decl,) + raise + except FFIError as e: + msg = self._convert_pycparser_error(e, csource) + if msg: + e.args = (e.args[0] + "\n *** Err: %s" % msg,) + raise + + def _add_constants(self, key, val): + if key in self._int_constants: + if self._int_constants[key] == val: + return # ignore identical double declarations + raise FFIError( + "multiple declarations of constant: %s" % (key,)) + self._int_constants[key] = val + + def _add_integer_constant(self, name, int_str): + int_str = int_str.lower().rstrip("ul") + neg = int_str.startswith('-') + if neg: + int_str = int_str[1:] + # "010" is not valid oct in py3 + if (int_str.startswith("0") and int_str != '0' + and not int_str.startswith("0x")): + int_str = "0o" + int_str[1:] + pyvalue = int(int_str, 0) + if neg: + pyvalue = -pyvalue + self._add_constants(name, pyvalue) + self._declare('macro ' + name, pyvalue) + + def _process_macros(self, macros): + for key, value in macros.items(): + value = value.strip() + if _r_int_literal.match(value): + self._add_integer_constant(key, value) + elif value == '...': + self._declare('macro ' + key, value) + else: + raise CDefError( + 'only supports one of the following syntax:\n' + ' #define %s ... (literally dot-dot-dot)\n' + ' #define %s NUMBER (with NUMBER an integer' + ' constant, decimal/hex/octal)\n' + 'got:\n' + ' #define %s %s' + % (key, key, key, value)) + + def _declare_function(self, tp, quals, decl): + tp = self._get_type_pointer(tp, quals) + if self._options.get('dllexport'): + tag = 'dllexport_python ' + elif self._inside_extern_python == '__cffi_extern_python_start': + tag = 'extern_python ' + elif self._inside_extern_python == '__cffi_extern_python_plus_c_start': + tag = 'extern_python_plus_c ' + else: + tag = 'function ' + self._declare(tag + decl.name, tp) + + def _parse_decl(self, decl): + node = decl.type + if isinstance(node, pycparser.c_ast.FuncDecl): + tp, quals = self._get_type_and_quals(node, name=decl.name) + assert isinstance(tp, model.RawFunctionType) + self._declare_function(tp, quals, decl) + else: + if isinstance(node, pycparser.c_ast.Struct): + self._get_struct_union_enum_type('struct', node) + elif isinstance(node, pycparser.c_ast.Union): + self._get_struct_union_enum_type('union', node) + elif isinstance(node, pycparser.c_ast.Enum): + self._get_struct_union_enum_type('enum', node) + elif not decl.name: + raise CDefError("construct does not declare any variable", + decl) + # + if decl.name: + tp, quals = self._get_type_and_quals(node, + partial_length_ok=True) + if tp.is_raw_function: + self._declare_function(tp, quals, decl) + elif (tp.is_integer_type() and + hasattr(decl, 'init') and + hasattr(decl.init, 'value') and + _r_int_literal.match(decl.init.value)): + self._add_integer_constant(decl.name, decl.init.value) + elif (tp.is_integer_type() and + isinstance(decl.init, pycparser.c_ast.UnaryOp) and + decl.init.op == '-' and + hasattr(decl.init.expr, 'value') and + _r_int_literal.match(decl.init.expr.value)): + self._add_integer_constant(decl.name, + '-' + decl.init.expr.value) + elif (tp is model.void_type and + decl.name.startswith('__cffi_extern_python_')): + # hack: `extern "Python"` in the C source is replaced + # with "void __cffi_extern_python_start;" and + # "void __cffi_extern_python_stop;" + self._inside_extern_python = decl.name + else: + if self._inside_extern_python !='__cffi_extern_python_stop': + raise CDefError( + "cannot declare constants or " + "variables with 'extern \"Python\"'") + if (quals & model.Q_CONST) and not tp.is_array_type: + self._declare('constant ' + decl.name, tp, quals=quals) + else: + _warn_for_non_extern_non_static_global_variable(decl) + self._declare('variable ' + decl.name, tp, quals=quals) + + def parse_type(self, cdecl): + return self.parse_type_and_quals(cdecl)[0] + + def parse_type_and_quals(self, cdecl): + ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2] + assert not macros + exprnode = ast.ext[-1].type.args.params[0] + if isinstance(exprnode, pycparser.c_ast.ID): + raise CDefError("unknown identifier '%s'" % (exprnode.name,)) + return self._get_type_and_quals(exprnode.type) + + def _declare(self, name, obj, included=False, quals=0): + if name in self._declarations: + prevobj, prevquals = self._declarations[name] + if prevobj is obj and prevquals == quals: + return + if not self._options.get('override'): + raise FFIError( + "multiple declarations of %s (for interactive usage, " + "try cdef(xx, override=True))" % (name,)) + assert '__dotdotdot__' not in name.split() + self._declarations[name] = (obj, quals) + if included: + self._included_declarations.add(obj) + + def _extract_quals(self, type): + quals = 0 + if isinstance(type, (pycparser.c_ast.TypeDecl, + pycparser.c_ast.PtrDecl)): + if 'const' in type.quals: + quals |= model.Q_CONST + if 'volatile' in type.quals: + quals |= model.Q_VOLATILE + if 'restrict' in type.quals: + quals |= model.Q_RESTRICT + return quals + + def _get_type_pointer(self, type, quals, declname=None): + if isinstance(type, model.RawFunctionType): + return type.as_function_pointer() + if (isinstance(type, model.StructOrUnionOrEnum) and + type.name.startswith('$') and type.name[1:].isdigit() and + type.forcename is None and declname is not None): + return model.NamedPointerType(type, declname, quals) + return model.PointerType(type, quals) + + def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False, + typedef_example=None): + # first, dereference typedefs, if we have it already parsed, we're good + if (isinstance(typenode, pycparser.c_ast.TypeDecl) and + isinstance(typenode.type, pycparser.c_ast.IdentifierType) and + len(typenode.type.names) == 1 and + ('typedef ' + typenode.type.names[0]) in self._declarations): + tp, quals = self._declarations['typedef ' + typenode.type.names[0]] + quals |= self._extract_quals(typenode) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.ArrayDecl): + # array type + if typenode.dim is None: + length = None + else: + length = self._parse_constant( + typenode.dim, partial_length_ok=partial_length_ok) + # a hack: in 'typedef int foo_t[...][...];', don't use '...' as + # the length but use directly the C expression that would be + # generated by recompiler.py. This lets the typedef be used in + # many more places within recompiler.py + if typedef_example is not None: + if length == '...': + length = '_cffi_array_len(%s)' % (typedef_example,) + typedef_example = "*" + typedef_example + # + tp, quals = self._get_type_and_quals(typenode.type, + partial_length_ok=partial_length_ok, + typedef_example=typedef_example) + return model.ArrayType(tp, length), quals + # + if isinstance(typenode, pycparser.c_ast.PtrDecl): + # pointer type + itemtype, itemquals = self._get_type_and_quals(typenode.type) + tp = self._get_type_pointer(itemtype, itemquals, declname=name) + quals = self._extract_quals(typenode) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.TypeDecl): + quals = self._extract_quals(typenode) + type = typenode.type + if isinstance(type, pycparser.c_ast.IdentifierType): + # assume a primitive type. get it from .names, but reduce + # synonyms to a single chosen combination + names = list(type.names) + if names != ['signed', 'char']: # keep this unmodified + prefixes = {} + while names: + name = names[0] + if name in ('short', 'long', 'signed', 'unsigned'): + prefixes[name] = prefixes.get(name, 0) + 1 + del names[0] + else: + break + # ignore the 'signed' prefix below, and reorder the others + newnames = [] + for prefix in ('unsigned', 'short', 'long'): + for i in range(prefixes.get(prefix, 0)): + newnames.append(prefix) + if not names: + names = ['int'] # implicitly + if names == ['int']: # but kill it if 'short' or 'long' + if 'short' in prefixes or 'long' in prefixes: + names = [] + names = newnames + names + ident = ' '.join(names) + if ident == 'void': + return model.void_type, quals + if ident == '__dotdotdot__': + raise FFIError(':%d: bad usage of "..."' % + typenode.coord.line) + tp0, quals0 = resolve_common_type(self, ident) + return tp0, (quals | quals0) + # + if isinstance(type, pycparser.c_ast.Struct): + # 'struct foobar' + tp = self._get_struct_union_enum_type('struct', type, name) + return tp, quals + # + if isinstance(type, pycparser.c_ast.Union): + # 'union foobar' + tp = self._get_struct_union_enum_type('union', type, name) + return tp, quals + # + if isinstance(type, pycparser.c_ast.Enum): + # 'enum foobar' + tp = self._get_struct_union_enum_type('enum', type, name) + return tp, quals + # + if isinstance(typenode, pycparser.c_ast.FuncDecl): + # a function type + return self._parse_function_type(typenode, name), 0 + # + # nested anonymous structs or unions end up here + if isinstance(typenode, pycparser.c_ast.Struct): + return self._get_struct_union_enum_type('struct', typenode, name, + nested=True), 0 + if isinstance(typenode, pycparser.c_ast.Union): + return self._get_struct_union_enum_type('union', typenode, name, + nested=True), 0 + # + raise FFIError(":%d: bad or unsupported type declaration" % + typenode.coord.line) + + def _parse_function_type(self, typenode, funcname=None): + params = list(getattr(typenode.args, 'params', [])) + for i, arg in enumerate(params): + if not hasattr(arg, 'type'): + raise CDefError("%s arg %d: unknown type '%s'" + " (if you meant to use the old C syntax of giving" + " untyped arguments, it is not supported)" + % (funcname or 'in expression', i + 1, + getattr(arg, 'name', '?'))) + ellipsis = ( + len(params) > 0 and + isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and + isinstance(params[-1].type.type, + pycparser.c_ast.IdentifierType) and + params[-1].type.type.names == ['__dotdotdot__']) + if ellipsis: + params.pop() + if not params: + raise CDefError( + "%s: a function with only '(...)' as argument" + " is not correct C" % (funcname or 'in expression')) + args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type)) + for argdeclnode in params] + if not ellipsis and args == [model.void_type]: + args = [] + result, quals = self._get_type_and_quals(typenode.type) + # the 'quals' on the result type are ignored. HACK: we absure them + # to detect __stdcall functions: we textually replace "__stdcall" + # with "volatile volatile const" above. + abi = None + if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway + if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']: + abi = '__stdcall' + return model.RawFunctionType(tuple(args), result, ellipsis, abi) + + def _as_func_arg(self, type, quals): + if isinstance(type, model.ArrayType): + return model.PointerType(type.item, quals) + elif isinstance(type, model.RawFunctionType): + return type.as_function_pointer() + else: + return type + + def _get_struct_union_enum_type(self, kind, type, name=None, nested=False): + # First, a level of caching on the exact 'type' node of the AST. + # This is obscure, but needed because pycparser "unrolls" declarations + # such as "typedef struct { } foo_t, *foo_p" and we end up with + # an AST that is not a tree, but a DAG, with the "type" node of the + # two branches foo_t and foo_p of the trees being the same node. + # It's a bit silly but detecting "DAG-ness" in the AST tree seems + # to be the only way to distinguish this case from two independent + # structs. See test_struct_with_two_usages. + try: + return self._structnode2type[type] + except KeyError: + pass + # + # Note that this must handle parsing "struct foo" any number of + # times and always return the same StructType object. Additionally, + # one of these times (not necessarily the first), the fields of + # the struct can be specified with "struct foo { ...fields... }". + # If no name is given, then we have to create a new anonymous struct + # with no caching; in this case, the fields are either specified + # right now or never. + # + force_name = name + name = type.name + # + # get the type or create it if needed + if name is None: + # 'force_name' is used to guess a more readable name for + # anonymous structs, for the common case "typedef struct { } foo". + if force_name is not None: + explicit_name = '$%s' % force_name + else: + self._anonymous_counter += 1 + explicit_name = '$%d' % self._anonymous_counter + tp = None + else: + explicit_name = name + key = '%s %s' % (kind, name) + tp, _ = self._declarations.get(key, (None, None)) + # + if tp is None: + if kind == 'struct': + tp = model.StructType(explicit_name, None, None, None) + elif kind == 'union': + tp = model.UnionType(explicit_name, None, None, None) + elif kind == 'enum': + if explicit_name == '__dotdotdot__': + raise CDefError("Enums cannot be declared with ...") + tp = self._build_enum_type(explicit_name, type.values) + else: + raise AssertionError("kind = %r" % (kind,)) + if name is not None: + self._declare(key, tp) + else: + if kind == 'enum' and type.values is not None: + raise NotImplementedError( + "enum %s: the '{}' declaration should appear on the first " + "time the enum is mentioned, not later" % explicit_name) + if not tp.forcename: + tp.force_the_name(force_name) + if tp.forcename and '$' in tp.name: + self._declare('anonymous %s' % tp.forcename, tp) + # + self._structnode2type[type] = tp + # + # enums: done here + if kind == 'enum': + return tp + # + # is there a 'type.decls'? If yes, then this is the place in the + # C sources that declare the fields. If no, then just return the + # existing type, possibly still incomplete. + if type.decls is None: + return tp + # + if tp.fldnames is not None: + raise CDefError("duplicate declaration of struct %s" % name) + fldnames = [] + fldtypes = [] + fldbitsize = [] + fldquals = [] + for decl in type.decls: + if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and + ''.join(decl.type.names) == '__dotdotdot__'): + # XXX pycparser is inconsistent: 'names' should be a list + # of strings, but is sometimes just one string. Use + # str.join() as a way to cope with both. + self._make_partial(tp, nested) + continue + if decl.bitsize is None: + bitsize = -1 + else: + bitsize = self._parse_constant(decl.bitsize) + self._partial_length = False + type, fqual = self._get_type_and_quals(decl.type, + partial_length_ok=True) + if self._partial_length: + self._make_partial(tp, nested) + if isinstance(type, model.StructType) and type.partial: + self._make_partial(tp, nested) + fldnames.append(decl.name or '') + fldtypes.append(type) + fldbitsize.append(bitsize) + fldquals.append(fqual) + tp.fldnames = tuple(fldnames) + tp.fldtypes = tuple(fldtypes) + tp.fldbitsize = tuple(fldbitsize) + tp.fldquals = tuple(fldquals) + if fldbitsize != [-1] * len(fldbitsize): + if isinstance(tp, model.StructType) and tp.partial: + raise NotImplementedError("%s: using both bitfields and '...;'" + % (tp,)) + tp.packed = self._options.get('packed') + if tp.completed: # must be re-completed: it is not opaque any more + tp.completed = 0 + self._recomplete.append(tp) + return tp + + def _make_partial(self, tp, nested): + if not isinstance(tp, model.StructOrUnion): + raise CDefError("%s cannot be partial" % (tp,)) + if not tp.has_c_name() and not nested: + raise NotImplementedError("%s is partial but has no C name" %(tp,)) + tp.partial = True + + def _parse_constant(self, exprnode, partial_length_ok=False): + # for now, limited to expressions that are an immediate number + # or positive/negative number + if isinstance(exprnode, pycparser.c_ast.Constant): + s = exprnode.value + if '0' <= s[0] <= '9': + s = s.rstrip('uUlL') + try: + if s.startswith('0'): + return int(s, 8) + else: + return int(s, 10) + except ValueError: + if len(s) > 1: + if s.lower()[0:2] == '0x': + return int(s, 16) + elif s.lower()[0:2] == '0b': + return int(s, 2) + raise CDefError("invalid constant %r" % (s,)) + elif s[0] == "'" and s[-1] == "'" and ( + len(s) == 3 or (len(s) == 4 and s[1] == "\\")): + return ord(s[-2]) + else: + raise CDefError("invalid constant %r" % (s,)) + # + if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and + exprnode.op == '+'): + return self._parse_constant(exprnode.expr) + # + if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and + exprnode.op == '-'): + return -self._parse_constant(exprnode.expr) + # load previously defined int constant + if (isinstance(exprnode, pycparser.c_ast.ID) and + exprnode.name in self._int_constants): + return self._int_constants[exprnode.name] + # + if (isinstance(exprnode, pycparser.c_ast.ID) and + exprnode.name == '__dotdotdotarray__'): + if partial_length_ok: + self._partial_length = True + return '...' + raise FFIError(":%d: unsupported '[...]' here, cannot derive " + "the actual array length in this context" + % exprnode.coord.line) + # + if isinstance(exprnode, pycparser.c_ast.BinaryOp): + left = self._parse_constant(exprnode.left) + right = self._parse_constant(exprnode.right) + if exprnode.op == '+': + return left + right + elif exprnode.op == '-': + return left - right + elif exprnode.op == '*': + return left * right + elif exprnode.op == '/': + return self._c_div(left, right) + elif exprnode.op == '%': + return left - self._c_div(left, right) * right + elif exprnode.op == '<<': + return left << right + elif exprnode.op == '>>': + return left >> right + elif exprnode.op == '&': + return left & right + elif exprnode.op == '|': + return left | right + elif exprnode.op == '^': + return left ^ right + # + raise FFIError(":%d: unsupported expression: expected a " + "simple numeric constant" % exprnode.coord.line) + + def _c_div(self, a, b): + result = a // b + if ((a < 0) ^ (b < 0)) and (a % b) != 0: + result += 1 + return result + + def _build_enum_type(self, explicit_name, decls): + if decls is not None: + partial = False + enumerators = [] + enumvalues = [] + nextenumvalue = 0 + for enum in decls.enumerators: + if _r_enum_dotdotdot.match(enum.name): + partial = True + continue + if enum.value is not None: + nextenumvalue = self._parse_constant(enum.value) + enumerators.append(enum.name) + enumvalues.append(nextenumvalue) + self._add_constants(enum.name, nextenumvalue) + nextenumvalue += 1 + enumerators = tuple(enumerators) + enumvalues = tuple(enumvalues) + tp = model.EnumType(explicit_name, enumerators, enumvalues) + tp.partial = partial + else: # opaque enum + tp = model.EnumType(explicit_name, (), ()) + return tp + + def include(self, other): + for name, (tp, quals) in other._declarations.items(): + if name.startswith('anonymous $enum_$'): + continue # fix for test_anonymous_enum_include + kind = name.split(' ', 1)[0] + if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'): + self._declare(name, tp, included=True, quals=quals) + for k, v in other._int_constants.items(): + self._add_constants(k, v) + + def _get_unknown_type(self, decl): + typenames = decl.type.type.names + if typenames == ['__dotdotdot__']: + return model.unknown_type(decl.name) + + if typenames == ['__dotdotdotint__']: + if self._uses_new_feature is None: + self._uses_new_feature = "'typedef int... %s'" % decl.name + return model.UnknownIntegerType(decl.name) + + if typenames == ['__dotdotdotfloat__']: + # note: not for 'long double' so far + if self._uses_new_feature is None: + self._uses_new_feature = "'typedef float... %s'" % decl.name + return model.UnknownFloatType(decl.name) + + raise FFIError(':%d: unsupported usage of "..." in typedef' + % decl.coord.line) + + def _get_unknown_ptr_type(self, decl): + if decl.type.type.type.names == ['__dotdotdot__']: + return model.unknown_ptr_type(decl.name) + raise FFIError(':%d: unsupported usage of "..." in typedef' + % decl.coord.line) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/error.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/error.py new file mode 100644 index 00000000..0a27247c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/error.py @@ -0,0 +1,31 @@ + +class FFIError(Exception): + __module__ = 'cffi' + +class CDefError(Exception): + __module__ = 'cffi' + def __str__(self): + try: + current_decl = self.args[1] + filename = current_decl.coord.file + linenum = current_decl.coord.line + prefix = '%s:%d: ' % (filename, linenum) + except (AttributeError, TypeError, IndexError): + prefix = '' + return '%s%s' % (prefix, self.args[0]) + +class VerificationError(Exception): + """ An error raised when verification fails + """ + __module__ = 'cffi' + +class VerificationMissing(Exception): + """ An error raised when incomplete structures are passed into + cdef, but no verification has been done + """ + __module__ = 'cffi' + +class PkgConfigError(Exception): + """ An error raised for missing modules in pkg-config + """ + __module__ = 'cffi' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/ffiplatform.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/ffiplatform.py new file mode 100644 index 00000000..85313460 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/ffiplatform.py @@ -0,0 +1,127 @@ +import sys, os +from .error import VerificationError + + +LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', + 'extra_objects', 'depends'] + +def get_extension(srcfilename, modname, sources=(), **kwds): + _hack_at_distutils() + from distutils.core import Extension + allsources = [srcfilename] + for src in sources: + allsources.append(os.path.normpath(src)) + return Extension(name=modname, sources=allsources, **kwds) + +def compile(tmpdir, ext, compiler_verbose=0, debug=None): + """Compile a C extension module using distutils.""" + + _hack_at_distutils() + saved_environ = os.environ.copy() + try: + outputfilename = _build(tmpdir, ext, compiler_verbose, debug) + outputfilename = os.path.abspath(outputfilename) + finally: + # workaround for a distutils bugs where some env vars can + # become longer and longer every time it is used + for key, value in saved_environ.items(): + if os.environ.get(key) != value: + os.environ[key] = value + return outputfilename + +def _build(tmpdir, ext, compiler_verbose=0, debug=None): + # XXX compact but horrible :-( + from distutils.core import Distribution + import distutils.errors, distutils.log + # + dist = Distribution({'ext_modules': [ext]}) + dist.parse_config_files() + options = dist.get_option_dict('build_ext') + if debug is None: + debug = sys.flags.debug + options['debug'] = ('ffiplatform', debug) + options['force'] = ('ffiplatform', True) + options['build_lib'] = ('ffiplatform', tmpdir) + options['build_temp'] = ('ffiplatform', tmpdir) + # + try: + old_level = distutils.log.set_threshold(0) or 0 + try: + distutils.log.set_verbosity(compiler_verbose) + dist.run_command('build_ext') + cmd_obj = dist.get_command_obj('build_ext') + [soname] = cmd_obj.get_outputs() + finally: + distutils.log.set_threshold(old_level) + except (distutils.errors.CompileError, + distutils.errors.LinkError) as e: + raise VerificationError('%s: %s' % (e.__class__.__name__, e)) + # + return soname + +try: + from os.path import samefile +except ImportError: + def samefile(f1, f2): + return os.path.abspath(f1) == os.path.abspath(f2) + +def maybe_relative_path(path): + if not os.path.isabs(path): + return path # already relative + dir = path + names = [] + while True: + prevdir = dir + dir, name = os.path.split(prevdir) + if dir == prevdir or not dir: + return path # failed to make it relative + names.append(name) + try: + if samefile(dir, os.curdir): + names.reverse() + return os.path.join(*names) + except OSError: + pass + +# ____________________________________________________________ + +try: + int_or_long = (int, long) + import cStringIO +except NameError: + int_or_long = int # Python 3 + import io as cStringIO + +def _flatten(x, f): + if isinstance(x, str): + f.write('%ds%s' % (len(x), x)) + elif isinstance(x, dict): + keys = sorted(x.keys()) + f.write('%dd' % len(keys)) + for key in keys: + _flatten(key, f) + _flatten(x[key], f) + elif isinstance(x, (list, tuple)): + f.write('%dl' % len(x)) + for value in x: + _flatten(value, f) + elif isinstance(x, int_or_long): + f.write('%di' % (x,)) + else: + raise TypeError( + "the keywords to verify() contains unsupported object %r" % (x,)) + +def flatten(x): + f = cStringIO.StringIO() + _flatten(x, f) + return f.getvalue() + +def _hack_at_distutils(): + # Windows-only workaround for some configurations: see + # https://bugs.python.org/issue23246 (Python 2.7 with + # a specific MS compiler suite download) + if sys.platform == "win32": + try: + import setuptools # for side-effects, patches distutils + except ImportError: + pass diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/lock.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/lock.py new file mode 100644 index 00000000..db91b715 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/lock.py @@ -0,0 +1,30 @@ +import sys + +if sys.version_info < (3,): + try: + from thread import allocate_lock + except ImportError: + from dummy_thread import allocate_lock +else: + try: + from _thread import allocate_lock + except ImportError: + from _dummy_thread import allocate_lock + + +##import sys +##l1 = allocate_lock + +##class allocate_lock(object): +## def __init__(self): +## self._real = l1() +## def __enter__(self): +## for i in range(4, 0, -1): +## print sys._getframe(i).f_code +## print +## return self._real.__enter__() +## def __exit__(self, *args): +## return self._real.__exit__(*args) +## def acquire(self, f): +## assert f is False +## return self._real.acquire(f) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/model.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/model.py new file mode 100644 index 00000000..ad1c1764 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/model.py @@ -0,0 +1,617 @@ +import types +import weakref + +from .lock import allocate_lock +from .error import CDefError, VerificationError, VerificationMissing + +# type qualifiers +Q_CONST = 0x01 +Q_RESTRICT = 0x02 +Q_VOLATILE = 0x04 + +def qualify(quals, replace_with): + if quals & Q_CONST: + replace_with = ' const ' + replace_with.lstrip() + if quals & Q_VOLATILE: + replace_with = ' volatile ' + replace_with.lstrip() + if quals & Q_RESTRICT: + # It seems that __restrict is supported by gcc and msvc. + # If you hit some different compiler, add a #define in + # _cffi_include.h for it (and in its copies, documented there) + replace_with = ' __restrict ' + replace_with.lstrip() + return replace_with + + +class BaseTypeByIdentity(object): + is_array_type = False + is_raw_function = False + + def get_c_name(self, replace_with='', context='a C file', quals=0): + result = self.c_name_with_marker + assert result.count('&') == 1 + # some logic duplication with ffi.getctype()... :-( + replace_with = replace_with.strip() + if replace_with: + if replace_with.startswith('*') and '&[' in result: + replace_with = '(%s)' % replace_with + elif not replace_with[0] in '[(': + replace_with = ' ' + replace_with + replace_with = qualify(quals, replace_with) + result = result.replace('&', replace_with) + if '$' in result: + raise VerificationError( + "cannot generate '%s' in %s: unknown type name" + % (self._get_c_name(), context)) + return result + + def _get_c_name(self): + return self.c_name_with_marker.replace('&', '') + + def has_c_name(self): + return '$' not in self._get_c_name() + + def is_integer_type(self): + return False + + def get_cached_btype(self, ffi, finishlist, can_delay=False): + try: + BType = ffi._cached_btypes[self] + except KeyError: + BType = self.build_backend_type(ffi, finishlist) + BType2 = ffi._cached_btypes.setdefault(self, BType) + assert BType2 is BType + return BType + + def __repr__(self): + return '<%s>' % (self._get_c_name(),) + + def _get_items(self): + return [(name, getattr(self, name)) for name in self._attrs_] + + +class BaseType(BaseTypeByIdentity): + + def __eq__(self, other): + return (self.__class__ == other.__class__ and + self._get_items() == other._get_items()) + + def __ne__(self, other): + return not self == other + + def __hash__(self): + return hash((self.__class__, tuple(self._get_items()))) + + +class VoidType(BaseType): + _attrs_ = () + + def __init__(self): + self.c_name_with_marker = 'void&' + + def build_backend_type(self, ffi, finishlist): + return global_cache(self, ffi, 'new_void_type') + +void_type = VoidType() + + +class BasePrimitiveType(BaseType): + def is_complex_type(self): + return False + + +class PrimitiveType(BasePrimitiveType): + _attrs_ = ('name',) + + ALL_PRIMITIVE_TYPES = { + 'char': 'c', + 'short': 'i', + 'int': 'i', + 'long': 'i', + 'long long': 'i', + 'signed char': 'i', + 'unsigned char': 'i', + 'unsigned short': 'i', + 'unsigned int': 'i', + 'unsigned long': 'i', + 'unsigned long long': 'i', + 'float': 'f', + 'double': 'f', + 'long double': 'f', + 'float _Complex': 'j', + 'double _Complex': 'j', + '_Bool': 'i', + # the following types are not primitive in the C sense + 'wchar_t': 'c', + 'char16_t': 'c', + 'char32_t': 'c', + 'int8_t': 'i', + 'uint8_t': 'i', + 'int16_t': 'i', + 'uint16_t': 'i', + 'int32_t': 'i', + 'uint32_t': 'i', + 'int64_t': 'i', + 'uint64_t': 'i', + 'int_least8_t': 'i', + 'uint_least8_t': 'i', + 'int_least16_t': 'i', + 'uint_least16_t': 'i', + 'int_least32_t': 'i', + 'uint_least32_t': 'i', + 'int_least64_t': 'i', + 'uint_least64_t': 'i', + 'int_fast8_t': 'i', + 'uint_fast8_t': 'i', + 'int_fast16_t': 'i', + 'uint_fast16_t': 'i', + 'int_fast32_t': 'i', + 'uint_fast32_t': 'i', + 'int_fast64_t': 'i', + 'uint_fast64_t': 'i', + 'intptr_t': 'i', + 'uintptr_t': 'i', + 'intmax_t': 'i', + 'uintmax_t': 'i', + 'ptrdiff_t': 'i', + 'size_t': 'i', + 'ssize_t': 'i', + } + + def __init__(self, name): + assert name in self.ALL_PRIMITIVE_TYPES + self.name = name + self.c_name_with_marker = name + '&' + + def is_char_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'c' + def is_integer_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'i' + def is_float_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'f' + def is_complex_type(self): + return self.ALL_PRIMITIVE_TYPES[self.name] == 'j' + + def build_backend_type(self, ffi, finishlist): + return global_cache(self, ffi, 'new_primitive_type', self.name) + + +class UnknownIntegerType(BasePrimitiveType): + _attrs_ = ('name',) + + def __init__(self, name): + self.name = name + self.c_name_with_marker = name + '&' + + def is_integer_type(self): + return True + + def build_backend_type(self, ffi, finishlist): + raise NotImplementedError("integer type '%s' can only be used after " + "compilation" % self.name) + +class UnknownFloatType(BasePrimitiveType): + _attrs_ = ('name', ) + + def __init__(self, name): + self.name = name + self.c_name_with_marker = name + '&' + + def build_backend_type(self, ffi, finishlist): + raise NotImplementedError("float type '%s' can only be used after " + "compilation" % self.name) + + +class BaseFunctionType(BaseType): + _attrs_ = ('args', 'result', 'ellipsis', 'abi') + + def __init__(self, args, result, ellipsis, abi=None): + self.args = args + self.result = result + self.ellipsis = ellipsis + self.abi = abi + # + reprargs = [arg._get_c_name() for arg in self.args] + if self.ellipsis: + reprargs.append('...') + reprargs = reprargs or ['void'] + replace_with = self._base_pattern % (', '.join(reprargs),) + if abi is not None: + replace_with = replace_with[:1] + abi + ' ' + replace_with[1:] + self.c_name_with_marker = ( + self.result.c_name_with_marker.replace('&', replace_with)) + + +class RawFunctionType(BaseFunctionType): + # Corresponds to a C type like 'int(int)', which is the C type of + # a function, but not a pointer-to-function. The backend has no + # notion of such a type; it's used temporarily by parsing. + _base_pattern = '(&)(%s)' + is_raw_function = True + + def build_backend_type(self, ffi, finishlist): + raise CDefError("cannot render the type %r: it is a function " + "type, not a pointer-to-function type" % (self,)) + + def as_function_pointer(self): + return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi) + + +class FunctionPtrType(BaseFunctionType): + _base_pattern = '(*&)(%s)' + + def build_backend_type(self, ffi, finishlist): + result = self.result.get_cached_btype(ffi, finishlist) + args = [] + for tp in self.args: + args.append(tp.get_cached_btype(ffi, finishlist)) + abi_args = () + if self.abi == "__stdcall": + if not self.ellipsis: # __stdcall ignored for variadic funcs + try: + abi_args = (ffi._backend.FFI_STDCALL,) + except AttributeError: + pass + return global_cache(self, ffi, 'new_function_type', + tuple(args), result, self.ellipsis, *abi_args) + + def as_raw_function(self): + return RawFunctionType(self.args, self.result, self.ellipsis, self.abi) + + +class PointerType(BaseType): + _attrs_ = ('totype', 'quals') + + def __init__(self, totype, quals=0): + self.totype = totype + self.quals = quals + extra = qualify(quals, " *&") + if totype.is_array_type: + extra = "(%s)" % (extra.lstrip(),) + self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) + + def build_backend_type(self, ffi, finishlist): + BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) + return global_cache(self, ffi, 'new_pointer_type', BItem) + +voidp_type = PointerType(void_type) + +def ConstPointerType(totype): + return PointerType(totype, Q_CONST) + +const_voidp_type = ConstPointerType(void_type) + + +class NamedPointerType(PointerType): + _attrs_ = ('totype', 'name') + + def __init__(self, totype, name, quals=0): + PointerType.__init__(self, totype, quals) + self.name = name + self.c_name_with_marker = name + '&' + + +class ArrayType(BaseType): + _attrs_ = ('item', 'length') + is_array_type = True + + def __init__(self, item, length): + self.item = item + self.length = length + # + if length is None: + brackets = '&[]' + elif length == '...': + brackets = '&[/*...*/]' + else: + brackets = '&[%s]' % length + self.c_name_with_marker = ( + self.item.c_name_with_marker.replace('&', brackets)) + + def length_is_unknown(self): + return isinstance(self.length, str) + + def resolve_length(self, newlength): + return ArrayType(self.item, newlength) + + def build_backend_type(self, ffi, finishlist): + if self.length_is_unknown(): + raise CDefError("cannot render the type %r: unknown length" % + (self,)) + self.item.get_cached_btype(ffi, finishlist) # force the item BType + BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) + return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) + +char_array_type = ArrayType(PrimitiveType('char'), None) + + +class StructOrUnionOrEnum(BaseTypeByIdentity): + _attrs_ = ('name',) + forcename = None + + def build_c_name_with_marker(self): + name = self.forcename or '%s %s' % (self.kind, self.name) + self.c_name_with_marker = name + '&' + + def force_the_name(self, forcename): + self.forcename = forcename + self.build_c_name_with_marker() + + def get_official_name(self): + assert self.c_name_with_marker.endswith('&') + return self.c_name_with_marker[:-1] + + +class StructOrUnion(StructOrUnionOrEnum): + fixedlayout = None + completed = 0 + partial = False + packed = 0 + + def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None): + self.name = name + self.fldnames = fldnames + self.fldtypes = fldtypes + self.fldbitsize = fldbitsize + self.fldquals = fldquals + self.build_c_name_with_marker() + + def anonymous_struct_fields(self): + if self.fldtypes is not None: + for name, type in zip(self.fldnames, self.fldtypes): + if name == '' and isinstance(type, StructOrUnion): + yield type + + def enumfields(self, expand_anonymous_struct_union=True): + fldquals = self.fldquals + if fldquals is None: + fldquals = (0,) * len(self.fldnames) + for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes, + self.fldbitsize, fldquals): + if (name == '' and isinstance(type, StructOrUnion) + and expand_anonymous_struct_union): + # nested anonymous struct/union + for result in type.enumfields(): + yield result + else: + yield (name, type, bitsize, quals) + + def force_flatten(self): + # force the struct or union to have a declaration that lists + # directly all fields returned by enumfields(), flattening + # nested anonymous structs/unions. + names = [] + types = [] + bitsizes = [] + fldquals = [] + for name, type, bitsize, quals in self.enumfields(): + names.append(name) + types.append(type) + bitsizes.append(bitsize) + fldquals.append(quals) + self.fldnames = tuple(names) + self.fldtypes = tuple(types) + self.fldbitsize = tuple(bitsizes) + self.fldquals = tuple(fldquals) + + def get_cached_btype(self, ffi, finishlist, can_delay=False): + BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist, + can_delay) + if not can_delay: + self.finish_backend_type(ffi, finishlist) + return BType + + def finish_backend_type(self, ffi, finishlist): + if self.completed: + if self.completed != 2: + raise NotImplementedError("recursive structure declaration " + "for '%s'" % (self.name,)) + return + BType = ffi._cached_btypes[self] + # + self.completed = 1 + # + if self.fldtypes is None: + pass # not completing it: it's an opaque struct + # + elif self.fixedlayout is None: + fldtypes = [tp.get_cached_btype(ffi, finishlist) + for tp in self.fldtypes] + lst = list(zip(self.fldnames, fldtypes, self.fldbitsize)) + extra_flags = () + if self.packed: + if self.packed == 1: + extra_flags = (8,) # SF_PACKED + else: + extra_flags = (0, self.packed) + ffi._backend.complete_struct_or_union(BType, lst, self, + -1, -1, *extra_flags) + # + else: + fldtypes = [] + fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout + for i in range(len(self.fldnames)): + fsize = fieldsize[i] + ftype = self.fldtypes[i] + # + if isinstance(ftype, ArrayType) and ftype.length_is_unknown(): + # fix the length to match the total size + BItemType = ftype.item.get_cached_btype(ffi, finishlist) + nlen, nrest = divmod(fsize, ffi.sizeof(BItemType)) + if nrest != 0: + self._verification_error( + "field '%s.%s' has a bogus size?" % ( + self.name, self.fldnames[i] or '{}')) + ftype = ftype.resolve_length(nlen) + self.fldtypes = (self.fldtypes[:i] + (ftype,) + + self.fldtypes[i+1:]) + # + BFieldType = ftype.get_cached_btype(ffi, finishlist) + if isinstance(ftype, ArrayType) and ftype.length is None: + assert fsize == 0 + else: + bitemsize = ffi.sizeof(BFieldType) + if bitemsize != fsize: + self._verification_error( + "field '%s.%s' is declared as %d bytes, but is " + "really %d bytes" % (self.name, + self.fldnames[i] or '{}', + bitemsize, fsize)) + fldtypes.append(BFieldType) + # + lst = list(zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)) + ffi._backend.complete_struct_or_union(BType, lst, self, + totalsize, totalalignment) + self.completed = 2 + + def _verification_error(self, msg): + raise VerificationError(msg) + + def check_not_partial(self): + if self.partial and self.fixedlayout is None: + raise VerificationMissing(self._get_c_name()) + + def build_backend_type(self, ffi, finishlist): + self.check_not_partial() + finishlist.append(self) + # + return global_cache(self, ffi, 'new_%s_type' % self.kind, + self.get_official_name(), key=self) + + +class StructType(StructOrUnion): + kind = 'struct' + + +class UnionType(StructOrUnion): + kind = 'union' + + +class EnumType(StructOrUnionOrEnum): + kind = 'enum' + partial = False + partial_resolved = False + + def __init__(self, name, enumerators, enumvalues, baseinttype=None): + self.name = name + self.enumerators = enumerators + self.enumvalues = enumvalues + self.baseinttype = baseinttype + self.build_c_name_with_marker() + + def force_the_name(self, forcename): + StructOrUnionOrEnum.force_the_name(self, forcename) + if self.forcename is None: + name = self.get_official_name() + self.forcename = '$' + name.replace(' ', '_') + + def check_not_partial(self): + if self.partial and not self.partial_resolved: + raise VerificationMissing(self._get_c_name()) + + def build_backend_type(self, ffi, finishlist): + self.check_not_partial() + base_btype = self.build_baseinttype(ffi, finishlist) + return global_cache(self, ffi, 'new_enum_type', + self.get_official_name(), + self.enumerators, self.enumvalues, + base_btype, key=self) + + def build_baseinttype(self, ffi, finishlist): + if self.baseinttype is not None: + return self.baseinttype.get_cached_btype(ffi, finishlist) + # + if self.enumvalues: + smallest_value = min(self.enumvalues) + largest_value = max(self.enumvalues) + else: + import warnings + try: + # XXX! The goal is to ensure that the warnings.warn() + # will not suppress the warning. We want to get it + # several times if we reach this point several times. + __warningregistry__.clear() + except NameError: + pass + warnings.warn("%r has no values explicitly defined; " + "guessing that it is equivalent to 'unsigned int'" + % self._get_c_name()) + smallest_value = largest_value = 0 + if smallest_value < 0: # needs a signed type + sign = 1 + candidate1 = PrimitiveType("int") + candidate2 = PrimitiveType("long") + else: + sign = 0 + candidate1 = PrimitiveType("unsigned int") + candidate2 = PrimitiveType("unsigned long") + btype1 = candidate1.get_cached_btype(ffi, finishlist) + btype2 = candidate2.get_cached_btype(ffi, finishlist) + size1 = ffi.sizeof(btype1) + size2 = ffi.sizeof(btype2) + if (smallest_value >= ((-1) << (8*size1-1)) and + largest_value < (1 << (8*size1-sign))): + return btype1 + if (smallest_value >= ((-1) << (8*size2-1)) and + largest_value < (1 << (8*size2-sign))): + return btype2 + raise CDefError("%s values don't all fit into either 'long' " + "or 'unsigned long'" % self._get_c_name()) + +def unknown_type(name, structname=None): + if structname is None: + structname = '$%s' % name + tp = StructType(structname, None, None, None) + tp.force_the_name(name) + tp.origin = "unknown_type" + return tp + +def unknown_ptr_type(name, structname=None): + if structname is None: + structname = '$$%s' % name + tp = StructType(structname, None, None, None) + return NamedPointerType(tp, name) + + +global_lock = allocate_lock() +_typecache_cffi_backend = weakref.WeakValueDictionary() + +def get_typecache(backend): + # returns _typecache_cffi_backend if backend is the _cffi_backend + # module, or type(backend).__typecache if backend is an instance of + # CTypesBackend (or some FakeBackend class during tests) + if isinstance(backend, types.ModuleType): + return _typecache_cffi_backend + with global_lock: + if not hasattr(type(backend), '__typecache'): + type(backend).__typecache = weakref.WeakValueDictionary() + return type(backend).__typecache + +def global_cache(srctype, ffi, funcname, *args, **kwds): + key = kwds.pop('key', (funcname, args)) + assert not kwds + try: + return ffi._typecache[key] + except KeyError: + pass + try: + res = getattr(ffi._backend, funcname)(*args) + except NotImplementedError as e: + raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) + # note that setdefault() on WeakValueDictionary is not atomic + # and contains a rare bug (http://bugs.python.org/issue19542); + # we have to use a lock and do it ourselves + cache = ffi._typecache + with global_lock: + res1 = cache.get(key) + if res1 is None: + cache[key] = res + return res + else: + return res1 + +def pointer_cache(ffi, BType): + return global_cache('?', ffi, 'new_pointer_type', BType) + +def attach_exception_info(e, name): + if e.args and type(e.args[0]) is str: + e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/parse_c_type.h b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/parse_c_type.h new file mode 100644 index 00000000..84e4ef85 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/parse_c_type.h @@ -0,0 +1,181 @@ + +/* This part is from file 'cffi/parse_c_type.h'. It is copied at the + beginning of C sources generated by CFFI's ffi.set_source(). */ + +typedef void *_cffi_opcode_t; + +#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) +#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) +#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8) + +#define _CFFI_OP_PRIMITIVE 1 +#define _CFFI_OP_POINTER 3 +#define _CFFI_OP_ARRAY 5 +#define _CFFI_OP_OPEN_ARRAY 7 +#define _CFFI_OP_STRUCT_UNION 9 +#define _CFFI_OP_ENUM 11 +#define _CFFI_OP_FUNCTION 13 +#define _CFFI_OP_FUNCTION_END 15 +#define _CFFI_OP_NOOP 17 +#define _CFFI_OP_BITFIELD 19 +#define _CFFI_OP_TYPENAME 21 +#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs +#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs +#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) +#define _CFFI_OP_CONSTANT 29 +#define _CFFI_OP_CONSTANT_INT 31 +#define _CFFI_OP_GLOBAL_VAR 33 +#define _CFFI_OP_DLOPEN_FUNC 35 +#define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 +#define _CFFI_OP_EXTERN_PYTHON 41 + +#define _CFFI_PRIM_VOID 0 +#define _CFFI_PRIM_BOOL 1 +#define _CFFI_PRIM_CHAR 2 +#define _CFFI_PRIM_SCHAR 3 +#define _CFFI_PRIM_UCHAR 4 +#define _CFFI_PRIM_SHORT 5 +#define _CFFI_PRIM_USHORT 6 +#define _CFFI_PRIM_INT 7 +#define _CFFI_PRIM_UINT 8 +#define _CFFI_PRIM_LONG 9 +#define _CFFI_PRIM_ULONG 10 +#define _CFFI_PRIM_LONGLONG 11 +#define _CFFI_PRIM_ULONGLONG 12 +#define _CFFI_PRIM_FLOAT 13 +#define _CFFI_PRIM_DOUBLE 14 +#define _CFFI_PRIM_LONGDOUBLE 15 + +#define _CFFI_PRIM_WCHAR 16 +#define _CFFI_PRIM_INT8 17 +#define _CFFI_PRIM_UINT8 18 +#define _CFFI_PRIM_INT16 19 +#define _CFFI_PRIM_UINT16 20 +#define _CFFI_PRIM_INT32 21 +#define _CFFI_PRIM_UINT32 22 +#define _CFFI_PRIM_INT64 23 +#define _CFFI_PRIM_UINT64 24 +#define _CFFI_PRIM_INTPTR 25 +#define _CFFI_PRIM_UINTPTR 26 +#define _CFFI_PRIM_PTRDIFF 27 +#define _CFFI_PRIM_SIZE 28 +#define _CFFI_PRIM_SSIZE 29 +#define _CFFI_PRIM_INT_LEAST8 30 +#define _CFFI_PRIM_UINT_LEAST8 31 +#define _CFFI_PRIM_INT_LEAST16 32 +#define _CFFI_PRIM_UINT_LEAST16 33 +#define _CFFI_PRIM_INT_LEAST32 34 +#define _CFFI_PRIM_UINT_LEAST32 35 +#define _CFFI_PRIM_INT_LEAST64 36 +#define _CFFI_PRIM_UINT_LEAST64 37 +#define _CFFI_PRIM_INT_FAST8 38 +#define _CFFI_PRIM_UINT_FAST8 39 +#define _CFFI_PRIM_INT_FAST16 40 +#define _CFFI_PRIM_UINT_FAST16 41 +#define _CFFI_PRIM_INT_FAST32 42 +#define _CFFI_PRIM_UINT_FAST32 43 +#define _CFFI_PRIM_INT_FAST64 44 +#define _CFFI_PRIM_UINT_FAST64 45 +#define _CFFI_PRIM_INTMAX 46 +#define _CFFI_PRIM_UINTMAX 47 +#define _CFFI_PRIM_FLOATCOMPLEX 48 +#define _CFFI_PRIM_DOUBLECOMPLEX 49 +#define _CFFI_PRIM_CHAR16 50 +#define _CFFI_PRIM_CHAR32 51 + +#define _CFFI__NUM_PRIM 52 +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) + +#define _CFFI__IO_FILE_STRUCT (-1) + + +struct _cffi_global_s { + const char *name; + void *address; + _cffi_opcode_t type_op; + void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown + // OP_CPYTHON_BLTN_*: addr of direct function +}; + +struct _cffi_getconst_s { + unsigned long long value; + const struct _cffi_type_context_s *ctx; + int gindex; +}; + +struct _cffi_struct_union_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_STRUCT_UNION + int flags; // _CFFI_F_* flags below + size_t size; + int alignment; + int first_field_index; // -> _cffi_fields array + int num_fields; +}; +#define _CFFI_F_UNION 0x01 // is a union, not a struct +#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the + // "standard layout" or if some are missing +#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct +#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() +#define _CFFI_F_OPAQUE 0x10 // opaque + +struct _cffi_field_s { + const char *name; + size_t field_offset; + size_t field_size; + _cffi_opcode_t field_type_op; +}; + +struct _cffi_enum_s { + const char *name; + int type_index; // -> _cffi_types, on a OP_ENUM + int type_prim; // _CFFI_PRIM_xxx + const char *enumerators; // comma-delimited string +}; + +struct _cffi_typename_s { + const char *name; + int type_index; /* if opaque, points to a possibly artificial + OP_STRUCT which is itself opaque */ +}; + +struct _cffi_type_context_s { + _cffi_opcode_t *types; + const struct _cffi_global_s *globals; + const struct _cffi_field_s *fields; + const struct _cffi_struct_union_s *struct_unions; + const struct _cffi_enum_s *enums; + const struct _cffi_typename_s *typenames; + int num_globals; + int num_struct_unions; + int num_enums; + int num_typenames; + const char *const *includes; + int num_types; + int flags; /* future extension */ +}; + +struct _cffi_parse_info_s { + const struct _cffi_type_context_s *ctx; + _cffi_opcode_t *output; + unsigned int output_size; + size_t error_location; + const char *error_message; +}; + +struct _cffi_externpy_s { + const char *name; + size_t size_of_result; + void *reserved1, *reserved2; +}; + +#ifdef _CFFI_INTERNAL +static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); +static int search_in_globals(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, + const char *search, size_t search_len); +#endif diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/pkgconfig.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/pkgconfig.py new file mode 100644 index 00000000..5c93f15a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/pkgconfig.py @@ -0,0 +1,121 @@ +# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi +import sys, os, subprocess + +from .error import PkgConfigError + + +def merge_flags(cfg1, cfg2): + """Merge values from cffi config flags cfg2 to cf1 + + Example: + merge_flags({"libraries": ["one"]}, {"libraries": ["two"]}) + {"libraries": ["one", "two"]} + """ + for key, value in cfg2.items(): + if key not in cfg1: + cfg1[key] = value + else: + if not isinstance(cfg1[key], list): + raise TypeError("cfg1[%r] should be a list of strings" % (key,)) + if not isinstance(value, list): + raise TypeError("cfg2[%r] should be a list of strings" % (key,)) + cfg1[key].extend(value) + return cfg1 + + +def call(libname, flag, encoding=sys.getfilesystemencoding()): + """Calls pkg-config and returns the output if found + """ + a = ["pkg-config", "--print-errors"] + a.append(flag) + a.append(libname) + try: + pc = subprocess.Popen(a, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except EnvironmentError as e: + raise PkgConfigError("cannot run pkg-config: %s" % (str(e).strip(),)) + + bout, berr = pc.communicate() + if pc.returncode != 0: + try: + berr = berr.decode(encoding) + except Exception: + pass + raise PkgConfigError(berr.strip()) + + if sys.version_info >= (3,) and not isinstance(bout, str): # Python 3.x + try: + bout = bout.decode(encoding) + except UnicodeDecodeError: + raise PkgConfigError("pkg-config %s %s returned bytes that cannot " + "be decoded with encoding %r:\n%r" % + (flag, libname, encoding, bout)) + + if os.altsep != '\\' and '\\' in bout: + raise PkgConfigError("pkg-config %s %s returned an unsupported " + "backslash-escaped output:\n%r" % + (flag, libname, bout)) + return bout + + +def flags_from_pkgconfig(libs): + r"""Return compiler line flags for FFI.set_source based on pkg-config output + + Usage + ... + ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"]) + + If pkg-config is installed on build machine, then arguments include_dirs, + library_dirs, libraries, define_macros, extra_compile_args and + extra_link_args are extended with an output of pkg-config for libfoo and + libbar. + + Raises PkgConfigError in case the pkg-config call fails. + """ + + def get_include_dirs(string): + return [x[2:] for x in string.split() if x.startswith("-I")] + + def get_library_dirs(string): + return [x[2:] for x in string.split() if x.startswith("-L")] + + def get_libraries(string): + return [x[2:] for x in string.split() if x.startswith("-l")] + + # convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils + def get_macros(string): + def _macro(x): + x = x[2:] # drop "-D" + if '=' in x: + return tuple(x.split("=", 1)) # "-Dfoo=bar" => ("foo", "bar") + else: + return (x, None) # "-Dfoo" => ("foo", None) + return [_macro(x) for x in string.split() if x.startswith("-D")] + + def get_other_cflags(string): + return [x for x in string.split() if not x.startswith("-I") and + not x.startswith("-D")] + + def get_other_libs(string): + return [x for x in string.split() if not x.startswith("-L") and + not x.startswith("-l")] + + # return kwargs for given libname + def kwargs(libname): + fse = sys.getfilesystemencoding() + all_cflags = call(libname, "--cflags") + all_libs = call(libname, "--libs") + return { + "include_dirs": get_include_dirs(all_cflags), + "library_dirs": get_library_dirs(all_libs), + "libraries": get_libraries(all_libs), + "define_macros": get_macros(all_cflags), + "extra_compile_args": get_other_cflags(all_cflags), + "extra_link_args": get_other_libs(all_libs), + } + + # merge all arguments together + ret = {} + for libname in libs: + lib_flags = kwargs(libname) + merge_flags(ret, lib_flags) + return ret diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/recompiler.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/recompiler.py new file mode 100644 index 00000000..86b37d7f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/recompiler.py @@ -0,0 +1,1581 @@ +import os, sys, io +from . import ffiplatform, model +from .error import VerificationError +from .cffi_opcode import * + +VERSION_BASE = 0x2601 +VERSION_EMBEDDED = 0x2701 +VERSION_CHAR16CHAR32 = 0x2801 + +USE_LIMITED_API = (sys.platform != 'win32' or sys.version_info < (3, 0) or + sys.version_info >= (3, 5)) + + +class GlobalExpr: + def __init__(self, name, address, type_op, size=0, check_value=0): + self.name = name + self.address = address + self.type_op = type_op + self.size = size + self.check_value = check_value + + def as_c_expr(self): + return ' { "%s", (void *)%s, %s, (void *)%s },' % ( + self.name, self.address, self.type_op.as_c_expr(), self.size) + + def as_python_expr(self): + return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name, + self.check_value) + +class FieldExpr: + def __init__(self, name, field_offset, field_size, fbitsize, field_type_op): + self.name = name + self.field_offset = field_offset + self.field_size = field_size + self.fbitsize = fbitsize + self.field_type_op = field_type_op + + def as_c_expr(self): + spaces = " " * len(self.name) + return (' { "%s", %s,\n' % (self.name, self.field_offset) + + ' %s %s,\n' % (spaces, self.field_size) + + ' %s %s },' % (spaces, self.field_type_op.as_c_expr())) + + def as_python_expr(self): + raise NotImplementedError + + def as_field_python_expr(self): + if self.field_type_op.op == OP_NOOP: + size_expr = '' + elif self.field_type_op.op == OP_BITFIELD: + size_expr = format_four_bytes(self.fbitsize) + else: + raise NotImplementedError + return "b'%s%s%s'" % (self.field_type_op.as_python_bytes(), + size_expr, + self.name) + +class StructUnionExpr: + def __init__(self, name, type_index, flags, size, alignment, comment, + first_field_index, c_fields): + self.name = name + self.type_index = type_index + self.flags = flags + self.size = size + self.alignment = alignment + self.comment = comment + self.first_field_index = first_field_index + self.c_fields = c_fields + + def as_c_expr(self): + return (' { "%s", %d, %s,' % (self.name, self.type_index, self.flags) + + '\n %s, %s, ' % (self.size, self.alignment) + + '%d, %d ' % (self.first_field_index, len(self.c_fields)) + + ('/* %s */ ' % self.comment if self.comment else '') + + '},') + + def as_python_expr(self): + flags = eval(self.flags, G_FLAGS) + fields_expr = [c_field.as_field_python_expr() + for c_field in self.c_fields] + return "(b'%s%s%s',%s)" % ( + format_four_bytes(self.type_index), + format_four_bytes(flags), + self.name, + ','.join(fields_expr)) + +class EnumExpr: + def __init__(self, name, type_index, size, signed, allenums): + self.name = name + self.type_index = type_index + self.size = size + self.signed = signed + self.allenums = allenums + + def as_c_expr(self): + return (' { "%s", %d, _cffi_prim_int(%s, %s),\n' + ' "%s" },' % (self.name, self.type_index, + self.size, self.signed, self.allenums)) + + def as_python_expr(self): + prim_index = { + (1, 0): PRIM_UINT8, (1, 1): PRIM_INT8, + (2, 0): PRIM_UINT16, (2, 1): PRIM_INT16, + (4, 0): PRIM_UINT32, (4, 1): PRIM_INT32, + (8, 0): PRIM_UINT64, (8, 1): PRIM_INT64, + }[self.size, self.signed] + return "b'%s%s%s\\x00%s'" % (format_four_bytes(self.type_index), + format_four_bytes(prim_index), + self.name, self.allenums) + +class TypenameExpr: + def __init__(self, name, type_index): + self.name = name + self.type_index = type_index + + def as_c_expr(self): + return ' { "%s", %d },' % (self.name, self.type_index) + + def as_python_expr(self): + return "b'%s%s'" % (format_four_bytes(self.type_index), self.name) + + +# ____________________________________________________________ + + +class Recompiler: + _num_externpy = 0 + + def __init__(self, ffi, module_name, target_is_python=False): + self.ffi = ffi + self.module_name = module_name + self.target_is_python = target_is_python + self._version = VERSION_BASE + + def needs_version(self, ver): + self._version = max(self._version, ver) + + def collect_type_table(self): + self._typesdict = {} + self._generate("collecttype") + # + all_decls = sorted(self._typesdict, key=str) + # + # prepare all FUNCTION bytecode sequences first + self.cffi_types = [] + for tp in all_decls: + if tp.is_raw_function: + assert self._typesdict[tp] is None + self._typesdict[tp] = len(self.cffi_types) + self.cffi_types.append(tp) # placeholder + for tp1 in tp.args: + assert isinstance(tp1, (model.VoidType, + model.BasePrimitiveType, + model.PointerType, + model.StructOrUnionOrEnum, + model.FunctionPtrType)) + if self._typesdict[tp1] is None: + self._typesdict[tp1] = len(self.cffi_types) + self.cffi_types.append(tp1) # placeholder + self.cffi_types.append('END') # placeholder + # + # prepare all OTHER bytecode sequences + for tp in all_decls: + if not tp.is_raw_function and self._typesdict[tp] is None: + self._typesdict[tp] = len(self.cffi_types) + self.cffi_types.append(tp) # placeholder + if tp.is_array_type and tp.length is not None: + self.cffi_types.append('LEN') # placeholder + assert None not in self._typesdict.values() + # + # collect all structs and unions and enums + self._struct_unions = {} + self._enums = {} + for tp in all_decls: + if isinstance(tp, model.StructOrUnion): + self._struct_unions[tp] = None + elif isinstance(tp, model.EnumType): + self._enums[tp] = None + for i, tp in enumerate(sorted(self._struct_unions, + key=lambda tp: tp.name)): + self._struct_unions[tp] = i + for i, tp in enumerate(sorted(self._enums, + key=lambda tp: tp.name)): + self._enums[tp] = i + # + # emit all bytecode sequences now + for tp in all_decls: + method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) + method(tp, self._typesdict[tp]) + # + # consistency check + for op in self.cffi_types: + assert isinstance(op, CffiOp) + self.cffi_types = tuple(self.cffi_types) # don't change any more + + def _enum_fields(self, tp): + # When producing C, expand all anonymous struct/union fields. + # That's necessary to have C code checking the offsets of the + # individual fields contained in them. When producing Python, + # don't do it and instead write it like it is, with the + # corresponding fields having an empty name. Empty names are + # recognized at runtime when we import the generated Python + # file. + expand_anonymous_struct_union = not self.target_is_python + return tp.enumfields(expand_anonymous_struct_union) + + def _do_collect_type(self, tp): + if not isinstance(tp, model.BaseTypeByIdentity): + if isinstance(tp, tuple): + for x in tp: + self._do_collect_type(x) + return + if tp not in self._typesdict: + self._typesdict[tp] = None + if isinstance(tp, model.FunctionPtrType): + self._do_collect_type(tp.as_raw_function()) + elif isinstance(tp, model.StructOrUnion): + if tp.fldtypes is not None and ( + tp not in self.ffi._parser._included_declarations): + for name1, tp1, _, _ in self._enum_fields(tp): + self._do_collect_type(self._field_type(tp, name1, tp1)) + else: + for _, x in tp._get_items(): + self._do_collect_type(x) + + def _generate(self, step_name): + lst = self.ffi._parser._declarations.items() + for name, (tp, quals) in sorted(lst): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_cpy_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in recompile(): %r" % name) + try: + self._current_quals = quals + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + # ---------- + + ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] + + def collect_step_tables(self): + # collect the declarations for '_cffi_globals', '_cffi_typenames', etc. + self._lsts = {} + for step_name in self.ALL_STEPS: + self._lsts[step_name] = [] + self._seen_struct_unions = set() + self._generate("ctx") + self._add_missing_struct_unions() + # + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + if step_name != "field": + lst.sort(key=lambda entry: entry.name) + self._lsts[step_name] = tuple(lst) # don't change any more + # + # check for a possible internal inconsistency: _cffi_struct_unions + # should have been generated with exactly self._struct_unions + lst = self._lsts["struct_union"] + for tp, i in self._struct_unions.items(): + assert i < len(lst) + assert lst[i].name == tp.name + assert len(lst) == len(self._struct_unions) + # same with enums + lst = self._lsts["enum"] + for tp, i in self._enums.items(): + assert i < len(lst) + assert lst[i].name == tp.name + assert len(lst) == len(self._enums) + + # ---------- + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def write_source_to_f(self, f, preamble): + if self.target_is_python: + assert preamble is None + self.write_py_source_to_f(f) + else: + assert preamble is not None + self.write_c_source_to_f(f, preamble) + + def _rel_readlines(self, filename): + g = open(os.path.join(os.path.dirname(__file__), filename), 'r') + lines = g.readlines() + g.close() + return lines + + def write_c_source_to_f(self, f, preamble): + self._f = f + prnt = self._prnt + if self.ffi._embedding is not None: + prnt('#define _CFFI_USE_EMBEDDING') + if not USE_LIMITED_API: + prnt('#define _CFFI_NO_LIMITED_API') + # + # first the '#include' (actually done by inlining the file's content) + lines = self._rel_readlines('_cffi_include.h') + i = lines.index('#include "parse_c_type.h"\n') + lines[i:i+1] = self._rel_readlines('parse_c_type.h') + prnt(''.join(lines)) + # + # if we have ffi._embedding != None, we give it here as a macro + # and include an extra file + base_module_name = self.module_name.split('.')[-1] + if self.ffi._embedding is not None: + prnt('#define _CFFI_MODULE_NAME "%s"' % (self.module_name,)) + prnt('static const char _CFFI_PYTHON_STARTUP_CODE[] = {') + self._print_string_literal_in_array(self.ffi._embedding) + prnt('0 };') + prnt('#ifdef PYPY_VERSION') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s' % ( + base_module_name,)) + prnt('#elif PY_MAJOR_VERSION >= 3') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s' % ( + base_module_name,)) + prnt('#else') + prnt('# define _CFFI_PYTHON_STARTUP_FUNC init%s' % ( + base_module_name,)) + prnt('#endif') + lines = self._rel_readlines('_embedding.h') + i = lines.index('#include "_cffi_errors.h"\n') + lines[i:i+1] = self._rel_readlines('_cffi_errors.h') + prnt(''.join(lines)) + self.needs_version(VERSION_EMBEDDED) + # + # then paste the C source given by the user, verbatim. + prnt('/************************************************************/') + prnt() + prnt(preamble) + prnt() + prnt('/************************************************************/') + prnt() + # + # the declaration of '_cffi_types' + prnt('static void *_cffi_types[] = {') + typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) + for i, op in enumerate(self.cffi_types): + comment = '' + if i in typeindex2type: + comment = ' // ' + typeindex2type[i]._get_c_name() + prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) + if not self.cffi_types: + prnt(' 0') + prnt('};') + prnt() + # + # call generate_cpy_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._seen_constants = set() + self._generate("decl") + # + # the declaration of '_cffi_globals' and '_cffi_typenames' + nums = {} + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + nums[step_name] = len(lst) + if nums[step_name] > 0: + prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( + step_name, step_name)) + for entry in lst: + prnt(entry.as_c_expr()) + prnt('};') + prnt() + # + # the declaration of '_cffi_includes' + if self.ffi._included_ffis: + prnt('static const char * const _cffi_includes[] = {') + for ffi_to_include in self.ffi._included_ffis: + try: + included_module_name, included_source = ( + ffi_to_include._assigned_source[:2]) + except AttributeError: + raise VerificationError( + "ffi object %r includes %r, but the latter has not " + "been prepared with set_source()" % ( + self.ffi, ffi_to_include,)) + if included_source is None: + raise VerificationError( + "not implemented yet: ffi.include() of a Python-based " + "ffi inside a C-based ffi") + prnt(' "%s",' % (included_module_name,)) + prnt(' NULL') + prnt('};') + prnt() + # + # the declaration of '_cffi_type_context' + prnt('static const struct _cffi_type_context_s _cffi_type_context = {') + prnt(' _cffi_types,') + for step_name in self.ALL_STEPS: + if nums[step_name] > 0: + prnt(' _cffi_%ss,' % step_name) + else: + prnt(' NULL, /* no %ss */' % step_name) + for step_name in self.ALL_STEPS: + if step_name != "field": + prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) + if self.ffi._included_ffis: + prnt(' _cffi_includes,') + else: + prnt(' NULL, /* no includes */') + prnt(' %d, /* num_types */' % (len(self.cffi_types),)) + flags = 0 + if self._num_externpy: + flags |= 1 # set to mean that we use extern "Python" + prnt(' %d, /* flags */' % flags) + prnt('};') + prnt() + # + # the init function + prnt('#ifdef __GNUC__') + prnt('# pragma GCC visibility push(default) /* for -fvisibility= */') + prnt('#endif') + prnt() + prnt('#ifdef PYPY_VERSION') + prnt('PyMODINIT_FUNC') + prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) + prnt('{') + if self._num_externpy: + prnt(' if (((intptr_t)p[0]) >= 0x0A03) {') + prnt(' _cffi_call_python_org = ' + '(void(*)(struct _cffi_externpy_s *, char *))p[1];') + prnt(' }') + prnt(' p[0] = (const void *)0x%x;' % self._version) + prnt(' p[1] = &_cffi_type_context;') + prnt('#if PY_MAJOR_VERSION >= 3') + prnt(' return NULL;') + prnt('#endif') + prnt('}') + # on Windows, distutils insists on putting init_cffi_xyz in + # 'export_symbols', so instead of fighting it, just give up and + # give it one + prnt('# ifdef _MSC_VER') + prnt(' PyMODINIT_FUNC') + prnt('# if PY_MAJOR_VERSION >= 3') + prnt(' PyInit_%s(void) { return NULL; }' % (base_module_name,)) + prnt('# else') + prnt(' init%s(void) { }' % (base_module_name,)) + prnt('# endif') + prnt('# endif') + prnt('#elif PY_MAJOR_VERSION >= 3') + prnt('PyMODINIT_FUNC') + prnt('PyInit_%s(void)' % (base_module_name,)) + prnt('{') + prnt(' return _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( + self.module_name, self._version)) + prnt('}') + prnt('#else') + prnt('PyMODINIT_FUNC') + prnt('init%s(void)' % (base_module_name,)) + prnt('{') + prnt(' _cffi_init("%s", 0x%x, &_cffi_type_context);' % ( + self.module_name, self._version)) + prnt('}') + prnt('#endif') + prnt() + prnt('#ifdef __GNUC__') + prnt('# pragma GCC visibility pop') + prnt('#endif') + self._version = None + + def _to_py(self, x): + if isinstance(x, str): + return "b'%s'" % (x,) + if isinstance(x, (list, tuple)): + rep = [self._to_py(item) for item in x] + if len(rep) == 1: + rep.append('') + return "(%s)" % (','.join(rep),) + return x.as_python_expr() # Py2: unicode unexpected; Py3: bytes unexp. + + def write_py_source_to_f(self, f): + self._f = f + prnt = self._prnt + # + # header + prnt("# auto-generated file") + prnt("import _cffi_backend") + # + # the 'import' of the included ffis + num_includes = len(self.ffi._included_ffis or ()) + for i in range(num_includes): + ffi_to_include = self.ffi._included_ffis[i] + try: + included_module_name, included_source = ( + ffi_to_include._assigned_source[:2]) + except AttributeError: + raise VerificationError( + "ffi object %r includes %r, but the latter has not " + "been prepared with set_source()" % ( + self.ffi, ffi_to_include,)) + if included_source is not None: + raise VerificationError( + "not implemented yet: ffi.include() of a C-based " + "ffi inside a Python-based ffi") + prnt('from %s import ffi as _ffi%d' % (included_module_name, i)) + prnt() + prnt("ffi = _cffi_backend.FFI('%s'," % (self.module_name,)) + prnt(" _version = 0x%x," % (self._version,)) + self._version = None + # + # the '_types' keyword argument + self.cffi_types = tuple(self.cffi_types) # don't change any more + types_lst = [op.as_python_bytes() for op in self.cffi_types] + prnt(' _types = %s,' % (self._to_py(''.join(types_lst)),)) + typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) + # + # the keyword arguments from ALL_STEPS + for step_name in self.ALL_STEPS: + lst = self._lsts[step_name] + if len(lst) > 0 and step_name != "field": + prnt(' _%ss = %s,' % (step_name, self._to_py(lst))) + # + # the '_includes' keyword argument + if num_includes > 0: + prnt(' _includes = (%s,),' % ( + ', '.join(['_ffi%d' % i for i in range(num_includes)]),)) + # + # the footer + prnt(')') + + # ---------- + + def _gettypenum(self, type): + # a KeyError here is a bug. please report it! :-) + return self._typesdict[type] + + def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): + extraarg = '' + if isinstance(tp, model.BasePrimitiveType) and not tp.is_complex_type(): + if tp.is_integer_type() and tp.name != '_Bool': + converter = '_cffi_to_c_int' + extraarg = ', %s' % tp.name + elif isinstance(tp, model.UnknownFloatType): + # don't check with is_float_type(): it may be a 'long + # double' here, and _cffi_to_c_double would loose precision + converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) + else: + cname = tp.get_c_name('') + converter = '(%s)_cffi_to_c_%s' % (cname, + tp.name.replace(' ', '_')) + if cname in ('char16_t', 'char32_t'): + self.needs_version(VERSION_CHAR16CHAR32) + errvalue = '-1' + # + elif isinstance(tp, model.PointerType): + self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, + tovar, errcode) + return + # + elif (isinstance(tp, model.StructOrUnionOrEnum) or + isinstance(tp, model.BasePrimitiveType)): + # a struct (not a struct pointer) as a function argument; + # or, a complex (the same code works) + self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' + % (tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s;' % errcode) + return + # + elif isinstance(tp, model.FunctionPtrType): + converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') + extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) + errvalue = 'NULL' + # + else: + raise NotImplementedError(tp) + # + self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) + self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( + tovar, tp.get_c_name(''), errvalue)) + self._prnt(' %s;' % errcode) + + def _extra_local_variables(self, tp, localvars, freelines): + if isinstance(tp, model.PointerType): + localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') + + def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): + self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') + self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( + self._gettypenum(tp), fromvar, tovar)) + self._prnt(' if (datasize != 0) {') + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + '(%s)alloca((size_t)datasize) : NULL;' % ( + tovar, tp.get_c_name(''))) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') + self._prnt(' %s;' % errcode) + self._prnt(' }') + + def _convert_expr_from_c(self, tp, var, context): + if isinstance(tp, model.BasePrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + return '_cffi_from_c_int(%s, %s)' % (var, tp.name) + elif isinstance(tp, model.UnknownFloatType): + return '_cffi_from_c_double(%s)' % (var,) + elif tp.name != 'long double' and not tp.is_complex_type(): + cname = tp.name.replace(' ', '_') + if cname in ('char16_t', 'char32_t'): + self.needs_version(VERSION_CHAR16CHAR32) + return '_cffi_from_c_%s(%s)' % (cname, var) + else: + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.ArrayType): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(model.PointerType(tp.item))) + elif isinstance(tp, model.StructOrUnion): + if tp.fldnames is None: + raise TypeError("'%s' is used as %s, but is opaque" % ( + tp._get_c_name(), context)) + return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.EnumType): + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + else: + raise NotImplementedError(tp) + + # ---------- + # typedefs + + def _typedef_type(self, tp, name): + return self._global_type(tp, "(*(%s *)0)" % (name,)) + + def _generate_cpy_typedef_collecttype(self, tp, name): + self._do_collect_type(self._typedef_type(tp, name)) + + def _generate_cpy_typedef_decl(self, tp, name): + pass + + def _typedef_ctx(self, tp, name): + type_index = self._typesdict[tp] + self._lsts["typename"].append(TypenameExpr(name, type_index)) + + def _generate_cpy_typedef_ctx(self, tp, name): + tp = self._typedef_type(tp, name) + self._typedef_ctx(tp, name) + if getattr(tp, "origin", None) == "unknown_type": + self._struct_ctx(tp, tp.name, approxname=None) + elif isinstance(tp, model.NamedPointerType): + self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, + named_ptr=tp) + + # ---------- + # function declarations + + def _generate_cpy_function_collecttype(self, tp, name): + self._do_collect_type(tp.as_raw_function()) + if tp.ellipsis and not self.target_is_python: + self._do_collect_type(tp) + + def _generate_cpy_function_decl(self, tp, name): + assert not self.target_is_python + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no CPython wrapper) + self._generate_cpy_constant_decl(tp, name) + return + prnt = self._prnt + numargs = len(tp.args) + if numargs == 0: + argname = 'noarg' + elif numargs == 1: + argname = 'arg0' + else: + argname = 'args' + # + # ------------------------------ + # the 'd' version of the function, only for addressof(lib, 'func') + arguments = [] + call_arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arguments.append(type.get_c_name(' x%d' % i, context)) + call_arguments.append('x%d' % i) + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + if tp.abi: + abi = tp.abi + ' ' + else: + abi = '' + name_and_arguments = '%s_cffi_d_%s(%s)' % (abi, name, repr_arguments) + prnt('static %s' % (tp.result.get_c_name(name_and_arguments),)) + prnt('{') + call_arguments = ', '.join(call_arguments) + result_code = 'return ' + if isinstance(tp.result, model.VoidType): + result_code = '' + prnt(' %s%s(%s);' % (result_code, name, call_arguments)) + prnt('}') + # + prnt('#ifndef PYPY_VERSION') # ------------------------------ + # + prnt('static PyObject *') + prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) + prnt('{') + # + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arg = type.get_c_name(' x%d' % i, context) + prnt(' %s;' % arg) + # + localvars = set() + freelines = set() + for type in tp.args: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): + prnt(' %s;' % (decl,)) + # + if not isinstance(tp.result, model.VoidType): + result_code = 'result = ' + context = 'result of %s' % name + result_decl = ' %s;' % tp.result.get_c_name(' result', context) + prnt(result_decl) + prnt(' PyObject *pyresult;') + else: + result_decl = None + result_code = '' + # + if len(tp.args) > 1: + rng = range(len(tp.args)) + for i in rng: + prnt(' PyObject *arg%d;' % i) + prnt() + prnt(' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))' % ( + name, len(rng), len(rng), + ', '.join(['&arg%d' % i for i in rng]))) + prnt(' return NULL;') + prnt() + # + for i, type in enumerate(tp.args): + self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, + 'return NULL') + prnt() + # + prnt(' Py_BEGIN_ALLOW_THREADS') + prnt(' _cffi_restore_errno();') + call_arguments = ['x%d' % i for i in range(len(tp.args))] + call_arguments = ', '.join(call_arguments) + prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) + prnt(' _cffi_save_errno();') + prnt(' Py_END_ALLOW_THREADS') + prnt() + # + prnt(' (void)self; /* unused */') + if numargs == 0: + prnt(' (void)noarg; /* unused */') + if result_code: + prnt(' pyresult = %s;' % + self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') + else: + for freeline in freelines: + prnt(' ' + freeline) + prnt(' Py_INCREF(Py_None);') + prnt(' return Py_None;') + prnt('}') + # + prnt('#else') # ------------------------------ + # + # the PyPy version: need to replace struct/union arguments with + # pointers, and if the result is a struct/union, insert a first + # arg that is a pointer to the result. We also do that for + # complex args and return type. + def need_indirection(type): + return (isinstance(type, model.StructOrUnion) or + (isinstance(type, model.PrimitiveType) and + type.is_complex_type())) + difference = False + arguments = [] + call_arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + indirection = '' + if need_indirection(type): + indirection = '*' + difference = True + arg = type.get_c_name(' %sx%d' % (indirection, i), context) + arguments.append(arg) + call_arguments.append('%sx%d' % (indirection, i)) + tp_result = tp.result + if need_indirection(tp_result): + context = 'result of %s' % name + arg = tp_result.get_c_name(' *result', context) + arguments.insert(0, arg) + tp_result = model.void_type + result_decl = None + result_code = '*result = ' + difference = True + if difference: + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + name_and_arguments = '%s_cffi_f_%s(%s)' % (abi, name, + repr_arguments) + prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) + prnt('{') + if result_decl: + prnt(result_decl) + call_arguments = ', '.join(call_arguments) + prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) + if result_decl: + prnt(' return result;') + prnt('}') + else: + prnt('# define _cffi_f_%s _cffi_d_%s' % (name, name)) + # + prnt('#endif') # ------------------------------ + prnt() + + def _generate_cpy_function_ctx(self, tp, name): + if tp.ellipsis and not self.target_is_python: + self._generate_cpy_constant_ctx(tp, name) + return + type_index = self._typesdict[tp.as_raw_function()] + numargs = len(tp.args) + if self.target_is_python: + meth_kind = OP_DLOPEN_FUNC + elif numargs == 0: + meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS' + elif numargs == 1: + meth_kind = OP_CPYTHON_BLTN_O # 'METH_O' + else: + meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS' + self._lsts["global"].append( + GlobalExpr(name, '_cffi_f_%s' % name, + CffiOp(meth_kind, type_index), + size='_cffi_d_%s' % name)) + + # ---------- + # named structs or unions + + def _field_type(self, tp_struct, field_name, tp_field): + if isinstance(tp_field, model.ArrayType): + actual_length = tp_field.length + if actual_length == '...': + ptr_struct_name = tp_struct.get_c_name('*') + actual_length = '_cffi_array_len(((%s)0)->%s)' % ( + ptr_struct_name, field_name) + tp_item = self._field_type(tp_struct, '%s[0]' % field_name, + tp_field.item) + tp_field = model.ArrayType(tp_item, actual_length) + return tp_field + + def _struct_collecttype(self, tp): + self._do_collect_type(tp) + if self.target_is_python: + # also requires nested anon struct/unions in ABI mode, recursively + for fldtype in tp.anonymous_struct_fields(): + self._struct_collecttype(fldtype) + + def _struct_decl(self, tp, cname, approxname): + if tp.fldtypes is None: + return + prnt = self._prnt + checkfuncname = '_cffi_checkfld_%s' % (approxname,) + prnt('_CFFI_UNUSED_FN') + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in self._enum_fields(tp): + try: + if ftype.is_integer_type() or fbitsize >= 0: + # accept all integers, but complain on float or double + if fname != '': + prnt(" (void)((p->%s) | 0); /* check that '%s.%s' is " + "an integer */" % (fname, cname, fname)) + continue + # only accept exactly the type declared, except that '[]' + # is interpreted as a '*' and so will match any array length. + # (It would also match '*', but that's harder to detect...) + while (isinstance(ftype, model.ArrayType) + and (ftype.length is None or ftype.length == '...')): + ftype = ftype.item + fname = fname + '[0]' + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) + prnt() + + def _struct_ctx(self, tp, cname, approxname, named_ptr=None): + type_index = self._typesdict[tp] + reason_for_not_expanding = None + flags = [] + if isinstance(tp, model.UnionType): + flags.append("_CFFI_F_UNION") + if tp.fldtypes is None: + flags.append("_CFFI_F_OPAQUE") + reason_for_not_expanding = "opaque" + if (tp not in self.ffi._parser._included_declarations and + (named_ptr is None or + named_ptr not in self.ffi._parser._included_declarations)): + if tp.fldtypes is None: + pass # opaque + elif tp.partial or any(tp.anonymous_struct_fields()): + pass # field layout obtained silently from the C compiler + else: + flags.append("_CFFI_F_CHECK_FIELDS") + if tp.packed: + if tp.packed > 1: + raise NotImplementedError( + "%r is declared with 'pack=%r'; only 0 or 1 are " + "supported in API mode (try to use \"...;\", which " + "does not require a 'pack' declaration)" % + (tp, tp.packed)) + flags.append("_CFFI_F_PACKED") + else: + flags.append("_CFFI_F_EXTERNAL") + reason_for_not_expanding = "external" + flags = '|'.join(flags) or '0' + c_fields = [] + if reason_for_not_expanding is None: + enumfields = list(self._enum_fields(tp)) + for fldname, fldtype, fbitsize, fqual in enumfields: + fldtype = self._field_type(tp, fldname, fldtype) + self._check_not_opaque(fldtype, + "field '%s.%s'" % (tp.name, fldname)) + # cname is None for _add_missing_struct_unions() only + op = OP_NOOP + if fbitsize >= 0: + op = OP_BITFIELD + size = '%d /* bits */' % fbitsize + elif cname is None or ( + isinstance(fldtype, model.ArrayType) and + fldtype.length is None): + size = '(size_t)-1' + else: + size = 'sizeof(((%s)0)->%s)' % ( + tp.get_c_name('*') if named_ptr is None + else named_ptr.name, + fldname) + if cname is None or fbitsize >= 0: + offset = '(size_t)-1' + elif named_ptr is not None: + offset = '((char *)&((%s)0)->%s) - (char *)0' % ( + named_ptr.name, fldname) + else: + offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) + c_fields.append( + FieldExpr(fldname, offset, size, fbitsize, + CffiOp(op, self._typesdict[fldtype]))) + first_field_index = len(self._lsts["field"]) + self._lsts["field"].extend(c_fields) + # + if cname is None: # unknown name, for _add_missing_struct_unions + size = '(size_t)-2' + align = -2 + comment = "unnamed" + else: + if named_ptr is not None: + size = 'sizeof(*(%s)0)' % (named_ptr.name,) + align = '-1 /* unknown alignment */' + else: + size = 'sizeof(%s)' % (cname,) + align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) + comment = None + else: + size = '(size_t)-1' + align = -1 + first_field_index = -1 + comment = reason_for_not_expanding + self._lsts["struct_union"].append( + StructUnionExpr(tp.name, type_index, flags, size, align, comment, + first_field_index, c_fields)) + self._seen_struct_unions.add(tp) + + def _check_not_opaque(self, tp, location): + while isinstance(tp, model.ArrayType): + tp = tp.item + if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: + raise TypeError( + "%s is of an opaque type (not declared in cdef())" % location) + + def _add_missing_struct_unions(self): + # not very nice, but some struct declarations might be missing + # because they don't have any known C name. Check that they are + # not partial (we can't complete or verify them!) and emit them + # anonymously. + lst = list(self._struct_unions.items()) + lst.sort(key=lambda tp_order: tp_order[1]) + for tp, order in lst: + if tp not in self._seen_struct_unions: + if tp.partial: + raise NotImplementedError("internal inconsistency: %r is " + "partial but was not seen at " + "this point" % (tp,)) + if tp.name.startswith('$') and tp.name[1:].isdigit(): + approxname = tp.name[1:] + elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': + approxname = 'FILE' + self._typedef_ctx(tp, 'FILE') + else: + raise NotImplementedError("internal inconsistency: %r" % + (tp,)) + self._struct_ctx(tp, None, approxname) + + def _generate_cpy_struct_collecttype(self, tp, name): + self._struct_collecttype(tp) + _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype + + def _struct_names(self, tp): + cname = tp.get_c_name('') + if ' ' in cname: + return cname, cname.replace(' ', '_') + else: + return cname, '_' + cname + + def _generate_cpy_struct_decl(self, tp, name): + self._struct_decl(tp, *self._struct_names(tp)) + _generate_cpy_union_decl = _generate_cpy_struct_decl + + def _generate_cpy_struct_ctx(self, tp, name): + self._struct_ctx(tp, *self._struct_names(tp)) + _generate_cpy_union_ctx = _generate_cpy_struct_ctx + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + def _generate_cpy_anonymous_collecttype(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_collecttype(tp, name) + else: + self._struct_collecttype(tp) + + def _generate_cpy_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_decl(tp) + else: + self._struct_decl(tp, name, 'typedef_' + name) + + def _generate_cpy_anonymous_ctx(self, tp, name): + if isinstance(tp, model.EnumType): + self._enum_ctx(tp, name) + else: + self._struct_ctx(tp, name, 'typedef_' + name) + + # ---------- + # constants, declared with "static const ..." + + def _generate_cpy_const(self, is_int, name, tp=None, category='const', + check_value=None): + if (category, name) in self._seen_constants: + raise VerificationError( + "duplicate declaration of %s '%s'" % (category, name)) + self._seen_constants.add((category, name)) + # + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + if is_int: + prnt('static int %s(unsigned long long *o)' % funcname) + prnt('{') + prnt(' int n = (%s) <= 0;' % (name,)) + prnt(' *o = (unsigned long long)((%s) | 0);' + ' /* check that %s is an integer */' % (name, name)) + if check_value is not None: + if check_value > 0: + check_value = '%dU' % (check_value,) + prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) + prnt(' n |= 2;') + prnt(' return n;') + prnt('}') + else: + assert check_value is None + prnt('static void %s(char *o)' % funcname) + prnt('{') + prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) + prnt('}') + prnt() + + def _generate_cpy_constant_collecttype(self, tp, name): + is_int = tp.is_integer_type() + if not is_int or self.target_is_python: + self._do_collect_type(tp) + + def _generate_cpy_constant_decl(self, tp, name): + is_int = tp.is_integer_type() + self._generate_cpy_const(is_int, name, tp) + + def _generate_cpy_constant_ctx(self, tp, name): + if not self.target_is_python and tp.is_integer_type(): + type_op = CffiOp(OP_CONSTANT_INT, -1) + else: + if self.target_is_python: + const_kind = OP_DLOPEN_CONST + else: + const_kind = OP_CONSTANT + type_index = self._typesdict[tp] + type_op = CffiOp(const_kind, type_index) + self._lsts["global"].append( + GlobalExpr(name, '_cffi_const_%s' % name, type_op)) + + # ---------- + # enums + + def _generate_cpy_enum_collecttype(self, tp, name): + self._do_collect_type(tp) + + def _generate_cpy_enum_decl(self, tp, name=None): + for enumerator in tp.enumerators: + self._generate_cpy_const(True, enumerator) + + def _enum_ctx(self, tp, cname): + type_index = self._typesdict[tp] + type_op = CffiOp(OP_ENUM, -1) + if self.target_is_python: + tp.check_not_partial() + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._lsts["global"].append( + GlobalExpr(enumerator, '_cffi_const_%s' % enumerator, type_op, + check_value=enumvalue)) + # + if cname is not None and '$' not in cname and not self.target_is_python: + size = "sizeof(%s)" % cname + signed = "((%s)-1) <= 0" % cname + else: + basetp = tp.build_baseinttype(self.ffi, []) + size = self.ffi.sizeof(basetp) + signed = int(int(self.ffi.cast(basetp, -1)) < 0) + allenums = ",".join(tp.enumerators) + self._lsts["enum"].append( + EnumExpr(tp.name, type_index, size, signed, allenums)) + + def _generate_cpy_enum_ctx(self, tp, name): + self._enum_ctx(tp, tp._get_c_name()) + + # ---------- + # macros: for now only for integers + + def _generate_cpy_macro_collecttype(self, tp, name): + pass + + def _generate_cpy_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_cpy_const(True, name, check_value=check_value) + + def _generate_cpy_macro_ctx(self, tp, name): + if tp == '...': + if self.target_is_python: + raise VerificationError( + "cannot use the syntax '...' in '#define %s ...' when " + "using the ABI mode" % (name,)) + check_value = None + else: + check_value = tp # an integer + type_op = CffiOp(OP_CONSTANT_INT, -1) + self._lsts["global"].append( + GlobalExpr(name, '_cffi_const_%s' % name, type_op, + check_value=check_value)) + + # ---------- + # global variables + + def _global_type(self, tp, global_name): + if isinstance(tp, model.ArrayType): + actual_length = tp.length + if actual_length == '...': + actual_length = '_cffi_array_len(%s)' % (global_name,) + tp_item = self._global_type(tp.item, '%s[0]' % global_name) + tp = model.ArrayType(tp_item, actual_length) + return tp + + def _generate_cpy_variable_collecttype(self, tp, name): + self._do_collect_type(self._global_type(tp, name)) + + def _generate_cpy_variable_decl(self, tp, name): + prnt = self._prnt + tp = self._global_type(tp, name) + if isinstance(tp, model.ArrayType) and tp.length is None: + tp = tp.item + ampersand = '' + else: + ampersand = '&' + # This code assumes that casts from "tp *" to "void *" is a + # no-op, i.e. a function that returns a "tp *" can be called + # as if it returned a "void *". This should be generally true + # on any modern machine. The only exception to that rule (on + # uncommon architectures, and as far as I can tell) might be + # if 'tp' were a function type, but that is not possible here. + # (If 'tp' is a function _pointer_ type, then casts from "fn_t + # **" to "void *" are again no-ops, as far as I can tell.) + decl = '*_cffi_var_%s(void)' % (name,) + prnt('static ' + tp.get_c_name(decl, quals=self._current_quals)) + prnt('{') + prnt(' return %s(%s);' % (ampersand, name)) + prnt('}') + prnt() + + def _generate_cpy_variable_ctx(self, tp, name): + tp = self._global_type(tp, name) + type_index = self._typesdict[tp] + if self.target_is_python: + op = OP_GLOBAL_VAR + else: + op = OP_GLOBAL_VAR_F + self._lsts["global"].append( + GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) + + # ---------- + # extern "Python" + + def _generate_cpy_extern_python_collecttype(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + self._do_collect_type(tp) + _generate_cpy_dllexport_python_collecttype = \ + _generate_cpy_extern_python_plus_c_collecttype = \ + _generate_cpy_extern_python_collecttype + + def _extern_python_decl(self, tp, name, tag_and_space): + prnt = self._prnt + if isinstance(tp.result, model.VoidType): + size_of_result = '0' + else: + context = 'result of %s' % name + size_of_result = '(int)sizeof(%s)' % ( + tp.result.get_c_name('', context),) + prnt('static struct _cffi_externpy_s _cffi_externpy__%s =' % name) + prnt(' { "%s.%s", %s, 0, 0 };' % ( + self.module_name, name, size_of_result)) + prnt() + # + arguments = [] + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + arg = type.get_c_name(' a%d' % i, context) + arguments.append(arg) + # + repr_arguments = ', '.join(arguments) + repr_arguments = repr_arguments or 'void' + name_and_arguments = '%s(%s)' % (name, repr_arguments) + if tp.abi == "__stdcall": + name_and_arguments = '_cffi_stdcall ' + name_and_arguments + # + def may_need_128_bits(tp): + return (isinstance(tp, model.PrimitiveType) and + tp.name == 'long double') + # + size_of_a = max(len(tp.args)*8, 8) + if may_need_128_bits(tp.result): + size_of_a = max(size_of_a, 16) + if isinstance(tp.result, model.StructOrUnion): + size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % ( + tp.result.get_c_name(''), size_of_a, + tp.result.get_c_name(''), size_of_a) + prnt('%s%s' % (tag_and_space, tp.result.get_c_name(name_and_arguments))) + prnt('{') + prnt(' char a[%s];' % size_of_a) + prnt(' char *p = a;') + for i, type in enumerate(tp.args): + arg = 'a%d' % i + if (isinstance(type, model.StructOrUnion) or + may_need_128_bits(type)): + arg = '&' + arg + type = model.PointerType(type) + prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg)) + prnt(' _cffi_call_python(&_cffi_externpy__%s, p);' % name) + if not isinstance(tp.result, model.VoidType): + prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),)) + prnt('}') + prnt() + self._num_externpy += 1 + + def _generate_cpy_extern_python_decl(self, tp, name): + self._extern_python_decl(tp, name, 'static ') + + def _generate_cpy_dllexport_python_decl(self, tp, name): + self._extern_python_decl(tp, name, 'CFFI_DLLEXPORT ') + + def _generate_cpy_extern_python_plus_c_decl(self, tp, name): + self._extern_python_decl(tp, name, '') + + def _generate_cpy_extern_python_ctx(self, tp, name): + if self.target_is_python: + raise VerificationError( + "cannot use 'extern \"Python\"' in the ABI mode") + if tp.ellipsis: + raise NotImplementedError("a vararg function is extern \"Python\"") + type_index = self._typesdict[tp] + type_op = CffiOp(OP_EXTERN_PYTHON, type_index) + self._lsts["global"].append( + GlobalExpr(name, '&_cffi_externpy__%s' % name, type_op, name)) + + _generate_cpy_dllexport_python_ctx = \ + _generate_cpy_extern_python_plus_c_ctx = \ + _generate_cpy_extern_python_ctx + + def _print_string_literal_in_array(self, s): + prnt = self._prnt + prnt('// # NB. this is not a string because of a size limit in MSVC') + if not isinstance(s, bytes): # unicode + s = s.encode('utf-8') # -> bytes + else: + s.decode('utf-8') # got bytes, check for valid utf-8 + try: + s.decode('ascii') + except UnicodeDecodeError: + s = b'# -*- encoding: utf8 -*-\n' + s + for line in s.splitlines(True): + comment = line + if type('//') is bytes: # python2 + line = map(ord, line) # make a list of integers + else: # python3 + # type(line) is bytes, which enumerates like a list of integers + comment = ascii(comment)[1:-1] + prnt(('// ' + comment).rstrip()) + printed_line = '' + for c in line: + if len(printed_line) >= 76: + prnt(printed_line) + printed_line = '' + printed_line += '%d,' % (c,) + prnt(printed_line) + + # ---------- + # emitting the opcodes for individual types + + def _emit_bytecode_VoidType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) + + def _emit_bytecode_PrimitiveType(self, tp, index): + prim_index = PRIMITIVE_TO_INDEX[tp.name] + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) + + def _emit_bytecode_UnknownIntegerType(self, tp, index): + s = ('_cffi_prim_int(sizeof(%s), (\n' + ' ((%s)-1) | 0 /* check that %s is an integer type */\n' + ' ) <= 0)' % (tp.name, tp.name, tp.name)) + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + + def _emit_bytecode_UnknownFloatType(self, tp, index): + s = ('_cffi_prim_float(sizeof(%s) *\n' + ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' + ' )' % (tp.name, tp.name)) + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + + def _emit_bytecode_RawFunctionType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) + index += 1 + for tp1 in tp.args: + realindex = self._typesdict[tp1] + if index != realindex: + if isinstance(tp1, model.PrimitiveType): + self._emit_bytecode_PrimitiveType(tp1, index) + else: + self.cffi_types[index] = CffiOp(OP_NOOP, realindex) + index += 1 + flags = int(tp.ellipsis) + if tp.abi is not None: + if tp.abi == '__stdcall': + flags |= 2 + else: + raise NotImplementedError("abi=%r" % (tp.abi,)) + self.cffi_types[index] = CffiOp(OP_FUNCTION_END, flags) + + def _emit_bytecode_PointerType(self, tp, index): + self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) + + _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType + _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType + + def _emit_bytecode_FunctionPtrType(self, tp, index): + raw = tp.as_raw_function() + self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) + + def _emit_bytecode_ArrayType(self, tp, index): + item_index = self._typesdict[tp.item] + if tp.length is None: + self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) + elif tp.length == '...': + raise VerificationError( + "type %s badly placed: the '...' array length can only be " + "used on global arrays or on fields of structures" % ( + str(tp).replace('/*...*/', '...'),)) + else: + assert self.cffi_types[index + 1] == 'LEN' + self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) + self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) + + def _emit_bytecode_StructType(self, tp, index): + struct_index = self._struct_unions[tp] + self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) + _emit_bytecode_UnionType = _emit_bytecode_StructType + + def _emit_bytecode_EnumType(self, tp, index): + enum_index = self._enums[tp] + self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) + + +if sys.version_info >= (3,): + NativeIO = io.StringIO +else: + class NativeIO(io.BytesIO): + def write(self, s): + if isinstance(s, unicode): + s = s.encode('ascii') + super(NativeIO, self).write(s) + +def _make_c_or_py_source(ffi, module_name, preamble, target_file, verbose): + if verbose: + print("generating %s" % (target_file,)) + recompiler = Recompiler(ffi, module_name, + target_is_python=(preamble is None)) + recompiler.collect_type_table() + recompiler.collect_step_tables() + f = NativeIO() + recompiler.write_source_to_f(f, preamble) + output = f.getvalue() + try: + with open(target_file, 'r') as f1: + if f1.read(len(output) + 1) != output: + raise IOError + if verbose: + print("(already up-to-date)") + return False # already up-to-date + except IOError: + tmp_file = '%s.~%d' % (target_file, os.getpid()) + with open(tmp_file, 'w') as f1: + f1.write(output) + try: + os.rename(tmp_file, target_file) + except OSError: + os.unlink(target_file) + os.rename(tmp_file, target_file) + return True + +def make_c_source(ffi, module_name, preamble, target_c_file, verbose=False): + assert preamble is not None + return _make_c_or_py_source(ffi, module_name, preamble, target_c_file, + verbose) + +def make_py_source(ffi, module_name, target_py_file, verbose=False): + return _make_c_or_py_source(ffi, module_name, None, target_py_file, + verbose) + +def _modname_to_file(outputdir, modname, extension): + parts = modname.split('.') + try: + os.makedirs(os.path.join(outputdir, *parts[:-1])) + except OSError: + pass + parts[-1] += extension + return os.path.join(outputdir, *parts), parts + + +# Aaargh. Distutils is not tested at all for the purpose of compiling +# DLLs that are not extension modules. Here are some hacks to work +# around that, in the _patch_for_*() functions... + +def _patch_meth(patchlist, cls, name, new_meth): + old = getattr(cls, name) + patchlist.append((cls, name, old)) + setattr(cls, name, new_meth) + return old + +def _unpatch_meths(patchlist): + for cls, name, old_meth in reversed(patchlist): + setattr(cls, name, old_meth) + +def _patch_for_embedding(patchlist): + if sys.platform == 'win32': + # we must not remove the manifest when building for embedding! + from distutils.msvc9compiler import MSVCCompiler + _patch_meth(patchlist, MSVCCompiler, '_remove_visual_c_ref', + lambda self, manifest_file: manifest_file) + + if sys.platform == 'darwin': + # we must not make a '-bundle', but a '-dynamiclib' instead + from distutils.ccompiler import CCompiler + def my_link_shared_object(self, *args, **kwds): + if '-bundle' in self.linker_so: + self.linker_so = list(self.linker_so) + i = self.linker_so.index('-bundle') + self.linker_so[i] = '-dynamiclib' + return old_link_shared_object(self, *args, **kwds) + old_link_shared_object = _patch_meth(patchlist, CCompiler, + 'link_shared_object', + my_link_shared_object) + +def _patch_for_target(patchlist, target): + from distutils.command.build_ext import build_ext + # if 'target' is different from '*', we need to patch some internal + # method to just return this 'target' value, instead of having it + # built from module_name + if target.endswith('.*'): + target = target[:-2] + if sys.platform == 'win32': + target += '.dll' + elif sys.platform == 'darwin': + target += '.dylib' + else: + target += '.so' + _patch_meth(patchlist, build_ext, 'get_ext_filename', + lambda self, ext_name: target) + + +def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True, + c_file=None, source_extension='.c', extradir=None, + compiler_verbose=1, target=None, debug=None, **kwds): + if not isinstance(module_name, str): + module_name = module_name.encode('ascii') + if ffi._windows_unicode: + ffi._apply_windows_unicode(kwds) + if preamble is not None: + embedding = (ffi._embedding is not None) + if embedding: + ffi._apply_embedding_fix(kwds) + if c_file is None: + c_file, parts = _modname_to_file(tmpdir, module_name, + source_extension) + if extradir: + parts = [extradir] + parts + ext_c_file = os.path.join(*parts) + else: + ext_c_file = c_file + # + if target is None: + if embedding: + target = '%s.*' % module_name + else: + target = '*' + # + ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds) + updated = make_c_source(ffi, module_name, preamble, c_file, + verbose=compiler_verbose) + if call_c_compiler: + patchlist = [] + cwd = os.getcwd() + try: + if embedding: + _patch_for_embedding(patchlist) + if target != '*': + _patch_for_target(patchlist, target) + if compiler_verbose: + if tmpdir == '.': + msg = 'the current directory is' + else: + msg = 'setting the current directory to' + print('%s %r' % (msg, os.path.abspath(tmpdir))) + os.chdir(tmpdir) + outputfilename = ffiplatform.compile('.', ext, + compiler_verbose, debug) + finally: + os.chdir(cwd) + _unpatch_meths(patchlist) + return outputfilename + else: + return ext, updated + else: + if c_file is None: + c_file, _ = _modname_to_file(tmpdir, module_name, '.py') + updated = make_py_source(ffi, module_name, c_file, + verbose=compiler_verbose) + if call_c_compiler: + return c_file + else: + return None, updated + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/setuptools_ext.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/setuptools_ext.py new file mode 100644 index 00000000..8fe36148 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/setuptools_ext.py @@ -0,0 +1,219 @@ +import os +import sys + +try: + basestring +except NameError: + # Python 3.x + basestring = str + +def error(msg): + from distutils.errors import DistutilsSetupError + raise DistutilsSetupError(msg) + + +def execfile(filename, glob): + # We use execfile() (here rewritten for Python 3) instead of + # __import__() to load the build script. The problem with + # a normal import is that in some packages, the intermediate + # __init__.py files may already try to import the file that + # we are generating. + with open(filename) as f: + src = f.read() + src += '\n' # Python 2.6 compatibility + code = compile(src, filename, 'exec') + exec(code, glob, glob) + + +def add_cffi_module(dist, mod_spec): + from cffi.api import FFI + + if not isinstance(mod_spec, basestring): + error("argument to 'cffi_modules=...' must be a str or a list of str," + " not %r" % (type(mod_spec).__name__,)) + mod_spec = str(mod_spec) + try: + build_file_name, ffi_var_name = mod_spec.split(':') + except ValueError: + error("%r must be of the form 'path/build.py:ffi_variable'" % + (mod_spec,)) + if not os.path.exists(build_file_name): + ext = '' + rewritten = build_file_name.replace('.', '/') + '.py' + if os.path.exists(rewritten): + ext = ' (rewrite cffi_modules to [%r])' % ( + rewritten + ':' + ffi_var_name,) + error("%r does not name an existing file%s" % (build_file_name, ext)) + + mod_vars = {'__name__': '__cffi__', '__file__': build_file_name} + execfile(build_file_name, mod_vars) + + try: + ffi = mod_vars[ffi_var_name] + except KeyError: + error("%r: object %r not found in module" % (mod_spec, + ffi_var_name)) + if not isinstance(ffi, FFI): + ffi = ffi() # maybe it's a function instead of directly an ffi + if not isinstance(ffi, FFI): + error("%r is not an FFI instance (got %r)" % (mod_spec, + type(ffi).__name__)) + if not hasattr(ffi, '_assigned_source'): + error("%r: the set_source() method was not called" % (mod_spec,)) + module_name, source, source_extension, kwds = ffi._assigned_source + if ffi._windows_unicode: + kwds = kwds.copy() + ffi._apply_windows_unicode(kwds) + + if source is None: + _add_py_module(dist, ffi, module_name) + else: + _add_c_module(dist, ffi, module_name, source, source_extension, kwds) + +def _set_py_limited_api(Extension, kwds): + """ + Add py_limited_api to kwds if setuptools >= 26 is in use. + Do not alter the setting if it already exists. + Setuptools takes care of ignoring the flag on Python 2 and PyPy. + + CPython itself should ignore the flag in a debugging version + (by not listing .abi3.so in the extensions it supports), but + it doesn't so far, creating troubles. That's why we check + for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent + of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) + + On Windows, with CPython <= 3.4, it's better not to use py_limited_api + because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. + Recently (2020) we started shipping only >= 3.5 wheels, though. So + we'll give it another try and set py_limited_api on Windows >= 3.5. + """ + from cffi import recompiler + + if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') + and recompiler.USE_LIMITED_API): + import setuptools + try: + setuptools_major_version = int(setuptools.__version__.partition('.')[0]) + if setuptools_major_version >= 26: + kwds['py_limited_api'] = True + except ValueError: # certain development versions of setuptools + # If we don't know the version number of setuptools, we + # try to set 'py_limited_api' anyway. At worst, we get a + # warning. + kwds['py_limited_api'] = True + return kwds + +def _add_c_module(dist, ffi, module_name, source, source_extension, kwds): + from distutils.core import Extension + # We are a setuptools extension. Need this build_ext for py_limited_api. + from setuptools.command.build_ext import build_ext + from distutils.dir_util import mkpath + from distutils import log + from cffi import recompiler + + allsources = ['$PLACEHOLDER'] + allsources.extend(kwds.pop('sources', [])) + kwds = _set_py_limited_api(Extension, kwds) + ext = Extension(name=module_name, sources=allsources, **kwds) + + def make_mod(tmpdir, pre_run=None): + c_file = os.path.join(tmpdir, module_name + source_extension) + log.info("generating cffi module %r" % c_file) + mkpath(tmpdir) + # a setuptools-only, API-only hook: called with the "ext" and "ffi" + # arguments just before we turn the ffi into C code. To use it, + # subclass the 'distutils.command.build_ext.build_ext' class and + # add a method 'def pre_run(self, ext, ffi)'. + if pre_run is not None: + pre_run(ext, ffi) + updated = recompiler.make_c_source(ffi, module_name, source, c_file) + if not updated: + log.info("already up-to-date") + return c_file + + if dist.ext_modules is None: + dist.ext_modules = [] + dist.ext_modules.append(ext) + + base_class = dist.cmdclass.get('build_ext', build_ext) + class build_ext_make_mod(base_class): + def run(self): + if ext.sources[0] == '$PLACEHOLDER': + pre_run = getattr(self, 'pre_run', None) + ext.sources[0] = make_mod(self.build_temp, pre_run) + base_class.run(self) + dist.cmdclass['build_ext'] = build_ext_make_mod + # NB. multiple runs here will create multiple 'build_ext_make_mod' + # classes. Even in this case the 'build_ext' command should be + # run once; but just in case, the logic above does nothing if + # called again. + + +def _add_py_module(dist, ffi, module_name): + from distutils.dir_util import mkpath + from setuptools.command.build_py import build_py + from setuptools.command.build_ext import build_ext + from distutils import log + from cffi import recompiler + + def generate_mod(py_file): + log.info("generating cffi module %r" % py_file) + mkpath(os.path.dirname(py_file)) + updated = recompiler.make_py_source(ffi, module_name, py_file) + if not updated: + log.info("already up-to-date") + + base_class = dist.cmdclass.get('build_py', build_py) + class build_py_make_mod(base_class): + def run(self): + base_class.run(self) + module_path = module_name.split('.') + module_path[-1] += '.py' + generate_mod(os.path.join(self.build_lib, *module_path)) + def get_source_files(self): + # This is called from 'setup.py sdist' only. Exclude + # the generate .py module in this case. + saved_py_modules = self.py_modules + try: + if saved_py_modules: + self.py_modules = [m for m in saved_py_modules + if m != module_name] + return base_class.get_source_files(self) + finally: + self.py_modules = saved_py_modules + dist.cmdclass['build_py'] = build_py_make_mod + + # distutils and setuptools have no notion I could find of a + # generated python module. If we don't add module_name to + # dist.py_modules, then things mostly work but there are some + # combination of options (--root and --record) that will miss + # the module. So we add it here, which gives a few apparently + # harmless warnings about not finding the file outside the + # build directory. + # Then we need to hack more in get_source_files(); see above. + if dist.py_modules is None: + dist.py_modules = [] + dist.py_modules.append(module_name) + + # the following is only for "build_ext -i" + base_class_2 = dist.cmdclass.get('build_ext', build_ext) + class build_ext_make_mod(base_class_2): + def run(self): + base_class_2.run(self) + if self.inplace: + # from get_ext_fullpath() in distutils/command/build_ext.py + module_path = module_name.split('.') + package = '.'.join(module_path[:-1]) + build_py = self.get_finalized_command('build_py') + package_dir = build_py.get_package_dir(package) + file_name = module_path[-1] + '.py' + generate_mod(os.path.join(package_dir, file_name)) + dist.cmdclass['build_ext'] = build_ext_make_mod + +def cffi_modules(dist, attr, value): + assert attr == 'cffi_modules' + if isinstance(value, basestring): + value = [value] + + for cffi_module in value: + add_cffi_module(dist, cffi_module) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_cpy.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_cpy.py new file mode 100644 index 00000000..6de0df0e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_cpy.py @@ -0,0 +1,1076 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys, imp +from . import model +from .error import VerificationError + + +class VCPythonEngine(object): + _class_key = 'x' + _gen_python_module = True + + def __init__(self, verifier): + self.verifier = verifier + self.ffi = verifier.ffi + self._struct_pending_verification = {} + self._types_of_builtin_functions = {} + + def patch_extension_kwds(self, kwds): + pass + + def find_module(self, module_name, path, so_suffixes): + try: + f, filename, descr = imp.find_module(module_name, path) + except ImportError: + return None + if f is not None: + f.close() + # Note that after a setuptools installation, there are both .py + # and .so files with the same basename. The code here relies on + # imp.find_module() locating the .so in priority. + if descr[0] not in so_suffixes: + return None + return filename + + def collect_types(self): + self._typesdict = {} + self._generate("collecttype") + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def _gettypenum(self, type): + # a KeyError here is a bug. please report it! :-) + return self._typesdict[type] + + def _do_collect_type(self, tp): + if ((not isinstance(tp, model.PrimitiveType) + or tp.name == 'long double') + and tp not in self._typesdict): + num = len(self._typesdict) + self._typesdict[tp] = num + + def write_source_to_f(self): + self.collect_types() + # + # The new module will have a _cffi_setup() function that receives + # objects from the ffi world, and that calls some setup code in + # the module. This setup code is split in several independent + # functions, e.g. one per constant. The functions are "chained" + # by ending in a tail call to each other. + # + # This is further split in two chained lists, depending on if we + # can do it at import-time or if we must wait for _cffi_setup() to + # provide us with the objects. This is needed because we + # need the values of the enum constants in order to build the + # that we may have to pass to _cffi_setup(). + # + # The following two 'chained_list_constants' items contains + # the head of these two chained lists, as a string that gives the + # call to do, if any. + self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] + # + prnt = self._prnt + # first paste some standard set of lines that are mostly '#define' + prnt(cffimod_header) + prnt() + # then paste the C source given by the user, verbatim. + prnt(self.verifier.preamble) + prnt() + # + # call generate_cpy_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._generate("decl") + # + # implement the function _cffi_setup_custom() as calling the + # head of the chained list. + self._generate_setup_custom() + prnt() + # + # produce the method table, including the entries for the + # generated Python->C function wrappers, which are done + # by generate_cpy_function_method(). + prnt('static PyMethodDef _cffi_methods[] = {') + self._generate("method") + prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},') + prnt(' {NULL, NULL, 0, NULL} /* Sentinel */') + prnt('};') + prnt() + # + # standard init. + modname = self.verifier.get_module_name() + constants = self._chained_list_constants[False] + prnt('#if PY_MAJOR_VERSION >= 3') + prnt() + prnt('static struct PyModuleDef _cffi_module_def = {') + prnt(' PyModuleDef_HEAD_INIT,') + prnt(' "%s",' % modname) + prnt(' NULL,') + prnt(' -1,') + prnt(' _cffi_methods,') + prnt(' NULL, NULL, NULL, NULL') + prnt('};') + prnt() + prnt('PyMODINIT_FUNC') + prnt('PyInit_%s(void)' % modname) + prnt('{') + prnt(' PyObject *lib;') + prnt(' lib = PyModule_Create(&_cffi_module_def);') + prnt(' if (lib == NULL)') + prnt(' return NULL;') + prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,)) + prnt(' Py_DECREF(lib);') + prnt(' return NULL;') + prnt(' }') + prnt(' return lib;') + prnt('}') + prnt() + prnt('#else') + prnt() + prnt('PyMODINIT_FUNC') + prnt('init%s(void)' % modname) + prnt('{') + prnt(' PyObject *lib;') + prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname) + prnt(' if (lib == NULL)') + prnt(' return;') + prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,)) + prnt(' return;') + prnt(' return;') + prnt('}') + prnt() + prnt('#endif') + + def load_library(self, flags=None): + # XXX review all usages of 'self' here! + # import it as a new extension module + imp.acquire_lock() + try: + if hasattr(sys, "getdlopenflags"): + previous_flags = sys.getdlopenflags() + try: + if hasattr(sys, "setdlopenflags") and flags is not None: + sys.setdlopenflags(flags) + module = imp.load_dynamic(self.verifier.get_module_name(), + self.verifier.modulefilename) + except ImportError as e: + error = "importing %r: %s" % (self.verifier.modulefilename, e) + raise VerificationError(error) + finally: + if hasattr(sys, "setdlopenflags"): + sys.setdlopenflags(previous_flags) + finally: + imp.release_lock() + # + # call loading_cpy_struct() to get the struct layout inferred by + # the C compiler + self._load(module, 'loading') + # + # the C code will need the objects. Collect them in + # order in a list. + revmapping = dict([(value, key) + for (key, value) in self._typesdict.items()]) + lst = [revmapping[i] for i in range(len(revmapping))] + lst = list(map(self.ffi._get_cached_btype, lst)) + # + # build the FFILibrary class and instance and call _cffi_setup(). + # this will set up some fields like '_cffi_types', and only then + # it will invoke the chained list of functions that will really + # build (notably) the constant objects, as if they are + # pointers, and store them as attributes on the 'library' object. + class FFILibrary(object): + _cffi_python_module = module + _cffi_ffi = self.ffi + _cffi_dir = [] + def __dir__(self): + return FFILibrary._cffi_dir + list(self.__dict__) + library = FFILibrary() + if module._cffi_setup(lst, VerificationError, library): + import warnings + warnings.warn("reimporting %r might overwrite older definitions" + % (self.verifier.get_module_name())) + # + # finally, call the loaded_cpy_xxx() functions. This will perform + # the final adjustments, like copying the Python->C wrapper + # functions from the module to the 'library' object, and setting + # up the FFILibrary class with properties for the global C variables. + self._load(module, 'loaded', library=library) + module._cffi_original_ffi = self.ffi + module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions + return library + + def _get_declarations(self): + lst = [(key, tp) for (key, (tp, qual)) in + self.ffi._parser._declarations.items()] + lst.sort() + return lst + + def _generate(self, step_name): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_cpy_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in verify(): %r" % name) + try: + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _load(self, module, step_name, **kwds): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) + try: + method(tp, realname, module, **kwds) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _generate_nothing(self, tp, name): + pass + + def _loaded_noop(self, tp, name, module, **kwds): + pass + + # ---------- + + def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): + extraarg = '' + if isinstance(tp, model.PrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + converter = '_cffi_to_c_int' + extraarg = ', %s' % tp.name + else: + converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), + tp.name.replace(' ', '_')) + errvalue = '-1' + # + elif isinstance(tp, model.PointerType): + self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, + tovar, errcode) + return + # + elif isinstance(tp, (model.StructOrUnion, model.EnumType)): + # a struct (not a struct pointer) as a function argument + self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' + % (tovar, self._gettypenum(tp), fromvar)) + self._prnt(' %s;' % errcode) + return + # + elif isinstance(tp, model.FunctionPtrType): + converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') + extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) + errvalue = 'NULL' + # + else: + raise NotImplementedError(tp) + # + self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) + self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( + tovar, tp.get_c_name(''), errvalue)) + self._prnt(' %s;' % errcode) + + def _extra_local_variables(self, tp, localvars, freelines): + if isinstance(tp, model.PointerType): + localvars.add('Py_ssize_t datasize') + localvars.add('struct _cffi_freeme_s *large_args_free = NULL') + freelines.add('if (large_args_free != NULL)' + ' _cffi_free_array_arguments(large_args_free);') + + def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): + self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') + self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( + self._gettypenum(tp), fromvar, tovar)) + self._prnt(' if (datasize != 0) {') + self._prnt(' %s = ((size_t)datasize) <= 640 ? ' + 'alloca((size_t)datasize) : NULL;' % (tovar,)) + self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, ' + '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar)) + self._prnt(' datasize, &large_args_free) < 0)') + self._prnt(' %s;' % errcode) + self._prnt(' }') + + def _convert_expr_from_c(self, tp, var, context): + if isinstance(tp, model.PrimitiveType): + if tp.is_integer_type() and tp.name != '_Bool': + return '_cffi_from_c_int(%s, %s)' % (var, tp.name) + elif tp.name != 'long double': + return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) + else: + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.ArrayType): + return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( + var, self._gettypenum(model.PointerType(tp.item))) + elif isinstance(tp, model.StructOrUnion): + if tp.fldnames is None: + raise TypeError("'%s' is used as %s, but is opaque" % ( + tp._get_c_name(), context)) + return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + elif isinstance(tp, model.EnumType): + return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( + var, self._gettypenum(tp)) + else: + raise NotImplementedError(tp) + + # ---------- + # typedefs: generates no code so far + + _generate_cpy_typedef_collecttype = _generate_nothing + _generate_cpy_typedef_decl = _generate_nothing + _generate_cpy_typedef_method = _generate_nothing + _loading_cpy_typedef = _loaded_noop + _loaded_cpy_typedef = _loaded_noop + + # ---------- + # function declarations + + def _generate_cpy_function_collecttype(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + self._do_collect_type(tp) + else: + # don't call _do_collect_type(tp) in this common case, + # otherwise test_autofilled_struct_as_argument fails + for type in tp.args: + self._do_collect_type(type) + self._do_collect_type(tp.result) + + def _generate_cpy_function_decl(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no CPython wrapper) + self._generate_cpy_const(False, name, tp) + return + prnt = self._prnt + numargs = len(tp.args) + if numargs == 0: + argname = 'noarg' + elif numargs == 1: + argname = 'arg0' + else: + argname = 'args' + prnt('static PyObject *') + prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) + prnt('{') + # + context = 'argument of %s' % name + for i, type in enumerate(tp.args): + prnt(' %s;' % type.get_c_name(' x%d' % i, context)) + # + localvars = set() + freelines = set() + for type in tp.args: + self._extra_local_variables(type, localvars, freelines) + for decl in sorted(localvars): + prnt(' %s;' % (decl,)) + # + if not isinstance(tp.result, model.VoidType): + result_code = 'result = ' + context = 'result of %s' % name + prnt(' %s;' % tp.result.get_c_name(' result', context)) + prnt(' PyObject *pyresult;') + else: + result_code = '' + # + if len(tp.args) > 1: + rng = range(len(tp.args)) + for i in rng: + prnt(' PyObject *arg%d;' % i) + prnt() + prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( + 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) + prnt(' return NULL;') + prnt() + # + for i, type in enumerate(tp.args): + self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, + 'return NULL') + prnt() + # + prnt(' Py_BEGIN_ALLOW_THREADS') + prnt(' _cffi_restore_errno();') + prnt(' { %s%s(%s); }' % ( + result_code, name, + ', '.join(['x%d' % i for i in range(len(tp.args))]))) + prnt(' _cffi_save_errno();') + prnt(' Py_END_ALLOW_THREADS') + prnt() + # + prnt(' (void)self; /* unused */') + if numargs == 0: + prnt(' (void)noarg; /* unused */') + if result_code: + prnt(' pyresult = %s;' % + self._convert_expr_from_c(tp.result, 'result', 'result type')) + for freeline in freelines: + prnt(' ' + freeline) + prnt(' return pyresult;') + else: + for freeline in freelines: + prnt(' ' + freeline) + prnt(' Py_INCREF(Py_None);') + prnt(' return Py_None;') + prnt('}') + prnt() + + def _generate_cpy_function_method(self, tp, name): + if tp.ellipsis: + return + numargs = len(tp.args) + if numargs == 0: + meth = 'METH_NOARGS' + elif numargs == 1: + meth = 'METH_O' + else: + meth = 'METH_VARARGS' + self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth)) + + _loading_cpy_function = _loaded_noop + + def _loaded_cpy_function(self, tp, name, module, library): + if tp.ellipsis: + return + func = getattr(module, name) + setattr(library, name, func) + self._types_of_builtin_functions[func] = tp + + # ---------- + # named structs + + _generate_cpy_struct_collecttype = _generate_nothing + def _generate_cpy_struct_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'struct', name) + def _generate_cpy_struct_method(self, tp, name): + self._generate_struct_or_union_method(tp, 'struct', name) + def _loading_cpy_struct(self, tp, name, module): + self._loading_struct_or_union(tp, 'struct', name, module) + def _loaded_cpy_struct(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + _generate_cpy_union_collecttype = _generate_nothing + def _generate_cpy_union_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'union', name) + def _generate_cpy_union_method(self, tp, name): + self._generate_struct_or_union_method(tp, 'union', name) + def _loading_cpy_union(self, tp, name, module): + self._loading_struct_or_union(tp, 'union', name, module) + def _loaded_cpy_union(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_struct_or_union_decl(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + checkfuncname = '_cffi_check_%s_%s' % (prefix, name) + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + cname = ('%s %s' % (prefix, name)).strip() + # + prnt = self._prnt + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if (isinstance(ftype, model.PrimitiveType) + and ftype.is_integer_type()) or fbitsize >= 0: + # accept all integers, but complain on float or double + prnt(' (void)((p->%s) << 1);' % fname) + else: + # only accept exactly the type declared. + try: + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + prnt('static PyObject *') + prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,)) + prnt('{') + prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) + prnt(' static Py_ssize_t nums[] = {') + prnt(' sizeof(%s),' % cname) + prnt(' offsetof(struct _cffi_aligncheck, y),') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + prnt(' offsetof(%s, %s),' % (cname, fname)) + if isinstance(ftype, model.ArrayType) and ftype.length is None: + prnt(' 0, /* %s */' % ftype._get_c_name()) + else: + prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) + prnt(' -1') + prnt(' };') + prnt(' (void)self; /* unused */') + prnt(' (void)noarg; /* unused */') + prnt(' return _cffi_get_struct_layout(nums);') + prnt(' /* the next line is not executed, but compiled */') + prnt(' %s(0);' % (checkfuncname,)) + prnt('}') + prnt() + + def _generate_struct_or_union_method(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname, + layoutfuncname)) + + def _loading_struct_or_union(self, tp, prefix, name, module): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + # + function = getattr(module, layoutfuncname) + layout = function() + if isinstance(tp, model.StructOrUnion) and tp.partial: + # use the function()'s sizes and offsets to guide the + # layout of the struct + totalsize = layout[0] + totalalignment = layout[1] + fieldofs = layout[2::2] + fieldsize = layout[3::2] + tp.force_flatten() + assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) + tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment + else: + cname = ('%s %s' % (prefix, name)).strip() + self._struct_pending_verification[tp] = layout, cname + + def _loaded_struct_or_union(self, tp): + if tp.fldnames is None: + return # nothing to do with opaque structs + self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered + + if tp in self._struct_pending_verification: + # check that the layout sizes and offsets match the real ones + def check(realvalue, expectedvalue, msg): + if realvalue != expectedvalue: + raise VerificationError( + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) + ffi = self.ffi + BStruct = ffi._get_cached_btype(tp) + layout, cname = self._struct_pending_verification.pop(tp) + check(layout[0], ffi.sizeof(BStruct), "wrong total size") + check(layout[1], ffi.alignof(BStruct), "wrong total alignment") + i = 2 + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + check(layout[i], ffi.offsetof(BStruct, fname), + "wrong offset for field %r" % (fname,)) + if layout[i+1] != 0: + BField = ffi._get_cached_btype(ftype) + check(layout[i+1], ffi.sizeof(BField), + "wrong size for field %r" % (fname,)) + i += 2 + assert i == len(layout) + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + _generate_cpy_anonymous_collecttype = _generate_nothing + + def _generate_cpy_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_cpy_enum_decl(tp, name, '') + else: + self._generate_struct_or_union_decl(tp, '', name) + + def _generate_cpy_anonymous_method(self, tp, name): + if not isinstance(tp, model.EnumType): + self._generate_struct_or_union_method(tp, '', name) + + def _loading_cpy_anonymous(self, tp, name, module): + if isinstance(tp, model.EnumType): + self._loading_cpy_enum(tp, name, module) + else: + self._loading_struct_or_union(tp, '', name, module) + + def _loaded_cpy_anonymous(self, tp, name, module, **kwds): + if isinstance(tp, model.EnumType): + self._loaded_cpy_enum(tp, name, module, **kwds) + else: + self._loaded_struct_or_union(tp) + + # ---------- + # constants, likely declared with '#define' + + def _generate_cpy_const(self, is_int, name, tp=None, category='const', + vartp=None, delayed=True, size_too=False, + check_value=None): + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + prnt('static int %s(PyObject *lib)' % funcname) + prnt('{') + prnt(' PyObject *o;') + prnt(' int res;') + if not is_int: + prnt(' %s;' % (vartp or tp).get_c_name(' i', name)) + else: + assert category == 'const' + # + if check_value is not None: + self._check_int_constant_value(name, check_value) + # + if not is_int: + if category == 'var': + realexpr = '&' + name + else: + realexpr = name + prnt(' i = (%s);' % (realexpr,)) + prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', + 'variable type'),)) + assert delayed + else: + prnt(' o = _cffi_from_c_int_const(%s);' % name) + prnt(' if (o == NULL)') + prnt(' return -1;') + if size_too: + prnt(' {') + prnt(' PyObject *o1 = o;') + prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));' + % (name,)) + prnt(' Py_DECREF(o1);') + prnt(' if (o == NULL)') + prnt(' return -1;') + prnt(' }') + prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name) + prnt(' Py_DECREF(o);') + prnt(' if (res < 0)') + prnt(' return -1;') + prnt(' return %s;' % self._chained_list_constants[delayed]) + self._chained_list_constants[delayed] = funcname + '(lib)' + prnt('}') + prnt() + + def _generate_cpy_constant_collecttype(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + if not is_int: + self._do_collect_type(tp) + + def _generate_cpy_constant_decl(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + self._generate_cpy_const(is_int, name, tp) + + _generate_cpy_constant_method = _generate_nothing + _loading_cpy_constant = _loaded_noop + _loaded_cpy_constant = _loaded_noop + + # ---------- + # enums + + def _check_int_constant_value(self, name, value, err_prefix=''): + prnt = self._prnt + if value <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( + name, name, value)) + else: + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( + name, name, value)) + prnt(' char buf[64];') + prnt(' if ((%s) <= 0)' % name) + prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name) + prnt(' else') + prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % + name) + prnt(' PyErr_Format(_cffi_VerificationError,') + prnt(' "%s%s has the real value %s, not %s",') + prnt(' "%s", "%s", buf, "%d");' % ( + err_prefix, name, value)) + prnt(' return -1;') + prnt(' }') + + def _enum_funcname(self, prefix, name): + # "$enum_$1" => "___D_enum____D_1" + name = name.replace('$', '___D_') + return '_cffi_e_%s_%s' % (prefix, name) + + def _generate_cpy_enum_decl(self, tp, name, prefix='enum'): + if tp.partial: + for enumerator in tp.enumerators: + self._generate_cpy_const(True, enumerator, delayed=False) + return + # + funcname = self._enum_funcname(prefix, name) + prnt = self._prnt + prnt('static int %s(PyObject *lib)' % funcname) + prnt('{') + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._check_int_constant_value(enumerator, enumvalue, + "enum %s: " % name) + prnt(' return %s;' % self._chained_list_constants[True]) + self._chained_list_constants[True] = funcname + '(lib)' + prnt('}') + prnt() + + _generate_cpy_enum_collecttype = _generate_nothing + _generate_cpy_enum_method = _generate_nothing + + def _loading_cpy_enum(self, tp, name, module): + if tp.partial: + enumvalues = [getattr(module, enumerator) + for enumerator in tp.enumerators] + tp.enumvalues = tuple(enumvalues) + tp.partial_resolved = True + + def _loaded_cpy_enum(self, tp, name, module, library): + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + setattr(library, enumerator, enumvalue) + + # ---------- + # macros: for now only for integers + + def _generate_cpy_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_cpy_const(True, name, check_value=check_value) + + _generate_cpy_macro_collecttype = _generate_nothing + _generate_cpy_macro_method = _generate_nothing + _loading_cpy_macro = _loaded_noop + _loaded_cpy_macro = _loaded_noop + + # ---------- + # global variables + + def _generate_cpy_variable_collecttype(self, tp, name): + if isinstance(tp, model.ArrayType): + tp_ptr = model.PointerType(tp.item) + else: + tp_ptr = model.PointerType(tp) + self._do_collect_type(tp_ptr) + + def _generate_cpy_variable_decl(self, tp, name): + if isinstance(tp, model.ArrayType): + tp_ptr = model.PointerType(tp.item) + self._generate_cpy_const(False, name, tp, vartp=tp_ptr, + size_too = tp.length_is_unknown()) + else: + tp_ptr = model.PointerType(tp) + self._generate_cpy_const(False, name, tp_ptr, category='var') + + _generate_cpy_variable_method = _generate_nothing + _loading_cpy_variable = _loaded_noop + + def _loaded_cpy_variable(self, tp, name, module, library): + value = getattr(library, name) + if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the + # sense that "a=..." is forbidden + if tp.length_is_unknown(): + assert isinstance(value, tuple) + (value, size) = value + BItemType = self.ffi._get_cached_btype(tp.item) + length, rest = divmod(size, self.ffi.sizeof(BItemType)) + if rest != 0: + raise VerificationError( + "bad size: %r does not seem to be an array of %s" % + (name, tp.item)) + tp = tp.resolve_length(length) + # 'value' is a which we have to replace with + # a if the N is actually known + if tp.length is not None: + BArray = self.ffi._get_cached_btype(tp) + value = self.ffi.cast(BArray, value) + setattr(library, name, value) + return + # remove ptr= from the library instance, and replace + # it by a property on the class, which reads/writes into ptr[0]. + ptr = value + delattr(library, name) + def getter(library): + return ptr[0] + def setter(library, value): + ptr[0] = value + setattr(type(library), name, property(getter, setter)) + type(library)._cffi_dir.append(name) + + # ---------- + + def _generate_setup_custom(self): + prnt = self._prnt + prnt('static int _cffi_setup_custom(PyObject *lib)') + prnt('{') + prnt(' return %s;' % self._chained_list_constants[True]) + prnt('}') + +cffimod_header = r''' +#include +#include + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif + +#if PY_MAJOR_VERSION < 3 +# undef PyCapsule_CheckExact +# undef PyCapsule_GetPointer +# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) +# define PyCapsule_GetPointer(capsule, name) \ + (PyCObject_AsVoidPtr(capsule)) +#endif + +#if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong PyLong_FromLong +#endif + +#define _cffi_from_c_double PyFloat_FromDouble +#define _cffi_from_c_float PyFloat_FromDouble +#define _cffi_from_c_long PyInt_FromLong +#define _cffi_from_c_ulong PyLong_FromUnsignedLong +#define _cffi_from_c_longlong PyLong_FromLongLong +#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong +#define _cffi_from_c__Bool PyBool_FromLong + +#define _cffi_to_c_double PyFloat_AsDouble +#define _cffi_to_c_float PyFloat_AsDouble + +#define _cffi_from_c_int_const(x) \ + (((x) > 0) ? \ + ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \ + ((long long)(x) >= (long long)LONG_MIN) ? \ + PyInt_FromLong((long)(x)) : \ + PyLong_FromLongLong((long long)(x))) + +#define _cffi_from_c_int(x, type) \ + (((type)-1) > 0 ? /* unsigned */ \ + (sizeof(type) < sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + sizeof(type) == sizeof(long) ? \ + PyLong_FromUnsignedLong((unsigned long)x) : \ + PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ + (sizeof(type) <= sizeof(long) ? \ + PyInt_FromLong((long)x) : \ + PyLong_FromLongLong((long long)x))) + +#define _cffi_to_c_int(o, type) \ + ((type)( \ + sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ + : (type)_cffi_to_c_i8(o)) : \ + sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ + : (type)_cffi_to_c_i16(o)) : \ + sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ + : (type)_cffi_to_c_i32(o)) : \ + sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ + : (type)_cffi_to_c_i64(o)) : \ + (Py_FatalError("unsupported size for type " #type), (type)0))) + +#define _cffi_to_c_i8 \ + ((int(*)(PyObject *))_cffi_exports[1]) +#define _cffi_to_c_u8 \ + ((int(*)(PyObject *))_cffi_exports[2]) +#define _cffi_to_c_i16 \ + ((int(*)(PyObject *))_cffi_exports[3]) +#define _cffi_to_c_u16 \ + ((int(*)(PyObject *))_cffi_exports[4]) +#define _cffi_to_c_i32 \ + ((int(*)(PyObject *))_cffi_exports[5]) +#define _cffi_to_c_u32 \ + ((unsigned int(*)(PyObject *))_cffi_exports[6]) +#define _cffi_to_c_i64 \ + ((long long(*)(PyObject *))_cffi_exports[7]) +#define _cffi_to_c_u64 \ + ((unsigned long long(*)(PyObject *))_cffi_exports[8]) +#define _cffi_to_c_char \ + ((int(*)(PyObject *))_cffi_exports[9]) +#define _cffi_from_c_pointer \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) +#define _cffi_to_c_pointer \ + ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) +#define _cffi_get_struct_layout \ + ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12]) +#define _cffi_restore_errno \ + ((void(*)(void))_cffi_exports[13]) +#define _cffi_save_errno \ + ((void(*)(void))_cffi_exports[14]) +#define _cffi_from_c_char \ + ((PyObject *(*)(char))_cffi_exports[15]) +#define _cffi_from_c_deref \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) +#define _cffi_to_c \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) +#define _cffi_from_c_struct \ + ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) +#define _cffi_to_c_wchar_t \ + ((wchar_t(*)(PyObject *))_cffi_exports[19]) +#define _cffi_from_c_wchar_t \ + ((PyObject *(*)(wchar_t))_cffi_exports[20]) +#define _cffi_to_c_long_double \ + ((long double(*)(PyObject *))_cffi_exports[21]) +#define _cffi_to_c__Bool \ + ((_Bool(*)(PyObject *))_cffi_exports[22]) +#define _cffi_prepare_pointer_call_argument \ + ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) +#define _cffi_convert_array_from_object \ + ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) +#define _CFFI_NUM_EXPORTS 25 + +typedef struct _ctypedescr CTypeDescrObject; + +static void *_cffi_exports[_CFFI_NUM_EXPORTS]; +static PyObject *_cffi_types, *_cffi_VerificationError; + +static int _cffi_setup_custom(PyObject *lib); /* forward */ + +static PyObject *_cffi_setup(PyObject *self, PyObject *args) +{ + PyObject *library; + int was_alive = (_cffi_types != NULL); + (void)self; /* unused */ + if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, + &library)) + return NULL; + Py_INCREF(_cffi_types); + Py_INCREF(_cffi_VerificationError); + if (_cffi_setup_custom(library) < 0) + return NULL; + return PyBool_FromLong(was_alive); +} + +union _cffi_union_alignment_u { + unsigned char m_char; + unsigned short m_short; + unsigned int m_int; + unsigned long m_long; + unsigned long long m_longlong; + float m_float; + double m_double; + long double m_longdouble; +}; + +struct _cffi_freeme_s { + struct _cffi_freeme_s *next; + union _cffi_union_alignment_u alignment; +}; + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg, + char **output_data, Py_ssize_t datasize, + struct _cffi_freeme_s **freeme) +{ + char *p; + if (datasize < 0) + return -1; + + p = *output_data; + if (p == NULL) { + struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc( + offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize); + if (fp == NULL) + return -1; + fp->next = *freeme; + *freeme = fp; + p = *output_data = (char *)&fp->alignment; + } + memset((void *)p, 0, (size_t)datasize); + return _cffi_convert_array_from_object(p, ctptr, arg); +} + +#ifdef __GNUC__ + __attribute__((unused)) +#endif +static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme) +{ + do { + void *p = (void *)freeme; + freeme = freeme->next; + PyObject_Free(p); + } while (freeme != NULL); +} + +static int _cffi_init(void) +{ + PyObject *module, *c_api_object = NULL; + + module = PyImport_ImportModule("_cffi_backend"); + if (module == NULL) + goto failure; + + c_api_object = PyObject_GetAttrString(module, "_C_API"); + if (c_api_object == NULL) + goto failure; + if (!PyCapsule_CheckExact(c_api_object)) { + PyErr_SetNone(PyExc_ImportError); + goto failure; + } + memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"), + _CFFI_NUM_EXPORTS * sizeof(void *)); + + Py_DECREF(module); + Py_DECREF(c_api_object); + return 0; + + failure: + Py_XDECREF(module); + Py_XDECREF(c_api_object); + return -1; +} + +#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num)) + +/**********/ +''' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_gen.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_gen.py new file mode 100644 index 00000000..26421526 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/vengine_gen.py @@ -0,0 +1,675 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys, os +import types + +from . import model +from .error import VerificationError + + +class VGenericEngine(object): + _class_key = 'g' + _gen_python_module = False + + def __init__(self, verifier): + self.verifier = verifier + self.ffi = verifier.ffi + self.export_symbols = [] + self._struct_pending_verification = {} + + def patch_extension_kwds(self, kwds): + # add 'export_symbols' to the dictionary. Note that we add the + # list before filling it. When we fill it, it will thus also show + # up in kwds['export_symbols']. + kwds.setdefault('export_symbols', self.export_symbols) + + def find_module(self, module_name, path, so_suffixes): + for so_suffix in so_suffixes: + basename = module_name + so_suffix + if path is None: + path = sys.path + for dirname in path: + filename = os.path.join(dirname, basename) + if os.path.isfile(filename): + return filename + + def collect_types(self): + pass # not needed in the generic engine + + def _prnt(self, what=''): + self._f.write(what + '\n') + + def write_source_to_f(self): + prnt = self._prnt + # first paste some standard set of lines that are mostly '#include' + prnt(cffimod_header) + # then paste the C source given by the user, verbatim. + prnt(self.verifier.preamble) + # + # call generate_gen_xxx_decl(), for every xxx found from + # ffi._parser._declarations. This generates all the functions. + self._generate('decl') + # + # on Windows, distutils insists on putting init_cffi_xyz in + # 'export_symbols', so instead of fighting it, just give up and + # give it one + if sys.platform == 'win32': + if sys.version_info >= (3,): + prefix = 'PyInit_' + else: + prefix = 'init' + modname = self.verifier.get_module_name() + prnt("void %s%s(void) { }\n" % (prefix, modname)) + + def load_library(self, flags=0): + # import it with the CFFI backend + backend = self.ffi._backend + # needs to make a path that contains '/', on Posix + filename = os.path.join(os.curdir, self.verifier.modulefilename) + module = backend.load_library(filename, flags) + # + # call loading_gen_struct() to get the struct layout inferred by + # the C compiler + self._load(module, 'loading') + + # build the FFILibrary class and instance, this is a module subclass + # because modules are expected to have usually-constant-attributes and + # in PyPy this means the JIT is able to treat attributes as constant, + # which we want. + class FFILibrary(types.ModuleType): + _cffi_generic_module = module + _cffi_ffi = self.ffi + _cffi_dir = [] + def __dir__(self): + return FFILibrary._cffi_dir + library = FFILibrary("") + # + # finally, call the loaded_gen_xxx() functions. This will set + # up the 'library' object. + self._load(module, 'loaded', library=library) + return library + + def _get_declarations(self): + lst = [(key, tp) for (key, (tp, qual)) in + self.ffi._parser._declarations.items()] + lst.sort() + return lst + + def _generate(self, step_name): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + try: + method = getattr(self, '_generate_gen_%s_%s' % (kind, + step_name)) + except AttributeError: + raise VerificationError( + "not implemented in verify(): %r" % name) + try: + method(tp, realname) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _load(self, module, step_name, **kwds): + for name, tp in self._get_declarations(): + kind, realname = name.split(' ', 1) + method = getattr(self, '_%s_gen_%s' % (step_name, kind)) + try: + method(tp, realname, module, **kwds) + except Exception as e: + model.attach_exception_info(e, name) + raise + + def _generate_nothing(self, tp, name): + pass + + def _loaded_noop(self, tp, name, module, **kwds): + pass + + # ---------- + # typedefs: generates no code so far + + _generate_gen_typedef_decl = _generate_nothing + _loading_gen_typedef = _loaded_noop + _loaded_gen_typedef = _loaded_noop + + # ---------- + # function declarations + + def _generate_gen_function_decl(self, tp, name): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + # cannot support vararg functions better than this: check for its + # exact type (including the fixed arguments), and build it as a + # constant function pointer (no _cffi_f_%s wrapper) + self._generate_gen_const(False, name, tp) + return + prnt = self._prnt + numargs = len(tp.args) + argnames = [] + for i, type in enumerate(tp.args): + indirection = '' + if isinstance(type, model.StructOrUnion): + indirection = '*' + argnames.append('%sx%d' % (indirection, i)) + context = 'argument of %s' % name + arglist = [type.get_c_name(' %s' % arg, context) + for type, arg in zip(tp.args, argnames)] + tpresult = tp.result + if isinstance(tpresult, model.StructOrUnion): + arglist.insert(0, tpresult.get_c_name(' *r', context)) + tpresult = model.void_type + arglist = ', '.join(arglist) or 'void' + wrappername = '_cffi_f_%s' % name + self.export_symbols.append(wrappername) + if tp.abi: + abi = tp.abi + ' ' + else: + abi = '' + funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist) + context = 'result of %s' % name + prnt(tpresult.get_c_name(funcdecl, context)) + prnt('{') + # + if isinstance(tp.result, model.StructOrUnion): + result_code = '*r = ' + elif not isinstance(tp.result, model.VoidType): + result_code = 'return ' + else: + result_code = '' + prnt(' %s%s(%s);' % (result_code, name, ', '.join(argnames))) + prnt('}') + prnt() + + _loading_gen_function = _loaded_noop + + def _loaded_gen_function(self, tp, name, module, library): + assert isinstance(tp, model.FunctionPtrType) + if tp.ellipsis: + newfunction = self._load_constant(False, tp, name, module) + else: + indirections = [] + base_tp = tp + if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args) + or isinstance(tp.result, model.StructOrUnion)): + indirect_args = [] + for i, typ in enumerate(tp.args): + if isinstance(typ, model.StructOrUnion): + typ = model.PointerType(typ) + indirections.append((i, typ)) + indirect_args.append(typ) + indirect_result = tp.result + if isinstance(indirect_result, model.StructOrUnion): + if indirect_result.fldtypes is None: + raise TypeError("'%s' is used as result type, " + "but is opaque" % ( + indirect_result._get_c_name(),)) + indirect_result = model.PointerType(indirect_result) + indirect_args.insert(0, indirect_result) + indirections.insert(0, ("result", indirect_result)) + indirect_result = model.void_type + tp = model.FunctionPtrType(tuple(indirect_args), + indirect_result, tp.ellipsis) + BFunc = self.ffi._get_cached_btype(tp) + wrappername = '_cffi_f_%s' % name + newfunction = module.load_function(BFunc, wrappername) + for i, typ in indirections: + newfunction = self._make_struct_wrapper(newfunction, i, typ, + base_tp) + setattr(library, name, newfunction) + type(library)._cffi_dir.append(name) + + def _make_struct_wrapper(self, oldfunc, i, tp, base_tp): + backend = self.ffi._backend + BType = self.ffi._get_cached_btype(tp) + if i == "result": + ffi = self.ffi + def newfunc(*args): + res = ffi.new(BType) + oldfunc(res, *args) + return res[0] + else: + def newfunc(*args): + args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:] + return oldfunc(*args) + newfunc._cffi_base_type = base_tp + return newfunc + + # ---------- + # named structs + + def _generate_gen_struct_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'struct', name) + + def _loading_gen_struct(self, tp, name, module): + self._loading_struct_or_union(tp, 'struct', name, module) + + def _loaded_gen_struct(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_gen_union_decl(self, tp, name): + assert name == tp.name + self._generate_struct_or_union_decl(tp, 'union', name) + + def _loading_gen_union(self, tp, name, module): + self._loading_struct_or_union(tp, 'union', name, module) + + def _loaded_gen_union(self, tp, name, module, **kwds): + self._loaded_struct_or_union(tp) + + def _generate_struct_or_union_decl(self, tp, prefix, name): + if tp.fldnames is None: + return # nothing to do with opaque structs + checkfuncname = '_cffi_check_%s_%s' % (prefix, name) + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + cname = ('%s %s' % (prefix, name)).strip() + # + prnt = self._prnt + prnt('static void %s(%s *p)' % (checkfuncname, cname)) + prnt('{') + prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if (isinstance(ftype, model.PrimitiveType) + and ftype.is_integer_type()) or fbitsize >= 0: + # accept all integers, but complain on float or double + prnt(' (void)((p->%s) << 1);' % fname) + else: + # only accept exactly the type declared. + try: + prnt(' { %s = &p->%s; (void)tmp; }' % ( + ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual), + fname)) + except VerificationError as e: + prnt(' /* %s */' % str(e)) # cannot verify it, ignore + prnt('}') + self.export_symbols.append(layoutfuncname) + prnt('intptr_t %s(intptr_t i)' % (layoutfuncname,)) + prnt('{') + prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname) + prnt(' static intptr_t nums[] = {') + prnt(' sizeof(%s),' % cname) + prnt(' offsetof(struct _cffi_aligncheck, y),') + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + prnt(' offsetof(%s, %s),' % (cname, fname)) + if isinstance(ftype, model.ArrayType) and ftype.length is None: + prnt(' 0, /* %s */' % ftype._get_c_name()) + else: + prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) + prnt(' -1') + prnt(' };') + prnt(' return nums[i];') + prnt(' /* the next line is not executed, but compiled */') + prnt(' %s(0);' % (checkfuncname,)) + prnt('}') + prnt() + + def _loading_struct_or_union(self, tp, prefix, name, module): + if tp.fldnames is None: + return # nothing to do with opaque structs + layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name) + # + BFunc = self.ffi._typeof_locked("intptr_t(*)(intptr_t)")[0] + function = module.load_function(BFunc, layoutfuncname) + layout = [] + num = 0 + while True: + x = function(num) + if x < 0: break + layout.append(x) + num += 1 + if isinstance(tp, model.StructOrUnion) and tp.partial: + # use the function()'s sizes and offsets to guide the + # layout of the struct + totalsize = layout[0] + totalalignment = layout[1] + fieldofs = layout[2::2] + fieldsize = layout[3::2] + tp.force_flatten() + assert len(fieldofs) == len(fieldsize) == len(tp.fldnames) + tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment + else: + cname = ('%s %s' % (prefix, name)).strip() + self._struct_pending_verification[tp] = layout, cname + + def _loaded_struct_or_union(self, tp): + if tp.fldnames is None: + return # nothing to do with opaque structs + self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered + + if tp in self._struct_pending_verification: + # check that the layout sizes and offsets match the real ones + def check(realvalue, expectedvalue, msg): + if realvalue != expectedvalue: + raise VerificationError( + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) + ffi = self.ffi + BStruct = ffi._get_cached_btype(tp) + layout, cname = self._struct_pending_verification.pop(tp) + check(layout[0], ffi.sizeof(BStruct), "wrong total size") + check(layout[1], ffi.alignof(BStruct), "wrong total alignment") + i = 2 + for fname, ftype, fbitsize, fqual in tp.enumfields(): + if fbitsize >= 0: + continue # xxx ignore fbitsize for now + check(layout[i], ffi.offsetof(BStruct, fname), + "wrong offset for field %r" % (fname,)) + if layout[i+1] != 0: + BField = ffi._get_cached_btype(ftype) + check(layout[i+1], ffi.sizeof(BField), + "wrong size for field %r" % (fname,)) + i += 2 + assert i == len(layout) + + # ---------- + # 'anonymous' declarations. These are produced for anonymous structs + # or unions; the 'name' is obtained by a typedef. + + def _generate_gen_anonymous_decl(self, tp, name): + if isinstance(tp, model.EnumType): + self._generate_gen_enum_decl(tp, name, '') + else: + self._generate_struct_or_union_decl(tp, '', name) + + def _loading_gen_anonymous(self, tp, name, module): + if isinstance(tp, model.EnumType): + self._loading_gen_enum(tp, name, module, '') + else: + self._loading_struct_or_union(tp, '', name, module) + + def _loaded_gen_anonymous(self, tp, name, module, **kwds): + if isinstance(tp, model.EnumType): + self._loaded_gen_enum(tp, name, module, **kwds) + else: + self._loaded_struct_or_union(tp) + + # ---------- + # constants, likely declared with '#define' + + def _generate_gen_const(self, is_int, name, tp=None, category='const', + check_value=None): + prnt = self._prnt + funcname = '_cffi_%s_%s' % (category, name) + self.export_symbols.append(funcname) + if check_value is not None: + assert is_int + assert category == 'const' + prnt('int %s(char *out_error)' % funcname) + prnt('{') + self._check_int_constant_value(name, check_value) + prnt(' return 0;') + prnt('}') + elif is_int: + assert category == 'const' + prnt('int %s(long long *out_value)' % funcname) + prnt('{') + prnt(' *out_value = (long long)(%s);' % (name,)) + prnt(' return (%s) <= 0;' % (name,)) + prnt('}') + else: + assert tp is not None + assert check_value is None + if category == 'var': + ampersand = '&' + else: + ampersand = '' + extra = '' + if category == 'const' and isinstance(tp, model.StructOrUnion): + extra = 'const *' + ampersand = '&' + prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name)) + prnt('{') + prnt(' return (%s%s);' % (ampersand, name)) + prnt('}') + prnt() + + def _generate_gen_constant_decl(self, tp, name): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + self._generate_gen_const(is_int, name, tp) + + _loading_gen_constant = _loaded_noop + + def _load_constant(self, is_int, tp, name, module, check_value=None): + funcname = '_cffi_const_%s' % name + if check_value is not None: + assert is_int + self._load_known_int_constant(module, funcname) + value = check_value + elif is_int: + BType = self.ffi._typeof_locked("long long*")[0] + BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0] + function = module.load_function(BFunc, funcname) + p = self.ffi.new(BType) + negative = function(p) + value = int(p[0]) + if value < 0 and not negative: + BLongLong = self.ffi._typeof_locked("long long")[0] + value += (1 << (8*self.ffi.sizeof(BLongLong))) + else: + assert check_value is None + fntypeextra = '(*)(void)' + if isinstance(tp, model.StructOrUnion): + fntypeextra = '*' + fntypeextra + BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0] + function = module.load_function(BFunc, funcname) + value = function() + if isinstance(tp, model.StructOrUnion): + value = value[0] + return value + + def _loaded_gen_constant(self, tp, name, module, library): + is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() + value = self._load_constant(is_int, tp, name, module) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + + # ---------- + # enums + + def _check_int_constant_value(self, name, value): + prnt = self._prnt + if value <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( + name, name, value)) + else: + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( + name, name, value)) + prnt(' char buf[64];') + prnt(' if ((%s) <= 0)' % name) + prnt(' sprintf(buf, "%%ld", (long)(%s));' % name) + prnt(' else') + prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % + name) + prnt(' sprintf(out_error, "%s has the real value %s, not %s",') + prnt(' "%s", buf, "%d");' % (name[:100], value)) + prnt(' return -1;') + prnt(' }') + + def _load_known_int_constant(self, module, funcname): + BType = self.ffi._typeof_locked("char[]")[0] + BFunc = self.ffi._typeof_locked("int(*)(char*)")[0] + function = module.load_function(BFunc, funcname) + p = self.ffi.new(BType, 256) + if function(p) < 0: + error = self.ffi.string(p) + if sys.version_info >= (3,): + error = str(error, 'utf-8') + raise VerificationError(error) + + def _enum_funcname(self, prefix, name): + # "$enum_$1" => "___D_enum____D_1" + name = name.replace('$', '___D_') + return '_cffi_e_%s_%s' % (prefix, name) + + def _generate_gen_enum_decl(self, tp, name, prefix='enum'): + if tp.partial: + for enumerator in tp.enumerators: + self._generate_gen_const(True, enumerator) + return + # + funcname = self._enum_funcname(prefix, name) + self.export_symbols.append(funcname) + prnt = self._prnt + prnt('int %s(char *out_error)' % funcname) + prnt('{') + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + self._check_int_constant_value(enumerator, enumvalue) + prnt(' return 0;') + prnt('}') + prnt() + + def _loading_gen_enum(self, tp, name, module, prefix='enum'): + if tp.partial: + enumvalues = [self._load_constant(True, tp, enumerator, module) + for enumerator in tp.enumerators] + tp.enumvalues = tuple(enumvalues) + tp.partial_resolved = True + else: + funcname = self._enum_funcname(prefix, name) + self._load_known_int_constant(module, funcname) + + def _loaded_gen_enum(self, tp, name, module, library): + for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): + setattr(library, enumerator, enumvalue) + type(library)._cffi_dir.append(enumerator) + + # ---------- + # macros: for now only for integers + + def _generate_gen_macro_decl(self, tp, name): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + self._generate_gen_const(True, name, check_value=check_value) + + _loading_gen_macro = _loaded_noop + + def _loaded_gen_macro(self, tp, name, module, library): + if tp == '...': + check_value = None + else: + check_value = tp # an integer + value = self._load_constant(True, tp, name, module, + check_value=check_value) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + + # ---------- + # global variables + + def _generate_gen_variable_decl(self, tp, name): + if isinstance(tp, model.ArrayType): + if tp.length_is_unknown(): + prnt = self._prnt + funcname = '_cffi_sizeof_%s' % (name,) + self.export_symbols.append(funcname) + prnt("size_t %s(void)" % funcname) + prnt("{") + prnt(" return sizeof(%s);" % (name,)) + prnt("}") + tp_ptr = model.PointerType(tp.item) + self._generate_gen_const(False, name, tp_ptr) + else: + tp_ptr = model.PointerType(tp) + self._generate_gen_const(False, name, tp_ptr, category='var') + + _loading_gen_variable = _loaded_noop + + def _loaded_gen_variable(self, tp, name, module, library): + if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the + # sense that "a=..." is forbidden + if tp.length_is_unknown(): + funcname = '_cffi_sizeof_%s' % (name,) + BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0] + function = module.load_function(BFunc, funcname) + size = function() + BItemType = self.ffi._get_cached_btype(tp.item) + length, rest = divmod(size, self.ffi.sizeof(BItemType)) + if rest != 0: + raise VerificationError( + "bad size: %r does not seem to be an array of %s" % + (name, tp.item)) + tp = tp.resolve_length(length) + tp_ptr = model.PointerType(tp.item) + value = self._load_constant(False, tp_ptr, name, module) + # 'value' is a which we have to replace with + # a if the N is actually known + if tp.length is not None: + BArray = self.ffi._get_cached_btype(tp) + value = self.ffi.cast(BArray, value) + setattr(library, name, value) + type(library)._cffi_dir.append(name) + return + # remove ptr= from the library instance, and replace + # it by a property on the class, which reads/writes into ptr[0]. + funcname = '_cffi_var_%s' % name + BFunc = self.ffi._typeof_locked(tp.get_c_name('*(*)(void)', name))[0] + function = module.load_function(BFunc, funcname) + ptr = function() + def getter(library): + return ptr[0] + def setter(library, value): + ptr[0] = value + setattr(type(library), name, property(getter, setter)) + type(library)._cffi_dir.append(name) + +cffimod_header = r''' +#include +#include +#include +#include +#include /* XXX for ssize_t on some platforms */ + +/* this block of #ifs should be kept exactly identical between + c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py + and cffi/_cffi_include.h */ +#if defined(_MSC_VER) +# include /* for alloca() */ +# if _MSC_VER < 1600 /* MSVC < 2010 */ + typedef __int8 int8_t; + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef __int64 int64_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; + typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; +# else +# include +# endif +# if _MSC_VER < 1800 /* MSVC < 2013 */ +# ifndef __cplusplus + typedef unsigned char _Bool; +# endif +# endif +#else +# include +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) +# include +# endif +#endif +''' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/verifier.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/verifier.py new file mode 100644 index 00000000..59b78c21 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/cffi/verifier.py @@ -0,0 +1,306 @@ +# +# DEPRECATED: implementation for ffi.verify() +# +import sys, os, binascii, shutil, io +from . import __version_verifier_modules__ +from . import ffiplatform +from .error import VerificationError + +if sys.version_info >= (3, 3): + import importlib.machinery + def _extension_suffixes(): + return importlib.machinery.EXTENSION_SUFFIXES[:] +else: + import imp + def _extension_suffixes(): + return [suffix for suffix, _, type in imp.get_suffixes() + if type == imp.C_EXTENSION] + + +if sys.version_info >= (3,): + NativeIO = io.StringIO +else: + class NativeIO(io.BytesIO): + def write(self, s): + if isinstance(s, unicode): + s = s.encode('ascii') + super(NativeIO, self).write(s) + + +class Verifier(object): + + def __init__(self, ffi, preamble, tmpdir=None, modulename=None, + ext_package=None, tag='', force_generic_engine=False, + source_extension='.c', flags=None, relative_to=None, **kwds): + if ffi._parser._uses_new_feature: + raise VerificationError( + "feature not supported with ffi.verify(), but only " + "with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,)) + self.ffi = ffi + self.preamble = preamble + if not modulename: + flattened_kwds = ffiplatform.flatten(kwds) + vengine_class = _locate_engine_class(ffi, force_generic_engine) + self._vengine = vengine_class(self) + self._vengine.patch_extension_kwds(kwds) + self.flags = flags + self.kwds = self.make_relative_to(kwds, relative_to) + # + if modulename: + if tag: + raise TypeError("can't specify both 'modulename' and 'tag'") + else: + key = '\x00'.join([sys.version[:3], __version_verifier_modules__, + preamble, flattened_kwds] + + ffi._cdefsources) + if sys.version_info >= (3,): + key = key.encode('utf-8') + k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff) + k1 = k1.lstrip('0x').rstrip('L') + k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff) + k2 = k2.lstrip('0').rstrip('L') + modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key, + k1, k2) + suffix = _get_so_suffixes()[0] + self.tmpdir = tmpdir or _caller_dir_pycache() + self.sourcefilename = os.path.join(self.tmpdir, modulename + source_extension) + self.modulefilename = os.path.join(self.tmpdir, modulename + suffix) + self.ext_package = ext_package + self._has_source = False + self._has_module = False + + def write_source(self, file=None): + """Write the C source code. It is produced in 'self.sourcefilename', + which can be tweaked beforehand.""" + with self.ffi._lock: + if self._has_source and file is None: + raise VerificationError( + "source code already written") + self._write_source(file) + + def compile_module(self): + """Write the C source code (if not done already) and compile it. + This produces a dynamic link library in 'self.modulefilename'.""" + with self.ffi._lock: + if self._has_module: + raise VerificationError("module already compiled") + if not self._has_source: + self._write_source() + self._compile_module() + + def load_library(self): + """Get a C module from this Verifier instance. + Returns an instance of a FFILibrary class that behaves like the + objects returned by ffi.dlopen(), but that delegates all + operations to the C module. If necessary, the C code is written + and compiled first. + """ + with self.ffi._lock: + if not self._has_module: + self._locate_module() + if not self._has_module: + if not self._has_source: + self._write_source() + self._compile_module() + return self._load_library() + + def get_module_name(self): + basename = os.path.basename(self.modulefilename) + # kill both the .so extension and the other .'s, as introduced + # by Python 3: 'basename.cpython-33m.so' + basename = basename.split('.', 1)[0] + # and the _d added in Python 2 debug builds --- but try to be + # conservative and not kill a legitimate _d + if basename.endswith('_d') and hasattr(sys, 'gettotalrefcount'): + basename = basename[:-2] + return basename + + def get_extension(self): + ffiplatform._hack_at_distutils() # backward compatibility hack + if not self._has_source: + with self.ffi._lock: + if not self._has_source: + self._write_source() + sourcename = ffiplatform.maybe_relative_path(self.sourcefilename) + modname = self.get_module_name() + return ffiplatform.get_extension(sourcename, modname, **self.kwds) + + def generates_python_module(self): + return self._vengine._gen_python_module + + def make_relative_to(self, kwds, relative_to): + if relative_to and os.path.dirname(relative_to): + dirname = os.path.dirname(relative_to) + kwds = kwds.copy() + for key in ffiplatform.LIST_OF_FILE_NAMES: + if key in kwds: + lst = kwds[key] + if not isinstance(lst, (list, tuple)): + raise TypeError("keyword '%s' should be a list or tuple" + % (key,)) + lst = [os.path.join(dirname, fn) for fn in lst] + kwds[key] = lst + return kwds + + # ---------- + + def _locate_module(self): + if not os.path.isfile(self.modulefilename): + if self.ext_package: + try: + pkg = __import__(self.ext_package, None, None, ['__doc__']) + except ImportError: + return # cannot import the package itself, give up + # (e.g. it might be called differently before installation) + path = pkg.__path__ + else: + path = None + filename = self._vengine.find_module(self.get_module_name(), path, + _get_so_suffixes()) + if filename is None: + return + self.modulefilename = filename + self._vengine.collect_types() + self._has_module = True + + def _write_source_to(self, file): + self._vengine._f = file + try: + self._vengine.write_source_to_f() + finally: + del self._vengine._f + + def _write_source(self, file=None): + if file is not None: + self._write_source_to(file) + else: + # Write our source file to an in memory file. + f = NativeIO() + self._write_source_to(f) + source_data = f.getvalue() + + # Determine if this matches the current file + if os.path.exists(self.sourcefilename): + with open(self.sourcefilename, "r") as fp: + needs_written = not (fp.read() == source_data) + else: + needs_written = True + + # Actually write the file out if it doesn't match + if needs_written: + _ensure_dir(self.sourcefilename) + with open(self.sourcefilename, "w") as fp: + fp.write(source_data) + + # Set this flag + self._has_source = True + + def _compile_module(self): + # compile this C source + tmpdir = os.path.dirname(self.sourcefilename) + outputfilename = ffiplatform.compile(tmpdir, self.get_extension()) + try: + same = ffiplatform.samefile(outputfilename, self.modulefilename) + except OSError: + same = False + if not same: + _ensure_dir(self.modulefilename) + shutil.move(outputfilename, self.modulefilename) + self._has_module = True + + def _load_library(self): + assert self._has_module + if self.flags is not None: + return self._vengine.load_library(self.flags) + else: + return self._vengine.load_library() + +# ____________________________________________________________ + +_FORCE_GENERIC_ENGINE = False # for tests + +def _locate_engine_class(ffi, force_generic_engine): + if _FORCE_GENERIC_ENGINE: + force_generic_engine = True + if not force_generic_engine: + if '__pypy__' in sys.builtin_module_names: + force_generic_engine = True + else: + try: + import _cffi_backend + except ImportError: + _cffi_backend = '?' + if ffi._backend is not _cffi_backend: + force_generic_engine = True + if force_generic_engine: + from . import vengine_gen + return vengine_gen.VGenericEngine + else: + from . import vengine_cpy + return vengine_cpy.VCPythonEngine + +# ____________________________________________________________ + +_TMPDIR = None + +def _caller_dir_pycache(): + if _TMPDIR: + return _TMPDIR + result = os.environ.get('CFFI_TMPDIR') + if result: + return result + filename = sys._getframe(2).f_code.co_filename + return os.path.abspath(os.path.join(os.path.dirname(filename), + '__pycache__')) + +def set_tmpdir(dirname): + """Set the temporary directory to use instead of __pycache__.""" + global _TMPDIR + _TMPDIR = dirname + +def cleanup_tmpdir(tmpdir=None, keep_so=False): + """Clean up the temporary directory by removing all files in it + called `_cffi_*.{c,so}` as well as the `build` subdirectory.""" + tmpdir = tmpdir or _caller_dir_pycache() + try: + filelist = os.listdir(tmpdir) + except OSError: + return + if keep_so: + suffix = '.c' # only remove .c files + else: + suffix = _get_so_suffixes()[0].lower() + for fn in filelist: + if fn.lower().startswith('_cffi_') and ( + fn.lower().endswith(suffix) or fn.lower().endswith('.c')): + try: + os.unlink(os.path.join(tmpdir, fn)) + except OSError: + pass + clean_dir = [os.path.join(tmpdir, 'build')] + for dir in clean_dir: + try: + for fn in os.listdir(dir): + fn = os.path.join(dir, fn) + if os.path.isdir(fn): + clean_dir.append(fn) + else: + os.unlink(fn) + except OSError: + pass + +def _get_so_suffixes(): + suffixes = _extension_suffixes() + if not suffixes: + # bah, no C_EXTENSION available. Occurs on pypy without cpyext + if sys.platform == 'win32': + suffixes = [".pyd"] + else: + suffixes = [".so"] + + return suffixes + +def _ensure_dir(filename): + dirname = os.path.dirname(filename) + if dirname and not os.path.isdir(dirname): + os.makedirs(dirname) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/METADATA new file mode 100644 index 00000000..f1f13a85 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/METADATA @@ -0,0 +1,98 @@ +Metadata-Version: 2.1 +Name: chardet +Version: 3.0.4 +Summary: Universal encoding detector for Python 2 and 3 +Home-page: https://github.com/chardet/chardet +Author: Mark Pilgrim +Author-email: mark@diveintomark.org +Maintainer: Daniel Blanchard +Maintainer-email: dan.blanchard@gmail.com +License: LGPL +Keywords: encoding,i18n,xml +Platform: UNKNOWN +Classifier: Development Status :: 4 - Beta +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Linguistic + +Chardet: The Universal Character Encoding Detector +-------------------------------------------------- + +.. image:: https://img.shields.io/travis/chardet/chardet/stable.svg + :alt: Build status + :target: https://travis-ci.org/chardet/chardet + +.. image:: https://img.shields.io/coveralls/chardet/chardet/stable.svg + :target: https://coveralls.io/r/chardet/chardet + +.. image:: https://img.shields.io/pypi/v/chardet.svg + :target: https://warehouse.python.org/project/chardet/ + :alt: Latest version on PyPI + +.. image:: https://img.shields.io/pypi/l/chardet.svg + :alt: License + + +Detects + - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants) + - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese) + - EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP (Japanese) + - EUC-KR, ISO-2022-KR (Korean) + - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic) + - ISO-8859-5, windows-1251 (Bulgarian) + - ISO-8859-1, windows-1252 (Western European languages) + - ISO-8859-7, windows-1253 (Greek) + - ISO-8859-8, windows-1255 (Visual and Logical Hebrew) + - TIS-620 (Thai) + +.. note:: + Our ISO-8859-2 and windows-1250 (Hungarian) probers have been temporarily + disabled until we can retrain the models. + +Requires Python 2.6, 2.7, or 3.3+. + +Installation +------------ + +Install from `PyPI `_:: + + pip install chardet + +Documentation +------------- + +For users, docs are now available at https://chardet.readthedocs.io/. + +Command-line Tool +----------------- + +chardet comes with a command-line script which reports on the encodings of one +or more files:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +About +----- + +This is a continuation of Mark Pilgrim's excellent chardet. Previously, two +versions needed to be maintained: one that supported python 2.x and one that +supported python 3.x. We've recently merged with `Ian Cordasco `_'s +`charade `_ fork, so now we have one +coherent version that works for Python 2.6+. + +:maintainer: Dan Blanchard + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD new file mode 100644 index 00000000..03310b99 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/RECORD @@ -0,0 +1,97 @@ +chardet/__init__.py,sha256=YsP5wQlsHJ2auF1RZJfypiSrCA7_bQiRm3ES_NI76-Y,1559 +chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +chardet/charsetgroupprober.py,sha256=6bDu8YIiRuScX4ca9Igb0U69TA2PGXXDej6Cc4_9kO4,3787 +chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +chardet/compat.py,sha256=PKTzHkSbtbHDqS9PyujMbX74q1a8mMpeQTDVsQhZMRw,1134 +chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +chardet/langbulgarianmodel.py,sha256=1HqQS9Pbtnj1xQgxitJMvw8X6kKr5OockNCZWfEQrPE,12839 +chardet/langcyrillicmodel.py,sha256=LODajvsetH87yYDDQKA2CULXUH87tI223dhfjh9Zx9c,17948 +chardet/langgreekmodel.py,sha256=8YAW7bU8YwSJap0kIJSbPMw1BEqzGjWzqcqf0WgUKAA,12688 +chardet/langhebrewmodel.py,sha256=JSnqmE5E62tDLTPTvLpQsg5gOMO4PbdWRvV7Avkc0HA,11345 +chardet/langhungarianmodel.py,sha256=RhapYSG5l0ZaO-VV4Fan5sW0WRGQqhwBM61yx3yxyOA,12592 +chardet/langthaimodel.py,sha256=8l0173Gu_W6G8mxmQOTEF4ls2YdE7FxWf3QkSxEGXJQ,11290 +chardet/langturkishmodel.py,sha256=W22eRNJsqI6uWAfwXSKVWWnCerYqrI8dZQTm_M0lRFk,11102 +chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +chardet/sbcharsetprober.py,sha256=LDSpCldDCFlYwUkGkwD2oFxLlPWIWXT09akH_2PiY74,5657 +chardet/sbcsgroupprober.py,sha256=1IprcCB_k1qfmnxGC6MBbxELlKqD3scW6S8YIwdeyXA,3546 +chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +chardet/universaldetector.py,sha256=qL0174lSZE442eB21nnktT9_VcAye07laFWUeUrjttY,12485 +chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +chardet/version.py,sha256=sp3B08mrDXB-pf3K9fqJ_zeDHOCLC8RrngQyDFap_7g,242 +chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +chardet/cli/chardetect.py,sha256=YBO8L4mXo0WR6_-Fjh_8QxPBoEBNqB9oNxNrdc54AQs,2738 +chardet-3.0.4.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +chardet-3.0.4.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +chardet-3.0.4.dist-info/METADATA,sha256=o6XNN41EUioeDnklH1-8haOSjI60AkAaI823ANFkOM4,3304 +chardet-3.0.4.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +chardet-3.0.4.dist-info/entry_points.txt,sha256=fAMmhu5eJ-zAJ-smfqQwRClQ3-nozOCmvJ6-E8lgGJo,60 +chardet-3.0.4.dist-info/top_level.txt,sha256=AowzBbZy4x8EirABDdJSLJZMkJ_53iIag8xfKR6D7kI,8 +chardet-3.0.4.dist-info/RECORD,, +chardet/euctwprober.cpython-38.pyc,, +chardet/charsetgroupprober.cpython-38.pyc,, +chardet/hebrewprober.cpython-38.pyc,, +chardet/cp949prober.cpython-38.pyc,, +chardet/__pycache__,, +chardet/sjisprober.cpython-38.pyc,, +chardet/big5prober.cpython-38.pyc,, +chardet-3.0.4.virtualenv,, +chardet/euckrfreq.cpython-38.pyc,, +chardet/charsetprober.cpython-38.pyc,, +chardet/cli/__pycache__,, +chardet/gb2312prober.cpython-38.pyc,, +../../../bin/chardetect-3.8,, +chardet/cli/chardetect.cpython-38.pyc,, +chardet/eucjpprober.cpython-38.pyc,, +chardet/jisfreq.cpython-38.pyc,, +chardet/codingstatemachine.cpython-38.pyc,, +chardet/chardistribution.cpython-38.pyc,, +chardet/universaldetector.cpython-38.pyc,, +chardet/escprober.cpython-38.pyc,, +chardet/langcyrillicmodel.cpython-38.pyc,, +chardet/mbcsgroupprober.cpython-38.pyc,, +chardet/escsm.cpython-38.pyc,, +chardet-3.0.4.dist-info/__pycache__,, +chardet/sbcsgroupprober.cpython-38.pyc,, +chardet/langturkishmodel.cpython-38.pyc,, +chardet/latin1prober.cpython-38.pyc,, +chardet/compat.cpython-38.pyc,, +chardet/__init__.cpython-38.pyc,, +chardet/langhungarianmodel.cpython-38.pyc,, +chardet/utf8prober.cpython-38.pyc,, +chardet/langhebrewmodel.cpython-38.pyc,, +chardet/langgreekmodel.cpython-38.pyc,, +chardet/big5freq.cpython-38.pyc,, +chardet/mbcssm.cpython-38.pyc,, +../../../bin/chardetect3,, +chardet/langbulgarianmodel.cpython-38.pyc,, +chardet/jpcntx.cpython-38.pyc,, +chardet/sbcharsetprober.cpython-38.pyc,, +../../../bin/chardetect,, +chardet-3.0.4.dist-info/INSTALLER,, +chardet/cli/__init__.cpython-38.pyc,, +chardet/euckrprober.cpython-38.pyc,, +chardet/gb2312freq.cpython-38.pyc,, +chardet/enums.cpython-38.pyc,, +chardet/langthaimodel.cpython-38.pyc,, +chardet/version.cpython-38.pyc,, +chardet/euctwfreq.cpython-38.pyc,, +chardet/mbcharsetprober.cpython-38.pyc,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/entry_points.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/entry_points.txt new file mode 100644 index 00000000..a884269e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +chardetect = chardet.cli.chardetect:main + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/top_level.txt new file mode 100644 index 00000000..79236f25 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.dist-info/top_level.txt @@ -0,0 +1 @@ +chardet diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet-3.0.4.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/__init__.py new file mode 100644 index 00000000..0f9f820e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/__init__.py @@ -0,0 +1,39 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +from .compat import PY2, PY3 +from .universaldetector import UniversalDetector +from .version import __version__, VERSION + + +def detect(byte_str): + """ + Detect the encoding of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{0}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + detector = UniversalDetector() + detector.feed(byte_str) + return detector.close() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5freq.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5freq.py new file mode 100644 index 00000000..38f32517 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5freq.py @@ -0,0 +1,386 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Big5 frequency table +# by Taiwan's Mandarin Promotion Council +# +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +BIG5_CHAR_TO_FREQ_ORDER = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 +) + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5prober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5prober.py new file mode 100644 index 00000000..98f99701 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import BIG5_SM_MODEL + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + super(Big5Prober, self).__init__() + self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) + self.distribution_analyzer = Big5DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "Big5" + + @property + def language(self): + return "Chinese" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/chardistribution.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/chardistribution.py new file mode 100644 index 00000000..c0395f4a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) + + +class CharDistributionAnalysis(object): + ENOUGH_DATA_THRESHOLD = 1024 + SURE_YES = 0.99 + SURE_NO = 0.01 + MINIMUM_DATA_THRESHOLD = 3 + + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._char_to_freq_order = None + self._table_size = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self.typical_distribution_ratio = None + self._done = None + self._total_chars = None + self._freq_chars = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + self._total_chars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._freq_chars = 0 + + def feed(self, char, char_len): + """feed a character with known length""" + if char_len == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(char) + else: + order = -1 + if order >= 0: + self._total_chars += 1 + # order is valid + if order < self._table_size: + if 512 > self._char_to_freq_order[order]: + self._freq_chars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: + return self.SURE_NO + + if self._total_chars != self._freq_chars: + r = (self._freq_chars / ((self._total_chars - self._freq_chars) + * self.typical_distribution_ratio)) + if r < self.SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return self.SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._total_chars > self.ENOUGH_DATA_THRESHOLD + + def get_order(self, byte_str): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCTWDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER + self._table_size = EUCTW_TABLE_SIZE + self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCKRDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER + self._table_size = EUCKR_TABLE_SIZE + self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(GB2312DistributionAnalysis, self).__init__() + self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER + self._table_size = GB2312_TABLE_SIZE + self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(Big5DistributionAnalysis, self).__init__() + self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER + self._table_size = BIG5_TABLE_SIZE + self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(SJISDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCJPDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = byte_str[0] + if char >= 0xA0: + return 94 * (char - 0xA1) + byte_str[1] - 0xa1 + else: + return -1 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetgroupprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetgroupprober.py new file mode 100644 index 00000000..8b3738ef --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetgroupprober.py @@ -0,0 +1,106 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self, lang_filter=None): + super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) + self._active_num = 0 + self.probers = [] + self._best_guess_prober = None + + def reset(self): + super(CharSetGroupProber, self).reset() + self._active_num = 0 + for prober in self.probers: + if prober: + prober.reset() + prober.active = True + self._active_num += 1 + self._best_guess_prober = None + + @property + def charset_name(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.charset_name + + @property + def language(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.language + + def feed(self, byte_str): + for prober in self.probers: + if not prober: + continue + if not prober.active: + continue + state = prober.feed(byte_str) + if not state: + continue + if state == ProbingState.FOUND_IT: + self._best_guess_prober = prober + return self.state + elif state == ProbingState.NOT_ME: + prober.active = False + self._active_num -= 1 + if self._active_num <= 0: + self._state = ProbingState.NOT_ME + return self.state + return self.state + + def get_confidence(self): + state = self.state + if state == ProbingState.FOUND_IT: + return 0.99 + elif state == ProbingState.NOT_ME: + return 0.01 + best_conf = 0.0 + self._best_guess_prober = None + for prober in self.probers: + if not prober: + continue + if not prober.active: + self.logger.debug('%s not active', prober.charset_name) + continue + conf = prober.get_confidence() + self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) + if best_conf < conf: + best_conf = conf + self._best_guess_prober = prober + if not self._best_guess_prober: + return 0.0 + return best_conf diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetprober.py new file mode 100644 index 00000000..eac4e598 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging +import re + +from .enums import ProbingState + + +class CharSetProber(object): + + SHORTCUT_THRESHOLD = 0.95 + + def __init__(self, lang_filter=None): + self._state = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + + def reset(self): + self._state = ProbingState.DETECTING + + @property + def charset_name(self): + return None + + def feed(self, buf): + pass + + @property + def state(self): + return self._state + + def get_confidence(self): + return 0.0 + + @staticmethod + def filter_high_byte_only(buf): + buf = re.sub(b'([\x00-\x7F])+', b' ', buf) + return buf + + @staticmethod + def filter_international_words(buf): + """ + We define three types of bytes: + alphabet: english alphabets [a-zA-Z] + international: international characters [\x80-\xFF] + marker: everything else [^a-zA-Z\x80-\xFF] + + The input buffer can be thought to contain a series of words delimited + by markers. This function works to filter all words that contain at + least one international character. All contiguous sequences of markers + are replaced by a single space ascii character. + + This filter applies to all scripts which do not use English characters. + """ + filtered = bytearray() + + # This regex expression filters out only words that have at-least one + # international character. The word may include one marker character at + # the end. + words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', + buf) + + for word in words: + filtered.extend(word[:-1]) + + # If the last character in the word is a marker, replace it with a + # space as markers shouldn't affect our analysis (they are used + # similarly across all languages and may thus have similar + # frequencies). + last_char = word[-1:] + if not last_char.isalpha() and last_char < b'\x80': + last_char = b' ' + filtered.extend(last_char) + + return filtered + + @staticmethod + def filter_with_english_letters(buf): + """ + Returns a copy of ``buf`` that retains only the sequences of English + alphabet and high byte characters that are not between <> characters. + Also retains English alphabet and high byte characters immediately + before occurrences of >. + + This filter can be applied to all scripts which contain both English + characters and extended ASCII characters, but is currently only used by + ``Latin1Prober``. + """ + filtered = bytearray() + in_tag = False + prev = 0 + + for curr in range(len(buf)): + # Slice here to get bytes instead of an int with Python 3 + buf_char = buf[curr:curr + 1] + # Check if we're coming out of or entering an HTML tag + if buf_char == b'>': + in_tag = False + elif buf_char == b'<': + in_tag = True + + # If current character is not extended-ASCII and not alphabetic... + if buf_char < b'\x80' and not buf_char.isalpha(): + # ...and we're not in a tag + if curr > prev and not in_tag: + # Keep everything after last non-extended-ASCII, + # non-alphabetic character + filtered.extend(buf[prev:curr]) + # Output a space to delimit stretch we kept + filtered.extend(b' ') + prev = curr + 1 + + # If we're not in a tag... + if not in_tag: + # Keep everything after last non-extended-ASCII, non-alphabetic + # character + filtered.extend(buf[prev:]) + + return filtered diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/chardetect.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/chardetect.py new file mode 100644 index 00000000..f0a4cc5d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cli/chardetect.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +""" +Script which takes one or more file paths and reports on their detected +encodings + +Example:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +If no paths are provided, it takes its input from stdin. + +""" + +from __future__ import absolute_import, print_function, unicode_literals + +import argparse +import sys + +from chardet import __version__ +from chardet.compat import PY2 +from chardet.universaldetector import UniversalDetector + + +def description_of(lines, name='stdin'): + """ + Return a string describing the probable encoding of a file or + list of strings. + + :param lines: The lines to get the encoding of. + :type lines: Iterable of bytes + :param name: Name of file or collection of lines + :type name: str + """ + u = UniversalDetector() + for line in lines: + line = bytearray(line) + u.feed(line) + # shortcut out of the loop to save reading further - particularly useful if we read a BOM. + if u.done: + break + u.close() + result = u.result + if PY2: + name = name.decode(sys.getfilesystemencoding(), 'ignore') + if result['encoding']: + return '{0}: {1} with confidence {2}'.format(name, result['encoding'], + result['confidence']) + else: + return '{0}: no result'.format(name) + + +def main(argv=None): + """ + Handles command line arguments and gets things started. + + :param argv: List of arguments, as if specified on the command-line. + If None, ``sys.argv[1:]`` is used instead. + :type argv: list of str + """ + # Get command line arguments + parser = argparse.ArgumentParser( + description="Takes one or more file paths and reports their detected \ + encodings") + parser.add_argument('input', + help='File whose encoding we would like to determine. \ + (default: stdin)', + type=argparse.FileType('rb'), nargs='*', + default=[sys.stdin if PY2 else sys.stdin.buffer]) + parser.add_argument('--version', action='version', + version='%(prog)s {0}'.format(__version__)) + args = parser.parse_args(argv) + + for f in args.input: + if f.isatty(): + print("You are running chardetect interactively. Press " + + "CTRL-D twice at the start of a blank line to signal the " + + "end of your input. If you want help, run chardetect " + + "--help\n", file=sys.stderr) + print(description_of(f, f.name)) + + +if __name__ == '__main__': + main() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/codingstatemachine.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/codingstatemachine.py new file mode 100644 index 00000000..68fba44f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/codingstatemachine.py @@ -0,0 +1,88 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging + +from .enums import MachineState + + +class CodingStateMachine(object): + """ + A state machine to verify a byte sequence for a particular encoding. For + each byte the detector receives, it will feed that byte to every active + state machine available, one byte at a time. The state machine changes its + state based on its previous state and the byte it receives. There are 3 + states in a state machine that are of interest to an auto-detector: + + START state: This is the state to start with, or a legal byte sequence + (i.e. a valid code point) for character has been identified. + + ME state: This indicates that the state machine identified a byte sequence + that is specific to the charset it is designed for and that + there is no other possible encoding which can contain this byte + sequence. This will to lead to an immediate positive answer for + the detector. + + ERROR state: This indicates the state machine identified an illegal byte + sequence for that encoding. This will lead to an immediate + negative answer for this encoding. Detector will exclude this + encoding from consideration from here on. + """ + def __init__(self, sm): + self._model = sm + self._curr_byte_pos = 0 + self._curr_char_len = 0 + self._curr_state = None + self.logger = logging.getLogger(__name__) + self.reset() + + def reset(self): + self._curr_state = MachineState.START + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + byte_class = self._model['class_table'][c] + if self._curr_state == MachineState.START: + self._curr_byte_pos = 0 + self._curr_char_len = self._model['char_len_table'][byte_class] + # from byte's class and state_table, we get its next state + curr_state = (self._curr_state * self._model['class_factor'] + + byte_class) + self._curr_state = self._model['state_table'][curr_state] + self._curr_byte_pos += 1 + return self._curr_state + + def get_current_charlen(self): + return self._curr_char_len + + def get_coding_state_machine(self): + return self._model['name'] + + @property + def language(self): + return self._model['language'] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/compat.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/compat.py new file mode 100644 index 00000000..ddd74687 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/compat.py @@ -0,0 +1,34 @@ +######################## BEGIN LICENSE BLOCK ######################## +# Contributor(s): +# Dan Blanchard +# Ian Cordasco +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys + + +if sys.version_info < (3, 0): + PY2 = True + PY3 = False + base_str = (str, unicode) + text_type = unicode +else: + PY2 = False + PY3 = True + base_str = (bytes, str) + text_type = str diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cp949prober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cp949prober.py new file mode 100644 index 00000000..efd793ab --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/cp949prober.py @@ -0,0 +1,49 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .chardistribution import EUCKRDistributionAnalysis +from .codingstatemachine import CodingStateMachine +from .mbcharsetprober import MultiByteCharSetProber +from .mbcssm import CP949_SM_MODEL + + +class CP949Prober(MultiByteCharSetProber): + def __init__(self): + super(CP949Prober, self).__init__() + self.coding_sm = CodingStateMachine(CP949_SM_MODEL) + # NOTE: CP949 is a superset of EUC-KR, so the distribution should be + # not different. + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "CP949" + + @property + def language(self): + return "Korean" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/enums.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/enums.py new file mode 100644 index 00000000..04512072 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/enums.py @@ -0,0 +1,76 @@ +""" +All of the Enums that are used throughout the chardet package. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + + +class InputState(object): + """ + This enum represents the different states a universal detector can be in. + """ + PURE_ASCII = 0 + ESC_ASCII = 1 + HIGH_BYTE = 2 + + +class LanguageFilter(object): + """ + This enum represents the different language filters we can apply to a + ``UniversalDetector``. + """ + CHINESE_SIMPLIFIED = 0x01 + CHINESE_TRADITIONAL = 0x02 + JAPANESE = 0x04 + KOREAN = 0x08 + NON_CJK = 0x10 + ALL = 0x1F + CHINESE = CHINESE_SIMPLIFIED | CHINESE_TRADITIONAL + CJK = CHINESE | JAPANESE | KOREAN + + +class ProbingState(object): + """ + This enum represents the different states a prober can be in. + """ + DETECTING = 0 + FOUND_IT = 1 + NOT_ME = 2 + + +class MachineState(object): + """ + This enum represents the different states a state machine can be in. + """ + START = 0 + ERROR = 1 + ITS_ME = 2 + + +class SequenceLikelihood(object): + """ + This enum represents the likelihood of a character following the previous one. + """ + NEGATIVE = 0 + UNLIKELY = 1 + LIKELY = 2 + POSITIVE = 3 + + @classmethod + def get_num_categories(cls): + """:returns: The number of likelihood categories in the enum.""" + return 4 + + +class CharacterCategory(object): + """ + This enum represents the different categories language models for + ``SingleByteCharsetProber`` put characters into. + + Anything less than CONTROL is considered a letter. + """ + UNDEFINED = 255 + LINE_BREAK = 254 + SYMBOL = 253 + DIGIT = 252 + CONTROL = 251 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escprober.py new file mode 100644 index 00000000..c70493f2 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escprober.py @@ -0,0 +1,101 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .enums import LanguageFilter, ProbingState, MachineState +from .escsm import (HZ_SM_MODEL, ISO2022CN_SM_MODEL, ISO2022JP_SM_MODEL, + ISO2022KR_SM_MODEL) + + +class EscCharSetProber(CharSetProber): + """ + This CharSetProber uses a "code scheme" approach for detecting encodings, + whereby easily recognizable escape or shift sequences are relied on to + identify these encodings. + """ + + def __init__(self, lang_filter=None): + super(EscCharSetProber, self).__init__(lang_filter=lang_filter) + self.coding_sm = [] + if self.lang_filter & LanguageFilter.CHINESE_SIMPLIFIED: + self.coding_sm.append(CodingStateMachine(HZ_SM_MODEL)) + self.coding_sm.append(CodingStateMachine(ISO2022CN_SM_MODEL)) + if self.lang_filter & LanguageFilter.JAPANESE: + self.coding_sm.append(CodingStateMachine(ISO2022JP_SM_MODEL)) + if self.lang_filter & LanguageFilter.KOREAN: + self.coding_sm.append(CodingStateMachine(ISO2022KR_SM_MODEL)) + self.active_sm_count = None + self._detected_charset = None + self._detected_language = None + self._state = None + self.reset() + + def reset(self): + super(EscCharSetProber, self).reset() + for coding_sm in self.coding_sm: + if not coding_sm: + continue + coding_sm.active = True + coding_sm.reset() + self.active_sm_count = len(self.coding_sm) + self._detected_charset = None + self._detected_language = None + + @property + def charset_name(self): + return self._detected_charset + + @property + def language(self): + return self._detected_language + + def get_confidence(self): + if self._detected_charset: + return 0.99 + else: + return 0.00 + + def feed(self, byte_str): + for c in byte_str: + for coding_sm in self.coding_sm: + if not coding_sm or not coding_sm.active: + continue + coding_state = coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + coding_sm.active = False + self.active_sm_count -= 1 + if self.active_sm_count <= 0: + self._state = ProbingState.NOT_ME + return self.state + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + self._detected_charset = coding_sm.get_coding_state_machine() + self._detected_language = coding_sm.language + return self.state + + return self.state diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escsm.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escsm.py new file mode 100644 index 00000000..0069523a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/escsm.py @@ -0,0 +1,246 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +HZ_CLS = ( +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_ST = ( +MachineState.START,MachineState.ERROR, 3,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START, 4,MachineState.ERROR,# 10-17 + 5,MachineState.ERROR, 6,MachineState.ERROR, 5, 5, 4,MachineState.ERROR,# 18-1f + 4,MachineState.ERROR, 4, 4, 4,MachineState.ERROR, 4,MachineState.ERROR,# 20-27 + 4,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 28-2f +) + +HZ_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +HZ_SM_MODEL = {'class_table': HZ_CLS, + 'class_factor': 6, + 'state_table': HZ_ST, + 'char_len_table': HZ_CHAR_LEN_TABLE, + 'name': "HZ-GB-2312", + 'language': 'Chinese'} + +ISO2022CN_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 20-27 + 5, 6,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,# 38-3f +) + +ISO2022CN_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CN_SM_MODEL = {'class_table': ISO2022CN_CLS, + 'class_factor': 9, + 'state_table': ISO2022CN_ST, + 'char_len_table': ISO2022CN_CHAR_LEN_TABLE, + 'name': "ISO-2022-CN", + 'language': 'Chinese'} + +ISO2022JP_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 20-27 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 6,MachineState.ITS_ME,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 38-3f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.START,# 40-47 +) + +ISO2022JP_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JP_SM_MODEL = {'class_table': ISO2022JP_CLS, + 'class_factor': 10, + 'state_table': ISO2022JP_ST, + 'char_len_table': ISO2022JP_CHAR_LEN_TABLE, + 'name': "ISO-2022-JP", + 'language': 'Japanese'} + +ISO2022KR_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 10-17 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 20-27 +) + +ISO2022KR_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +ISO2022KR_SM_MODEL = {'class_table': ISO2022KR_CLS, + 'class_factor': 6, + 'state_table': ISO2022KR_ST, + 'char_len_table': ISO2022KR_CHAR_LEN_TABLE, + 'name': "ISO-2022-KR", + 'language': 'Korean'} + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/eucjpprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/eucjpprober.py new file mode 100644 index 00000000..20ce8f7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/eucjpprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState, MachineState +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCJPDistributionAnalysis +from .jpcntx import EUCJPContextAnalysis +from .mbcssm import EUCJP_SM_MODEL + + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + super(EUCJPProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCJP_SM_MODEL) + self.distribution_analyzer = EUCJPDistributionAnalysis() + self.context_analyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + super(EUCJPProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return "EUC-JP" + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + # PY3K: byte_str is a byte array, so byte_str[i] is an int, not a byte + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char, char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrfreq.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrfreq.py new file mode 100644 index 00000000..b68078cb --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKR_CHAR_TO_FREQ_ORDER = ( + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +) + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrprober.py new file mode 100644 index 00000000..345a060d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKR_SM_MODEL + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + super(EUCKRProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-KR" + + @property + def language(self): + return "Korean" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwfreq.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwfreq.py new file mode 100644 index 00000000..ed7a995a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 5376 + +EUCTW_CHAR_TO_FREQ_ORDER = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +) + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwprober.py new file mode 100644 index 00000000..35669cc4 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTW_SM_MODEL + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + super(EUCTWProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) + self.distribution_analyzer = EUCTWDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-TW" + + @property + def language(self): + return "Taiwan" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312freq.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312freq.py new file mode 100644 index 00000000..697837bd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312_CHAR_TO_FREQ_ORDER = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 +) + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312prober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312prober.py new file mode 100644 index 00000000..8446d2dd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312_SM_MODEL + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + super(GB2312Prober, self).__init__() + self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) + self.distribution_analyzer = GB2312DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "GB2312" + + @property + def language(self): + return "Chinese" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/hebrewprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/hebrewprober.py new file mode 100644 index 00000000..b0e1bf49 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +class HebrewProber(CharSetProber): + # windows-1255 / ISO-8859-8 code points of interest + FINAL_KAF = 0xea + NORMAL_KAF = 0xeb + FINAL_MEM = 0xed + NORMAL_MEM = 0xee + FINAL_NUN = 0xef + NORMAL_NUN = 0xf0 + FINAL_PE = 0xf3 + NORMAL_PE = 0xf4 + FINAL_TSADI = 0xf5 + NORMAL_TSADI = 0xf6 + + # Minimum Visual vs Logical final letter score difference. + # If the difference is below this, don't rely solely on the final letter score + # distance. + MIN_FINAL_CHAR_DISTANCE = 5 + + # Minimum Visual vs Logical model score difference. + # If the difference is below this, don't rely at all on the model score + # distance. + MIN_MODEL_DISTANCE = 0.01 + + VISUAL_HEBREW_NAME = "ISO-8859-8" + LOGICAL_HEBREW_NAME = "windows-1255" + + def __init__(self): + super(HebrewProber, self).__init__() + self._final_char_logical_score = None + self._final_char_visual_score = None + self._prev = None + self._before_prev = None + self._logical_prober = None + self._visual_prober = None + self.reset() + + def reset(self): + self._final_char_logical_score = 0 + self._final_char_visual_score = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._prev = ' ' + self._before_prev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._logical_prober = logicalProber + self._visual_prober = visualProber + + def is_final(self, c): + return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, + self.FINAL_PE, self.FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return c in [self.NORMAL_KAF, self.NORMAL_MEM, + self.NORMAL_NUN, self.NORMAL_PE] + + def feed(self, byte_str): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.state == ProbingState.NOT_ME: + # Both model probers say it's not them. No reason to continue. + return ProbingState.NOT_ME + + byte_str = self.filter_high_byte_only(byte_str) + + for cur in byte_str: + if cur == ' ': + # We stand on a space - a word just ended + if self._before_prev != ' ': + # next-to-last char was not a space so self._prev is not a + # 1 letter word + if self.is_final(self._prev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._final_char_logical_score += 1 + elif self.is_non_final(self._prev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._final_char_visual_score += 1 + else: + # Not standing on a space + if ((self._before_prev == ' ') and + (self.is_final(self._prev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._final_char_visual_score += 1 + self._before_prev = self._prev + self._prev = cur + + # Forever detecting, till the end or until both model probers return + # ProbingState.NOT_ME (handled above) + return ProbingState.DETECTING + + @property + def charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._final_char_logical_score - self._final_char_visual_score + if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._logical_prober.get_confidence() + - self._visual_prober.get_confidence()) + if modelsub > self.MIN_MODEL_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if modelsub < -self.MIN_MODEL_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return self.VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return self.LOGICAL_HEBREW_NAME + + @property + def language(self): + return 'Hebrew' + + @property + def state(self): + # Remain active as long as any of the model probers are active. + if (self._logical_prober.state == ProbingState.NOT_ME) and \ + (self._visual_prober.state == ProbingState.NOT_ME): + return ProbingState.NOT_ME + return ProbingState.DETECTING diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jisfreq.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jisfreq.py new file mode 100644 index 00000000..83fc082b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JIS_CHAR_TO_FREQ_ORDER = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +) + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jpcntx.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jpcntx.py new file mode 100644 index 00000000..20044e4b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis(object): + NUM_OF_CATEGORY = 6 + DONT_KNOW = -1 + ENOUGH_REL_THRESHOLD = 100 + MAX_REL_THRESHOLD = 1000 + MINIMUM_DATA_THRESHOLD = 4 + + def __init__(self): + self._total_rel = None + self._rel_sample = None + self._need_to_skip_char_num = None + self._last_char_order = None + self._done = None + self.reset() + + def reset(self): + self._total_rel = 0 # total sequence received + # category counters, each integer counts sequence in its category + self._rel_sample = [0] * self.NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._need_to_skip_char_num = 0 + self._last_char_order = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + + def feed(self, byte_str, num_bytes): + if self._done: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._need_to_skip_char_num + while i < num_bytes: + order, char_len = self.get_order(byte_str[i:i + 2]) + i += char_len + if i > num_bytes: + self._need_to_skip_char_num = i - num_bytes + self._last_char_order = -1 + else: + if (order != -1) and (self._last_char_order != -1): + self._total_rel += 1 + if self._total_rel > self.MAX_REL_THRESHOLD: + self._done = True + break + self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 + self._last_char_order = order + + def got_enough_data(self): + return self._total_rel > self.ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._total_rel > self.MINIMUM_DATA_THRESHOLD: + return (self._total_rel - self._rel_sample[0]) / self._total_rel + else: + return self.DONT_KNOW + + def get_order(self, byte_str): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def __init__(self): + super(SJISContextAnalysis, self).__init__() + self._charset_name = "SHIFT_JIS" + + @property + def charset_name(self): + return self._charset_name + + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): + char_len = 2 + if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): + self._charset_name = "CP932" + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, char_len + + return -1, char_len + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + char_len = 2 + elif first_char == 0x8F: + char_len = 3 + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, char_len + + return -1, char_len + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langbulgarianmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langbulgarianmodel.py new file mode 100644 index 00000000..2aa4fb2e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langbulgarianmodel.py @@ -0,0 +1,228 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +# this table is modified base on win1251BulgarianCharToOrderMap, so +# only number <64 is sure valid + +Latin5_BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 +210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 + 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 + 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 +) + +win1251BulgarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 +110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 +253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 +116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 +206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 +221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 + 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 + 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 + 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 + 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 + 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 + 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 96.9392% +# first 1024 sequences:3.0618% +# rest sequences: 0.2992% +# negative sequences: 0.0020% +BulgarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, +3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, +0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, +0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, +0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, +0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, +0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, +2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, +3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, +3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, +1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, +3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, +1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, +2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, +2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, +3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, +1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, +2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, +2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, +1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, +2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, +2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, +2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, +1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, +2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, +1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, +3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, +1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, +3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, +1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, +2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, +1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, +2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, +1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, +2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, +1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, +2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, +1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, +2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, +1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, +0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, +1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, +1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, +1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, +0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, +1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, +1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, +1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +) + +Latin5BulgarianModel = { + 'char_to_order_map': Latin5_BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Bulgairan', +} + +Win1251BulgarianModel = { + 'char_to_order_map': win1251BulgarianCharToOrderMap, + 'precedence_matrix': BulgarianLangModel, + 'typical_positive_ratio': 0.969392, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Bulgarian', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langcyrillicmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langcyrillicmodel.py new file mode 100644 index 00000000..e5f9a1fd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langcyrillicmodel.py @@ -0,0 +1,333 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# KOI8-R language model +# Character Mapping Table: +KOI8R_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 +223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 +238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 + 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 + 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 + 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 + 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 +) + +win1251_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +) + +latin5_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +macCyrillic_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, +239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, +) + +IBM855_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 +191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, +206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, + 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, +220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, +230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, + 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, + 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, +250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, +) + +IBM866_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 +155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 +253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 + 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 + 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, + 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, + 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, +191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, +207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, +223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, + 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, +239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 97.6601% +# first 1024 sequences: 2.3389% +# rest sequences: 0.1237% +# negative sequences: 0.0009% +RussianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, +0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, +0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, +1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, +1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, +2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, +1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, +3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, +1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, +2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, +1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, +1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, +1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, +1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, +3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, +1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, +2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, +1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, +2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, +0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, +1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, +1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, +1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, +3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, +3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, +1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, +1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, +0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, +1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, +1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, +0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, +1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, +2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, +1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, +1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, +2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, +1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, +0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, +2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, +1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, +1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, +0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, +0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, +1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, +0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, +0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, +2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, +0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +) + +Koi8rModel = { + 'char_to_order_map': KOI8R_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "KOI8-R", + 'language': 'Russian', +} + +Win1251CyrillicModel = { + 'char_to_order_map': win1251_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "windows-1251", + 'language': 'Russian', +} + +Latin5CyrillicModel = { + 'char_to_order_map': latin5_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-5", + 'language': 'Russian', +} + +MacCyrillicModel = { + 'char_to_order_map': macCyrillic_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "MacCyrillic", + 'language': 'Russian', +} + +Ibm866Model = { + 'char_to_order_map': IBM866_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM866", + 'language': 'Russian', +} + +Ibm855Model = { + 'char_to_order_map': IBM855_char_to_order_map, + 'precedence_matrix': RussianLangModel, + 'typical_positive_ratio': 0.976601, + 'keep_english_letter': False, + 'charset_name': "IBM855", + 'language': 'Russian', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langgreekmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langgreekmodel.py new file mode 100644 index 00000000..53322216 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langgreekmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin7_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +win1253_char_to_order_map = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 + 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 +253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 + 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 +253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 +253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 +110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 + 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 +124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 + 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.2851% +# first 1024 sequences:1.7001% +# rest sequences: 0.0359% +# negative sequences: 0.0148% +GreekLangModel = ( +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, +2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, +2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, +2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, +0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, +3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, +3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, +2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, +2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, +0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, +0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, +0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, +0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, +0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, +0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, +0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, +0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, +0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, +0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, +0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, +0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, +0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, +0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, +0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, +0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, +0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, +0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, +0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, +0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, +0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, +0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, +0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, +0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, +0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, +0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin7GreekModel = { + 'char_to_order_map': Latin7_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "ISO-8859-7", + 'language': 'Greek', +} + +Win1253GreekModel = { + 'char_to_order_map': win1253_char_to_order_map, + 'precedence_matrix': GreekLangModel, + 'typical_positive_ratio': 0.982851, + 'keep_english_letter': False, + 'charset_name': "windows-1253", + 'language': 'Greek', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhebrewmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhebrewmodel.py new file mode 100644 index 00000000..58f4c875 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhebrewmodel.py @@ -0,0 +1,200 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Simon Montagu +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Shoshannah Forbes - original C code (?) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Windows-1255 language model +# Character Mapping Table: +WIN1255_CHAR_TO_ORDER_MAP = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 + 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 +253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 + 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 +124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, +215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, + 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, +106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, + 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, +238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, + 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, + 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 98.4004% +# first 1024 sequences: 1.5981% +# rest sequences: 0.087% +# negative sequences: 0.0015% +HEBREW_LANG_MODEL = ( +0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, +3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, +1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, +1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, +1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, +1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, +0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, +1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, +0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, +0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, +0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, +0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, +0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, +0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, +0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, +3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, +0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, +0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, +0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, +0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, +3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, +0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, +0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, +0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, +0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, +0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, +1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, +0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, +1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, +2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, +2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, +0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, +0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, +) + +Win1255HebrewModel = { + 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, + 'precedence_matrix': HEBREW_LANG_MODEL, + 'typical_positive_ratio': 0.984004, + 'keep_english_letter': False, + 'charset_name': "windows-1255", + 'language': 'Hebrew', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhungarianmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhungarianmodel.py new file mode 100644 index 00000000..bb7c095e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langhungarianmodel.py @@ -0,0 +1,225 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin2_HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, +175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, + 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, + 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, +245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +win1250HungarianCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, + 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, +253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, + 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, +161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, +177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, +191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, + 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, +221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, +232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, + 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, +245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 94.7368% +# first 1024 sequences:5.2623% +# rest sequences: 0.8894% +# negative sequences: 0.0009% +HungarianLangModel = ( +0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, +3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, +3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, +0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, +3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, +0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, +0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, +3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, +1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, +1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, +3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, +2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, +2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, +2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, +2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, +2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, +1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, +1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, +3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, +1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, +1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, +2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, +2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, +2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, +3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, +2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, +1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, +1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, +2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, +1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, +2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, +1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, +1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, +2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, +2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, +2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, +1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, +1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, +0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, +2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, +1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, +2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, +1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, +1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, +2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, +2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, +2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, +1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, +2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, +0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, +2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +) + +Latin2HungarianModel = { + 'char_to_order_map': Latin2_HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-2", + 'language': 'Hungarian', +} + +Win1250HungarianModel = { + 'char_to_order_map': win1250HungarianCharToOrderMap, + 'precedence_matrix': HungarianLangModel, + 'typical_positive_ratio': 0.947368, + 'keep_english_letter': True, + 'charset_name': "windows-1250", + 'language': 'Hungarian', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langthaimodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langthaimodel.py new file mode 100644 index 00000000..15f94c2d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langthaimodel.py @@ -0,0 +1,199 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# The following result for thai was collected from a limited sample (1M). + +# Character Mapping Table: +TIS620CharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 +252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 +253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 +188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 +253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 + 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 +209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, +223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, +236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, + 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, + 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, + 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, + 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, + 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, +) + +# Model Table: +# total sequences: 100% +# first 512 sequences: 92.6386% +# first 1024 sequences:7.3177% +# rest sequences: 1.0230% +# negative sequences: 0.0436% +ThaiLangModel = ( +0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, +0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, +3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, +0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, +3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, +3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, +3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, +3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, +3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, +2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, +3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, +0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, +1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, +3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, +3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, +1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, +0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, +0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, +3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, +2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, +3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, +0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, +3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, +3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, +2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, +2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, +3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, +3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, +3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, +3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, +3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, +1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, +0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, +0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, +3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, +3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, +1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, +3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, +3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, +0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, +0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, +1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, +1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, +3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, +0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, +0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, +3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, +0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, +0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, +0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, +0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, +0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, +3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, +0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, +0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, +3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, +2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, +0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, +3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, +1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, +1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, +1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, +1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +TIS620ThaiModel = { + 'char_to_order_map': TIS620CharToOrderMap, + 'precedence_matrix': ThaiLangModel, + 'typical_positive_ratio': 0.926386, + 'keep_english_letter': False, + 'charset_name': "TIS-620", + 'language': 'Thai', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langturkishmodel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langturkishmodel.py new file mode 100644 index 00000000..a427a457 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/langturkishmodel.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Özgür Baskın - Turkish Language Model +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# 255: Control characters that usually does not exist in any text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 + +# Character Mapping Table: +Latin5_TurkishCharToOrderMap = ( +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, + 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, +255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, + 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, +180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, +164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, +150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, + 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, +124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, + 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, + 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, + 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, +) + +TurkishLangModel = ( +3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, +3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, +3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, +3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, +3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, +3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, +2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, +3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, +1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, +3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, +3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, +2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, +2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, +3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, +3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, +0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, +3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, +3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, +3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, +2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, +3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, +0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, +1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, +3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, +3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, +0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, +3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, +1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, +1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, +2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, +2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, +0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, +2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, +3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, +2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, +0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, +3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, +1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, +1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, +0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, +3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, +0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, +3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0, +3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, +1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, +2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, +0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, +3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, +0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, +0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, +3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, +0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, +0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, +3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, +0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, +3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, +0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, +0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, +3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, +3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, +0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, +3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, +0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, +0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, +0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, +3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, +0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, +3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, +0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, +0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, +0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, +2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, +1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, +0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, +0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, +3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, +0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, +2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, +2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, +0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, +1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1, +0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, +2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +) + +Latin5TurkishModel = { + 'char_to_order_map': Latin5_TurkishCharToOrderMap, + 'precedence_matrix': TurkishLangModel, + 'typical_positive_ratio': 0.970290, + 'keep_english_letter': True, + 'charset_name': "ISO-8859-9", + 'language': 'Turkish', +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/latin1prober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/latin1prober.py new file mode 100644 index 00000000..7d1e8c20 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + super(Latin1Prober, self).__init__() + self._last_char_class = None + self._freq_counter = None + self.reset() + + def reset(self): + self._last_char_class = OTH + self._freq_counter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + @property + def charset_name(self): + return "ISO-8859-1" + + @property + def language(self): + return "" + + def feed(self, byte_str): + byte_str = self.filter_with_english_letters(byte_str) + for c in byte_str: + char_class = Latin1_CharToClass[c] + freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) + + char_class] + if freq == 0: + self._state = ProbingState.NOT_ME + break + self._freq_counter[freq] += 1 + self._last_char_class = char_class + + return self.state + + def get_confidence(self): + if self.state == ProbingState.NOT_ME: + return 0.01 + + total = sum(self._freq_counter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) + / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.73 + return confidence diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcharsetprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcharsetprober.py new file mode 100644 index 00000000..6256ecfd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState + + +class MultiByteCharSetProber(CharSetProber): + """ + MultiByteCharSetProber + """ + + def __init__(self, lang_filter=None): + super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) + self.distribution_analyzer = None + self.coding_sm = None + self._last_char = [0, 0] + + def reset(self): + super(MultiByteCharSetProber, self).reset() + if self.coding_sm: + self.coding_sm.reset() + if self.distribution_analyzer: + self.distribution_analyzer.reset() + self._last_char = [0, 0] + + @property + def charset_name(self): + raise NotImplementedError + + @property + def language(self): + raise NotImplementedError + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.distribution_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + return self.distribution_analyzer.get_confidence() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcsgroupprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcsgroupprober.py new file mode 100644 index 00000000..530abe75 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self, lang_filter=None): + super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) + self.probers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcssm.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcssm.py new file mode 100644 index 00000000..8360d0f2 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +# BIG5 + +BIG5_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 +) + +BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) + +BIG5_SM_MODEL = {'class_table': BIG5_CLS, + 'class_factor': 5, + 'state_table': BIG5_ST, + 'char_len_table': BIG5_CHAR_LEN_TABLE, + 'name': 'Big5'} + +# CP949 + +CP949_CLS = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_ST = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 +) + +CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949_SM_MODEL = {'class_table': CP949_CLS, + 'class_factor': 10, + 'state_table': CP949_ST, + 'char_len_table': CP949_CHAR_LEN_TABLE, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_CLS = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_ST = ( + 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f + 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 +) + +EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) + +EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, + 'class_factor': 6, + 'state_table': EUCJP_ST, + 'char_len_table': EUCJP_CHAR_LEN_TABLE, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_ST = ( + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f +) + +EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) + +EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, + 'class_factor': 4, + 'state_table': EUCKR_ST, + 'char_len_table': EUCKR_CHAR_LEN_TABLE, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_CLS = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_ST = ( + MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 + MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 + MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) + +EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, + 'class_factor': 7, + 'state_table': EUCTW_ST, + 'char_len_table': EUCTW_CHAR_LEN_TABLE, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 + 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validating +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) + +GB2312_SM_MODEL = {'class_table': GB2312_CLS, + 'class_factor': 7, + 'state_table': GB2312_ST, + 'char_len_table': GB2312_CHAR_LEN_TABLE, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,2,2,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,0,0,0) # f8 - ff + + +SJIS_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 +) + +SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) + +SJIS_SM_MODEL = {'class_table': SJIS_CLS, + 'class_factor': 6, + 'state_table': SJIS_ST, + 'char_len_table': SJIS_CHAR_LEN_TABLE, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_ST = ( + 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 + 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 + 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f + 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) + +UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, + 'class_factor': 6, + 'state_table': UCS2BE_ST, + 'char_len_table': UCS2BE_CHAR_LEN_TABLE, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_ST = ( + 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 + 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) + +UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, + 'class_factor': 6, + 'state_table': UCS2LE_ST, + 'char_len_table': UCS2LE_CHAR_LEN_TABLE, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_ST = ( + MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f + MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f + MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f + MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f + MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af + MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf +) + +UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8_SM_MODEL = {'class_table': UTF8_CLS, + 'class_factor': 16, + 'state_table': UTF8_ST, + 'char_len_table': UTF8_CHAR_LEN_TABLE, + 'name': 'UTF-8'} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcharsetprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcharsetprober.py new file mode 100644 index 00000000..0adb51de --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcharsetprober.py @@ -0,0 +1,132 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import CharacterCategory, ProbingState, SequenceLikelihood + + +class SingleByteCharSetProber(CharSetProber): + SAMPLE_SIZE = 64 + SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 + POSITIVE_SHORTCUT_THRESHOLD = 0.95 + NEGATIVE_SHORTCUT_THRESHOLD = 0.05 + + def __init__(self, model, reversed=False, name_prober=None): + super(SingleByteCharSetProber, self).__init__() + self._model = model + # TRUE if we need to reverse every pair in the model lookup + self._reversed = reversed + # Optional auxiliary prober for name decision + self._name_prober = name_prober + self._last_order = None + self._seq_counters = None + self._total_seqs = None + self._total_char = None + self._freq_char = None + self.reset() + + def reset(self): + super(SingleByteCharSetProber, self).reset() + # char order of last character + self._last_order = 255 + self._seq_counters = [0] * SequenceLikelihood.get_num_categories() + self._total_seqs = 0 + self._total_char = 0 + # characters that fall in our sampling range + self._freq_char = 0 + + @property + def charset_name(self): + if self._name_prober: + return self._name_prober.charset_name + else: + return self._model['charset_name'] + + @property + def language(self): + if self._name_prober: + return self._name_prober.language + else: + return self._model.get('language') + + def feed(self, byte_str): + if not self._model['keep_english_letter']: + byte_str = self.filter_international_words(byte_str) + if not byte_str: + return self.state + char_to_order_map = self._model['char_to_order_map'] + for i, c in enumerate(byte_str): + # XXX: Order is in range 1-64, so one would think we want 0-63 here, + # but that leads to 27 more test failures than before. + order = char_to_order_map[c] + # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but + # CharacterCategory.SYMBOL is actually 253, so we use CONTROL + # to make it closer to the original intent. The only difference + # is whether or not we count digits and control characters for + # _total_char purposes. + if order < CharacterCategory.CONTROL: + self._total_char += 1 + if order < self.SAMPLE_SIZE: + self._freq_char += 1 + if self._last_order < self.SAMPLE_SIZE: + self._total_seqs += 1 + if not self._reversed: + i = (self._last_order * self.SAMPLE_SIZE) + order + model = self._model['precedence_matrix'][i] + else: # reverse the order of the letters in the lookup + i = (order * self.SAMPLE_SIZE) + self._last_order + model = self._model['precedence_matrix'][i] + self._seq_counters[model] += 1 + self._last_order = order + + charset_name = self._model['charset_name'] + if self.state == ProbingState.DETECTING: + if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: + confidence = self.get_confidence() + if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, we have a winner', + charset_name, confidence) + self._state = ProbingState.FOUND_IT + elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, below negative ' + 'shortcut threshhold %s', charset_name, + confidence, + self.NEGATIVE_SHORTCUT_THRESHOLD) + self._state = ProbingState.NOT_ME + + return self.state + + def get_confidence(self): + r = 0.01 + if self._total_seqs > 0: + r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / + self._total_seqs / self._model['typical_positive_ratio']) + r = r * self._freq_char / self._total_char + if r >= 1.0: + r = 0.99 + return r diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcsgroupprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcsgroupprober.py new file mode 100644 index 00000000..98e95dc1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sbcsgroupprober.py @@ -0,0 +1,73 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .sbcharsetprober import SingleByteCharSetProber +from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, + Latin5CyrillicModel, MacCyrillicModel, + Ibm866Model, Ibm855Model) +from .langgreekmodel import Latin7GreekModel, Win1253GreekModel +from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel +# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel +from .langthaimodel import TIS620ThaiModel +from .langhebrewmodel import Win1255HebrewModel +from .hebrewprober import HebrewProber +from .langturkishmodel import Latin5TurkishModel + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + super(SBCSGroupProber, self).__init__() + self.probers = [ + SingleByteCharSetProber(Win1251CyrillicModel), + SingleByteCharSetProber(Koi8rModel), + SingleByteCharSetProber(Latin5CyrillicModel), + SingleByteCharSetProber(MacCyrillicModel), + SingleByteCharSetProber(Ibm866Model), + SingleByteCharSetProber(Ibm855Model), + SingleByteCharSetProber(Latin7GreekModel), + SingleByteCharSetProber(Win1253GreekModel), + SingleByteCharSetProber(Latin5BulgarianModel), + SingleByteCharSetProber(Win1251BulgarianModel), + # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) + # after we retrain model. + # SingleByteCharSetProber(Latin2HungarianModel), + # SingleByteCharSetProber(Win1250HungarianModel), + SingleByteCharSetProber(TIS620ThaiModel), + SingleByteCharSetProber(Latin5TurkishModel), + ] + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, + False, hebrew_prober) + visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, + hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) + self.probers.extend([hebrew_prober, logical_hebrew_prober, + visual_hebrew_prober]) + + self.reset() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sjisprober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sjisprober.py new file mode 100644 index 00000000..9e29623b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJIS_SM_MODEL +from .enums import ProbingState, MachineState + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + super(SJISProber, self).__init__() + self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) + self.distribution_analyzer = SJISDistributionAnalysis() + self.context_analyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + super(SJISProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return self.context_analyzer.charset_name + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char[2 - char_len:], + char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 + - char_len], char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/universaldetector.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/universaldetector.py new file mode 100644 index 00000000..7b4e92d6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### +""" +Module containing the UniversalDetector detector class, which is the primary +class a user of ``chardet`` should use. + +:author: Mark Pilgrim (initial port to Python) +:author: Shy Shalom (original C code) +:author: Dan Blanchard (major refactoring for 3.0) +:author: Ian Cordasco +""" + + +import codecs +import logging +import re + +from .charsetgroupprober import CharSetGroupProber +from .enums import InputState, LanguageFilter, ProbingState +from .escprober import EscCharSetProber +from .latin1prober import Latin1Prober +from .mbcsgroupprober import MBCSGroupProber +from .sbcsgroupprober import SBCSGroupProber + + +class UniversalDetector(object): + """ + The ``UniversalDetector`` class underlies the ``chardet.detect`` function + and coordinates all of the different charset probers. + + To get a ``dict`` containing an encoding and its confidence, you can simply + run: + + .. code:: + + u = UniversalDetector() + u.feed(some_bytes) + u.close() + detected = u.result + + """ + + MINIMUM_THRESHOLD = 0.20 + HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') + ESC_DETECTOR = re.compile(b'(\033|~{)') + WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') + ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', + 'iso-8859-2': 'Windows-1250', + 'iso-8859-5': 'Windows-1251', + 'iso-8859-6': 'Windows-1256', + 'iso-8859-7': 'Windows-1253', + 'iso-8859-8': 'Windows-1255', + 'iso-8859-9': 'Windows-1254', + 'iso-8859-13': 'Windows-1257'} + + def __init__(self, lang_filter=LanguageFilter.ALL): + self._esc_charset_prober = None + self._charset_probers = [] + self.result = None + self.done = None + self._got_data = None + self._input_state = None + self._last_char = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + self._has_win_bytes = None + self.reset() + + def reset(self): + """ + Reset the UniversalDetector and all of its probers back to their + initial states. This is called by ``__init__``, so you only need to + call this directly in between analyses of different documents. + """ + self.result = {'encoding': None, 'confidence': 0.0, 'language': None} + self.done = False + self._got_data = False + self._has_win_bytes = False + self._input_state = InputState.PURE_ASCII + self._last_char = b'' + if self._esc_charset_prober: + self._esc_charset_prober.reset() + for prober in self._charset_probers: + prober.reset() + + def feed(self, byte_str): + """ + Takes a chunk of a document and feeds it through all of the relevant + charset probers. + + After calling ``feed``, you can check the value of the ``done`` + attribute to see if you need to continue feeding the + ``UniversalDetector`` more data, or if it has made a prediction + (in the ``result`` attribute). + + .. note:: + You should always call ``close`` when you're done feeding in your + document if ``done`` is not already ``True``. + """ + if self.done: + return + + if not len(byte_str): + return + + if not isinstance(byte_str, bytearray): + byte_str = bytearray(byte_str) + + # First check for known BOMs, since these are guaranteed to be correct + if not self._got_data: + # If the data starts with BOM, we know it is UTF + if byte_str.startswith(codecs.BOM_UTF8): + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8-SIG", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_UTF32_LE, + codecs.BOM_UTF32_BE)): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\xFE\xFF\x00\x00'): + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\x00\x00\xFF\xFE'): + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", + 'confidence': 1.0, + 'language': ''} + + self._got_data = True + if self.result['encoding'] is not None: + self.done = True + return + + # If none of those matched and we've only see ASCII so far, check + # for high bytes and escape sequences + if self._input_state == InputState.PURE_ASCII: + if self.HIGH_BYTE_DETECTOR.search(byte_str): + self._input_state = InputState.HIGH_BYTE + elif self._input_state == InputState.PURE_ASCII and \ + self.ESC_DETECTOR.search(self._last_char + byte_str): + self._input_state = InputState.ESC_ASCII + + self._last_char = byte_str[-1:] + + # If we've seen escape sequences, use the EscCharSetProber, which + # uses a simple state machine to check for known escape sequences in + # HZ and ISO-2022 encodings, since those are the only encodings that + # use such sequences. + if self._input_state == InputState.ESC_ASCII: + if not self._esc_charset_prober: + self._esc_charset_prober = EscCharSetProber(self.lang_filter) + if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': + self._esc_charset_prober.charset_name, + 'confidence': + self._esc_charset_prober.get_confidence(), + 'language': + self._esc_charset_prober.language} + self.done = True + # If we've seen high bytes (i.e., those with values greater than 127), + # we need to do more complicated checks using all our multi-byte and + # single-byte probers that are left. The single-byte probers + # use character bigram distributions to determine the encoding, whereas + # the multi-byte probers use a combination of character unigram and + # bigram distributions. + elif self._input_state == InputState.HIGH_BYTE: + if not self._charset_probers: + self._charset_probers = [MBCSGroupProber(self.lang_filter)] + # If we're checking non-CJK encodings, use single-byte prober + if self.lang_filter & LanguageFilter.NON_CJK: + self._charset_probers.append(SBCSGroupProber()) + self._charset_probers.append(Latin1Prober()) + for prober in self._charset_probers: + if prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': prober.charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language} + self.done = True + break + if self.WIN_BYTE_DETECTOR.search(byte_str): + self._has_win_bytes = True + + def close(self): + """ + Stop analyzing the current document and come up with a final + prediction. + + :returns: The ``result`` attribute, a ``dict`` with the keys + `encoding`, `confidence`, and `language`. + """ + # Don't bother with checks if we're already done + if self.done: + return self.result + self.done = True + + if not self._got_data: + self.logger.debug('no data received!') + + # Default to ASCII if it is all we've seen so far + elif self._input_state == InputState.PURE_ASCII: + self.result = {'encoding': 'ascii', + 'confidence': 1.0, + 'language': ''} + + # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD + elif self._input_state == InputState.HIGH_BYTE: + prober_confidence = None + max_prober_confidence = 0.0 + max_prober = None + for prober in self._charset_probers: + if not prober: + continue + prober_confidence = prober.get_confidence() + if prober_confidence > max_prober_confidence: + max_prober_confidence = prober_confidence + max_prober = prober + if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): + charset_name = max_prober.charset_name + lower_charset_name = max_prober.charset_name.lower() + confidence = max_prober.get_confidence() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if self._has_win_bytes: + charset_name = self.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + self.result = {'encoding': charset_name, + 'confidence': confidence, + 'language': max_prober.language} + + # Log all prober confidences if none met MINIMUM_THRESHOLD + if self.logger.getEffectiveLevel() == logging.DEBUG: + if self.result['encoding'] is None: + self.logger.debug('no probers hit minimum threshold') + for group_prober in self._charset_probers: + if not group_prober: + continue + if isinstance(group_prober, CharSetGroupProber): + for prober in group_prober.probers: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + else: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + return self.result diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/utf8prober.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/utf8prober.py new file mode 100644 index 00000000..6c3196cc --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8_SM_MODEL + + + +class UTF8Prober(CharSetProber): + ONE_CHAR_PROB = 0.5 + + def __init__(self): + super(UTF8Prober, self).__init__() + self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) + self._num_mb_chars = None + self.reset() + + def reset(self): + super(UTF8Prober, self).reset() + self.coding_sm.reset() + self._num_mb_chars = 0 + + @property + def charset_name(self): + return "utf-8" + + @property + def language(self): + return "" + + def feed(self, byte_str): + for c in byte_str: + coding_state = self.coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + if self.coding_sm.get_current_charlen() >= 2: + self._num_mb_chars += 1 + + if self.state == ProbingState.DETECTING: + if self.get_confidence() > self.SHORTCUT_THRESHOLD: + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + unlike = 0.99 + if self._num_mb_chars < 6: + unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars + return 1.0 - unlike + else: + return unlike diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/version.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/version.py new file mode 100644 index 00000000..bb2a34a7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/chardet/version.py @@ -0,0 +1,9 @@ +""" +This module exists only to simplify retrieving the version number of chardet +from within setup.py and from chardet subpackages. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + +__version__ = "3.0.4" +VERSION = __version__.split('.') diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/LICENSE b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/METADATA new file mode 100644 index 00000000..ad14c771 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/METADATA @@ -0,0 +1,184 @@ +Metadata-Version: 2.1 +Name: charmcraft +Version: 0.8.1 +Summary: The main tool to build, upload, and develop in general the Juju charms. +Home-page: https://github.com/canonical/charmcraft +Author: Facundo Batista +Author-email: facundo.batista@canonical.com +License: Apache-2.0 +Platform: UNKNOWN +Classifier: Environment :: Console +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 3 +Requires-Python: >=3 +Description-Content-Type: text/markdown +Requires-Dist: Jinja2 (==2.11.2) +Requires-Dist: PyYAML (==5.3.1) +Requires-Dist: appdirs (==1.4.4) +Requires-Dist: attrs (==20.3.0) +Requires-Dist: jsonschema (==3.2.0) +Requires-Dist: macaroonbakery (==1.3.1) +Requires-Dist: python-dateutil (==2.8.1) +Requires-Dist: requests-toolbelt (==0.9.1) +Requires-Dist: requests (==2.24.0) +Requires-Dist: tabulate (==0.8.7) + +# Charmcraft is for Kubernetes operator developers + +Charmcraft supports Kubernetes operator development. + +Charmcraft enables collaboration between operator developers, and +publication on [Charmhub](https://charmhub.io/), home of the Open Operator +Collection. + +Use `charmcraft` to: + + * Init a new charm file structure + * Build your operator into a charm for distribution + * Register your charm name on Charmhub + * Upload your charms to Charmhub + * Release your charms into channels + +You can use charmcraft with operators written in any language but we +recommend the [Python Operator Framework on +Github](https://github.com/canonical/operator) which is also [on +PyPI](https://pypi.org/project/ops/) for ease of development and +collaboration. + +Charmcraft and the Python Operator Framework extend the operator pattern +beyond Kubernetes with [universal +operators](https://juju.is/universal-operators) that drive Linux and +Windows apps. The universal operator pattern is very exciting for +multi-cloud application management. + +## Install + +The easiest way to install `charmcraft` is with + + sudo snap install charmcraft --beta + +There are multiple channels other than `--beta`. See the full list with +`snap info charmcraft`. We recommend either `latest/stable` or `latest/beta` +for everyday charming. With the snap you will always be up to date as +Charmhub services and APIs evolve. + +You can also install from PyPI with `pip3 install --user charmcraft` + +## Initialize a charm operator package file structure + +Use `charmcraft init` to create a new template charm operator file tree: + +```bash +$ mkdir my-new-charm; cd my-new-charm +$ charmcraft init +All done. +There are some notes about things we think you should do. +These are marked with ‘TODO:’, as is customary. Namely: + README.md: fill out the description + README.md: explain how to use the charm + metadata.yaml: fill out the charm's description + metadata.yaml: fill out the charm's summary +``` + +You will now have all the essential files for a charmed operator, including +the actual `src/charm.py` skeleton and various items of metadata. Charmcraft +assumes you want to work in Python so it will add `requirements.txt` with +the Python operator framework `ops`, and other conventional development +support files. + +## Build your charm + +With a correct `metadata.yaml` and with `ops` in `requirements.txt` you can +build a charm with: + +```text +$ charmcraft build +Created 'test-charm.charm'. +``` + +`charmcraft build` will fetch additional files into the tree from PyPI based +on `requirements.txt` and will compile modules using a virtualenv. + +The charm is just a zipfile with metadata and the operator code itself: + +```text +$ unzip -l test-charm.charm +Archive: test-charm.charm + Length Date Time Name +--------- ---------- ----- ---- + 221 2020-11-15 08:10 metadata.yaml +[...] + 25304 2020-11-15 08:14 venv/yaml/__pycache__/scanner.cpython-38.pyc +--------- ------- + 812617 84 files +``` + +Now, if you have a Kubernetes cluster with the Juju OLM accessible you can +directly `juju deploy ` to the cluster. You do not need to +publish your operator on Charmhub, you can pass the charm file around +directly to users, or for CI/CD purposes. + +## Charmhub login and charm name reservations + +[Charmhub](https://charmhub.io/) is the world's largest repository of +operators. It makes it easy to share and collaborate on operators. The +community are interested in operators for a very wide range of purposes, +including infrastructure-as-code and legacy application management, and of +course Kubernetes operators. + +Use `charmcraft login` and `charmcraft logout` to sign into Charmhub. + +## Charmhub name registration + +You can register operator names in Charmhub with `charmcraft register +`. Many common names have been reserved, you are encouraged to discuss +your interest in leading or collaborating on a charm in [Charmhub +Discourse](https://discourse.charmhub.io/). + +Charmhub naming policy is the principle of least surprise - a well-known +name should map to an operator that most people would expect to get for that +name. + +Operators in Charmhub can be renamed as needed, so feel free to register a +temporary name, such as - as a placeholder. + +## Operator upload and release + +Charmhub operators are published in channels, like: + +```text +latest/stable +latest/candidate +latest/beta +latest/edge +1.3/beta +1.3/edge +1.2/stable +1.2/candidate +1.0/stable +``` + +Use `charmcraft upload` to get a new revision number for your freshly built +charm, and `charmcraft release` to release a revision into any particular +channel for your users. + +# Charmcraft source + +Get the source from github with: + + git clone https://github.com/canonical/charmcraft.git + cd charmcraft + virtualenv venv + . venv/bin/activate + pip install -r requirements.txt + python -m charmcraft + +If you would like to run the tests you can do so with + + pip install -r requirements-dev.txt + ./run_tests + +Contributions welcome! + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/RECORD new file mode 100644 index 00000000..f647a035 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/RECORD @@ -0,0 +1,60 @@ +../../../bin/charmcraft,sha256=fAaIBsliYVWVXzAYVjcVYridqqw0bPQK50dmRbE-RIk,293 +charmcraft-0.8.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +charmcraft-0.8.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357 +charmcraft-0.8.1.dist-info/METADATA,sha256=5lgDbi7x0cy_yZBVDkwH5THtStmFeX5Ml0z6MhJV4Mw,5960 +charmcraft-0.8.1.dist-info/RECORD,, +charmcraft-0.8.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 +charmcraft-0.8.1.dist-info/entry_points.txt,sha256=FdKmbFVt0I-CrHjl2mkwDf8fEx8GUIay0WIqdShVCoE,53 +charmcraft-0.8.1.dist-info/top_level.txt,sha256=ka37dQ3nvtNMpOvQhGWe3mn6HAXzkIyXk_sDS-_pqwg,11 +charmcraft/__init__.py,sha256=U0JaBQpFXw-eN4coTMHoAYL3ta6H3NhYzjcUwrTTvcM,778 +charmcraft/__main__.py,sha256=1E7b40xpslduLrUAy1SJJGrv0aiS_z9cOBo99Na_1jo,769 +charmcraft/__pycache__/__init__.cpython-38.pyc,, +charmcraft/__pycache__/__main__.cpython-38.pyc,, +charmcraft/__pycache__/cmdbase.cpython-38.pyc,, +charmcraft/__pycache__/config.cpython-38.pyc,, +charmcraft/__pycache__/helptexts.cpython-38.pyc,, +charmcraft/__pycache__/jujuignore.cpython-38.pyc,, +charmcraft/__pycache__/logsetup.cpython-38.pyc,, +charmcraft/__pycache__/main.cpython-38.pyc,, +charmcraft/__pycache__/utils.cpython-38.pyc,, +charmcraft/__pycache__/version.cpython-38.pyc,, +charmcraft/cmdbase.py,sha256=QLDNWfO_nEZsmo4CBe7uwcsntu-S00GvIw_mO3CgSh8,2868 +charmcraft/commands/__init__.py,sha256=LZ2OkKYoSMuPEKljK6kdFuR4weflnaCEkgnWU51_fuo,719 +charmcraft/commands/__pycache__/__init__.cpython-38.pyc,, +charmcraft/commands/__pycache__/build.cpython-38.pyc,, +charmcraft/commands/__pycache__/init.cpython-38.pyc,, +charmcraft/commands/__pycache__/pack.cpython-38.pyc,, +charmcraft/commands/__pycache__/utils.cpython-38.pyc,, +charmcraft/commands/__pycache__/version.cpython-38.pyc,, +charmcraft/commands/build.py,sha256=JqFYEE53ClwCHXi_KaWsrgfJNZNC1fmWvwzEgu_i0U4,15598 +charmcraft/commands/init.py,sha256=-ER6ibBYVM0t1QwU-rgVvzyFEnEpS2JI_cZxkfBcZBA,5756 +charmcraft/commands/pack.py,sha256=euv21xou4T5NTshqAErhktYCpa0_SI8o4BWhLwcBzzo,3465 +charmcraft/commands/store/__init__.py,sha256=nhWO4DIutpMvuhfirHXQdjo3IiHRlP5XvvMtFBoGq7c,37408 +charmcraft/commands/store/__pycache__/__init__.cpython-38.pyc,, +charmcraft/commands/store/__pycache__/client.cpython-38.pyc,, +charmcraft/commands/store/__pycache__/store.cpython-38.pyc,, +charmcraft/commands/store/client.py,sha256=UCZus7S9Lef0pfNGc9XwFPktzHy7BCy9tPafptGg26w,10811 +charmcraft/commands/store/store.py,sha256=IrFDMxnbUJa-TgJb4acE9CJ6jn1qK4WPcs5kj04QHEQ,9756 +charmcraft/commands/utils.py,sha256=KtpKn0KcA_oRh03ccLp17_KAmIlu5qgsur8Y5RWoC6c,2205 +charmcraft/commands/version.py,sha256=0EYCsGFQh4Mt3LW5hkpGWtki9YCR02-pI_nfytaVEQg,1572 +charmcraft/config.py,sha256=eZfs5VBw1OMZU8hXTnemYkZXR5u2EhdPXiMaCFrm_ws,6730 +charmcraft/helptexts.py,sha256=6iWbDScQdLqajeXPVXf5oLIZ_oyDXU4NKPNrJyRJsbk,9143 +charmcraft/jujuignore.py,sha256=7ZQTyxeSzfj2LW-NB-AYxNunt0KN7tU5C45gCUdbe9w,6954 +charmcraft/logsetup.py,sha256=nkfnzexNZTVgEHp77skcDdhY1wXKLhfKtQRoJMeHGrQ,4303 +charmcraft/main.py,sha256=4Lbn9MNGjUQyXmrfx9YBSjIlhXHtaDu6Auj6GFWNE3M,12578 +charmcraft/templates/charmlibs/new_library.py.j2,sha256=_m3DD9Pppdi4AY5reBb-GBTklTvfoc3TKDASUdIhwK0,1028 +charmcraft/templates/init/.flake8.j2,sha256=yOvP97zjncARsnYbYuS_w-t_iVxGrBtw1FCC59spFyY,99 +charmcraft/templates/init/.jujuignore.j2,sha256=d3D298wbcb9lpzaJazhatEIPVe2Ad6wtWqQy7m5E28A,24 +charmcraft/templates/init/LICENSE.j2,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358 +charmcraft/templates/init/README.md.j2,sha256=zxVTpo1f9DgqObe7QbjZlvnTCe2Tq8CgyEKCtUiRx64,517 +charmcraft/templates/init/actions.yaml.j2,sha256=qenRrrPa-ktCVSNI-QszxXnvbYDeT6HRGedrgiyseAY,447 +charmcraft/templates/init/config.yaml.j2,sha256=IGe6LZ8H_Hdrbvk-R9huvEv9ndGmes0otlZH0VkTMpo,319 +charmcraft/templates/init/metadata.yaml.j2,sha256=_w0f5m5Usi_tLEu3XGoSUTbB3MIvOeNPWBBq_BFhDek,221 +charmcraft/templates/init/requirements-dev.txt.j2,sha256=k_Yz7UH3mvSaAIHSnZDUMB_jwKtyYd0B2BZ9kWt439c,36 +charmcraft/templates/init/requirements.txt.j2,sha256=enC05wWafSg8iDKIvj3gvtAtEP2kYCyN5Gmd689q-_I,4 +charmcraft/templates/init/run_tests.j2,sha256=HHNPI8NLJGkR65WqOmDdHikW5r_t9D6VFo3VNO6zKVk,340 +charmcraft/templates/init/src/charm.py.j2,sha256=6K9peWQyDAQM5iDzKqmjELWv-8ykKX-tWSQCeshMZrE,1531 +charmcraft/templates/init/tests/__init__.py.j2,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +charmcraft/templates/init/tests/test_charm.py.j2,sha256=ur5WN8-yoKI5_9Bbobs8_TauyBuLWV1EOn3a93sbYi4,1175 +charmcraft/utils.py,sha256=MHJzQH3JgTcpxhkfrR1TJG-UA7dI0_LsCEQiqQpot5M,2253 +charmcraft/version.py,sha256=HbQcNycvTh_GG9dkE3Cfg9zBZDRhdfe0iiVe9I18Msk,47 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/WHEEL new file mode 100644 index 00000000..b552003f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/entry_points.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/entry_points.txt new file mode 100644 index 00000000..1d892b95 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +charmcraft = charmcraft.main:main + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/top_level.txt new file mode 100644 index 00000000..8b826e4b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft-0.8.1.dist-info/top_level.txt @@ -0,0 +1 @@ +charmcraft diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__init__.py new file mode 100644 index 00000000..8420e7fe --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__init__.py @@ -0,0 +1,19 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Expose needed names at main package level.""" + +from .version import version as __version__ # noqa: F401 (imported but unused) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__main__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__main__.py new file mode 100644 index 00000000..68a3d121 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/__main__.py @@ -0,0 +1,23 @@ +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Init file to allow execution of charmcraft as a module.""" + +import sys + +from charmcraft import main + +sys.exit(main.main()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/cmdbase.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/cmdbase.py new file mode 100644 index 00000000..fcaba306 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/cmdbase.py @@ -0,0 +1,81 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Infrastructure for common base commands functionality.""" + + +class CommandError(Exception): + """Base exception for all error commands. + + It optionally receives a `retcode` parameter that will be the returned code + by the process on exit, and a `argsparsing` one to indicate that the problem + is in the command line usage. + + XXX Facundo 2020-09-21: This will be refactored soon in the branch where all + output messages are standarized. + """ + + def __init__(self, message, retcode=1, argsparsing=False): + self.retcode = retcode + self.argsparsing = argsparsing + super().__init__(message) + + +class BaseCommand: + """Base class to build charmcraft commands. + + Subclass this to create a new command; the subclass must define the following attributes: + + - name: the identifier in the command line + - help_msg: a one line help for user documentation + - common: if it's a common/starter command, which are prioritized in the help + - needs_config: will ensure a config is provided when executing the command + + It also must/can override some methods for the proper command behaviour (see each + method's docstring). + + The subclass must be declared in the corresponding section of main.COMMAND_GROUPS, + and will receive and store this group on instantiation (if overriding `__init__`, the + subclass must pass it through upwards). + """ + + name = None + help_msg = None + overview = None + common = False + needs_config = False + + def __init__(self, group, config): + self.group = group + self.config = config + + def fill_parser(self, parser): + """Specify command's specific parameters. + + Each command parameters are independant of other commands, but note there are some + global ones (see `main.Dispatcher._build_argument_parser`). + + If this method is not overriden, the command will not have any parameters. + """ + + def run(self, parsed_args): + """Execute command's actual functionality. + + It must be overridden by the command implementation. + + This will receive parsed arguments that were defined in :meth:.fill_parser. + """ + raise NotImplementedError() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/__init__.py new file mode 100644 index 00000000..85360b37 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/__init__.py @@ -0,0 +1,17 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Flag the sub package for files to be included when distributing.""" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/build.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/build.py new file mode 100644 index 00000000..25775c65 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/build.py @@ -0,0 +1,398 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Infrastructure for the 'build' command.""" + +import errno +import logging +import os +import pathlib +import shutil +import subprocess +import zipfile + +import yaml + +from charmcraft.cmdbase import BaseCommand, CommandError +from charmcraft.jujuignore import JujuIgnore, default_juju_ignore +from charmcraft.utils import make_executable + +logger = logging.getLogger(__name__) + +# Some constants that are used through the code. +CHARM_METADATA = 'metadata.yaml' +BUILD_DIRNAME = 'build' +VENV_DIRNAME = 'venv' + +# The file name and template for the dispatch script +DISPATCH_FILENAME = 'dispatch' +# If Juju doesn't support the dispatch mechanism, it will execute the +# hook, and we'd need sys.argv[0] to be the name of the hook but it's +# geting lost by calling this dispatch, so we fake JUJU_DISPATCH_PATH +# to be the value it would've otherwise been. +DISPATCH_CONTENT = """#!/bin/sh + +JUJU_DISPATCH_PATH="${{JUJU_DISPATCH_PATH:-$0}}" PYTHONPATH=lib:venv ./{entrypoint_relative_path} +""" + +# The minimum set of hooks to be provided for compatibility with old Juju +MANDATORY_HOOK_NAMES = {'install', 'start', 'upgrade-charm'} +HOOKS_DIR = 'hooks' + + +def _pip_needs_system(): + """Determine whether pip3 defaults to --user, needing --system to turn it off.""" + try: + from pip.commands.install import InstallCommand + return InstallCommand().cmd_opts.get_option('--system') is not None + except (ImportError, AttributeError, TypeError): + # probably not the bionic pip version then + return False + + +def polite_exec(cmd): + """Execute a command, only showing output if error.""" + logger.debug("Running external command %s", cmd) + try: + proc = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True) + except Exception as err: + logger.error("Executing %s crashed with %r", cmd, err) + return 1 + + for line in proc.stdout: + logger.debug(":: %s", line.rstrip()) + retcode = proc.wait() + + if retcode: + logger.error("Executing %s failed with return code %d", cmd, retcode) + return retcode + + +def relativise(src, dst): + """Build a relative path from src to dst.""" + return pathlib.Path(os.path.relpath(str(dst), str(src.parent))) + + +class Builder: + """The package builder.""" + + def __init__(self, args): + self.charmdir = args['from'] + self.entrypoint = args['entrypoint'] + self.requirement_paths = args['requirement'] + + self.buildpath = self.charmdir / BUILD_DIRNAME + self.ignore_rules = self._load_juju_ignore() + + def run(self): + """Build the charm.""" + logger.debug("Building charm in '%s'", self.buildpath) + + if self.buildpath.exists(): + shutil.rmtree(str(self.buildpath)) + self.buildpath.mkdir() + + linked_entrypoint = self.handle_generic_paths() + self.handle_dispatcher(linked_entrypoint) + self.handle_dependencies() + zipname = self.handle_package() + + logger.info("Created '%s'.", zipname) + return zipname + + def _load_juju_ignore(self): + ignore = JujuIgnore(default_juju_ignore) + path = self.charmdir / '.jujuignore' + if path.exists(): + with path.open('r', encoding='utf-8') as ignores: + ignore.extend_patterns(ignores) + return ignore + + def create_symlink(self, src_path, dest_path): + """Create a symlink in dest_path pointing relatively like src_path. + + It also verifies that the linked dir or file is inside the project. + """ + resolved_path = src_path.resolve() + if self.charmdir in resolved_path.parents: + relative_link = relativise(src_path, resolved_path) + dest_path.symlink_to(relative_link) + else: + rel_path = src_path.relative_to(self.charmdir) + logger.warning( + "Ignoring symlink because targets outside the project: '%s'", rel_path) + + def handle_generic_paths(self): + """Handle all files and dirs except what's ignored and what will be handled later. + + Works differently for the different file types: + - regular files: hard links + - directories: created + - symlinks: respected if are internal to the project + - other types (blocks, mount points, etc): ignored + """ + logger.debug("Linking in generic paths") + + for basedir, dirnames, filenames in os.walk(str(self.charmdir), followlinks=False): + abs_basedir = pathlib.Path(basedir) + rel_basedir = abs_basedir.relative_to(self.charmdir) + + # process the directories + ignored = [] + for pos, name in enumerate(dirnames): + rel_path = rel_basedir / name + abs_path = abs_basedir / name + + if self.ignore_rules.match(str(rel_path), is_dir=True): + logger.debug("Ignoring directory because of rules: '%s'", rel_path) + ignored.append(pos) + elif abs_path.is_symlink(): + dest_path = self.buildpath / rel_path + self.create_symlink(abs_path, dest_path) + else: + dest_path = self.buildpath / rel_path + dest_path.mkdir(mode=abs_path.stat().st_mode) + + # in the future don't go inside ignored directories + for pos in reversed(ignored): + del dirnames[pos] + + # process the files + for name in filenames: + rel_path = rel_basedir / name + abs_path = abs_basedir / name + + if self.ignore_rules.match(str(rel_path), is_dir=False): + logger.debug("Ignoring file because of rules: '%s'", rel_path) + elif abs_path.is_symlink(): + dest_path = self.buildpath / rel_path + self.create_symlink(abs_path, dest_path) + elif abs_path.is_file(): + dest_path = self.buildpath / rel_path + try: + os.link(str(abs_path), str(dest_path)) + except PermissionError: + # when not allowed to create hard links + shutil.copy2(str(abs_path), str(dest_path)) + except OSError as e: + if e.errno != errno.EXDEV: + raise + shutil.copy2(str(abs_path), str(dest_path)) + else: + logger.debug("Ignoring file because of type: '%s'", rel_path) + + # the linked entrypoint is calculated here because it's when it's really in the build dir + linked_entrypoint = self.buildpath / self.entrypoint.relative_to(self.charmdir) + return linked_entrypoint + + def handle_dispatcher(self, linked_entrypoint): + """Handle modern and classic dispatch mechanisms.""" + # dispatch mechanism, create one if wasn't provided by the project + dispatch_path = self.buildpath / DISPATCH_FILENAME + if not dispatch_path.exists(): + logger.debug("Creating the dispatch mechanism") + dispatch_content = DISPATCH_CONTENT.format( + entrypoint_relative_path=linked_entrypoint.relative_to(self.buildpath)) + with dispatch_path.open("wt", encoding="utf8") as fh: + fh.write(dispatch_content) + make_executable(fh) + + # bunch of symlinks, to support old juju: verify that any of the already included hooks + # in the directory is not linking directly to the entrypoint, and also check all the + # mandatory ones are present + dest_hookpath = self.buildpath / HOOKS_DIR + if not dest_hookpath.exists(): + dest_hookpath.mkdir() + + # get those built hooks that we need to replace because they are pointing to the + # entrypoint directly and we need to fix the environment in the middle + current_hooks_to_replace = [] + for node in dest_hookpath.iterdir(): + if node.resolve() == linked_entrypoint: + current_hooks_to_replace.append(node) + node.unlink() + logger.debug( + "Replacing existing hook %r as it's a symlink to the entrypoint", node.name) + + # include the mandatory ones and those we need to replace + hooknames = MANDATORY_HOOK_NAMES | {x.name for x in current_hooks_to_replace} + for hookname in hooknames: + logger.debug("Creating the %r hook script pointing to dispatch", hookname) + dest_hook = dest_hookpath / hookname + if not dest_hook.exists(): + relative_link = relativise(dest_hook, dispatch_path) + dest_hook.symlink_to(relative_link) + + def handle_dependencies(self): + """Handle from-directory and virtualenv dependencies.""" + logger.debug("Installing dependencies") + + # virtualenv with other dependencies (if any) + if self.requirement_paths: + retcode = polite_exec(['pip3', 'list']) + if retcode: + raise CommandError("problems using pip") + + venvpath = self.buildpath / VENV_DIRNAME + cmd = [ + 'pip3', 'install', # base command + '--target={}'.format(venvpath), # put all the resulting files in that specific dir + ] + if _pip_needs_system(): + logger.debug("adding --system to work around pip3 defaulting to --user") + cmd.append("--system") + for reqspath in self.requirement_paths: + cmd.append('--requirement={}'.format(reqspath)) # the dependencies file(s) + retcode = polite_exec(cmd) + if retcode: + raise CommandError("problems installing dependencies") + + def handle_package(self): + """Handle the final package creation.""" + logger.debug("Parsing the project's metadata") + with (self.charmdir / CHARM_METADATA).open('rt', encoding='utf8') as fh: + metadata = yaml.safe_load(fh) + + logger.debug("Creating the package itself") + zipname = metadata['name'] + '.charm' + zipfh = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) + buildpath_str = str(self.buildpath) # os.walk does not support pathlib in 3.5 + for dirpath, dirnames, filenames in os.walk(buildpath_str, followlinks=True): + dirpath = pathlib.Path(dirpath) + for filename in filenames: + filepath = dirpath / filename + zipfh.write(str(filepath), str(filepath.relative_to(self.buildpath))) + + zipfh.close() + return zipname + + +class Validator: + """A validator of all received options.""" + + _options = [ + 'from', # this needs to be processed first, as it's a base dir to find other files + 'entrypoint', + 'requirement', + ] + + def __init__(self): + self.basedir = None # this will be fulfilled when processing 'from' + + def process(self, parsed_args): + """Process the received options.""" + result = {} + for opt in self._options: + meth = getattr(self, 'validate_' + opt) + result[opt] = meth(getattr(parsed_args, opt, None)) + return result + + def validate_from(self, dirpath): + """Validate that the charm dir is there and yes, a directory.""" + if dirpath is None: + dirpath = pathlib.Path.cwd() + else: + dirpath = dirpath.expanduser().absolute() + + if not dirpath.exists(): + raise CommandError("Charm directory was not found: {!r}".format(str(dirpath))) + if not dirpath.is_dir(): + raise CommandError( + "Charm directory is not really a directory: {!r}".format(str(dirpath))) + + self.basedir = dirpath + return dirpath + + def validate_entrypoint(self, filepath): + """Validate that the entrypoint exists and is executable.""" + if filepath is None: + filepath = self.basedir / 'src' / 'charm.py' + else: + filepath = filepath.expanduser().absolute() + + if not filepath.exists(): + raise CommandError("Charm entry point was not found: {!r}".format(str(filepath))) + if self.basedir not in filepath.parents: + raise CommandError( + "Charm entry point must be inside the project: {!r}".format(str(filepath))) + if not os.access(str(filepath), os.X_OK): # access does not support pathlib in 3.5 + raise CommandError( + "Charm entry point must be executable: {!r}".format(str(filepath))) + return filepath + + def validate_requirement(self, filepaths): + """Validate that the given requirement(s) (if any) exist. + + If not specified, default to requirements.txt if there. + """ + if filepaths is None: + req = self.basedir / 'requirements.txt' + if req.exists() and os.access(str(req), os.R_OK): # access doesn't support pathlib 3.5 + return [req] + return [] + + filepaths = [x.expanduser().absolute() for x in filepaths] + for fpath in filepaths: + if not fpath.exists(): + raise CommandError("the requirements file was not found: {!r}".format(str(fpath))) + return filepaths + + +_overview = """ +Build a charm operator package. + +You can `juju deploy` the resulting `.charm` file directly, or upload it +to Charmhub with `charmcraft upload`. + +You must be inside a charm directory with a valid `metadata.yaml`, +`requirements.txt` including the `ops` package for the Python operator +framework, and an operator entrypoint, usually `src/charm.py`. + +See `charmcraft init` to create a template charm directory structure. +""" + + +class BuildCommand(BaseCommand): + """Build the charm.""" + + name = 'build' + help_msg = "Build the charm" + overview = _overview + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + '-f', '--from', type=pathlib.Path, + help="Charm directory with metadata.yaml where the build " + "takes place; defaults to '.'") + parser.add_argument( + '-e', '--entrypoint', type=pathlib.Path, + help="The executable which is the operator entry point; " + "defaults to 'src/charm.py'") + parser.add_argument( + '-r', '--requirement', action='append', type=pathlib.Path, + help="File(s) listing needed PyPI dependencies (can be used multiple " + "times); defaults to 'requirements.txt'") + + def run(self, parsed_args): + """Run the command.""" + validator = Validator() + args = validator.process(parsed_args) + logger.debug("working arguments: %s", args) + builder = Builder(args) + builder.run() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/init.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/init.py new file mode 100644 index 00000000..04793e82 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/init.py @@ -0,0 +1,145 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Infrastructure for the 'init' command.""" + +import logging +import os +import pwd +import re +from datetime import date + +import yaml + +from charmcraft.cmdbase import BaseCommand, CommandError +from charmcraft.utils import make_executable, get_templates_environment + +logger = logging.getLogger(__name__) + +_overview = """ +Initialize a charm operator package tree and files. + +This command will modify the directory to create the necessary files for a +charm operator package. By default it will work in the current directory. +It will setup the following tree of files and directories: + +. +├── metadata.yaml - Charm operator package description +├── README.md - Frontpage for your charmhub.io/charm/ +├── actions.yaml - Day-2 action declarations, e.g. backup, restore +├── config.yaml - Config schema for your operator +├── LICENSE - Your charm license, we recommend Apache 2 +├── requirements.txt - PyPI dependencies for your charm, with `ops` +├── requirements-dev.txt - PyPI for development tooling, notably flake8 +├── run_tests +├── src +│   └── charm.py - Minimal operator using Python operator framework +└── tests + ├── __init__.py + └── test_charm.py + +You will need to edit at least metadata.yaml and README.md. + +Your minimal operator code is in src/charm.py which uses the Python operator +framework from https://github.com/canonical/operator and there are some +example tests with a harness to run them. +""" + + +class InitCommand(BaseCommand): + """Initialize a directory to be a charm project.""" + + name = "init" + help_msg = "Initialize a charm operator package tree and files" + overview = _overview + common = True + + def fill_parser(self, parser): + """Specify command's specific parameters.""" + parser.add_argument( + "--name", + help="The name of the charm; defaults to the directory name") + parser.add_argument( + "--author", + help="The charm author; defaults to the current user name per GECOS") + parser.add_argument( + "--series", default="kubernetes", + help="A comma-separated list of supported platform series;" + " defaults to 'kubernetes'") + parser.add_argument( + "-f", "--force", action="store_true", + help="Initialize even if the directory is not empty (will not overwrite files)") + + def run(self, args): + """Execute command's actual functionality.""" + if any(self.config.project.dirpath.iterdir()) and not args.force: + raise CommandError( + "{} is not empty (consider using --force to work on nonempty directories)" + .format(self.config.project.dirpath)) + logger.debug("Using project directory '%s'", self.config.project.dirpath) + + if args.author is None: + gecos = pwd.getpwuid(os.getuid()).pw_gecos.split(',', 1)[0] + if not gecos: + raise CommandError("Author not given, and nothing in GECOS field") + logger.debug("Setting author to %r from GECOS field", gecos) + args.author = gecos + + if not args.name: + args.name = self.config.project.dirpath.name + logger.debug("Set project name to '%s'", args.name) + + if not re.match(r"[a-z][a-z0-9-]*[a-z0-9]$", args.name): + raise CommandError("{} is not a valid charm name".format(args.name)) + + context = { + "name": args.name, + "author": args.author, + "year": date.today().year, + "class_name": "".join(re.split(r"\W+", args.name.title())) + "Charm", + "series": yaml.dump(args.series.split(","), default_flow_style=True), + } + + env = get_templates_environment('init') + + _todo_rx = re.compile("TODO: (.*)") + todos = [] + executables = ["run_tests", "src/charm.py"] + for template_name in env.list_templates(): + if not template_name.endswith(".j2"): + continue + template = env.get_template(template_name) + template_name = template_name[:-3] + logger.debug("Rendering %s", template_name) + path = self.config.project.dirpath / template_name + if path.exists(): + continue + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("wt", encoding="utf8") as fh: + out = template.render(context) + fh.write(out) + for todo in _todo_rx.findall(out): + todos.append((template_name, todo)) + if template_name in executables: + make_executable(fh) + logger.debug(" made executable") + logger.info("Charm operator package file and directory tree initialized.") + if todos: + logger.info("TODO:") + logger.info("") + w = max(len(i[0]) for i in todos) + for fn, todo in todos: + logger.info("%*s: %s", w + 2, fn, todo) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/pack.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/pack.py new file mode 100644 index 00000000..7eb58a62 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/pack.py @@ -0,0 +1,104 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Infrastructure for the 'pack' command.""" + +import logging +import zipfile + +from charmcraft.cmdbase import BaseCommand, CommandError +from charmcraft.utils import load_yaml + +logger = logging.getLogger(__name__) + +# the minimum set of files in a bundle +MANDATORY_FILES = {'bundle.yaml'} + + +def build_zip(zippath, basedir, fpaths): + """Build the final file. + + Note we convert all paths to str to support Python 3.5. + """ + zipfh = zipfile.ZipFile(str(zippath), 'w', zipfile.ZIP_DEFLATED) + for fpath in fpaths: + zipfh.write(str(fpath), str(fpath.relative_to(basedir))) + zipfh.close() + + +def get_paths_to_include(config): + """Get all file/dir paths to include.""" + dirpath = config.project.dirpath + allpaths = set() + + # all mandatory files, which must exist (currently only bundles.yaml is mandatory, and + # it's verified before) + for fname in MANDATORY_FILES: + allpaths.add(dirpath / fname) + + # the extra files (relative paths) + for spec in config.parts: + fpaths = sorted(fpath for fpath in dirpath.glob(spec) if fpath.is_file()) + logger.debug("Including per prime config %r: %s.", spec, fpaths) + allpaths.update(fpaths) + + return sorted(allpaths) + + +_overview = """ +Build the bundle and package it as a zip archive. + +You can `juju deploy` the bundle .zip file or upload it to +the store (see the "upload" command). +""" + + +class PackCommand(BaseCommand): + """Build the bundle or the charm. + + Eventually this command will also support charms, but for now it will work only + on bundles. + """ + + name = 'pack' + help_msg = "Build the bundle" + overview = _overview + needs_config = True + + def run(self, parsed_args): + """Run the command.""" + # get the config files + bundle_filepath = self.config.project.dirpath / 'bundle.yaml' + bundle_config = load_yaml(bundle_filepath) + if bundle_config is None: + raise CommandError( + "Missing or invalid main bundle file: '{}'.".format(bundle_filepath)) + bundle_name = bundle_config.get('name') + if not bundle_name: + raise CommandError( + "Invalid bundle config; missing a 'name' field indicating the bundle's name in " + "file '{}'.".format(bundle_filepath)) + + # so far 'pack' works for bundles only (later this will operate also on charms) + if self.config.type != 'bundle': + raise CommandError( + "Bad config: 'type' field in charmcraft.yaml must be 'bundle' for this command.") + + # pack everything + paths = get_paths_to_include(self.config) + zipname = self.config.project.dirpath / (bundle_name + '.zip') + build_zip(zipname, self.config.project.dirpath, paths) + logger.info("Created '%s'.", zipname) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/__init__.py new file mode 100644 index 00000000..ff0cf214 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/__init__.py @@ -0,0 +1,977 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Commands related to Charmhub.""" + +import ast +import hashlib +import logging +import os +import pathlib +import string +import textwrap +from collections import namedtuple +from operator import attrgetter + +import yaml +from tabulate import tabulate + +from charmcraft.cmdbase import BaseCommand, CommandError +from charmcraft.utils import get_templates_environment + +from .store import Store + +logger = logging.getLogger('charmcraft.commands.store') + +LibData = namedtuple( + 'LibData', 'lib_id api patch content content_hash full_name path lib_name charm_name') + + +def get_name_from_metadata(): + """Return the name if present and plausible in metadata.yaml.""" + try: + with open('metadata.yaml', 'rb') as fh: + metadata = yaml.safe_load(fh) + charm_name = metadata['name'] + except (yaml.error.YAMLError, OSError, KeyError): + return + return charm_name + + +class LoginCommand(BaseCommand): + """Login to Charmhub.""" + + name = 'login' + help_msg = "Login to Charmhub" + overview = textwrap.dedent(""" + Login to Charmhub. + + Charmcraft will provide a URL for the Charmhub login. When you have + successfully logged in, charmcraft will store a token for ongoing + access to Charmhub at the CLI. + + Remember to `charmcraft logout` if you want to remove that token + from your local system, especially in a shared environment. + + See also `charmcraft whoami` to verify that you are logged in. + + """) + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + store.login() + logger.info("Logged in as '%s'.", store.whoami().username) + + +class LogoutCommand(BaseCommand): + """Clear Charmhub token.""" + + name = 'logout' + help_msg = "Logout from Charmhub and remove token" + overview = textwrap.dedent(""" + Clear the Charmhub token. + + Charmcraft will remove the local token used for Charmhub access. + This is important on any shared system because the token allows + manipulation of your published charms. + + See also `charmcraft whoami` to verify that you are logged in, + and `charmcraft login`. + + """) + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + store.logout() + logger.info("Charmhub token cleared.") + + +class WhoamiCommand(BaseCommand): + """Show login information.""" + + name = 'whoami' + help_msg = "Show your Charmhub login status" + overview = textwrap.dedent(""" + Show your Charmhub login status. + + See also `charmcraft login` and `charmcraft logout`. + """) + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + result = store.whoami() + + data = [ + ('name:', result.name), + ('username:', result.username), + ('id:', result.userid), + ] + table = tabulate(data, tablefmt='plain') + for line in table.splitlines(): + logger.info(line) + + +class RegisterNameCommand(BaseCommand): + """Register a name in Charmhub.""" + + name = 'register' + help_msg = "Register a charm name in Charmhub" + overview = textwrap.dedent(""" + Register a charm name in Charmhub. + + Claim a name for your operator in Charmhub. Once you have registered + a name, you can upload charm operator packages for that name and + release them for wider consumption. + + Charmhub operates on the 'principle of least surprise' with regard + to naming. A charm with a well-known name should provide the best + operator for the microservice most people associate with that name. + Charms can be renamed in the Charmhub, but we would nonetheless ask + you to use a qualified name, such as `yourname-charmname` if you are + in any doubt about your ability to meet that standard. + + We discuss registrations in Charmhub Discourse: + + https://discourse.charmhub.io/c/charm + + Registration will take you through login if needed. + + """) + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument('name', help="The name to register in Charmhub") + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + store.register_name(parsed_args.name) + logger.info("You are now the publisher of %r in Charmhub.", parsed_args.name) + + +class ListNamesCommand(BaseCommand): + """List the charms registered in Charmhub.""" + + name = 'names' + help_msg = "List your registered charm names in Charmhub" + overview = textwrap.dedent(""" + An overview of names you have registered to publish in Charmhub. + + $ charmcraft names + Name Visibility Status + sabdfl-hello-world public registered + + Visibility and status are shown for each name. `public` items can be + seen by any user, while `private` items are only for you and the + other accounts with permission to collaborate on that specific name. + + Listing names will take you through login if needed. + + """) + common = True + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + result = store.list_registered_names() + if not result: + logger.info("No charms registered.") + return + + headers = ['Name', 'Visibility', 'Status'] + data = [] + for item in result: + visibility = 'private' if item.private else 'public' + data.append([ + item.name, + visibility, + item.status, + ]) + + table = tabulate(data, headers=headers, tablefmt='plain') + for line in table.splitlines(): + logger.info(line) + + +class UploadCommand(BaseCommand): + """Upload a charm to Charmhub.""" + + name = 'upload' + help_msg = "Upload a charm to Charmhub" + overview = textwrap.dedent(""" + Upload a charm to Charmhub. + + Push a charm to Charmhub where it will be verified for conformance + to the packaging standard. This command will finish successfully + once the package is approved by Charmhub. + + In the event of a failure in the verification process, charmcraft + will report details of the failure, otherwise it will give you the + new charm revision. + + Upload will take you through login if needed. + + """) + common = True + + def _discover_charm(self, charm_filepath): + """Discover the charm name and file path. + + If received path is None, a metadata.yaml will be searched in the current directory. If + path is given the name is taken from the filename. + + """ + if charm_filepath is None: + # discover the info using project's metadata, asume the file has the project's name + # with a .charm extension + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Cannot find a valid charm name in metadata.yaml to upload. Check you are in " + "a charm directory with metadata.yaml, or use --charm-file=foo.charm.") + + charm_filepath = pathlib.Path(charm_name + '.charm').absolute() + if not os.access(str(charm_filepath), os.R_OK): # access doesnt support pathlib in 3.5 + raise CommandError( + "Cannot access charm at {!r}. Try --charm-file=foo.charm" + .format(str(charm_filepath))) + + else: + # the path is given, asume the charm name is part of the file name + # XXX Facundo 2020-06-30: Actually, we need to open the ZIP file, extract the + # included metadata.yaml file, and read the name from there. Issue: #77. + charm_filepath = charm_filepath.expanduser() + if not os.access(str(charm_filepath), os.R_OK): # access doesnt support pathlib in 3.5 + raise CommandError( + "Cannot access {!r}.".format(str(charm_filepath))) + if not charm_filepath.is_file(): + raise CommandError( + "{!r} is not a file.".format(str(charm_filepath))) + + charm_name = charm_filepath.stem + + return charm_name, charm_filepath + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + '--charm-file', type=pathlib.Path, + help="The charm to upload") + + def run(self, parsed_args): + """Run the command.""" + name, path = self._discover_charm(parsed_args.charm_file) + store = Store(self.config.charmhub) + result = store.upload(name, path) + if result.ok: + logger.info("Revision %s of %r created", result.revision, str(name)) + else: + logger.info("Upload failed with status %r:", result.status) + for error in result.errors: + logger.info("- %s: %s", error.code, error.message) + + +class ListRevisionsCommand(BaseCommand): + """List revisions for a charm.""" + + name = 'revisions' + help_msg = "List revisions for a charm in Charmhub" + overview = textwrap.dedent(""" + Show version, date and status for each revision in Charmhub. + + For example: + + $ charmcraft revisions + Revision Version Created at Status + 1 1 2020-11-15 released + + Listing revisions will take you through login if needed. + + """) + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument('--name', help="The name of the charm") + + def run(self, parsed_args): + """Run the command.""" + if parsed_args.name: + charm_name = parsed_args.name + else: + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Cannot find a valid charm name in metadata.yaml. Check you are in a charm " + "directory with metadata.yaml, or use --name=foo.") + + store = Store(self.config.charmhub) + result = store.list_revisions(charm_name) + if not result: + logger.info("No revisions found.") + return + + headers = ['Revision', 'Version', 'Created at', 'Status'] + data = [] + for item in sorted(result, key=attrgetter('revision'), reverse=True): + # use just the status or include error message/code in it (if exist) + if item.errors: + errors = ("{0.message} [{0.code}]".format(e) for e in item.errors) + status = "{}: {}".format(item.status, '; '.join(errors)) + else: + status = item.status + + data.append([ + item.revision, + item.version, + item.created_at.strftime('%Y-%m-%d'), + status, + ]) + + table = tabulate(data, headers=headers, tablefmt='plain', numalign='left') + for line in table.splitlines(): + logger.info(line) + + +class ReleaseCommand(BaseCommand): + """Release a charm revision to specific channels.""" + + name = 'release' + help_msg = "Release a charm revision in one or more channels" + overview = textwrap.dedent(""" + Release a charm revision in the channel(s) provided. + + Charm revisions are not published for anybody else until you release + them in a channel. When you release a revision into a channel, users + who deploy the charm from that channel will get see the new revision + as a potential update. + + A channel is made up of `track/risk/branch` with both the track and + the branch as optional items, so formally: + + [track/]risk[/branch] + + Channel risk must be one of stable, candidate, beta or edge. The + track defaults to `latest` and branch has no default. + + It is enough just to provide a channel risk, like `stable` because + the track will be assumed to be `latest` and branch is not required. + + Some channel examples: + + stable + edge + 2.0/candidate + beta/hotfix-23425 + 1.3/beta/feature-foo + + Listing revisions will take you through login if needed. + """) + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + 'revision', type=int, help='The revision to release') + parser.add_argument( + 'channels', metavar='channel', nargs='+', + help="The channel(s) to release to") + parser.add_argument('--name', help="The name of the charm") + + def run(self, parsed_args): + """Run the command.""" + store = Store(self.config.charmhub) + + if parsed_args.name: + charm_name = parsed_args.name + else: + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Cannot find a valid charm name in metadata.yaml. Check you are in a charm " + "directory with metadata.yaml, or use --name=foo.") + + store.release(charm_name, parsed_args.revision, parsed_args.channels) + logger.info( + "Revision %d of charm %r released to %s", + parsed_args.revision, charm_name, ", ".join(parsed_args.channels)) + + +class StatusCommand(BaseCommand): + """Show channel status for a charm.""" + + name = 'status' + help_msg = "Show channel and released revisions" + overview = textwrap.dedent(""" + Show channels and released revisions in Charmhub + + Charm revisions are not available to users until they are released + into a channel. This command shows the various channels for a charm + and whether there is a charm released. + + For example: + + $ charmcraft status + Track Channel Version Revision + latest stable - - + candidate - - + beta - - + edge 1 1 + + Showing channels will take you through login if needed. + """) + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument('--name', help="The name of the charm") + + def run(self, parsed_args): + """Run the command.""" + if parsed_args.name: + charm_name = parsed_args.name + else: + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Cannot find a valid charm name in metadata.yaml. Check you are in a charm " + "directory with metadata.yaml, or use --name=foo.") + + store = Store(self.config.charmhub) + channel_map, channels, revisions = store.list_releases(charm_name) + if not channel_map: + logger.info("Nothing has been released yet.") + return + + # build easier to access structures + releases_by_channel = {item.channel: item for item in channel_map} + revisions_by_revno = {item.revision: item for item in revisions} + + # process and order the channels, while preserving the tracks order + all_tracks = [] + per_track = {} + branch_present = False + for channel in channels: + # it's super rare to have a more than just a bunch of tracks (furthermore, normally + # there's only one), so it's ok to do this sequential search + if channel.track not in all_tracks: + all_tracks.append(channel.track) + + nonbranches_list, branches_list = per_track.setdefault(channel.track, ([], [])) + if channel.branch is None: + # insert branch right after its fallback + for idx, stored in enumerate(nonbranches_list, 1): + if stored.name == channel.fallback: + nonbranches_list.insert(idx, channel) + break + else: + nonbranches_list.append(channel) + else: + branches_list.append(channel) + branch_present = True + + headers = ['Track', 'Channel', 'Version', 'Revision'] + if branch_present: + headers.append('Expires at') + + # show everything, grouped by tracks, with regular channels at first and + # branches (if any) after those + data = [] + for track in all_tracks: + release_shown_for_this_track = False + shown_track = track + channels, branches = per_track[track] + + for channel in channels: + description = channel.risk + + # get the release of the channel, fallbacking accordingly + release = releases_by_channel.get(channel.name) + if release is None: + version = revno = '↑' if release_shown_for_this_track else '-' + else: + release_shown_for_this_track = True + revno = release.revision + revision = revisions_by_revno[revno] + version = revision.version + + data.append([shown_track, description, version, revno]) + + # stop showing the track name for the rest of the track + shown_track = '' + + for branch in branches: + description = '/'.join((branch.risk, branch.branch)) + release = releases_by_channel[branch.name] + expiration = release.expires_at.isoformat() + revision = revisions_by_revno[release.revision] + data.append(['', description, revision.version, release.revision, expiration]) + + table = tabulate(data, headers=headers, tablefmt='plain', numalign='left') + for line in table.splitlines(): + logger.info(line) + + +class _BadLibraryPathError(CommandError): + """Subclass to provide a specific error for a bad library path.""" + + def __init__(self, path): + super().__init__( + "Charm library path {} must conform to lib/charms//vN/.py" + "".format(path)) + + +class _BadLibraryNameError(CommandError): + """Subclass to provide a specific error for a bad library name.""" + + def __init__(self, name): + super().__init__( + "Charm library name {!r} must conform to charms..vN." + .format(name)) + + +def _get_positive_int(raw_value): + """Convert the raw value for api/patch into a positive integer.""" + value = int(raw_value) + if value < 0: + raise ValueError('negative') + return value + + +def _get_lib_info(*, full_name=None, lib_path=None): + """Get the whole lib info from the path/file.""" + if full_name is None: + # get it from the lib_path + try: + libsdir, charmsdir, charm_name, v_api = lib_path.parts[:-1] + except ValueError: + raise _BadLibraryPathError(lib_path) + if libsdir != 'lib' or charmsdir != 'charms' or lib_path.suffix != '.py': + raise _BadLibraryPathError(lib_path) + full_name = '.'.join((charmsdir, charm_name, v_api, lib_path.stem)) + + else: + # build the path! convert a lib name with dots to the full path, including lib + # dir and Python extension. + # e.g.: charms.mycharm.v4.foo -> lib/charms/mycharm/v4/foo.py + try: + charmsdir, charm_name, v_api, libfile = full_name.split('.') + except ValueError: + raise _BadLibraryNameError(full_name) + if charmsdir != 'charms': + raise _BadLibraryNameError(full_name) + lib_path = pathlib.Path('lib') / charmsdir / charm_name / v_api / (libfile + '.py') + + if v_api[0] != 'v' or not v_api[1:].isdigit(): + raise CommandError( + "The API version in the library path must be 'vN' where N is an integer.") + api_from_path = int(v_api[1:]) + + lib_name = lib_path.stem + if not lib_path.exists(): + return LibData( + lib_id=None, api=api_from_path, patch=-1, content_hash=None, content=None, + full_name=full_name, path=lib_path, lib_name=lib_name, charm_name=charm_name) + + # parse the file and extract metadata from it, while hashing + metadata_fields = (b'LIBAPI', b'LIBPATCH', b'LIBID') + metadata = dict.fromkeys(metadata_fields) + hasher = hashlib.sha256() + with lib_path.open('rb') as fh: + for line in fh: + if line.startswith(metadata_fields): + try: + field, value = [x.strip() for x in line.split(b'=')] + except ValueError: + raise CommandError("Bad metadata line in {}: {!r}".format(lib_path, line)) + metadata[field] = value + else: + hasher.update(line) + + missing = [k.decode('ascii') for k, v in metadata.items() if v is None] + if missing: + raise CommandError( + "Library {} is missing the mandatory metadata fields: {}." + .format(lib_path, ', '.join(sorted(missing)))) + + bad_api_patch_msg = "Library {} metadata field {} is not zero or a positive integer." + try: + libapi = _get_positive_int(metadata[b'LIBAPI']) + except ValueError: + raise CommandError(bad_api_patch_msg.format(lib_path, 'LIBAPI')) + try: + libpatch = _get_positive_int(metadata[b'LIBPATCH']) + except ValueError: + raise CommandError(bad_api_patch_msg.format(lib_path, 'LIBPATCH')) + + if libapi == 0 and libpatch == 0: + raise CommandError( + "Library {} metadata fields LIBAPI and LIBPATCH cannot both be zero." + .format(lib_path)) + + if libapi != api_from_path: + raise CommandError( + "Library {} metadata field LIBAPI is different from the version in the path." + .format(lib_path)) + + bad_libid_msg = "Library {} metadata field LIBID must be a non-empty ASCII string." + try: + libid = ast.literal_eval(metadata[b'LIBID'].decode('ascii')) + except (ValueError, UnicodeDecodeError): + raise CommandError(bad_libid_msg.format(lib_path)) + if not libid or not isinstance(libid, str): + raise CommandError(bad_libid_msg.format(lib_path)) + + content_hash = hasher.hexdigest() + content = lib_path.read_text() + + return LibData( + lib_id=libid, api=libapi, patch=libpatch, content_hash=content_hash, content=content, + full_name=full_name, path=lib_path, lib_name=lib_name, charm_name=charm_name) + + +def _get_libs_from_tree(charm_name=None): + """Get library info from the directories tree (for a specific charm if specified). + + It only follows/uses the the directories/files for a correct charmlibs + disk structure. + """ + local_libs_data = [] + + if charm_name is None: + base_dir = pathlib.Path('lib') / 'charms' + charm_dirs = sorted(base_dir.iterdir()) if base_dir.is_dir() else [] + else: + base_dir = pathlib.Path('lib') / 'charms' / charm_name + charm_dirs = [base_dir] if base_dir.is_dir() else [] + + for charm_dir in charm_dirs: + for v_dir in sorted(charm_dir.iterdir()): + if v_dir.is_dir() and v_dir.name[0] == 'v' and v_dir.name[1:].isdigit(): + for libfile in sorted(v_dir.glob('*.py')): + local_libs_data.append(_get_lib_info(lib_path=libfile)) + + found_libs = [lib_data.full_name for lib_data in local_libs_data] + logger.debug("Libraries found under %s: %s", base_dir, found_libs) + return local_libs_data + + +class CreateLibCommand(BaseCommand): + """Create a charm library.""" + + name = 'create-lib' + help_msg = "Create a charm library" + overview = textwrap.dedent(""" + Create a charm library. + + Charmcraft manages charm libraries, which are published by charmers + to help other charmers integrate their charms. This command creates + a new library in your charm which you are publishing for others. + + This command MUST be run inside your charm directory with a valid + metadata.yaml. It will create the Python library with API version 0 + initially: + + lib/charms//v0/.py + + Each library has a unique identifier assigned by Charmhub that + supports accurate updates of libraries even if charms are renamed. + Charmcraft will request a unique ID from Charmhub and initialise a + template Python library. + + Creating a charm library will take you through login if needed. + + """) + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + 'name', metavar='name', + help="The name of the library file (e.g. 'db')") + + def run(self, parsed_args): + """Run the command.""" + lib_name = parsed_args.name + valid_all_chars = set(string.ascii_lowercase + string.digits + '_') + valid_first_char = string.ascii_lowercase + if set(lib_name) - valid_all_chars or not lib_name or lib_name[0] not in valid_first_char: + raise CommandError( + "Invalid library name. Must only use lowercase alphanumeric " + "characters and underscore, starting with alpha.") + + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Cannot find a valid charm name in metadata.yaml. Check you are in a charm " + "directory with metadata.yaml.") + + # all libraries born with API version 0 + full_name = 'charms.{}.v0.{}'.format(charm_name, lib_name) + lib_data = _get_lib_info(full_name=full_name) + lib_path = lib_data.path + if lib_path.exists(): + raise CommandError('This library already exists: {}'.format(lib_path)) + + store = Store(self.config.charmhub) + lib_id = store.create_library_id(charm_name, lib_name) + + # create the new library file from the template + env = get_templates_environment('charmlibs') + template = env.get_template('new_library.py.j2') + context = dict(lib_id=lib_id) + try: + lib_path.parent.mkdir(parents=True, exist_ok=True) + lib_path.write_text(template.render(context)) + except OSError as exc: + raise CommandError( + "Error writing the library in {}: {!r}.".format(lib_path, exc)) + + logger.info("Library %s created with id %s.", full_name, lib_id) + logger.info("Consider 'git add %s'.", lib_path) + + +class PublishLibCommand(BaseCommand): + """Publish one or more charm libraries.""" + + name = 'publish-lib' + help_msg = "Publish one or more charm libraries" + overview = textwrap.dedent(""" + Publish charm libraries. + + Upload and release in Charmhub the new api/patch version of the + indicated library, or all the charm libraries if --all is used. + + It will automatically take you through the login process if + your credentials are missing or too old. + """) + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + 'library', nargs='?', + help="Library to publish (e.g. charms.mycharm.v2.foo.); optional, default to all") + + def run(self, parsed_args): + """Run the command.""" + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Can't access name in 'metadata.yaml' file. The 'publish-lib' command needs to " + "be executed in a valid project's directory.") + + if parsed_args.library: + lib_data = _get_lib_info(full_name=parsed_args.library) + if not lib_data.path.exists(): + raise CommandError( + "The specified library was not found at path {}.".format(lib_data.path)) + if lib_data.charm_name != charm_name: + raise CommandError( + "The library {} does not belong to this charm {!r}.".format( + lib_data.full_name, charm_name)) + local_libs_data = [lib_data] + else: + local_libs_data = _get_libs_from_tree(charm_name) + + # check if something needs to be done + store = Store(self.config.charmhub) + to_query = [dict(lib_id=lib.lib_id, api=lib.api) for lib in local_libs_data] + libs_tips = store.get_libraries_tips(to_query) + to_publish = [] + for lib_data in local_libs_data: + logger.debug("Verifying local lib %s", lib_data) + tip = libs_tips.get((lib_data.lib_id, lib_data.api)) + logger.debug("Store tip: %s", tip) + if tip is None: + # needs to first publish + to_publish.append(lib_data) + continue + + if tip.patch > lib_data.patch: + # the store is more advanced than local + logger.info( + "Library %s is out-of-date locally, Charmhub has version %d.%d, please " + "fetch the updates before publishing.", lib_data.full_name, tip.api, tip.patch) + elif tip.patch == lib_data.patch: + # the store has same version numbers than local + if tip.content_hash == lib_data.content_hash: + logger.info("Library %s is already updated in Charmhub.", lib_data.full_name) + else: + # but shouldn't as hash is different! + logger.info( + "Library %s version %d.%d is the same than in Charmhub but content is " + "different", lib_data.full_name, tip.api, tip.patch) + elif tip.patch + 1 == lib_data.patch: + # local is correctly incremented + if tip.content_hash == lib_data.content_hash: + # but shouldn't as hash is the same! + logger.info( + "Library %s LIBPATCH number was incorrectly incremented, Charmhub has the " + "same content in version %d.%d.", lib_data.full_name, tip.api, tip.patch) + else: + to_publish.append(lib_data) + else: + logger.info( + "Library %s has a wrong LIBPATCH number, it's too high, Charmhub " + "highest version is %d.%d.", lib_data.full_name, tip.api, tip.patch) + + for lib_data in to_publish: + store.create_library_revision( + lib_data.charm_name, lib_data.lib_id, lib_data.api, lib_data.patch, + lib_data.content, lib_data.content_hash) + logger.info( + "Library %s sent to the store with version %d.%d", + lib_data.full_name, lib_data.api, lib_data.patch) + + +class FetchLibCommand(BaseCommand): + """Fetch one or more charm libraries.""" + + name = 'fetch-lib' + help_msg = "Fetch one or more charm libraries" + overview = textwrap.dedent(""" + Fetch charm libraries. + + The first time a library is downloaded the command will create the needed + directories to place it, subsequent fetches will just update the local copy. + """) + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + 'library', nargs='?', + help="Library to fetch (e.g. charms.mycharm.v2.foo.); optional, default to all") + + def run(self, parsed_args): + """Run the command.""" + if parsed_args.library: + local_libs_data = [_get_lib_info(full_name=parsed_args.library)] + else: + local_libs_data = _get_libs_from_tree() + + # get tips from the Store + store = Store(self.config.charmhub) + to_query = [] + for lib in local_libs_data: + if lib.lib_id is None: + item = dict(charm_name=lib.charm_name, lib_name=lib.lib_name) + else: + item = dict(lib_id=lib.lib_id) + item['api'] = lib.api + to_query.append(item) + libs_tips = store.get_libraries_tips(to_query) + + # check if something needs to be done + to_fetch = [] + for lib_data in local_libs_data: + logger.debug("Verifying local lib %s", lib_data) + # fix any missing lib id using the Store info + if lib_data.lib_id is None: + for tip in libs_tips.values(): + if lib_data.charm_name == tip.charm_name and lib_data.lib_name == tip.lib_name: + lib_data = lib_data._replace(lib_id=tip.lib_id) + break + + tip = libs_tips.get((lib_data.lib_id, lib_data.api)) + logger.debug("Store tip: %s", tip) + if tip is None: + logger.info("Library %s not found in Charmhub.", lib_data.full_name) + continue + + if tip.patch > lib_data.patch: + # the store has a higher version than local + to_fetch.append(lib_data) + elif tip.patch < lib_data.patch: + # the store has a lower version numbers than local + logger.info( + "Library %s has local changes, can not be updated.", lib_data.full_name) + else: + # same versions locally and in the store + if tip.content_hash == lib_data.content_hash: + logger.info( + "Library %s was already up to date in version %d.%d.", + lib_data.full_name, tip.api, tip.patch) + else: + logger.info( + "Library %s has local changes, can not be updated.", lib_data.full_name) + + for lib_data in to_fetch: + downloaded = store.get_library(lib_data.charm_name, lib_data.lib_id, lib_data.api) + if lib_data.content is None: + # locally new + lib_data.path.parent.mkdir(parents=True, exist_ok=True) + lib_data.path.write_text(downloaded.content) + logger.info( + "Library %s version %d.%d downloaded.", + lib_data.full_name, downloaded.api, downloaded.patch) + else: + # XXX Facundo 2020-12-17: manage the case where the library was renamed + # (related GH issue: #214) + lib_data.path.write_text(downloaded.content) + logger.info( + "Library %s updated to version %d.%d.", + lib_data.full_name, downloaded.api, downloaded.patch) + + +class ListLibCommand(BaseCommand): + """List all libraries belonging to a charm.""" + + name = 'list-lib' + help_msg = "List all libraries from a charm" + overview = textwrap.dedent(""" + List all libraries from a charm. + + For each library, it will show the name and the api and patch versions + for its tip. + """) + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + 'name', nargs='?', help=( + "The name of the charm (optional, will get the name from" + "metadata.yaml if not given)")) + + def run(self, parsed_args): + """Run the command.""" + if parsed_args.name: + charm_name = parsed_args.name + else: + charm_name = get_name_from_metadata() + if charm_name is None: + raise CommandError( + "Can't access name in 'metadata.yaml' file. The 'list-lib' command must " + "either be executed from a valid project directory, or specify a charm " + "name using the --charm-name option.") + + # get tips from the Store + store = Store(self.config.charmhub) + to_query = [{'charm_name': charm_name}] + libs_tips = store.get_libraries_tips(to_query) + + if not libs_tips: + logger.info("No libraries found for charm %s.", charm_name) + return + + headers = ['Library name', 'API', 'Patch'] + data = sorted((item.lib_name, item.api, item.patch) for item in libs_tips.values()) + + table = tabulate(data, headers=headers, tablefmt='plain', numalign='left') + for line in table.splitlines(): + logger.info(line) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/client.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/client.py new file mode 100644 index 00000000..8bd2024a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/client.py @@ -0,0 +1,278 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""A client to hit the Store.""" + +import logging +import os +import pathlib +import platform +import webbrowser +from http.cookiejar import MozillaCookieJar + +import appdirs +import requests +from macaroonbakery import httpbakery +from requests.adapters import HTTPAdapter +from requests.exceptions import RequestException +from requests.packages.urllib3.util.retry import Retry +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor + +from charmcraft import __version__ +from charmcraft.cmdbase import CommandError + +# set urllib3's logger to only emit errors, not warnings. Otherwise even +# retries are printed, and they're nasty. +logging.getLogger(requests.packages.urllib3.__package__).setLevel(logging.ERROR) + +logger = logging.getLogger('charmcraft.commands.store') + +TESTING_ENV_PREFIXES = ["TRAVIS", "AUTOPKGTEST_TMP"] + + +def _get_os_platform(filepath=pathlib.Path("/etc/os-release")): + """Determine a system/release combo for an OS using /etc/os-release if available.""" + system = platform.system() + release = platform.release() + machine = platform.machine() + + if system == "Linux": + os_release = {} + try: + with filepath.open("r", encoding='utf-8') as f: + for line in f: + if "=" in line: + key, value = line.rstrip().split("=", 1) + os_release[key] = value.strip('"') + except FileNotFoundError: + logger.debug("Unable to locate 'os-release' file, using default values") + finally: + system = os_release.get("NAME", system) + release = os_release.get("VERSION_ID", release) + + return "{}/{} ({})".format(system, release, machine) + + +def build_user_agent(): + """Build the charmcraft's user agent.""" + if any(key.startswith(prefix) for prefix in TESTING_ENV_PREFIXES for key in os.environ.keys()): + testing = " (testing) " + else: + testing = " " + return "charmcraft/{}{}{} python/{}".format(__version__, + testing, + _get_os_platform(), + platform.python_version()) + + +def visit_page_with_browser(visit_url): + """Open a browser so the user can validate its identity.""" + logger.warning( + "Opening an authorization web page in your browser; if it does not open, " + "please open this URL: %s", visit_url) + webbrowser.open(visit_url, new=1) + + +class _AuthHolder: + """Holder and wrapper of all authentication bits. + + Main two purposes of this class: + + - deal with credentials persistence + + - wrap HTTP calls to ensure authentication + + XXX Facundo 2020-06-18: right now for functionality bootstrapping we're storing credentials + on disk, we may move to a keyring, wallet, other solution, or firmly remain here when we + get a "security" recommendation (related: issue #52). + """ + + def __init__(self): + self._cookiejar_filepath = appdirs.user_config_dir('charmcraft.credentials') + self._cookiejar = None + self._client = None + + def clear_credentials(self): + """Clear stored credentials.""" + if os.path.exists(self._cookiejar_filepath): + os.unlink(self._cookiejar_filepath) + logger.debug("Credentials cleared: file '%s' removed", self._cookiejar_filepath) + else: + logger.debug( + "Credentials file not found to be removed: '%s'", self._cookiejar_filepath) + + def _save_credentials_if_changed(self): + """Save credentials if changed.""" + if list(self._cookiejar) != self._old_cookies: + logger.debug("Saving credentials to file: '%s'", self._cookiejar_filepath) + dirpath = os.path.dirname(self._cookiejar_filepath) + os.makedirs(dirpath, exist_ok=True) + + fd = os.open(self._cookiejar_filepath, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) + os.fchmod(fd, 0o600) + self._cookiejar.save(fd) + + def _load_credentials(self): + """Load credentials and set up internal auth request objects.""" + wbi = httpbakery.WebBrowserInteractor(open=visit_page_with_browser) + self._cookiejar = MozillaCookieJar(self._cookiejar_filepath) + self._client = httpbakery.Client(cookies=self._cookiejar, interaction_methods=[wbi]) + + if os.path.exists(self._cookiejar_filepath): + logger.debug("Loading credentials from file: '%s'", self._cookiejar_filepath) + try: + self._cookiejar.load() + except Exception as err: + # alert and continue processing (without having credentials, of course, the user + # will be asked to authenticate) + logger.warning("Failed to read credentials: %r", err) + else: + logger.debug("Credentials file not found: '%s'", self._cookiejar_filepath) + + # iterates the cookiejar (which is mutable, may change later) and get the cookies + # for comparison after hitting the endpoint + self._old_cookies = list(self._cookiejar) + + def request(self, method, url, body): + """Do a request.""" + if self._client is None: + # load everything on first usage + self._load_credentials() + + headers = {"User-Agent": build_user_agent()} + + # this request through the bakery lib will automatically catch any authentication + # problem and (if any) ask the user to authenticate and retry the original request; if + # that fails we capture it and raise a proper error + try: + resp = self._client.request(method, url, json=body, headers=headers) + except httpbakery.InteractionError as err: + raise CommandError("Authentication failure: {}".format(err)) + + self._save_credentials_if_changed() + return resp + + +def _storage_push(monitor, storage_base_url): + """Push bytes to the storage.""" + url = storage_base_url + '/unscanned-upload/' + headers = { + 'Content-Type': monitor.content_type, + 'Accept': 'application/json', + 'User-Agent': build_user_agent(), + } + retries = Retry(total=5, backoff_factor=2, status_forcelist=[500, 502, 503, 504]) + + with requests.Session() as session: + session.mount("https://", HTTPAdapter(max_retries=retries)) + + try: + response = session.post(url, headers=headers, data=monitor) + except RequestException as err: + raise CommandError("Network error when pushing file: {}({!r})".format( + err.__class__.__name__, str(err))) + + return response + + +class Client: + """Lightweight layer above _AuthHolder to present a more network oriented interface.""" + + def __init__(self, api_base_url, storage_base_url): + self._auth_client = _AuthHolder() + self.api_base_url = api_base_url.rstrip('/') + self.storage_base_url = storage_base_url.rstrip('/') + + def clear_credentials(self): + """Clear stored credentials.""" + self._auth_client.clear_credentials() + + def _parse_store_error(self, response): + """Get the proper error from the Store response.""" + default_msg = "Failure working with the Store: [{}] {!r}".format( + response.status_code, response.content) + try: + error_data = response.json() + except ValueError: + return default_msg + + try: + error_info = [(error['message'], error['code']) for error in error_data['error-list']] + except (KeyError, TypeError): + return default_msg + + if not error_info: + return default_msg + + messages = [] + for msg, code in error_info: + if code: + msg += " [code: {}]".format(code) + messages.append(msg) + return "Store failure! " + "; ".join(messages) + + def _hit(self, method, urlpath, body=None): + """Issue a request to the Store.""" + url = self.api_base_url + urlpath + logger.debug("Hitting the store: %s %s %s", method, url, body) + resp = self._auth_client.request(method, url, body) + if not resp.ok: + raise CommandError(self._parse_store_error(resp)) + + logger.debug("Store ok: %s", resp.status_code) + # XXX Facundo 2020-06-30: we need to wrap this .json() call, and raise UnknownError (after + # logging in debug the received raw response). This would catch weird "html" responses, + # for example, without making charmcraft to badly crash. Related: issue #73. + data = resp.json() + return data + + def get(self, urlpath): + """GET something from the Store.""" + return self._hit('GET', urlpath) + + def post(self, urlpath, body): + """POST a body (json-encoded) to the Store.""" + return self._hit('POST', urlpath, body) + + def push(self, filepath): + """Push the bytes from filepath to the Storage.""" + logger.debug("Starting to push %s", filepath) + + def _progress(monitor): + # XXX Facundo 2020-07-01: use a real progress bar + if monitor.bytes_read <= monitor.len: + progress = 100 * monitor.bytes_read / monitor.len + print("Uploading... {:.2f}%\r".format(progress), end='', flush=True) + + with filepath.open('rb') as fh: + encoder = MultipartEncoder( + fields={"binary": (filepath.name, fh, "application/octet-stream")}) + + # create a monitor (so that progress can be displayed) as call the real pusher + monitor = MultipartEncoderMonitor(encoder, _progress) + response = _storage_push(monitor, self.storage_base_url) + + if not response.ok: + raise CommandError("Failure while pushing file: [{}] {!r}".format( + response.status_code, response.content)) + + result = response.json() + if not result['successful']: + raise CommandError("Server error while pushing file: {}".format(result)) + + upload_id = result['upload_id'] + logger.debug("Uploading bytes ended, id %s", upload_id) + return upload_id diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/store.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/store.py new file mode 100644 index 00000000..05511e9f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/store/store.py @@ -0,0 +1,252 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""The Store API handling.""" + +import logging +import time +from collections import namedtuple + +from dateutil import parser + +from charmcraft.commands.store.client import Client + +logger = logging.getLogger('charmcraft.commands.store') + +# helpers to build responses from this layer +User = namedtuple('User', 'name username userid') +Charm = namedtuple('Charm', 'name private status') +Uploaded = namedtuple('Uploaded', 'ok status revision errors') +# XXX Facundo 2020-07-23: Need to do a massive rename to call `revno` to the "revision as +# the number" inside the "revision as the structure", this gets super confusing in the code with +# time, and now it's the moment to do it (also in Release below!) +Revision = namedtuple('Revision', 'revision version created_at status errors') +Error = namedtuple('Error', 'message code') +Release = namedtuple('Release', 'revision channel expires_at') +Channel = namedtuple('Channel', 'name fallback track risk branch') +Library = namedtuple('Library', 'api content content_hash lib_id lib_name charm_name patch') + +# those statuses after upload that flag that the review ended (and if it ended succesfully or not) +UPLOAD_ENDING_STATUSES = { + 'approved': True, + 'rejected': False, +} +POLL_DELAY = 1 + + +def _build_errors(item): + """Build a list of Errors from response item.""" + return [Error(message=e['message'], code=e['code']) for e in (item['errors'] or [])] + + +def _build_revision(item): + """Build a Revision from a response item.""" + rev = Revision( + revision=item['revision'], + version=item['version'], + created_at=parser.parse(item['created-at']), + status=item['status'], + errors=_build_errors(item), + ) + return rev + + +def _build_library(resp): + """Build a Library from a response.""" + lib = Library( + api=resp['api'], + content=resp.get('content'), # not always present + content_hash=resp['hash'], + lib_id=resp['library-id'], + lib_name=resp['library-name'], + charm_name=resp['charm-name'], + patch=resp['patch'], + ) + return lib + + +class Store: + """The main interface to the Store's API.""" + + def __init__(self, charmhub_config): + self._client = Client(charmhub_config.api_url, charmhub_config.storage_url) + + def login(self): + """Login into the store. + + The login happens on every request to the Store (if current credentials were not + enough), so to trigger a new login we... + + - remove local credentials + + - exercise the simplest command regarding developer identity + """ + self._client.clear_credentials() + self._client.get('/v1/whoami') + + def logout(self): + """Logout from the store. + + There's no action really in the Store to logout, we just remove local credentials. + """ + self._client.clear_credentials() + + def whoami(self): + """Return authenticated user details.""" + response = self._client.get('/v1/whoami') + # XXX Facundo 2020-06-30: Every time we consume data from the Store (after a succesful + # call) we need to wrap it with a context manager that will raise UnknownError (after + # logging in debug the received response). This would catch API changes, for example, + # without making charmcraft to badly crash. Related: issue #73. + result = User( + name=response['display-name'], + username=response['username'], + userid=response['id'], + ) + return result + + def register_name(self, name): + """Register the specified name for the authenticated user.""" + self._client.post('/v1/charm', {'name': name}) + + def list_registered_names(self): + """Return names registered by the authenticated user.""" + response = self._client.get('/v1/charm') + result = [] + for item in response['results']: + result.append(Charm(name=item['name'], private=item['private'], status=item['status'])) + return result + + def upload(self, name, filepath): + """Upload the content of filepath to the indicated charm.""" + upload_id = self._client.push(filepath) + + endpoint = '/v1/charm/{}/revisions'.format(name) + response = self._client.post(endpoint, {'upload-id': upload_id}) + status_url = response['status-url'] + logger.debug("Upload %s started, got status url %s", upload_id, status_url) + + while True: + response = self._client.get(status_url) + logger.debug("Status checked: %s", response) + + # as we're asking for a single upload_id, the response will always have only one item + (revision,) = response['revisions'] + status = revision['status'] + + if status in UPLOAD_ENDING_STATUSES: + return Uploaded( + ok=UPLOAD_ENDING_STATUSES[status], errors=_build_errors(revision), + status=status, revision=revision['revision']) + + # XXX Facundo 2020-06-30: Implement a slight backoff algorithm and fallout after + # N attempts (which should be big, as per snapcraft experience). Issue: #79. + time.sleep(POLL_DELAY) + + def list_revisions(self, name): + """Return charm revisions for the indicated charm.""" + response = self._client.get('/v1/charm/{}/revisions'.format(name)) + result = [_build_revision(item) for item in response['revisions']] + return result + + def release(self, name, revision, channels): + """Release one or more revisions for a package.""" + endpoint = '/v1/charm/{}/releases'.format(name) + items = [{'revision': revision, 'channel': channel} for channel in channels] + self._client.post(endpoint, items) + + def list_releases(self, name): + """List current releases for a package.""" + endpoint = '/v1/charm/{}/releases'.format(name) + response = self._client.get(endpoint) + + channel_map = [] + for item in response['channel-map']: + expires_at = item['expiration-date'] + if expires_at is not None: + # `datetime.datetime.fromisoformat` is available only since Py3.7 + expires_at = parser.parse(expires_at) + channel_map.append( + Release(revision=item['revision'], channel=item['channel'], expires_at=expires_at)) + + channels = [ + Channel( + name=item['name'], + fallback=item['fallback'], + track=item['track'], + risk=item['risk'], + branch=item['branch'], + ) for item in response['package']['channels']] + + revisions = [_build_revision(item) for item in response['revisions']] + + return channel_map, channels, revisions + + def create_library_id(self, charm_name, lib_name): + """Create a new library id.""" + endpoint = '/v1/charm/libraries/{}'.format(charm_name) + response = self._client.post(endpoint, {'library-name': lib_name}) + lib_id = response['library-id'] + return lib_id + + def create_library_revision(self, charm_name, lib_id, api, patch, content, content_hash): + """Create a new library revision.""" + endpoint = '/v1/charm/libraries/{}/{}'.format(charm_name, lib_id) + payload = { + 'api': api, + 'patch': patch, + 'content': content, + 'hash': content_hash, + } + response = self._client.post(endpoint, payload) + result = _build_library(response) + return result + + def get_library(self, charm_name, lib_id, api): + """Get the library tip by id for a given api version.""" + endpoint = '/v1/charm/libraries/{}/{}?api={}'.format(charm_name, lib_id, api) + response = self._client.get(endpoint) + result = _build_library(response) + return result + + def get_libraries_tips(self, libraries): + """Get the tip details for several libraries at once. + + Each requested library can be specified in different ways: using the library id + or the charm and library names (both will pinpoint the library), but in the later + case the library name is optional (so all libraries for that charm will be + returned). Also, for all those cases, an API version can be specified. + """ + endpoint = '/v1/charm/libraries/bulk' + payload = [] + for lib in libraries: + if 'lib_id' in lib: + item = { + 'library-id': lib['lib_id'], + } + else: + item = { + 'charm-name': lib['charm_name'], + } + if 'lib_name' in lib: + item['library-name'] = lib['lib_name'] + if 'api' in lib: + item['api'] = lib['api'] + payload.append(item) + response = self._client.post(endpoint, payload) + libraries = response['libraries'] + result = {(item['library-id'], item['api']): _build_library(item) for item in libraries} + return result diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/utils.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/utils.py new file mode 100644 index 00000000..3ba5da08 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/utils.py @@ -0,0 +1,64 @@ +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +import logging +import os +from stat import S_IXUSR, S_IXGRP, S_IXOTH, S_IRUSR, S_IRGRP, S_IROTH + +import yaml +from jinja2 import Environment, PackageLoader, StrictUndefined + +logger = logging.getLogger('charmcraft.commands') + + +# handy masks for execution and reading for everybody +S_IXALL = S_IXUSR | S_IXGRP | S_IXOTH +S_IRALL = S_IRUSR | S_IRGRP | S_IROTH + + +def make_executable(fh): + """make open file fh executable""" + fileno = fh.fileno() + mode = os.fstat(fileno).st_mode + mode_r = mode & S_IRALL + mode_x = mode_r >> 2 + mode = mode | mode_x + os.fchmod(fileno, mode) + + +def load_yaml(fpath): + """Return the content of a YAML file.""" + if not fpath.is_file(): + logger.debug("Couldn't find config file %s", fpath) + return + try: + with fpath.open('rb') as fh: + content = yaml.safe_load(fh) + except (yaml.error.YAMLError, OSError) as err: + logger.error("Failed to read/parse config file %s (got %r)", fpath, err) + return + return content + + +def get_templates_environment(templates_dir): + """Create and return a Jinja environment to deal with the templates.""" + env = Environment( + loader=PackageLoader('charmcraft', 'templates/{}'.format(templates_dir)), + autoescape=False, # no need to escape things here :-) + keep_trailing_newline=True, # they're not text files if they don't end in newline! + optimized=False, # optimization doesn't make sense for one-offs + undefined=StrictUndefined) # fail on undefined + return env diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/version.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/version.py new file mode 100644 index 00000000..cdc7cff0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/commands/version.py @@ -0,0 +1,56 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Infrastructure for the 'version' command.""" + +import logging + +from charmcraft import __version__ +from charmcraft.cmdbase import BaseCommand + +logger = logging.getLogger(__name__) + +_overview = """ +Show charmcraft version. + +The output has the following format: X.Y.Z[+N.gHASH[.dirty]] + +Where: + +- X, Y and Z are the major, minor and patch version numbers, + upgraded when a release is done + +- +N.gHASH is present if using charmcraft from the project (how many + commits after last release, and last commit's hash) + +- .dirty is present if the branch you're executing charmcraft from has + modifications + +Example: 0.3.1+40.g883455b.dirty +""" + + +class VersionCommand(BaseCommand): + """Show the charmcraft version.""" + + name = 'version' + help_msg = "Show charmcraft version" + overview = _overview + common = True + + def run(self, parsed_args): + """Run the command.""" + logger.info("%s", __version__) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/config.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/config.py new file mode 100644 index 00000000..b08b4336 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/config.py @@ -0,0 +1,202 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Central configuration management.""" + +import pathlib +from urllib.parse import urlparse + +import attr +import jsonschema + +from charmcraft.cmdbase import CommandError +from charmcraft.utils import load_yaml + +format_checker = jsonschema.FormatChecker() + +# translator between "json" and pythonic yaml names +TYPE_TRANSLATOR = { + 'object': 'dict', + 'array': 'list', +} + + +def get_field_reference(path): + """Get a field indicator from the received path.""" + if isinstance(path[-1], int): + field = '.'.join(list(path)[:-1]) + ref = "item {} in '{}' field".format(path[-1], field) + else: + field = '.'.join(path) + ref = "'{}' field".format(field) + return ref + + +def adapt_validation_error(error): + """Take a jsonschema.ValidationError and create a proper CommandError.""" + if error.validator == 'required': + msg = "Bad charmcraft.yaml content; missing fields: {}.".format( + ', '.join(error.validator_value)) + elif error.validator == 'type': + expected_type = TYPE_TRANSLATOR.get(error.validator_value, error.validator_value) + field_ref = get_field_reference(error.absolute_path) + msg = "Bad charmcraft.yaml content; the {} must be a {}: got '{}'.".format( + field_ref, expected_type, error.instance.__class__.__name__) + elif error.validator == 'enum': + field_ref = get_field_reference(error.absolute_path) + msg = "Bad charmcraft.yaml content; the {} must be one of: {}.".format( + field_ref, ', '.join(map(repr, error.validator_value))) + elif error.validator == 'format': + field_ref = get_field_reference(error.absolute_path) + msg = "Bad charmcraft.yaml content; the {} {}: got {!r}.".format( + field_ref, error.cause, error.instance) + else: + # safe fallback + msg = error.message + + raise CommandError(msg) + + +@format_checker.checks('url', raises=ValueError) +def check_url(value): + """Check that the URL has at least scheme and net location.""" + if isinstance(value, str): + url = urlparse(value) + if url.scheme and url.netloc: + return True + raise ValueError("must be a full URL (e.g. 'https://some.server.com')") + + +@format_checker.checks('relative_path', raises=ValueError) +def check_relative_paths(value): + """Check that the received paths are all valid relative ones.""" + if isinstance(value, str): + # check if it's an absolute path using POSIX's '/' (not os.path.sep, as the charm's + # config is independent of the platform where charmcraft is running) + if value and value[0] != '/': + return True + raise ValueError("must be a valid relative URL") + + +@attr.s(kw_only=True, frozen=True) +class CharmhubConfig: + """Configuration for all Charmhub related options.""" + + api_url = attr.ib(default='https://api.charmhub.io') + storage_url = attr.ib(default='https://storage.snapcraftcontent.com') + + @classmethod + def from_dict(cls, source): + """Build from a raw dict.""" + return cls(**source) + + +class BasicPrime(tuple): + """Hold the list of files to include, specified under parts/bundle/prime configs. + + This is a intermediate structure until we have the full Lifecycle in place. + """ + + @classmethod + def from_dict(cls, parts): + """Build from a dicts sequence.""" + prime = parts.get('bundle', {}).get('prime', []) + return cls(prime) + + +@attr.s(kw_only=True, frozen=True) +class Project: + """Configuration for all project-related options, used internally.""" + + dirpath = attr.ib(default=None) + config_provided = attr.ib(default=None) + + +@attr.s(kw_only=True, frozen=True) +class Config: + """Root of all the configuration.""" + + charmhub = attr.ib(default={}, converter=CharmhubConfig.from_dict) + parts = attr.ib(default={}, converter=BasicPrime.from_dict) + type = attr.ib(default=None) + + # this item is provided by the code itself, not the user, as convenience for the + # rest of the code + project = attr.ib(default=None) + + +CONFIG_SCHEMA = { + 'type': 'object', + 'properties': { + 'type': {'type': 'string', 'enum': ['charm', 'bundle']}, + 'charmhub': { + 'type': 'object', + 'properties': { + 'api_url': {'type': 'string', 'format': 'url'}, + 'storage_url': {'type': 'string', 'format': 'url'}, + }, + 'additionalProperties': False, + }, + 'parts': { + 'type': 'object', + 'properties': { + 'bundle': { + 'type': 'object', + 'properties': { + 'prime': { + 'type': 'array', + 'items': { + 'type': 'string', + 'format': 'relative_path', + }, + }, + }, + }, + }, + }, + }, + 'required': ['type'], + 'additionalProperties': False, +} + + +def load(dirpath): + """Load the config from charmcraft.yaml in the indicated directory.""" + if dirpath is None: + dirpath = pathlib.Path.cwd() + else: + dirpath = pathlib.Path(dirpath).expanduser().resolve() + + content = load_yaml(dirpath / 'charmcraft.yaml') + if content is None: + # configuration is mandatory only for some commands; when not provided, it will + # be initialized all with defaults (but marked as not provided for later verification) + content = {} + config_provided = False + + else: + # config provided! validate the loaded config is ok and mark as such + try: + jsonschema.validate( + instance=content, schema=CONFIG_SCHEMA, format_checker=format_checker) + except jsonschema.ValidationError as exc: + adapt_validation_error(exc) + config_provided = True + + # inject project's config + content['project'] = Project(dirpath=dirpath, config_provided=config_provided) + + return Config(**content) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/helptexts.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/helptexts.py new file mode 100644 index 00000000..16e037d5 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/helptexts.py @@ -0,0 +1,271 @@ +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Provide all help texts.""" + +import textwrap +from operator import attrgetter + +# max columns used in the terminal +TERMINAL_WIDTH = 72 + +# the summary of the whole program, already indented so it represents the real +# "columns spread", for easier human editing. +GENERAL_SUMMARY = """ + Charmcraft helps build, package and publish operators on Charmhub. + + Together with the Python Operator Framework, charmcraft simplifies + operator development and collaboration. + + See https://charmhub.io/publishing for more information. +""" +# XXX Facundo 2020-09-10: we should add an extra (separated) line to the summary with: +# See for additional documentation. +# Related issue: https://github.com/canonical/charmcraft/issues/161 + +# generic intro and outro texts +HEADER = """ +Usage: + charmcraft [help] +""" + +USAGE = """\ +Usage: charmcraft [options] command [args]... +Try '{fullcommand} -h' for help. + +Error: {error_message} +""" + + +def get_usage_message(fullcommand, error_message): + """Build a usage and error message. + + The fullcommand is the command used by the user (`charmcraft`, `charmcraft build`, etc), + and the error message is the specific problem in the given parameters. + """ + return USAGE.format(fullcommand=fullcommand, error_message=error_message) + + +def _build_item(title, text, title_space): + """Show an item in the help, generically a title and a text aligned. + + The title starts in column 4 with an extra ':'. The text starts in + 4 plus the title space; if too wide it's wrapped. + """ + # wrap the general text to the desired max width (discounting the space for the title, + # the first 4 spaces, the two spaces to separate title/text, and the ':' + not_title_space = 7 + text_space = TERMINAL_WIDTH - title_space - not_title_space + wrapped_lines = textwrap.wrap(text, text_space) + + # first line goes with the title at column 4 + first = " {:>{title_space}s}: {}".format(title, wrapped_lines[0], title_space=title_space) + result = [first] + + # the rest (if any) still aligned but without title + for line in wrapped_lines[1:]: + result.append(" " * (title_space + not_title_space) + line) + + return result + + +def get_full_help(command_groups, global_options): + """Produce the text for the default help. + + - command_groups: list of grouped commands, as it's defined in the main + module + + - global_options: options defined at charmcraft level (not in the commands), + with the (options, description) structure + + The help text has the following structure: + + - usage + - summary + - common commands listed and described shortly + - all commands grouped, just listed + - more help + """ + textblocks = [] + + # title + textblocks.append(HEADER) + + # summary + textblocks.append("Summary:" + GENERAL_SUMMARY) + + # column alignment is dictated by longest common commands names and groups names + max_title_len = 0 + + # collect common commands + common_commands = [] + for group, _, commands in command_groups: + max_title_len = max(len(group), max_title_len) + for cmd in commands: + if cmd.common: + common_commands.append(cmd) + max_title_len = max(len(cmd.name), max_title_len) + + for title, _ in global_options: + max_title_len = max(len(title), max_title_len) + + global_lines = ["Global options:"] + for title, text in global_options: + global_lines.extend(_build_item(title, text, max_title_len)) + textblocks.append("\n".join(global_lines)) + + common_lines = ["Starter commands:"] + for cmd in sorted(common_commands, key=attrgetter('name')): + common_lines.extend(_build_item(cmd.name, cmd.help_msg, max_title_len)) + textblocks.append("\n".join(common_lines)) + + grouped_lines = ["Commands can be classified as follows:"] + for group, _, commands in sorted(command_groups): + command_names = ", ".join(sorted(cmd.name for cmd in commands)) + grouped_lines.extend(_build_item(group, command_names, max_title_len)) + textblocks.append("\n".join(grouped_lines)) + + textblocks.append(textwrap.dedent(""" + For more information about a command, run 'charmcraft help '. + For a summary of all commands, run 'charmcraft help --all'. + """)) + + # join all stripped blocks, leaving ONE empty blank line between + text = '\n\n'.join(block.strip() for block in textblocks) + '\n' + return text + + +def get_detailed_help(command_groups, global_options): + """Produce the text for the detailed help. + + - command_groups: list of grouped commands, as it's defined in the main + module + + - global_options: options defined at charmcraft level (not in the commands), + with the (options, description) structure + + The help text has the following structure: + + - usage + - summary + - global options + - all commands shown with description, grouped + - more help + """ + textblocks = [] + + # title + textblocks.append(HEADER) + + # summary + textblocks.append("Summary:" + GENERAL_SUMMARY) + + # column alignment is dictated by longest common commands names and groups names + max_title_len = 0 + for _, _, commands in command_groups: + for cmd in commands: + max_title_len = max(len(cmd.name), max_title_len) + for title, _ in global_options: + max_title_len = max(len(title), max_title_len) + + global_lines = ["Global options:"] + for title, text in global_options: + global_lines.extend(_build_item(title, text, max_title_len)) + textblocks.append("\n".join(global_lines)) + + textblocks.append("Commands can be classified as follows:") + + for _, group_description, commands in command_groups: + group_lines = ["{}:".format(group_description)] + for cmd in commands: + group_lines.extend(_build_item(cmd.name, cmd.help_msg, max_title_len)) + textblocks.append("\n".join(group_lines)) + + textblocks.append(textwrap.dedent(""" + For more information about a specific command, run 'charmcraft help '. + """)) + + # join all stripped blocks, leaving ONE empty blank line between + text = '\n\n'.join(block.strip() for block in textblocks) + '\n' + return text + + +def get_command_help(command_groups, command, arguments): + """Produce the text for each command's help. + + - command_groups: list of grouped commands, as it's defined in the main + module + + - command: the instanciated command for which help is prepared + + - arguments: all command options and parameters, with the (name, description) structure + + The help text has the following structure: + + - usage + - summary + - options + - other related commands + - footer + """ + textblocks = [] + + # separate all arguments into the parameters and optional ones, just checking + # if first char is a dash + parameters = [] + options = [] + for name, title in arguments: + if name[0] == '-': + options.append((name, title)) + else: + parameters.append(name) + + textblocks.append(textwrap.dedent("""\ + Usage: + charmcraft {} [options] {} + """.format(command.name, " ".join("<{}>".format(parameter) for parameter in parameters)))) + + textblocks.append("Summary:{}".format(textwrap.indent(command.overview, ' '))) + + # column alignment is dictated by longest options title + max_title_len = max(len(title) for title, text in options) + + # command options + option_lines = ["Options:"] + for title, text in options: + option_lines.extend(_build_item(title, text, max_title_len)) + textblocks.append("\n".join(option_lines)) + + # recommend other commands of the same group + for group_name, _, command_classes in command_groups: + if group_name == command.group: + break + else: + raise RuntimeError("Internal inconsistency in commands groups") + other_command_names = [c.name for c in command_classes if not isinstance(command, c)] + if other_command_names: + see_also_block = ["See also:"] + see_also_block.extend((" " + name) for name in sorted(other_command_names)) + textblocks.append('\n'.join(see_also_block)) + + # footer + textblocks.append(""" + For a summary of all commands, run 'charmcraft help --all'. + """) + + # join all stripped blocks, leaving ONE empty blank line between + text = '\n\n'.join(block.strip() for block in textblocks) + '\n' + return text diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/jujuignore.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/jujuignore.py new file mode 100644 index 00000000..f0c103f7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/jujuignore.py @@ -0,0 +1,228 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Indicate which files are ignored by Juju.""" + +import logging +import re +import typing + +logger = logging.getLogger(__name__) + +KEEP = 'keep' +SKIP = 'skip' +FORCEKEEP = 'forcekeep' + +_unescapes = { + r'\!': '!', + r'\ ': ' ', + r'\#': '#', + +} + + +def _rstrip_unescaped(rule): + """Remove trailing whitespace that isn't escaped.""" + i = len(rule) - 1 + last = len(rule) + while i >= 0: + if rule[i] == '\n' or rule[i] == '\r': + last = i + elif rule[i] != ' ': + break + elif i == 0 or rule[i - 1] != '\\': + last = i + i -= 1 + rule = rule[:last] + return rule + + +def _unescape_rule(rule): + """Take out escape characters and trailing unescaped whitespace from the rule.""" + rule = rule.lstrip() + rule = _rstrip_unescaped(rule) + for old, new in _unescapes.items(): + rule = rule.replace(old, new) + return rule + + +def _rule_to_regex(rule): + """Turn a rule into a regex that we can use. + + This assumes that all the meta processing, like 'ends with /' and 'starts with !' have + already been checked. + """ + # Things we currently care about: + # * = matches only within a directory "[^/]*" + # ** = matches across directories ".*" + # ? = matches a single character + # [0-9] can match anything 0-9 + # This is taken from fnmatch.fnmatch, but that doesn't handle '**' and '*' also matches + # directories + + i, n = 0, len(rule) + res = '' + while i < n: + c = rule[i] + i += 1 + if c == '*': + if i < n and rule[i] == '*': + i += 1 + res += '.*' + else: + res += '[^/]*' + elif c == '?': + res += '[^/]' + elif c == '[': + j = i + if j < n and rule[j] == '!': + j += 1 + if j < n and rule[j] == ']': + j += 1 + while j < n and rule[j] != ']': + j += 1 + if j >= n: + res += '\\[' + else: + stuff = rule[i:j] + # Escape regex set operations (&~|). + stuff = re.sub(r'([&~|])', r'\\\1', stuff) + i = j + 1 + if stuff[0] == '!': + stuff = '^' + stuff[1:] + elif stuff[0] in ('['): + stuff = '\\' + stuff + res = '%s[%s]' % (res, stuff) + elif c == '/': + # Special case of '/**/' which can match a single '/' + if i < n and rule[i] == '*' and rule[i - 1:i + 3] == '/**/': + i += 3 + res = res + '.*/' + else: + res = res + '/' + else: + res += re.escape(c) + res += r'\Z' + return res + + +class _Matcher: + """Couple a regex with other metadata for how we should match a given pattern.""" + + def __init__(self, line_num: int, orig_rule: str, invert: bool, only_dirs: bool, + regex: typing.Pattern): + self.line_num = line_num + self.orig_rule = orig_rule + self.invert = invert + self.only_dirs = only_dirs + self.compiled = re.compile(regex, re.DOTALL) + + def match(self, path: str, is_dir: bool) -> str: + """Check if a path matches. + + Returns: + Can return one of KEEP, SKIP, FORCEKEEP + """ + if self.only_dirs and not is_dir: + return KEEP + if self.compiled.match(path): + if self.invert: + return FORCEKEEP + return SKIP + return KEEP + + +class JujuIgnore: + """Track a set of ignore patterns from a .jujuignore file.""" + + def __init__(self, patterns: typing.Iterable[str]): + self._matchers = [] + self._compile_from(patterns) + + def extend_patterns(self, patterns: typing.Iterable[str]) -> None: + """Add more patterns to the ignore list.""" + self._compile_from(patterns) + + def _compile_from(self, patterns: typing.Iterable[str]): + for line_num, rule in enumerate(patterns, 1): + orig_rule = rule + rule = rule.lstrip().rstrip('\r\n') + if not rule or rule.startswith('#'): + continue + invert = False + if rule.startswith('!'): + invert = True + rule = rule.lstrip('!') + rule = _unescape_rule(rule) + only_dirs = False + if rule.endswith('/'): + only_dirs = True + rule = rule.rstrip('/') + if not rule.startswith('/'): + # A rule that doesn't start with '/' means to match any + # subdirectory + rule = '**/' + rule + regex = _rule_to_regex(rule) + m = _Matcher( + line_num=line_num, + orig_rule=orig_rule, + invert=invert, + only_dirs=only_dirs, + regex=regex, + ) + self._matchers.append(m) + logger.debug('Translated .jujuignore %d "%s" => "%s"', line_num, orig_rule, regex) + + def match(self, path: str, is_dir: bool) -> bool: + """Check if the given path should be ignored. + + Args: + path: A local path (eg /foo/bar or foo/bar) from the root directory of the project. + is_dir: Indicate whether the given path is a directory (because of special handling + from ignore files when the path ends with a '/') + Return: + A boolean indicating whether the ignore rules matched the given path (thus the path + should be ignored). + """ + if not path.startswith('/'): + path = '/' + path + keep = True + for matcher in self._matchers: + matchRes = matcher.match(path, is_dir) + if matchRes == SKIP: + keep = False + elif matchRes == FORCEKEEP: + keep = True + break + return not keep + + +# default_juju_ignore is the initial set of ignores. +# juju itself always includes these before adding the contents of .jujuignore +# NOTE that this diverges from Juju ignore list, which also ignores "version", +# because we need the version file to populate the store +default_juju_ignore = ''' +.git +.svn +.hg +.bzr +.tox + +/build/ +/revision + +.jujuignore +'''.split('\n') diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/logsetup.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/logsetup.py new file mode 100644 index 00000000..de2cf2f1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/logsetup.py @@ -0,0 +1,121 @@ +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Set up logging.""" + +import logging +import os +import tempfile + +from charmcraft import __version__ + +FORMATTER_SIMPLE = "%(message)s" +FORMATTER_DETAILED = "%(asctime)s %(name)-30s %(levelname)-8s %(message)s" + +_logger = logging.getLogger('charmcraft') +_logger.setLevel(logging.DEBUG) + + +class _MessageHandler: + """Handle all the messages to the user. + + This class deals with several combination of the following dimensions: + + - the mode: quiet, normal or verbose + - the output: sometimes, some messages, to the terminal; always to the file + - the execution result: what happens if succeeded, raise a controlled error, or crashed + """ + + _modes = { + 'quiet': (logging.WARNING, FORMATTER_SIMPLE), + 'normal': (logging.INFO, FORMATTER_SIMPLE), + 'verbose': (logging.DEBUG, FORMATTER_DETAILED), + } + + def __init__(self): + self._stderr_handler = logging.StreamHandler() + _logger.addHandler(self._stderr_handler) + + # autoset modes constants for simpler interface + for k in self._modes: + setattr(self, k.upper(), k) + + def init(self, initial_mode): + """Initialize internal structures; this must be done before start logging.""" + self._set_filehandler() + self.set_mode(initial_mode) + + def set_mode(self, mode): + """Set logging in different modes.""" + self.mode = mode + level, format_string = self._modes[mode] + self._stderr_handler.setFormatter(logging.Formatter(format_string)) + self._stderr_handler.setLevel(level) + if mode == self.VERBOSE: + _logger.debug("Starting charmcraft version %s", __version__) + + def _set_filehandler(self): + """Set the file handler to log everything to the temp file.""" + _, self._log_filepath = tempfile.mkstemp(prefix='charmcraft-log-') + + file_handler = logging.FileHandler(self._log_filepath) + file_handler.setFormatter(logging.Formatter(FORMATTER_DETAILED)) + file_handler.setLevel(0) # log eeeeeverything + _logger.addHandler(file_handler) + + # a logger for only the file + self._file_logger = logging.getLogger('charmcraft.guard') + self._file_logger.propagate = False + self._file_logger.addHandler(file_handler) + self._file_logger.debug("Starting charmcraft version %s", __version__) + + def ended_ok(self): + """Cleanup after successful execution.""" + os.unlink(self._log_filepath) + + def ended_interrupt(self): + """Clean up on keyboard interrupt.""" + if self.mode == self.VERBOSE: + _logger.exception("Interrupted.") + else: + _logger.error("Interrupted.") + os.unlink(self._log_filepath) + + def ended_cmderror(self, err): + """Report the (expected) problem and (maybe) logfile location.""" + if err.argsparsing: + print(err) + else: + msg = "{} (full execution logs in {})".format(err, self._log_filepath) + _logger.error(msg) + + def ended_crash(self, err): + """Report the internal error and logfile location. + + Show just the error to the user, but send the whole traceback to the log file. + """ + msg = "charmcraft internal error! {}: {} (full execution logs in {})".format( + err.__class__.__name__, err, self._log_filepath) + if self.mode == self.VERBOSE: + # both to screen and file! + _logger.exception(msg) + else: + # the error to screen and file, plus the traceback to the file + _logger.error(msg) + self._file_logger.exception('') + + +message_handler = _MessageHandler() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/main.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/main.py new file mode 100644 index 00000000..28283672 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/main.py @@ -0,0 +1,319 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Main entry point module for all the tool functionality.""" + +import argparse +import logging +import sys +from collections import namedtuple + +from charmcraft import helptexts, config +from charmcraft.commands import version, build, store, init, pack +from charmcraft.cmdbase import CommandError, BaseCommand +from charmcraft.logsetup import message_handler + +logger = logging.getLogger(__name__) + + +class HelpCommand(BaseCommand): + """Special internal command to produce help and usage messages. + + It bends the rules for parameters (we have an optional parameter without dashes), the + idea is to lower the barrier as much as possible for the user getting help. + """ + + name = 'help' + help_msg = "Provide help on charmcraft usage" + overview = "Produce a general or a detailed charmcraft help, or a specific command one." + common = True + + def fill_parser(self, parser): + """Add own parameters to the general parser.""" + parser.add_argument( + '--all', action='store_true', help="Produce an extensive help of all commands") + parser.add_argument( + 'command_to_help', nargs='?', metavar='command', + help="Produce a detailed help of the specified command") + + def run(self, parsed_args, all_commands): + """Present different help messages to the user. + + Unlike other commands, this one receives an extra parameter with all commands, + to validate if the help requested is on a valid one, or even parse its data. + """ + retcode = 0 + if parsed_args.command_to_help is None or parsed_args.command_to_help == self.name: + # help on no command in particular, get general text + help_text = get_general_help(detailed=parsed_args.all) + elif parsed_args.command_to_help not in all_commands: + # asked help on a command that doesn't exist + msg = "no such command {!r}".format(parsed_args.command_to_help) + help_text = helptexts.get_usage_message('charmcraft', msg) + retcode = 1 + else: + cmd_class, group = all_commands[parsed_args.command_to_help] + cmd = cmd_class(group, None) + parser = CustomArgumentParser(prog=cmd.name, add_help=False) + cmd.fill_parser(parser) + help_text = get_command_help(parser, cmd) + raise CommandError(help_text, argsparsing=True, retcode=retcode) + + +# Collect commands in different groups, for easier human consumption. Note that this is not +# declared in each command because it's much easier to do this separation/grouping in one +# central place and not distributed in several classes/files. Also note that order here is +# important when lisgint commands and showing help. +COMMAND_GROUPS = [ + ('basic', "Basic", [ + HelpCommand, + build.BuildCommand, + pack.PackCommand, + init.InitCommand, + version.VersionCommand, + ]), + ('store', "Charmhub", [ + # auth + store.LoginCommand, store.LogoutCommand, store.WhoamiCommand, + # name handling + store.RegisterNameCommand, store.ListNamesCommand, + # pushing files and checking revisions + store.UploadCommand, store.ListRevisionsCommand, + # release process, and show status + store.ReleaseCommand, store.StatusCommand, + # libraries support + store.CreateLibCommand, store.PublishLibCommand, store.ListLibCommand, + store.FetchLibCommand, + ]), +] + + +# global options: the name used internally, its type, short and long parameters, and help text +_Global = namedtuple('Global', 'name type short_option long_option help_message') +GLOBAL_ARGS = [ + _Global('help', 'flag', '-h', '--help', "Show this help message and exit"), + _Global('verbose', 'flag', '-v', '--verbose', "Show debug information and be more verbose"), + _Global('quiet', 'flag', '-q', '--quiet', "Only show warnings and errors, not progress"), + _Global( + 'project_dir', 'option', '-p', '--project-dir', + "Specify the project's directory (defaults to current)"), +] + + +class CustomArgumentParser(argparse.ArgumentParser): + """ArgumentParser with custom error manager..""" + + def error(self, message): + """Show the usage, the error message, and no more.""" + fullcommand = "charmcraft " + self.prog + full_msg = helptexts.get_usage_message(fullcommand, message) + raise CommandError(full_msg, argsparsing=True) + + +def _get_global_options(): + """Return the global flags ready to present as options in the help messages.""" + options = [] + for arg in GLOBAL_ARGS: + options.append(("{}, {}".format(arg.short_option, arg.long_option), arg.help_message)) + return options + + +def get_command_help(parser, command): + """Produce the complete help message for a command.""" + options = _get_global_options() + + for action in parser._actions: + # store the different options if present, otherwise it's just the dest + if action.option_strings: + options.append((', '.join(action.option_strings), action.help)) + else: + options.append((action.dest, action.help)) + + help_text = helptexts.get_command_help(COMMAND_GROUPS, command, options) + return help_text + + +def get_general_help(detailed=False): + """Produce the "general charmcraft" help.""" + options = _get_global_options() + if detailed: + help_text = helptexts.get_detailed_help(COMMAND_GROUPS, options) + else: + help_text = helptexts.get_full_help(COMMAND_GROUPS, options) + return help_text + + +class Dispatcher: + """Set up infrastructure and let the needed command run. + + ♪♫"Leeeeeet, the command ruuun"♪♫ https://www.youtube.com/watch?v=cv-0mmVnxPA + """ + + def __init__(self, sysargs, commands_groups): + self.commands = self._get_commands_info(commands_groups) + command_name, cmd_args, charmcraft_config = self._pre_parse_args(sysargs) + self.command, self.parsed_args = self._load_command( + command_name, cmd_args, charmcraft_config) + + def _get_commands_info(self, commands_groups): + """Process the commands groups structure for easier programmable access.""" + commands = {} + for _cmd_group, _, _cmd_classes in commands_groups: + for _cmd_class in _cmd_classes: + if _cmd_class.name in commands: + _stored_class, _ = commands[_cmd_class.name] + raise RuntimeError( + "Multiple commands with same name: {} and {}".format( + _cmd_class.__name__, _stored_class.__name__)) + commands[_cmd_class.name] = (_cmd_class, _cmd_group) + return commands + + def _load_command(self, command_name, cmd_args, charmcraft_config): + """Load a command.""" + cmd_class, group = self.commands[command_name] + cmd = cmd_class(group, charmcraft_config) + + # load and parse the command specific options/params + parser = CustomArgumentParser(prog=cmd.name) + cmd.fill_parser(parser) + parsed_args = parser.parse_args(cmd_args) + logger.debug("Command parsed sysargs: %s", parsed_args) + + return cmd, parsed_args + + def _pre_parse_args(self, sysargs): + """Pre-parse sys args. + + Several steps: + + - extract the global options and detects the possible command and its args + + - validate global options and apply them + + - validate that command is correct (NOT loading and parsing its arguments) + """ + # get all arguments (default to what's specified) and those per options, to filter sysargs + global_args = {} + arg_per_option = {} + options_with_equal = [] + for arg in GLOBAL_ARGS: + arg_per_option[arg.short_option] = arg + arg_per_option[arg.long_option] = arg + if arg.type == 'flag': + default = False + elif arg.type == 'option': + default = None + options_with_equal.append(arg.long_option + '=') + else: + raise ValueError("Bad GLOBAL_ARGS structure.") + global_args[arg.name] = default + + filtered_sysargs = [] + sysargs = iter(sysargs) + options_with_equal = tuple(options_with_equal) + for sysarg in sysargs: + if sysarg in arg_per_option: + arg = arg_per_option[sysarg] + if arg.type == 'flag': + value = True + else: + try: + value = next(sysargs) + except StopIteration: + raise CommandError("The 'project-dir' option expects one argument.") + global_args[arg.name] = value + elif sysarg.startswith(options_with_equal): + option, value = sysarg.split('=', 1) + if not value: + raise CommandError("The 'project-dir' option expects one argument.") + arg = arg_per_option[option] + global_args[arg.name] = value + else: + filtered_sysargs.append(sysarg) + + # control and use quiet/verbose options + if global_args['quiet'] and global_args['verbose']: + raise CommandError("The 'verbose' and 'quiet' options are mutually exclusive.") + if global_args['quiet']: + message_handler.set_mode(message_handler.QUIET) + elif global_args['verbose']: + message_handler.set_mode(message_handler.VERBOSE) + logger.debug("Raw pre-parsed sysargs: args=%s filtered=%s", global_args, filtered_sysargs) + + # if help requested, transform the parameters to make that explicit + if global_args['help']: + command = HelpCommand.name + cmd_args = filtered_sysargs + elif filtered_sysargs: + command = filtered_sysargs[0] + cmd_args = filtered_sysargs[1:] + if command not in self.commands: + msg = "no such command {!r}".format(command) + help_text = helptexts.get_usage_message('charmcraft', msg) + raise CommandError(help_text, argsparsing=True) + else: + # no command! + help_text = get_general_help() + raise CommandError(help_text, argsparsing=True) + + # load the system's config + charmcraft_config = config.load(global_args['project_dir']) + + logger.debug("General parsed sysargs: command=%r args=%s", command, cmd_args) + return command, cmd_args, charmcraft_config + + def run(self): + """Really run the command.""" + if isinstance(self.command, HelpCommand): + self.command.run(self.parsed_args, self.commands) + else: + if self.command.needs_config and not self.command.config.project.config_provided: + raise CommandError( + "The specified command needs a valid 'charmcraft.yaml' configuration file (in " + "the current directory or where specified with --project-dir option); see " + "the reference: https://discourse.charmhub.io/t/charmcraft-configuration/4138") + self.command.run(self.parsed_args) + + +def main(argv=None): + """Provide the main entry point.""" + message_handler.init(message_handler.NORMAL) + + if argv is None: + argv = sys.argv + + # process + try: + dispatcher = Dispatcher(argv[1:], COMMAND_GROUPS) + dispatcher.run() + except CommandError as err: + message_handler.ended_cmderror(err) + retcode = err.retcode + except KeyboardInterrupt: + message_handler.ended_interrupt() + retcode = 1 + except Exception as err: + message_handler.ended_crash(err) + retcode = 1 + else: + message_handler.ended_ok() + retcode = 0 + + return retcode + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/charmlibs/new_library.py.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/charmlibs/new_library.py.j2 new file mode 100644 index 00000000..4a7da958 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/charmlibs/new_library.py.j2 @@ -0,0 +1,29 @@ +"""TODO: Add a proper docstring here. + +This is a placeholder docstring for this charm library. Docstrings are +presented on Charmhub and updated whenever you push a new version of the +library. + +See `charmcraft push-lib` and `charmcraft fetch-lib` for details of how to +share and consume charm libraries. They serve to enhance collaboration +between charmers. Use a charmer's libraries for classes that handle +integration with their charm. + +Bear in mind that new revisions of the different major API versions (v0, v1, +v2 etc) are maintained independently. You can continue to update v0 and v1 +after you have pushed v3. + +Markdown is supported, following the CommonMark specification. +""" + +# The unique Charmhub library identifier, never change it +LIBID = "{{ lib_id }}" + +# Increment this major API version when introducing breaking changes +LIBAPI = 0 + +# Increment this PATCH version before using `charmcraft push-lib` or reset +# to 0 if you are raising the major API version +LIBPATCH = 1 + +# TODO: add your code here! Happy coding! diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.flake8.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.flake8.j2 new file mode 100644 index 00000000..8ef84fcd --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.flake8.j2 @@ -0,0 +1,9 @@ +[flake8] +max-line-length = 99 +select: E,W,F,C,N +exclude: + venv + .git + build + dist + *.egg_info diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.jujuignore.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.jujuignore.j2 new file mode 100644 index 00000000..6ccd559e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/.jujuignore.j2 @@ -0,0 +1,3 @@ +/venv +*.py[cod] +*.charm diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/LICENSE.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/LICENSE.j2 new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/LICENSE.j2 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/README.md.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/README.md.j2 new file mode 100644 index 00000000..a1a54301 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/README.md.j2 @@ -0,0 +1,25 @@ +# {{ name }} + +## Description + +TODO: Describe your charm in a few paragraphs of Markdown + +## Usage + +TODO: Provide high-level usage, such as required config or relations + + +## Developing + +Create and activate a virtualenv with the development requirements: + + virtualenv -p python3 venv + source venv/bin/activate + pip install -r requirements-dev.txt + +## Testing + +The Python operator framework includes a very nice harness for testing +operator behaviour without full deployment. Just `run_tests`: + + ./run_tests diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/actions.yaml.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/actions.yaml.j2 new file mode 100644 index 00000000..98b14cea --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/actions.yaml.j2 @@ -0,0 +1,14 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. +# +# This is only an example, and you should edit to suit your needs. +# If you don't need actions, you can remove the file entirely. +# It ties in to the example _on_fortune_action handler in src/charm.py +# +# fortune: +# description: Returns a pithy phrase. +# params: +# fail: +# description: "Fail with this message" +# type: string +# default: "" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/config.yaml.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/config.yaml.j2 new file mode 100644 index 00000000..5f47d30f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/config.yaml.j2 @@ -0,0 +1,11 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. +# +# This is only an example, and you should edit to suit your needs. +# If you don't need config, you can remove the file entirely. +# +# options: +# thing: +# default: 🎁 +# description: A thing used by the charm. +# type: string diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/metadata.yaml.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/metadata.yaml.j2 new file mode 100644 index 00000000..c26951c2 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/metadata.yaml.j2 @@ -0,0 +1,9 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. +name: {{ name }} +description: | + TODO: fill out the charm's description +summary: | + TODO: fill out the charm's summary +series: {{ series }} + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements-dev.txt.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements-dev.txt.j2 new file mode 100644 index 00000000..4f2a3f5b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements-dev.txt.j2 @@ -0,0 +1,3 @@ +-r requirements.txt +coverage +flake8 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements.txt.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements.txt.j2 new file mode 100644 index 00000000..2d81d3bb --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/requirements.txt.j2 @@ -0,0 +1 @@ +ops diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/run_tests.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/run_tests.j2 new file mode 100755 index 00000000..da70cb36 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/run_tests.j2 @@ -0,0 +1,17 @@ +#!/bin/sh -e +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +if [ -z "$VIRTUAL_ENV" -a -d venv/ ]; then + . venv/bin/activate +fi + +if [ -z "$PYTHONPATH" ]; then + export PYTHONPATH=src +else + export PYTHONPATH="src:$PYTHONPATH" +fi + +flake8 +coverage run --source=src -m unittest -v "$@" +coverage report -m diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/src/charm.py.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/src/charm.py.j2 new file mode 100644 index 00000000..d7ea6197 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/src/charm.py.j2 @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +"""Charm the service.""" + +import logging + +from ops.charm import CharmBase +from ops.main import main +from ops.framework import StoredState + +logger = logging.getLogger(__name__) + + +class {{ class_name }}(CharmBase): + """Charm the service.""" + + _stored = StoredState() + + def __init__(self, *args): + super().__init__(*args) + self.framework.observe(self.on.config_changed, self._on_config_changed) + self.framework.observe(self.on.fortune_action, self._on_fortune_action) + self._stored.set_default(things=[]) + + def _on_config_changed(self, _): + # Note: you need to uncomment the example in the config.yaml file for this to work (ensure + # to not just leave the example, but adapt to your configuration needs) + current = self.config["thing"] + if current not in self._stored.things: + logger.debug("found a new thing: %r", current) + self._stored.things.append(current) + + def _on_fortune_action(self, event): + # Note: you need to uncomment the example in the actions.yaml file for this to work (ensure + # to not just leave the example, but adapt to your needs for actions commands) + fail = event.params["fail"] + if fail: + event.fail(fail) + else: + event.set_results({"fortune": "A bug in the code is worth two in the documentation."}) + + +if __name__ == "__main__": + main({{ class_name }}) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/__init__.py.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/__init__.py.j2 new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/test_charm.py.j2 b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/test_charm.py.j2 new file mode 100644 index 00000000..e0348ff3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/templates/init/tests/test_charm.py.j2 @@ -0,0 +1,35 @@ +# Copyright {{ year }} {{ author }} +# See LICENSE file for licensing details. + +import unittest +from unittest.mock import Mock + +from ops.testing import Harness +from charm import {{ class_name }} + + +class TestCharm(unittest.TestCase): + def test_config_changed(self): + harness = Harness({{ class_name }}) + self.addCleanup(harness.cleanup) + harness.begin() + self.assertEqual(list(harness.charm._stored.things), []) + harness.update_config({"thing": "foo"}) + self.assertEqual(list(harness.charm._stored.things), ["foo"]) + + def test_action(self): + harness = Harness({{ class_name }}) + harness.begin() + # the harness doesn't (yet!) help much with actions themselves + action_event = Mock(params={"fail": ""}) + harness.charm._on_fortune_action(action_event) + + self.assertTrue(action_event.set_results.called) + + def test_action_fail(self): + harness = Harness({{ class_name }}) + harness.begin() + action_event = Mock(params={"fail": "fail this"}) + harness.charm._on_fortune_action(action_event) + + self.assertEqual(action_event.fail.call_args, [("fail this",)]) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/utils.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/utils.py new file mode 100644 index 00000000..8dc03a5b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/utils.py @@ -0,0 +1,66 @@ +# Copyright 2020-2021 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# For further info, check https://github.com/canonical/charmcraft + +"""Collection of utilities for charmcraft.""" + +import logging +import os +from stat import S_IXUSR, S_IXGRP, S_IXOTH, S_IRUSR, S_IRGRP, S_IROTH + +import yaml +from jinja2 import Environment, PackageLoader, StrictUndefined + +logger = logging.getLogger('charmcraft.commands') + + +# handy masks for execution and reading for everybody +S_IXALL = S_IXUSR | S_IXGRP | S_IXOTH +S_IRALL = S_IRUSR | S_IRGRP | S_IROTH + + +def make_executable(fh): + """Make open file fh executable.""" + fileno = fh.fileno() + mode = os.fstat(fileno).st_mode + mode_r = mode & S_IRALL + mode_x = mode_r >> 2 + mode = mode | mode_x + os.fchmod(fileno, mode) + + +def load_yaml(fpath): + """Return the content of a YAML file.""" + if not fpath.is_file(): + logger.debug("Couldn't find config file %s", fpath) + return + try: + with fpath.open('rb') as fh: + content = yaml.safe_load(fh) + except (yaml.error.YAMLError, OSError) as err: + logger.error("Failed to read/parse config file %s: %r", fpath, err) + return + return content + + +def get_templates_environment(templates_dir): + """Create and return a Jinja environment to deal with the templates.""" + env = Environment( + loader=PackageLoader('charmcraft', 'templates/{}'.format(templates_dir)), + autoescape=False, # no need to escape things here :-) + keep_trailing_newline=True, # they're not text files if they don't end in newline! + optimized=False, # optimization doesn't make sense for one-offs + undefined=StrictUndefined) # fail on undefined + return env diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/version.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/version.py new file mode 100644 index 00000000..eac7dc5e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/charmcraft/version.py @@ -0,0 +1,4 @@ + +# this is a generated file + +version = '0.8.1' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/METADATA new file mode 100644 index 00000000..c455cb51 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/METADATA @@ -0,0 +1,411 @@ +Metadata-Version: 2.1 +Name: colorama +Version: 0.4.3 +Summary: Cross-platform colored terminal text. +Home-page: https://github.com/tartley/colorama +Author: Jonathan Hartley +Author-email: tartley@tartley.com +Maintainer: Arnon Yaari +License: BSD +Keywords: color colour terminal text ansi windows crossplatform xplatform +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Terminals +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.* + +.. image:: https://img.shields.io/pypi/v/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Latest Version + +.. image:: https://img.shields.io/pypi/pyversions/colorama.svg + :target: https://pypi.org/project/colorama/ + :alt: Supported Python versions + +.. image:: https://travis-ci.org/tartley/colorama.svg?branch=master + :target: https://travis-ci.org/tartley/colorama + :alt: Build Status + +Download and docs: + https://pypi.org/project/colorama/ +Source code & Development: + https://github.com/tartley/colorama +Colorama for Enterprise: + https://github.com/tartley/colorama/blob/master/ENTERPRISE.md + +Description +=========== + +Makes ANSI escape character sequences (for producing colored terminal text and +cursor positioning) work under MS Windows. + +ANSI escape character sequences have long been used to produce colored terminal +text and cursor positioning on Unix and Macs. Colorama makes this work on +Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which +would appear as gobbledygook in the output), and converting them into the +appropriate win32 calls to modify the state of the terminal. On other platforms, +Colorama does nothing. + +Colorama also provides some shortcuts to help generate ANSI sequences +but works fine in conjunction with any other ANSI sequence generation library, +such as the venerable Termcolor (https://pypi.org/project/termcolor/) +or the fabulous Blessings (https://pypi.org/project/blessings/). + +This has the upshot of providing a simple cross-platform API for printing +colored terminal text from Python, and has the happy side-effect that existing +applications or libraries which use ANSI sequences to produce colored output on +Linux or Macs can now also work on Windows, simply by calling +``colorama.init()``. + +An alternative approach is to install ``ansi.sys`` on Windows machines, which +provides the same behaviour for all applications running in terminals. Colorama +is intended for situations where that isn't easy (e.g., maybe your app doesn't +have an installer.) + +Demo scripts in the source code repository print some colored text using +ANSI sequences. Compare their output under Gnome-terminal's built in ANSI +handling, versus on Windows Command-Prompt using Colorama: + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png + :width: 661 + :height: 357 + :alt: ANSI sequences on Ubuntu under gnome-terminal. + +.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png + :width: 668 + :height: 325 + :alt: Same ANSI sequences on Windows, using Colorama. + +These screengrabs show that, on Windows, Colorama does not support ANSI 'dim +text'; it looks the same as 'normal text'. + + +License +======= + +Copyright Jonathan Hartley & Arnon Yaari, 2013. BSD 3-Clause license; see LICENSE file. + + +Dependencies +============ + +None, other than Python. Tested on Python 2.7, 3.5, 3.6, 3.7 and 3.8. + +Usage +===== + +Initialisation +-------------- + +Applications should initialise Colorama using: + +.. code-block:: python + + from colorama import init + init() + +On Windows, calling ``init()`` will filter ANSI escape sequences out of any +text sent to ``stdout`` or ``stderr``, and replace them with equivalent Win32 +calls. + +On other platforms, calling ``init()`` has no effect (unless you request other +optional functionality; see "Init Keyword Args", below). By design, this permits +applications to call ``init()`` unconditionally on all platforms, after which +ANSI output should just work. + +To stop using colorama before your program exits, simply call ``deinit()``. +This will restore ``stdout`` and ``stderr`` to their original values, so that +Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is +cheaper to calling ``init()`` again (but does the same thing). + + +Colored Output +-------------- + +Cross-platform printing of colored text can then be done using Colorama's +constant shorthand for ANSI escape sequences: + +.. code-block:: python + + from colorama import Fore, Back, Style + print(Fore.RED + 'some red text') + print(Back.GREEN + 'and with a green background') + print(Style.DIM + 'and in dim text') + print(Style.RESET_ALL) + print('back to normal now') + +...or simply by manually printing ANSI sequences from your own code: + +.. code-block:: python + + print('\033[31m' + 'some red text') + print('\033[39m') # and reset to default color + +...or, Colorama can be used happily in conjunction with existing ANSI libraries +such as Termcolor: + +.. code-block:: python + + from colorama import init + from termcolor import colored + + # use Colorama to make Termcolor work on Windows too + init() + + # then use Termcolor for all colored text output + print(colored('Hello, World!', 'green', 'on_red')) + +Available formatting constants are:: + + Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. + Style: DIM, NORMAL, BRIGHT, RESET_ALL + +``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will +perform this reset automatically on program exit. + + +Cursor Positioning +------------------ + +ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for +an example of how to generate them. + + +Init Keyword Args +----------------- + +``init()`` accepts some ``**kwargs`` to override default behaviour. + +init(autoreset=False): + If you find yourself repeatedly sending reset sequences to turn off color + changes at the end of every print, then ``init(autoreset=True)`` will + automate that: + + .. code-block:: python + + from colorama import init + init(autoreset=True) + print(Fore.RED + 'some red text') + print('automatically back to default color again') + +init(strip=None): + Pass ``True`` or ``False`` to override whether ansi codes should be + stripped from the output. The default behaviour is to strip if on Windows + or if output is redirected (not a tty). + +init(convert=None): + Pass ``True`` or ``False`` to override whether to convert ANSI codes in the + output into win32 calls. The default behaviour is to convert if on Windows + and output is to a tty (terminal). + +init(wrap=True): + On Windows, colorama works by replacing ``sys.stdout`` and ``sys.stderr`` + with proxy objects, which override the ``.write()`` method to do their work. + If this wrapping causes you problems, then this can be disabled by passing + ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or + ``strip`` or ``convert`` are True. + + When wrapping is disabled, colored printing on non-Windows platforms will + continue to work as normal. To do cross-platform colored output, you can + use Colorama's ``AnsiToWin32`` proxy directly: + + .. code-block:: python + + import sys + from colorama import init, AnsiToWin32 + init(wrap=False) + stream = AnsiToWin32(sys.stderr).stream + + # Python 2 + print >>stream, Fore.BLUE + 'blue text on stderr' + + # Python 3 + print(Fore.BLUE + 'blue text on stderr', file=stream) + + +Installation +======================= +colorama is currently installable from PyPI: + + pip install colorama + +colorama also can be installed by the conda package manager: + + conda install -c anaconda colorama + + +Status & Known Problems +======================= + +I've personally only tested it on Windows XP (CMD, Console2), Ubuntu +(gnome-terminal, xterm), and OS X. + +Some presumably valid ANSI sequences aren't recognised (see details below), +but to my knowledge nobody has yet complained about this. Puzzling. + +See outstanding issues and wishlist: +https://github.com/tartley/colorama/issues + +If anything doesn't work for you, or doesn't do what you expected or hoped for, +I'd love to hear about it on that issues list, would be delighted by patches, +and would be happy to grant commit access to anyone who submits a working patch +or two. + + +Recognised ANSI Sequences +========================= + +ANSI sequences generally take the form: + + ESC [ ; ... + +Where ```` is an integer, and ```` is a single letter. Zero or +more params are passed to a ````. If no params are passed, it is +generally synonymous with passing a single zero. No spaces exist in the +sequence; they have been inserted here simply to read more easily. + +The only ANSI sequences that colorama converts into win32 calls are:: + + ESC [ 0 m # reset all (colors and brightness) + ESC [ 1 m # bright + ESC [ 2 m # dim (looks same as normal brightness) + ESC [ 22 m # normal brightness + + # FOREGROUND: + ESC [ 30 m # black + ESC [ 31 m # red + ESC [ 32 m # green + ESC [ 33 m # yellow + ESC [ 34 m # blue + ESC [ 35 m # magenta + ESC [ 36 m # cyan + ESC [ 37 m # white + ESC [ 39 m # reset + + # BACKGROUND + ESC [ 40 m # black + ESC [ 41 m # red + ESC [ 42 m # green + ESC [ 43 m # yellow + ESC [ 44 m # blue + ESC [ 45 m # magenta + ESC [ 46 m # cyan + ESC [ 47 m # white + ESC [ 49 m # reset + + # cursor positioning + ESC [ y;x H # position cursor at x across, y down + ESC [ y;x f # position cursor at x across, y down + ESC [ n A # move cursor n lines up + ESC [ n B # move cursor n lines down + ESC [ n C # move cursor n characters forward + ESC [ n D # move cursor n characters backward + + # clear the screen + ESC [ mode J # clear the screen + + # clear the line + ESC [ mode K # clear the line + +Multiple numeric params to the ``'m'`` command can be combined into a single +sequence:: + + ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background + +All other ANSI sequences of the form ``ESC [ ; ... `` +are silently stripped from the output on Windows. + +Any other form of ANSI sequence, such as single-character codes or alternative +initial characters, are not recognised or stripped. It would be cool to add +them though. Let me know if it would be useful for you, via the Issues on +GitHub. + + +Development +=========== + +Help and fixes welcome! + +Running tests requires: + +- Michael Foord's ``mock`` module to be installed. +- Tests are written using 2010-era updates to ``unittest`` + +To run tests:: + + python -m unittest discover -p *_test.py + +This, like a few other handy commands, is captured in a ``Makefile``. + +If you use nose to run the tests, you must pass the ``-s`` flag; otherwise, +``nosetests`` applies its own proxy to ``stdout``, which confuses the unit +tests. + + +Professional support +==================== + +.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png + :alt: Tidelift + :target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + +.. list-table:: + :widths: 10 100 + + * - |tideliftlogo| + - Professional support for colorama is available as part of the + `Tidelift Subscription`_. + Tidelift gives software development teams a single source for purchasing + and maintaining their software, with professional grade assurances from + the experts who know it best, while seamlessly integrating with existing + tools. + +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme + + +Thanks +====== +* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. +* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, + providing a solution to issue #7's setuptools/distutils debate, + and other fixes. +* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. +* Matthew McCormick for politely pointing out a longstanding crash on non-Win. +* Ben Hoyt, for a magnificent fix under 64-bit Windows. +* Jesse at Empty Square for submitting a fix for examples in the README. +* User 'jamessp', an observant documentation fix for cursor positioning. +* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 + fix. +* Julien Stuyck, for wisely suggesting Python3 compatible updates to README. +* Daniel Griffith for multiple fabulous patches. +* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty + output. +* Roger Binns, for many suggestions, valuable feedback, & bug reports. +* Tim Golden for thought and much appreciated feedback on the initial idea. +* User 'Zearin' for updates to the README file. +* John Szakmeister for adding support for light colors +* Charles Merriam for adding documentation to demos +* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes +* Florian Bruhin for a fix when stdout or stderr are None +* Thomas Weininger for fixing ValueError on Windows +* Remi Rampin for better Github integration and fixes to the README file +* Simeon Visser for closing a file handle using 'with' and updating classifiers + to include Python 3.3 and 3.4 +* Andy Neff for fixing RESET of LIGHT_EX colors. +* Jonathan Hartley for the initial idea and implementation. + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/RECORD new file mode 100644 index 00000000..f9bdc1a7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/RECORD @@ -0,0 +1,22 @@ +colorama/__init__.py,sha256=DqjXH9URVP3IJwmMt7peYw50ns1RNAymIB9-XdPEFV8,239 +colorama/ansi.py,sha256=Fi0un-QLqRm-v7o_nKiOqyC8PapBJK7DLV_q9LKtTO0,2524 +colorama/ansitowin32.py,sha256=u8QaqdqS_xYSfNkPM1eRJLHz6JMWPodaJaP0mxgHCDc,10462 +colorama/initialise.py,sha256=PprovDNxMTrvoNHFcL2NZjpH2XzDc8BLxLxiErfUl4k,1915 +colorama/win32.py,sha256=bJ8Il9jwaBN5BJ8bmN6FoYZ1QYuMKv2j8fGrXh7TJjw,5404 +colorama/winterm.py,sha256=2y_2b7Zsv34feAsP67mLOVc-Bgq51mdYGo571VprlrM,6438 +colorama-0.4.3.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +colorama-0.4.3.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +colorama-0.4.3.dist-info/METADATA,sha256=-ovqULHfBHs9pV2e_Ua8-w2VSVLno-6x36SXSTsWvSc,14432 +colorama-0.4.3.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +colorama-0.4.3.dist-info/top_level.txt,sha256=_Kx6-Cni2BT1PEATPhrSRxo0d7kSgfBbHf5o7IF1ABw,9 +colorama-0.4.3.dist-info/RECORD,, +colorama/__pycache__,, +colorama/winterm.cpython-38.pyc,, +colorama-0.4.3.dist-info/__pycache__,, +colorama/ansi.cpython-38.pyc,, +colorama/ansitowin32.cpython-38.pyc,, +colorama/win32.cpython-38.pyc,, +colorama-0.4.3.virtualenv,, +colorama/initialise.cpython-38.pyc,, +colorama/__init__.cpython-38.pyc,, +colorama-0.4.3.dist-info/INSTALLER,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/top_level.txt new file mode 100644 index 00000000..3fcfb51b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.dist-info/top_level.txt @@ -0,0 +1 @@ +colorama diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama-0.4.3.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/__init__.py new file mode 100644 index 00000000..34c263cc --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/__init__.py @@ -0,0 +1,6 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.4.3' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansi.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansi.py new file mode 100644 index 00000000..78776588 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\007' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansitowin32.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansitowin32.py new file mode 100644 index 00000000..359c92be --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/ansitowin32.py @@ -0,0 +1,257 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def __enter__(self, *args, **kwargs): + # special method lookup bypasses __getattr__/__getattribute__, see + # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit + # thus, contextlib magic methods are not proxied via __getattr__ + return self.__wrapped.__enter__(*args, **kwargs) + + def __exit__(self, *args, **kwargs): + return self.__wrapped.__exit__(*args, **kwargs) + + def write(self, text): + self.__convertor.write(text) + + def isatty(self): + stream = self.__wrapped + if 'PYCHARM_HOSTED' in os.environ: + if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): + return True + try: + stream_isatty = stream.isatty + except AttributeError: + return False + else: + return stream_isatty() + + @property + def closed(self): + stream = self.__wrapped + try: + return stream.closed + except AttributeError: + return True + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]((?:.|;)*?)(\x07)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + + # should we strip ANSI sequences from our output? + if strip is None: + strip = conversion_supported or (not self.stream.closed and not self.stream.isatty()) + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = conversion_supported and not self.stream.closed and self.stream.isatty() + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not self.stream.closed: + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command in '\x07': # \x07 = BEL + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/initialise.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/initialise.py new file mode 100644 index 00000000..430d0668 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/initialise.py @@ -0,0 +1,80 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = None +orig_stderr = None + +wrapped_stdout = None +wrapped_stderr = None + +atexit_done = False + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/win32.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/win32.py new file mode 100644 index 00000000..c2d83603 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/win32.py @@ -0,0 +1,152 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in + (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = _GetStdHandle(stream_id) + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = _GetStdHandle(stream_id) + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = _GetStdHandle(stream_id) + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = _GetStdHandle(stream_id) + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = _GetStdHandle(stream_id) + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/winterm.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/winterm.py new file mode 100644 index 00000000..0fdb4ec4 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/colorama/winterm.py @@ -0,0 +1,169 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + self._light = 0 + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + elif mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + elif mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/METADATA new file mode 100644 index 00000000..f4d89c41 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/METADATA @@ -0,0 +1,70 @@ +Metadata-Version: 2.1 +Name: contextlib2 +Version: 0.6.0 +Summary: Backports and enhancements for the contextlib module +Home-page: http://contextlib2.readthedocs.org +Author: Nick Coghlan +Author-email: ncoghlan@gmail.com +License: PSF License +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* + +.. image:: https://jazzband.co/static/img/badge.svg + :target: https://jazzband.co/ + :alt: Jazzband + +.. image:: https://readthedocs.org/projects/contextlib2/badge/?version=latest + :target: https://contextlib2.readthedocs.org/ + :alt: Latest Docs + +.. image:: https://img.shields.io/travis/jazzband/contextlib2/master.svg + :target: http://travis-ci.org/jazzband/contextlib2 + +.. image:: https://coveralls.io/repos/github/jazzband/contextlib2/badge.svg?branch=master + :target: https://coveralls.io/github/jazzband/contextlib2?branch=master + +.. image:: https://landscape.io/github/jazzband/contextlib2/master/landscape.svg + :target: https://landscape.io/github/jazzband/contextlib2/ + +contextlib2 is a backport of the `standard library's contextlib +module `_ to +earlier Python versions. + +It also serves as a real world proving ground for possible future +enhancements to the standard library version. + +Development +----------- + +contextlib2 has no runtime dependencies, but requires ``unittest2`` for testing +on Python 2.x, as well as ``setuptools`` and ``wheel`` to generate universal +wheel archives. + +Local testing is just a matter of running ``python test_contextlib2.py``. + +You can test against multiple versions of Python with +`tox `_:: + + pip install tox + tox + +Versions currently tested in both tox and Travis CI are: + +* CPython 2.7 +* CPython 3.4 +* CPython 3.5 +* CPython 3.6 +* CPython 3.7 +* PyPy +* PyPy3 + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/RECORD new file mode 100644 index 00000000..d64bd474 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/RECORD @@ -0,0 +1,11 @@ +contextlib2.py,sha256=5HjGflUzwWAUfcILhSmC2GqvoYdZZzFzVfIDztHigUs,16915 +contextlib2-0.6.0.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +contextlib2-0.6.0.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +contextlib2-0.6.0.dist-info/METADATA,sha256=gSVIyF9xprVGAJdZdrVoZR9VXpXRWURqyrugGzj66Rk,2291 +contextlib2-0.6.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +contextlib2-0.6.0.dist-info/top_level.txt,sha256=RxWWBMkHA_rsw1laXJ8L3yE_fyYaBmvt2bVUvj3WbMg,12 +contextlib2-0.6.0.dist-info/RECORD,, +contextlib2-0.6.0.dist-info/INSTALLER,, +contextlib2-0.6.0.dist-info/__pycache__,, +contextlib2.cpython-38.pyc,, +contextlib2-0.6.0.virtualenv,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/top_level.txt new file mode 100644 index 00000000..03fdf8ed --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.dist-info/top_level.txt @@ -0,0 +1 @@ +contextlib2 diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2-0.6.0.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2.py new file mode 100644 index 00000000..3aae8f41 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/contextlib2.py @@ -0,0 +1,518 @@ +"""contextlib2 - backports and enhancements to the contextlib module""" + +import abc +import sys +import warnings +from collections import deque +from functools import wraps + +__all__ = ["contextmanager", "closing", "nullcontext", + "AbstractContextManager", + "ContextDecorator", "ExitStack", + "redirect_stdout", "redirect_stderr", "suppress"] + +# Backwards compatibility +__all__ += ["ContextStack"] + + +# Backport abc.ABC +if sys.version_info[:2] >= (3, 4): + _abc_ABC = abc.ABC +else: + _abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) + + +# Backport classic class MRO +def _classic_mro(C, result): + if C in result: + return + result.append(C) + for B in C.__bases__: + _classic_mro(B, result) + return result + + +# Backport _collections_abc._check_methods +def _check_methods(C, *methods): + try: + mro = C.__mro__ + except AttributeError: + mro = tuple(_classic_mro(C, [])) + + for method in methods: + for B in mro: + if method in B.__dict__: + if B.__dict__[method] is None: + return NotImplemented + break + else: + return NotImplemented + return True + + +class AbstractContextManager(_abc_ABC): + """An abstract base class for context managers.""" + + def __enter__(self): + """Return `self` upon entering the runtime context.""" + return self + + @abc.abstractmethod + def __exit__(self, exc_type, exc_value, traceback): + """Raise any exception triggered within the runtime context.""" + return None + + @classmethod + def __subclasshook__(cls, C): + """Check whether subclass is considered a subclass of this ABC.""" + if cls is AbstractContextManager: + return _check_methods(C, "__enter__", "__exit__") + return NotImplemented + + +class ContextDecorator(object): + """A base class or mixin that enables context managers to work as decorators.""" + + def refresh_cm(self): + """Returns the context manager used to actually wrap the call to the + decorated function. + + The default implementation just returns *self*. + + Overriding this method allows otherwise one-shot context managers + like _GeneratorContextManager to support use as decorators via + implicit recreation. + + DEPRECATED: refresh_cm was never added to the standard library's + ContextDecorator API + """ + warnings.warn("refresh_cm was never added to the standard library", + DeprecationWarning) + return self._recreate_cm() + + def _recreate_cm(self): + """Return a recreated instance of self. + + Allows an otherwise one-shot context manager like + _GeneratorContextManager to support use as + a decorator via implicit recreation. + + This is a private interface just for _GeneratorContextManager. + See issue #11647 for details. + """ + return self + + def __call__(self, func): + @wraps(func) + def inner(*args, **kwds): + with self._recreate_cm(): + return func(*args, **kwds) + return inner + + +class _GeneratorContextManager(ContextDecorator): + """Helper for @contextmanager decorator.""" + + def __init__(self, func, args, kwds): + self.gen = func(*args, **kwds) + self.func, self.args, self.kwds = func, args, kwds + # Issue 19330: ensure context manager instances have good docstrings + doc = getattr(func, "__doc__", None) + if doc is None: + doc = type(self).__doc__ + self.__doc__ = doc + # Unfortunately, this still doesn't provide good help output when + # inspecting the created context manager instances, since pydoc + # currently bypasses the instance docstring and shows the docstring + # for the class instead. + # See http://bugs.python.org/issue19404 for more details. + + def _recreate_cm(self): + # _GCM instances are one-shot context managers, so the + # CM must be recreated each time a decorated function is + # called + return self.__class__(self.func, self.args, self.kwds) + + def __enter__(self): + try: + return next(self.gen) + except StopIteration: + raise RuntimeError("generator didn't yield") + + def __exit__(self, type, value, traceback): + if type is None: + try: + next(self.gen) + except StopIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + if value is None: + # Need to force instantiation so we can reliably + # tell if we get the same exception back + value = type() + try: + self.gen.throw(type, value, traceback) + raise RuntimeError("generator didn't stop after throw()") + except StopIteration as exc: + # Suppress StopIteration *unless* it's the same exception that + # was passed to throw(). This prevents a StopIteration + # raised inside the "with" statement from being suppressed. + return exc is not value + except RuntimeError as exc: + # Don't re-raise the passed in exception + if exc is value: + return False + # Likewise, avoid suppressing if a StopIteration exception + # was passed to throw() and later wrapped into a RuntimeError + # (see PEP 479). + if _HAVE_EXCEPTION_CHAINING and exc.__cause__ is value: + return False + raise + except: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise + # an exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so this + # fixes the impedance mismatch between the throw() protocol + # and the __exit__() protocol. + # + if sys.exc_info()[1] is not value: + raise + + +def contextmanager(func): + """@contextmanager decorator. + + Typical usage: + + @contextmanager + def some_generator(): + + try: + yield + finally: + + + This makes this: + + with some_generator() as : + + + equivalent to this: + + + try: + = + + finally: + + + """ + @wraps(func) + def helper(*args, **kwds): + return _GeneratorContextManager(func, args, kwds) + return helper + + +class closing(object): + """Context to automatically close something at the end of a block. + + Code like this: + + with closing(.open()) as f: + + + is equivalent to this: + + f = .open() + try: + + finally: + f.close() + + """ + def __init__(self, thing): + self.thing = thing + + def __enter__(self): + return self.thing + + def __exit__(self, *exc_info): + self.thing.close() + + +class _RedirectStream(object): + + _stream = None + + def __init__(self, new_target): + self._new_target = new_target + # We use a list of old targets to make this CM re-entrant + self._old_targets = [] + + def __enter__(self): + self._old_targets.append(getattr(sys, self._stream)) + setattr(sys, self._stream, self._new_target) + return self._new_target + + def __exit__(self, exctype, excinst, exctb): + setattr(sys, self._stream, self._old_targets.pop()) + + +class redirect_stdout(_RedirectStream): + """Context manager for temporarily redirecting stdout to another file. + + # How to send help() to stderr + with redirect_stdout(sys.stderr): + help(dir) + + # How to write help() to a file + with open('help.txt', 'w') as f: + with redirect_stdout(f): + help(pow) + """ + + _stream = "stdout" + + +class redirect_stderr(_RedirectStream): + """Context manager for temporarily redirecting stderr to another file.""" + + _stream = "stderr" + + +class suppress(object): + """Context manager to suppress specified exceptions + + After the exception is suppressed, execution proceeds with the next + statement following the with statement. + + with suppress(FileNotFoundError): + os.remove(somefile) + # Execution still resumes here if the file was already removed + """ + + def __init__(self, *exceptions): + self._exceptions = exceptions + + def __enter__(self): + pass + + def __exit__(self, exctype, excinst, exctb): + # Unlike isinstance and issubclass, CPython exception handling + # currently only looks at the concrete type hierarchy (ignoring + # the instance and subclass checking hooks). While Guido considers + # that a bug rather than a feature, it's a fairly hard one to fix + # due to various internal implementation details. suppress provides + # the simpler issubclass based semantics, rather than trying to + # exactly reproduce the limitations of the CPython interpreter. + # + # See http://bugs.python.org/issue12029 for more details + return exctype is not None and issubclass(exctype, self._exceptions) + + +# Context manipulation is Python 3 only +_HAVE_EXCEPTION_CHAINING = sys.version_info[0] >= 3 +if _HAVE_EXCEPTION_CHAINING: + def _make_context_fixer(frame_exc): + def _fix_exception_context(new_exc, old_exc): + # Context may not be correct, so find the end of the chain + while 1: + exc_context = new_exc.__context__ + if exc_context is old_exc: + # Context is already set correctly (see issue 20317) + return + if exc_context is None or exc_context is frame_exc: + break + new_exc = exc_context + # Change the end of the chain to point to the exception + # we expect it to reference + new_exc.__context__ = old_exc + return _fix_exception_context + + def _reraise_with_existing_context(exc_details): + try: + # bare "raise exc_details[1]" replaces our carefully + # set-up context + fixed_ctx = exc_details[1].__context__ + raise exc_details[1] + except BaseException: + exc_details[1].__context__ = fixed_ctx + raise +else: + # No exception context in Python 2 + def _make_context_fixer(frame_exc): + return lambda new_exc, old_exc: None + + # Use 3 argument raise in Python 2, + # but use exec to avoid SyntaxError in Python 3 + def _reraise_with_existing_context(exc_details): + exc_type, exc_value, exc_tb = exc_details + exec("raise exc_type, exc_value, exc_tb") + +# Handle old-style classes if they exist +try: + from types import InstanceType +except ImportError: + # Python 3 doesn't have old-style classes + _get_type = type +else: + # Need to handle old-style context managers on Python 2 + def _get_type(obj): + obj_type = type(obj) + if obj_type is InstanceType: + return obj.__class__ # Old-style class + return obj_type # New-style class + + +# Inspired by discussions on http://bugs.python.org/issue13585 +class ExitStack(object): + """Context manager for dynamic management of a stack of exit callbacks + + For example: + + with ExitStack() as stack: + files = [stack.enter_context(open(fname)) for fname in filenames] + # All opened files will automatically be closed at the end of + # the with statement, even if attempts to open files later + # in the list raise an exception + + """ + def __init__(self): + self._exit_callbacks = deque() + + def pop_all(self): + """Preserve the context stack by transferring it to a new instance""" + new_stack = type(self)() + new_stack._exit_callbacks = self._exit_callbacks + self._exit_callbacks = deque() + return new_stack + + def _push_cm_exit(self, cm, cm_exit): + """Helper to correctly register callbacks to __exit__ methods""" + def _exit_wrapper(*exc_details): + return cm_exit(cm, *exc_details) + _exit_wrapper.__self__ = cm + self.push(_exit_wrapper) + + def push(self, exit): + """Registers a callback with the standard __exit__ method signature + + Can suppress exceptions the same way __exit__ methods can. + + Also accepts any object with an __exit__ method (registering a call + to the method instead of the object itself) + """ + # We use an unbound method rather than a bound method to follow + # the standard lookup behaviour for special methods + _cb_type = _get_type(exit) + try: + exit_method = _cb_type.__exit__ + except AttributeError: + # Not a context manager, so assume its a callable + self._exit_callbacks.append(exit) + else: + self._push_cm_exit(exit, exit_method) + return exit # Allow use as a decorator + + def callback(self, callback, *args, **kwds): + """Registers an arbitrary callback and arguments. + + Cannot suppress exceptions. + """ + def _exit_wrapper(exc_type, exc, tb): + callback(*args, **kwds) + # We changed the signature, so using @wraps is not appropriate, but + # setting __wrapped__ may still help with introspection + _exit_wrapper.__wrapped__ = callback + self.push(_exit_wrapper) + return callback # Allow use as a decorator + + def enter_context(self, cm): + """Enters the supplied context manager + + If successful, also pushes its __exit__ method as a callback and + returns the result of the __enter__ method. + """ + # We look up the special methods on the type to match the with statement + _cm_type = _get_type(cm) + _exit = _cm_type.__exit__ + result = _cm_type.__enter__(cm) + self._push_cm_exit(cm, _exit) + return result + + def close(self): + """Immediately unwind the context stack""" + self.__exit__(None, None, None) + + def __enter__(self): + return self + + def __exit__(self, *exc_details): + received_exc = exc_details[0] is not None + + # We manipulate the exception state so it behaves as though + # we were actually nesting multiple with statements + frame_exc = sys.exc_info()[1] + _fix_exception_context = _make_context_fixer(frame_exc) + + # Callbacks are invoked in LIFO order to match the behaviour of + # nested context managers + suppressed_exc = False + pending_raise = False + while self._exit_callbacks: + cb = self._exit_callbacks.pop() + try: + if cb(*exc_details): + suppressed_exc = True + pending_raise = False + exc_details = (None, None, None) + except: + new_exc_details = sys.exc_info() + # simulate the stack of exceptions by setting the context + _fix_exception_context(new_exc_details[1], exc_details[1]) + pending_raise = True + exc_details = new_exc_details + if pending_raise: + _reraise_with_existing_context(exc_details) + return received_exc and suppressed_exc + + +# Preserve backwards compatibility +class ContextStack(ExitStack): + """Backwards compatibility alias for ExitStack""" + + def __init__(self): + warnings.warn("ContextStack has been renamed to ExitStack", + DeprecationWarning) + super(ContextStack, self).__init__() + + def register_exit(self, callback): + return self.push(callback) + + def register(self, callback, *args, **kwds): + return self.callback(callback, *args, **kwds) + + def preserve(self): + return self.pop_all() + + +class nullcontext(AbstractContextManager): + """Context manager that does no additional processing. + Used as a stand-in for a normal context manager, when a particular + block of code is only sometimes used with a normal context manager: + cm = optional_cm if condition else nullcontext() + with cm: + # Perform operation, using optional_cm if condition is True + """ + + def __init__(self, enter_result=None): + self.enter_result = enter_result + + def __enter__(self): + return self.enter_result + + def __exit__(self, *excinfo): + pass diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/__init__.py new file mode 100644 index 00000000..0defb82e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/__init__.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +try: + from ._version import version as __version__ +except ImportError: + __version__ = 'unknown' + +__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz', + 'utils', 'zoneinfo'] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_common.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_common.py new file mode 100644 index 00000000..4eb2659b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_common.py @@ -0,0 +1,43 @@ +""" +Common code used in multiple modules. +""" + + +class weekday(object): + __slots__ = ["weekday", "n"] + + def __init__(self, weekday, n=None): + self.weekday = weekday + self.n = n + + def __call__(self, n): + if n == self.n: + return self + else: + return self.__class__(self.weekday, n) + + def __eq__(self, other): + try: + if self.weekday != other.weekday or self.n != other.n: + return False + except AttributeError: + return False + return True + + def __hash__(self): + return hash(( + self.weekday, + self.n, + )) + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday] + if not self.n: + return s + else: + return "%s(%+d)" % (s, self.n) + +# vim:ts=4:sw=4:et diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_version.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_version.py new file mode 100644 index 00000000..eac12096 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/_version.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# file generated by setuptools_scm +# don't change, don't track in version control +version = '2.8.1' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/easter.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/easter.py new file mode 100644 index 00000000..53b7c789 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/easter.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- +""" +This module offers a generic easter computing method for any given year, using +Western, Orthodox or Julian algorithms. +""" + +import datetime + +__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"] + +EASTER_JULIAN = 1 +EASTER_ORTHODOX = 2 +EASTER_WESTERN = 3 + + +def easter(year, method=EASTER_WESTERN): + """ + This method was ported from the work done by GM Arts, + on top of the algorithm by Claus Tondering, which was + based in part on the algorithm of Ouding (1940), as + quoted in "Explanatory Supplement to the Astronomical + Almanac", P. Kenneth Seidelmann, editor. + + This algorithm implements three different easter + calculation methods: + + 1 - Original calculation in Julian calendar, valid in + dates after 326 AD + 2 - Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3 - Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well + + These methods are represented by the constants: + + * ``EASTER_JULIAN = 1`` + * ``EASTER_ORTHODOX = 2`` + * ``EASTER_WESTERN = 3`` + + The default method is method 3. + + More about the algorithm may be found at: + + `GM Arts: Easter Algorithms `_ + + and + + `The Calendar FAQ: Easter `_ + + """ + + if not (1 <= method <= 3): + raise ValueError("invalid method") + + # g - Golden year - 1 + # c - Century + # h - (23 - Epact) mod 30 + # i - Number of days from March 21 to Paschal Full Moon + # j - Weekday for PFM (0=Sunday, etc) + # p - Number of days from March 21 to Sunday on or before PFM + # (-6 to 28 methods 1 & 3, to 56 for method 2) + # e - Extra days to add for method 2 (converting Julian + # date to Gregorian date) + + y = year + g = y % 19 + e = 0 + if method < 3: + # Old method + i = (19*g + 15) % 30 + j = (y + y//4 + i) % 7 + if method == 2: + # Extra dates to convert Julian to Gregorian date + e = 10 + if y > 1600: + e = e + y//100 - 16 - (y//100 - 16)//4 + else: + # New method + c = y//100 + h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30 + i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11)) + j = (y + y//4 + i + 2 - c + c//4) % 7 + + # p can be from -6 to 56 corresponding to dates 22 March to 23 May + # (later dates apply to method 2, although 23 May never actually occurs) + p = i - j + e + d = 1 + (p + 27 + (p + 6)//40) % 31 + m = 3 + (p + 26)//30 + return datetime.date(int(y), int(m), int(d)) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/__init__.py new file mode 100644 index 00000000..d174b0e4 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/__init__.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +from ._parser import parse, parser, parserinfo, ParserError +from ._parser import DEFAULTPARSER, DEFAULTTZPARSER +from ._parser import UnknownTimezoneWarning + +from ._parser import __doc__ + +from .isoparser import isoparser, isoparse + +__all__ = ['parse', 'parser', 'parserinfo', + 'isoparse', 'isoparser', + 'ParserError', + 'UnknownTimezoneWarning'] + + +### +# Deprecate portions of the private interface so that downstream code that +# is improperly relying on it is given *some* notice. + + +def __deprecated_private_func(f): + from functools import wraps + import warnings + + msg = ('{name} is a private function and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=f.__name__) + + @wraps(f) + def deprecated_func(*args, **kwargs): + warnings.warn(msg, DeprecationWarning) + return f(*args, **kwargs) + + return deprecated_func + +def __deprecate_private_class(c): + import warnings + + msg = ('{name} is a private class and may break without warning, ' + 'it will be moved and or renamed in future versions.') + msg = msg.format(name=c.__name__) + + class private_class(c): + __doc__ = c.__doc__ + + def __init__(self, *args, **kwargs): + warnings.warn(msg, DeprecationWarning) + super(private_class, self).__init__(*args, **kwargs) + + private_class.__name__ = c.__name__ + + return private_class + + +from ._parser import _timelex, _resultbase +from ._parser import _tzparser, _parsetz + +_timelex = __deprecate_private_class(_timelex) +_tzparser = __deprecate_private_class(_tzparser) +_resultbase = __deprecate_private_class(_resultbase) +_parsetz = __deprecated_private_func(_parsetz) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/_parser.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/_parser.py new file mode 100644 index 00000000..458aa6a3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/_parser.py @@ -0,0 +1,1609 @@ +# -*- coding: utf-8 -*- +""" +This module offers a generic date/time string parser which is able to parse +most known formats to represent a date and/or time. + +This module attempts to be forgiving with regards to unlikely input formats, +returning a datetime object even for dates which are ambiguous. If an element +of a date/time stamp is omitted, the following rules are applied: + +- If AM or PM is left unspecified, a 24-hour clock is assumed, however, an hour + on a 12-hour clock (``0 <= hour <= 12``) *must* be specified if AM or PM is + specified. +- If a time zone is omitted, a timezone-naive datetime is returned. + +If any other elements are missing, they are taken from the +:class:`datetime.datetime` object passed to the parameter ``default``. If this +results in a day number exceeding the valid number of days per month, the +value falls back to the end of the month. + +Additional resources about date/time string formats can be found below: + +- `A summary of the international standard date and time notation + `_ +- `W3C Date and Time Formats `_ +- `Time Formats (Planetary Rings Node) `_ +- `CPAN ParseDate module + `_ +- `Java SimpleDateFormat Class + `_ +""" +from __future__ import unicode_literals + +import datetime +import re +import string +import time +import warnings + +from calendar import monthrange +from io import StringIO + +import six +from six import integer_types, text_type + +from decimal import Decimal + +from warnings import warn + +from .. import relativedelta +from .. import tz + +__all__ = ["parse", "parserinfo", "ParserError"] + + +# TODO: pandas.core.tools.datetimes imports this explicitly. Might be worth +# making public and/or figuring out if there is something we can +# take off their plate. +class _timelex(object): + # Fractional seconds are sometimes split by a comma + _split_decimal = re.compile("([.,])") + + def __init__(self, instream): + if six.PY2: + # In Python 2, we can't duck type properly because unicode has + # a 'decode' function, and we'd be double-decoding + if isinstance(instream, (bytes, bytearray)): + instream = instream.decode() + else: + if getattr(instream, 'decode', None) is not None: + instream = instream.decode() + + if isinstance(instream, text_type): + instream = StringIO(instream) + elif getattr(instream, 'read', None) is None: + raise TypeError('Parser must be a string or character stream, not ' + '{itype}'.format(itype=instream.__class__.__name__)) + + self.instream = instream + self.charstack = [] + self.tokenstack = [] + self.eof = False + + def get_token(self): + """ + This function breaks the time string into lexical units (tokens), which + can be parsed by the parser. Lexical units are demarcated by changes in + the character set, so any continuous string of letters is considered + one unit, any continuous string of numbers is considered one unit. + + The main complication arises from the fact that dots ('.') can be used + both as separators (e.g. "Sep.20.2009") or decimal points (e.g. + "4:30:21.447"). As such, it is necessary to read the full context of + any dot-separated strings before breaking it into tokens; as such, this + function maintains a "token stack", for when the ambiguous context + demands that multiple tokens be parsed at once. + """ + if self.tokenstack: + return self.tokenstack.pop(0) + + seenletters = False + token = None + state = None + + while not self.eof: + # We only realize that we've reached the end of a token when we + # find a character that's not part of the current token - since + # that character may be part of the next token, it's stored in the + # charstack. + if self.charstack: + nextchar = self.charstack.pop(0) + else: + nextchar = self.instream.read(1) + while nextchar == '\x00': + nextchar = self.instream.read(1) + + if not nextchar: + self.eof = True + break + elif not state: + # First character of the token - determines if we're starting + # to parse a word, a number or something else. + token = nextchar + if self.isword(nextchar): + state = 'a' + elif self.isnum(nextchar): + state = '0' + elif self.isspace(nextchar): + token = ' ' + break # emit token + else: + break # emit token + elif state == 'a': + # If we've already started reading a word, we keep reading + # letters until we find something that's not part of a word. + seenletters = True + if self.isword(nextchar): + token += nextchar + elif nextchar == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0': + # If we've already started reading a number, we keep reading + # numbers until we find something that doesn't fit. + if self.isnum(nextchar): + token += nextchar + elif nextchar == '.' or (nextchar == ',' and len(token) >= 2): + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == 'a.': + # If we've seen some letters and a dot separator, continue + # parsing, and the tokens will be broken up later. + seenletters = True + if nextchar == '.' or self.isword(nextchar): + token += nextchar + elif self.isnum(nextchar) and token[-1] == '.': + token += nextchar + state = '0.' + else: + self.charstack.append(nextchar) + break # emit token + elif state == '0.': + # If we've seen at least one dot separator, keep going, we'll + # break up the tokens later. + if nextchar == '.' or self.isnum(nextchar): + token += nextchar + elif self.isword(nextchar) and token[-1] == '.': + token += nextchar + state = 'a.' + else: + self.charstack.append(nextchar) + break # emit token + + if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or + token[-1] in '.,')): + l = self._split_decimal.split(token) + token = l[0] + for tok in l[1:]: + if tok: + self.tokenstack.append(tok) + + if state == '0.' and token.count('.') == 0: + token = token.replace(',', '.') + + return token + + def __iter__(self): + return self + + def __next__(self): + token = self.get_token() + if token is None: + raise StopIteration + + return token + + def next(self): + return self.__next__() # Python 2.x support + + @classmethod + def split(cls, s): + return list(cls(s)) + + @classmethod + def isword(cls, nextchar): + """ Whether or not the next character is part of a word """ + return nextchar.isalpha() + + @classmethod + def isnum(cls, nextchar): + """ Whether the next character is part of a number """ + return nextchar.isdigit() + + @classmethod + def isspace(cls, nextchar): + """ Whether the next character is whitespace """ + return nextchar.isspace() + + +class _resultbase(object): + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def _repr(self, classname): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (classname, ", ".join(l)) + + def __len__(self): + return (sum(getattr(self, attr) is not None + for attr in self.__slots__)) + + def __repr__(self): + return self._repr(self.__class__.__name__) + + +class parserinfo(object): + """ + Class which handles what inputs are accepted. Subclass this to customize + the language and acceptable values for each parameter. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. Default is ``False``. + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + Default is ``False``. + """ + + # m from a.m/p.m, t from ISO T separator + JUMP = [" ", ".", ",", ";", "-", "/", "'", + "at", "on", "and", "ad", "m", "t", "of", + "st", "nd", "rd", "th"] + + WEEKDAYS = [("Mon", "Monday"), + ("Tue", "Tuesday"), # TODO: "Tues" + ("Wed", "Wednesday"), + ("Thu", "Thursday"), # TODO: "Thurs" + ("Fri", "Friday"), + ("Sat", "Saturday"), + ("Sun", "Sunday")] + MONTHS = [("Jan", "January"), + ("Feb", "February"), # TODO: "Febr" + ("Mar", "March"), + ("Apr", "April"), + ("May", "May"), + ("Jun", "June"), + ("Jul", "July"), + ("Aug", "August"), + ("Sep", "Sept", "September"), + ("Oct", "October"), + ("Nov", "November"), + ("Dec", "December")] + HMS = [("h", "hour", "hours"), + ("m", "minute", "minutes"), + ("s", "second", "seconds")] + AMPM = [("am", "a"), + ("pm", "p")] + UTCZONE = ["UTC", "GMT", "Z", "z"] + PERTAIN = ["of"] + TZOFFSET = {} + # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate", + # "Anno Domini", "Year of Our Lord"] + + def __init__(self, dayfirst=False, yearfirst=False): + self._jump = self._convert(self.JUMP) + self._weekdays = self._convert(self.WEEKDAYS) + self._months = self._convert(self.MONTHS) + self._hms = self._convert(self.HMS) + self._ampm = self._convert(self.AMPM) + self._utczone = self._convert(self.UTCZONE) + self._pertain = self._convert(self.PERTAIN) + + self.dayfirst = dayfirst + self.yearfirst = yearfirst + + self._year = time.localtime().tm_year + self._century = self._year // 100 * 100 + + def _convert(self, lst): + dct = {} + for i, v in enumerate(lst): + if isinstance(v, tuple): + for v in v: + dct[v.lower()] = i + else: + dct[v.lower()] = i + return dct + + def jump(self, name): + return name.lower() in self._jump + + def weekday(self, name): + try: + return self._weekdays[name.lower()] + except KeyError: + pass + return None + + def month(self, name): + try: + return self._months[name.lower()] + 1 + except KeyError: + pass + return None + + def hms(self, name): + try: + return self._hms[name.lower()] + except KeyError: + return None + + def ampm(self, name): + try: + return self._ampm[name.lower()] + except KeyError: + return None + + def pertain(self, name): + return name.lower() in self._pertain + + def utczone(self, name): + return name.lower() in self._utczone + + def tzoffset(self, name): + if name in self._utczone: + return 0 + + return self.TZOFFSET.get(name) + + def convertyear(self, year, century_specified=False): + """ + Converts two-digit years to year within [-50, 49] + range of self._year (current local time) + """ + + # Function contract is that the year is always positive + assert year >= 0 + + if year < 100 and not century_specified: + # assume current century to start + year += self._century + + if year >= self._year + 50: # if too far in future + year -= 100 + elif year < self._year - 50: # if too far in past + year += 100 + + return year + + def validate(self, res): + # move to info + if res.year is not None: + res.year = self.convertyear(res.year, res.century_specified) + + if ((res.tzoffset == 0 and not res.tzname) or + (res.tzname == 'Z' or res.tzname == 'z')): + res.tzname = "UTC" + res.tzoffset = 0 + elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname): + res.tzoffset = 0 + return True + + +class _ymd(list): + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + self.century_specified = False + self.dstridx = None + self.mstridx = None + self.ystridx = None + + @property + def has_year(self): + return self.ystridx is not None + + @property + def has_month(self): + return self.mstridx is not None + + @property + def has_day(self): + return self.dstridx is not None + + def could_be_day(self, value): + if self.has_day: + return False + elif not self.has_month: + return 1 <= value <= 31 + elif not self.has_year: + # Be permissive, assume leap year + month = self[self.mstridx] + return 1 <= value <= monthrange(2000, month)[1] + else: + month = self[self.mstridx] + year = self[self.ystridx] + return 1 <= value <= monthrange(year, month)[1] + + def append(self, val, label=None): + if hasattr(val, '__len__'): + if val.isdigit() and len(val) > 2: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + elif val > 100: + self.century_specified = True + if label not in [None, 'Y']: # pragma: no cover + raise ValueError(label) + label = 'Y' + + super(self.__class__, self).append(int(val)) + + if label == 'M': + if self.has_month: + raise ValueError('Month is already set') + self.mstridx = len(self) - 1 + elif label == 'D': + if self.has_day: + raise ValueError('Day is already set') + self.dstridx = len(self) - 1 + elif label == 'Y': + if self.has_year: + raise ValueError('Year is already set') + self.ystridx = len(self) - 1 + + def _resolve_from_stridxs(self, strids): + """ + Try to resolve the identities of year/month/day elements using + ystridx, mstridx, and dstridx, if enough of these are specified. + """ + if len(self) == 3 and len(strids) == 2: + # we can back out the remaining stridx value + missing = [x for x in range(3) if x not in strids.values()] + key = [x for x in ['y', 'm', 'd'] if x not in strids] + assert len(missing) == len(key) == 1 + key = key[0] + val = missing[0] + strids[key] = val + + assert len(self) == len(strids) # otherwise this should not be called + out = {key: self[strids[key]] for key in strids} + return (out.get('y'), out.get('m'), out.get('d')) + + def resolve_ymd(self, yearfirst, dayfirst): + len_ymd = len(self) + year, month, day = (None, None, None) + + strids = (('y', self.ystridx), + ('m', self.mstridx), + ('d', self.dstridx)) + + strids = {key: val for key, val in strids if val is not None} + if (len(self) == len(strids) > 0 or + (len(self) == 3 and len(strids) == 2)): + return self._resolve_from_stridxs(strids) + + mstridx = self.mstridx + + if len_ymd > 3: + raise ValueError("More than three YMD values") + elif len_ymd == 1 or (mstridx is not None and len_ymd == 2): + # One member, or two members with a month string + if mstridx is not None: + month = self[mstridx] + # since mstridx is 0 or 1, self[mstridx-1] always + # looks up the other element + other = self[mstridx - 1] + else: + other = self[0] + + if len_ymd > 1 or mstridx is None: + if other > 31: + year = other + else: + day = other + + elif len_ymd == 2: + # Two members with numbers + if self[0] > 31: + # 99-01 + year, month = self + elif self[1] > 31: + # 01-99 + month, year = self + elif dayfirst and self[1] <= 12: + # 13-01 + day, month = self + else: + # 01-13 + month, day = self + + elif len_ymd == 3: + # Three members + if mstridx == 0: + if self[1] > 31: + # Apr-2003-25 + month, year, day = self + else: + month, day, year = self + elif mstridx == 1: + if self[0] > 31 or (yearfirst and self[2] <= 31): + # 99-Jan-01 + year, month, day = self + else: + # 01-Jan-01 + # Give precedence to day-first, since + # two-digit years is usually hand-written. + day, month, year = self + + elif mstridx == 2: + # WTF!? + if self[1] > 31: + # 01-99-Jan + day, year, month = self + else: + # 99-01-Jan + year, day, month = self + + else: + if (self[0] > 31 or + self.ystridx == 0 or + (yearfirst and self[1] <= 12 and self[2] <= 31)): + # 99-01-01 + if dayfirst and self[2] <= 12: + year, day, month = self + else: + year, month, day = self + elif self[0] > 12 or (dayfirst and self[1] <= 12): + # 13-01-01 + day, month, year = self + else: + # 01-13-01 + month, day, year = self + + return year, month, day + + +class parser(object): + def __init__(self, info=None): + self.info = info or parserinfo() + + def parse(self, timestr, default=None, + ignoretz=False, tzinfos=None, **kwargs): + """ + Parse the date/time string into a :class:`datetime.datetime` object. + + :param timestr: + Any date/time string using the supported formats. + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a + naive :class:`datetime.datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param \\*\\*kwargs: + Keyword arguments as passed to ``_parse()``. + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ParserError: + Raised for invalid or unknown string format, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date + would be created. + + :raises TypeError: + Raised for non-string or character stream input. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + + if default is None: + default = datetime.datetime.now().replace(hour=0, minute=0, + second=0, microsecond=0) + + res, skipped_tokens = self._parse(timestr, **kwargs) + + if res is None: + raise ParserError("Unknown string format: %s", timestr) + + if len(res) == 0: + raise ParserError("String does not contain a date: %s", timestr) + + try: + ret = self._build_naive(res, default) + except ValueError as e: + six.raise_from(ParserError(e.args[0] + ": %s", timestr), e) + + if not ignoretz: + ret = self._build_tzaware(ret, res, tzinfos) + + if kwargs.get('fuzzy_with_tokens', False): + return ret, skipped_tokens + else: + return ret + + class _result(_resultbase): + __slots__ = ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond", + "tzname", "tzoffset", "ampm","any_unused_tokens"] + + def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False, + fuzzy_with_tokens=False): + """ + Private method which performs the heavy lifting of parsing, called from + ``parse()``, which passes on its ``kwargs`` to this function. + + :param timestr: + The string to parse. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM + and YMD. If set to ``None``, this value is retrieved from the + current :class:`parserinfo` object (which itself defaults to + ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken + to be the year, otherwise the last number is taken to be the year. + If this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + """ + if fuzzy_with_tokens: + fuzzy = True + + info = self.info + + if dayfirst is None: + dayfirst = info.dayfirst + + if yearfirst is None: + yearfirst = info.yearfirst + + res = self._result() + l = _timelex.split(timestr) # Splits the timestr into tokens + + skipped_idxs = [] + + # year/month/day list + ymd = _ymd() + + len_l = len(l) + i = 0 + try: + while i < len_l: + + # Check if it's a number + value_repr = l[i] + try: + value = float(value_repr) + except ValueError: + value = None + + if value is not None: + # Numeric token + i = self._parse_numeric_token(l, i, info, ymd, res, fuzzy) + + # Check weekday + elif info.weekday(l[i]) is not None: + value = info.weekday(l[i]) + res.weekday = value + + # Check month name + elif info.month(l[i]) is not None: + value = info.month(l[i]) + ymd.append(value, 'M') + + if i + 1 < len_l: + if l[i + 1] in ('-', '/'): + # Jan-01[-99] + sep = l[i + 1] + ymd.append(l[i + 2]) + + if i + 3 < len_l and l[i + 3] == sep: + # Jan-01-99 + ymd.append(l[i + 4]) + i += 2 + + i += 2 + + elif (i + 4 < len_l and l[i + 1] == l[i + 3] == ' ' and + info.pertain(l[i + 2])): + # Jan of 01 + # In this case, 01 is clearly year + if l[i + 4].isdigit(): + # Convert it here to become unambiguous + value = int(l[i + 4]) + year = str(info.convertyear(value)) + ymd.append(year, 'Y') + else: + # Wrong guess + pass + # TODO: not hit in tests + i += 4 + + # Check am/pm + elif info.ampm(l[i]) is not None: + value = info.ampm(l[i]) + val_is_ampm = self._ampm_valid(res.hour, res.ampm, fuzzy) + + if val_is_ampm: + res.hour = self._adjust_ampm(res.hour, value) + res.ampm = value + + elif fuzzy: + skipped_idxs.append(i) + + # Check for a timezone name + elif self._could_be_tzname(res.hour, res.tzname, res.tzoffset, l[i]): + res.tzname = l[i] + res.tzoffset = info.tzoffset(res.tzname) + + # Check for something like GMT+3, or BRST+3. Notice + # that it doesn't mean "I am 3 hours after GMT", but + # "my time +3 is GMT". If found, we reverse the + # logic so that timezone parsing code will get it + # right. + if i + 1 < len_l and l[i + 1] in ('+', '-'): + l[i + 1] = ('+', '-')[l[i + 1] == '+'] + res.tzoffset = None + if info.utczone(res.tzname): + # With something like GMT+3, the timezone + # is *not* GMT. + res.tzname = None + + # Check for a numbered timezone + elif res.hour is not None and l[i] in ('+', '-'): + signal = (-1, 1)[l[i] == '+'] + len_li = len(l[i + 1]) + + # TODO: check that l[i + 1] is integer? + if len_li == 4: + # -0300 + hour_offset = int(l[i + 1][:2]) + min_offset = int(l[i + 1][2:]) + elif i + 2 < len_l and l[i + 2] == ':': + # -03:00 + hour_offset = int(l[i + 1]) + min_offset = int(l[i + 3]) # TODO: Check that l[i+3] is minute-like? + i += 2 + elif len_li <= 2: + # -[0]3 + hour_offset = int(l[i + 1][:2]) + min_offset = 0 + else: + raise ValueError(timestr) + + res.tzoffset = signal * (hour_offset * 3600 + min_offset * 60) + + # Look for a timezone name between parenthesis + if (i + 5 < len_l and + info.jump(l[i + 2]) and l[i + 3] == '(' and + l[i + 5] == ')' and + 3 <= len(l[i + 4]) and + self._could_be_tzname(res.hour, res.tzname, + None, l[i + 4])): + # -0300 (BRST) + res.tzname = l[i + 4] + i += 4 + + i += 1 + + # Check jumps + elif not (info.jump(l[i]) or fuzzy): + raise ValueError(timestr) + + else: + skipped_idxs.append(i) + i += 1 + + # Process year/month/day + year, month, day = ymd.resolve_ymd(yearfirst, dayfirst) + + res.century_specified = ymd.century_specified + res.year = year + res.month = month + res.day = day + + except (IndexError, ValueError): + return None, None + + if not info.validate(res): + return None, None + + if fuzzy_with_tokens: + skipped_tokens = self._recombine_skipped(l, skipped_idxs) + return res, tuple(skipped_tokens) + else: + return res, None + + def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy): + # Token is a number + value_repr = tokens[idx] + try: + value = self._to_decimal(value_repr) + except Exception as e: + six.raise_from(ValueError('Unknown numeric token'), e) + + len_li = len(value_repr) + + len_l = len(tokens) + + if (len(ymd) == 3 and len_li in (2, 4) and + res.hour is None and + (idx + 1 >= len_l or + (tokens[idx + 1] != ':' and + info.hms(tokens[idx + 1]) is None))): + # 19990101T23[59] + s = tokens[idx] + res.hour = int(s[:2]) + + if len_li == 4: + res.minute = int(s[2:]) + + elif len_li == 6 or (len_li > 6 and tokens[idx].find('.') == 6): + # YYMMDD or HHMMSS[.ss] + s = tokens[idx] + + if not ymd and '.' not in tokens[idx]: + ymd.append(s[:2]) + ymd.append(s[2:4]) + ymd.append(s[4:]) + else: + # 19990101T235959[.59] + + # TODO: Check if res attributes already set. + res.hour = int(s[:2]) + res.minute = int(s[2:4]) + res.second, res.microsecond = self._parsems(s[4:]) + + elif len_li in (8, 12, 14): + # YYYYMMDD + s = tokens[idx] + ymd.append(s[:4], 'Y') + ymd.append(s[4:6]) + ymd.append(s[6:8]) + + if len_li > 8: + res.hour = int(s[8:10]) + res.minute = int(s[10:12]) + + if len_li > 12: + res.second = int(s[12:]) + + elif self._find_hms_idx(idx, tokens, info, allow_jump=True) is not None: + # HH[ ]h or MM[ ]m or SS[.ss][ ]s + hms_idx = self._find_hms_idx(idx, tokens, info, allow_jump=True) + (idx, hms) = self._parse_hms(idx, tokens, info, hms_idx) + if hms is not None: + # TODO: checking that hour/minute/second are not + # already set? + self._assign_hms(res, value_repr, hms) + + elif idx + 2 < len_l and tokens[idx + 1] == ':': + # HH:MM[:SS[.ss]] + res.hour = int(value) + value = self._to_decimal(tokens[idx + 2]) # TODO: try/except for this? + (res.minute, res.second) = self._parse_min_sec(value) + + if idx + 4 < len_l and tokens[idx + 3] == ':': + res.second, res.microsecond = self._parsems(tokens[idx + 4]) + + idx += 2 + + idx += 2 + + elif idx + 1 < len_l and tokens[idx + 1] in ('-', '/', '.'): + sep = tokens[idx + 1] + ymd.append(value_repr) + + if idx + 2 < len_l and not info.jump(tokens[idx + 2]): + if tokens[idx + 2].isdigit(): + # 01-01[-01] + ymd.append(tokens[idx + 2]) + else: + # 01-Jan[-01] + value = info.month(tokens[idx + 2]) + + if value is not None: + ymd.append(value, 'M') + else: + raise ValueError() + + if idx + 3 < len_l and tokens[idx + 3] == sep: + # We have three members + value = info.month(tokens[idx + 4]) + + if value is not None: + ymd.append(value, 'M') + else: + ymd.append(tokens[idx + 4]) + idx += 2 + + idx += 1 + idx += 1 + + elif idx + 1 >= len_l or info.jump(tokens[idx + 1]): + if idx + 2 < len_l and info.ampm(tokens[idx + 2]) is not None: + # 12 am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 2])) + idx += 1 + else: + # Year, month or day + ymd.append(value) + idx += 1 + + elif info.ampm(tokens[idx + 1]) is not None and (0 <= value < 24): + # 12am + hour = int(value) + res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 1])) + idx += 1 + + elif ymd.could_be_day(value): + ymd.append(value) + + elif not fuzzy: + raise ValueError() + + return idx + + def _find_hms_idx(self, idx, tokens, info, allow_jump): + len_l = len(tokens) + + if idx+1 < len_l and info.hms(tokens[idx+1]) is not None: + # There is an "h", "m", or "s" label following this token. We take + # assign the upcoming label to the current token. + # e.g. the "12" in 12h" + hms_idx = idx + 1 + + elif (allow_jump and idx+2 < len_l and tokens[idx+1] == ' ' and + info.hms(tokens[idx+2]) is not None): + # There is a space and then an "h", "m", or "s" label. + # e.g. the "12" in "12 h" + hms_idx = idx + 2 + + elif idx > 0 and info.hms(tokens[idx-1]) is not None: + # There is a "h", "m", or "s" preceding this token. Since neither + # of the previous cases was hit, there is no label following this + # token, so we use the previous label. + # e.g. the "04" in "12h04" + hms_idx = idx-1 + + elif (1 < idx == len_l-1 and tokens[idx-1] == ' ' and + info.hms(tokens[idx-2]) is not None): + # If we are looking at the final token, we allow for a + # backward-looking check to skip over a space. + # TODO: Are we sure this is the right condition here? + hms_idx = idx - 2 + + else: + hms_idx = None + + return hms_idx + + def _assign_hms(self, res, value_repr, hms): + # See GH issue #427, fixing float rounding + value = self._to_decimal(value_repr) + + if hms == 0: + # Hour + res.hour = int(value) + if value % 1: + res.minute = int(60*(value % 1)) + + elif hms == 1: + (res.minute, res.second) = self._parse_min_sec(value) + + elif hms == 2: + (res.second, res.microsecond) = self._parsems(value_repr) + + def _could_be_tzname(self, hour, tzname, tzoffset, token): + return (hour is not None and + tzname is None and + tzoffset is None and + len(token) <= 5 and + (all(x in string.ascii_uppercase for x in token) + or token in self.info.UTCZONE)) + + def _ampm_valid(self, hour, ampm, fuzzy): + """ + For fuzzy parsing, 'a' or 'am' (both valid English words) + may erroneously trigger the AM/PM flag. Deal with that + here. + """ + val_is_ampm = True + + # If there's already an AM/PM flag, this one isn't one. + if fuzzy and ampm is not None: + val_is_ampm = False + + # If AM/PM is found and hour is not, raise a ValueError + if hour is None: + if fuzzy: + val_is_ampm = False + else: + raise ValueError('No hour specified with AM or PM flag.') + elif not 0 <= hour <= 12: + # If AM/PM is found, it's a 12 hour clock, so raise + # an error for invalid range + if fuzzy: + val_is_ampm = False + else: + raise ValueError('Invalid hour specified for 12-hour clock.') + + return val_is_ampm + + def _adjust_ampm(self, hour, ampm): + if hour < 12 and ampm == 1: + hour += 12 + elif hour == 12 and ampm == 0: + hour = 0 + return hour + + def _parse_min_sec(self, value): + # TODO: Every usage of this function sets res.second to the return + # value. Are there any cases where second will be returned as None and + # we *don't* want to set res.second = None? + minute = int(value) + second = None + + sec_remainder = value % 1 + if sec_remainder: + second = int(60 * sec_remainder) + return (minute, second) + + def _parse_hms(self, idx, tokens, info, hms_idx): + # TODO: Is this going to admit a lot of false-positives for when we + # just happen to have digits and "h", "m" or "s" characters in non-date + # text? I guess hex hashes won't have that problem, but there's plenty + # of random junk out there. + if hms_idx is None: + hms = None + new_idx = idx + elif hms_idx > idx: + hms = info.hms(tokens[hms_idx]) + new_idx = hms_idx + else: + # Looking backwards, increment one. + hms = info.hms(tokens[hms_idx]) + 1 + new_idx = idx + + return (new_idx, hms) + + # ------------------------------------------------------------------ + # Handling for individual tokens. These are kept as methods instead + # of functions for the sake of customizability via subclassing. + + def _parsems(self, value): + """Parse a I[.F] seconds value into (seconds, microseconds).""" + if "." not in value: + return int(value), 0 + else: + i, f = value.split(".") + return int(i), int(f.ljust(6, "0")[:6]) + + def _to_decimal(self, val): + try: + decimal_value = Decimal(val) + # See GH 662, edge case, infinite value should not be converted + # via `_to_decimal` + if not decimal_value.is_finite(): + raise ValueError("Converted decimal value is infinite or NaN") + except Exception as e: + msg = "Could not convert %s to decimal" % val + six.raise_from(ValueError(msg), e) + else: + return decimal_value + + # ------------------------------------------------------------------ + # Post-Parsing construction of datetime output. These are kept as + # methods instead of functions for the sake of customizability via + # subclassing. + + def _build_tzinfo(self, tzinfos, tzname, tzoffset): + if callable(tzinfos): + tzdata = tzinfos(tzname, tzoffset) + else: + tzdata = tzinfos.get(tzname) + # handle case where tzinfo is paased an options that returns None + # eg tzinfos = {'BRST' : None} + if isinstance(tzdata, datetime.tzinfo) or tzdata is None: + tzinfo = tzdata + elif isinstance(tzdata, text_type): + tzinfo = tz.tzstr(tzdata) + elif isinstance(tzdata, integer_types): + tzinfo = tz.tzoffset(tzname, tzdata) + else: + raise TypeError("Offset must be tzinfo subclass, tz string, " + "or int offset.") + return tzinfo + + def _build_tzaware(self, naive, res, tzinfos): + if (callable(tzinfos) or (tzinfos and res.tzname in tzinfos)): + tzinfo = self._build_tzinfo(tzinfos, res.tzname, res.tzoffset) + aware = naive.replace(tzinfo=tzinfo) + aware = self._assign_tzname(aware, res.tzname) + + elif res.tzname and res.tzname in time.tzname: + aware = naive.replace(tzinfo=tz.tzlocal()) + + # Handle ambiguous local datetime + aware = self._assign_tzname(aware, res.tzname) + + # This is mostly relevant for winter GMT zones parsed in the UK + if (aware.tzname() != res.tzname and + res.tzname in self.info.UTCZONE): + aware = aware.replace(tzinfo=tz.UTC) + + elif res.tzoffset == 0: + aware = naive.replace(tzinfo=tz.UTC) + + elif res.tzoffset: + aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset)) + + elif not res.tzname and not res.tzoffset: + # i.e. no timezone information was found. + aware = naive + + elif res.tzname: + # tz-like string was parsed but we don't know what to do + # with it + warnings.warn("tzname {tzname} identified but not understood. " + "Pass `tzinfos` argument in order to correctly " + "return a timezone-aware datetime. In a future " + "version, this will raise an " + "exception.".format(tzname=res.tzname), + category=UnknownTimezoneWarning) + aware = naive + + return aware + + def _build_naive(self, res, default): + repl = {} + for attr in ("year", "month", "day", "hour", + "minute", "second", "microsecond"): + value = getattr(res, attr) + if value is not None: + repl[attr] = value + + if 'day' not in repl: + # If the default day exceeds the last day of the month, fall back + # to the end of the month. + cyear = default.year if res.year is None else res.year + cmonth = default.month if res.month is None else res.month + cday = default.day if res.day is None else res.day + + if cday > monthrange(cyear, cmonth)[1]: + repl['day'] = monthrange(cyear, cmonth)[1] + + naive = default.replace(**repl) + + if res.weekday is not None and not res.day: + naive = naive + relativedelta.relativedelta(weekday=res.weekday) + + return naive + + def _assign_tzname(self, dt, tzname): + if dt.tzname() != tzname: + new_dt = tz.enfold(dt, fold=1) + if new_dt.tzname() == tzname: + return new_dt + + return dt + + def _recombine_skipped(self, tokens, skipped_idxs): + """ + >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"] + >>> skipped_idxs = [0, 1, 2, 5] + >>> _recombine_skipped(tokens, skipped_idxs) + ["foo bar", "baz"] + """ + skipped_tokens = [] + for i, idx in enumerate(sorted(skipped_idxs)): + if i > 0 and idx - 1 == skipped_idxs[i - 1]: + skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx] + else: + skipped_tokens.append(tokens[idx]) + + return skipped_tokens + + +DEFAULTPARSER = parser() + + +def parse(timestr, parserinfo=None, **kwargs): + """ + + Parse a string in one of the supported formats, using the + ``parserinfo`` parameters. + + :param timestr: + A string containing a date/time stamp. + + :param parserinfo: + A :class:`parserinfo` object containing parameters for the parser. + If ``None``, the default arguments to the :class:`parserinfo` + constructor are used. + + The ``**kwargs`` parameter takes the following keyword arguments: + + :param default: + The default datetime object, if this is a datetime object and not + ``None``, elements specified in ``timestr`` replace elements in the + default object. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime` object is returned. + + :param tzinfos: + Additional time zone names / aliases which may be present in the + string. This argument maps time zone names (and optionally offsets + from those time zones) to time zones. This parameter can be a + dictionary with timezone aliases mapping time zone names to time + zones or a function taking two parameters (``tzname`` and + ``tzoffset``) and returning a time zone. + + The timezones to which the names are mapped can be an integer + offset from UTC in seconds or a :class:`tzinfo` object. + + .. doctest:: + :options: +NORMALIZE_WHITESPACE + + >>> from dateutil.parser import parse + >>> from dateutil.tz import gettz + >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")} + >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200)) + >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos) + datetime.datetime(2012, 1, 19, 17, 21, + tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago')) + + This parameter is ignored if ``ignoretz`` is set. + + :param dayfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the day (``True``) or month (``False``). If + ``yearfirst`` is set to ``True``, this distinguishes between YDM and + YMD. If set to ``None``, this value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param yearfirst: + Whether to interpret the first value in an ambiguous 3-integer date + (e.g. 01/05/09) as the year. If ``True``, the first number is taken to + be the year, otherwise the last number is taken to be the year. If + this is set to ``None``, the value is retrieved from the current + :class:`parserinfo` object (which itself defaults to ``False``). + + :param fuzzy: + Whether to allow fuzzy parsing, allowing for string like "Today is + January 1, 2047 at 8:21:00AM". + + :param fuzzy_with_tokens: + If ``True``, ``fuzzy`` is automatically set to True, and the parser + will return a tuple where the first element is the parsed + :class:`datetime.datetime` datetimestamp and the second element is + a tuple containing the portions of the string which were ignored: + + .. doctest:: + + >>> from dateutil.parser import parse + >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True) + (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at ')) + + :return: + Returns a :class:`datetime.datetime` object or, if the + ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the + first element being a :class:`datetime.datetime` object, the second + a tuple containing the fuzzy tokens. + + :raises ValueError: + Raised for invalid or unknown string format, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date + would be created. + + :raises OverflowError: + Raised if the parsed date exceeds the largest valid C integer on + your system. + """ + if parserinfo: + return parser(parserinfo).parse(timestr, **kwargs) + else: + return DEFAULTPARSER.parse(timestr, **kwargs) + + +class _tzparser(object): + + class _result(_resultbase): + + __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset", + "start", "end"] + + class _attr(_resultbase): + __slots__ = ["month", "week", "weekday", + "yday", "jyday", "day", "time"] + + def __repr__(self): + return self._repr("") + + def __init__(self): + _resultbase.__init__(self) + self.start = self._attr() + self.end = self._attr() + + def parse(self, tzstr): + res = self._result() + l = [x for x in re.split(r'([,:.]|[a-zA-Z]+|[0-9]+)',tzstr) if x] + used_idxs = list() + try: + + len_l = len(l) + + i = 0 + while i < len_l: + # BRST+3[BRDT[+2]] + j = i + while j < len_l and not [x for x in l[j] + if x in "0123456789:,-+"]: + j += 1 + if j != i: + if not res.stdabbr: + offattr = "stdoffset" + res.stdabbr = "".join(l[i:j]) + else: + offattr = "dstoffset" + res.dstabbr = "".join(l[i:j]) + + for ii in range(j): + used_idxs.append(ii) + i = j + if (i < len_l and (l[i] in ('+', '-') or l[i][0] in + "0123456789")): + if l[i] in ('+', '-'): + # Yes, that's right. See the TZ variable + # documentation. + signal = (1, -1)[l[i] == '+'] + used_idxs.append(i) + i += 1 + else: + signal = -1 + len_li = len(l[i]) + if len_li == 4: + # -0300 + setattr(res, offattr, (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) * signal) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + setattr(res, offattr, + (int(l[i]) * 3600 + + int(l[i + 2]) * 60) * signal) + used_idxs.append(i) + i += 2 + elif len_li <= 2: + # -[0]3 + setattr(res, offattr, + int(l[i][:2]) * 3600 * signal) + else: + return None + used_idxs.append(i) + i += 1 + if res.dstabbr: + break + else: + break + + + if i < len_l: + for j in range(i, len_l): + if l[j] == ';': + l[j] = ',' + + assert l[i] == ',' + + i += 1 + + if i >= len_l: + pass + elif (8 <= l.count(',') <= 9 and + not [y for x in l[i:] if x != ',' + for y in x if y not in "0123456789+-"]): + # GMT0BST,3,0,30,3600,10,0,26,7200[,3600] + for x in (res.start, res.end): + x.month = int(l[i]) + used_idxs.append(i) + i += 2 + if l[i] == '-': + value = int(l[i + 1]) * -1 + used_idxs.append(i) + i += 1 + else: + value = int(l[i]) + used_idxs.append(i) + i += 2 + if value: + x.week = value + x.weekday = (int(l[i]) - 1) % 7 + else: + x.day = int(l[i]) + used_idxs.append(i) + i += 2 + x.time = int(l[i]) + used_idxs.append(i) + i += 2 + if i < len_l: + if l[i] in ('-', '+'): + signal = (-1, 1)[l[i] == "+"] + used_idxs.append(i) + i += 1 + else: + signal = 1 + used_idxs.append(i) + res.dstoffset = (res.stdoffset + int(l[i]) * signal) + + # This was a made-up format that is not in normal use + warn(('Parsed time zone "%s"' % tzstr) + + 'is in a non-standard dateutil-specific format, which ' + + 'is now deprecated; support for parsing this format ' + + 'will be removed in future versions. It is recommended ' + + 'that you switch to a standard format like the GNU ' + + 'TZ variable format.', tz.DeprecatedTzFormatWarning) + elif (l.count(',') == 2 and l[i:].count('/') <= 2 and + not [y for x in l[i:] if x not in (',', '/', 'J', 'M', + '.', '-', ':') + for y in x if y not in "0123456789"]): + for x in (res.start, res.end): + if l[i] == 'J': + # non-leap year day (1 based) + used_idxs.append(i) + i += 1 + x.jyday = int(l[i]) + elif l[i] == 'M': + # month[-.]week[-.]weekday + used_idxs.append(i) + i += 1 + x.month = int(l[i]) + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.week = int(l[i]) + if x.week == 5: + x.week = -1 + used_idxs.append(i) + i += 1 + assert l[i] in ('-', '.') + used_idxs.append(i) + i += 1 + x.weekday = (int(l[i]) - 1) % 7 + else: + # year day (zero based) + x.yday = int(l[i]) + 1 + + used_idxs.append(i) + i += 1 + + if i < len_l and l[i] == '/': + used_idxs.append(i) + i += 1 + # start time + len_li = len(l[i]) + if len_li == 4: + # -0300 + x.time = (int(l[i][:2]) * 3600 + + int(l[i][2:]) * 60) + elif i + 1 < len_l and l[i + 1] == ':': + # -03:00 + x.time = int(l[i]) * 3600 + int(l[i + 2]) * 60 + used_idxs.append(i) + i += 2 + if i + 1 < len_l and l[i + 1] == ':': + used_idxs.append(i) + i += 2 + x.time += int(l[i]) + elif len_li <= 2: + # -[0]3 + x.time = (int(l[i][:2]) * 3600) + else: + return None + used_idxs.append(i) + i += 1 + + assert i == len_l or l[i] == ',' + + i += 1 + + assert i >= len_l + + except (IndexError, ValueError, AssertionError): + return None + + unused_idxs = set(range(len_l)).difference(used_idxs) + res.any_unused_tokens = not {l[n] for n in unused_idxs}.issubset({",",":"}) + return res + + +DEFAULTTZPARSER = _tzparser() + + +def _parsetz(tzstr): + return DEFAULTTZPARSER.parse(tzstr) + + +class ParserError(ValueError): + """Error class for representing failure to parse a datetime string.""" + def __str__(self): + try: + return self.args[0] % self.args[1:] + except (TypeError, IndexError): + return super(ParserError, self).__str__() + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, str(self)) + + +class UnknownTimezoneWarning(RuntimeWarning): + """Raised when the parser finds a timezone it cannot parse into a tzinfo""" +# vim:ts=4:sw=4:et diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py new file mode 100644 index 00000000..48f86a33 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +""" +This module offers a parser for ISO-8601 strings + +It is intended to support all valid date, time and datetime formats per the +ISO-8601 specification. + +..versionadded:: 2.7.0 +""" +from datetime import datetime, timedelta, time, date +import calendar +from dateutil import tz + +from functools import wraps + +import re +import six + +__all__ = ["isoparse", "isoparser"] + + +def _takes_ascii(f): + @wraps(f) + def func(self, str_in, *args, **kwargs): + # If it's a stream, read the whole thing + str_in = getattr(str_in, 'read', lambda: str_in)() + + # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII + if isinstance(str_in, six.text_type): + # ASCII is the same in UTF-8 + try: + str_in = str_in.encode('ascii') + except UnicodeEncodeError as e: + msg = 'ISO-8601 strings should contain only ASCII characters' + six.raise_from(ValueError(msg), e) + + return f(self, str_in, *args, **kwargs) + + return func + + +class isoparser(object): + def __init__(self, sep=None): + """ + :param sep: + A single character that separates date and time portions. If + ``None``, the parser will accept any single character. + For strict ISO-8601 adherence, pass ``'T'``. + """ + if sep is not None: + if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'): + raise ValueError('Separator must be a single, non-numeric ' + + 'ASCII character') + + sep = sep.encode('ascii') + + self._sep = sep + + @_takes_ascii + def isoparse(self, dt_str): + """ + Parse an ISO-8601 datetime string into a :class:`datetime.datetime`. + + An ISO-8601 datetime string consists of a date portion, followed + optionally by a time portion - the date and time portions are separated + by a single character separator, which is ``T`` in the official + standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be + combined with a time portion. + + Supported date formats are: + + Common: + + - ``YYYY`` + - ``YYYY-MM`` or ``YYYYMM`` + - ``YYYY-MM-DD`` or ``YYYYMMDD`` + + Uncommon: + + - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0) + - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day + + The ISO week and day numbering follows the same logic as + :func:`datetime.date.isocalendar`. + + Supported time formats are: + + - ``hh`` + - ``hh:mm`` or ``hhmm`` + - ``hh:mm:ss`` or ``hhmmss`` + - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits) + + Midnight is a special case for `hh`, as the standard supports both + 00:00 and 24:00 as a representation. The decimal separator can be + either a dot or a comma. + + + .. caution:: + + Support for fractional components other than seconds is part of the + ISO-8601 standard, but is not currently implemented in this parser. + + Supported time zone offset formats are: + + - `Z` (UTC) + - `±HH:MM` + - `±HHMM` + - `±HH` + + Offsets will be represented as :class:`dateutil.tz.tzoffset` objects, + with the exception of UTC, which will be represented as + :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such + as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`. + + :param dt_str: + A string or stream containing only an ISO-8601 datetime string + + :return: + Returns a :class:`datetime.datetime` representing the string. + Unspecified components default to their lowest value. + + .. warning:: + + As of version 2.7.0, the strictness of the parser should not be + considered a stable part of the contract. Any valid ISO-8601 string + that parses correctly with the default settings will continue to + parse correctly in future versions, but invalid strings that + currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not + guaranteed to continue failing in future versions if they encode + a valid date. + + .. versionadded:: 2.7.0 + """ + components, pos = self._parse_isodate(dt_str) + + if len(dt_str) > pos: + if self._sep is None or dt_str[pos:pos + 1] == self._sep: + components += self._parse_isotime(dt_str[pos + 1:]) + else: + raise ValueError('String contains unknown ISO components') + + if len(components) > 3 and components[3] == 24: + components[3] = 0 + return datetime(*components) + timedelta(days=1) + + return datetime(*components) + + @_takes_ascii + def parse_isodate(self, datestr): + """ + Parse the date portion of an ISO string. + + :param datestr: + The string portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.date` object + """ + components, pos = self._parse_isodate(datestr) + if pos < len(datestr): + raise ValueError('String contains unknown ISO ' + + 'components: {}'.format(datestr)) + return date(*components) + + @_takes_ascii + def parse_isotime(self, timestr): + """ + Parse the time portion of an ISO string. + + :param timestr: + The time portion of an ISO string, without a separator + + :return: + Returns a :class:`datetime.time` object + """ + components = self._parse_isotime(timestr) + if components[0] == 24: + components[0] = 0 + return time(*components) + + @_takes_ascii + def parse_tzstr(self, tzstr, zero_as_utc=True): + """ + Parse a valid ISO time zone string. + + See :func:`isoparser.isoparse` for details on supported formats. + + :param tzstr: + A string representing an ISO time zone offset + + :param zero_as_utc: + Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones + + :return: + Returns :class:`dateutil.tz.tzoffset` for offsets and + :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is + specified) offsets equivalent to UTC. + """ + return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc) + + # Constants + _DATE_SEP = b'-' + _TIME_SEP = b':' + _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)') + + def _parse_isodate(self, dt_str): + try: + return self._parse_isodate_common(dt_str) + except ValueError: + return self._parse_isodate_uncommon(dt_str) + + def _parse_isodate_common(self, dt_str): + len_str = len(dt_str) + components = [1, 1, 1] + + if len_str < 4: + raise ValueError('ISO string too short') + + # Year + components[0] = int(dt_str[0:4]) + pos = 4 + if pos >= len_str: + return components, pos + + has_sep = dt_str[pos:pos + 1] == self._DATE_SEP + if has_sep: + pos += 1 + + # Month + if len_str - pos < 2: + raise ValueError('Invalid common month') + + components[1] = int(dt_str[pos:pos + 2]) + pos += 2 + + if pos >= len_str: + if has_sep: + return components, pos + else: + raise ValueError('Invalid ISO format') + + if has_sep: + if dt_str[pos:pos + 1] != self._DATE_SEP: + raise ValueError('Invalid separator in ISO string') + pos += 1 + + # Day + if len_str - pos < 2: + raise ValueError('Invalid common day') + components[2] = int(dt_str[pos:pos + 2]) + return components, pos + 2 + + def _parse_isodate_uncommon(self, dt_str): + if len(dt_str) < 4: + raise ValueError('ISO string too short') + + # All ISO formats start with the year + year = int(dt_str[0:4]) + + has_sep = dt_str[4:5] == self._DATE_SEP + + pos = 4 + has_sep # Skip '-' if it's there + if dt_str[pos:pos + 1] == b'W': + # YYYY-?Www-?D? + pos += 1 + weekno = int(dt_str[pos:pos + 2]) + pos += 2 + + dayno = 1 + if len(dt_str) > pos: + if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep: + raise ValueError('Inconsistent use of dash separator') + + pos += has_sep + + dayno = int(dt_str[pos:pos + 1]) + pos += 1 + + base_date = self._calculate_weekdate(year, weekno, dayno) + else: + # YYYYDDD or YYYY-DDD + if len(dt_str) - pos < 3: + raise ValueError('Invalid ordinal day') + + ordinal_day = int(dt_str[pos:pos + 3]) + pos += 3 + + if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)): + raise ValueError('Invalid ordinal day' + + ' {} for year {}'.format(ordinal_day, year)) + + base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1) + + components = [base_date.year, base_date.month, base_date.day] + return components, pos + + def _calculate_weekdate(self, year, week, day): + """ + Calculate the day of corresponding to the ISO year-week-day calendar. + + This function is effectively the inverse of + :func:`datetime.date.isocalendar`. + + :param year: + The year in the ISO calendar + + :param week: + The week in the ISO calendar - range is [1, 53] + + :param day: + The day in the ISO calendar - range is [1 (MON), 7 (SUN)] + + :return: + Returns a :class:`datetime.date` + """ + if not 0 < week < 54: + raise ValueError('Invalid week: {}'.format(week)) + + if not 0 < day < 8: # Range is 1-7 + raise ValueError('Invalid weekday: {}'.format(day)) + + # Get week 1 for the specific year: + jan_4 = date(year, 1, 4) # Week 1 always has January 4th in it + week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1) + + # Now add the specific number of weeks and days to get what we want + week_offset = (week - 1) * 7 + (day - 1) + return week_1 + timedelta(days=week_offset) + + def _parse_isotime(self, timestr): + len_str = len(timestr) + components = [0, 0, 0, 0, None] + pos = 0 + comp = -1 + + if len(timestr) < 2: + raise ValueError('ISO time too short') + + has_sep = len_str >= 3 and timestr[2:3] == self._TIME_SEP + + while pos < len_str and comp < 5: + comp += 1 + + if timestr[pos:pos + 1] in b'-+Zz': + # Detect time zone boundary + components[-1] = self._parse_tzstr(timestr[pos:]) + pos = len_str + break + + if comp < 3: + # Hour, minute, second + components[comp] = int(timestr[pos:pos + 2]) + pos += 2 + if (has_sep and pos < len_str and + timestr[pos:pos + 1] == self._TIME_SEP): + pos += 1 + + if comp == 3: + # Fraction of a second + frac = self._FRACTION_REGEX.match(timestr[pos:]) + if not frac: + continue + + us_str = frac.group(1)[:6] # Truncate to microseconds + components[comp] = int(us_str) * 10**(6 - len(us_str)) + pos += len(frac.group()) + + if pos < len_str: + raise ValueError('Unused components in ISO string') + + if components[0] == 24: + # Standard supports 00:00 and 24:00 as representations of midnight + if any(component != 0 for component in components[1:4]): + raise ValueError('Hour may only be 24 at 24:00:00.000') + + return components + + def _parse_tzstr(self, tzstr, zero_as_utc=True): + if tzstr == b'Z' or tzstr == b'z': + return tz.UTC + + if len(tzstr) not in {3, 5, 6}: + raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters') + + if tzstr[0:1] == b'-': + mult = -1 + elif tzstr[0:1] == b'+': + mult = 1 + else: + raise ValueError('Time zone offset requires sign') + + hours = int(tzstr[1:3]) + if len(tzstr) == 3: + minutes = 0 + else: + minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):]) + + if zero_as_utc and hours == 0 and minutes == 0: + return tz.UTC + else: + if minutes > 59: + raise ValueError('Invalid minutes in time zone offset') + + if hours > 23: + raise ValueError('Invalid hours in time zone offset') + + return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60) + + +DEFAULT_ISOPARSER = isoparser() +isoparse = DEFAULT_ISOPARSER.isoparse diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/relativedelta.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/relativedelta.py new file mode 100644 index 00000000..a9e85f7e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/relativedelta.py @@ -0,0 +1,599 @@ +# -*- coding: utf-8 -*- +import datetime +import calendar + +import operator +from math import copysign + +from six import integer_types +from warnings import warn + +from ._common import weekday + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + +__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + + +class relativedelta(object): + """ + The relativedelta type is designed to be applied to an existing datetime and + can replace specific components of that datetime, or represents an interval + of time. + + It is based on the specification of the excellent work done by M.-A. Lemburg + in his + `mx.DateTime `_ extension. + However, notice that this type does *NOT* implement the same algorithm as + his work. Do *NOT* expect it to behave like mx.DateTime's counterpart. + + There are two different ways to build a relativedelta instance. The + first one is passing it two date/datetime classes:: + + relativedelta(datetime1, datetime2) + + The second one is passing it any number of the following keyword arguments:: + + relativedelta(arg1=x,arg2=y,arg3=z...) + + year, month, day, hour, minute, second, microsecond: + Absolute information (argument is singular); adding or subtracting a + relativedelta with absolute information does not perform an arithmetic + operation, but rather REPLACES the corresponding value in the + original datetime with the value(s) in relativedelta. + + years, months, weeks, days, hours, minutes, seconds, microseconds: + Relative information, may be negative (argument is plural); adding + or subtracting a relativedelta with relative information performs + the corresponding arithmetic operation on the original datetime value + with the information in the relativedelta. + + weekday: + One of the weekday instances (MO, TU, etc) available in the + relativedelta module. These instances may receive a parameter N, + specifying the Nth weekday, which could be positive or negative + (like MO(+1) or MO(-2)). Not specifying it is the same as specifying + +1. You can also use an integer, where 0=MO. This argument is always + relative e.g. if the calculated date is already Monday, using MO(1) + or MO(-1) won't change the day. To effectively make it absolute, use + it in combination with the day argument (e.g. day=1, MO(1) for first + Monday of the month). + + leapdays: + Will add given days to the date found, if year is a leap + year, and the date found is post 28 of february. + + yearday, nlyearday: + Set the yearday or the non-leap year day (jump leap days). + These are converted to day/month/leapdays information. + + There are relative and absolute forms of the keyword + arguments. The plural is relative, and the singular is + absolute. For each argument in the order below, the absolute form + is applied first (by setting each attribute to that value) and + then the relative form (by adding the value to the attribute). + + The order of attributes considered when this relativedelta is + added to a datetime is: + + 1. Year + 2. Month + 3. Day + 4. Hours + 5. Minutes + 6. Seconds + 7. Microseconds + + Finally, weekday is applied, using the rule described above. + + For example + + >>> from datetime import datetime + >>> from dateutil.relativedelta import relativedelta, MO + >>> dt = datetime(2018, 4, 9, 13, 37, 0) + >>> delta = relativedelta(hours=25, day=1, weekday=MO(1)) + >>> dt + delta + datetime.datetime(2018, 4, 2, 14, 37) + + First, the day is set to 1 (the first of the month), then 25 hours + are added, to get to the 2nd day and 14th hour, finally the + weekday is applied, but since the 2nd is already a Monday there is + no effect. + + """ + + def __init__(self, dt1=None, dt2=None, + years=0, months=0, days=0, leapdays=0, weeks=0, + hours=0, minutes=0, seconds=0, microseconds=0, + year=None, month=None, day=None, weekday=None, + yearday=None, nlyearday=None, + hour=None, minute=None, second=None, microsecond=None): + + if dt1 and dt2: + # datetime is a subclass of date. So both must be date + if not (isinstance(dt1, datetime.date) and + isinstance(dt2, datetime.date)): + raise TypeError("relativedelta only diffs datetime/date") + + # We allow two dates, or two datetimes, so we coerce them to be + # of the same type + if (isinstance(dt1, datetime.datetime) != + isinstance(dt2, datetime.datetime)): + if not isinstance(dt1, datetime.datetime): + dt1 = datetime.datetime.fromordinal(dt1.toordinal()) + elif not isinstance(dt2, datetime.datetime): + dt2 = datetime.datetime.fromordinal(dt2.toordinal()) + + self.years = 0 + self.months = 0 + self.days = 0 + self.leapdays = 0 + self.hours = 0 + self.minutes = 0 + self.seconds = 0 + self.microseconds = 0 + self.year = None + self.month = None + self.day = None + self.weekday = None + self.hour = None + self.minute = None + self.second = None + self.microsecond = None + self._has_time = 0 + + # Get year / month delta between the two + months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month) + self._set_months(months) + + # Remove the year/month delta so the timedelta is just well-defined + # time units (seconds, days and microseconds) + dtm = self.__radd__(dt2) + + # If we've overshot our target, make an adjustment + if dt1 < dt2: + compare = operator.gt + increment = 1 + else: + compare = operator.lt + increment = -1 + + while compare(dt1, dtm): + months += increment + self._set_months(months) + dtm = self.__radd__(dt2) + + # Get the timedelta between the "months-adjusted" date and dt1 + delta = dt1 - dtm + self.seconds = delta.seconds + delta.days * 86400 + self.microseconds = delta.microseconds + else: + # Check for non-integer values in integer-only quantities + if any(x is not None and x != int(x) for x in (years, months)): + raise ValueError("Non-integer years and months are " + "ambiguous and not currently supported.") + + # Relative information + self.years = int(years) + self.months = int(months) + self.days = days + weeks * 7 + self.leapdays = leapdays + self.hours = hours + self.minutes = minutes + self.seconds = seconds + self.microseconds = microseconds + + # Absolute information + self.year = year + self.month = month + self.day = day + self.hour = hour + self.minute = minute + self.second = second + self.microsecond = microsecond + + if any(x is not None and int(x) != x + for x in (year, month, day, hour, + minute, second, microsecond)): + # For now we'll deprecate floats - later it'll be an error. + warn("Non-integer value passed as absolute information. " + + "This is not a well-defined condition and will raise " + + "errors in future versions.", DeprecationWarning) + + if isinstance(weekday, integer_types): + self.weekday = weekdays[weekday] + else: + self.weekday = weekday + + yday = 0 + if nlyearday: + yday = nlyearday + elif yearday: + yday = yearday + if yearday > 59: + self.leapdays = -1 + if yday: + ydayidx = [31, 59, 90, 120, 151, 181, 212, + 243, 273, 304, 334, 366] + for idx, ydays in enumerate(ydayidx): + if yday <= ydays: + self.month = idx+1 + if idx == 0: + self.day = yday + else: + self.day = yday-ydayidx[idx-1] + break + else: + raise ValueError("invalid year day (%d)" % yday) + + self._fix() + + def _fix(self): + if abs(self.microseconds) > 999999: + s = _sign(self.microseconds) + div, mod = divmod(self.microseconds * s, 1000000) + self.microseconds = mod * s + self.seconds += div * s + if abs(self.seconds) > 59: + s = _sign(self.seconds) + div, mod = divmod(self.seconds * s, 60) + self.seconds = mod * s + self.minutes += div * s + if abs(self.minutes) > 59: + s = _sign(self.minutes) + div, mod = divmod(self.minutes * s, 60) + self.minutes = mod * s + self.hours += div * s + if abs(self.hours) > 23: + s = _sign(self.hours) + div, mod = divmod(self.hours * s, 24) + self.hours = mod * s + self.days += div * s + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years += div * s + if (self.hours or self.minutes or self.seconds or self.microseconds + or self.hour is not None or self.minute is not None or + self.second is not None or self.microsecond is not None): + self._has_time = 1 + else: + self._has_time = 0 + + @property + def weeks(self): + return int(self.days / 7.0) + + @weeks.setter + def weeks(self, value): + self.days = self.days - (self.weeks * 7) + value * 7 + + def _set_months(self, months): + self.months = months + if abs(self.months) > 11: + s = _sign(self.months) + div, mod = divmod(self.months * s, 12) + self.months = mod * s + self.years = div * s + else: + self.years = 0 + + def normalized(self): + """ + Return a version of this object represented entirely using integer + values for the relative attributes. + + >>> relativedelta(days=1.5, hours=2).normalized() + relativedelta(days=+1, hours=+14) + + :return: + Returns a :class:`dateutil.relativedelta.relativedelta` object. + """ + # Cascade remainders down (rounding each to roughly nearest microsecond) + days = int(self.days) + + hours_f = round(self.hours + 24 * (self.days - days), 11) + hours = int(hours_f) + + minutes_f = round(self.minutes + 60 * (hours_f - hours), 10) + minutes = int(minutes_f) + + seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8) + seconds = int(seconds_f) + + microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds)) + + # Constructor carries overflow back up with call to _fix() + return self.__class__(years=self.years, months=self.months, + days=days, hours=hours, minutes=minutes, + seconds=seconds, microseconds=microseconds, + leapdays=self.leapdays, year=self.year, + month=self.month, day=self.day, + weekday=self.weekday, hour=self.hour, + minute=self.minute, second=self.second, + microsecond=self.microsecond) + + def __add__(self, other): + if isinstance(other, relativedelta): + return self.__class__(years=other.years + self.years, + months=other.months + self.months, + days=other.days + self.days, + hours=other.hours + self.hours, + minutes=other.minutes + self.minutes, + seconds=other.seconds + self.seconds, + microseconds=(other.microseconds + + self.microseconds), + leapdays=other.leapdays or self.leapdays, + year=(other.year if other.year is not None + else self.year), + month=(other.month if other.month is not None + else self.month), + day=(other.day if other.day is not None + else self.day), + weekday=(other.weekday if other.weekday is not None + else self.weekday), + hour=(other.hour if other.hour is not None + else self.hour), + minute=(other.minute if other.minute is not None + else self.minute), + second=(other.second if other.second is not None + else self.second), + microsecond=(other.microsecond if other.microsecond + is not None else + self.microsecond)) + if isinstance(other, datetime.timedelta): + return self.__class__(years=self.years, + months=self.months, + days=self.days + other.days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds + other.seconds, + microseconds=self.microseconds + other.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + if not isinstance(other, datetime.date): + return NotImplemented + elif self._has_time and not isinstance(other, datetime.datetime): + other = datetime.datetime.fromordinal(other.toordinal()) + year = (self.year or other.year)+self.years + month = self.month or other.month + if self.months: + assert 1 <= abs(self.months) <= 12 + month += self.months + if month > 12: + year += 1 + month -= 12 + elif month < 1: + year -= 1 + month += 12 + day = min(calendar.monthrange(year, month)[1], + self.day or other.day) + repl = {"year": year, "month": month, "day": day} + for attr in ["hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + repl[attr] = value + days = self.days + if self.leapdays and month > 2 and calendar.isleap(year): + days += self.leapdays + ret = (other.replace(**repl) + + datetime.timedelta(days=days, + hours=self.hours, + minutes=self.minutes, + seconds=self.seconds, + microseconds=self.microseconds)) + if self.weekday: + weekday, nth = self.weekday.weekday, self.weekday.n or 1 + jumpdays = (abs(nth) - 1) * 7 + if nth > 0: + jumpdays += (7 - ret.weekday() + weekday) % 7 + else: + jumpdays += (ret.weekday() - weekday) % 7 + jumpdays *= -1 + ret += datetime.timedelta(days=jumpdays) + return ret + + def __radd__(self, other): + return self.__add__(other) + + def __rsub__(self, other): + return self.__neg__().__radd__(other) + + def __sub__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented # In case the other object defines __rsub__ + return self.__class__(years=self.years - other.years, + months=self.months - other.months, + days=self.days - other.days, + hours=self.hours - other.hours, + minutes=self.minutes - other.minutes, + seconds=self.seconds - other.seconds, + microseconds=self.microseconds - other.microseconds, + leapdays=self.leapdays or other.leapdays, + year=(self.year if self.year is not None + else other.year), + month=(self.month if self.month is not None else + other.month), + day=(self.day if self.day is not None else + other.day), + weekday=(self.weekday if self.weekday is not None else + other.weekday), + hour=(self.hour if self.hour is not None else + other.hour), + minute=(self.minute if self.minute is not None else + other.minute), + second=(self.second if self.second is not None else + other.second), + microsecond=(self.microsecond if self.microsecond + is not None else + other.microsecond)) + + def __abs__(self): + return self.__class__(years=abs(self.years), + months=abs(self.months), + days=abs(self.days), + hours=abs(self.hours), + minutes=abs(self.minutes), + seconds=abs(self.seconds), + microseconds=abs(self.microseconds), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __neg__(self): + return self.__class__(years=-self.years, + months=-self.months, + days=-self.days, + hours=-self.hours, + minutes=-self.minutes, + seconds=-self.seconds, + microseconds=-self.microseconds, + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + def __bool__(self): + return not (not self.years and + not self.months and + not self.days and + not self.hours and + not self.minutes and + not self.seconds and + not self.microseconds and + not self.leapdays and + self.year is None and + self.month is None and + self.day is None and + self.weekday is None and + self.hour is None and + self.minute is None and + self.second is None and + self.microsecond is None) + # Compatibility with Python 2.x + __nonzero__ = __bool__ + + def __mul__(self, other): + try: + f = float(other) + except TypeError: + return NotImplemented + + return self.__class__(years=int(self.years * f), + months=int(self.months * f), + days=int(self.days * f), + hours=int(self.hours * f), + minutes=int(self.minutes * f), + seconds=int(self.seconds * f), + microseconds=int(self.microseconds * f), + leapdays=self.leapdays, + year=self.year, + month=self.month, + day=self.day, + weekday=self.weekday, + hour=self.hour, + minute=self.minute, + second=self.second, + microsecond=self.microsecond) + + __rmul__ = __mul__ + + def __eq__(self, other): + if not isinstance(other, relativedelta): + return NotImplemented + if self.weekday or other.weekday: + if not self.weekday or not other.weekday: + return False + if self.weekday.weekday != other.weekday.weekday: + return False + n1, n2 = self.weekday.n, other.weekday.n + if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)): + return False + return (self.years == other.years and + self.months == other.months and + self.days == other.days and + self.hours == other.hours and + self.minutes == other.minutes and + self.seconds == other.seconds and + self.microseconds == other.microseconds and + self.leapdays == other.leapdays and + self.year == other.year and + self.month == other.month and + self.day == other.day and + self.hour == other.hour and + self.minute == other.minute and + self.second == other.second and + self.microsecond == other.microsecond) + + def __hash__(self): + return hash(( + self.weekday, + self.years, + self.months, + self.days, + self.hours, + self.minutes, + self.seconds, + self.microseconds, + self.leapdays, + self.year, + self.month, + self.day, + self.hour, + self.minute, + self.second, + self.microsecond, + )) + + def __ne__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + try: + reciprocal = 1 / float(other) + except TypeError: + return NotImplemented + + return self.__mul__(reciprocal) + + __truediv__ = __div__ + + def __repr__(self): + l = [] + for attr in ["years", "months", "days", "leapdays", + "hours", "minutes", "seconds", "microseconds"]: + value = getattr(self, attr) + if value: + l.append("{attr}={value:+g}".format(attr=attr, value=value)) + for attr in ["year", "month", "day", "weekday", + "hour", "minute", "second", "microsecond"]: + value = getattr(self, attr) + if value is not None: + l.append("{attr}={value}".format(attr=attr, value=repr(value))) + return "{classname}({attrs})".format(classname=self.__class__.__name__, + attrs=", ".join(l)) + + +def _sign(x): + return int(copysign(1, x)) + +# vim:ts=4:sw=4:et diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/rrule.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/rrule.py new file mode 100644 index 00000000..6bf0ea9c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/rrule.py @@ -0,0 +1,1735 @@ +# -*- coding: utf-8 -*- +""" +The rrule module offers a small, complete, and very fast, implementation of +the recurrence rules documented in the +`iCalendar RFC `_, +including support for caching of results. +""" +import itertools +import datetime +import calendar +import re +import sys + +try: + from math import gcd +except ImportError: + from fractions import gcd + +from six import advance_iterator, integer_types +from six.moves import _thread, range +import heapq + +from ._common import weekday as weekdaybase + +# For warning about deprecation of until and count +from warnings import warn + +__all__ = ["rrule", "rruleset", "rrulestr", + "YEARLY", "MONTHLY", "WEEKLY", "DAILY", + "HOURLY", "MINUTELY", "SECONDLY", + "MO", "TU", "WE", "TH", "FR", "SA", "SU"] + +# Every mask is 7 days longer to handle cross-year weekly periods. +M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 + + [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7) +M365MASK = list(M366MASK) +M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32)) +MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +MDAY365MASK = list(MDAY366MASK) +M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0)) +NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7]) +NMDAY365MASK = list(NMDAY366MASK) +M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366) +M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365) +WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55 +del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31] +MDAY365MASK = tuple(MDAY365MASK) +M365MASK = tuple(M365MASK) + +FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY'] + +(YEARLY, + MONTHLY, + WEEKLY, + DAILY, + HOURLY, + MINUTELY, + SECONDLY) = list(range(7)) + +# Imported on demand. +easter = None +parser = None + + +class weekday(weekdaybase): + """ + This version of weekday does not allow n = 0. + """ + def __init__(self, wkday, n=None): + if n == 0: + raise ValueError("Can't create weekday with n==0") + + super(weekday, self).__init__(wkday, n) + + +MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7)) + + +def _invalidates_cache(f): + """ + Decorator for rruleset methods which may invalidate the + cached length. + """ + def inner_func(self, *args, **kwargs): + rv = f(self, *args, **kwargs) + self._invalidate_cache() + return rv + + return inner_func + + +class rrulebase(object): + def __init__(self, cache=False): + if cache: + self._cache = [] + self._cache_lock = _thread.allocate_lock() + self._invalidate_cache() + else: + self._cache = None + self._cache_complete = False + self._len = None + + def __iter__(self): + if self._cache_complete: + return iter(self._cache) + elif self._cache is None: + return self._iter() + else: + return self._iter_cached() + + def _invalidate_cache(self): + if self._cache is not None: + self._cache = [] + self._cache_complete = False + self._cache_gen = self._iter() + + if self._cache_lock.locked(): + self._cache_lock.release() + + self._len = None + + def _iter_cached(self): + i = 0 + gen = self._cache_gen + cache = self._cache + acquire = self._cache_lock.acquire + release = self._cache_lock.release + while gen: + if i == len(cache): + acquire() + if self._cache_complete: + break + try: + for j in range(10): + cache.append(advance_iterator(gen)) + except StopIteration: + self._cache_gen = gen = None + self._cache_complete = True + break + release() + yield cache[i] + i += 1 + while i < self._len: + yield cache[i] + i += 1 + + def __getitem__(self, item): + if self._cache_complete: + return self._cache[item] + elif isinstance(item, slice): + if item.step and item.step < 0: + return list(iter(self))[item] + else: + return list(itertools.islice(self, + item.start or 0, + item.stop or sys.maxsize, + item.step or 1)) + elif item >= 0: + gen = iter(self) + try: + for i in range(item+1): + res = advance_iterator(gen) + except StopIteration: + raise IndexError + return res + else: + return list(iter(self))[item] + + def __contains__(self, item): + if self._cache_complete: + return item in self._cache + else: + for i in self: + if i == item: + return True + elif i > item: + return False + return False + + # __len__() introduces a large performance penalty. + def count(self): + """ Returns the number of recurrences in this set. It will have go + trough the whole recurrence, if this hasn't been done before. """ + if self._len is None: + for x in self: + pass + return self._len + + def before(self, dt, inc=False): + """ Returns the last recurrence before the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + last = None + if inc: + for i in gen: + if i > dt: + break + last = i + else: + for i in gen: + if i >= dt: + break + last = i + return last + + def after(self, dt, inc=False): + """ Returns the first recurrence after the given datetime instance. The + inc keyword defines what happens if dt is an occurrence. With + inc=True, if dt itself is an occurrence, it will be returned. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + if inc: + for i in gen: + if i >= dt: + return i + else: + for i in gen: + if i > dt: + return i + return None + + def xafter(self, dt, count=None, inc=False): + """ + Generator which yields up to `count` recurrences after the given + datetime instance, equivalent to `after`. + + :param dt: + The datetime at which to start generating recurrences. + + :param count: + The maximum number of recurrences to generate. If `None` (default), + dates are generated until the recurrence rule is exhausted. + + :param inc: + If `dt` is an instance of the rule and `inc` is `True`, it is + included in the output. + + :yields: Yields a sequence of `datetime` objects. + """ + + if self._cache_complete: + gen = self._cache + else: + gen = self + + # Select the comparison function + if inc: + comp = lambda dc, dtc: dc >= dtc + else: + comp = lambda dc, dtc: dc > dtc + + # Generate dates + n = 0 + for d in gen: + if comp(d, dt): + if count is not None: + n += 1 + if n > count: + break + + yield d + + def between(self, after, before, inc=False, count=1): + """ Returns all the occurrences of the rrule between after and before. + The inc keyword defines what happens if after and/or before are + themselves occurrences. With inc=True, they will be included in the + list, if they are found in the recurrence set. """ + if self._cache_complete: + gen = self._cache + else: + gen = self + started = False + l = [] + if inc: + for i in gen: + if i > before: + break + elif not started: + if i >= after: + started = True + l.append(i) + else: + l.append(i) + else: + for i in gen: + if i >= before: + break + elif not started: + if i > after: + started = True + l.append(i) + else: + l.append(i) + return l + + +class rrule(rrulebase): + """ + That's the base of the rrule operation. It accepts all the keywords + defined in the RFC as its constructor parameters (except byday, + which was renamed to byweekday) and more. The constructor prototype is:: + + rrule(freq) + + Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, + or SECONDLY. + + .. note:: + Per RFC section 3.3.10, recurrence instances falling on invalid dates + and times are ignored rather than coerced: + + Recurrence rules may generate recurrence instances with an invalid + date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM + on a day where the local time is moved forward by an hour at 1:00 + AM). Such recurrence instances MUST be ignored and MUST NOT be + counted as part of the recurrence set. + + This can lead to possibly surprising behavior when, for example, the + start date occurs at the end of the month: + + >>> from dateutil.rrule import rrule, MONTHLY + >>> from datetime import datetime + >>> start_date = datetime(2014, 12, 31) + >>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date)) + ... # doctest: +NORMALIZE_WHITESPACE + [datetime.datetime(2014, 12, 31, 0, 0), + datetime.datetime(2015, 1, 31, 0, 0), + datetime.datetime(2015, 3, 31, 0, 0), + datetime.datetime(2015, 5, 31, 0, 0)] + + Additionally, it supports the following keyword arguments: + + :param dtstart: + The recurrence start. Besides being the base for the recurrence, + missing parameters in the final recurrence instances will also be + extracted from this date. If not given, datetime.now() will be used + instead. + :param interval: + The interval between each freq iteration. For example, when using + YEARLY, an interval of 2 means once every two years, but with HOURLY, + it means once every two hours. The default interval is 1. + :param wkst: + The week start day. Must be one of the MO, TU, WE constants, or an + integer, specifying the first day of the week. This will affect + recurrences based on weekly periods. The default week start is got + from calendar.firstweekday(), and may be modified by + calendar.setfirstweekday(). + :param count: + If given, this determines how many occurrences will be generated. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param until: + If given, this must be a datetime instance specifying the upper-bound + limit of the recurrence. The last recurrence in the rule is the greatest + datetime that is less than or equal to the value specified in the + ``until`` parameter. + + .. note:: + As of version 2.5.0, the use of the keyword ``until`` in conjunction + with ``count`` is deprecated, to make sure ``dateutil`` is fully + compliant with `RFC-5545 Sec. 3.3.10 `_. Therefore, ``until`` and ``count`` + **must not** occur in the same call to ``rrule``. + :param bysetpos: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each given integer will specify an occurrence + number, corresponding to the nth occurrence of the rule inside the + frequency period. For example, a bysetpos of -1 if combined with a + MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will + result in the last work day of every month. + :param bymonth: + If given, it must be either an integer, or a sequence of integers, + meaning the months to apply the recurrence to. + :param bymonthday: + If given, it must be either an integer, or a sequence of integers, + meaning the month days to apply the recurrence to. + :param byyearday: + If given, it must be either an integer, or a sequence of integers, + meaning the year days to apply the recurrence to. + :param byeaster: + If given, it must be either an integer, or a sequence of integers, + positive or negative. Each integer will define an offset from the + Easter Sunday. Passing the offset 0 to byeaster will yield the Easter + Sunday itself. This is an extension to the RFC specification. + :param byweekno: + If given, it must be either an integer, or a sequence of integers, + meaning the week numbers to apply the recurrence to. Week numbers + have the meaning described in ISO8601, that is, the first week of + the year is that containing at least four days of the new year. + :param byweekday: + If given, it must be either an integer (0 == MO), a sequence of + integers, one of the weekday constants (MO, TU, etc), or a sequence + of these constants. When given, these variables will define the + weekdays where the recurrence will be applied. It's also possible to + use an argument n for the weekday instances, which will mean the nth + occurrence of this weekday in the period. For example, with MONTHLY, + or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the + first friday of the month where the recurrence happens. Notice that in + the RFC documentation, this is specified as BYDAY, but was renamed to + avoid the ambiguity of that keyword. + :param byhour: + If given, it must be either an integer, or a sequence of integers, + meaning the hours to apply the recurrence to. + :param byminute: + If given, it must be either an integer, or a sequence of integers, + meaning the minutes to apply the recurrence to. + :param bysecond: + If given, it must be either an integer, or a sequence of integers, + meaning the seconds to apply the recurrence to. + :param cache: + If given, it must be a boolean value specifying to enable or disable + caching of results. If you will use the same rrule instance multiple + times, enabling caching will improve the performance considerably. + """ + def __init__(self, freq, dtstart=None, + interval=1, wkst=None, count=None, until=None, bysetpos=None, + bymonth=None, bymonthday=None, byyearday=None, byeaster=None, + byweekno=None, byweekday=None, + byhour=None, byminute=None, bysecond=None, + cache=False): + super(rrule, self).__init__(cache) + global easter + if not dtstart: + if until and until.tzinfo: + dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0) + else: + dtstart = datetime.datetime.now().replace(microsecond=0) + elif not isinstance(dtstart, datetime.datetime): + dtstart = datetime.datetime.fromordinal(dtstart.toordinal()) + else: + dtstart = dtstart.replace(microsecond=0) + self._dtstart = dtstart + self._tzinfo = dtstart.tzinfo + self._freq = freq + self._interval = interval + self._count = count + + # Cache the original byxxx rules, if they are provided, as the _byxxx + # attributes do not necessarily map to the inputs, and this can be + # a problem in generating the strings. Only store things if they've + # been supplied (the string retrieval will just use .get()) + self._original_rule = {} + + if until and not isinstance(until, datetime.datetime): + until = datetime.datetime.fromordinal(until.toordinal()) + self._until = until + + if self._dtstart and self._until: + if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None): + # According to RFC5545 Section 3.3.10: + # https://tools.ietf.org/html/rfc5545#section-3.3.10 + # + # > If the "DTSTART" property is specified as a date with UTC + # > time or a date with local time and time zone reference, + # > then the UNTIL rule part MUST be specified as a date with + # > UTC time. + raise ValueError( + 'RRULE UNTIL values must be specified in UTC when DTSTART ' + 'is timezone-aware' + ) + + if count is not None and until: + warn("Using both 'count' and 'until' is inconsistent with RFC 5545" + " and has been deprecated in dateutil. Future versions will " + "raise an error.", DeprecationWarning) + + if wkst is None: + self._wkst = calendar.firstweekday() + elif isinstance(wkst, integer_types): + self._wkst = wkst + else: + self._wkst = wkst.weekday + + if bysetpos is None: + self._bysetpos = None + elif isinstance(bysetpos, integer_types): + if bysetpos == 0 or not (-366 <= bysetpos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + self._bysetpos = (bysetpos,) + else: + self._bysetpos = tuple(bysetpos) + for pos in self._bysetpos: + if pos == 0 or not (-366 <= pos <= 366): + raise ValueError("bysetpos must be between 1 and 366, " + "or between -366 and -1") + + if self._bysetpos: + self._original_rule['bysetpos'] = self._bysetpos + + if (byweekno is None and byyearday is None and bymonthday is None and + byweekday is None and byeaster is None): + if freq == YEARLY: + if bymonth is None: + bymonth = dtstart.month + self._original_rule['bymonth'] = None + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == MONTHLY: + bymonthday = dtstart.day + self._original_rule['bymonthday'] = None + elif freq == WEEKLY: + byweekday = dtstart.weekday() + self._original_rule['byweekday'] = None + + # bymonth + if bymonth is None: + self._bymonth = None + else: + if isinstance(bymonth, integer_types): + bymonth = (bymonth,) + + self._bymonth = tuple(sorted(set(bymonth))) + + if 'bymonth' not in self._original_rule: + self._original_rule['bymonth'] = self._bymonth + + # byyearday + if byyearday is None: + self._byyearday = None + else: + if isinstance(byyearday, integer_types): + byyearday = (byyearday,) + + self._byyearday = tuple(sorted(set(byyearday))) + self._original_rule['byyearday'] = self._byyearday + + # byeaster + if byeaster is not None: + if not easter: + from dateutil import easter + if isinstance(byeaster, integer_types): + self._byeaster = (byeaster,) + else: + self._byeaster = tuple(sorted(byeaster)) + + self._original_rule['byeaster'] = self._byeaster + else: + self._byeaster = None + + # bymonthday + if bymonthday is None: + self._bymonthday = () + self._bynmonthday = () + else: + if isinstance(bymonthday, integer_types): + bymonthday = (bymonthday,) + + bymonthday = set(bymonthday) # Ensure it's unique + + self._bymonthday = tuple(sorted(x for x in bymonthday if x > 0)) + self._bynmonthday = tuple(sorted(x for x in bymonthday if x < 0)) + + # Storing positive numbers first, then negative numbers + if 'bymonthday' not in self._original_rule: + self._original_rule['bymonthday'] = tuple( + itertools.chain(self._bymonthday, self._bynmonthday)) + + # byweekno + if byweekno is None: + self._byweekno = None + else: + if isinstance(byweekno, integer_types): + byweekno = (byweekno,) + + self._byweekno = tuple(sorted(set(byweekno))) + + self._original_rule['byweekno'] = self._byweekno + + # byweekday / bynweekday + if byweekday is None: + self._byweekday = None + self._bynweekday = None + else: + # If it's one of the valid non-sequence types, convert to a + # single-element sequence before the iterator that builds the + # byweekday set. + if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"): + byweekday = (byweekday,) + + self._byweekday = set() + self._bynweekday = set() + for wday in byweekday: + if isinstance(wday, integer_types): + self._byweekday.add(wday) + elif not wday.n or freq > MONTHLY: + self._byweekday.add(wday.weekday) + else: + self._bynweekday.add((wday.weekday, wday.n)) + + if not self._byweekday: + self._byweekday = None + elif not self._bynweekday: + self._bynweekday = None + + if self._byweekday is not None: + self._byweekday = tuple(sorted(self._byweekday)) + orig_byweekday = [weekday(x) for x in self._byweekday] + else: + orig_byweekday = () + + if self._bynweekday is not None: + self._bynweekday = tuple(sorted(self._bynweekday)) + orig_bynweekday = [weekday(*x) for x in self._bynweekday] + else: + orig_bynweekday = () + + if 'byweekday' not in self._original_rule: + self._original_rule['byweekday'] = tuple(itertools.chain( + orig_byweekday, orig_bynweekday)) + + # byhour + if byhour is None: + if freq < HOURLY: + self._byhour = {dtstart.hour} + else: + self._byhour = None + else: + if isinstance(byhour, integer_types): + byhour = (byhour,) + + if freq == HOURLY: + self._byhour = self.__construct_byset(start=dtstart.hour, + byxxx=byhour, + base=24) + else: + self._byhour = set(byhour) + + self._byhour = tuple(sorted(self._byhour)) + self._original_rule['byhour'] = self._byhour + + # byminute + if byminute is None: + if freq < MINUTELY: + self._byminute = {dtstart.minute} + else: + self._byminute = None + else: + if isinstance(byminute, integer_types): + byminute = (byminute,) + + if freq == MINUTELY: + self._byminute = self.__construct_byset(start=dtstart.minute, + byxxx=byminute, + base=60) + else: + self._byminute = set(byminute) + + self._byminute = tuple(sorted(self._byminute)) + self._original_rule['byminute'] = self._byminute + + # bysecond + if bysecond is None: + if freq < SECONDLY: + self._bysecond = ((dtstart.second,)) + else: + self._bysecond = None + else: + if isinstance(bysecond, integer_types): + bysecond = (bysecond,) + + self._bysecond = set(bysecond) + + if freq == SECONDLY: + self._bysecond = self.__construct_byset(start=dtstart.second, + byxxx=bysecond, + base=60) + else: + self._bysecond = set(bysecond) + + self._bysecond = tuple(sorted(self._bysecond)) + self._original_rule['bysecond'] = self._bysecond + + if self._freq >= HOURLY: + self._timeset = None + else: + self._timeset = [] + for hour in self._byhour: + for minute in self._byminute: + for second in self._bysecond: + self._timeset.append( + datetime.time(hour, minute, second, + tzinfo=self._tzinfo)) + self._timeset.sort() + self._timeset = tuple(self._timeset) + + def __str__(self): + """ + Output a string that would generate this RRULE if passed to rrulestr. + This is mostly compatible with RFC5545, except for the + dateutil-specific extension BYEASTER. + """ + + output = [] + h, m, s = [None] * 3 + if self._dtstart: + output.append(self._dtstart.strftime('DTSTART:%Y%m%dT%H%M%S')) + h, m, s = self._dtstart.timetuple()[3:6] + + parts = ['FREQ=' + FREQNAMES[self._freq]] + if self._interval != 1: + parts.append('INTERVAL=' + str(self._interval)) + + if self._wkst: + parts.append('WKST=' + repr(weekday(self._wkst))[0:2]) + + if self._count is not None: + parts.append('COUNT=' + str(self._count)) + + if self._until: + parts.append(self._until.strftime('UNTIL=%Y%m%dT%H%M%S')) + + if self._original_rule.get('byweekday') is not None: + # The str() method on weekday objects doesn't generate + # RFC5545-compliant strings, so we should modify that. + original_rule = dict(self._original_rule) + wday_strings = [] + for wday in original_rule['byweekday']: + if wday.n: + wday_strings.append('{n:+d}{wday}'.format( + n=wday.n, + wday=repr(wday)[0:2])) + else: + wday_strings.append(repr(wday)) + + original_rule['byweekday'] = wday_strings + else: + original_rule = self._original_rule + + partfmt = '{name}={vals}' + for name, key in [('BYSETPOS', 'bysetpos'), + ('BYMONTH', 'bymonth'), + ('BYMONTHDAY', 'bymonthday'), + ('BYYEARDAY', 'byyearday'), + ('BYWEEKNO', 'byweekno'), + ('BYDAY', 'byweekday'), + ('BYHOUR', 'byhour'), + ('BYMINUTE', 'byminute'), + ('BYSECOND', 'bysecond'), + ('BYEASTER', 'byeaster')]: + value = original_rule.get(key) + if value: + parts.append(partfmt.format(name=name, vals=(','.join(str(v) + for v in value)))) + + output.append('RRULE:' + ';'.join(parts)) + return '\n'.join(output) + + def replace(self, **kwargs): + """Return new rrule with same attributes except for those attributes given new + values by whichever keyword arguments are specified.""" + new_kwargs = {"interval": self._interval, + "count": self._count, + "dtstart": self._dtstart, + "freq": self._freq, + "until": self._until, + "wkst": self._wkst, + "cache": False if self._cache is None else True } + new_kwargs.update(self._original_rule) + new_kwargs.update(kwargs) + return rrule(**new_kwargs) + + def _iter(self): + year, month, day, hour, minute, second, weekday, yearday, _ = \ + self._dtstart.timetuple() + + # Some local variables to speed things up a bit + freq = self._freq + interval = self._interval + wkst = self._wkst + until = self._until + bymonth = self._bymonth + byweekno = self._byweekno + byyearday = self._byyearday + byweekday = self._byweekday + byeaster = self._byeaster + bymonthday = self._bymonthday + bynmonthday = self._bynmonthday + bysetpos = self._bysetpos + byhour = self._byhour + byminute = self._byminute + bysecond = self._bysecond + + ii = _iterinfo(self) + ii.rebuild(year, month) + + getdayset = {YEARLY: ii.ydayset, + MONTHLY: ii.mdayset, + WEEKLY: ii.wdayset, + DAILY: ii.ddayset, + HOURLY: ii.ddayset, + MINUTELY: ii.ddayset, + SECONDLY: ii.ddayset}[freq] + + if freq < HOURLY: + timeset = self._timeset + else: + gettimeset = {HOURLY: ii.htimeset, + MINUTELY: ii.mtimeset, + SECONDLY: ii.stimeset}[freq] + if ((freq >= HOURLY and + self._byhour and hour not in self._byhour) or + (freq >= MINUTELY and + self._byminute and minute not in self._byminute) or + (freq >= SECONDLY and + self._bysecond and second not in self._bysecond)): + timeset = () + else: + timeset = gettimeset(hour, minute, second) + + total = 0 + count = self._count + while True: + # Get dayset with the right frequency + dayset, start, end = getdayset(year, month, day) + + # Do the "hard" work ;-) + filtered = False + for i in dayset[start:end]: + if ((bymonth and ii.mmask[i] not in bymonth) or + (byweekno and not ii.wnomask[i]) or + (byweekday and ii.wdaymask[i] not in byweekday) or + (ii.nwdaymask and not ii.nwdaymask[i]) or + (byeaster and not ii.eastermask[i]) or + ((bymonthday or bynmonthday) and + ii.mdaymask[i] not in bymonthday and + ii.nmdaymask[i] not in bynmonthday) or + (byyearday and + ((i < ii.yearlen and i+1 not in byyearday and + -ii.yearlen+i not in byyearday) or + (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and + -ii.nextyearlen+i-ii.yearlen not in byyearday)))): + dayset[i] = None + filtered = True + + # Output results + if bysetpos and timeset: + poslist = [] + for pos in bysetpos: + if pos < 0: + daypos, timepos = divmod(pos, len(timeset)) + else: + daypos, timepos = divmod(pos-1, len(timeset)) + try: + i = [x for x in dayset[start:end] + if x is not None][daypos] + time = timeset[timepos] + except IndexError: + pass + else: + date = datetime.date.fromordinal(ii.yearordinal+i) + res = datetime.datetime.combine(date, time) + if res not in poslist: + poslist.append(res) + poslist.sort() + for res in poslist: + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + total += 1 + yield res + else: + for i in dayset[start:end]: + if i is not None: + date = datetime.date.fromordinal(ii.yearordinal + i) + for time in timeset: + res = datetime.datetime.combine(date, time) + if until and res > until: + self._len = total + return + elif res >= self._dtstart: + if count is not None: + count -= 1 + if count < 0: + self._len = total + return + + total += 1 + yield res + + # Handle frequency and interval + fixday = False + if freq == YEARLY: + year += interval + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == MONTHLY: + month += interval + if month > 12: + div, mod = divmod(month, 12) + month = mod + year += div + if month == 0: + month = 12 + year -= 1 + if year > datetime.MAXYEAR: + self._len = total + return + ii.rebuild(year, month) + elif freq == WEEKLY: + if wkst > weekday: + day += -(weekday+1+(6-wkst))+self._interval*7 + else: + day += -(weekday-wkst)+self._interval*7 + weekday = wkst + fixday = True + elif freq == DAILY: + day += interval + fixday = True + elif freq == HOURLY: + if filtered: + # Jump to one iteration before next day + hour += ((23-hour)//interval)*interval + + if byhour: + ndays, hour = self.__mod_distance(value=hour, + byxxx=self._byhour, + base=24) + else: + ndays, hour = divmod(hour+interval, 24) + + if ndays: + day += ndays + fixday = True + + timeset = gettimeset(hour, minute, second) + elif freq == MINUTELY: + if filtered: + # Jump to one iteration before next day + minute += ((1439-(hour*60+minute))//interval)*interval + + valid = False + rep_rate = (24*60) + for j in range(rep_rate // gcd(interval, rep_rate)): + if byminute: + nhours, minute = \ + self.__mod_distance(value=minute, + byxxx=self._byminute, + base=60) + else: + nhours, minute = divmod(minute+interval, 60) + + div, hour = divmod(hour+nhours, 24) + if div: + day += div + fixday = True + filtered = False + + if not byhour or hour in byhour: + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval and ' + + 'byhour resulting in empty rule.') + + timeset = gettimeset(hour, minute, second) + elif freq == SECONDLY: + if filtered: + # Jump to one iteration before next day + second += (((86399 - (hour * 3600 + minute * 60 + second)) + // interval) * interval) + + rep_rate = (24 * 3600) + valid = False + for j in range(0, rep_rate // gcd(interval, rep_rate)): + if bysecond: + nminutes, second = \ + self.__mod_distance(value=second, + byxxx=self._bysecond, + base=60) + else: + nminutes, second = divmod(second+interval, 60) + + div, minute = divmod(minute+nminutes, 60) + if div: + hour += div + div, hour = divmod(hour, 24) + if div: + day += div + fixday = True + + if ((not byhour or hour in byhour) and + (not byminute or minute in byminute) and + (not bysecond or second in bysecond)): + valid = True + break + + if not valid: + raise ValueError('Invalid combination of interval, ' + + 'byhour and byminute resulting in empty' + + ' rule.') + + timeset = gettimeset(hour, minute, second) + + if fixday and day > 28: + daysinmonth = calendar.monthrange(year, month)[1] + if day > daysinmonth: + while day > daysinmonth: + day -= daysinmonth + month += 1 + if month == 13: + month = 1 + year += 1 + if year > datetime.MAXYEAR: + self._len = total + return + daysinmonth = calendar.monthrange(year, month)[1] + ii.rebuild(year, month) + + def __construct_byset(self, start, byxxx, base): + """ + If a `BYXXX` sequence is passed to the constructor at the same level as + `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some + specifications which cannot be reached given some starting conditions. + + This occurs whenever the interval is not coprime with the base of a + given unit and the difference between the starting position and the + ending position is not coprime with the greatest common denominator + between the interval and the base. For example, with a FREQ of hourly + starting at 17:00 and an interval of 4, the only valid values for + BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not + coprime. + + :param start: + Specifies the starting position. + :param byxxx: + An iterable containing the list of allowed values. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + This does not preserve the type of the iterable, returning a set, since + the values should be unique and the order is irrelevant, this will + speed up later lookups. + + In the event of an empty set, raises a :exception:`ValueError`, as this + results in an empty rrule. + """ + + cset = set() + + # Support a single byxxx value. + if isinstance(byxxx, integer_types): + byxxx = (byxxx, ) + + for num in byxxx: + i_gcd = gcd(self._interval, base) + # Use divmod rather than % because we need to wrap negative nums. + if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0: + cset.add(num) + + if len(cset) == 0: + raise ValueError("Invalid rrule byxxx generates an empty set.") + + return cset + + def __mod_distance(self, value, byxxx, base): + """ + Calculates the next value in a sequence where the `FREQ` parameter is + specified along with a `BYXXX` parameter at the same "level" + (e.g. `HOURLY` specified with `BYHOUR`). + + :param value: + The old value of the component. + :param byxxx: + The `BYXXX` set, which should have been generated by + `rrule._construct_byset`, or something else which checks that a + valid rule is present. + :param base: + The largest allowable value for the specified frequency (e.g. + 24 hours, 60 minutes). + + If a valid value is not found after `base` iterations (the maximum + number before the sequence would start to repeat), this raises a + :exception:`ValueError`, as no valid values were found. + + This returns a tuple of `divmod(n*interval, base)`, where `n` is the + smallest number of `interval` repetitions until the next specified + value in `byxxx` is found. + """ + accumulator = 0 + for ii in range(1, base + 1): + # Using divmod() over % to account for negative intervals + div, value = divmod(value + self._interval, base) + accumulator += div + if value in byxxx: + return (accumulator, value) + + +class _iterinfo(object): + __slots__ = ["rrule", "lastyear", "lastmonth", + "yearlen", "nextyearlen", "yearordinal", "yearweekday", + "mmask", "mrange", "mdaymask", "nmdaymask", + "wdaymask", "wnomask", "nwdaymask", "eastermask"] + + def __init__(self, rrule): + for attr in self.__slots__: + setattr(self, attr, None) + self.rrule = rrule + + def rebuild(self, year, month): + # Every mask is 7 days longer to handle cross-year weekly periods. + rr = self.rrule + if year != self.lastyear: + self.yearlen = 365 + calendar.isleap(year) + self.nextyearlen = 365 + calendar.isleap(year + 1) + firstyday = datetime.date(year, 1, 1) + self.yearordinal = firstyday.toordinal() + self.yearweekday = firstyday.weekday() + + wday = datetime.date(year, 1, 1).weekday() + if self.yearlen == 365: + self.mmask = M365MASK + self.mdaymask = MDAY365MASK + self.nmdaymask = NMDAY365MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M365RANGE + else: + self.mmask = M366MASK + self.mdaymask = MDAY366MASK + self.nmdaymask = NMDAY366MASK + self.wdaymask = WDAYMASK[wday:] + self.mrange = M366RANGE + + if not rr._byweekno: + self.wnomask = None + else: + self.wnomask = [0]*(self.yearlen+7) + # no1wkst = firstwkst = self.wdaymask.index(rr._wkst) + no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7 + if no1wkst >= 4: + no1wkst = 0 + # Number of days in the year, plus the days we got + # from last year. + wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7 + else: + # Number of days in the year, minus the days we + # left in last year. + wyearlen = self.yearlen-no1wkst + div, mod = divmod(wyearlen, 7) + numweeks = div+mod//4 + for n in rr._byweekno: + if n < 0: + n += numweeks+1 + if not (0 < n <= numweeks): + continue + if n > 1: + i = no1wkst+(n-1)*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + else: + i = no1wkst + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if 1 in rr._byweekno: + # Check week number 1 of next year as well + # TODO: Check -numweeks for next year. + i = no1wkst+numweeks*7 + if no1wkst != firstwkst: + i -= 7-firstwkst + if i < self.yearlen: + # If week starts in next year, we + # don't care about it. + for j in range(7): + self.wnomask[i] = 1 + i += 1 + if self.wdaymask[i] == rr._wkst: + break + if no1wkst: + # Check last week number of last year as + # well. If no1wkst is 0, either the year + # started on week start, or week number 1 + # got days from last year, so there are no + # days from last year's last week number in + # this year. + if -1 not in rr._byweekno: + lyearweekday = datetime.date(year-1, 1, 1).weekday() + lno1wkst = (7-lyearweekday+rr._wkst) % 7 + lyearlen = 365+calendar.isleap(year-1) + if lno1wkst >= 4: + lno1wkst = 0 + lnumweeks = 52+(lyearlen + + (lyearweekday-rr._wkst) % 7) % 7//4 + else: + lnumweeks = 52+(self.yearlen-no1wkst) % 7//4 + else: + lnumweeks = -1 + if lnumweeks in rr._byweekno: + for i in range(no1wkst): + self.wnomask[i] = 1 + + if (rr._bynweekday and (month != self.lastmonth or + year != self.lastyear)): + ranges = [] + if rr._freq == YEARLY: + if rr._bymonth: + for month in rr._bymonth: + ranges.append(self.mrange[month-1:month+1]) + else: + ranges = [(0, self.yearlen)] + elif rr._freq == MONTHLY: + ranges = [self.mrange[month-1:month+1]] + if ranges: + # Weekly frequency won't get here, so we may not + # care about cross-year weekly periods. + self.nwdaymask = [0]*self.yearlen + for first, last in ranges: + last -= 1 + for wday, n in rr._bynweekday: + if n < 0: + i = last+(n+1)*7 + i -= (self.wdaymask[i]-wday) % 7 + else: + i = first+(n-1)*7 + i += (7-self.wdaymask[i]+wday) % 7 + if first <= i <= last: + self.nwdaymask[i] = 1 + + if rr._byeaster: + self.eastermask = [0]*(self.yearlen+7) + eyday = easter.easter(year).toordinal()-self.yearordinal + for offset in rr._byeaster: + self.eastermask[eyday+offset] = 1 + + self.lastyear = year + self.lastmonth = month + + def ydayset(self, year, month, day): + return list(range(self.yearlen)), 0, self.yearlen + + def mdayset(self, year, month, day): + dset = [None]*self.yearlen + start, end = self.mrange[month-1:month+1] + for i in range(start, end): + dset[i] = i + return dset, start, end + + def wdayset(self, year, month, day): + # We need to handle cross-year weeks here. + dset = [None]*(self.yearlen+7) + i = datetime.date(year, month, day).toordinal()-self.yearordinal + start = i + for j in range(7): + dset[i] = i + i += 1 + # if (not (0 <= i < self.yearlen) or + # self.wdaymask[i] == self.rrule._wkst): + # This will cross the year boundary, if necessary. + if self.wdaymask[i] == self.rrule._wkst: + break + return dset, start, i + + def ddayset(self, year, month, day): + dset = [None] * self.yearlen + i = datetime.date(year, month, day).toordinal() - self.yearordinal + dset[i] = i + return dset, i, i + 1 + + def htimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for minute in rr._byminute: + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, + tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def mtimeset(self, hour, minute, second): + tset = [] + rr = self.rrule + for second in rr._bysecond: + tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo)) + tset.sort() + return tset + + def stimeset(self, hour, minute, second): + return (datetime.time(hour, minute, second, + tzinfo=self.rrule._tzinfo),) + + +class rruleset(rrulebase): + """ The rruleset type allows more complex recurrence setups, mixing + multiple rules, dates, exclusion rules, and exclusion dates. The type + constructor takes the following keyword arguments: + + :param cache: If True, caching of results will be enabled, improving + performance of multiple queries considerably. """ + + class _genitem(object): + def __init__(self, genlist, gen): + try: + self.dt = advance_iterator(gen) + genlist.append(self) + except StopIteration: + pass + self.genlist = genlist + self.gen = gen + + def __next__(self): + try: + self.dt = advance_iterator(self.gen) + except StopIteration: + if self.genlist[0] is self: + heapq.heappop(self.genlist) + else: + self.genlist.remove(self) + heapq.heapify(self.genlist) + + next = __next__ + + def __lt__(self, other): + return self.dt < other.dt + + def __gt__(self, other): + return self.dt > other.dt + + def __eq__(self, other): + return self.dt == other.dt + + def __ne__(self, other): + return self.dt != other.dt + + def __init__(self, cache=False): + super(rruleset, self).__init__(cache) + self._rrule = [] + self._rdate = [] + self._exrule = [] + self._exdate = [] + + @_invalidates_cache + def rrule(self, rrule): + """ Include the given :py:class:`rrule` instance in the recurrence set + generation. """ + self._rrule.append(rrule) + + @_invalidates_cache + def rdate(self, rdate): + """ Include the given :py:class:`datetime` instance in the recurrence + set generation. """ + self._rdate.append(rdate) + + @_invalidates_cache + def exrule(self, exrule): + """ Include the given rrule instance in the recurrence set exclusion + list. Dates which are part of the given recurrence rules will not + be generated, even if some inclusive rrule or rdate matches them. + """ + self._exrule.append(exrule) + + @_invalidates_cache + def exdate(self, exdate): + """ Include the given datetime instance in the recurrence set + exclusion list. Dates included that way will not be generated, + even if some inclusive rrule or rdate matches them. """ + self._exdate.append(exdate) + + def _iter(self): + rlist = [] + self._rdate.sort() + self._genitem(rlist, iter(self._rdate)) + for gen in [iter(x) for x in self._rrule]: + self._genitem(rlist, gen) + exlist = [] + self._exdate.sort() + self._genitem(exlist, iter(self._exdate)) + for gen in [iter(x) for x in self._exrule]: + self._genitem(exlist, gen) + lastdt = None + total = 0 + heapq.heapify(rlist) + heapq.heapify(exlist) + while rlist: + ritem = rlist[0] + if not lastdt or lastdt != ritem.dt: + while exlist and exlist[0] < ritem: + exitem = exlist[0] + advance_iterator(exitem) + if exlist and exlist[0] is exitem: + heapq.heapreplace(exlist, exitem) + if not exlist or ritem != exlist[0]: + total += 1 + yield ritem.dt + lastdt = ritem.dt + advance_iterator(ritem) + if rlist and rlist[0] is ritem: + heapq.heapreplace(rlist, ritem) + self._len = total + + + + +class _rrulestr(object): + """ Parses a string representation of a recurrence rule or set of + recurrence rules. + + :param s: + Required, a string defining one or more recurrence rules. + + :param dtstart: + If given, used as the default recurrence start if not specified in the + rule string. + + :param cache: + If set ``True`` caching of results will be enabled, improving + performance of multiple queries considerably. + + :param unfold: + If set ``True`` indicates that a rule string is split over more + than one line and should be joined before processing. + + :param forceset: + If set ``True`` forces a :class:`dateutil.rrule.rruleset` to + be returned. + + :param compatible: + If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``. + + :param ignoretz: + If set ``True``, time zones in parsed strings are ignored and a naive + :class:`datetime.datetime` object is returned. + + :param tzids: + If given, a callable or mapping used to retrieve a + :class:`datetime.tzinfo` from a string representation. + Defaults to :func:`dateutil.tz.gettz`. + + :param tzinfos: + Additional time zone names / aliases which may be present in a string + representation. See :func:`dateutil.parser.parse` for more + information. + + :return: + Returns a :class:`dateutil.rrule.rruleset` or + :class:`dateutil.rrule.rrule` + """ + + _freq_map = {"YEARLY": YEARLY, + "MONTHLY": MONTHLY, + "WEEKLY": WEEKLY, + "DAILY": DAILY, + "HOURLY": HOURLY, + "MINUTELY": MINUTELY, + "SECONDLY": SECONDLY} + + _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3, + "FR": 4, "SA": 5, "SU": 6} + + def _handle_int(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = int(value) + + def _handle_int_list(self, rrkwargs, name, value, **kwargs): + rrkwargs[name.lower()] = [int(x) for x in value.split(',')] + + _handle_INTERVAL = _handle_int + _handle_COUNT = _handle_int + _handle_BYSETPOS = _handle_int_list + _handle_BYMONTH = _handle_int_list + _handle_BYMONTHDAY = _handle_int_list + _handle_BYYEARDAY = _handle_int_list + _handle_BYEASTER = _handle_int_list + _handle_BYWEEKNO = _handle_int_list + _handle_BYHOUR = _handle_int_list + _handle_BYMINUTE = _handle_int_list + _handle_BYSECOND = _handle_int_list + + def _handle_FREQ(self, rrkwargs, name, value, **kwargs): + rrkwargs["freq"] = self._freq_map[value] + + def _handle_UNTIL(self, rrkwargs, name, value, **kwargs): + global parser + if not parser: + from dateutil import parser + try: + rrkwargs["until"] = parser.parse(value, + ignoretz=kwargs.get("ignoretz"), + tzinfos=kwargs.get("tzinfos")) + except ValueError: + raise ValueError("invalid until date") + + def _handle_WKST(self, rrkwargs, name, value, **kwargs): + rrkwargs["wkst"] = self._weekday_map[value] + + def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwargs): + """ + Two ways to specify this: +1MO or MO(+1) + """ + l = [] + for wday in value.split(','): + if '(' in wday: + # If it's of the form TH(+1), etc. + splt = wday.split('(') + w = splt[0] + n = int(splt[1][:-1]) + elif len(wday): + # If it's of the form +1MO + for i in range(len(wday)): + if wday[i] not in '+-0123456789': + break + n = wday[:i] or None + w = wday[i:] + if n: + n = int(n) + else: + raise ValueError("Invalid (empty) BYDAY specification.") + + l.append(weekdays[self._weekday_map[w]](n)) + rrkwargs["byweekday"] = l + + _handle_BYDAY = _handle_BYWEEKDAY + + def _parse_rfc_rrule(self, line, + dtstart=None, + cache=False, + ignoretz=False, + tzinfos=None): + if line.find(':') != -1: + name, value = line.split(':') + if name != "RRULE": + raise ValueError("unknown parameter name") + else: + value = line + rrkwargs = {} + for pair in value.split(';'): + name, value = pair.split('=') + name = name.upper() + value = value.upper() + try: + getattr(self, "_handle_"+name)(rrkwargs, name, value, + ignoretz=ignoretz, + tzinfos=tzinfos) + except AttributeError: + raise ValueError("unknown parameter '%s'" % name) + except (KeyError, ValueError): + raise ValueError("invalid '%s': %s" % (name, value)) + return rrule(dtstart=dtstart, cache=cache, **rrkwargs) + + def _parse_date_value(self, date_value, parms, rule_tzids, + ignoretz, tzids, tzinfos): + global parser + if not parser: + from dateutil import parser + + datevals = [] + value_found = False + TZID = None + + for parm in parms: + if parm.startswith("TZID="): + try: + tzkey = rule_tzids[parm.split('TZID=')[-1]] + except KeyError: + continue + if tzids is None: + from . import tz + tzlookup = tz.gettz + elif callable(tzids): + tzlookup = tzids + else: + tzlookup = getattr(tzids, 'get', None) + if tzlookup is None: + msg = ('tzids must be a callable, mapping, or None, ' + 'not %s' % tzids) + raise ValueError(msg) + + TZID = tzlookup(tzkey) + continue + + # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found + # only once. + if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}: + raise ValueError("unsupported parm: " + parm) + else: + if value_found: + msg = ("Duplicate value parameter found in: " + parm) + raise ValueError(msg) + value_found = True + + for datestr in date_value.split(','): + date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos) + if TZID is not None: + if date.tzinfo is None: + date = date.replace(tzinfo=TZID) + else: + raise ValueError('DTSTART/EXDATE specifies multiple timezone') + datevals.append(date) + + return datevals + + def _parse_rfc(self, s, + dtstart=None, + cache=False, + unfold=False, + forceset=False, + compatible=False, + ignoretz=False, + tzids=None, + tzinfos=None): + global parser + if compatible: + forceset = True + unfold = True + + TZID_NAMES = dict(map( + lambda x: (x.upper(), x), + re.findall('TZID=(?P[^:]+):', s) + )) + s = s.upper() + if not s.strip(): + raise ValueError("empty string") + if unfold: + lines = s.splitlines() + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + else: + lines = s.split() + if (not forceset and len(lines) == 1 and (s.find(':') == -1 or + s.startswith('RRULE:'))): + return self._parse_rfc_rrule(lines[0], cache=cache, + dtstart=dtstart, ignoretz=ignoretz, + tzinfos=tzinfos) + else: + rrulevals = [] + rdatevals = [] + exrulevals = [] + exdatevals = [] + for line in lines: + if not line: + continue + if line.find(':') == -1: + name = "RRULE" + value = line + else: + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0] + parms = parms[1:] + if name == "RRULE": + for parm in parms: + raise ValueError("unsupported RRULE parm: "+parm) + rrulevals.append(value) + elif name == "RDATE": + for parm in parms: + if parm != "VALUE=DATE-TIME": + raise ValueError("unsupported RDATE parm: "+parm) + rdatevals.append(value) + elif name == "EXRULE": + for parm in parms: + raise ValueError("unsupported EXRULE parm: "+parm) + exrulevals.append(value) + elif name == "EXDATE": + exdatevals.extend( + self._parse_date_value(value, parms, + TZID_NAMES, ignoretz, + tzids, tzinfos) + ) + elif name == "DTSTART": + dtvals = self._parse_date_value(value, parms, TZID_NAMES, + ignoretz, tzids, tzinfos) + if len(dtvals) != 1: + raise ValueError("Multiple DTSTART values specified:" + + value) + dtstart = dtvals[0] + else: + raise ValueError("unsupported property: "+name) + if (forceset or len(rrulevals) > 1 or rdatevals + or exrulevals or exdatevals): + if not parser and (rdatevals or exdatevals): + from dateutil import parser + rset = rruleset(cache=cache) + for value in rrulevals: + rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in rdatevals: + for datestr in value.split(','): + rset.rdate(parser.parse(datestr, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exrulevals: + rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart, + ignoretz=ignoretz, + tzinfos=tzinfos)) + for value in exdatevals: + rset.exdate(value) + if compatible and dtstart: + rset.rdate(dtstart) + return rset + else: + return self._parse_rfc_rrule(rrulevals[0], + dtstart=dtstart, + cache=cache, + ignoretz=ignoretz, + tzinfos=tzinfos) + + def __call__(self, s, **kwargs): + return self._parse_rfc(s, **kwargs) + + +rrulestr = _rrulestr() + +# vim:ts=4:sw=4:et diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/__init__.py new file mode 100644 index 00000000..af1352c4 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +from .tz import * +from .tz import __doc__ + +__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", + "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz", + "enfold", "datetime_ambiguous", "datetime_exists", + "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"] + + +class DeprecatedTzFormatWarning(Warning): + """Warning raised when time zones are parsed from deprecated formats.""" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_common.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_common.py new file mode 100644 index 00000000..e6ac1183 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_common.py @@ -0,0 +1,419 @@ +from six import PY2 + +from functools import wraps + +from datetime import datetime, timedelta, tzinfo + + +ZERO = timedelta(0) + +__all__ = ['tzname_in_python2', 'enfold'] + + +def tzname_in_python2(namefunc): + """Change unicode output into bytestrings in Python 2 + + tzname() API changed in Python 3. It used to return bytes, but was changed + to unicode strings + """ + if PY2: + @wraps(namefunc) + def adjust_encoding(*args, **kwargs): + name = namefunc(*args, **kwargs) + if name is not None: + name = name.encode() + + return name + + return adjust_encoding + else: + return namefunc + + +# The following is adapted from Alexander Belopolsky's tz library +# https://github.com/abalkin/tz +if hasattr(datetime, 'fold'): + # This is the pre-python 3.6 fold situation + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + return dt.replace(fold=fold) + +else: + class _DatetimeWithFold(datetime): + """ + This is a class designed to provide a PEP 495-compliant interface for + Python versions before 3.6. It is used only for dates in a fold, so + the ``fold`` attribute is fixed at ``1``. + + .. versionadded:: 2.6.0 + """ + __slots__ = () + + def replace(self, *args, **kwargs): + """ + Return a datetime with the same attributes, except for those + attributes given new values by whichever keyword arguments are + specified. Note that tzinfo=None can be specified to create a naive + datetime from an aware datetime with no conversion of date and time + data. + + This is reimplemented in ``_DatetimeWithFold`` because pypy3 will + return a ``datetime.datetime`` even if ``fold`` is unchanged. + """ + argnames = ( + 'year', 'month', 'day', 'hour', 'minute', 'second', + 'microsecond', 'tzinfo' + ) + + for arg, argname in zip(args, argnames): + if argname in kwargs: + raise TypeError('Duplicate argument: {}'.format(argname)) + + kwargs[argname] = arg + + for argname in argnames: + if argname not in kwargs: + kwargs[argname] = getattr(self, argname) + + dt_class = self.__class__ if kwargs.get('fold', 1) else datetime + + return dt_class(**kwargs) + + @property + def fold(self): + return 1 + + def enfold(dt, fold=1): + """ + Provides a unified interface for assigning the ``fold`` attribute to + datetimes both before and after the implementation of PEP-495. + + :param fold: + The value for the ``fold`` attribute in the returned datetime. This + should be either 0 or 1. + + :return: + Returns an object for which ``getattr(dt, 'fold', 0)`` returns + ``fold`` for all versions of Python. In versions prior to + Python 3.6, this is a ``_DatetimeWithFold`` object, which is a + subclass of :py:class:`datetime.datetime` with the ``fold`` + attribute added, if ``fold`` is 1. + + .. versionadded:: 2.6.0 + """ + if getattr(dt, 'fold', 0) == fold: + return dt + + args = dt.timetuple()[:6] + args += (dt.microsecond, dt.tzinfo) + + if fold: + return _DatetimeWithFold(*args) + else: + return datetime(*args) + + +def _validate_fromutc_inputs(f): + """ + The CPython version of ``fromutc`` checks that the input is a ``datetime`` + object and that ``self`` is attached as its ``tzinfo``. + """ + @wraps(f) + def fromutc(self, dt): + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + return f(self, dt) + + return fromutc + + +class _tzinfo(tzinfo): + """ + Base class for all ``dateutil`` ``tzinfo`` objects. + """ + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + + dt = dt.replace(tzinfo=self) + + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None) + + return same_dt and not same_offset + + def _fold_status(self, dt_utc, dt_wall): + """ + Determine the fold status of a "wall" datetime, given a representation + of the same datetime as a (naive) UTC datetime. This is calculated based + on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all + datetimes, and that this offset is the actual number of hours separating + ``dt_utc`` and ``dt_wall``. + + :param dt_utc: + Representation of the datetime as UTC + + :param dt_wall: + Representation of the datetime as "wall time". This parameter must + either have a `fold` attribute or have a fold-naive + :class:`datetime.tzinfo` attached, otherwise the calculation may + fail. + """ + if self.is_ambiguous(dt_wall): + delta_wall = dt_wall - dt_utc + _fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst())) + else: + _fold = 0 + + return _fold + + def _fold(self, dt): + return getattr(dt, 'fold', 0) + + def _fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurrence, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + + # Re-implement the algorithm from Python's datetime.py + dtoff = dt.utcoffset() + if dtoff is None: + raise ValueError("fromutc() requires a non-None utcoffset() " + "result") + + # The original datetime.py code assumes that `dst()` defaults to + # zero during ambiguous times. PEP 495 inverts this presumption, so + # for pre-PEP 495 versions of python, we need to tweak the algorithm. + dtdst = dt.dst() + if dtdst is None: + raise ValueError("fromutc() requires a non-None dst() result") + delta = dtoff - dtdst + + dt += delta + # Set fold=1 so we can default to being in the fold for + # ambiguous dates. + dtdst = enfold(dt, fold=1).dst() + if dtdst is None: + raise ValueError("fromutc(): dt.dst gave inconsistent " + "results; cannot convert") + return dt + dtdst + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Given a timezone-aware datetime in a given timezone, calculates a + timezone-aware datetime in a new timezone. + + Since this is the one time that we *know* we have an unambiguous + datetime object, we take this opportunity to determine whether the + datetime is ambiguous and in a "fold" state (e.g. if it's the first + occurrence, chronologically, of the ambiguous datetime). + + :param dt: + A timezone-aware :class:`datetime.datetime` object. + """ + dt_wall = self._fromutc(dt) + + # Calculate the fold status given the two datetimes. + _fold = self._fold_status(dt, dt_wall) + + # Set the default fold value for ambiguous dates + return enfold(dt_wall, fold=_fold) + + +class tzrangebase(_tzinfo): + """ + This is an abstract base class for time zones represented by an annual + transition into and out of DST. Child classes should implement the following + methods: + + * ``__init__(self, *args, **kwargs)`` + * ``transitions(self, year)`` - this is expected to return a tuple of + datetimes representing the DST on and off transitions in standard + time. + + A fully initialized ``tzrangebase`` subclass should also provide the + following attributes: + * ``hasdst``: Boolean whether or not the zone uses DST. + * ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects + representing the respective UTC offsets. + * ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short + abbreviations in DST and STD, respectively. + * ``_hasdst``: Whether or not the zone has DST. + + .. versionadded:: 2.6.0 + """ + def __init__(self): + raise NotImplementedError('tzrangebase is an abstract base class') + + def utcoffset(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + isdst = self._isdst(dt) + + if isdst is None: + return None + elif isdst: + return self._dst_base_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + if self._isdst(dt): + return self._dst_abbr + else: + return self._std_abbr + + def fromutc(self, dt): + """ Given a datetime in UTC, return local time """ + if not isinstance(dt, datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # Get transitions - if there are none, fixed offset + transitions = self.transitions(dt.year) + if transitions is None: + return dt + self.utcoffset(dt) + + # Get the transition times in UTC + dston, dstoff = transitions + + dston -= self._std_offset + dstoff -= self._std_offset + + utc_transitions = (dston, dstoff) + dt_utc = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt_utc, utc_transitions) + + if isdst: + dt_wall = dt + self._dst_offset + else: + dt_wall = dt + self._std_offset + + _fold = int(not isdst and self.is_ambiguous(dt_wall)) + + return enfold(dt_wall, fold=_fold) + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if not self.hasdst: + return False + + start, end = self.transitions(dt.year) + + dt = dt.replace(tzinfo=None) + return (end <= dt < end + self._dst_base_offset) + + def _isdst(self, dt): + if not self.hasdst: + return False + elif dt is None: + return None + + transitions = self.transitions(dt.year) + + if transitions is None: + return False + + dt = dt.replace(tzinfo=None) + + isdst = self._naive_isdst(dt, transitions) + + # Handle ambiguous dates + if not isdst and self.is_ambiguous(dt): + return not self._fold(dt) + else: + return isdst + + def _naive_isdst(self, dt, transitions): + dston, dstoff = transitions + + dt = dt.replace(tzinfo=None) + + if dston < dstoff: + isdst = dston <= dt < dstoff + else: + isdst = not dstoff <= dt < dston + + return isdst + + @property + def _dst_base_offset(self): + return self._dst_offset - self._std_offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(...)" % self.__class__.__name__ + + __reduce__ = object.__reduce__ diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_factories.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_factories.py new file mode 100644 index 00000000..f8a65891 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/_factories.py @@ -0,0 +1,80 @@ +from datetime import timedelta +import weakref +from collections import OrderedDict + +from six.moves import _thread + + +class _TzSingleton(type): + def __init__(cls, *args, **kwargs): + cls.__instance = None + super(_TzSingleton, cls).__init__(*args, **kwargs) + + def __call__(cls): + if cls.__instance is None: + cls.__instance = super(_TzSingleton, cls).__call__() + return cls.__instance + + +class _TzFactory(type): + def instance(cls, *args, **kwargs): + """Alternate constructor that returns a fresh instance""" + return type.__call__(cls, *args, **kwargs) + + +class _TzOffsetFactory(_TzFactory): + def __init__(cls, *args, **kwargs): + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + cls._cache_lock = _thread.allocate_lock() + + def __call__(cls, name, offset): + if isinstance(offset, timedelta): + key = (name, offset.total_seconds()) + else: + key = (name, offset) + + instance = cls.__instances.get(key, None) + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(name, offset)) + + # This lock may not be necessary in Python 3. See GH issue #901 + with cls._cache_lock: + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + + +class _TzStrFactory(_TzFactory): + def __init__(cls, *args, **kwargs): + cls.__instances = weakref.WeakValueDictionary() + cls.__strong_cache = OrderedDict() + cls.__strong_cache_size = 8 + + cls.__cache_lock = _thread.allocate_lock() + + def __call__(cls, s, posix_offset=False): + key = (s, posix_offset) + instance = cls.__instances.get(key, None) + + if instance is None: + instance = cls.__instances.setdefault(key, + cls.instance(s, posix_offset)) + + # This lock may not be necessary in Python 3. See GH issue #901 + with cls.__cache_lock: + cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance) + + # Remove an item if the strong cache is overpopulated + if len(cls.__strong_cache) > cls.__strong_cache_size: + cls.__strong_cache.popitem(last=False) + + return instance + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/tz.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/tz.py new file mode 100644 index 00000000..af81e88e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/tz.py @@ -0,0 +1,1849 @@ +# -*- coding: utf-8 -*- +""" +This module offers timezone implementations subclassing the abstract +:py:class:`datetime.tzinfo` type. There are classes to handle tzfile format +files (usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`, +etc), TZ environment string (in all known formats), given ranges (with help +from relative deltas), local machine timezone, fixed offset timezone, and UTC +timezone. +""" +import datetime +import struct +import time +import sys +import os +import bisect +import weakref +from collections import OrderedDict + +import six +from six import string_types +from six.moves import _thread +from ._common import tzname_in_python2, _tzinfo +from ._common import tzrangebase, enfold +from ._common import _validate_fromutc_inputs + +from ._factories import _TzSingleton, _TzOffsetFactory +from ._factories import _TzStrFactory +try: + from .win import tzwin, tzwinlocal +except ImportError: + tzwin = tzwinlocal = None + +# For warning about rounding tzinfo +from warnings import warn + +ZERO = datetime.timedelta(0) +EPOCH = datetime.datetime.utcfromtimestamp(0) +EPOCHORDINAL = EPOCH.toordinal() + + +@six.add_metaclass(_TzSingleton) +class tzutc(datetime.tzinfo): + """ + This is a tzinfo object that represents the UTC time zone. + + **Examples:** + + .. doctest:: + + >>> from datetime import * + >>> from dateutil.tz import * + + >>> datetime.now() + datetime.datetime(2003, 9, 27, 9, 40, 1, 521290) + + >>> datetime.now(tzutc()) + datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc()) + + >>> datetime.now(tzutc()).tzname() + 'UTC' + + .. versionchanged:: 2.7.0 + ``tzutc()`` is now a singleton, so the result of ``tzutc()`` will + always return the same object. + + .. doctest:: + + >>> from dateutil.tz import tzutc, UTC + >>> tzutc() is tzutc() + True + >>> tzutc() is UTC + True + """ + def utcoffset(self, dt): + return ZERO + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return "UTC" + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + @_validate_fromutc_inputs + def fromutc(self, dt): + """ + Fast track version of fromutc() returns the original ``dt`` object for + any valid :py:class:`datetime.datetime` object. + """ + return dt + + def __eq__(self, other): + if not isinstance(other, (tzutc, tzoffset)): + return NotImplemented + + return (isinstance(other, tzutc) or + (isinstance(other, tzoffset) and other._offset == ZERO)) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +#: Convenience constant providing a :class:`tzutc()` instance +#: +#: .. versionadded:: 2.7.0 +UTC = tzutc() + + +@six.add_metaclass(_TzOffsetFactory) +class tzoffset(datetime.tzinfo): + """ + A simple class for representing a fixed offset from UTC. + + :param name: + The timezone name, to be returned when ``tzname()`` is called. + :param offset: + The time zone offset in seconds, or (since version 2.6.0, represented + as a :py:class:`datetime.timedelta` object). + """ + def __init__(self, name, offset): + self._name = name + + try: + # Allow a timedelta + offset = offset.total_seconds() + except (TypeError, AttributeError): + pass + + self._offset = datetime.timedelta(seconds=_get_supported_offset(offset)) + + def utcoffset(self, dt): + return self._offset + + def dst(self, dt): + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._name + + @_validate_fromutc_inputs + def fromutc(self, dt): + return dt + self._offset + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + return False + + def __eq__(self, other): + if not isinstance(other, tzoffset): + return NotImplemented + + return self._offset == other._offset + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s, %s)" % (self.__class__.__name__, + repr(self._name), + int(self._offset.total_seconds())) + + __reduce__ = object.__reduce__ + + +class tzlocal(_tzinfo): + """ + A :class:`tzinfo` subclass built around the ``time`` timezone functions. + """ + def __init__(self): + super(tzlocal, self).__init__() + + self._std_offset = datetime.timedelta(seconds=-time.timezone) + if time.daylight: + self._dst_offset = datetime.timedelta(seconds=-time.altzone) + else: + self._dst_offset = self._std_offset + + self._dst_saved = self._dst_offset - self._std_offset + self._hasdst = bool(self._dst_saved) + self._tznames = tuple(time.tzname) + + def utcoffset(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset + else: + return self._std_offset + + def dst(self, dt): + if dt is None and self._hasdst: + return None + + if self._isdst(dt): + return self._dst_offset - self._std_offset + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._tznames[self._isdst(dt)] + + def is_ambiguous(self, dt): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + naive_dst = self._naive_is_dst(dt) + return (not naive_dst and + (naive_dst != self._naive_is_dst(dt - self._dst_saved))) + + def _naive_is_dst(self, dt): + timestamp = _datetime_to_timestamp(dt) + return time.localtime(timestamp + time.timezone).tm_isdst + + def _isdst(self, dt, fold_naive=True): + # We can't use mktime here. It is unstable when deciding if + # the hour near to a change is DST or not. + # + # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour, + # dt.minute, dt.second, dt.weekday(), 0, -1)) + # return time.localtime(timestamp).tm_isdst + # + # The code above yields the following result: + # + # >>> import tz, datetime + # >>> t = tz.tzlocal() + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRST' + # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname() + # 'BRDT' + # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname() + # 'BRDT' + # + # Here is a more stable implementation: + # + if not self._hasdst: + return False + + # Check for ambiguous times: + dstval = self._naive_is_dst(dt) + fold = getattr(dt, 'fold', None) + + if self.is_ambiguous(dt): + if fold is not None: + return not self._fold(dt) + else: + return True + + return dstval + + def __eq__(self, other): + if isinstance(other, tzlocal): + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset) + elif isinstance(other, tzutc): + return (not self._hasdst and + self._tznames[0] in {'UTC', 'GMT'} and + self._std_offset == ZERO) + elif isinstance(other, tzoffset): + return (not self._hasdst and + self._tznames[0] == other._name and + self._std_offset == other._offset) + else: + return NotImplemented + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s()" % self.__class__.__name__ + + __reduce__ = object.__reduce__ + + +class _ttinfo(object): + __slots__ = ["offset", "delta", "isdst", "abbr", + "isstd", "isgmt", "dstoffset"] + + def __init__(self): + for attr in self.__slots__: + setattr(self, attr, None) + + def __repr__(self): + l = [] + for attr in self.__slots__: + value = getattr(self, attr) + if value is not None: + l.append("%s=%s" % (attr, repr(value))) + return "%s(%s)" % (self.__class__.__name__, ", ".join(l)) + + def __eq__(self, other): + if not isinstance(other, _ttinfo): + return NotImplemented + + return (self.offset == other.offset and + self.delta == other.delta and + self.isdst == other.isdst and + self.abbr == other.abbr and + self.isstd == other.isstd and + self.isgmt == other.isgmt and + self.dstoffset == other.dstoffset) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __getstate__(self): + state = {} + for name in self.__slots__: + state[name] = getattr(self, name, None) + return state + + def __setstate__(self, state): + for name in self.__slots__: + if name in state: + setattr(self, name, state[name]) + + +class _tzfile(object): + """ + Lightweight class for holding the relevant transition and time zone + information read from binary tzfiles. + """ + attrs = ['trans_list', 'trans_list_utc', 'trans_idx', 'ttinfo_list', + 'ttinfo_std', 'ttinfo_dst', 'ttinfo_before', 'ttinfo_first'] + + def __init__(self, **kwargs): + for attr in self.attrs: + setattr(self, attr, kwargs.get(attr, None)) + + +class tzfile(_tzinfo): + """ + This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)`` + format timezone files to extract current and historical zone information. + + :param fileobj: + This can be an opened file stream or a file name that the time zone + information can be read from. + + :param filename: + This is an optional parameter specifying the source of the time zone + information in the event that ``fileobj`` is a file object. If omitted + and ``fileobj`` is a file stream, this parameter will be set either to + ``fileobj``'s ``name`` attribute or to ``repr(fileobj)``. + + See `Sources for Time Zone and Daylight Saving Time Data + `_ for more information. + Time zone files can be compiled from the `IANA Time Zone database files + `_ with the `zic time zone compiler + `_ + + .. note:: + + Only construct a ``tzfile`` directly if you have a specific timezone + file on disk that you want to read into a Python ``tzinfo`` object. + If you want to get a ``tzfile`` representing a specific IANA zone, + (e.g. ``'America/New_York'``), you should call + :func:`dateutil.tz.gettz` with the zone identifier. + + + **Examples:** + + Using the US Eastern time zone as an example, we can see that a ``tzfile`` + provides time zone information for the standard Daylight Saving offsets: + + .. testsetup:: tzfile + + from dateutil.tz import gettz + from datetime import datetime + + .. doctest:: tzfile + + >>> NYC = gettz('America/New_York') + >>> NYC + tzfile('/usr/share/zoneinfo/America/New_York') + + >>> print(datetime(2016, 1, 3, tzinfo=NYC)) # EST + 2016-01-03 00:00:00-05:00 + + >>> print(datetime(2016, 7, 7, tzinfo=NYC)) # EDT + 2016-07-07 00:00:00-04:00 + + + The ``tzfile`` structure contains a fully history of the time zone, + so historical dates will also have the right offsets. For example, before + the adoption of the UTC standards, New York used local solar mean time: + + .. doctest:: tzfile + + >>> print(datetime(1901, 4, 12, tzinfo=NYC)) # LMT + 1901-04-12 00:00:00-04:56 + + And during World War II, New York was on "Eastern War Time", which was a + state of permanent daylight saving time: + + .. doctest:: tzfile + + >>> print(datetime(1944, 2, 7, tzinfo=NYC)) # EWT + 1944-02-07 00:00:00-04:00 + + """ + + def __init__(self, fileobj, filename=None): + super(tzfile, self).__init__() + + file_opened_here = False + if isinstance(fileobj, string_types): + self._filename = fileobj + fileobj = open(fileobj, 'rb') + file_opened_here = True + elif filename is not None: + self._filename = filename + elif hasattr(fileobj, "name"): + self._filename = fileobj.name + else: + self._filename = repr(fileobj) + + if fileobj is not None: + if not file_opened_here: + fileobj = _nullcontext(fileobj) + + with fileobj as file_stream: + tzobj = self._read_tzfile(file_stream) + + self._set_tzdata(tzobj) + + def _set_tzdata(self, tzobj): + """ Set the time zone data of this object from a _tzfile object """ + # Copy the relevant attributes over as private attributes + for attr in _tzfile.attrs: + setattr(self, '_' + attr, getattr(tzobj, attr)) + + def _read_tzfile(self, fileobj): + out = _tzfile() + + # From tzfile(5): + # + # The time zone information files used by tzset(3) + # begin with the magic characters "TZif" to identify + # them as time zone information files, followed by + # sixteen bytes reserved for future use, followed by + # six four-byte values of type long, written in a + # ``standard'' byte order (the high-order byte + # of the value is written first). + if fileobj.read(4).decode() != "TZif": + raise ValueError("magic not found") + + fileobj.read(16) + + ( + # The number of UTC/local indicators stored in the file. + ttisgmtcnt, + + # The number of standard/wall indicators stored in the file. + ttisstdcnt, + + # The number of leap seconds for which data is + # stored in the file. + leapcnt, + + # The number of "transition times" for which data + # is stored in the file. + timecnt, + + # The number of "local time types" for which data + # is stored in the file (must not be zero). + typecnt, + + # The number of characters of "time zone + # abbreviation strings" stored in the file. + charcnt, + + ) = struct.unpack(">6l", fileobj.read(24)) + + # The above header is followed by tzh_timecnt four-byte + # values of type long, sorted in ascending order. + # These values are written in ``standard'' byte order. + # Each is used as a transition time (as returned by + # time(2)) at which the rules for computing local time + # change. + + if timecnt: + out.trans_list_utc = list(struct.unpack(">%dl" % timecnt, + fileobj.read(timecnt*4))) + else: + out.trans_list_utc = [] + + # Next come tzh_timecnt one-byte values of type unsigned + # char; each one tells which of the different types of + # ``local time'' types described in the file is associated + # with the same-indexed transition time. These values + # serve as indices into an array of ttinfo structures that + # appears next in the file. + + if timecnt: + out.trans_idx = struct.unpack(">%dB" % timecnt, + fileobj.read(timecnt)) + else: + out.trans_idx = [] + + # Each ttinfo structure is written as a four-byte value + # for tt_gmtoff of type long, in a standard byte + # order, followed by a one-byte value for tt_isdst + # and a one-byte value for tt_abbrind. In each + # structure, tt_gmtoff gives the number of + # seconds to be added to UTC, tt_isdst tells whether + # tm_isdst should be set by localtime(3), and + # tt_abbrind serves as an index into the array of + # time zone abbreviation characters that follow the + # ttinfo structure(s) in the file. + + ttinfo = [] + + for i in range(typecnt): + ttinfo.append(struct.unpack(">lbb", fileobj.read(6))) + + abbr = fileobj.read(charcnt).decode() + + # Then there are tzh_leapcnt pairs of four-byte + # values, written in standard byte order; the + # first value of each pair gives the time (as + # returned by time(2)) at which a leap second + # occurs; the second gives the total number of + # leap seconds to be applied after the given time. + # The pairs of values are sorted in ascending order + # by time. + + # Not used, for now (but seek for correct file position) + if leapcnt: + fileobj.seek(leapcnt * 8, os.SEEK_CUR) + + # Then there are tzh_ttisstdcnt standard/wall + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as standard + # time or wall clock time, and are used when + # a time zone file is used in handling POSIX-style + # time zone environment variables. + + if ttisstdcnt: + isstd = struct.unpack(">%db" % ttisstdcnt, + fileobj.read(ttisstdcnt)) + + # Finally, there are tzh_ttisgmtcnt UTC/local + # indicators, each stored as a one-byte value; + # they tell whether the transition times associated + # with local time types were specified as UTC or + # local time, and are used when a time zone file + # is used in handling POSIX-style time zone envi- + # ronment variables. + + if ttisgmtcnt: + isgmt = struct.unpack(">%db" % ttisgmtcnt, + fileobj.read(ttisgmtcnt)) + + # Build ttinfo list + out.ttinfo_list = [] + for i in range(typecnt): + gmtoff, isdst, abbrind = ttinfo[i] + gmtoff = _get_supported_offset(gmtoff) + tti = _ttinfo() + tti.offset = gmtoff + tti.dstoffset = datetime.timedelta(0) + tti.delta = datetime.timedelta(seconds=gmtoff) + tti.isdst = isdst + tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)] + tti.isstd = (ttisstdcnt > i and isstd[i] != 0) + tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0) + out.ttinfo_list.append(tti) + + # Replace ttinfo indexes for ttinfo objects. + out.trans_idx = [out.ttinfo_list[idx] for idx in out.trans_idx] + + # Set standard, dst, and before ttinfos. before will be + # used when a given time is before any transitions, + # and will be set to the first non-dst ttinfo, or to + # the first dst, if all of them are dst. + out.ttinfo_std = None + out.ttinfo_dst = None + out.ttinfo_before = None + if out.ttinfo_list: + if not out.trans_list_utc: + out.ttinfo_std = out.ttinfo_first = out.ttinfo_list[0] + else: + for i in range(timecnt-1, -1, -1): + tti = out.trans_idx[i] + if not out.ttinfo_std and not tti.isdst: + out.ttinfo_std = tti + elif not out.ttinfo_dst and tti.isdst: + out.ttinfo_dst = tti + + if out.ttinfo_std and out.ttinfo_dst: + break + else: + if out.ttinfo_dst and not out.ttinfo_std: + out.ttinfo_std = out.ttinfo_dst + + for tti in out.ttinfo_list: + if not tti.isdst: + out.ttinfo_before = tti + break + else: + out.ttinfo_before = out.ttinfo_list[0] + + # Now fix transition times to become relative to wall time. + # + # I'm not sure about this. In my tests, the tz source file + # is setup to wall time, and in the binary file isstd and + # isgmt are off, so it should be in wall time. OTOH, it's + # always in gmt time. Let me know if you have comments + # about this. + lastdst = None + lastoffset = None + lastdstoffset = None + lastbaseoffset = None + out.trans_list = [] + + for i, tti in enumerate(out.trans_idx): + offset = tti.offset + dstoffset = 0 + + if lastdst is not None: + if tti.isdst: + if not lastdst: + dstoffset = offset - lastoffset + + if not dstoffset and lastdstoffset: + dstoffset = lastdstoffset + + tti.dstoffset = datetime.timedelta(seconds=dstoffset) + lastdstoffset = dstoffset + + # If a time zone changes its base offset during a DST transition, + # then you need to adjust by the previous base offset to get the + # transition time in local time. Otherwise you use the current + # base offset. Ideally, I would have some mathematical proof of + # why this is true, but I haven't really thought about it enough. + baseoffset = offset - dstoffset + adjustment = baseoffset + if (lastbaseoffset is not None and baseoffset != lastbaseoffset + and tti.isdst != lastdst): + # The base DST has changed + adjustment = lastbaseoffset + + lastdst = tti.isdst + lastoffset = offset + lastbaseoffset = baseoffset + + out.trans_list.append(out.trans_list_utc[i] + adjustment) + + out.trans_idx = tuple(out.trans_idx) + out.trans_list = tuple(out.trans_list) + out.trans_list_utc = tuple(out.trans_list_utc) + + return out + + def _find_last_transition(self, dt, in_utc=False): + # If there's no list, there are no transitions to find + if not self._trans_list: + return None + + timestamp = _datetime_to_timestamp(dt) + + # Find where the timestamp fits in the transition list - if the + # timestamp is a transition time, it's part of the "after" period. + trans_list = self._trans_list_utc if in_utc else self._trans_list + idx = bisect.bisect_right(trans_list, timestamp) + + # We want to know when the previous transition was, so subtract off 1 + return idx - 1 + + def _get_ttinfo(self, idx): + # For no list or after the last transition, default to _ttinfo_std + if idx is None or (idx + 1) >= len(self._trans_list): + return self._ttinfo_std + + # If there is a list and the time is before it, return _ttinfo_before + if idx < 0: + return self._ttinfo_before + + return self._trans_idx[idx] + + def _find_ttinfo(self, dt): + idx = self._resolve_ambiguous_time(dt) + + return self._get_ttinfo(idx) + + def fromutc(self, dt): + """ + The ``tzfile`` implementation of :py:func:`datetime.tzinfo.fromutc`. + + :param dt: + A :py:class:`datetime.datetime` object. + + :raises TypeError: + Raised if ``dt`` is not a :py:class:`datetime.datetime` object. + + :raises ValueError: + Raised if this is called with a ``dt`` which does not have this + ``tzinfo`` attached. + + :return: + Returns a :py:class:`datetime.datetime` object representing the + wall time in ``self``'s time zone. + """ + # These isinstance checks are in datetime.tzinfo, so we'll preserve + # them, even if we don't care about duck typing. + if not isinstance(dt, datetime.datetime): + raise TypeError("fromutc() requires a datetime argument") + + if dt.tzinfo is not self: + raise ValueError("dt.tzinfo is not self") + + # First treat UTC as wall time and get the transition we're in. + idx = self._find_last_transition(dt, in_utc=True) + tti = self._get_ttinfo(idx) + + dt_out = dt + datetime.timedelta(seconds=tti.offset) + + fold = self.is_ambiguous(dt_out, idx=idx) + + return enfold(dt_out, fold=int(fold)) + + def is_ambiguous(self, dt, idx=None): + """ + Whether or not the "wall time" of a given datetime is ambiguous in this + zone. + + :param dt: + A :py:class:`datetime.datetime`, naive or time zone aware. + + + :return: + Returns ``True`` if ambiguous, ``False`` otherwise. + + .. versionadded:: 2.6.0 + """ + if idx is None: + idx = self._find_last_transition(dt) + + # Calculate the difference in offsets from current to previous + timestamp = _datetime_to_timestamp(dt) + tti = self._get_ttinfo(idx) + + if idx is None or idx <= 0: + return False + + od = self._get_ttinfo(idx - 1).offset - tti.offset + tt = self._trans_list[idx] # Transition time + + return timestamp < tt + od + + def _resolve_ambiguous_time(self, dt): + idx = self._find_last_transition(dt) + + # If we have no transitions, return the index + _fold = self._fold(dt) + if idx is None or idx == 0: + return idx + + # If it's ambiguous and we're in a fold, shift to a different index. + idx_offset = int(not _fold and self.is_ambiguous(dt, idx)) + + return idx - idx_offset + + def utcoffset(self, dt): + if dt is None: + return None + + if not self._ttinfo_std: + return ZERO + + return self._find_ttinfo(dt).delta + + def dst(self, dt): + if dt is None: + return None + + if not self._ttinfo_dst: + return ZERO + + tti = self._find_ttinfo(dt) + + if not tti.isdst: + return ZERO + + # The documentation says that utcoffset()-dst() must + # be constant for every dt. + return tti.dstoffset + + @tzname_in_python2 + def tzname(self, dt): + if not self._ttinfo_std or dt is None: + return None + return self._find_ttinfo(dt).abbr + + def __eq__(self, other): + if not isinstance(other, tzfile): + return NotImplemented + return (self._trans_list == other._trans_list and + self._trans_idx == other._trans_idx and + self._ttinfo_list == other._ttinfo_list) + + __hash__ = None + + def __ne__(self, other): + return not (self == other) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._filename)) + + def __reduce__(self): + return self.__reduce_ex__(None) + + def __reduce_ex__(self, protocol): + return (self.__class__, (None, self._filename), self.__dict__) + + +class tzrange(tzrangebase): + """ + The ``tzrange`` object is a time zone specified by a set of offsets and + abbreviations, equivalent to the way the ``TZ`` variable can be specified + in POSIX-like systems, but using Python delta objects to specify DST + start, end and offsets. + + :param stdabbr: + The abbreviation for standard time (e.g. ``'EST'``). + + :param stdoffset: + An integer or :class:`datetime.timedelta` object or equivalent + specifying the base offset from UTC. + + If unspecified, +00:00 is used. + + :param dstabbr: + The abbreviation for DST / "Summer" time (e.g. ``'EDT'``). + + If specified, with no other DST information, DST is assumed to occur + and the default behavior or ``dstoffset``, ``start`` and ``end`` is + used. If unspecified and no other DST information is specified, it + is assumed that this zone has no DST. + + If this is unspecified and other DST information is *is* specified, + DST occurs in the zone but the time zone abbreviation is left + unchanged. + + :param dstoffset: + A an integer or :class:`datetime.timedelta` object or equivalent + specifying the UTC offset during DST. If unspecified and any other DST + information is specified, it is assumed to be the STD offset +1 hour. + + :param start: + A :class:`relativedelta.relativedelta` object or equivalent specifying + the time and time of year that daylight savings time starts. To + specify, for example, that DST starts at 2AM on the 2nd Sunday in + March, pass: + + ``relativedelta(hours=2, month=3, day=1, weekday=SU(+2))`` + + If unspecified and any other DST information is specified, the default + value is 2 AM on the first Sunday in April. + + :param end: + A :class:`relativedelta.relativedelta` object or equivalent + representing the time and time of year that daylight savings time + ends, with the same specification method as in ``start``. One note is + that this should point to the first time in the *standard* zone, so if + a transition occurs at 2AM in the DST zone and the clocks are set back + 1 hour to 1AM, set the ``hours`` parameter to +1. + + + **Examples:** + + .. testsetup:: tzrange + + from dateutil.tz import tzrange, tzstr + + .. doctest:: tzrange + + >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT") + True + + >>> from dateutil.relativedelta import * + >>> range1 = tzrange("EST", -18000, "EDT") + >>> range2 = tzrange("EST", -18000, "EDT", -14400, + ... relativedelta(hours=+2, month=4, day=1, + ... weekday=SU(+1)), + ... relativedelta(hours=+1, month=10, day=31, + ... weekday=SU(-1))) + >>> tzstr('EST5EDT') == range1 == range2 + True + + """ + def __init__(self, stdabbr, stdoffset=None, + dstabbr=None, dstoffset=None, + start=None, end=None): + + global relativedelta + from dateutil import relativedelta + + self._std_abbr = stdabbr + self._dst_abbr = dstabbr + + try: + stdoffset = stdoffset.total_seconds() + except (TypeError, AttributeError): + pass + + try: + dstoffset = dstoffset.total_seconds() + except (TypeError, AttributeError): + pass + + if stdoffset is not None: + self._std_offset = datetime.timedelta(seconds=stdoffset) + else: + self._std_offset = ZERO + + if dstoffset is not None: + self._dst_offset = datetime.timedelta(seconds=dstoffset) + elif dstabbr and stdoffset is not None: + self._dst_offset = self._std_offset + datetime.timedelta(hours=+1) + else: + self._dst_offset = ZERO + + if dstabbr and start is None: + self._start_delta = relativedelta.relativedelta( + hours=+2, month=4, day=1, weekday=relativedelta.SU(+1)) + else: + self._start_delta = start + + if dstabbr and end is None: + self._end_delta = relativedelta.relativedelta( + hours=+1, month=10, day=31, weekday=relativedelta.SU(-1)) + else: + self._end_delta = end + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = bool(self._start_delta) + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + if not self.hasdst: + return None + + base_year = datetime.datetime(year, 1, 1) + + start = base_year + self._start_delta + end = base_year + self._end_delta + + return (start, end) + + def __eq__(self, other): + if not isinstance(other, tzrange): + return NotImplemented + + return (self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr and + self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._start_delta == other._start_delta and + self._end_delta == other._end_delta) + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +@six.add_metaclass(_TzStrFactory) +class tzstr(tzrange): + """ + ``tzstr`` objects are time zone objects specified by a time-zone string as + it would be passed to a ``TZ`` variable on POSIX-style systems (see + the `GNU C Library: TZ Variable`_ for more details). + + There is one notable exception, which is that POSIX-style time zones use an + inverted offset format, so normally ``GMT+3`` would be parsed as an offset + 3 hours *behind* GMT. The ``tzstr`` time zone object will parse this as an + offset 3 hours *ahead* of GMT. If you would like to maintain the POSIX + behavior, pass a ``True`` value to ``posix_offset``. + + The :class:`tzrange` object provides the same functionality, but is + specified using :class:`relativedelta.relativedelta` objects. rather than + strings. + + :param s: + A time zone string in ``TZ`` variable format. This can be a + :class:`bytes` (2.x: :class:`str`), :class:`str` (2.x: + :class:`unicode`) or a stream emitting unicode characters + (e.g. :class:`StringIO`). + + :param posix_offset: + Optional. If set to ``True``, interpret strings such as ``GMT+3`` or + ``UTC+3`` as being 3 hours *behind* UTC rather than ahead, per the + POSIX standard. + + .. caution:: + + Prior to version 2.7.0, this function also supported time zones + in the format: + + * ``EST5EDT,4,0,6,7200,10,0,26,7200,3600`` + * ``EST5EDT,4,1,0,7200,10,-1,0,7200,3600`` + + This format is non-standard and has been deprecated; this function + will raise a :class:`DeprecatedTZFormatWarning` until + support is removed in a future version. + + .. _`GNU C Library: TZ Variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + """ + def __init__(self, s, posix_offset=False): + global parser + from dateutil.parser import _parser as parser + + self._s = s + + res = parser._parsetz(s) + if res is None or res.any_unused_tokens: + raise ValueError("unknown string format") + + # Here we break the compatibility with the TZ variable handling. + # GMT-3 actually *means* the timezone -3. + if res.stdabbr in ("GMT", "UTC") and not posix_offset: + res.stdoffset *= -1 + + # We must initialize it first, since _delta() needs + # _std_offset and _dst_offset set. Use False in start/end + # to avoid building it two times. + tzrange.__init__(self, res.stdabbr, res.stdoffset, + res.dstabbr, res.dstoffset, + start=False, end=False) + + if not res.dstabbr: + self._start_delta = None + self._end_delta = None + else: + self._start_delta = self._delta(res.start) + if self._start_delta: + self._end_delta = self._delta(res.end, isend=1) + + self.hasdst = bool(self._start_delta) + + def _delta(self, x, isend=0): + from dateutil import relativedelta + kwargs = {} + if x.month is not None: + kwargs["month"] = x.month + if x.weekday is not None: + kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week) + if x.week > 0: + kwargs["day"] = 1 + else: + kwargs["day"] = 31 + elif x.day: + kwargs["day"] = x.day + elif x.yday is not None: + kwargs["yearday"] = x.yday + elif x.jyday is not None: + kwargs["nlyearday"] = x.jyday + if not kwargs: + # Default is to start on first sunday of april, and end + # on last sunday of october. + if not isend: + kwargs["month"] = 4 + kwargs["day"] = 1 + kwargs["weekday"] = relativedelta.SU(+1) + else: + kwargs["month"] = 10 + kwargs["day"] = 31 + kwargs["weekday"] = relativedelta.SU(-1) + if x.time is not None: + kwargs["seconds"] = x.time + else: + # Default is 2AM. + kwargs["seconds"] = 7200 + if isend: + # Convert to standard time, to follow the documented way + # of working with the extra hour. See the documentation + # of the tzinfo class. + delta = self._dst_offset - self._std_offset + kwargs["seconds"] -= delta.seconds + delta.days * 86400 + return relativedelta.relativedelta(**kwargs) + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +class _tzicalvtzcomp(object): + def __init__(self, tzoffsetfrom, tzoffsetto, isdst, + tzname=None, rrule=None): + self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom) + self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto) + self.tzoffsetdiff = self.tzoffsetto - self.tzoffsetfrom + self.isdst = isdst + self.tzname = tzname + self.rrule = rrule + + +class _tzicalvtz(_tzinfo): + def __init__(self, tzid, comps=[]): + super(_tzicalvtz, self).__init__() + + self._tzid = tzid + self._comps = comps + self._cachedate = [] + self._cachecomp = [] + self._cache_lock = _thread.allocate_lock() + + def _find_comp(self, dt): + if len(self._comps) == 1: + return self._comps[0] + + dt = dt.replace(tzinfo=None) + + try: + with self._cache_lock: + return self._cachecomp[self._cachedate.index( + (dt, self._fold(dt)))] + except ValueError: + pass + + lastcompdt = None + lastcomp = None + + for comp in self._comps: + compdt = self._find_compdt(comp, dt) + + if compdt and (not lastcompdt or lastcompdt < compdt): + lastcompdt = compdt + lastcomp = comp + + if not lastcomp: + # RFC says nothing about what to do when a given + # time is before the first onset date. We'll look for the + # first standard component, or the first component, if + # none is found. + for comp in self._comps: + if not comp.isdst: + lastcomp = comp + break + else: + lastcomp = comp[0] + + with self._cache_lock: + self._cachedate.insert(0, (dt, self._fold(dt))) + self._cachecomp.insert(0, lastcomp) + + if len(self._cachedate) > 10: + self._cachedate.pop() + self._cachecomp.pop() + + return lastcomp + + def _find_compdt(self, comp, dt): + if comp.tzoffsetdiff < ZERO and self._fold(dt): + dt -= comp.tzoffsetdiff + + compdt = comp.rrule.before(dt, inc=True) + + return compdt + + def utcoffset(self, dt): + if dt is None: + return None + + return self._find_comp(dt).tzoffsetto + + def dst(self, dt): + comp = self._find_comp(dt) + if comp.isdst: + return comp.tzoffsetdiff + else: + return ZERO + + @tzname_in_python2 + def tzname(self, dt): + return self._find_comp(dt).tzname + + def __repr__(self): + return "" % repr(self._tzid) + + __reduce__ = object.__reduce__ + + +class tzical(object): + """ + This object is designed to parse an iCalendar-style ``VTIMEZONE`` structure + as set out in `RFC 5545`_ Section 4.6.5 into one or more `tzinfo` objects. + + :param `fileobj`: + A file or stream in iCalendar format, which should be UTF-8 encoded + with CRLF endings. + + .. _`RFC 5545`: https://tools.ietf.org/html/rfc5545 + """ + def __init__(self, fileobj): + global rrule + from dateutil import rrule + + if isinstance(fileobj, string_types): + self._s = fileobj + # ical should be encoded in UTF-8 with CRLF + fileobj = open(fileobj, 'r') + else: + self._s = getattr(fileobj, 'name', repr(fileobj)) + fileobj = _nullcontext(fileobj) + + self._vtz = {} + + with fileobj as fobj: + self._parse_rfc(fobj.read()) + + def keys(self): + """ + Retrieves the available time zones as a list. + """ + return list(self._vtz.keys()) + + def get(self, tzid=None): + """ + Retrieve a :py:class:`datetime.tzinfo` object by its ``tzid``. + + :param tzid: + If there is exactly one time zone available, omitting ``tzid`` + or passing :py:const:`None` value returns it. Otherwise a valid + key (which can be retrieved from :func:`keys`) is required. + + :raises ValueError: + Raised if ``tzid`` is not specified but there are either more + or fewer than 1 zone defined. + + :returns: + Returns either a :py:class:`datetime.tzinfo` object representing + the relevant time zone or :py:const:`None` if the ``tzid`` was + not found. + """ + if tzid is None: + if len(self._vtz) == 0: + raise ValueError("no timezones defined") + elif len(self._vtz) > 1: + raise ValueError("more than one timezone available") + tzid = next(iter(self._vtz)) + + return self._vtz.get(tzid) + + def _parse_offset(self, s): + s = s.strip() + if not s: + raise ValueError("empty offset") + if s[0] in ('+', '-'): + signal = (-1, +1)[s[0] == '+'] + s = s[1:] + else: + signal = +1 + if len(s) == 4: + return (int(s[:2]) * 3600 + int(s[2:]) * 60) * signal + elif len(s) == 6: + return (int(s[:2]) * 3600 + int(s[2:4]) * 60 + int(s[4:])) * signal + else: + raise ValueError("invalid offset: " + s) + + def _parse_rfc(self, s): + lines = s.splitlines() + if not lines: + raise ValueError("empty string") + + # Unfold + i = 0 + while i < len(lines): + line = lines[i].rstrip() + if not line: + del lines[i] + elif i > 0 and line[0] == " ": + lines[i-1] += line[1:] + del lines[i] + else: + i += 1 + + tzid = None + comps = [] + invtz = False + comptype = None + for line in lines: + if not line: + continue + name, value = line.split(':', 1) + parms = name.split(';') + if not parms: + raise ValueError("empty property name") + name = parms[0].upper() + parms = parms[1:] + if invtz: + if name == "BEGIN": + if value in ("STANDARD", "DAYLIGHT"): + # Process component + pass + else: + raise ValueError("unknown component: "+value) + comptype = value + founddtstart = False + tzoffsetfrom = None + tzoffsetto = None + rrulelines = [] + tzname = None + elif name == "END": + if value == "VTIMEZONE": + if comptype: + raise ValueError("component not closed: "+comptype) + if not tzid: + raise ValueError("mandatory TZID not found") + if not comps: + raise ValueError( + "at least one component is needed") + # Process vtimezone + self._vtz[tzid] = _tzicalvtz(tzid, comps) + invtz = False + elif value == comptype: + if not founddtstart: + raise ValueError("mandatory DTSTART not found") + if tzoffsetfrom is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + if tzoffsetto is None: + raise ValueError( + "mandatory TZOFFSETFROM not found") + # Process component + rr = None + if rrulelines: + rr = rrule.rrulestr("\n".join(rrulelines), + compatible=True, + ignoretz=True, + cache=True) + comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto, + (comptype == "DAYLIGHT"), + tzname, rr) + comps.append(comp) + comptype = None + else: + raise ValueError("invalid component end: "+value) + elif comptype: + if name == "DTSTART": + # DTSTART in VTIMEZONE takes a subset of valid RRULE + # values under RFC 5545. + for parm in parms: + if parm != 'VALUE=DATE-TIME': + msg = ('Unsupported DTSTART param in ' + + 'VTIMEZONE: ' + parm) + raise ValueError(msg) + rrulelines.append(line) + founddtstart = True + elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"): + rrulelines.append(line) + elif name == "TZOFFSETFROM": + if parms: + raise ValueError( + "unsupported %s parm: %s " % (name, parms[0])) + tzoffsetfrom = self._parse_offset(value) + elif name == "TZOFFSETTO": + if parms: + raise ValueError( + "unsupported TZOFFSETTO parm: "+parms[0]) + tzoffsetto = self._parse_offset(value) + elif name == "TZNAME": + if parms: + raise ValueError( + "unsupported TZNAME parm: "+parms[0]) + tzname = value + elif name == "COMMENT": + pass + else: + raise ValueError("unsupported property: "+name) + else: + if name == "TZID": + if parms: + raise ValueError( + "unsupported TZID parm: "+parms[0]) + tzid = value + elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"): + pass + else: + raise ValueError("unsupported property: "+name) + elif name == "BEGIN" and value == "VTIMEZONE": + tzid = None + comps = [] + invtz = True + + def __repr__(self): + return "%s(%s)" % (self.__class__.__name__, repr(self._s)) + + +if sys.platform != "win32": + TZFILES = ["/etc/localtime", "localtime"] + TZPATHS = ["/usr/share/zoneinfo", + "/usr/lib/zoneinfo", + "/usr/share/lib/zoneinfo", + "/etc/zoneinfo"] +else: + TZFILES = [] + TZPATHS = [] + + +def __get_gettz(): + tzlocal_classes = (tzlocal,) + if tzwinlocal is not None: + tzlocal_classes += (tzwinlocal,) + + class GettzFunc(object): + """ + Retrieve a time zone object from a string representation + + This function is intended to retrieve the :py:class:`tzinfo` subclass + that best represents the time zone that would be used if a POSIX + `TZ variable`_ were set to the same value. + + If no argument or an empty string is passed to ``gettz``, local time + is returned: + + .. code-block:: python3 + + >>> gettz() + tzfile('/etc/localtime') + + This function is also the preferred way to map IANA tz database keys + to :class:`tzfile` objects: + + .. code-block:: python3 + + >>> gettz('Pacific/Kiritimati') + tzfile('/usr/share/zoneinfo/Pacific/Kiritimati') + + On Windows, the standard is extended to include the Windows-specific + zone names provided by the operating system: + + .. code-block:: python3 + + >>> gettz('Egypt Standard Time') + tzwin('Egypt Standard Time') + + Passing a GNU ``TZ`` style string time zone specification returns a + :class:`tzstr` object: + + .. code-block:: python3 + + >>> gettz('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + tzstr('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3') + + :param name: + A time zone name (IANA, or, on Windows, Windows keys), location of + a ``tzfile(5)`` zoneinfo file or ``TZ`` variable style time zone + specifier. An empty string, no argument or ``None`` is interpreted + as local time. + + :return: + Returns an instance of one of ``dateutil``'s :py:class:`tzinfo` + subclasses. + + .. versionchanged:: 2.7.0 + + After version 2.7.0, any two calls to ``gettz`` using the same + input strings will return the same object: + + .. code-block:: python3 + + >>> tz.gettz('America/Chicago') is tz.gettz('America/Chicago') + True + + In addition to improving performance, this ensures that + `"same zone" semantics`_ are used for datetimes in the same zone. + + + .. _`TZ variable`: + https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + + .. _`"same zone" semantics`: + https://blog.ganssle.io/articles/2018/02/aware-datetime-arithmetic.html + """ + def __init__(self): + + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache_size = 8 + self.__strong_cache = OrderedDict() + self._cache_lock = _thread.allocate_lock() + + def __call__(self, name=None): + with self._cache_lock: + rv = self.__instances.get(name, None) + + if rv is None: + rv = self.nocache(name=name) + if not (name is None + or isinstance(rv, tzlocal_classes) + or rv is None): + # tzlocal is slightly more complicated than the other + # time zone providers because it depends on environment + # at construction time, so don't cache that. + # + # We also cannot store weak references to None, so we + # will also not store that. + self.__instances[name] = rv + else: + # No need for strong caching, return immediately + return rv + + self.__strong_cache[name] = self.__strong_cache.pop(name, rv) + + if len(self.__strong_cache) > self.__strong_cache_size: + self.__strong_cache.popitem(last=False) + + return rv + + def set_cache_size(self, size): + with self._cache_lock: + self.__strong_cache_size = size + while len(self.__strong_cache) > size: + self.__strong_cache.popitem(last=False) + + def cache_clear(self): + with self._cache_lock: + self.__instances = weakref.WeakValueDictionary() + self.__strong_cache.clear() + + @staticmethod + def nocache(name=None): + """A non-cached version of gettz""" + tz = None + if not name: + try: + name = os.environ["TZ"] + except KeyError: + pass + if name is None or name == ":": + for filepath in TZFILES: + if not os.path.isabs(filepath): + filename = filepath + for path in TZPATHS: + filepath = os.path.join(path, filename) + if os.path.isfile(filepath): + break + else: + continue + if os.path.isfile(filepath): + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = tzlocal() + else: + try: + if name.startswith(":"): + name = name[1:] + except TypeError as e: + if isinstance(name, bytes): + new_msg = "gettz argument should be str, not bytes" + six.raise_from(TypeError(new_msg), e) + else: + raise + if os.path.isabs(name): + if os.path.isfile(name): + tz = tzfile(name) + else: + tz = None + else: + for path in TZPATHS: + filepath = os.path.join(path, name) + if not os.path.isfile(filepath): + filepath = filepath.replace(' ', '_') + if not os.path.isfile(filepath): + continue + try: + tz = tzfile(filepath) + break + except (IOError, OSError, ValueError): + pass + else: + tz = None + if tzwin is not None: + try: + tz = tzwin(name) + except (WindowsError, UnicodeEncodeError): + # UnicodeEncodeError is for Python 2.7 compat + tz = None + + if not tz: + from dateutil.zoneinfo import get_zonefile_instance + tz = get_zonefile_instance().get(name) + + if not tz: + for c in name: + # name is not a tzstr unless it has at least + # one offset. For short values of "name", an + # explicit for loop seems to be the fastest way + # To determine if a string contains a digit + if c in "0123456789": + try: + tz = tzstr(name) + except ValueError: + pass + break + else: + if name in ("GMT", "UTC"): + tz = UTC + elif name in time.tzname: + tz = tzlocal() + return tz + + return GettzFunc() + + +gettz = __get_gettz() +del __get_gettz + + +def datetime_exists(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + would fall in a gap. + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" exists in + ``tz``. + + .. versionadded:: 2.7.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + tz = dt.tzinfo + + dt = dt.replace(tzinfo=None) + + # This is essentially a test of whether or not the datetime can survive + # a round trip to UTC. + dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz) + dt_rt = dt_rt.replace(tzinfo=None) + + return dt == dt_rt + + +def datetime_ambiguous(dt, tz=None): + """ + Given a datetime and a time zone, determine whether or not a given datetime + is ambiguous (i.e if there are two times differentiated only by their DST + status). + + :param dt: + A :class:`datetime.datetime` (whose time zone will be ignored if ``tz`` + is provided.) + + :param tz: + A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If + ``None`` or not provided, the datetime's own time zone will be used. + + :return: + Returns a boolean value whether or not the "wall time" is ambiguous in + ``tz``. + + .. versionadded:: 2.6.0 + """ + if tz is None: + if dt.tzinfo is None: + raise ValueError('Datetime is naive and no time zone provided.') + + tz = dt.tzinfo + + # If a time zone defines its own "is_ambiguous" function, we'll use that. + is_ambiguous_fn = getattr(tz, 'is_ambiguous', None) + if is_ambiguous_fn is not None: + try: + return tz.is_ambiguous(dt) + except Exception: + pass + + # If it doesn't come out and tell us it's ambiguous, we'll just check if + # the fold attribute has any effect on this particular date and time. + dt = dt.replace(tzinfo=tz) + wall_0 = enfold(dt, fold=0) + wall_1 = enfold(dt, fold=1) + + same_offset = wall_0.utcoffset() == wall_1.utcoffset() + same_dst = wall_0.dst() == wall_1.dst() + + return not (same_offset and same_dst) + + +def resolve_imaginary(dt): + """ + Given a datetime that may be imaginary, return an existing datetime. + + This function assumes that an imaginary datetime represents what the + wall time would be in a zone had the offset transition not occurred, so + it will always fall forward by the transition's change in offset. + + .. doctest:: + + >>> from dateutil import tz + >>> from datetime import datetime + >>> NYC = tz.gettz('America/New_York') + >>> print(tz.resolve_imaginary(datetime(2017, 3, 12, 2, 30, tzinfo=NYC))) + 2017-03-12 03:30:00-04:00 + + >>> KIR = tz.gettz('Pacific/Kiritimati') + >>> print(tz.resolve_imaginary(datetime(1995, 1, 1, 12, 30, tzinfo=KIR))) + 1995-01-02 12:30:00+14:00 + + As a note, :func:`datetime.astimezone` is guaranteed to produce a valid, + existing datetime, so a round-trip to and from UTC is sufficient to get + an extant datetime, however, this generally "falls back" to an earlier time + rather than falling forward to the STD side (though no guarantees are made + about this behavior). + + :param dt: + A :class:`datetime.datetime` which may or may not exist. + + :return: + Returns an existing :class:`datetime.datetime`. If ``dt`` was not + imaginary, the datetime returned is guaranteed to be the same object + passed to the function. + + .. versionadded:: 2.7.0 + """ + if dt.tzinfo is not None and not datetime_exists(dt): + + curr_offset = (dt + datetime.timedelta(hours=24)).utcoffset() + old_offset = (dt - datetime.timedelta(hours=24)).utcoffset() + + dt += curr_offset - old_offset + + return dt + + +def _datetime_to_timestamp(dt): + """ + Convert a :class:`datetime.datetime` object to an epoch timestamp in + seconds since January 1, 1970, ignoring the time zone. + """ + return (dt.replace(tzinfo=None) - EPOCH).total_seconds() + + +if sys.version_info >= (3, 6): + def _get_supported_offset(second_offset): + return second_offset +else: + def _get_supported_offset(second_offset): + # For python pre-3.6, round to full-minutes if that's not the case. + # Python's datetime doesn't accept sub-minute timezones. Check + # http://python.org/sf/1447945 or https://bugs.python.org/issue5288 + # for some information. + old_offset = second_offset + calculated_offset = 60 * ((second_offset + 30) // 60) + return calculated_offset + + +try: + # Python 3.7 feature + from contextlib import nullcontext as _nullcontext +except ImportError: + class _nullcontext(object): + """ + Class for wrapping contexts so that they are passed through in a + with statement. + """ + def __init__(self, context): + self.context = context + + def __enter__(self): + return self.context + + def __exit__(*args, **kwargs): + pass + +# vim:ts=4:sw=4:et diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/win.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/win.py new file mode 100644 index 00000000..cde07ba7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tz/win.py @@ -0,0 +1,370 @@ +# -*- coding: utf-8 -*- +""" +This module provides an interface to the native time zone data on Windows, +including :py:class:`datetime.tzinfo` implementations. + +Attempting to import this module on a non-Windows platform will raise an +:py:obj:`ImportError`. +""" +# This code was originally contributed by Jeffrey Harris. +import datetime +import struct + +from six.moves import winreg +from six import text_type + +try: + import ctypes + from ctypes import wintypes +except ValueError: + # ValueError is raised on non-Windows systems for some horrible reason. + raise ImportError("Running tzwin on non-Windows system") + +from ._common import tzrangebase + +__all__ = ["tzwin", "tzwinlocal", "tzres"] + +ONEWEEK = datetime.timedelta(7) + +TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" +TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones" +TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" + + +def _settzkeyname(): + handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) + try: + winreg.OpenKey(handle, TZKEYNAMENT).Close() + TZKEYNAME = TZKEYNAMENT + except WindowsError: + TZKEYNAME = TZKEYNAME9X + handle.Close() + return TZKEYNAME + + +TZKEYNAME = _settzkeyname() + + +class tzres(object): + """ + Class for accessing ``tzres.dll``, which contains timezone name related + resources. + + .. versionadded:: 2.5.0 + """ + p_wchar = ctypes.POINTER(wintypes.WCHAR) # Pointer to a wide char + + def __init__(self, tzres_loc='tzres.dll'): + # Load the user32 DLL so we can load strings from tzres + user32 = ctypes.WinDLL('user32') + + # Specify the LoadStringW function + user32.LoadStringW.argtypes = (wintypes.HINSTANCE, + wintypes.UINT, + wintypes.LPWSTR, + ctypes.c_int) + + self.LoadStringW = user32.LoadStringW + self._tzres = ctypes.WinDLL(tzres_loc) + self.tzres_loc = tzres_loc + + def load_name(self, offset): + """ + Load a timezone name from a DLL offset (integer). + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.load_name(112)) + 'Eastern Standard Time' + + :param offset: + A positive integer value referring to a string from the tzres dll. + + .. note:: + + Offsets found in the registry are generally of the form + ``@tzres.dll,-114``. The offset in this case is 114, not -114. + + """ + resource = self.p_wchar() + lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR) + nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0) + return resource[:nchar] + + def name_from_string(self, tzname_str): + """ + Parse strings as returned from the Windows registry into the time zone + name as defined in the registry. + + >>> from dateutil.tzwin import tzres + >>> tzr = tzres() + >>> print(tzr.name_from_string('@tzres.dll,-251')) + 'Dateline Daylight Time' + >>> print(tzr.name_from_string('Eastern Standard Time')) + 'Eastern Standard Time' + + :param tzname_str: + A timezone name string as returned from a Windows registry key. + + :return: + Returns the localized timezone string from tzres.dll if the string + is of the form `@tzres.dll,-offset`, else returns the input string. + """ + if not tzname_str.startswith('@'): + return tzname_str + + name_splt = tzname_str.split(',-') + try: + offset = int(name_splt[1]) + except: + raise ValueError("Malformed timezone string.") + + return self.load_name(offset) + + +class tzwinbase(tzrangebase): + """tzinfo class based on win32's timezones available in the registry.""" + def __init__(self): + raise NotImplementedError('tzwinbase is an abstract base class') + + def __eq__(self, other): + # Compare on all relevant dimensions, including name. + if not isinstance(other, tzwinbase): + return NotImplemented + + return (self._std_offset == other._std_offset and + self._dst_offset == other._dst_offset and + self._stddayofweek == other._stddayofweek and + self._dstdayofweek == other._dstdayofweek and + self._stdweeknumber == other._stdweeknumber and + self._dstweeknumber == other._dstweeknumber and + self._stdhour == other._stdhour and + self._dsthour == other._dsthour and + self._stdminute == other._stdminute and + self._dstminute == other._dstminute and + self._std_abbr == other._std_abbr and + self._dst_abbr == other._dst_abbr) + + @staticmethod + def list(): + """Return a list of all time zones known to the system.""" + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZKEYNAME) as tzkey: + result = [winreg.EnumKey(tzkey, i) + for i in range(winreg.QueryInfoKey(tzkey)[0])] + return result + + def display(self): + """ + Return the display name of the time zone. + """ + return self._display + + def transitions(self, year): + """ + For a given year, get the DST on and off transition times, expressed + always on the standard time side. For zones with no transitions, this + function returns ``None``. + + :param year: + The year whose transitions you would like to query. + + :return: + Returns a :class:`tuple` of :class:`datetime.datetime` objects, + ``(dston, dstoff)`` for zones with an annual DST transition, or + ``None`` for fixed offset zones. + """ + + if not self.hasdst: + return None + + dston = picknthweekday(year, self._dstmonth, self._dstdayofweek, + self._dsthour, self._dstminute, + self._dstweeknumber) + + dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek, + self._stdhour, self._stdminute, + self._stdweeknumber) + + # Ambiguous dates default to the STD side + dstoff -= self._dst_base_offset + + return dston, dstoff + + def _get_hasdst(self): + return self._dstmonth != 0 + + @property + def _dst_base_offset(self): + return self._dst_base_offset_ + + +class tzwin(tzwinbase): + """ + Time zone object created from the zone info in the Windows registry + + These are similar to :py:class:`dateutil.tz.tzrange` objects in that + the time zone data is provided in the format of a single offset rule + for either 0 or 2 time zone transitions per year. + + :param: name + The name of a Windows time zone key, e.g. "Eastern Standard Time". + The full list of keys can be retrieved with :func:`tzwin.list`. + """ + + def __init__(self, name): + self._name = name + + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + keydict = valuestodict(tzkey) + + self._std_abbr = keydict["Std"] + self._dst_abbr = keydict["Dlt"] + + self._display = keydict["Display"] + + # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm + tup = struct.unpack("=3l16h", keydict["TZI"]) + stdoffset = -tup[0]-tup[1] # Bias + StandardBias * -1 + dstoffset = stdoffset-tup[2] # + DaylightBias * -1 + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs + # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx + (self._stdmonth, + self._stddayofweek, # Sunday = 0 + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[4:9] + + (self._dstmonth, + self._dstdayofweek, # Sunday = 0 + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[12:17] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwin(%s)" % repr(self._name) + + def __reduce__(self): + return (self.__class__, (self._name,)) + + +class tzwinlocal(tzwinbase): + """ + Class representing the local time zone information in the Windows registry + + While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time` + module) to retrieve time zone information, ``tzwinlocal`` retrieves the + rules directly from the Windows registry and creates an object like + :class:`dateutil.tz.tzwin`. + + Because Windows does not have an equivalent of :func:`time.tzset`, on + Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the + time zone settings *at the time that the process was started*, meaning + changes to the machine's time zone settings during the run of a program + on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`. + Because ``tzwinlocal`` reads the registry directly, it is unaffected by + this issue. + """ + def __init__(self): + with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle: + with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey: + keydict = valuestodict(tzlocalkey) + + self._std_abbr = keydict["StandardName"] + self._dst_abbr = keydict["DaylightName"] + + try: + tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME, + sn=self._std_abbr) + with winreg.OpenKey(handle, tzkeyname) as tzkey: + _keydict = valuestodict(tzkey) + self._display = _keydict["Display"] + except OSError: + self._display = None + + stdoffset = -keydict["Bias"]-keydict["StandardBias"] + dstoffset = stdoffset-keydict["DaylightBias"] + + self._std_offset = datetime.timedelta(minutes=stdoffset) + self._dst_offset = datetime.timedelta(minutes=dstoffset) + + # For reasons unclear, in this particular key, the day of week has been + # moved to the END of the SYSTEMTIME structure. + tup = struct.unpack("=8h", keydict["StandardStart"]) + + (self._stdmonth, + self._stdweeknumber, # Last = 5 + self._stdhour, + self._stdminute) = tup[1:5] + + self._stddayofweek = tup[7] + + tup = struct.unpack("=8h", keydict["DaylightStart"]) + + (self._dstmonth, + self._dstweeknumber, # Last = 5 + self._dsthour, + self._dstminute) = tup[1:5] + + self._dstdayofweek = tup[7] + + self._dst_base_offset_ = self._dst_offset - self._std_offset + self.hasdst = self._get_hasdst() + + def __repr__(self): + return "tzwinlocal()" + + def __str__(self): + # str will return the standard name, not the daylight name. + return "tzwinlocal(%s)" % repr(self._std_abbr) + + def __reduce__(self): + return (self.__class__, ()) + + +def picknthweekday(year, month, dayofweek, hour, minute, whichweek): + """ dayofweek == 0 means Sunday, whichweek 5 means last instance """ + first = datetime.datetime(year, month, 1, hour, minute) + + # This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6), + # Because 7 % 7 = 0 + weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1) + wd = weekdayone + ((whichweek - 1) * ONEWEEK) + if (wd.month != month): + wd -= ONEWEEK + + return wd + + +def valuestodict(key): + """Convert a registry key's values to a dictionary.""" + dout = {} + size = winreg.QueryInfoKey(key)[1] + tz_res = None + + for i in range(size): + key_name, value, dtype = winreg.EnumValue(key, i) + if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN: + # If it's a DWORD (32-bit integer), it's stored as unsigned - convert + # that to a proper signed integer + if value & (1 << 31): + value = value - (1 << 32) + elif dtype == winreg.REG_SZ: + # If it's a reference to the tzres DLL, load the actual string + if value.startswith('@tzres'): + tz_res = tz_res or tzres() + value = tz_res.name_from_string(value) + + value = value.rstrip('\x00') # Remove trailing nulls + + dout[key_name] = value + + return dout diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tzwin.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tzwin.py new file mode 100644 index 00000000..cebc673e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/tzwin.py @@ -0,0 +1,2 @@ +# tzwin has moved to dateutil.tz.win +from .tz.win import * diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/utils.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/utils.py new file mode 100644 index 00000000..44d9c994 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/utils.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" +This module offers general convenience and utility functions for dealing with +datetimes. + +.. versionadded:: 2.7.0 +""" +from __future__ import unicode_literals + +from datetime import datetime, time + + +def today(tzinfo=None): + """ + Returns a :py:class:`datetime` representing the current day at midnight + + :param tzinfo: + The time zone to attach (also used to determine the current day). + + :return: + A :py:class:`datetime.datetime` object representing the current day + at midnight. + """ + + dt = datetime.now(tzinfo) + return datetime.combine(dt.date(), time(0, tzinfo=tzinfo)) + + +def default_tzinfo(dt, tzinfo): + """ + Sets the ``tzinfo`` parameter on naive datetimes only + + This is useful for example when you are provided a datetime that may have + either an implicit or explicit time zone, such as when parsing a time zone + string. + + .. doctest:: + + >>> from dateutil.tz import tzoffset + >>> from dateutil.parser import parse + >>> from dateutil.utils import default_tzinfo + >>> dflt_tz = tzoffset("EST", -18000) + >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz)) + 2014-01-01 12:30:00+00:00 + >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz)) + 2014-01-01 12:30:00-05:00 + + :param dt: + The datetime on which to replace the time zone + + :param tzinfo: + The :py:class:`datetime.tzinfo` subclass instance to assign to + ``dt`` if (and only if) it is naive. + + :return: + Returns an aware :py:class:`datetime.datetime`. + """ + if dt.tzinfo is not None: + return dt + else: + return dt.replace(tzinfo=tzinfo) + + +def within_delta(dt1, dt2, delta): + """ + Useful for comparing two datetimes that may a negilible difference + to be considered equal. + """ + delta = abs(delta) + difference = dt1 - dt2 + return -delta <= difference <= delta diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py new file mode 100644 index 00000000..34f11ad6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +import warnings +import json + +from tarfile import TarFile +from pkgutil import get_data +from io import BytesIO + +from dateutil.tz import tzfile as _tzfile + +__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"] + +ZONEFILENAME = "dateutil-zoneinfo.tar.gz" +METADATA_FN = 'METADATA' + + +class tzfile(_tzfile): + def __reduce__(self): + return (gettz, (self._filename,)) + + +def getzoneinfofile_stream(): + try: + return BytesIO(get_data(__name__, ZONEFILENAME)) + except IOError as e: # TODO switch to FileNotFoundError? + warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror)) + return None + + +class ZoneInfoFile(object): + def __init__(self, zonefile_stream=None): + if zonefile_stream is not None: + with TarFile.open(fileobj=zonefile_stream) as tf: + self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name) + for zf in tf.getmembers() + if zf.isfile() and zf.name != METADATA_FN} + # deal with links: They'll point to their parent object. Less + # waste of memory + links = {zl.name: self.zones[zl.linkname] + for zl in tf.getmembers() if + zl.islnk() or zl.issym()} + self.zones.update(links) + try: + metadata_json = tf.extractfile(tf.getmember(METADATA_FN)) + metadata_str = metadata_json.read().decode('UTF-8') + self.metadata = json.loads(metadata_str) + except KeyError: + # no metadata in tar file + self.metadata = None + else: + self.zones = {} + self.metadata = None + + def get(self, name, default=None): + """ + Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method + for retrieving zones from the zone dictionary. + + :param name: + The name of the zone to retrieve. (Generally IANA zone names) + + :param default: + The value to return in the event of a missing key. + + .. versionadded:: 2.6.0 + + """ + return self.zones.get(name, default) + + +# The current API has gettz as a module function, although in fact it taps into +# a stateful class. So as a workaround for now, without changing the API, we +# will create a new "global" class instance the first time a user requests a +# timezone. Ugly, but adheres to the api. +# +# TODO: Remove after deprecation period. +_CLASS_ZONE_INSTANCE = [] + + +def get_zonefile_instance(new_instance=False): + """ + This is a convenience function which provides a :class:`ZoneInfoFile` + instance using the data provided by the ``dateutil`` package. By default, it + caches a single instance of the ZoneInfoFile object and returns that. + + :param new_instance: + If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and + used as the cached instance for the next call. Otherwise, new instances + are created only as necessary. + + :return: + Returns a :class:`ZoneInfoFile` object. + + .. versionadded:: 2.6 + """ + if new_instance: + zif = None + else: + zif = getattr(get_zonefile_instance, '_cached_instance', None) + + if zif is None: + zif = ZoneInfoFile(getzoneinfofile_stream()) + + get_zonefile_instance._cached_instance = zif + + return zif + + +def gettz(name): + """ + This retrieves a time zone from the local zoneinfo tarball that is packaged + with dateutil. + + :param name: + An IANA-style time zone name, as found in the zoneinfo file. + + :return: + Returns a :class:`dateutil.tz.tzfile` time zone object. + + .. warning:: + It is generally inadvisable to use this function, and it is only + provided for API compatibility with earlier versions. This is *not* + equivalent to ``dateutil.tz.gettz()``, which selects an appropriate + time zone based on the inputs, favoring system zoneinfo. This is ONLY + for accessing the dateutil-specific zoneinfo (which may be out of + date compared to the system zoneinfo). + + .. deprecated:: 2.6 + If you need to use a specific zoneinfofile over the system zoneinfo, + instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call + :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead. + + Use :func:`get_zonefile_instance` to retrieve an instance of the + dateutil-provided zoneinfo. + """ + warnings.warn("zoneinfo.gettz() will be removed in future versions, " + "to use the dateutil-provided zoneinfo files, instantiate a " + "ZoneInfoFile object and use ZoneInfoFile.zones.get() " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].zones.get(name) + + +def gettz_db_metadata(): + """ Get the zonefile metadata + + See `zonefile_metadata`_ + + :returns: + A dictionary with the database metadata + + .. deprecated:: 2.6 + See deprecation warning in :func:`zoneinfo.gettz`. To get metadata, + query the attribute ``zoneinfo.ZoneInfoFile.metadata``. + """ + warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future " + "versions, to use the dateutil-provided zoneinfo files, " + "ZoneInfoFile object and query the 'metadata' attribute " + "instead. See the documentation for details.", + DeprecationWarning) + + if len(_CLASS_ZONE_INSTANCE) == 0: + _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream())) + return _CLASS_ZONE_INSTANCE[0].metadata diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py new file mode 100644 index 00000000..78f0d1a0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py @@ -0,0 +1,53 @@ +import logging +import os +import tempfile +import shutil +import json +from subprocess import check_call +from tarfile import TarFile + +from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME + + +def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): + """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar* + + filename is the timezone tarball from ``ftp.iana.org/tz``. + + """ + tmpdir = tempfile.mkdtemp() + zonedir = os.path.join(tmpdir, "zoneinfo") + moduledir = os.path.dirname(__file__) + try: + with TarFile.open(filename) as tf: + for name in zonegroups: + tf.extract(name, tmpdir) + filepaths = [os.path.join(tmpdir, n) for n in zonegroups] + try: + check_call(["zic", "-d", zonedir] + filepaths) + except OSError as e: + _print_on_nosuchfile(e) + raise + # write metadata file + with open(os.path.join(zonedir, METADATA_FN), 'w') as f: + json.dump(metadata, f, indent=4, sort_keys=True) + target = os.path.join(moduledir, ZONEFILENAME) + with TarFile.open(target, "w:%s" % format) as tf: + for entry in os.listdir(zonedir): + entrypath = os.path.join(zonedir, entry) + tf.add(entrypath, entry) + finally: + shutil.rmtree(tmpdir) + + +def _print_on_nosuchfile(e): + """Print helpful troubleshooting message + + e is an exception raised by subprocess.check_call() + + """ + if e.errno == 2: + logging.error( + "Could not find zic. Perhaps you need to install " + "libc-bin or some other package that provides it, " + "or it's not in your PATH?") diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/METADATA new file mode 100644 index 00000000..7905cc97 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/METADATA @@ -0,0 +1,31 @@ +Metadata-Version: 2.1 +Name: distlib +Version: 0.3.0 +Summary: Distribution utilities +Home-page: https://bitbucket.org/pypa/distlib +Author: Vinay Sajip +Author-email: vinay_sajip@red-dove.com +License: Python license +Download-URL: https://bitbucket.org/pypa/distlib/downloads/distlib-0.3.0.zip +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Topic :: Software Development + +Low-level components of distutils2/packaging, augmented with higher-level APIs for making packaging easier. + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/RECORD new file mode 100644 index 00000000..39025d47 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/RECORD @@ -0,0 +1,48 @@ +distlib/__init__.py,sha256=gzl1hjUXmDGrqRyU7ZLjBwJGAcMimQbrZ22XPVaKaRE,581 +distlib/compat.py,sha256=xdNZmqFN5HwF30HjRn5M415pcC2kgXRBXn767xS8v-M,41404 +distlib/database.py,sha256=fhNzEDtb4HXrpxKyQvhVzDXcOiJlzrOM--UYnvCeZrI,51045 +distlib/index.py,sha256=SXKzpQCERctxYDMp_OLee2f0J0e19ZhGdCIoMlUfUQM,21066 +distlib/locators.py,sha256=c9E4cDEacJ_uKbuE5BqAVocoWp6rsuBGTkiNDQq3zV4,52100 +distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 +distlib/markers.py,sha256=6Ac3cCfFBERexiESWIOXmg-apIP8l2esafNSX3KMy-8,4387 +distlib/metadata.py,sha256=OhbCKmf5lswE8unWBopI1hj7tRpHp4ZbFvU4d6aAEMM,40234 +distlib/resources.py,sha256=2FGv0ZHF14KXjLIlL0R991lyQQGcewOS4mJ-5n-JVnc,10766 +distlib/scripts.py,sha256=OAkEwxRvIzX-VSfhEttQEKJFVLA47gbW0OgQXJRs7OQ,16998 +distlib/util.py,sha256=f2jZCPrcLCt6LcnC0gUy-Fur60tXD8reA7k4rDpHMDw,59845 +distlib/version.py,sha256=_n7F6juvQGAcn769E_SHa7fOcf5ERlEVymJ_EjPRwGw,23391 +distlib/wheel.py,sha256=bRtR5bNR_u_DwkwktN1bgZuwLVOJT1p_vNIUPyN8kJc,40452 +distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 +distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 +distlib/_backport/shutil.py,sha256=VW1t3uYqUjWZH7jV-6QiimLhnldoV5uIpH4EuiT1jfw,25647 +distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 +distlib/_backport/sysconfig.py,sha256=BQHFlb6pubCl_dvT1NjtzIthylofjKisox239stDg0U,26854 +distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 +distlib-0.3.0.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +distlib-0.3.0.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +distlib-0.3.0.dist-info/METADATA,sha256=K-1KbKXfYWPNkxh639g8H_epsxZqI8SOWXsMxZfD3j4,1251 +distlib-0.3.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +distlib-0.3.0.dist-info/top_level.txt,sha256=9BERqitu_vzyeyILOcGzX9YyA2AB_xlC4-81V6xoizk,8 +distlib-0.3.0.dist-info/RECORD,, +distlib/index.cpython-38.pyc,, +distlib/__pycache__,, +distlib/resources.cpython-38.pyc,, +distlib/_backport/sysconfig.cpython-38.pyc,, +distlib-0.3.0.dist-info/__pycache__,, +distlib/_backport/tarfile.cpython-38.pyc,, +distlib/util.cpython-38.pyc,, +distlib/_backport/__pycache__,, +distlib/scripts.cpython-38.pyc,, +distlib/_backport/shutil.cpython-38.pyc,, +distlib/locators.cpython-38.pyc,, +distlib-0.3.0.virtualenv,, +distlib/manifest.cpython-38.pyc,, +distlib-0.3.0.dist-info/INSTALLER,, +distlib/compat.cpython-38.pyc,, +distlib/markers.cpython-38.pyc,, +distlib/__init__.cpython-38.pyc,, +distlib/metadata.cpython-38.pyc,, +distlib/wheel.cpython-38.pyc,, +distlib/_backport/misc.cpython-38.pyc,, +distlib/database.cpython-38.pyc,, +distlib/version.cpython-38.pyc,, +distlib/_backport/__init__.cpython-38.pyc,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/top_level.txt new file mode 100644 index 00000000..f68bb072 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.dist-info/top_level.txt @@ -0,0 +1 @@ +distlib diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib-0.3.0.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/__init__.py new file mode 100644 index 00000000..e19aebdc --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2019 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import logging + +__version__ = '0.3.0' + +class DistlibException(Exception): + pass + +try: + from logging import NullHandler +except ImportError: # pragma: no cover + class NullHandler(logging.Handler): + def handle(self, record): pass + def emit(self, record): pass + def createLock(self): self.lock = None + +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/__init__.py new file mode 100644 index 00000000..f7dbf4c9 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/__init__.py @@ -0,0 +1,6 @@ +"""Modules copied from Python 3 standard libraries, for internal use only. + +Individual classes and functions are found in d2._backport.misc. Intended +usage is to always import things missing from 3.1 from that module: the +built-in/stdlib objects will be used if found. +""" diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/misc.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/misc.py new file mode 100644 index 00000000..cfb318d3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/misc.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Backports for individual classes and functions.""" + +import os +import sys + +__all__ = ['cache_from_source', 'callable', 'fsencode'] + + +try: + from imp import cache_from_source +except ImportError: + def cache_from_source(py_file, debug=__debug__): + ext = debug and 'c' or 'o' + return py_file + ext + + +try: + callable = callable +except NameError: + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode +except AttributeError: + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, str): + return filename.encode(sys.getfilesystemencoding()) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/shutil.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/shutil.py new file mode 100644 index 00000000..159e49ee --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/shutil.py @@ -0,0 +1,761 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Utility functions for copying and archiving files and directory trees. + +XXX The functions here don't copy the resource fork or other metadata on Mac. + +""" + +import os +import sys +import stat +from os.path import abspath +import fnmatch +import collections +import errno +from . import tarfile + +try: + import bz2 + _BZ2_SUPPORTED = True +except ImportError: + _BZ2_SUPPORTED = False + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + +__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2", + "copytree", "move", "rmtree", "Error", "SpecialFileError", + "ExecError", "make_archive", "get_archive_formats", + "register_archive_format", "unregister_archive_format", + "get_unpack_formats", "register_unpack_format", + "unregister_unpack_format", "unpack_archive", "ignore_patterns"] + +class Error(EnvironmentError): + pass + +class SpecialFileError(EnvironmentError): + """Raised when trying to do a kind of operation (e.g. copying) which is + not supported on a special file (e.g. a named pipe)""" + +class ExecError(EnvironmentError): + """Raised when a command could not be executed""" + +class ReadError(EnvironmentError): + """Raised when an archive cannot be read""" + +class RegistryError(Exception): + """Raised when a registry operation with the archiving + and unpacking registries fails""" + + +try: + WindowsError +except NameError: + WindowsError = None + +def copyfileobj(fsrc, fdst, length=16*1024): + """copy data from file-like object fsrc to file-like object fdst""" + while 1: + buf = fsrc.read(length) + if not buf: + break + fdst.write(buf) + +def _samefile(src, dst): + # Macintosh, Unix. + if hasattr(os.path, 'samefile'): + try: + return os.path.samefile(src, dst) + except OSError: + return False + + # All other platforms: check for same pathname. + return (os.path.normcase(os.path.abspath(src)) == + os.path.normcase(os.path.abspath(dst))) + +def copyfile(src, dst): + """Copy data from src to dst""" + if _samefile(src, dst): + raise Error("`%s` and `%s` are the same file" % (src, dst)) + + for fn in [src, dst]: + try: + st = os.stat(fn) + except OSError: + # File most likely does not exist + pass + else: + # XXX What about other special files? (sockets, devices...) + if stat.S_ISFIFO(st.st_mode): + raise SpecialFileError("`%s` is a named pipe" % fn) + + with open(src, 'rb') as fsrc: + with open(dst, 'wb') as fdst: + copyfileobj(fsrc, fdst) + +def copymode(src, dst): + """Copy mode bits from src to dst""" + if hasattr(os, 'chmod'): + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + os.chmod(dst, mode) + +def copystat(src, dst): + """Copy all stat info (mode bits, atime, mtime, flags) from src to dst""" + st = os.stat(src) + mode = stat.S_IMODE(st.st_mode) + if hasattr(os, 'utime'): + os.utime(dst, (st.st_atime, st.st_mtime)) + if hasattr(os, 'chmod'): + os.chmod(dst, mode) + if hasattr(os, 'chflags') and hasattr(st, 'st_flags'): + try: + os.chflags(dst, st.st_flags) + except OSError as why: + if (not hasattr(errno, 'EOPNOTSUPP') or + why.errno != errno.EOPNOTSUPP): + raise + +def copy(src, dst): + """Copy data and mode bits ("cp src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copymode(src, dst) + +def copy2(src, dst): + """Copy data and all stat info ("cp -p src dst"). + + The destination may be a directory. + + """ + if os.path.isdir(dst): + dst = os.path.join(dst, os.path.basename(src)) + copyfile(src, dst) + copystat(src, dst) + +def ignore_patterns(*patterns): + """Function that can be used as copytree() ignore parameter. + + Patterns is a sequence of glob-style patterns + that are used to exclude files""" + def _ignore_patterns(path, names): + ignored_names = [] + for pattern in patterns: + ignored_names.extend(fnmatch.filter(names, pattern)) + return set(ignored_names) + return _ignore_patterns + +def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, + ignore_dangling_symlinks=False): + """Recursively copy a directory tree. + + The destination directory must not already exist. + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. If the file pointed by the symlink doesn't + exist, an exception will be added in the list of errors raised in + an Error exception at the end of the copy process. + + You can set the optional ignore_dangling_symlinks flag to true if you + want to silence this exception. Notice that this has no effect on + platforms that don't support os.symlink. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + The optional copy_function argument is a callable that will be used + to copy each file. It will be called with the source path and the + destination path as arguments. By default, copy2() is used, but any + function that supports the same signature (like copy()) can be used. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if os.path.islink(srcname): + linkto = os.readlink(srcname) + if symlinks: + os.symlink(linkto, dstname) + else: + # ignore dangling symlink if the flag is on + if not os.path.exists(linkto) and ignore_dangling_symlinks: + continue + # otherwise let the copy occurs. copy2 will raise an error + copy_function(srcname, dstname) + elif os.path.isdir(srcname): + copytree(srcname, dstname, symlinks, ignore, copy_function) + else: + # Will raise a SpecialFileError for unsupported file types + copy_function(srcname, dstname) + # catch the Error from the recursive copytree so that we can + # continue with other files + except Error as err: + errors.extend(err.args[0]) + except EnvironmentError as why: + errors.append((srcname, dstname, str(why))) + try: + copystat(src, dst) + except OSError as why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error(errors) + +def rmtree(path, ignore_errors=False, onerror=None): + """Recursively delete a directory tree. + + If ignore_errors is set, errors are ignored; otherwise, if onerror + is set, it is called to handle the error with arguments (func, + path, exc_info) where func is os.listdir, os.remove, or os.rmdir; + path is the argument to that function that caused it to fail; and + exc_info is a tuple returned by sys.exc_info(). If ignore_errors + is false and onerror is None, an exception is raised. + + """ + if ignore_errors: + def onerror(*args): + pass + elif onerror is None: + def onerror(*args): + raise + try: + if os.path.islink(path): + # symlinks to directories are forbidden, see bug #1669 + raise OSError("Cannot call rmtree on a symbolic link") + except OSError: + onerror(os.path.islink, path, sys.exc_info()) + # can't continue even if onerror hook returns + return + names = [] + try: + names = os.listdir(path) + except os.error: + onerror(os.listdir, path, sys.exc_info()) + for name in names: + fullname = os.path.join(path, name) + try: + mode = os.lstat(fullname).st_mode + except os.error: + mode = 0 + if stat.S_ISDIR(mode): + rmtree(fullname, ignore_errors, onerror) + else: + try: + os.remove(fullname) + except os.error: + onerror(os.remove, fullname, sys.exc_info()) + try: + os.rmdir(path) + except os.error: + onerror(os.rmdir, path, sys.exc_info()) + + +def _basename(path): + # A basename() variant which first strips the trailing slash, if present. + # Thus we always get the last component of the path, even for directories. + return os.path.basename(path.rstrip(os.path.sep)) + +def move(src, dst): + """Recursively move a file or directory to another location. This is + similar to the Unix "mv" command. + + If the destination is a directory or a symlink to a directory, the source + is moved inside the directory. The destination path must not already + exist. + + If the destination already exists but is not a directory, it may be + overwritten depending on os.rename() semantics. + + If the destination is on our current filesystem, then rename() is used. + Otherwise, src is copied to the destination and then removed. + A lot more could be done here... A look at a mv.c shows a lot of + the issues this implementation glosses over. + + """ + real_dst = dst + if os.path.isdir(dst): + if _samefile(src, dst): + # We might be on a case insensitive filesystem, + # perform the rename anyway. + os.rename(src, dst) + return + + real_dst = os.path.join(dst, _basename(src)) + if os.path.exists(real_dst): + raise Error("Destination path '%s' already exists" % real_dst) + try: + os.rename(src, real_dst) + except OSError: + if os.path.isdir(src): + if _destinsrc(src, dst): + raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) + copytree(src, real_dst, symlinks=True) + rmtree(src) + else: + copy2(src, real_dst) + os.unlink(src) + +def _destinsrc(src, dst): + src = abspath(src) + dst = abspath(dst) + if not src.endswith(os.path.sep): + src += os.path.sep + if not dst.endswith(os.path.sep): + dst += os.path.sep + return dst.startswith(src) + +def _get_gid(name): + """Returns a gid, given a group name.""" + if getgrnam is None or name is None: + return None + try: + result = getgrnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _get_uid(name): + """Returns an uid, given a user name.""" + if getpwnam is None or name is None: + return None + try: + result = getpwnam(name) + except KeyError: + result = None + if result is not None: + return result[2] + return None + +def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, + owner=None, group=None, logger=None): + """Create a (possibly compressed) tar file from all the files under + 'base_dir'. + + 'compress' must be "gzip" (the default), "bzip2", or None. + + 'owner' and 'group' can be used to define an owner and a group for the + archive that is being built. If not provided, the current owner and group + will be used. + + The output tar file will be named 'base_name' + ".tar", possibly plus + the appropriate compression extension (".gz", or ".bz2"). + + Returns the output filename. + """ + tar_compression = {'gzip': 'gz', None: ''} + compress_ext = {'gzip': '.gz'} + + if _BZ2_SUPPORTED: + tar_compression['bzip2'] = 'bz2' + compress_ext['bzip2'] = '.bz2' + + # flags for compression program, each element of list will be an argument + if compress is not None and compress not in compress_ext: + raise ValueError("bad value for 'compress', or compression format not " + "supported : {0}".format(compress)) + + archive_name = base_name + '.tar' + compress_ext.get(compress, '') + archive_dir = os.path.dirname(archive_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # creating the tarball + if logger is not None: + logger.info('Creating tar archive') + + uid = _get_uid(owner) + gid = _get_gid(group) + + def _set_uid_gid(tarinfo): + if gid is not None: + tarinfo.gid = gid + tarinfo.gname = group + if uid is not None: + tarinfo.uid = uid + tarinfo.uname = owner + return tarinfo + + if not dry_run: + tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + return archive_name + +def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): + # XXX see if we want to keep an external call here + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + from distutils.errors import DistutilsExecError + from distutils.spawn import spawn + try: + spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise ExecError("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename + +def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): + """Create a zip file from all the files under 'base_dir'. + + The output zip file will be named 'base_name' + ".zip". Uses either the + "zipfile" Python module (if available) or the InfoZIP "zip" utility + (if installed and found on the default search path). If neither tool is + available, raises ExecError. Returns the name of the output zip + file. + """ + zip_filename = base_name + ".zip" + archive_dir = os.path.dirname(base_name) + + if not os.path.exists(archive_dir): + if logger is not None: + logger.info("creating %s", archive_dir) + if not dry_run: + os.makedirs(archive_dir) + + # If zipfile module is not available, try spawning an external 'zip' + # command. + try: + import zipfile + except ImportError: + zipfile = None + + if zipfile is None: + _call_external_zip(base_dir, zip_filename, verbose, dry_run) + else: + if logger is not None: + logger.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + zip.close() + + return zip_filename + +_ARCHIVE_FORMATS = { + 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), + 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), + 'zip': (_make_zipfile, [], "ZIP file"), + } + +if _BZ2_SUPPORTED: + _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], + "bzip2'ed tar-file") + +def get_archive_formats(): + """Returns a list of supported formats for archiving and unarchiving. + + Each element of the returned sequence is a tuple (name, description) + """ + formats = [(name, registry[2]) for name, registry in + _ARCHIVE_FORMATS.items()] + formats.sort() + return formats + +def register_archive_format(name, function, extra_args=None, description=''): + """Registers an archive format. + + name is the name of the format. function is the callable that will be + used to create archives. If provided, extra_args is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_archive_formats() function. + """ + if extra_args is None: + extra_args = [] + if not isinstance(function, collections.Callable): + raise TypeError('The %s object is not callable' % function) + if not isinstance(extra_args, (tuple, list)): + raise TypeError('extra_args needs to be a sequence') + for element in extra_args: + if not isinstance(element, (tuple, list)) or len(element) !=2: + raise TypeError('extra_args elements are : (arg_name, value)') + + _ARCHIVE_FORMATS[name] = (function, extra_args, description) + +def unregister_archive_format(name): + del _ARCHIVE_FORMATS[name] + +def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, + dry_run=0, owner=None, group=None, logger=None): + """Create an archive file (eg. zip or tar). + + 'base_name' is the name of the file to create, minus any format-specific + extension; 'format' is the archive format: one of "zip", "tar", "bztar" + or "gztar". + + 'root_dir' is a directory that will be the root directory of the + archive; ie. we typically chdir into 'root_dir' before creating the + archive. 'base_dir' is the directory where we start archiving from; + ie. 'base_dir' will be the common prefix of all files and + directories in the archive. 'root_dir' and 'base_dir' both default + to the current directory. Returns the name of the archive file. + + 'owner' and 'group' are used when creating a tar archive. By default, + uses the current owner and group. + """ + save_cwd = os.getcwd() + if root_dir is not None: + if logger is not None: + logger.debug("changing into '%s'", root_dir) + base_name = os.path.abspath(base_name) + if not dry_run: + os.chdir(root_dir) + + if base_dir is None: + base_dir = os.curdir + + kwargs = {'dry_run': dry_run, 'logger': logger} + + try: + format_info = _ARCHIVE_FORMATS[format] + except KeyError: + raise ValueError("unknown archive format '%s'" % format) + + func = format_info[0] + for arg, val in format_info[1]: + kwargs[arg] = val + + if format != 'zip': + kwargs['owner'] = owner + kwargs['group'] = group + + try: + filename = func(base_name, base_dir, **kwargs) + finally: + if root_dir is not None: + if logger is not None: + logger.debug("changing back to '%s'", save_cwd) + os.chdir(save_cwd) + + return filename + + +def get_unpack_formats(): + """Returns a list of supported formats for unpacking. + + Each element of the returned sequence is a tuple + (name, extensions, description) + """ + formats = [(name, info[0], info[3]) for name, info in + _UNPACK_FORMATS.items()] + formats.sort() + return formats + +def _check_unpack_options(extensions, function, extra_args): + """Checks what gets registered as an unpacker.""" + # first make sure no other unpacker is registered for this extension + existing_extensions = {} + for name, info in _UNPACK_FORMATS.items(): + for ext in info[0]: + existing_extensions[ext] = name + + for extension in extensions: + if extension in existing_extensions: + msg = '%s is already registered for "%s"' + raise RegistryError(msg % (extension, + existing_extensions[extension])) + + if not isinstance(function, collections.Callable): + raise TypeError('The registered function must be a callable') + + +def register_unpack_format(name, extensions, function, extra_args=None, + description=''): + """Registers an unpack format. + + `name` is the name of the format. `extensions` is a list of extensions + corresponding to the format. + + `function` is the callable that will be + used to unpack archives. The callable will receive archives to unpack. + If it's unable to handle an archive, it needs to raise a ReadError + exception. + + If provided, `extra_args` is a sequence of + (name, value) tuples that will be passed as arguments to the callable. + description can be provided to describe the format, and will be returned + by the get_unpack_formats() function. + """ + if extra_args is None: + extra_args = [] + _check_unpack_options(extensions, function, extra_args) + _UNPACK_FORMATS[name] = extensions, function, extra_args, description + +def unregister_unpack_format(name): + """Removes the pack format from the registry.""" + del _UNPACK_FORMATS[name] + +def _ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + if not os.path.isdir(dirname): + os.makedirs(dirname) + +def _unpack_zipfile(filename, extract_dir): + """Unpack zip `filename` to `extract_dir` + """ + try: + import zipfile + except ImportError: + raise ReadError('zlib not supported, cannot unpack this archive.') + + if not zipfile.is_zipfile(filename): + raise ReadError("%s is not a zip file" % filename) + + zip = zipfile.ZipFile(filename) + try: + for info in zip.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name: + continue + + target = os.path.join(extract_dir, *name.split('/')) + if not target: + continue + + _ensure_directory(target) + if not name.endswith('/'): + # file + data = zip.read(info.filename) + f = open(target, 'wb') + try: + f.write(data) + finally: + f.close() + del data + finally: + zip.close() + +def _unpack_tarfile(filename, extract_dir): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError: + raise ReadError( + "%s is not a compressed or uncompressed tar file" % filename) + try: + tarobj.extractall(extract_dir) + finally: + tarobj.close() + +_UNPACK_FORMATS = { + 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), + 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), + 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") + } + +if _BZ2_SUPPORTED: + _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], + "bzip2'ed tar-file") + +def _find_unpack_format(filename): + for name, info in _UNPACK_FORMATS.items(): + for extension in info[0]: + if filename.endswith(extension): + return name + return None + +def unpack_archive(filename, extract_dir=None, format=None): + """Unpack an archive. + + `filename` is the name of the archive. + + `extract_dir` is the name of the target directory, where the archive + is unpacked. If not provided, the current working directory is used. + + `format` is the archive format: one of "zip", "tar", or "gztar". Or any + other registered format. If not provided, unpack_archive will use the + filename extension and see if an unpacker was registered for that + extension. + + In case none is found, a ValueError is raised. + """ + if extract_dir is None: + extract_dir = os.getcwd() + + if format is not None: + try: + format_info = _UNPACK_FORMATS[format] + except KeyError: + raise ValueError("Unknown unpack format '{0}'".format(format)) + + func = format_info[1] + func(filename, extract_dir, **dict(format_info[2])) + else: + # we need to look at the registered unpackers supported extensions + format = _find_unpack_format(filename) + if format is None: + raise ReadError("Unknown archive format '{0}'".format(filename)) + + func = _UNPACK_FORMATS[format][1] + kwargs = dict(_UNPACK_FORMATS[format][2]) + func(filename, extract_dir, **kwargs) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.cfg b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.cfg new file mode 100644 index 00000000..1746bd01 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[posix_prefix] +# Configuration directories. Some of these come straight out of the +# configure script. They are for implementing the other variables, not to +# be used directly in [resource_locations]. +confdir = /etc +datadir = /usr/share +libdir = /usr/lib +statedir = /var +# User resource directory +local = ~/.local/{distribution.name} + +stdlib = {base}/lib/python{py_version_short} +platstdlib = {platbase}/lib/python{py_version_short} +purelib = {base}/lib/python{py_version_short}/site-packages +platlib = {platbase}/lib/python{py_version_short}/site-packages +include = {base}/include/python{py_version_short}{abiflags} +platinclude = {platbase}/include/python{py_version_short}{abiflags} +data = {base} + +[posix_home] +stdlib = {base}/lib/python +platstdlib = {base}/lib/python +purelib = {base}/lib/python +platlib = {base}/lib/python +include = {base}/include/python +platinclude = {base}/include/python +scripts = {base}/bin +data = {base} + +[nt] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2_home] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[nt_user] +stdlib = {userbase}/Python{py_version_nodot} +platstdlib = {userbase}/Python{py_version_nodot} +purelib = {userbase}/Python{py_version_nodot}/site-packages +platlib = {userbase}/Python{py_version_nodot}/site-packages +include = {userbase}/Python{py_version_nodot}/Include +scripts = {userbase}/Scripts +data = {userbase} + +[posix_user] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[osx_framework_user] +stdlib = {userbase}/lib/python +platstdlib = {userbase}/lib/python +purelib = {userbase}/lib/python/site-packages +platlib = {userbase}/lib/python/site-packages +include = {userbase}/include +scripts = {userbase}/bin +data = {userbase} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.py new file mode 100644 index 00000000..b470a373 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/sysconfig.py @@ -0,0 +1,786 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Access to Python's configuration information.""" + +import codecs +import os +import re +import sys +from os.path import pardir, realpath +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +__all__ = [ + 'get_config_h_filename', + 'get_config_var', + 'get_config_vars', + 'get_makefile_filename', + 'get_path', + 'get_path_names', + 'get_paths', + 'get_platform', + 'get_python_version', + 'get_scheme_names', + 'parse_config_h', +] + + +def _safe_realpath(path): + try: + return realpath(path) + except OSError: + return path + + +if sys.executable: + _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) +else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + _PROJECT_BASE = _safe_realpath(os.getcwd()) + +if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) + + +def is_python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): + return True + return False + +_PYTHON_BUILD = is_python_build() + +_cfg_read = False + +def _ensure_cfg_read(): + global _cfg_read + if not _cfg_read: + from ..resources import finder + backport_package = __name__.rsplit('.', 1)[0] + _finder = finder(backport_package) + _cfgfile = _finder.find('sysconfig.cfg') + assert _cfgfile, 'sysconfig.cfg exists' + with _cfgfile.as_stream() as s: + _SCHEMES.readfp(s) + if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + _SCHEMES.set(scheme, 'include', '{srcdir}/Include') + _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') + + _cfg_read = True + + +_SCHEMES = configparser.RawConfigParser() +_VAR_REPL = re.compile(r'\{([^{]*?)\}') + +def _expand_globals(config): + _ensure_cfg_read() + if config.has_section('globals'): + globals = config.items('globals') + else: + globals = tuple() + + sections = config.sections() + for section in sections: + if section == 'globals': + continue + for option, value in globals: + if config.has_option(section, option): + continue + config.set(section, option, value) + config.remove_section('globals') + + # now expanding local variables defined in the cfg file + # + for section in config.sections(): + variables = dict(config.items(section)) + + def _replacer(matchobj): + name = matchobj.group(1) + if name in variables: + return variables[name] + return matchobj.group(0) + + for option, value in config.items(section): + config.set(section, option, _VAR_REPL.sub(_replacer, value)) + +#_expand_globals(_SCHEMES) + +_PY_VERSION = '%s.%s.%s' % sys.version_info[:3] +_PY_VERSION_SHORT = '%s.%s' % sys.version_info[:2] +_PY_VERSION_SHORT_NO_DOT = '%s%s' % sys.version_info[:2] +_PREFIX = os.path.normpath(sys.prefix) +_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +_CONFIG_VARS = None +_USER_BASE = None + + +def _subst_vars(path, local_vars): + """In the string `path`, replace tokens like {some.thing} with the + corresponding value from the map `local_vars`. + + If there is no corresponding value, leave the token unchanged. + """ + def _replacer(matchobj): + name = matchobj.group(1) + if name in local_vars: + return local_vars[name] + elif name in os.environ: + return os.environ[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, path) + + +def _extend_dict(target_dict, other_dict): + target_keys = target_dict.keys() + for key, value in other_dict.items(): + if key in target_keys: + continue + target_dict[key] = value + + +def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} + _extend_dict(vars, get_config_vars()) + + for key, value in _SCHEMES.items(scheme): + if os.name in ('posix', 'nt'): + value = os.path.expanduser(value) + res[key] = os.path.normpath(_subst_vars(value, vars)) + return res + + +def format_value(value, vars): + def _replacer(matchobj): + name = matchobj.group(1) + if name in vars: + return vars[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, value) + + +def _get_default_scheme(): + if os.name == 'posix': + # the default scheme for posix is posix_prefix + return 'posix_prefix' + return os.name + + +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + # what about 'os2emx', 'riscos' ? + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + return env_base + else: + return joinuser(base, "Python") + + if sys.platform == "darwin": + framework = get_config_var("PYTHONFRAMEWORK") + if framework: + if env_base: + return env_base + else: + return joinuser("~", "Library", framework, "%d.%d" % + sys.version_info[:2]) + + if env_base: + return env_base + else: + return joinuser("~", ".local") + + +def _parse_makefile(filename, vars=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + # Regexes needed for parsing Makefile (and similar syntaxes, + # like old-style Setup files). + _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") + _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") + _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + + if vars is None: + vars = {} + done = {} + notdone = {} + + with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: + lines = f.readlines() + + for line in lines: + if line.startswith('#') or line.strip() == '': + continue + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m is not None: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if (name.startswith('PY_') and + name[3:] in renamed_variables): + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + + else: + done[n] = item = "" + + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: + value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + variables.remove(name) + + if (name.startswith('PY_') and + name[3:] in renamed_variables): + + name = name[3:] + if name not in done: + done[name] = value + + else: + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + vars.update(done) + return vars + + +def get_makefile_filename(): + """Return the path of the Makefile.""" + if _PYTHON_BUILD: + return os.path.join(_PROJECT_BASE, "Makefile") + if hasattr(sys, 'abiflags'): + config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) + else: + config_dir_name = 'config' + return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') + + +def _init_posix(vars): + """Initialize the module as appropriate for POSIX systems.""" + # load the installed Makefile: + makefile = get_makefile_filename() + try: + _parse_makefile(makefile, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % makefile + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # load the installed pyconfig.h: + config_h = get_config_h_filename() + try: + with open(config_h) as f: + parse_config_h(f, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % config_h + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if _PYTHON_BUILD: + vars['LDSHARED'] = vars['BLDSHARED'] + + +def _init_non_posix(vars): + """Initialize the module as appropriate for NT""" + # set basic install directories + vars['LIBDEST'] = get_path('stdlib') + vars['BINLIBDEST'] = get_path('platstdlib') + vars['INCLUDEPY'] = get_path('include') + vars['SO'] = '.pyd' + vars['EXE'] = '.exe' + vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT + vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + +# +# public APIs +# + + +def parse_config_h(fp, vars=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if vars is None: + vars = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + + while True: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: + v = int(v) + except ValueError: + pass + vars[n] = v + else: + m = undef_rx.match(line) + if m: + vars[m.group(1)] = 0 + return vars + + +def get_config_h_filename(): + """Return the path of pyconfig.h.""" + if _PYTHON_BUILD: + if os.name == "nt": + inc_dir = os.path.join(_PROJECT_BASE, "PC") + else: + inc_dir = _PROJECT_BASE + else: + inc_dir = get_path('platinclude') + return os.path.join(inc_dir, 'pyconfig.h') + + +def get_scheme_names(): + """Return a tuple containing the schemes names.""" + return tuple(sorted(_SCHEMES.sections())) + + +def get_path_names(): + """Return a tuple containing the paths names.""" + # xxx see if we want a static list + return _SCHEMES.options('posix_prefix') + + +def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): + """Return a mapping containing an install scheme. + + ``scheme`` is the install scheme name. If not provided, it will + return the default scheme for the current platform. + """ + _ensure_cfg_read() + if expand: + return _expand_vars(scheme, vars) + else: + return dict(_SCHEMES.items(scheme)) + + +def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): + """Return a path corresponding to the scheme. + + ``scheme`` is the install scheme name. + """ + return get_paths(scheme, vars, expand)[name] + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. + + On Unix, this means every variable defined in Python's installed Makefile; + On Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _CONFIG_VARS + if _CONFIG_VARS is None: + _CONFIG_VARS = {} + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # distutils2 module. + _CONFIG_VARS['prefix'] = _PREFIX + _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX + _CONFIG_VARS['py_version'] = _PY_VERSION + _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT + _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] + _CONFIG_VARS['base'] = _PREFIX + _CONFIG_VARS['platbase'] = _EXEC_PREFIX + _CONFIG_VARS['projectbase'] = _PROJECT_BASE + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + + if os.name in ('nt', 'os2'): + _init_non_posix(_CONFIG_VARS) + if os.name == 'posix': + _init_posix(_CONFIG_VARS) + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + if sys.version >= '2.6': + _CONFIG_VARS['userbase'] = _getuserbase() + + if 'srcdir' not in _CONFIG_VARS: + _CONFIG_VARS['srcdir'] = _PROJECT_BASE + else: + _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) + + # Convert srcdir into an absolute path if it appears necessary. + # Normally it is relative to the build directory. However, during + # testing, for example, we might be running a non-installed python + # from a different directory. + if _PYTHON_BUILD and os.name == "posix": + base = _PROJECT_BASE + try: + cwd = os.getcwd() + except OSError: + cwd = None + if (not os.path.isabs(_CONFIG_VARS['srcdir']) and + base != cwd): + # srcdir is relative and we are not in the same directory + # as the executable. Assume executable is in the build + # directory and make srcdir absolute. + srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) + _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) + + if sys.platform == 'darwin': + kernel_version = os.uname()[2] # Kernel version (8.4.3) + major_version = int(kernel_version.split('.')[0]) + + if major_version < 8: + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _CONFIG_VARS[key] = flags + else: + # Allow the user to override the architecture flags using + # an environment variable. + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _CONFIG_VARS[key] = flags + + # If we're on OSX 10.5 or later and the user tries to + # compiles an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. + # + # The major usecase for this is users using a Python.org + # binary installer on OSX 10.6: that installer uses + # the 10.4u SDK, but that SDK is not installed by default + # when you install Xcode. + # + CFLAGS = _CONFIG_VARS.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', CFLAGS) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags) + _CONFIG_VARS[key] = flags + + if args: + vals = [] + for name in args: + vals.append(_CONFIG_VARS.get(name)) + return vals + else: + return _CONFIG_VARS + + +def get_config_var(name): + """Return the value of a single variable using the dictionary returned by + 'get_config_vars()'. + + Equivalent to get_config_vars().get(name) + """ + return get_config_vars().get(name) + + +def get_platform(): + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name + and version and the architecture (as supplied by 'os.uname()'), + although the exact information included depends on the OS; eg. for IRIX + the architecture isn't particularly important (IRIX only runs on SGI + hardware), but for Linux the kernel version isn't particularly + important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + irix-5.3 + irix64-6.2 + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win-ia64 (64bit Windows on Itanium) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + """ + if os.name == 'nt': + # sniff sys.version for architecture. + prefix = " bit (" + i = sys.version.find(prefix) + if i == -1: + return sys.platform + j = sys.version.find(")", i) + look = sys.version[i+len(prefix):j].lower() + if look == 'amd64': + return 'win-amd64' + if look == 'itanium': + return 'win-ia64' + return sys.platform + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters + # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # fall through to standard osname-release-machine representation + elif osname[:4] == "irix": # could be "irix64"! + return "%s-%s" % (osname, release) + elif osname[:3] == "aix": + return "%s-%s.%s" % (osname, version, release) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile(r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + cfgvars = get_config_vars() + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + + if True: + # Always calculate the release of the running machine, + # needed to determine if we can build fat binaries or not. + + macrelease = macver + # Get the system version. Reading this plist is a documented + # way to get the system version (see the documentation for + # the Gestalt Manager) + try: + f = open('/System/Library/CoreServices/SystemVersion.plist') + except IOError: + # We're on a plain darwin box, fall back to the default + # behaviour. + pass + else: + try: + m = re.search(r'ProductUserVisibleVersion\s*' + r'(.*?)', f.read()) + finally: + f.close() + if m is not None: + macrelease = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + if not macver: + macver = macrelease + + if macver: + release = macver + osname = "macosx" + + if ((macrelease + '.') >= '10.4.' and + '-arch' in get_config_vars().get('CFLAGS', '').strip()): + # The universal build will build fat binaries, but not on + # systems before 10.4 + # + # Try to detect 4-way universal builds, those have machine-type + # 'universal' instead of 'fat'. + + machine = 'fat' + cflags = get_config_vars().get('CFLAGS') + + archs = re.findall(r'-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxsize >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxsize >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return "%s-%s-%s" % (osname, release, machine) + + +def get_python_version(): + return _PY_VERSION_SHORT + + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print('%s: ' % (title)) + print('\t%s = "%s"' % (key, value)) + + +def _main(): + """Display all information sysconfig detains.""" + print('Platform: "%s"' % get_platform()) + print('Python version: "%s"' % get_python_version()) + print('Current installation scheme: "%s"' % _get_default_scheme()) + print() + _print_dict('Paths', get_paths()) + print() + _print_dict('Variables', get_config_vars()) + + +if __name__ == '__main__': + _main() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/tarfile.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/tarfile.py new file mode 100644 index 00000000..d66d8566 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/_backport/tarfile.py @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------- +# tarfile.py +#------------------------------------------------------------------- +# Copyright (C) 2002 Lars Gustaebel +# All rights reserved. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +from __future__ import print_function + +"""Read from and write to tar format archives. +""" + +__version__ = "$Revision$" + +version = "0.9.0" +__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" +__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" +__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" +__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." + +#--------- +# Imports +#--------- +import sys +import os +import stat +import errno +import time +import struct +import copy +import re + +try: + import grp, pwd +except ImportError: + grp = pwd = None + +# os.symlink on Windows prior to 6.0 raises NotImplementedError +symlink_exception = (AttributeError, NotImplementedError) +try: + # WindowsError (1314) will be raised if the caller does not hold the + # SeCreateSymbolicLinkPrivilege privilege + symlink_exception += (WindowsError,) +except NameError: + pass + +# from tarfile import * +__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] + +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins + +_open = builtins.open # Since 'open' is TarFile.open + +#--------------------------------------------------------- +# tar constants +#--------------------------------------------------------- +NUL = b"\0" # the null character +BLOCKSIZE = 512 # length of processing blocks +RECORDSIZE = BLOCKSIZE * 20 # length of records +GNU_MAGIC = b"ustar \0" # magic gnu tar string +POSIX_MAGIC = b"ustar\x0000" # magic posix tar string + +LENGTH_NAME = 100 # maximum length of a filename +LENGTH_LINK = 100 # maximum length of a linkname +LENGTH_PREFIX = 155 # maximum length of the prefix field + +REGTYPE = b"0" # regular file +AREGTYPE = b"\0" # regular file +LNKTYPE = b"1" # link (inside tarfile) +SYMTYPE = b"2" # symbolic link +CHRTYPE = b"3" # character special device +BLKTYPE = b"4" # block special device +DIRTYPE = b"5" # directory +FIFOTYPE = b"6" # fifo special device +CONTTYPE = b"7" # contiguous file + +GNUTYPE_LONGNAME = b"L" # GNU tar longname +GNUTYPE_LONGLINK = b"K" # GNU tar longlink +GNUTYPE_SPARSE = b"S" # GNU tar sparse file + +XHDTYPE = b"x" # POSIX.1-2001 extended header +XGLTYPE = b"g" # POSIX.1-2001 global header +SOLARIS_XHDTYPE = b"X" # Solaris extended header + +USTAR_FORMAT = 0 # POSIX.1-1988 (ustar) format +GNU_FORMAT = 1 # GNU tar format +PAX_FORMAT = 2 # POSIX.1-2001 (pax) format +DEFAULT_FORMAT = GNU_FORMAT + +#--------------------------------------------------------- +# tarfile constants +#--------------------------------------------------------- +# File types that tarfile supports: +SUPPORTED_TYPES = (REGTYPE, AREGTYPE, LNKTYPE, + SYMTYPE, DIRTYPE, FIFOTYPE, + CONTTYPE, CHRTYPE, BLKTYPE, + GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# File types that will be treated as a regular file. +REGULAR_TYPES = (REGTYPE, AREGTYPE, + CONTTYPE, GNUTYPE_SPARSE) + +# File types that are part of the GNU tar format. +GNU_TYPES = (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK, + GNUTYPE_SPARSE) + +# Fields from a pax header that override a TarInfo attribute. +PAX_FIELDS = ("path", "linkpath", "size", "mtime", + "uid", "gid", "uname", "gname") + +# Fields from a pax header that are affected by hdrcharset. +PAX_NAME_FIELDS = set(("path", "linkpath", "uname", "gname")) + +# Fields in a pax header that are numbers, all other fields +# are treated as strings. +PAX_NUMBER_FIELDS = { + "atime": float, + "ctime": float, + "mtime": float, + "uid": int, + "gid": int, + "size": int +} + +#--------------------------------------------------------- +# Bits used in the mode field, values in octal. +#--------------------------------------------------------- +S_IFLNK = 0o120000 # symbolic link +S_IFREG = 0o100000 # regular file +S_IFBLK = 0o060000 # block device +S_IFDIR = 0o040000 # directory +S_IFCHR = 0o020000 # character device +S_IFIFO = 0o010000 # fifo + +TSUID = 0o4000 # set UID on execution +TSGID = 0o2000 # set GID on execution +TSVTX = 0o1000 # reserved + +TUREAD = 0o400 # read by owner +TUWRITE = 0o200 # write by owner +TUEXEC = 0o100 # execute/search by owner +TGREAD = 0o040 # read by group +TGWRITE = 0o020 # write by group +TGEXEC = 0o010 # execute/search by group +TOREAD = 0o004 # read by other +TOWRITE = 0o002 # write by other +TOEXEC = 0o001 # execute/search by other + +#--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +if os.name in ("nt", "ce"): + ENCODING = "utf-8" +else: + ENCODING = sys.getfilesystemencoding() + +#--------------------------------------------------------- +# Some useful functions +#--------------------------------------------------------- + +def stn(s, length, encoding, errors): + """Convert a string to a null-terminated bytes object. + """ + s = s.encode(encoding, errors) + return s[:length] + (length - len(s)) * NUL + +def nts(s, encoding, errors): + """Convert a null-terminated bytes object to a string. + """ + p = s.find(b"\0") + if p != -1: + s = s[:p] + return s.decode(encoding, errors) + +def nti(s): + """Convert a number field to a python number. + """ + # There are two possible encodings for a number field, see + # itn() below. + if s[0] != chr(0o200): + try: + n = int(nts(s, "ascii", "strict") or "0", 8) + except ValueError: + raise InvalidHeaderError("invalid header") + else: + n = 0 + for i in range(len(s) - 1): + n <<= 8 + n += ord(s[i + 1]) + return n + +def itn(n, digits=8, format=DEFAULT_FORMAT): + """Convert a python number to a number field. + """ + # POSIX 1003.1-1988 requires numbers to be encoded as a string of + # octal digits followed by a null-byte, this allows values up to + # (8**(digits-1))-1. GNU tar allows storing numbers greater than + # that if necessary. A leading 0o200 byte indicates this particular + # encoding, the following digits-1 bytes are a big-endian + # representation. This allows values up to (256**(digits-1))-1. + if 0 <= n < 8 ** (digits - 1): + s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL + else: + if format != GNU_FORMAT or n >= 256 ** (digits - 1): + raise ValueError("overflow in number field") + + if n < 0: + # XXX We mimic GNU tar's behaviour with negative numbers, + # this could raise OverflowError. + n = struct.unpack("L", struct.pack("l", n))[0] + + s = bytearray() + for i in range(digits - 1): + s.insert(0, n & 0o377) + n >>= 8 + s.insert(0, 0o200) + return s + +def calc_chksums(buf): + """Calculate the checksum for a member's header by summing up all + characters except for the chksum field which is treated as if + it was filled with spaces. According to the GNU tar sources, + some tars (Sun and NeXT) calculate chksum with signed char, + which will be different if there are chars in the buffer with + the high bit set. So we calculate two checksums, unsigned and + signed. + """ + unsigned_chksum = 256 + sum(struct.unpack("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) + signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) + return unsigned_chksum, signed_chksum + +def copyfileobj(src, dst, length=None): + """Copy length bytes from fileobj src to fileobj dst. + If length is None, copy the entire content. + """ + if length == 0: + return + if length is None: + while True: + buf = src.read(16*1024) + if not buf: + break + dst.write(buf) + return + + BUFSIZE = 16 * 1024 + blocks, remainder = divmod(length, BUFSIZE) + for b in range(blocks): + buf = src.read(BUFSIZE) + if len(buf) < BUFSIZE: + raise IOError("end of file reached") + dst.write(buf) + + if remainder != 0: + buf = src.read(remainder) + if len(buf) < remainder: + raise IOError("end of file reached") + dst.write(buf) + return + +filemode_table = ( + ((S_IFLNK, "l"), + (S_IFREG, "-"), + (S_IFBLK, "b"), + (S_IFDIR, "d"), + (S_IFCHR, "c"), + (S_IFIFO, "p")), + + ((TUREAD, "r"),), + ((TUWRITE, "w"),), + ((TUEXEC|TSUID, "s"), + (TSUID, "S"), + (TUEXEC, "x")), + + ((TGREAD, "r"),), + ((TGWRITE, "w"),), + ((TGEXEC|TSGID, "s"), + (TSGID, "S"), + (TGEXEC, "x")), + + ((TOREAD, "r"),), + ((TOWRITE, "w"),), + ((TOEXEC|TSVTX, "t"), + (TSVTX, "T"), + (TOEXEC, "x")) +) + +def filemode(mode): + """Convert a file's mode to a string of the form + -rwxrwxrwx. + Used by TarFile.list() + """ + perm = [] + for table in filemode_table: + for bit, char in table: + if mode & bit == bit: + perm.append(char) + break + else: + perm.append("-") + return "".join(perm) + +class TarError(Exception): + """Base exception.""" + pass +class ExtractError(TarError): + """General exception for extract errors.""" + pass +class ReadError(TarError): + """Exception for unreadable tar archives.""" + pass +class CompressionError(TarError): + """Exception for unavailable compression methods.""" + pass +class StreamError(TarError): + """Exception for unsupported operations on stream-like TarFiles.""" + pass +class HeaderError(TarError): + """Base exception for header errors.""" + pass +class EmptyHeaderError(HeaderError): + """Exception for empty headers.""" + pass +class TruncatedHeaderError(HeaderError): + """Exception for truncated headers.""" + pass +class EOFHeaderError(HeaderError): + """Exception for end of file headers.""" + pass +class InvalidHeaderError(HeaderError): + """Exception for invalid headers.""" + pass +class SubsequentHeaderError(HeaderError): + """Exception for missing and invalid extended headers.""" + pass + +#--------------------------- +# internal stream interface +#--------------------------- +class _LowLevelFile(object): + """Low-level file object. Supports reading and writing. + It is used instead of a regular file object for streaming + access. + """ + + def __init__(self, name, mode): + mode = { + "r": os.O_RDONLY, + "w": os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + }[mode] + if hasattr(os, "O_BINARY"): + mode |= os.O_BINARY + self.fd = os.open(name, mode, 0o666) + + def close(self): + os.close(self.fd) + + def read(self, size): + return os.read(self.fd, size) + + def write(self, s): + os.write(self.fd, s) + +class _Stream(object): + """Class that serves as an adapter between TarFile and + a stream-like object. The stream-like object only + needs to have a read() or write() method and is accessed + blockwise. Use of gzip or bzip2 compression is possible. + A stream-like object could be for example: sys.stdin, + sys.stdout, a socket, a tape device etc. + + _Stream is intended to be used only internally. + """ + + def __init__(self, name, mode, comptype, fileobj, bufsize): + """Construct a _Stream object. + """ + self._extfileobj = True + if fileobj is None: + fileobj = _LowLevelFile(name, mode) + self._extfileobj = False + + if comptype == '*': + # Enable transparent compression detection for the + # stream interface + fileobj = _StreamProxy(fileobj) + comptype = fileobj.getcomptype() + + self.name = name or "" + self.mode = mode + self.comptype = comptype + self.fileobj = fileobj + self.bufsize = bufsize + self.buf = b"" + self.pos = 0 + self.closed = False + + try: + if comptype == "gz": + try: + import zlib + except ImportError: + raise CompressionError("zlib module is not available") + self.zlib = zlib + self.crc = zlib.crc32(b"") + if mode == "r": + self._init_read_gz() + else: + self._init_write_gz() + + if comptype == "bz2": + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = bz2.BZ2Decompressor() + else: + self.cmp = bz2.BZ2Compressor() + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + def __del__(self): + if hasattr(self, "closed") and not self.closed: + self.close() + + def _init_write_gz(self): + """Initialize for writing with gzip compression. + """ + self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, + -self.zlib.MAX_WBITS, + self.zlib.DEF_MEM_LEVEL, + 0) + timestamp = struct.pack(" self.bufsize: + self.fileobj.write(self.buf[:self.bufsize]) + self.buf = self.buf[self.bufsize:] + + def close(self): + """Close the _Stream object. No operation should be + done on it afterwards. + """ + if self.closed: + return + + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() + + if self.mode == "w" and self.buf: + self.fileobj.write(self.buf) + self.buf = b"" + if self.comptype == "gz": + # The native zlib crc is an unsigned 32-bit integer, but + # the Python wrapper implicitly casts that to a signed C + # long. So, on a 32-bit box self.crc may "look negative", + # while the same crc on a 64-bit box may "look positive". + # To avoid irksome warnings from the `struct` module, force + # it to look positive on all boxes. + self.fileobj.write(struct.pack("= 0: + blocks, remainder = divmod(pos - self.pos, self.bufsize) + for i in range(blocks): + self.read(self.bufsize) + self.read(remainder) + else: + raise StreamError("seeking backwards is not allowed") + return self.pos + + def read(self, size=None): + """Return the next size number of bytes from the stream. + If size is not defined, return all bytes of the stream + up to EOF. + """ + if size is None: + t = [] + while True: + buf = self._read(self.bufsize) + if not buf: + break + t.append(buf) + buf = "".join(t) + else: + buf = self._read(size) + self.pos += len(buf) + return buf + + def _read(self, size): + """Return size bytes from the stream. + """ + if self.comptype == "tar": + return self.__read(size) + + c = len(self.dbuf) + while c < size: + buf = self.__read(self.bufsize) + if not buf: + break + try: + buf = self.cmp.decompress(buf) + except IOError: + raise ReadError("invalid compressed data") + self.dbuf += buf + c += len(buf) + buf = self.dbuf[:size] + self.dbuf = self.dbuf[size:] + return buf + + def __read(self, size): + """Return size bytes from stream. If internal buffer is empty, + read another block from the stream. + """ + c = len(self.buf) + while c < size: + buf = self.fileobj.read(self.bufsize) + if not buf: + break + self.buf += buf + c += len(buf) + buf = self.buf[:size] + self.buf = self.buf[size:] + return buf +# class _Stream + +class _StreamProxy(object): + """Small proxy class that enables transparent compression + detection for the Stream interface (mode 'r|*'). + """ + + def __init__(self, fileobj): + self.fileobj = fileobj + self.buf = self.fileobj.read(BLOCKSIZE) + + def read(self, size): + self.read = self.fileobj.read + return self.buf + + def getcomptype(self): + if self.buf.startswith(b"\037\213\010"): + return "gz" + if self.buf.startswith(b"BZh91"): + return "bz2" + return "tar" + + def close(self): + self.fileobj.close() +# class StreamProxy + +class _BZ2Proxy(object): + """Small proxy class that enables external file object + support for "r:bz2" and "w:bz2" modes. This is actually + a workaround for a limitation in bz2 module's BZ2File + class which (unlike gzip.GzipFile) has no support for + a file object argument. + """ + + blocksize = 16 * 1024 + + def __init__(self, fileobj, mode): + self.fileobj = fileobj + self.mode = mode + self.name = getattr(self.fileobj, "name", None) + self.init() + + def init(self): + import bz2 + self.pos = 0 + if self.mode == "r": + self.bz2obj = bz2.BZ2Decompressor() + self.fileobj.seek(0) + self.buf = b"" + else: + self.bz2obj = bz2.BZ2Compressor() + + def read(self, size): + x = len(self.buf) + while x < size: + raw = self.fileobj.read(self.blocksize) + if not raw: + break + data = self.bz2obj.decompress(raw) + self.buf += data + x += len(data) + + buf = self.buf[:size] + self.buf = self.buf[size:] + self.pos += len(buf) + return buf + + def seek(self, pos): + if pos < self.pos: + self.init() + self.read(pos - self.pos) + + def tell(self): + return self.pos + + def write(self, data): + self.pos += len(data) + raw = self.bz2obj.compress(data) + self.fileobj.write(raw) + + def close(self): + if self.mode == "w": + raw = self.bz2obj.flush() + self.fileobj.write(raw) +# class _BZ2Proxy + +#------------------------ +# Extraction file object +#------------------------ +class _FileInFile(object): + """A thin wrapper around an existing file object that + provides a part of its data as an individual file + object. + """ + + def __init__(self, fileobj, offset, size, blockinfo=None): + self.fileobj = fileobj + self.offset = offset + self.size = size + self.position = 0 + + if blockinfo is None: + blockinfo = [(0, size)] + + # Construct a map with data and zero blocks. + self.map_index = 0 + self.map = [] + lastpos = 0 + realpos = self.offset + for offset, size in blockinfo: + if offset > lastpos: + self.map.append((False, lastpos, offset, None)) + self.map.append((True, offset, offset + size, realpos)) + realpos += size + lastpos = offset + size + if lastpos < self.size: + self.map.append((False, lastpos, self.size, None)) + + def seekable(self): + if not hasattr(self.fileobj, "seekable"): + # XXX gzip.GzipFile and bz2.BZ2File + return True + return self.fileobj.seekable() + + def tell(self): + """Return the current file position. + """ + return self.position + + def seek(self, position): + """Seek to a position in the file. + """ + self.position = position + + def read(self, size=None): + """Read data from the file. + """ + if size is None: + size = self.size - self.position + else: + size = min(size, self.size - self.position) + + buf = b"" + while size > 0: + while True: + data, start, stop, offset = self.map[self.map_index] + if start <= self.position < stop: + break + else: + self.map_index += 1 + if self.map_index == len(self.map): + self.map_index = 0 + length = min(size, stop - self.position) + if data: + self.fileobj.seek(offset + (self.position - start)) + buf += self.fileobj.read(length) + else: + buf += NUL * length + size -= length + self.position += length + return buf +#class _FileInFile + + +class ExFileObject(object): + """File-like object for reading an archive member. + Is returned by TarFile.extractfile(). + """ + blocksize = 1024 + + def __init__(self, tarfile, tarinfo): + self.fileobj = _FileInFile(tarfile.fileobj, + tarinfo.offset_data, + tarinfo.size, + tarinfo.sparse) + self.name = tarinfo.name + self.mode = "r" + self.closed = False + self.size = tarinfo.size + + self.position = 0 + self.buffer = b"" + + def readable(self): + return True + + def writable(self): + return False + + def seekable(self): + return self.fileobj.seekable() + + def read(self, size=None): + """Read at most size bytes from the file. If size is not + present or None, read all data until EOF is reached. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + buf = b"" + if self.buffer: + if size is None: + buf = self.buffer + self.buffer = b"" + else: + buf = self.buffer[:size] + self.buffer = self.buffer[size:] + + if size is None: + buf += self.fileobj.read() + else: + buf += self.fileobj.read(size - len(buf)) + + self.position += len(buf) + return buf + + # XXX TextIOWrapper uses the read1() method. + read1 = read + + def readline(self, size=-1): + """Read one entire line from the file. If size is present + and non-negative, return a string with at most that + size, which may be an incomplete line. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + while True: + buf = self.fileobj.read(self.blocksize) + self.buffer += buf + if not buf or b"\n" in buf: + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + pos = len(self.buffer) + break + + if size != -1: + pos = min(size, pos) + + buf = self.buffer[:pos] + self.buffer = self.buffer[pos:] + self.position += len(buf) + return buf + + def readlines(self): + """Return a list with all remaining lines. + """ + result = [] + while True: + line = self.readline() + if not line: break + result.append(line) + return result + + def tell(self): + """Return the current file position. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + return self.position + + def seek(self, pos, whence=os.SEEK_SET): + """Seek to a position in the file. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + if whence == os.SEEK_SET: + self.position = min(max(pos, 0), self.size) + elif whence == os.SEEK_CUR: + if pos < 0: + self.position = max(self.position + pos, 0) + else: + self.position = min(self.position + pos, self.size) + elif whence == os.SEEK_END: + self.position = max(min(self.size + pos, self.size), 0) + else: + raise ValueError("Invalid argument") + + self.buffer = b"" + self.fileobj.seek(self.position) + + def close(self): + """Close the file object. + """ + self.closed = True + + def __iter__(self): + """Get an iterator over the file's lines. + """ + while True: + line = self.readline() + if not line: + break + yield line +#class ExFileObject + +#------------------ +# Exported Classes +#------------------ +class TarInfo(object): + """Informational class which holds the details about an + archive member given by a tar header block. + TarInfo objects are returned by TarFile.getmember(), + TarFile.getmembers() and TarFile.gettarinfo() and are + usually created internally. + """ + + __slots__ = ("name", "mode", "uid", "gid", "size", "mtime", + "chksum", "type", "linkname", "uname", "gname", + "devmajor", "devminor", + "offset", "offset_data", "pax_headers", "sparse", + "tarfile", "_sparse_structs", "_link_target") + + def __init__(self, name=""): + """Construct a TarInfo object. name is the optional name + of the member. + """ + self.name = name # member name + self.mode = 0o644 # file permissions + self.uid = 0 # user id + self.gid = 0 # group id + self.size = 0 # file size + self.mtime = 0 # modification time + self.chksum = 0 # header checksum + self.type = REGTYPE # member type + self.linkname = "" # link name + self.uname = "" # user name + self.gname = "" # group name + self.devmajor = 0 # device major number + self.devminor = 0 # device minor number + + self.offset = 0 # the tar header starts here + self.offset_data = 0 # the file's data starts here + + self.sparse = None # sparse member information + self.pax_headers = {} # pax header information + + # In pax headers the "name" and "linkname" field are called + # "path" and "linkpath". + def _getpath(self): + return self.name + def _setpath(self, name): + self.name = name + path = property(_getpath, _setpath) + + def _getlinkpath(self): + return self.linkname + def _setlinkpath(self, linkname): + self.linkname = linkname + linkpath = property(_getlinkpath, _setlinkpath) + + def __repr__(self): + return "<%s %r at %#x>" % (self.__class__.__name__,self.name,id(self)) + + def get_info(self): + """Return the TarInfo's attributes as a dictionary. + """ + info = { + "name": self.name, + "mode": self.mode & 0o7777, + "uid": self.uid, + "gid": self.gid, + "size": self.size, + "mtime": self.mtime, + "chksum": self.chksum, + "type": self.type, + "linkname": self.linkname, + "uname": self.uname, + "gname": self.gname, + "devmajor": self.devmajor, + "devminor": self.devminor + } + + if info["type"] == DIRTYPE and not info["name"].endswith("/"): + info["name"] += "/" + + return info + + def tobuf(self, format=DEFAULT_FORMAT, encoding=ENCODING, errors="surrogateescape"): + """Return a tar header as a string of 512 byte blocks. + """ + info = self.get_info() + + if format == USTAR_FORMAT: + return self.create_ustar_header(info, encoding, errors) + elif format == GNU_FORMAT: + return self.create_gnu_header(info, encoding, errors) + elif format == PAX_FORMAT: + return self.create_pax_header(info, encoding) + else: + raise ValueError("invalid format") + + def create_ustar_header(self, info, encoding, errors): + """Return the object as a ustar header block. + """ + info["magic"] = POSIX_MAGIC + + if len(info["linkname"]) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"]) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + + return self._create_header(info, USTAR_FORMAT, encoding, errors) + + def create_gnu_header(self, info, encoding, errors): + """Return the object as a GNU header block sequence. + """ + info["magic"] = GNU_MAGIC + + buf = b"" + if len(info["linkname"]) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) + + if len(info["name"]) > LENGTH_NAME: + buf += self._create_gnu_long_header(info["name"], GNUTYPE_LONGNAME, encoding, errors) + + return buf + self._create_header(info, GNU_FORMAT, encoding, errors) + + def create_pax_header(self, info, encoding): + """Return the object as a ustar header block. If it cannot be + represented this way, prepend a pax extended header sequence + with supplement information. + """ + info["magic"] = POSIX_MAGIC + pax_headers = self.pax_headers.copy() + + # Test string fields for values that exceed the field length or cannot + # be represented in ASCII encoding. + for name, hname, length in ( + ("name", "path", LENGTH_NAME), ("linkname", "linkpath", LENGTH_LINK), + ("uname", "uname", 32), ("gname", "gname", 32)): + + if hname in pax_headers: + # The pax header has priority. + continue + + # Try to encode the string as ASCII. + try: + info[name].encode("ascii", "strict") + except UnicodeEncodeError: + pax_headers[hname] = info[name] + continue + + if len(info[name]) > length: + pax_headers[hname] = info[name] + + # Test number fields for values that exceed the field limit or values + # that like to be stored as float. + for name, digits in (("uid", 8), ("gid", 8), ("size", 12), ("mtime", 12)): + if name in pax_headers: + # The pax header has priority. Avoid overflow. + info[name] = 0 + continue + + val = info[name] + if not 0 <= val < 8 ** (digits - 1) or isinstance(val, float): + pax_headers[name] = str(val) + info[name] = 0 + + # Create a pax extended header if necessary. + if pax_headers: + buf = self._create_pax_generic_header(pax_headers, XHDTYPE, encoding) + else: + buf = b"" + + return buf + self._create_header(info, USTAR_FORMAT, "ascii", "replace") + + @classmethod + def create_pax_global_header(cls, pax_headers): + """Return the object as a pax global header block sequence. + """ + return cls._create_pax_generic_header(pax_headers, XGLTYPE, "utf8") + + def _posix_split_name(self, name): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + prefix = name[:LENGTH_PREFIX + 1] + while prefix and prefix[-1] != "/": + prefix = prefix[:-1] + + name = name[len(prefix):] + prefix = prefix[:-1] + + if not prefix or len(name) > LENGTH_NAME: + raise ValueError("name is too long") + return prefix, name + + @staticmethod + def _create_header(info, format, encoding, errors): + """Return a header block. info is a dictionary with file + information, format must be one of the *_FORMAT constants. + """ + parts = [ + stn(info.get("name", ""), 100, encoding, errors), + itn(info.get("mode", 0) & 0o7777, 8, format), + itn(info.get("uid", 0), 8, format), + itn(info.get("gid", 0), 8, format), + itn(info.get("size", 0), 12, format), + itn(info.get("mtime", 0), 12, format), + b" ", # checksum field + info.get("type", REGTYPE), + stn(info.get("linkname", ""), 100, encoding, errors), + info.get("magic", POSIX_MAGIC), + stn(info.get("uname", ""), 32, encoding, errors), + stn(info.get("gname", ""), 32, encoding, errors), + itn(info.get("devmajor", 0), 8, format), + itn(info.get("devminor", 0), 8, format), + stn(info.get("prefix", ""), 155, encoding, errors) + ] + + buf = struct.pack("%ds" % BLOCKSIZE, b"".join(parts)) + chksum = calc_chksums(buf[-BLOCKSIZE:])[0] + buf = buf[:-364] + ("%06o\0" % chksum).encode("ascii") + buf[-357:] + return buf + + @staticmethod + def _create_payload(payload): + """Return the string payload filled with zero bytes + up to the next 512 byte border. + """ + blocks, remainder = divmod(len(payload), BLOCKSIZE) + if remainder > 0: + payload += (BLOCKSIZE - remainder) * NUL + return payload + + @classmethod + def _create_gnu_long_header(cls, name, type, encoding, errors): + """Return a GNUTYPE_LONGNAME or GNUTYPE_LONGLINK sequence + for name. + """ + name = name.encode(encoding, errors) + NUL + + info = {} + info["name"] = "././@LongLink" + info["type"] = type + info["size"] = len(name) + info["magic"] = GNU_MAGIC + + # create extended header + name blocks. + return cls._create_header(info, USTAR_FORMAT, encoding, errors) + \ + cls._create_payload(name) + + @classmethod + def _create_pax_generic_header(cls, pax_headers, type, encoding): + """Return a POSIX.1-2008 extended or global header sequence + that contains a list of keyword, value pairs. The values + must be strings. + """ + # Check if one of the fields contains surrogate characters and thereby + # forces hdrcharset=BINARY, see _proc_pax() for more information. + binary = False + for keyword, value in pax_headers.items(): + try: + value.encode("utf8", "strict") + except UnicodeEncodeError: + binary = True + break + + records = b"" + if binary: + # Put the hdrcharset field at the beginning of the header. + records += b"21 hdrcharset=BINARY\n" + + for keyword, value in pax_headers.items(): + keyword = keyword.encode("utf8") + if binary: + # Try to restore the original byte representation of `value'. + # Needless to say, that the encoding must match the string. + value = value.encode(encoding, "surrogateescape") + else: + value = value.encode("utf8") + + l = len(keyword) + len(value) + 3 # ' ' + '=' + '\n' + n = p = 0 + while True: + n = l + len(str(p)) + if n == p: + break + p = n + records += bytes(str(p), "ascii") + b" " + keyword + b"=" + value + b"\n" + + # We use a hardcoded "././@PaxHeader" name like star does + # instead of the one that POSIX recommends. + info = {} + info["name"] = "././@PaxHeader" + info["type"] = type + info["size"] = len(records) + info["magic"] = POSIX_MAGIC + + # Create pax header + record blocks. + return cls._create_header(info, USTAR_FORMAT, "ascii", "replace") + \ + cls._create_payload(records) + + @classmethod + def frombuf(cls, buf, encoding, errors): + """Construct a TarInfo object from a 512 byte bytes object. + """ + if len(buf) == 0: + raise EmptyHeaderError("empty header") + if len(buf) != BLOCKSIZE: + raise TruncatedHeaderError("truncated header") + if buf.count(NUL) == BLOCKSIZE: + raise EOFHeaderError("end of file header") + + chksum = nti(buf[148:156]) + if chksum not in calc_chksums(buf): + raise InvalidHeaderError("bad checksum") + + obj = cls() + obj.name = nts(buf[0:100], encoding, errors) + obj.mode = nti(buf[100:108]) + obj.uid = nti(buf[108:116]) + obj.gid = nti(buf[116:124]) + obj.size = nti(buf[124:136]) + obj.mtime = nti(buf[136:148]) + obj.chksum = chksum + obj.type = buf[156:157] + obj.linkname = nts(buf[157:257], encoding, errors) + obj.uname = nts(buf[265:297], encoding, errors) + obj.gname = nts(buf[297:329], encoding, errors) + obj.devmajor = nti(buf[329:337]) + obj.devminor = nti(buf[337:345]) + prefix = nts(buf[345:500], encoding, errors) + + # Old V7 tar format represents a directory as a regular + # file with a trailing slash. + if obj.type == AREGTYPE and obj.name.endswith("/"): + obj.type = DIRTYPE + + # The old GNU sparse format occupies some of the unused + # space in the buffer for up to 4 sparse structures. + # Save the them for later processing in _proc_sparse(). + if obj.type == GNUTYPE_SPARSE: + pos = 386 + structs = [] + for i in range(4): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[482]) + origsize = nti(buf[483:495]) + obj._sparse_structs = (structs, isextended, origsize) + + # Remove redundant slashes from directories. + if obj.isdir(): + obj.name = obj.name.rstrip("/") + + # Reconstruct a ustar longname. + if prefix and obj.type not in GNU_TYPES: + obj.name = prefix + "/" + obj.name + return obj + + @classmethod + def fromtarfile(cls, tarfile): + """Return the next TarInfo object from TarFile object + tarfile. + """ + buf = tarfile.fileobj.read(BLOCKSIZE) + obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors) + obj.offset = tarfile.fileobj.tell() - BLOCKSIZE + return obj._proc_member(tarfile) + + #-------------------------------------------------------------------------- + # The following are methods that are called depending on the type of a + # member. The entry point is _proc_member() which can be overridden in a + # subclass to add custom _proc_*() methods. A _proc_*() method MUST + # implement the following + # operations: + # 1. Set self.offset_data to the position where the data blocks begin, + # if there is data that follows. + # 2. Set tarfile.offset to the position where the next member's header will + # begin. + # 3. Return self or another valid TarInfo object. + def _proc_member(self, tarfile): + """Choose the right processing method depending on + the type and call it. + """ + if self.type in (GNUTYPE_LONGNAME, GNUTYPE_LONGLINK): + return self._proc_gnulong(tarfile) + elif self.type == GNUTYPE_SPARSE: + return self._proc_sparse(tarfile) + elif self.type in (XHDTYPE, XGLTYPE, SOLARIS_XHDTYPE): + return self._proc_pax(tarfile) + else: + return self._proc_builtin(tarfile) + + def _proc_builtin(self, tarfile): + """Process a builtin type or an unknown type which + will be treated as a regular file. + """ + self.offset_data = tarfile.fileobj.tell() + offset = self.offset_data + if self.isreg() or self.type not in SUPPORTED_TYPES: + # Skip the following data blocks. + offset += self._block(self.size) + tarfile.offset = offset + + # Patch the TarInfo object with saved global + # header information. + self._apply_pax_info(tarfile.pax_headers, tarfile.encoding, tarfile.errors) + + return self + + def _proc_gnulong(self, tarfile): + """Process the blocks that hold a GNU longname + or longlink member. + """ + buf = tarfile.fileobj.read(self._block(self.size)) + + # Fetch the next header and process it. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Patch the TarInfo object from the next header with + # the longname information. + next.offset = self.offset + if self.type == GNUTYPE_LONGNAME: + next.name = nts(buf, tarfile.encoding, tarfile.errors) + elif self.type == GNUTYPE_LONGLINK: + next.linkname = nts(buf, tarfile.encoding, tarfile.errors) + + return next + + def _proc_sparse(self, tarfile): + """Process a GNU sparse header plus extra headers. + """ + # We already collected some sparse structures in frombuf(). + structs, isextended, origsize = self._sparse_structs + del self._sparse_structs + + # Collect sparse structures from extended header blocks. + while isextended: + buf = tarfile.fileobj.read(BLOCKSIZE) + pos = 0 + for i in range(21): + try: + offset = nti(buf[pos:pos + 12]) + numbytes = nti(buf[pos + 12:pos + 24]) + except ValueError: + break + if offset and numbytes: + structs.append((offset, numbytes)) + pos += 24 + isextended = bool(buf[504]) + self.sparse = structs + + self.offset_data = tarfile.fileobj.tell() + tarfile.offset = self.offset_data + self._block(self.size) + self.size = origsize + return self + + def _proc_pax(self, tarfile): + """Process an extended or global header as described in + POSIX.1-2008. + """ + # Read the header information. + buf = tarfile.fileobj.read(self._block(self.size)) + + # A pax header stores supplemental information for either + # the following file (extended) or all following files + # (global). + if self.type == XGLTYPE: + pax_headers = tarfile.pax_headers + else: + pax_headers = tarfile.pax_headers.copy() + + # Check if the pax header contains a hdrcharset field. This tells us + # the encoding of the path, linkpath, uname and gname fields. Normally, + # these fields are UTF-8 encoded but since POSIX.1-2008 tar + # implementations are allowed to store them as raw binary strings if + # the translation to UTF-8 fails. + match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) + if match is not None: + pax_headers["hdrcharset"] = match.group(1).decode("utf8") + + # For the time being, we don't care about anything other than "BINARY". + # The only other value that is currently allowed by the standard is + # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. + hdrcharset = pax_headers.get("hdrcharset") + if hdrcharset == "BINARY": + encoding = tarfile.encoding + else: + encoding = "utf8" + + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and + # the newline. keyword and value are both UTF-8 encoded strings. + regex = re.compile(br"(\d+) ([^=]+)=") + pos = 0 + while True: + match = regex.match(buf, pos) + if not match: + break + + length, keyword = match.groups() + length = int(length) + value = buf[match.end(2) + 1:match.start(1) + length - 1] + + # Normally, we could just use "utf8" as the encoding and "strict" + # as the error handler, but we better not take the risk. For + # example, GNU tar <= 1.23 is known to store filenames it cannot + # translate to UTF-8 as raw strings (unfortunately without a + # hdrcharset=BINARY header). + # We first try the strict standard encoding, and if that fails we + # fall back on the user's encoding and error handler. + keyword = self._decode_pax_field(keyword, "utf8", "utf8", + tarfile.errors) + if keyword in PAX_NAME_FIELDS: + value = self._decode_pax_field(value, encoding, tarfile.encoding, + tarfile.errors) + else: + value = self._decode_pax_field(value, "utf8", "utf8", + tarfile.errors) + + pax_headers[keyword] = value + pos += length + + # Fetch the next header. + try: + next = self.fromtarfile(tarfile) + except HeaderError: + raise SubsequentHeaderError("missing or bad subsequent header") + + # Process GNU sparse information. + if "GNU.sparse.map" in pax_headers: + # GNU extended sparse format version 0.1. + self._proc_gnusparse_01(next, pax_headers) + + elif "GNU.sparse.size" in pax_headers: + # GNU extended sparse format version 0.0. + self._proc_gnusparse_00(next, pax_headers, buf) + + elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": + # GNU extended sparse format version 1.0. + self._proc_gnusparse_10(next, pax_headers, tarfile) + + if self.type in (XHDTYPE, SOLARIS_XHDTYPE): + # Patch the TarInfo object with the extended header info. + next._apply_pax_info(pax_headers, tarfile.encoding, tarfile.errors) + next.offset = self.offset + + if "size" in pax_headers: + # If the extended header replaces the size field, + # we need to recalculate the offset where the next + # header starts. + offset = next.offset_data + if next.isreg() or next.type not in SUPPORTED_TYPES: + offset += next._block(next.size) + tarfile.offset = offset + + return next + + def _proc_gnusparse_00(self, next, pax_headers, buf): + """Process a GNU tar extended sparse header, version 0.0. + """ + offsets = [] + for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): + offsets.append(int(match.group(1))) + numbytes = [] + for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): + numbytes.append(int(match.group(1))) + next.sparse = list(zip(offsets, numbytes)) + + def _proc_gnusparse_01(self, next, pax_headers): + """Process a GNU tar extended sparse header, version 0.1. + """ + sparse = [int(x) for x in pax_headers["GNU.sparse.map"].split(",")] + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _proc_gnusparse_10(self, next, pax_headers, tarfile): + """Process a GNU tar extended sparse header, version 1.0. + """ + fields = None + sparse = [] + buf = tarfile.fileobj.read(BLOCKSIZE) + fields, buf = buf.split(b"\n", 1) + fields = int(fields) + while len(sparse) < fields * 2: + if b"\n" not in buf: + buf += tarfile.fileobj.read(BLOCKSIZE) + number, buf = buf.split(b"\n", 1) + sparse.append(int(number)) + next.offset_data = tarfile.fileobj.tell() + next.sparse = list(zip(sparse[::2], sparse[1::2])) + + def _apply_pax_info(self, pax_headers, encoding, errors): + """Replace fields with supplemental information from a previous + pax extended or global header. + """ + for keyword, value in pax_headers.items(): + if keyword == "GNU.sparse.name": + setattr(self, "path", value) + elif keyword == "GNU.sparse.size": + setattr(self, "size", int(value)) + elif keyword == "GNU.sparse.realsize": + setattr(self, "size", int(value)) + elif keyword in PAX_FIELDS: + if keyword in PAX_NUMBER_FIELDS: + try: + value = PAX_NUMBER_FIELDS[keyword](value) + except ValueError: + value = 0 + if keyword == "path": + value = value.rstrip("/") + setattr(self, keyword, value) + + self.pax_headers = pax_headers.copy() + + def _decode_pax_field(self, value, encoding, fallback_encoding, fallback_errors): + """Decode a single field from a pax record. + """ + try: + return value.decode(encoding, "strict") + except UnicodeDecodeError: + return value.decode(fallback_encoding, fallback_errors) + + def _block(self, count): + """Round up a byte count by BLOCKSIZE and return it, + e.g. _block(834) => 1024. + """ + blocks, remainder = divmod(count, BLOCKSIZE) + if remainder: + blocks += 1 + return blocks * BLOCKSIZE + + def isreg(self): + return self.type in REGULAR_TYPES + def isfile(self): + return self.isreg() + def isdir(self): + return self.type == DIRTYPE + def issym(self): + return self.type == SYMTYPE + def islnk(self): + return self.type == LNKTYPE + def ischr(self): + return self.type == CHRTYPE + def isblk(self): + return self.type == BLKTYPE + def isfifo(self): + return self.type == FIFOTYPE + def issparse(self): + return self.sparse is not None + def isdev(self): + return self.type in (CHRTYPE, BLKTYPE, FIFOTYPE) +# class TarInfo + +class TarFile(object): + """The TarFile Class provides an interface to tar archives. + """ + + debug = 0 # May be set from 0 (no msgs) to 3 (all msgs) + + dereference = False # If true, add content of linked file to the + # tar file, else the link. + + ignore_zeros = False # If true, skips empty or invalid blocks and + # continues processing. + + errorlevel = 1 # If 0, fatal errors only appear in debug + # messages (if debug >= 0). If > 0, errors + # are passed to the caller as exceptions. + + format = DEFAULT_FORMAT # The format to use when creating an archive. + + encoding = ENCODING # Encoding for 8-bit character strings. + + errors = None # Error handler for unicode conversion. + + tarinfo = TarInfo # The default TarInfo class to use. + + fileobject = ExFileObject # The default ExFileObject class to use. + + def __init__(self, name=None, mode="r", fileobj=None, format=None, + tarinfo=None, dereference=None, ignore_zeros=None, encoding=None, + errors="surrogateescape", pax_headers=None, debug=None, errorlevel=None): + """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to + read from an existing archive, 'a' to append data to an existing + file or 'w' to create a new file overwriting an existing one. `mode' + defaults to 'r'. + If `fileobj' is given, it is used for reading or writing data. If it + can be determined, `mode' is overridden by `fileobj's mode. + `fileobj' is not closed, when TarFile is closed. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + self.mode = mode + self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[mode] + + if not fileobj: + if self.mode == "a" and not os.path.exists(name): + # Create nonexistent files in append mode. + self.mode = "w" + self._mode = "wb" + fileobj = bltn_open(name, self._mode) + self._extfileobj = False + else: + if name is None and hasattr(fileobj, "name"): + name = fileobj.name + if hasattr(fileobj, "mode"): + self._mode = fileobj.mode + self._extfileobj = True + self.name = os.path.abspath(name) if name else None + self.fileobj = fileobj + + # Init attributes. + if format is not None: + self.format = format + if tarinfo is not None: + self.tarinfo = tarinfo + if dereference is not None: + self.dereference = dereference + if ignore_zeros is not None: + self.ignore_zeros = ignore_zeros + if encoding is not None: + self.encoding = encoding + self.errors = errors + + if pax_headers is not None and self.format == PAX_FORMAT: + self.pax_headers = pax_headers + else: + self.pax_headers = {} + + if debug is not None: + self.debug = debug + if errorlevel is not None: + self.errorlevel = errorlevel + + # Init datastructures. + self.closed = False + self.members = [] # list of members as TarInfo objects + self._loaded = False # flag if all members have been read + self.offset = self.fileobj.tell() + # current position in the archive file + self.inodes = {} # dictionary caching the inodes of + # archive members already added + + try: + if self.mode == "r": + self.firstmember = None + self.firstmember = self.next() + + if self.mode == "a": + # Move to the end of the archive, + # before the first empty block. + while True: + self.fileobj.seek(self.offset) + try: + tarinfo = self.tarinfo.fromtarfile(self) + self.members.append(tarinfo) + except EOFHeaderError: + self.fileobj.seek(self.offset) + break + except HeaderError as e: + raise ReadError(str(e)) + + if self.mode in "aw": + self._loaded = True + + if self.pax_headers: + buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy()) + self.fileobj.write(buf) + self.offset += len(buf) + except: + if not self._extfileobj: + self.fileobj.close() + self.closed = True + raise + + #-------------------------------------------------------------------------- + # Below are the classmethods which act as alternate constructors to the + # TarFile class. The open() method is the only one that is needed for + # public use; it is the "super"-constructor and is able to select an + # adequate "sub"-constructor for a particular compression using the mapping + # from OPEN_METH. + # + # This concept allows one to subclass TarFile without losing the comfort of + # the super-constructor. A sub-constructor is registered and made available + # by adding it to the mapping in OPEN_METH. + + @classmethod + def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs): + """Open a tar archive for reading, writing or appending. Return + an appropriate TarFile class. + + mode: + 'r' or 'r:*' open for reading with transparent compression + 'r:' open for reading exclusively uncompressed + 'r:gz' open for reading with gzip compression + 'r:bz2' open for reading with bzip2 compression + 'a' or 'a:' open for appending, creating the file if necessary + 'w' or 'w:' open for writing without compression + 'w:gz' open for writing with gzip compression + 'w:bz2' open for writing with bzip2 compression + + 'r|*' open a stream of tar blocks with transparent compression + 'r|' open an uncompressed stream of tar blocks for reading + 'r|gz' open a gzip compressed stream of tar blocks + 'r|bz2' open a bzip2 compressed stream of tar blocks + 'w|' open an uncompressed stream for writing + 'w|gz' open a gzip compressed stream for writing + 'w|bz2' open a bzip2 compressed stream for writing + """ + + if not name and not fileobj: + raise ValueError("nothing to open") + + if mode in ("r", "r:*"): + # Find out which *open() is appropriate for opening the file. + for comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + if fileobj is not None: + saved_pos = fileobj.tell() + try: + return func(name, "r", fileobj, **kwargs) + except (ReadError, CompressionError) as e: + if fileobj is not None: + fileobj.seek(saved_pos) + continue + raise ReadError("file could not be opened successfully") + + elif ":" in mode: + filemode, comptype = mode.split(":", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + # Select the *open() function according to + # given compression. + if comptype in cls.OPEN_METH: + func = getattr(cls, cls.OPEN_METH[comptype]) + else: + raise CompressionError("unknown compression type %r" % comptype) + return func(name, filemode, fileobj, **kwargs) + + elif "|" in mode: + filemode, comptype = mode.split("|", 1) + filemode = filemode or "r" + comptype = comptype or "tar" + + if filemode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + stream = _Stream(name, filemode, comptype, fileobj, bufsize) + try: + t = cls(name, filemode, stream, **kwargs) + except: + stream.close() + raise + t._extfileobj = False + return t + + elif mode in "aw": + return cls.taropen(name, mode, fileobj, **kwargs) + + raise ValueError("undiscernible mode") + + @classmethod + def taropen(cls, name, mode="r", fileobj=None, **kwargs): + """Open uncompressed tar archive name for reading or writing. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + return cls(name, mode, fileobj, **kwargs) + + @classmethod + def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open gzip compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + try: + import gzip + gzip.GzipFile + except (ImportError, AttributeError): + raise CompressionError("gzip module is not available") + + extfileobj = fileobj is not None + try: + fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + t = cls.taropen(name, mode, fileobj, **kwargs) + except IOError: + if not extfileobj and fileobj is not None: + fileobj.close() + if fileobj is None: + raise + raise ReadError("not a gzip file") + except: + if not extfileobj and fileobj is not None: + fileobj.close() + raise + t._extfileobj = extfileobj + return t + + @classmethod + def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs): + """Open bzip2 compressed tar archive name for reading or writing. + Appending is not allowed. + """ + if len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'.") + + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + + if fileobj is not None: + fileobj = _BZ2Proxy(fileobj, mode) + else: + fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (IOError, EOFError): + fileobj.close() + raise ReadError("not a bzip2 file") + t._extfileobj = False + return t + + # All *open() methods are registered here. + OPEN_METH = { + "tar": "taropen", # uncompressed tar + "gz": "gzopen", # gzip compressed tar + "bz2": "bz2open" # bzip2 compressed tar + } + + #-------------------------------------------------------------------------- + # The public methods which TarFile provides: + + def close(self): + """Close the TarFile. In write-mode, two finishing zero blocks are + appended to the archive. + """ + if self.closed: + return + + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + + if not self._extfileobj: + self.fileobj.close() + self.closed = True + + def getmember(self, name): + """Return a TarInfo object for member `name'. If `name' can not be + found in the archive, KeyError is raised. If a member occurs more + than once in the archive, its last occurrence is assumed to be the + most up-to-date version. + """ + tarinfo = self._getmember(name) + if tarinfo is None: + raise KeyError("filename %r not found" % name) + return tarinfo + + def getmembers(self): + """Return the members of the archive as a list of TarInfo objects. The + list has the same order as the members in the archive. + """ + self._check() + if not self._loaded: # if we want to obtain a list of + self._load() # all members, we first have to + # scan the whole archive. + return self.members + + def getnames(self): + """Return the members of the archive as a list of their names. It has + the same order as the list returned by getmembers(). + """ + return [tarinfo.name for tarinfo in self.getmembers()] + + def gettarinfo(self, name=None, arcname=None, fileobj=None): + """Create a TarInfo object for either the file `name' or the file + object `fileobj' (using os.fstat on its file descriptor). You can + modify some of the TarInfo's attributes before you add it using + addfile(). If given, `arcname' specifies an alternative name for the + file in the archive. + """ + self._check("aw") + + # When fileobj is given, replace name by + # fileobj's real name. + if fileobj is not None: + name = fileobj.name + + # Building the name of the member in the archive. + # Backward slashes are converted to forward slashes, + # Absolute paths are turned to relative paths. + if arcname is None: + arcname = name + drv, arcname = os.path.splitdrive(arcname) + arcname = arcname.replace(os.sep, "/") + arcname = arcname.lstrip("/") + + # Now, fill the TarInfo object with + # information specific for the file. + tarinfo = self.tarinfo() + tarinfo.tarfile = self + + # Use os.stat or os.lstat, depending on platform + # and if symlinks shall be resolved. + if fileobj is None: + if hasattr(os, "lstat") and not self.dereference: + statres = os.lstat(name) + else: + statres = os.stat(name) + else: + statres = os.fstat(fileobj.fileno()) + linkname = "" + + stmd = statres.st_mode + if stat.S_ISREG(stmd): + inode = (statres.st_ino, statres.st_dev) + if not self.dereference and statres.st_nlink > 1 and \ + inode in self.inodes and arcname != self.inodes[inode]: + # Is it a hardlink to an already + # archived file? + type = LNKTYPE + linkname = self.inodes[inode] + else: + # The inode is added only if its valid. + # For win32 it is always 0. + type = REGTYPE + if inode[0]: + self.inodes[inode] = arcname + elif stat.S_ISDIR(stmd): + type = DIRTYPE + elif stat.S_ISFIFO(stmd): + type = FIFOTYPE + elif stat.S_ISLNK(stmd): + type = SYMTYPE + linkname = os.readlink(name) + elif stat.S_ISCHR(stmd): + type = CHRTYPE + elif stat.S_ISBLK(stmd): + type = BLKTYPE + else: + return None + + # Fill the TarInfo object with all + # information we can get. + tarinfo.name = arcname + tarinfo.mode = stmd + tarinfo.uid = statres.st_uid + tarinfo.gid = statres.st_gid + if type == REGTYPE: + tarinfo.size = statres.st_size + else: + tarinfo.size = 0 + tarinfo.mtime = statres.st_mtime + tarinfo.type = type + tarinfo.linkname = linkname + if pwd: + try: + tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0] + except KeyError: + pass + if grp: + try: + tarinfo.gname = grp.getgrgid(tarinfo.gid)[0] + except KeyError: + pass + + if type in (CHRTYPE, BLKTYPE): + if hasattr(os, "major") and hasattr(os, "minor"): + tarinfo.devmajor = os.major(statres.st_rdev) + tarinfo.devminor = os.minor(statres.st_rdev) + return tarinfo + + def list(self, verbose=True): + """Print a table of contents to sys.stdout. If `verbose' is False, only + the names of the members are printed. If it is True, an `ls -l'-like + output is produced. + """ + self._check() + + for tarinfo in self: + if verbose: + print(filemode(tarinfo.mode), end=' ') + print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid), end=' ') + if tarinfo.ischr() or tarinfo.isblk(): + print("%10s" % ("%d,%d" \ + % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + else: + print("%10d" % tarinfo.size, end=' ') + print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6], end=' ') + + print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + + if verbose: + if tarinfo.issym(): + print("->", tarinfo.linkname, end=' ') + if tarinfo.islnk(): + print("link to", tarinfo.linkname, end=' ') + print() + + def add(self, name, arcname=None, recursive=True, exclude=None, filter=None): + """Add the file `name' to the archive. `name' may be any type of file + (directory, fifo, symbolic link, etc.). If given, `arcname' + specifies an alternative name for the file in the archive. + Directories are added recursively by default. This can be avoided by + setting `recursive' to False. `exclude' is a function that should + return True for each filename to be excluded. `filter' is a function + that expects a TarInfo object argument and returns the changed + TarInfo object, if it returns None the TarInfo object will be + excluded from the archive. + """ + self._check("aw") + + if arcname is None: + arcname = name + + # Exclude pathnames. + if exclude is not None: + import warnings + warnings.warn("use the filter argument instead", + DeprecationWarning, 2) + if exclude(name): + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Skip if somebody tries to archive the archive... + if self.name is not None and os.path.abspath(name) == self.name: + self._dbg(2, "tarfile: Skipped %r" % name) + return + + self._dbg(1, name) + + # Create a TarInfo object from the file. + tarinfo = self.gettarinfo(name, arcname) + + if tarinfo is None: + self._dbg(1, "tarfile: Unsupported type %r" % name) + return + + # Change or exclude the TarInfo object. + if filter is not None: + tarinfo = filter(tarinfo) + if tarinfo is None: + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # Append the tar header and data to the archive. + if tarinfo.isreg(): + f = bltn_open(name, "rb") + self.addfile(tarinfo, f) + f.close() + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in os.listdir(name): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, exclude, filter=filter) + + else: + self.addfile(tarinfo) + + def addfile(self, tarinfo, fileobj=None): + """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is + given, tarinfo.size bytes are read from it and added to the archive. + You can create TarInfo objects using gettarinfo(). + On Windows platforms, `fileobj' should always be opened with mode + 'rb' to avoid irritation about the file size. + """ + self._check("aw") + + tarinfo = copy.copy(tarinfo) + + buf = tarinfo.tobuf(self.format, self.encoding, self.errors) + self.fileobj.write(buf) + self.offset += len(buf) + + # If there's data to follow, append it. + if fileobj is not None: + copyfileobj(fileobj, self.fileobj, tarinfo.size) + blocks, remainder = divmod(tarinfo.size, BLOCKSIZE) + if remainder > 0: + self.fileobj.write(NUL * (BLOCKSIZE - remainder)) + blocks += 1 + self.offset += blocks * BLOCKSIZE + + self.members.append(tarinfo) + + def extractall(self, path=".", members=None): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directories with a safe mode. + directories.append(tarinfo) + tarinfo = copy.copy(tarinfo) + tarinfo.mode = 0o700 + # Do not set_attrs directories, as we will do that further down + self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) + + # Reverse sort directories. + directories.sort(key=lambda a: a.name) + directories.reverse() + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + dirpath = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, dirpath) + self.utime(tarinfo, dirpath) + self.chmod(tarinfo, dirpath) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extract(self, member, path="", set_attrs=True): + """Extract a member from the archive to the current working directory, + using its full name. Its file information is extracted as accurately + as possible. `member' may be a filename or a TarInfo object. You can + specify a different directory using `path'. File attributes (owner, + mtime, mode) are set unless `set_attrs' is False. + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + # Prepare the link target for makelink(). + if tarinfo.islnk(): + tarinfo._link_target = os.path.join(path, tarinfo.linkname) + + try: + self._extract_member(tarinfo, os.path.join(path, tarinfo.name), + set_attrs=set_attrs) + except EnvironmentError as e: + if self.errorlevel > 0: + raise + else: + if e.filename is None: + self._dbg(1, "tarfile: %s" % e.strerror) + else: + self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename)) + except ExtractError as e: + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + def extractfile(self, member): + """Extract a member from the archive as a file object. `member' may be + a filename or a TarInfo object. If `member' is a regular file, a + file-like object is returned. If `member' is a link, a file-like + object is constructed from the link's target. If `member' is none of + the above, None is returned. + The file-like object is read-only and provides the following + methods: read(), readline(), readlines(), seek() and tell() + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + if tarinfo.isreg(): + return self.fileobject(self, tarinfo) + + elif tarinfo.type not in SUPPORTED_TYPES: + # If a member's type is unknown, it is treated as a + # regular file. + return self.fileobject(self, tarinfo) + + elif tarinfo.islnk() or tarinfo.issym(): + if isinstance(self.fileobj, _Stream): + # A small but ugly workaround for the case that someone tries + # to extract a (sym)link as a file-object from a non-seekable + # stream of tar blocks. + raise StreamError("cannot extract (sym)link as file object") + else: + # A (sym)link's file object is its target's file object. + return self.extractfile(self._find_link_target(tarinfo)) + else: + # If there's no data associated with the member (directory, chrdev, + # blkdev, etc.), return None instead of a file object. + return None + + def _extract_member(self, tarinfo, targetpath, set_attrs=True): + """Extract the TarInfo object tarinfo to a physical + file called targetpath. + """ + # Fetch the TarInfo object for the given name + # and build the destination pathname, replacing + # forward slashes to platform specific separators. + targetpath = targetpath.rstrip("/") + targetpath = targetpath.replace("/", os.sep) + + # Create all upper directories. + upperdirs = os.path.dirname(targetpath) + if upperdirs and not os.path.exists(upperdirs): + # Create directories that are not part of the archive with + # default permissions. + os.makedirs(upperdirs) + + if tarinfo.islnk() or tarinfo.issym(): + self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname)) + else: + self._dbg(1, tarinfo.name) + + if tarinfo.isreg(): + self.makefile(tarinfo, targetpath) + elif tarinfo.isdir(): + self.makedir(tarinfo, targetpath) + elif tarinfo.isfifo(): + self.makefifo(tarinfo, targetpath) + elif tarinfo.ischr() or tarinfo.isblk(): + self.makedev(tarinfo, targetpath) + elif tarinfo.islnk() or tarinfo.issym(): + self.makelink(tarinfo, targetpath) + elif tarinfo.type not in SUPPORTED_TYPES: + self.makeunknown(tarinfo, targetpath) + else: + self.makefile(tarinfo, targetpath) + + if set_attrs: + self.chown(tarinfo, targetpath) + if not tarinfo.issym(): + self.chmod(tarinfo, targetpath) + self.utime(tarinfo, targetpath) + + #-------------------------------------------------------------------------- + # Below are the different file methods. They are called via + # _extract_member() when extract() is called. They can be replaced in a + # subclass to implement other functionality. + + def makedir(self, tarinfo, targetpath): + """Make a directory called targetpath. + """ + try: + # Use a safe mode for the directory, the real mode is set + # later in _extract_member(). + os.mkdir(targetpath, 0o700) + except EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + + def makefile(self, tarinfo, targetpath): + """Make a file called targetpath. + """ + source = self.fileobj + source.seek(tarinfo.offset_data) + target = bltn_open(targetpath, "wb") + if tarinfo.sparse is not None: + for offset, size in tarinfo.sparse: + target.seek(offset) + copyfileobj(source, target, size) + else: + copyfileobj(source, target, tarinfo.size) + target.seek(tarinfo.size) + target.truncate() + target.close() + + def makeunknown(self, tarinfo, targetpath): + """Make a file from a TarInfo object with an unknown type + at targetpath. + """ + self.makefile(tarinfo, targetpath) + self._dbg(1, "tarfile: Unknown file type %r, " \ + "extracted as regular file." % tarinfo.type) + + def makefifo(self, tarinfo, targetpath): + """Make a fifo called targetpath. + """ + if hasattr(os, "mkfifo"): + os.mkfifo(targetpath) + else: + raise ExtractError("fifo not supported by system") + + def makedev(self, tarinfo, targetpath): + """Make a character or block device called targetpath. + """ + if not hasattr(os, "mknod") or not hasattr(os, "makedev"): + raise ExtractError("special devices not supported by system") + + mode = tarinfo.mode + if tarinfo.isblk(): + mode |= stat.S_IFBLK + else: + mode |= stat.S_IFCHR + + os.mknod(targetpath, mode, + os.makedev(tarinfo.devmajor, tarinfo.devminor)) + + def makelink(self, tarinfo, targetpath): + """Make a (symbolic) link called targetpath. If it cannot be created + (platform limitation), we try to make a copy of the referenced file + instead of a link. + """ + try: + # For systems that support symbolic and hard links. + if tarinfo.issym(): + os.symlink(tarinfo.linkname, targetpath) + else: + # See extract(). + if os.path.exists(tarinfo._link_target): + os.link(tarinfo._link_target, targetpath) + else: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except symlink_exception: + if tarinfo.issym(): + linkpath = os.path.join(os.path.dirname(tarinfo.name), + tarinfo.linkname) + else: + linkpath = tarinfo.linkname + else: + try: + self._extract_member(self._find_link_target(tarinfo), + targetpath) + except KeyError: + raise ExtractError("unable to resolve link inside archive") + + def chown(self, tarinfo, targetpath): + """Set owner of targetpath according to tarinfo. + """ + if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: + # We have to be root to do so. + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid + try: + if tarinfo.issym() and hasattr(os, "lchown"): + os.lchown(targetpath, u, g) + else: + if sys.platform != "os2emx": + os.chown(targetpath, u, g) + except EnvironmentError as e: + raise ExtractError("could not change owner") + + def chmod(self, tarinfo, targetpath): + """Set file permissions of targetpath according to tarinfo. + """ + if hasattr(os, 'chmod'): + try: + os.chmod(targetpath, tarinfo.mode) + except EnvironmentError as e: + raise ExtractError("could not change mode") + + def utime(self, tarinfo, targetpath): + """Set modification time of targetpath according to tarinfo. + """ + if not hasattr(os, 'utime'): + return + try: + os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime)) + except EnvironmentError as e: + raise ExtractError("could not change modification time") + + #-------------------------------------------------------------------------- + def next(self): + """Return the next member of the archive as a TarInfo object, when + TarFile is opened for reading. Return None if there is no more + available. + """ + self._check("ra") + if self.firstmember is not None: + m = self.firstmember + self.firstmember = None + return m + + # Read the next block. + self.fileobj.seek(self.offset) + tarinfo = None + while True: + try: + tarinfo = self.tarinfo.fromtarfile(self) + except EOFHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + except InvalidHeaderError as e: + if self.ignore_zeros: + self._dbg(2, "0x%X: %s" % (self.offset, e)) + self.offset += BLOCKSIZE + continue + elif self.offset == 0: + raise ReadError(str(e)) + except EmptyHeaderError: + if self.offset == 0: + raise ReadError("empty file") + except TruncatedHeaderError as e: + if self.offset == 0: + raise ReadError(str(e)) + except SubsequentHeaderError as e: + raise ReadError(str(e)) + break + + if tarinfo is not None: + self.members.append(tarinfo) + else: + self._loaded = True + + return tarinfo + + #-------------------------------------------------------------------------- + # Little helper methods: + + def _getmember(self, name, tarinfo=None, normalize=False): + """Find an archive member by name from bottom to top. + If tarinfo is given, it is used as the starting point. + """ + # Ensure that all members have been loaded. + members = self.getmembers() + + # Limit the member search list up to tarinfo. + if tarinfo is not None: + members = members[:members.index(tarinfo)] + + if normalize: + name = os.path.normpath(name) + + for member in reversed(members): + if normalize: + member_name = os.path.normpath(member.name) + else: + member_name = member.name + + if name == member_name: + return member + + def _load(self): + """Read through the entire archive file and look for readable + members. + """ + while True: + tarinfo = self.next() + if tarinfo is None: + break + self._loaded = True + + def _check(self, mode=None): + """Check if TarFile is still open, and if the operation's mode + corresponds to TarFile's mode. + """ + if self.closed: + raise IOError("%s is closed" % self.__class__.__name__) + if mode is not None and self.mode not in mode: + raise IOError("bad operation for mode %r" % self.mode) + + def _find_link_target(self, tarinfo): + """Find the target member of a symlink or hardlink member in the + archive. + """ + if tarinfo.issym(): + # Always search the entire archive. + linkname = os.path.dirname(tarinfo.name) + "/" + tarinfo.linkname + limit = None + else: + # Search the archive before the link, because a hard link is + # just a reference to an already archived file. + linkname = tarinfo.linkname + limit = tarinfo + + member = self._getmember(linkname, tarinfo=limit, normalize=True) + if member is None: + raise KeyError("linkname %r not found" % linkname) + return member + + def __iter__(self): + """Provide an iterator object. + """ + if self._loaded: + return iter(self.members) + else: + return TarIter(self) + + def _dbg(self, level, msg): + """Write debugging output to sys.stderr. + """ + if level <= self.debug: + print(msg, file=sys.stderr) + + def __enter__(self): + self._check() + return self + + def __exit__(self, type, value, traceback): + if type is None: + self.close() + else: + # An exception occurred. We must not call close() because + # it would try to write end-of-archive blocks and padding. + if not self._extfileobj: + self.fileobj.close() + self.closed = True +# class TarFile + +class TarIter(object): + """Iterator Class. + + for tarinfo in TarFile(...): + suite... + """ + + def __init__(self, tarfile): + """Construct a TarIter object. + """ + self.tarfile = tarfile + self.index = 0 + def __iter__(self): + """Return iterator object. + """ + return self + + def __next__(self): + """Return the next item using TarFile's next() method. + When all members have been read, set TarFile as _loaded. + """ + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will cause TarIter to stop prematurely. + if not self.tarfile._loaded: + tarinfo = self.tarfile.next() + if not tarinfo: + self.tarfile._loaded = True + raise StopIteration + else: + try: + tarinfo = self.tarfile.members[self.index] + except IndexError: + raise StopIteration + self.index += 1 + return tarinfo + + next = __next__ # for Python 2.x + +#-------------------- +# exported functions +#-------------------- +def is_tarfile(name): + """Return True if name points to a tar archive that we + are able to handle, else return False. + """ + try: + t = open(name) + t.close() + return True + except TarError: + return False + +bltn_open = open +open = TarFile.open diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/compat.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/compat.py new file mode 100644 index 00000000..ff328c8e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/compat.py @@ -0,0 +1,1120 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import absolute_import + +import os +import re +import sys + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +if sys.version_info[0] < 3: # pragma: no cover + from StringIO import StringIO + string_types = basestring, + text_type = unicode + from types import FileType as file_type + import __builtin__ as builtins + import ConfigParser as configparser + from ._backport import shutil + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit + from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, + pathname2url, ContentTooShortError, splittype) + + def quote(s): + if isinstance(s, unicode): + s = s.encode('utf-8') + return _quote(s) + + import urllib2 + from urllib2 import (Request, urlopen, URLError, HTTPError, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib2 import HTTPSHandler + import httplib + import xmlrpclib + import Queue as queue + from HTMLParser import HTMLParser + import htmlentitydefs + raw_input = raw_input + from itertools import ifilter as filter + from itertools import ifilterfalse as filterfalse + + _userprog = None + def splituser(host): + """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + global _userprog + if _userprog is None: + import re + _userprog = re.compile('^(.*)@(.*)$') + + match = _userprog.match(host) + if match: return match.group(1, 2) + return None, host + +else: # pragma: no cover + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote, + unquote, urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib.request import HTTPSHandler + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + +try: + from ssl import match_hostname, CertificateError +except ImportError: # pragma: no cover + class CertificateError(ValueError): + pass + + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + parts = dn.split('.') + leftmost, remainder = parts[0], parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +try: + from types import SimpleNamespace as Container +except ImportError: # pragma: no cover + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: # pragma: no cover + # Implementation from Python 3.3 + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + + """ + # Check that a given file can be accessed with the correct mode. + # Additionally check that `file` is not a directory, as on Windows + # directories pass the os.access check. + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + # If we're given a path with a directory part, look it up directly rather + # than referring to PATH directories. This includes checking relative to the + # current directory, e.g. ./script + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + # The current directory takes precedence on Windows. + if not os.curdir in path: + path.insert(0, os.curdir) + + # PATHEXT is necessary to check on Windows. + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + # See if the given file matches any of the expected path extensions. + # This will allow us to short circuit when given "python.exe". + # If it does match, only test that one, otherwise we have to try + # others. + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + # On other platforms you don't have things like PATHEXT to tell you + # what file suffixes are executable, so just pass on cmd as-is. + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if not normdir in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None + + +# ZipFile is a context manager in 2.7, but not in 2.6 + +from zipfile import ZipFile as BaseZipFile + +if hasattr(BaseZipFile, '__enter__'): # pragma: no cover + ZipFile = BaseZipFile +else: # pragma: no cover + from zipfile import ZipExtFile as BaseZipExtFile + + class ZipExtFile(BaseZipExtFile): + def __init__(self, base): + self.__dict__.update(base.__dict__) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + class ZipFile(BaseZipFile): + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + def open(self, *args, **kwargs): + base = BaseZipFile.open(self, *args, **kwargs) + return ZipExtFile(base) + +try: + from platform import python_implementation +except ImportError: # pragma: no cover + def python_implementation(): + """Return a string identifying the Python implementation.""" + if 'PyPy' in sys.version: + return 'PyPy' + if os.name == 'java': + return 'Jython' + if sys.version.startswith('IronPython'): + return 'IronPython' + return 'CPython' + +try: + import sysconfig +except ImportError: # pragma: no cover + from ._backport import sysconfig + +try: + callable = callable +except NameError: # pragma: no cover + from collections import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode + fsdecode = os.fsdecode +except AttributeError: # pragma: no cover + # Issue #99: on some systems (e.g. containerised), + # sys.getfilesystemencoding() returns None, and we need a real value, + # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and + # sys.getfilesystemencoding(): the return value is "the user’s preference + # according to the result of nl_langinfo(CODESET), or None if the + # nl_langinfo(CODESET) failed." + _fsencoding = sys.getfilesystemencoding() or 'utf-8' + if _fsencoding == 'mbcs': + _fserrors = 'strict' + else: + _fserrors = 'surrogateescape' + + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, text_type): + return filename.encode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + def fsdecode(filename): + if isinstance(filename, text_type): + return filename + elif isinstance(filename, bytes): + return filename.decode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + +try: + from tokenize import detect_encoding +except ImportError: # pragma: no cover + from codecs import BOM_UTF8, lookup + import re + + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") + + def _get_normal_name(orig_enc): + """Imitates get_normal_name in tokenizer.c.""" + # Only care about the first 12 characters. + enc = orig_enc[:12].lower().replace("_", "-") + if enc == "utf-8" or enc.startswith("utf-8-"): + return "utf-8" + if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \ + enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")): + return "iso-8859-1" + return orig_enc + + def detect_encoding(readline): + """ + The detect_encoding() function is used to detect the encoding that should + be used to decode a Python source file. It requires one argument, readline, + in the same way as the tokenize() generator. + + It will call readline a maximum of twice, and return the encoding used + (as a string) and a list of any lines (left as bytes) it has read in. + + It detects the encoding from the presence of a utf-8 bom or an encoding + cookie as specified in pep-0263. If both a bom and a cookie are present, + but disagree, a SyntaxError will be raised. If the encoding cookie is an + invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found, + 'utf-8-sig' is returned. + + If no encoding is specified, then the default of 'utf-8' will be returned. + """ + try: + filename = readline.__self__.name + except AttributeError: + filename = None + bom_found = False + encoding = None + default = 'utf-8' + def read_or_stop(): + try: + return readline() + except StopIteration: + return b'' + + def find_cookie(line): + try: + # Decode as UTF-8. Either the line is an encoding declaration, + # in which case it should be pure ASCII, or it must be UTF-8 + # per default encoding. + line_string = line.decode('utf-8') + except UnicodeDecodeError: + msg = "invalid or missing encoding declaration" + if filename is not None: + msg = '{} for {!r}'.format(msg, filename) + raise SyntaxError(msg) + + matches = cookie_re.findall(line_string) + if not matches: + return None + encoding = _get_normal_name(matches[0]) + try: + codec = lookup(encoding) + except LookupError: + # This behaviour mimics the Python interpreter + if filename is None: + msg = "unknown encoding: " + encoding + else: + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) + raise SyntaxError(msg) + + if bom_found: + if codec.name != 'utf-8': + # This behaviour mimics the Python interpreter + if filename is None: + msg = 'encoding problem: utf-8' + else: + msg = 'encoding problem for {!r}: utf-8'.format(filename) + raise SyntaxError(msg) + encoding += '-sig' + return encoding + + first = read_or_stop() + if first.startswith(BOM_UTF8): + bom_found = True + first = first[3:] + default = 'utf-8-sig' + if not first: + return default, [] + + encoding = find_cookie(first) + if encoding: + return encoding, [first] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + +# For converting & <-> & etc. +try: + from html import escape +except ImportError: + from cgi import escape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape + +try: + from collections import ChainMap +except ImportError: # pragma: no cover + from collections import MutableMapping + + try: + from reprlib import recursive_repr as _recursive_repr + except ImportError: + def _recursive_repr(fillvalue='...'): + ''' + Decorator to make a repr function return fillvalue for a recursive + call + ''' + + def decorating_function(user_function): + repr_running = set() + + def wrapper(self): + key = id(self), get_ident() + if key in repr_running: + return fillvalue + repr_running.add(key) + try: + result = user_function(self) + finally: + repr_running.discard(key) + return result + + # Can't use functools.wraps() here because of bootstrap issues + wrapper.__module__ = getattr(user_function, '__module__') + wrapper.__doc__ = getattr(user_function, '__doc__') + wrapper.__name__ = getattr(user_function, '__name__') + wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) + return wrapper + + return decorating_function + + class ChainMap(MutableMapping): + ''' A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + accessed or updated using the *maps* attribute. There is no other state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__(key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union(*self.maps)) # reuses stored hash values if possible + + def __iter__(self): + return iter(set().union(*self.maps)) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self): # like Django's Context.push() + 'New ChainMap with a new dict followed by all previous maps.' + return self.__class__({}, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + +try: + from importlib.util import cache_from_source # Python >= 3.4 +except ImportError: # pragma: no cover + try: + from imp import cache_from_source + except ImportError: # pragma: no cover + def cache_from_source(path, debug_override=None): + assert path.endswith('.py') + if debug_override is None: + debug_override = __debug__ + if debug_override: + suffix = 'c' + else: + suffix = 'o' + return path + suffix + +try: + from collections import OrderedDict +except ImportError: # pragma: no cover +## {{{ http://code.activestate.com/recipes/576693/ (r9) +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + try: + from thread import get_ident as _get_ident + except ImportError: + from dummy_thread import get_ident as _get_ident + + try: + from _abcoll import KeysView, ValuesView, ItemsView + except ImportError: + pass + + + class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + for key in other: + self[key] = other[key] + elif hasattr(other, 'keys'): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value. + If key is not found, d is returned if given, otherwise KeyError is raised. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running=None): + 'od.__repr__() <==> repr(od)' + if not _repr_running: _repr_running = {} + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/database.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/database.py new file mode 100644 index 00000000..c16c0c8d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/database.py @@ -0,0 +1,1339 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""PEP 376 implementation.""" + +from __future__ import unicode_literals + +import base64 +import codecs +import contextlib +import hashlib +import logging +import os +import posixpath +import sys +import zipimport + +from . import DistlibException, resources +from .compat import StringIO +from .version import get_scheme, UnsupportedVersionError +from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, + LEGACY_METADATA_FILENAME) +from .util import (parse_requirement, cached_property, parse_name_and_version, + read_exports, write_exports, CSVReader, CSVWriter) + + +__all__ = ['Distribution', 'BaseInstalledDistribution', + 'InstalledDistribution', 'EggInfoDistribution', + 'DistributionPath'] + + +logger = logging.getLogger(__name__) + +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', + 'RESOURCES', EXPORTS_FILENAME, 'SHARED') + +DISTINFO_EXT = '.dist-info' + + +class _Cache(object): + """ + A simple cache mapping names and .dist-info paths to distributions + """ + def __init__(self): + """ + Initialise an instance. There is normally one for each DistributionPath. + """ + self.name = {} + self.path = {} + self.generated = False + + def clear(self): + """ + Clear the cache, setting it to its initial state. + """ + self.name.clear() + self.path.clear() + self.generated = False + + def add(self, dist): + """ + Add a distribution to the cache. + :param dist: The distribution to add. + """ + if dist.path not in self.path: + self.path[dist.path] = dist + self.name.setdefault(dist.key, []).append(dist) + + +class DistributionPath(object): + """ + Represents a set of distributions installed on a path (typically sys.path). + """ + def __init__(self, path=None, include_egg=False): + """ + Create an instance from a path, optionally including legacy (distutils/ + setuptools/distribute) distributions. + :param path: The path to use, as a list of directories. If not specified, + sys.path is used. + :param include_egg: If True, this instance will look for and return legacy + distributions as well as those based on PEP 376. + """ + if path is None: + path = sys.path + self.path = path + self._include_dist = True + self._include_egg = include_egg + + self._cache = _Cache() + self._cache_egg = _Cache() + self._cache_enabled = True + self._scheme = get_scheme('default') + + def _get_cache_enabled(self): + return self._cache_enabled + + def _set_cache_enabled(self, value): + self._cache_enabled = value + + cache_enabled = property(_get_cache_enabled, _set_cache_enabled) + + def clear_cache(self): + """ + Clears the internal cache. + """ + self._cache.clear() + self._cache_egg.clear() + + + def _yield_distributions(self): + """ + Yield .dist-info and/or .egg(-info) distributions. + """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() + for path in self.path: + finder = resources.finder_for_path(path) + if finder is None: + continue + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + if self._include_dist and entry.endswith(DISTINFO_EXT): + possible_filenames = [METADATA_FILENAME, + WHEEL_METADATA_FILENAME, + LEGACY_METADATA_FILENAME] + for metadata_filename in possible_filenames: + metadata_path = posixpath.join(entry, metadata_filename) + pydist = finder.find(metadata_path) + if pydist: + break + else: + continue + + with contextlib.closing(pydist.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, + env=self) + elif self._include_egg and entry.endswith(('.egg-info', + '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) + + def _generate_cache(self): + """ + Scan the path for distributions and populate the cache with + those that are found. + """ + gen_dist = not self._cache.generated + gen_egg = self._include_egg and not self._cache_egg.generated + if gen_dist or gen_egg: + for dist in self._yield_distributions(): + if isinstance(dist, InstalledDistribution): + self._cache.add(dist) + else: + self._cache_egg.add(dist) + + if gen_dist: + self._cache.generated = True + if gen_egg: + self._cache_egg.generated = True + + @classmethod + def distinfo_dirname(cls, name, version): + """ + The *name* and *version* parameters are converted into their + filename-escaped form, i.e. any ``'-'`` characters are replaced + with ``'_'`` other than the one in ``'dist-info'`` and the one + separating the name from the version number. + + :parameter name: is converted to a standard distribution name by replacing + any runs of non- alphanumeric characters with a single + ``'-'``. + :type name: string + :parameter version: is converted to a standard version string. Spaces + become dots, and all other non-alphanumeric characters + (except dots) become dashes, with runs of multiple + dashes condensed to a single dash. + :type version: string + :returns: directory name + :rtype: string""" + name = name.replace('-', '_') + return '-'.join([name, version]) + DISTINFO_EXT + + def get_distributions(self): + """ + Provides an iterator that looks for distributions and returns + :class:`InstalledDistribution` or + :class:`EggInfoDistribution` instances for each one of them. + + :rtype: iterator of :class:`InstalledDistribution` and + :class:`EggInfoDistribution` instances + """ + if not self._cache_enabled: + for dist in self._yield_distributions(): + yield dist + else: + self._generate_cache() + + for dist in self._cache.path.values(): + yield dist + + if self._include_egg: + for dist in self._cache_egg.path.values(): + yield dist + + def get_distribution(self, name): + """ + Looks for a named distribution on the path. + + This function only returns the first result found, as no more than one + value is expected. If nothing is found, ``None`` is returned. + + :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` + or ``None`` + """ + result = None + name = name.lower() + if not self._cache_enabled: + for dist in self._yield_distributions(): + if dist.key == name: + result = dist + break + else: + self._generate_cache() + + if name in self._cache.name: + result = self._cache.name[name][0] + elif self._include_egg and name in self._cache_egg.name: + result = self._cache_egg.name[name][0] + return result + + def provides_distribution(self, name, version=None): + """ + Iterates over all distributions to find which distributions provide *name*. + If a *version* is provided, it will be used to filter the results. + + This function only returns the first result found, since no more than + one values are expected. If the directory is not found, returns ``None``. + + :parameter version: a version specifier that indicates the version + required, conforming to the format in ``PEP-345`` + + :type name: string + :type version: string + """ + matcher = None + if version is not None: + try: + matcher = self._scheme.matcher('%s (%s)' % (name, version)) + except ValueError: + raise DistlibException('invalid name or version: %r, %r' % + (name, version)) + + for dist in self.get_distributions(): + # We hit a problem on Travis where enum34 was installed and doesn't + # have a provides attribute ... + if not hasattr(dist, 'provides'): + logger.debug('No "provides": %s', dist) + else: + provided = dist.provides + + for p in provided: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: + yield dist + break + else: + if p_name == name and matcher.match(p_ver): + yield dist + break + + def get_file_path(self, name, relative_path): + """ + Return the path to a resource file. + """ + dist = self.get_distribution(name) + if dist is None: + raise LookupError('no distribution named %r found' % name) + return dist.get_resource_path(relative_path) + + def get_exported_entries(self, category, name=None): + """ + Return all of the exported entries in a particular category. + + :param category: The category to search for entries. + :param name: If specified, only entries with that name are returned. + """ + for dist in self.get_distributions(): + r = dist.exports + if category in r: + d = r[category] + if name is not None: + if name in d: + yield d[name] + else: + for v in d.values(): + yield v + + +class Distribution(object): + """ + A base class for distributions, whether installed or from indexes. + Either way, it must have some metadata, so that's all that's needed + for construction. + """ + + build_time_dependency = False + """ + Set to True if it's known to be only a build-time dependency (i.e. + not needed after installation). + """ + + requested = False + """A boolean that indicates whether the ``REQUESTED`` metadata file is + present (in other words, whether the package was installed by user + request or it was installed as a dependency).""" + + def __init__(self, metadata): + """ + Initialise an instance. + :param metadata: The instance of :class:`Metadata` describing this + distribution. + """ + self.metadata = metadata + self.name = metadata.name + self.key = self.name.lower() # for case-insensitive comparisons + self.version = metadata.version + self.locator = None + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides + self.download_urls = set() + self.digests = {} + + @property + def source_url(self): + """ + The source archive download URL for this distribution. + """ + return self.metadata.source_url + + download_url = source_url # Backward compatibility + + @property + def name_and_version(self): + """ + A utility property which displays the name and version in parentheses. + """ + return '%s (%s)' % (self.name, self.version) + + @property + def provides(self): + """ + A set of distribution names and versions provided by this distribution. + :return: A set of "name (version)" strings. + """ + plist = self.metadata.provides + s = '%s (%s)' % (self.name, self.version) + if s not in plist: + plist.append(s) + return plist + + def _get_requirements(self, req_attr): + md = self.metadata + logger.debug('Getting requirements from metadata %r', md.todict()) + reqts = getattr(md, req_attr) + return set(md.get_requirements(reqts, extras=self.extras, + env=self.context)) + + @property + def run_requires(self): + return self._get_requirements('run_requires') + + @property + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') + + @property + def test_requires(self): + return self._get_requirements('test_requires') + + @property + def dev_requires(self): + return self._get_requirements('dev_requires') + + def matches_requirement(self, req): + """ + Say if this instance matches (fulfills) a requirement. + :param req: The requirement to match. + :rtype req: str + :return: True if it matches, else False. + """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) + scheme = get_scheme(self.metadata.scheme) + try: + matcher = scheme.matcher(r.requirement) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + result = False + for p in self.provides: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: + continue + try: + result = matcher.match(p_ver) + break + except UnsupportedVersionError: + pass + return result + + def __repr__(self): + """ + Return a textual representation of this instance, + """ + if self.source_url: + suffix = ' [%s]' % self.source_url + else: + suffix = '' + return '' % (self.name, self.version, suffix) + + def __eq__(self, other): + """ + See if this distribution is the same as another. + :param other: The distribution to compare with. To be equal to one + another. distributions must have the same type, name, + version and source_url. + :return: True if it is the same, else False. + """ + if type(other) is not type(self): + result = False + else: + result = (self.name == other.name and + self.version == other.version and + self.source_url == other.source_url) + return result + + def __hash__(self): + """ + Compute hash in a way which matches the equality test. + """ + return hash(self.name) + hash(self.version) + hash(self.source_url) + + +class BaseInstalledDistribution(Distribution): + """ + This is the base class for installed distributions (whether PEP 376 or + legacy). + """ + + hasher = None + + def __init__(self, metadata, path, env=None): + """ + Initialise an instance. + :param metadata: An instance of :class:`Metadata` which describes the + distribution. This will normally have been initialised + from a metadata file in the ``path``. + :param path: The path of the ``.dist-info`` or ``.egg-info`` + directory for the distribution. + :param env: This is normally the :class:`DistributionPath` + instance where this distribution was found. + """ + super(BaseInstalledDistribution, self).__init__(metadata) + self.path = path + self.dist_path = env + + def get_hash(self, data, hasher=None): + """ + Get the hash of some data, using a particular hash algorithm, if + specified. + + :param data: The data to be hashed. + :type data: bytes + :param hasher: The name of a hash implementation, supported by hashlib, + or ``None``. Examples of valid values are ``'sha1'``, + ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and + ``'sha512'``. If no hasher is specified, the ``hasher`` + attribute of the :class:`InstalledDistribution` instance + is used. If the hasher is determined to be ``None``, MD5 + is used as the hashing algorithm. + :returns: The hash of the data. If a hasher was explicitly specified, + the returned hash will be prefixed with the specified hasher + followed by '='. + :rtype: str + """ + if hasher is None: + hasher = self.hasher + if hasher is None: + hasher = hashlib.md5 + prefix = '' + else: + hasher = getattr(hashlib, hasher) + prefix = '%s=' % self.hasher + digest = hasher(data).digest() + digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') + return '%s%s' % (prefix, digest) + + +class InstalledDistribution(BaseInstalledDistribution): + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is + instantiated., or uses a passed in Metadata instance (useful for when + dry-run mode is being used). + """ + + hasher = 'sha256' + + def __init__(self, path, metadata=None, env=None): + self.modules = [] + self.finder = finder = resources.finder_for_path(path) + if finder is None: + raise ValueError('finder unavailable for %s' % path) + if env and env._cache_enabled and path in env._cache.path: + metadata = env._cache.path[path].metadata + elif metadata is None: + r = finder.find(METADATA_FILENAME) + # Temporary - for Wheel 0.23 support + if r is None: + r = finder.find(WHEEL_METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find('METADATA') + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, + path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + + super(InstalledDistribution, self).__init__(metadata, path, env) + + if env and env._cache_enabled: + env._cache.add(self) + + r = finder.find('REQUESTED') + self.requested = r is not None + p = os.path.join(path, 'top_level.txt') + if os.path.exists(p): + with open(p, 'rb') as f: + data = f.read().decode('utf-8') + self.modules = data.splitlines() + + def __repr__(self): + return '' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def _get_records(self): + """ + Get the list of installed files for the distribution + :return: A list of tuples of path, hash and size. Note that hash and + size might be ``None`` for some entries. The path is exactly + as stored in the file (which is as in PEP 376). + """ + results = [] + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + #base_location = os.path.dirname(self.path) + #base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + #if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) + return results + + @cached_property + def exports(self): + """ + Return the information exported by this distribution. + :return: A dictionary of exports, mapping an export category to a dict + of :class:`ExportEntry` instances describing the individual + export entries, and keyed by name. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() + return result + + def read_exports(self): + """ + Read exports data from a file in .ini format. + + :return: A dictionary of exports, mapping an export category to a list + of :class:`ExportEntry` instances describing the individual + export entries. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) + return result + + def write_exports(self, exports): + """ + Write a dictionary of exports to a file in .ini format. + :param exports: A dictionary of exports, mapping an export category to + a list of :class:`ExportEntry` instances describing the + individual export entries. + """ + rf = self.get_distinfo_file(EXPORTS_FILENAME) + with open(rf, 'w') as f: + write_exports(exports, f) + + def get_resource_path(self, relative_path): + """ + NOTE: This API may change in the future. + + Return the absolute path to a resource file with the given relative + path. + + :param relative_path: The path, relative to .dist-info, of the resource + of interest. + :return: The absolute path where the resource is to be found. + """ + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination + raise KeyError('no resource file with relative path %r ' + 'is installed' % relative_path) + + def list_installed_files(self): + """ + Iterates over the ``RECORD`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: iterator of (path, hash, size) + """ + for result in self._get_records(): + yield result + + def write_installed_files(self, paths, prefix, dry_run=False): + """ + Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any + existing ``RECORD`` file is silently overwritten. + + prefix is used to determine when to write absolute paths. + """ + prefix = os.path.join(prefix, '') + base = os.path.dirname(self.path) + base_under_prefix = base.startswith(prefix) + base = os.path.join(base, '') + record_path = self.get_distinfo_file('RECORD') + logger.info('creating %s', record_path) + if dry_run: + return None + with CSVWriter(record_path) as writer: + for path in paths: + if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): + # do not put size and hash, as in PEP-376 + hash_value = size = '' + else: + size = '%d' % os.path.getsize(path) + with open(path, 'rb') as fp: + hash_value = self.get_hash(fp.read()) + if path.startswith(base) or (base_under_prefix and + path.startswith(prefix)): + path = os.path.relpath(path, base) + writer.writerow((path, hash_value, size)) + + # add the RECORD file itself + if record_path.startswith(base): + record_path = os.path.relpath(record_path, base) + writer.writerow((record_path, '', '')) + return record_path + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + base = os.path.dirname(self.path) + record_path = self.get_distinfo_file('RECORD') + for path, hash_value, size in self.list_installed_files(): + if not os.path.isabs(path): + path = os.path.join(base, path) + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + elif os.path.isfile(path): + actual_size = str(os.path.getsize(path)) + if size and actual_size != size: + mismatches.append((path, 'size', size, actual_size)) + elif hash_value: + if '=' in hash_value: + hasher = hash_value.split('=', 1)[0] + else: + hasher = None + + with open(path, 'rb') as f: + actual_hash = self.get_hash(f.read(), hasher) + if actual_hash != hash_value: + mismatches.append((path, 'hash', hash_value, actual_hash)) + return mismatches + + @cached_property + def shared_locations(self): + """ + A dictionary of shared locations whose keys are in the set 'prefix', + 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. + The corresponding value is the absolute path of that category for + this distribution, and takes into account any paths selected by the + user at installation time (e.g. via command-line arguments). In the + case of the 'namespace' key, this would be a list of absolute paths + for the roots of namespace packages in this distribution. + + The first time this property is accessed, the relevant information is + read from the SHARED file in the .dist-info directory. + """ + result = {} + shared_path = os.path.join(self.path, 'SHARED') + if os.path.isfile(shared_path): + with codecs.open(shared_path, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + key, value = line.split('=', 1) + if key == 'namespace': + result.setdefault(key, []).append(value) + else: + result[key] = value + return result + + def write_shared_locations(self, paths, dry_run=False): + """ + Write shared location information to the SHARED file in .dist-info. + :param paths: A dictionary as described in the documentation for + :meth:`shared_locations`. + :param dry_run: If True, the action is logged but no file is actually + written. + :return: The path of the file written to. + """ + shared_path = os.path.join(self.path, 'SHARED') + logger.info('creating %s', shared_path) + if dry_run: + return None + lines = [] + for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): + path = paths[key] + if os.path.isdir(paths[key]): + lines.append('%s=%s' % (key, path)) + for ns in paths.get('namespace', ()): + lines.append('namespace=%s' % ns) + + with codecs.open(shared_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return shared_path + + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + + def get_distinfo_file(self, path): + """ + Returns a path located under the ``.dist-info`` directory. Returns a + string representing the path. + + :parameter path: a ``'/'``-separated path relative to the + ``.dist-info`` directory or an absolute path; + If *path* is an absolute path and doesn't start + with the ``.dist-info`` directory path, + a :class:`DistlibException` is raised + :type path: str + :rtype: str + """ + # Check if it is an absolute path # XXX use relpath, add tests + if path.find(os.sep) >= 0: + # it's an absolute path? + distinfo_dirname, path = path.split(os.sep)[-2:] + if distinfo_dirname != self.path.split(os.sep)[-1]: + raise DistlibException( + 'dist-info file %r does not belong to the %r %s ' + 'distribution' % (path, self.name, self.version)) + + # The file must be relative + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + + return os.path.join(self.path, path) + + def list_distinfo_files(self): + """ + Iterates over the ``RECORD`` entries and returns paths for each line if + the path is pointing to a file located in the ``.dist-info`` directory + or one of its subdirectories. + + :returns: iterator of paths + """ + base = os.path.dirname(self.path) + for path, checksum, size in self._get_records(): + # XXX add separator or use real relpath algo + if not os.path.isabs(path): + path = os.path.join(base, path) + if path.startswith(self.path): + yield path + + def __eq__(self, other): + return (isinstance(other, InstalledDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +class EggInfoDistribution(BaseInstalledDistribution): + """Created with the *path* of the ``.egg-info`` directory or file provided + to the constructor. It reads the metadata contained in the file itself, or + if the given path happens to be a directory, the metadata is read from the + file ``PKG-INFO`` under that directory.""" + + requested = True # as we have no way of knowing, assume it was + shared_locations = {} + + def __init__(self, path, env=None): + def set_name_and_version(s, n, v): + s.name = n + s.key = n.lower() # for case-insensitive comparisons + s.version = v + + self.path = path + self.dist_path = env + if env and env._cache_enabled and path in env._cache_egg.path: + metadata = env._cache_egg.path[path].metadata + set_name_and_version(self, metadata.name, metadata.version) + else: + metadata = self._get_metadata(path) + + # Need to be set before caching + set_name_and_version(self, metadata.name, metadata.version) + + if env and env._cache_enabled: + env._cache_egg.add(self) + super(EggInfoDistribution, self).__init__(metadata, path, env) + + def _get_metadata(self, path): + requires = None + + def parse_requires_data(data): + """Create a list of dependencies from a requires.txt file. + + *data*: the contents of a setuptools-produced requires.txt file. + """ + reqs = [] + lines = data.splitlines() + for line in lines: + line = line.strip() + if line.startswith('['): + logger.warning('Unexpected line: quitting requirement scan: %r', + line) + break + r = parse_requirement(line) + if not r: + logger.warning('Not recognised as a requirement: %r', line) + continue + if r.extras: + logger.warning('extra requirements in requires.txt are ' + 'not supported') + if not r.constraints: + reqs.append(r.name) + else: + cons = ', '.join('%s%s' % c for c in r.constraints) + reqs.append('%s (%s)' % (r.name, cons)) + return reqs + + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + + tl_path = tl_data = None + if path.endswith('.egg'): + if os.path.isdir(path): + p = os.path.join(path, 'EGG-INFO') + meta_path = os.path.join(p, 'PKG-INFO') + metadata = Metadata(path=meta_path, scheme='legacy') + req_path = os.path.join(p, 'requires.txt') + tl_path = os.path.join(p, 'top_level.txt') + requires = parse_requires_path(req_path) + else: + # FIXME handle the case where zipfile is not available + zipf = zipimport.zipimporter(path) + fileobj = StringIO( + zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) + metadata = Metadata(fileobj=fileobj, scheme='legacy') + try: + data = zipf.get_data('EGG-INFO/requires.txt') + tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') + requires = parse_requires_data(data.decode('utf-8')) + except IOError: + requires = None + elif path.endswith('.egg-info'): + if os.path.isdir(path): + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires_path(req_path) + path = os.path.join(path, 'PKG-INFO') + tl_path = os.path.join(path, 'top_level.txt') + metadata = Metadata(path=path, scheme='legacy') + else: + raise DistlibException('path must end with .egg-info or .egg, ' + 'got %r' % path) + + if requires: + metadata.add_requirements(requires) + # look for top-level modules in top_level.txt, if present + if tl_data is None: + if tl_path is not None and os.path.exists(tl_path): + with open(tl_path, 'rb') as f: + tl_data = f.read().decode('utf-8') + if not tl_data: + tl_data = [] + else: + tl_data = tl_data.splitlines() + self.modules = tl_data + return metadata + + def __repr__(self): + return '' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + for path, _, _ in self.list_installed_files(): + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + return mismatches + + def list_installed_files(self): + """ + Iterates over the ``installed-files.txt`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: a list of (path, hash, size) + """ + + def _md5(path): + f = open(path, 'rb') + try: + content = f.read() + finally: + f.close() + return hashlib.md5(content).hexdigest() + + def _size(path): + return os.stat(path).st_size + + record_path = os.path.join(self.path, 'installed-files.txt') + result = [] + if os.path.exists(record_path): + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + p = os.path.normpath(os.path.join(self.path, line)) + # "./" is present as a marker between installed files + # and installation metadata files + if not os.path.exists(p): + logger.warning('Non-existent file: %s', p) + if p.endswith(('.pyc', '.pyo')): + continue + #otherwise fall through and fail + if not os.path.isdir(p): + result.append((p, _md5(p), _size(p))) + result.append((record_path, None, None)) + return result + + def list_distinfo_files(self, absolute=False): + """ + Iterates over the ``installed-files.txt`` entries and returns paths for + each line if the path is pointing to a file located in the + ``.egg-info`` directory or one of its subdirectories. + + :parameter absolute: If *absolute* is ``True``, each returned path is + transformed into a local absolute path. Otherwise the + raw value from ``installed-files.txt`` is returned. + :type absolute: boolean + :returns: iterator of paths + """ + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + skip = True + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line == './': + skip = False + continue + if not skip: + p = os.path.normpath(os.path.join(self.path, line)) + if p.startswith(self.path): + if absolute: + yield p + else: + yield line + + def __eq__(self, other): + return (isinstance(other, EggInfoDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + +new_dist_class = InstalledDistribution +old_dist_class = EggInfoDistribution + + +class DependencyGraph(object): + """ + Represents a dependency graph between distributions. + + The dependency relationships are stored in an ``adjacency_list`` that maps + distributions to a list of ``(other, label)`` tuples where ``other`` + is a distribution and the edge is labeled with ``label`` (i.e. the version + specifier, if such was provided). Also, for more efficient traversal, for + every distribution ``x``, a list of predecessors is kept in + ``reverse_list[x]``. An edge from distribution ``a`` to + distribution ``b`` means that ``a`` depends on ``b``. If any missing + dependencies are found, they are stored in ``missing``, which is a + dictionary that maps distributions to a list of requirements that were not + provided by any other distributions. + """ + + def __init__(self): + self.adjacency_list = {} + self.reverse_list = {} + self.missing = {} + + def add_distribution(self, distribution): + """Add the *distribution* to the graph. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + """ + self.adjacency_list[distribution] = [] + self.reverse_list[distribution] = [] + #self.missing[distribution] = [] + + def add_edge(self, x, y, label=None): + """Add an edge from distribution *x* to distribution *y* with the given + *label*. + + :type x: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type y: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type label: ``str`` or ``None`` + """ + self.adjacency_list[x].append((y, label)) + # multiple edges are allowed, so be careful + if x not in self.reverse_list[y]: + self.reverse_list[y].append(x) + + def add_missing(self, distribution, requirement): + """ + Add a missing *requirement* for the given *distribution*. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + :type requirement: ``str`` + """ + logger.debug('%s missing %r', distribution, requirement) + self.missing.setdefault(distribution, []).append(requirement) + + def _repr_dist(self, dist): + return '%s %s' % (dist.name, dist.version) + + def repr_node(self, dist, level=1): + """Prints only a subgraph""" + output = [self._repr_dist(dist)] + for other, label in self.adjacency_list[dist]: + dist = self._repr_dist(other) + if label is not None: + dist = '%s [%s]' % (dist, label) + output.append(' ' * level + str(dist)) + suboutput = self.repr_node(other, level + 1) + subs = suboutput.split('\n') + output.extend(subs[1:]) + return '\n'.join(output) + + def to_dot(self, f, skip_disconnected=True): + """Writes a DOT output for the graph to the provided file *f*. + + If *skip_disconnected* is set to ``True``, then all distributions + that are not dependent on any other distribution are skipped. + + :type f: has to support ``file``-like operations + :type skip_disconnected: ``bool`` + """ + disconnected = [] + + f.write("digraph dependencies {\n") + for dist, adjs in self.adjacency_list.items(): + if len(adjs) == 0 and not skip_disconnected: + disconnected.append(dist) + for other, label in adjs: + if not label is None: + f.write('"%s" -> "%s" [label="%s"]\n' % + (dist.name, other.name, label)) + else: + f.write('"%s" -> "%s"\n' % (dist.name, other.name)) + if not skip_disconnected and len(disconnected) > 0: + f.write('subgraph disconnected {\n') + f.write('label = "Disconnected"\n') + f.write('bgcolor = red\n') + + for dist in disconnected: + f.write('"%s"' % dist.name) + f.write('\n') + f.write('}\n') + f.write('}\n') + + def topological_sort(self): + """ + Perform a topological sort of the graph. + :return: A tuple, the first element of which is a topologically sorted + list of distributions, and the second element of which is a + list of distributions that cannot be sorted because they have + circular dependencies and so form a cycle. + """ + result = [] + # Make a shallow copy of the adjacency list + alist = {} + for k, v in self.adjacency_list.items(): + alist[k] = v[:] + while True: + # See what we can remove in this run + to_remove = [] + for k, v in list(alist.items())[:]: + if not v: + to_remove.append(k) + del alist[k] + if not to_remove: + # What's left in alist (if anything) is a cycle. + break + # Remove from the adjacency list of others + for k, v in alist.items(): + alist[k] = [(d, r) for d, r in v if d not in to_remove] + logger.debug('Moving to result: %s', + ['%s (%s)' % (d.name, d.version) for d in to_remove]) + result.extend(to_remove) + return result, list(alist.keys()) + + def __repr__(self): + """Representation of the graph""" + output = [] + for dist, adjs in self.adjacency_list.items(): + output.append(self.repr_node(dist)) + return '\n'.join(output) + + +def make_graph(dists, scheme='default'): + """Makes a dependency graph from the given distributions. + + :parameter dists: a list of distributions + :type dists: list of :class:`distutils2.database.InstalledDistribution` and + :class:`distutils2.database.EggInfoDistribution` instances + :rtype: a :class:`DependencyGraph` instance + """ + scheme = get_scheme(scheme) + graph = DependencyGraph() + provided = {} # maps names to lists of (version, dist) tuples + + # first, build the graph and find out what's provided + for dist in dists: + graph.add_distribution(dist) + + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + provided.setdefault(name, []).append((version, dist)) + + # now make the edges + for dist in dists: + requires = (dist.run_requires | dist.meta_requires | + dist.build_requires | dist.dev_requires) + for req in requires: + try: + matcher = scheme.matcher(req) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + matched = False + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + graph.add_edge(dist, provider, req) + matched = True + break + if not matched: + graph.add_missing(dist, req) + return graph + + +def get_dependent_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + dependent on *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + dep = [dist] # dependent distributions + todo = graph.reverse_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop() + dep.append(d) + for succ in graph.reverse_list[d]: + if succ not in dep: + todo.append(succ) + + dep.pop(0) # remove dist from dep, was there to prevent infinite loops + return dep + + +def get_required_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + required by *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + req = [] # required distributions + todo = graph.adjacency_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop()[0] + req.append(d) + for pred in graph.adjacency_list[d]: + if pred not in req: + todo.append(pred) + + return req + + +def make_dist(name, version, **kwargs): + """ + A convenience method for making a dist given just a name and version. + """ + summary = kwargs.pop('summary', 'Placeholder for summary') + md = Metadata(**kwargs) + md.name = name + md.version = version + md.summary = summary or 'Placeholder for summary' + return Distribution(md) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/index.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/index.py new file mode 100644 index 00000000..7a87cdcf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/index.py @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import hashlib +import logging +import os +import shutil +import subprocess +import tempfile +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread + +from . import DistlibException +from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, + urlparse, build_opener, string_types) +from .util import cached_property, zip_dir, ServerProxy + +logger = logging.getLogger(__name__) + +DEFAULT_INDEX = 'https://pypi.org/pypi' +DEFAULT_REALM = 'pypi' + +class PackageIndex(object): + """ + This class represents a package index compatible with PyPI, the Python + Package Index. + """ + + boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' + + def __init__(self, url=None): + """ + Initialise an instance. + + :param url: The URL of the index. If not specified, the URL for PyPI is + used. + """ + self.url = url or DEFAULT_INDEX + self.read_configuration() + scheme, netloc, path, params, query, frag = urlparse(self.url) + if params or query or frag or scheme not in ('http', 'https'): + raise DistlibException('invalid repository: %s' % self.url) + self.password_handler = None + self.ssl_verifier = None + self.gpg = None + self.gpg_home = None + with open(os.devnull, 'w') as sink: + # Use gpg by default rather than gpg2, as gpg2 insists on + # prompting for passwords + for s in ('gpg', 'gpg2'): + try: + rc = subprocess.check_call([s, '--version'], stdout=sink, + stderr=sink) + if rc == 0: + self.gpg = s + break + except OSError: + pass + + def _get_pypirc_command(self): + """ + Get the distutils command for interacting with PyPI configurations. + :return: the command. + """ + from distutils.core import Distribution + from distutils.config import PyPIRCCommand + d = Distribution() + return PyPIRCCommand(d) + + def read_configuration(self): + """ + Read the PyPI access configuration as supported by distutils, getting + PyPI to do the actual work. This populates ``username``, ``password``, + ``realm`` and ``url`` attributes from the configuration. + """ + # get distutils to do the work + c = self._get_pypirc_command() + c.repository = self.url + cfg = c._read_pypirc() + self.username = cfg.get('username') + self.password = cfg.get('password') + self.realm = cfg.get('realm', 'pypi') + self.url = cfg.get('repository', self.url) + + def save_configuration(self): + """ + Save the PyPI access configuration. You must have set ``username`` and + ``password`` attributes before calling this method. + + Again, distutils is used to do the actual work. + """ + self.check_credentials() + # get distutils to do the work + c = self._get_pypirc_command() + c._store_pypirc(self.username, self.password) + + def check_credentials(self): + """ + Check that ``username`` and ``password`` have been set, and raise an + exception if not. + """ + if self.username is None or self.password is None: + raise DistlibException('username and password must be set') + pm = HTTPPasswordMgr() + _, netloc, _, _, _, _ = urlparse(self.url) + pm.add_password(self.realm, netloc, self.username, self.password) + self.password_handler = HTTPBasicAuthHandler(pm) + + def register(self, metadata): + """ + Register a distribution on PyPI, using the provided metadata. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the distribution to be + registered. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + metadata.validate() + d = metadata.todict() + d[':action'] = 'verify' + request = self.encode_request(d.items(), []) + response = self.send_request(request) + d[':action'] = 'submit' + request = self.encode_request(d.items(), []) + return self.send_request(request) + + def _reader(self, name, stream, outbuf): + """ + Thread runner for reading lines of from a subprocess into a buffer. + + :param name: The logical name of the stream (used for logging only). + :param stream: The stream to read from. This will typically a pipe + connected to the output stream of a subprocess. + :param outbuf: The list to append the read lines to. + """ + while True: + s = stream.readline() + if not s: + break + s = s.decode('utf-8').rstrip() + outbuf.append(s) + logger.debug('%s: %s' % (name, s)) + stream.close() + + def get_sign_command(self, filename, signer, sign_password, + keystore=None): + """ + Return a suitable command for signing a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The signing command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + if sign_password is not None: + cmd.extend(['--batch', '--passphrase-fd', '0']) + td = tempfile.mkdtemp() + sf = os.path.join(td, os.path.basename(filename) + '.asc') + cmd.extend(['--detach-sign', '--armor', '--local-user', + signer, '--output', sf, filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd, sf + + def run_command(self, cmd, input_data=None): + """ + Run a command in a child process , passing it any input data specified. + + :param cmd: The command to run. + :param input_data: If specified, this must be a byte string containing + data to be sent to the child process. + :return: A tuple consisting of the subprocess' exit code, a list of + lines read from the subprocess' ``stdout``, and a list of + lines read from the subprocess' ``stderr``. + """ + kwargs = { + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + } + if input_data is not None: + kwargs['stdin'] = subprocess.PIPE + stdout = [] + stderr = [] + p = subprocess.Popen(cmd, **kwargs) + # We don't use communicate() here because we may need to + # get clever with interacting with the command + t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) + t1.start() + t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) + t2.start() + if input_data is not None: + p.stdin.write(input_data) + p.stdin.close() + + p.wait() + t1.join() + t2.join() + return p.returncode, stdout, stderr + + def sign_file(self, filename, signer, sign_password, keystore=None): + """ + Sign a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The absolute pathname of the file where the signature is + stored. + """ + cmd, sig_file = self.get_sign_command(filename, signer, sign_password, + keystore) + rc, stdout, stderr = self.run_command(cmd, + sign_password.encode('utf-8')) + if rc != 0: + raise DistlibException('sign command failed with error ' + 'code %s' % rc) + return sig_file + + def upload_file(self, metadata, filename, signer=None, sign_password=None, + filetype='sdist', pyversion='source', keystore=None): + """ + Upload a release file to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the file to be uploaded. + :param filename: The pathname of the file to be uploaded. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param filetype: The type of the file being uploaded. This is the + distutils command which produced that file, e.g. + ``sdist`` or ``bdist_wheel``. + :param pyversion: The version of Python which the release relates + to. For code compatible with any Python, this would + be ``source``, otherwise it would be e.g. ``3.2``. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.exists(filename): + raise DistlibException('not found: %s' % filename) + metadata.validate() + d = metadata.todict() + sig_file = None + if signer: + if not self.gpg: + logger.warning('no signing program available - not signed') + else: + sig_file = self.sign_file(filename, signer, sign_password, + keystore) + with open(filename, 'rb') as f: + file_data = f.read() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() + d.update({ + ':action': 'file_upload', + 'protocol_version': '1', + 'filetype': filetype, + 'pyversion': pyversion, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, + }) + files = [('content', os.path.basename(filename), file_data)] + if sig_file: + with open(sig_file, 'rb') as f: + sig_data = f.read() + files.append(('gpg_signature', os.path.basename(sig_file), + sig_data)) + shutil.rmtree(os.path.dirname(sig_file)) + request = self.encode_request(d.items(), files) + return self.send_request(request) + + def upload_documentation(self, metadata, doc_dir): + """ + Upload documentation to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the documentation to be + uploaded. + :param doc_dir: The pathname of the directory which contains the + documentation. This should be the directory that + contains the ``index.html`` for the documentation. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.isdir(doc_dir): + raise DistlibException('not a directory: %r' % doc_dir) + fn = os.path.join(doc_dir, 'index.html') + if not os.path.exists(fn): + raise DistlibException('not found: %r' % fn) + metadata.validate() + name, version = metadata.name, metadata.version + zip_data = zip_dir(doc_dir).getvalue() + fields = [(':action', 'doc_upload'), + ('name', name), ('version', version)] + files = [('content', name, zip_data)] + request = self.encode_request(fields, files) + return self.send_request(request) + + def get_verify_command(self, signature_filename, data_filename, + keystore=None): + """ + Return a suitable command for verifying a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The verifying command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + cmd.extend(['--verify', signature_filename, data_filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd + + def verify_signature(self, signature_filename, data_filename, + keystore=None): + """ + Verify a signature for a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: True if the signature was verified, else False. + """ + if not self.gpg: + raise DistlibException('verification unavailable because gpg ' + 'unavailable') + cmd = self.get_verify_command(signature_filename, data_filename, + keystore) + rc, stdout, stderr = self.run_command(cmd) + if rc not in (0, 1): + raise DistlibException('verify command failed with error ' + 'code %s' % rc) + return rc == 0 + + def download_file(self, url, destfile, digest=None, reporthook=None): + """ + This is a convenience method for downloading a file from an URL. + Normally, this will be a file from the index, though currently + no check is made for this (i.e. a file can be downloaded from + anywhere). + + The method is just like the :func:`urlretrieve` function in the + standard library, except that it allows digest computation to be + done during download and checking that the downloaded data + matched any expected value. + + :param url: The URL of the file to be downloaded (assumed to be + available via an HTTP GET request). + :param destfile: The pathname where the downloaded file is to be + saved. + :param digest: If specified, this must be a (hasher, value) + tuple, where hasher is the algorithm used (e.g. + ``'md5'``) and ``value`` is the expected value. + :param reporthook: The same as for :func:`urlretrieve` in the + standard library. + """ + if digest is None: + digester = None + logger.debug('No digest specified') + else: + if isinstance(digest, (list, tuple)): + hasher, digest = digest + else: + hasher = 'md5' + digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) + # The following code is equivalent to urlretrieve. + # We need to do it this way so that we can compute the + # digest of the file as we go. + with open(destfile, 'wb') as dfp: + # addinfourl is not a context manager on 2.x + # so we have to use try/finally + sfp = self.send_request(Request(url)) + try: + headers = sfp.info() + blocksize = 8192 + size = -1 + read = 0 + blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) + if reporthook: + reporthook(blocknum, blocksize, size) + while True: + block = sfp.read(blocksize) + if not block: + break + read += len(block) + dfp.write(block) + if digester: + digester.update(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, blocksize, size) + finally: + sfp.close() + + # check that we got the whole file, if we can + if size >= 0 and read < size: + raise DistlibException( + 'retrieval incomplete: got only %d out of %d bytes' + % (read, size)) + # if we have a digest, it must match. + if digester: + actual = digester.hexdigest() + if digest != actual: + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) + + def send_request(self, req): + """ + Send a standard library :class:`Request` to PyPI and return its + response. + + :param req: The request to send. + :return: The HTTP response from PyPI (a standard library HTTPResponse). + """ + handlers = [] + if self.password_handler: + handlers.append(self.password_handler) + if self.ssl_verifier: + handlers.append(self.ssl_verifier) + opener = build_opener(*handlers) + return opener.open(req) + + def encode_request(self, fields, files): + """ + Encode fields and files for posting to an HTTP server. + + :param fields: The fields to send as a list of (fieldname, value) + tuples. + :param files: The files to send as a list of (fieldname, filename, + file_bytes) tuple. + """ + # Adapted from packaging, which in turn was adapted from + # http://code.activestate.com/recipes/146306 + + parts = [] + boundary = self.boundary + for k, values in fields: + if not isinstance(values, (list, tuple)): + values = [values] + + for v in values: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"' % + k).encode('utf-8'), + b'', + v.encode('utf-8'))) + for key, filename, value in files: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)).encode('utf-8'), + b'', + value)) + + parts.extend((b'--' + boundary + b'--', b'')) + + body = b'\r\n'.join(parts) + ct = b'multipart/form-data; boundary=' + boundary + headers = { + 'Content-type': ct, + 'Content-length': str(len(body)) + } + return Request(self.url, body, headers) + + def search(self, terms, operator=None): + if isinstance(terms, string_types): + terms = {'name': terms} + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/locators.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/locators.py new file mode 100644 index 00000000..12a1d063 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/locators.py @@ -0,0 +1,1302 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# + +import gzip +from io import BytesIO +import json +import logging +import os +import posixpath +import re +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import zlib + +from . import DistlibException +from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, + queue, quote, unescape, string_types, build_opener, + HTTPRedirectHandler as BaseRedirectHandler, text_type, + Request, HTTPError, URLError) +from .database import Distribution, DistributionPath, make_dist +from .metadata import Metadata, MetadataInvalidError +from .util import (cached_property, parse_credentials, ensure_slash, + split_filename, get_project_data, parse_requirement, + parse_name_and_version, ServerProxy, normalize_name) +from .version import get_scheme, UnsupportedVersionError +from .wheel import Wheel, is_compatible + +logger = logging.getLogger(__name__) + +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') +CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) +HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') +DEFAULT_INDEX = 'https://pypi.org/pypi' + +def get_all_distribution_names(url=None): + """ + Return all distribution names known by an index. + :param url: The URL of the index. + :return: A list of all known distribution names. + """ + if url is None: + url = DEFAULT_INDEX + client = ServerProxy(url, timeout=3.0) + try: + return client.list_packages() + finally: + client('close')() + +class RedirectHandler(BaseRedirectHandler): + """ + A class to work around a bug in some Python 3.2.x releases. + """ + # There's a bug in the base version for some 3.2.x + # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header + # returns e.g. /abc, it bails because it says the scheme '' + # is bogus, when actually it should use the request's + # URL for the scheme. See Python issue #13696. + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + newurl = None + for key in ('location', 'uri'): + if key in headers: + newurl = headers[key] + break + if newurl is None: # pragma: no cover + return + urlparts = urlparse(newurl) + if urlparts.scheme == '': + newurl = urljoin(req.get_full_url(), newurl) + if hasattr(headers, 'replace_header'): + headers.replace_header(key, newurl) + else: + headers[key] = newurl + return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, + headers) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + +class Locator(object): + """ + A base class for locators - things that locate distributions. + """ + source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') + binary_extensions = ('.egg', '.exe', '.whl') + excluded_extensions = ('.pdf',) + + # A list of tags indicating which wheels you want to match. The default + # value of None matches against the tags compatible with the running + # Python. If you want to match other values, set wheel_tags on a locator + # instance to a list of tuples (pyver, abi, arch) which you want to match. + wheel_tags = None + + downloadable_extensions = source_extensions + ('.whl',) + + def __init__(self, scheme='default'): + """ + Initialise an instance. + :param scheme: Because locators look for most recent versions, they + need to know the version scheme to use. This specifies + the current PEP-recommended scheme - use ``'legacy'`` + if you need to support existing distributions on PyPI. + """ + self._cache = {} + self.scheme = scheme + # Because of bugs in some of the handlers on some of the platforms, + # we use our own opener rather than just using urlopen. + self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None + self.errors = queue.Queue() + + def get_errors(self): + """ + Return any errors which have occurred. + """ + result = [] + while not self.errors.empty(): # pragma: no cover + try: + e = self.errors.get(False) + result.append(e) + except self.errors.Empty: + continue + self.errors.task_done() + return result + + def clear_errors(self): + """ + Clear any errors which may have been logged. + """ + # Just get the errors and throw them away + self.get_errors() + + def clear_cache(self): + self._cache.clear() + + def _get_scheme(self): + return self._scheme + + def _set_scheme(self, value): + self._scheme = value + + scheme = property(_get_scheme, _set_scheme) + + def _get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This calls _get_project to do all the work, and just implements a caching layer on top. + """ + if self._cache is None: # pragma: no cover + result = self._get_project(name) + elif name in self._cache: + result = self._cache[name] + else: + self.clear_errors() + result = self._get_project(name) + self._cache[name] = result + return result + + def score_url(self, url): + """ + Give an url a score which can be used to choose preferred URLs + for a given project release. + """ + t = urlparse(url) + basename = posixpath.basename(t.path) + compatible = True + is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) + if is_wheel: + compatible = is_compatible(Wheel(basename), self.wheel_tags) + return (t.scheme == 'https', 'pypi.org' in t.netloc, + is_downloadable, is_wheel, compatible, basename) + + def prefer_url(self, url1, url2): + """ + Choose one of two URLs where both are candidates for distribution + archives for the same version of a distribution (for example, + .tar.gz vs. zip). + + The current implementation favours https:// URLs over http://, archives + from PyPI over those from other locations, wheel compatibility (if a + wheel) and then the archive name. + """ + result = url2 + if url1: + s1 = self.score_url(url1) + s2 = self.score_url(url2) + if s1 > s2: + result = url1 + if result != url2: + logger.debug('Not replacing %r with %r', url1, url2) + else: + logger.debug('Replacing %r with %r', url1, url2) + return result + + def split_filename(self, filename, project_name): + """ + Attempt to split a filename in project name, version and Python version. + """ + return split_filename(filename, project_name) + + def convert_url_to_download_info(self, url, project_name): + """ + See if a URL is a candidate for a download URL for a project (the URL + has typically been scraped from an HTML page). + + If it is, a dictionary is returned with keys "name", "version", + "filename" and "url"; otherwise, None is returned. + """ + def same_project(name1, name2): + return normalize_name(name1) == normalize_name(name2) + + result = None + scheme, netloc, path, params, query, frag = urlparse(url) + if frag.lower().startswith('egg='): # pragma: no cover + logger.debug('%s: version hint in fragment: %r', + project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None + origpath = path + if path and path[-1] == '/': # pragma: no cover + path = path[:-1] + if path.endswith('.whl'): + try: + wheel = Wheel(path) + if not is_compatible(wheel, self.wheel_tags): + logger.debug('Wheel not compatible: %s', path) + else: + if project_name is None: + include = True + else: + include = same_project(wheel.name, project_name) + if include: + result = { + 'name': wheel.name, + 'version': wheel.version, + 'filename': wheel.filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + 'python-version': ', '.join( + ['.'.join(list(v[2:])) for v in wheel.pyver]), + } + except Exception as e: # pragma: no cover + logger.warning('invalid path for wheel: %s', path) + elif not path.endswith(self.downloadable_extensions): # pragma: no cover + logger.debug('Not downloadable: %s', path) + else: # downloadable extension + path = filename = posixpath.basename(path) + for ext in self.downloadable_extensions: + if path.endswith(ext): + path = path[:-len(ext)] + t = self.split_filename(path, project_name) + if not t: # pragma: no cover + logger.debug('No match for project/version: %s', path) + else: + name, version, pyver = t + if not project_name or same_project(project_name, name): + result = { + 'name': name, + 'version': version, + 'filename': filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + #'packagetype': 'sdist', + } + if pyver: # pragma: no cover + result['python-version'] = pyver + break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at a "digests" dictionary + or keys of the form 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + if 'digests' in info: + digests = info['digests'] + for algo in ('sha256', 'md5'): + if algo in digests: + result = (algo, digests[algo]) + break + if not result: + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break + return result + + def _update_version_data(self, result, info): + """ + Update a result dictionary (the final result from _get_project) with a + dictionary for a specific version, which typically holds information + gleaned from a filename or URL for an archive for the distribution. + """ + name = info.pop('name') + version = info.pop('version') + if version in result: + dist = result[version] + md = dist.metadata + else: + dist = make_dist(name, version, scheme=self.scheme) + md = dist.metadata + dist.digest = digest = self._get_digest(info) + url = info['url'] + result['digests'][url] = digest + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, url) + result['urls'].setdefault(version, set()).add(url) + dist.locator = self + result[version] = dist + + def locate(self, requirement, prereleases=False): + """ + Find the most recent distribution which matches the given + requirement. + + :param requirement: A requirement of the form 'foo (1.0)' or perhaps + 'foo (>= 1.0, < 2.0, != 1.3)' + :param prereleases: If ``True``, allow pre-release versions + to be located. Otherwise, pre-release versions + are not returned. + :return: A :class:`Distribution` instance, or ``None`` if no such + distribution could be located. + """ + result = None + r = parse_requirement(requirement) + if r is None: # pragma: no cover + raise DistlibException('Not a valid requirement: %r' % requirement) + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) + logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) + versions = self.get_project(r.name) + if len(versions) > 2: # urls and digests keys are present + # sometimes, versions are invalid + slist = [] + vcls = matcher.version_class + for k in versions: + if k in ('urls', 'digests'): + continue + try: + if not matcher.match(k): + logger.debug('%s did not match %r', matcher, k) + else: + if prereleases or not vcls(k).is_prerelease: + slist.append(k) + else: + logger.debug('skipping pre-release ' + 'version %s of %s', k, matcher.name) + except Exception: # pragma: no cover + logger.warning('error matching %s with %r', matcher, k) + pass # slist.append(k) + if len(slist) > 1: + slist = sorted(slist, key=scheme.key) + if slist: + logger.debug('sorted list: %s', slist) + version = slist[-1] + result = versions[version] + if result: + if r.extras: + result.extras = r.extras + result.download_urls = versions.get('urls', {}).get(version, set()) + d = {} + sd = versions.get('digests', {}) + for url in result.download_urls: + if url in sd: # pragma: no cover + d[url] = sd[url] + result.digests = d + self.matcher = None + return result + + +class PyPIRPCLocator(Locator): + """ + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). + """ + def __init__(self, url, **kwargs): + """ + Initialise an instance. + + :param url: The URL to use for XML-RPC. + :param kwargs: Passed to the superclass constructor. + """ + super(PyPIRPCLocator, self).__init__(**kwargs) + self.base_url = url + self.client = ServerProxy(url, timeout=3.0) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + return set(self.client.list_packages()) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + versions = self.client.package_releases(name, True) + for v in versions: + urls = self.client.release_urls(name, v) + data = self.client.release_data(name, v) + metadata = Metadata(scheme=self.scheme) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') + dist = Distribution(metadata) + if urls: + info = urls[0] + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) + dist.locator = self + result[v] = dist + for info in urls: + url = info['url'] + digest = self._get_digest(info) + result['urls'].setdefault(v, set()).add(url) + result['digests'][url] = digest + return result + +class PyPIJSONLocator(Locator): + """ + This locator uses PyPI's JSON interface. It's very limited in functionality + and probably not worth using. + """ + def __init__(self, url, **kwargs): + super(PyPIJSONLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + url = urljoin(self.base_url, '%s/json' % quote(name)) + try: + resp = self.opener.open(url) + data = resp.read().decode() # for now + d = json.loads(data) + md = Metadata(scheme=self.scheme) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') + dist = Distribution(md) + dist.locator = self + urls = d['urls'] + result[md.version] = dist + for info in d['urls']: + url = info['url'] + dist.download_urls.add(url) + dist.digests[url] = self._get_digest(info) + result['urls'].setdefault(md.version, set()).add(url) + result['digests'][url] = self._get_digest(info) + # Now get other releases + for version, infos in d['releases'].items(): + if version == md.version: + continue # already done + omd = Metadata(scheme=self.scheme) + omd.name = md.name + omd.version = version + odist = Distribution(omd) + odist.locator = self + result[version] = odist + for info in infos: + url = info['url'] + odist.download_urls.add(url) + odist.digests[url] = self._get_digest(info) + result['urls'].setdefault(version, set()).add(url) + result['digests'][url] = self._get_digest(info) +# for info in urls: +# md.source_url = info['url'] +# dist.digest = self._get_digest(info) +# dist.locator = self +# for info in urls: +# url = info['url'] +# result['urls'].setdefault(md.version, set()).add(url) +# result['digests'][url] = self._get_digest(info) + except Exception as e: + self.errors.put(text_type(e)) + logger.exception('JSON fetch failed: %s', e) + return result + + +class Page(object): + """ + This class represents a scraped HTML page. + """ + # The following slightly hairy-looking regex just looks for the contents of + # an anchor link, which has an attribute "href" either immediately preceded + # or immediately followed by a "rel" attribute. The attribute values can be + # declared with double quotes, single quotes or no quotes - which leads to + # the length of the expression. + _href = re.compile(""" +(rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))? +""", re.I | re.S | re.X) + _base = re.compile(r"""]+)""", re.I | re.S) + + def __init__(self, data, url): + """ + Initialise an instance with the Unicode page contents and the URL they + came from. + """ + self.data = data + self.base_url = self.url = url + m = self._base.search(self.data) + if m: + self.base_url = m.group(1) + + _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + @cached_property + def links(self): + """ + Return the URLs of all the links on a page together with information + about their "rel" attribute, for determining which ones to treat as + downloads and which ones to queue for further scraping. + """ + def clean(url): + "Tidy up an URL." + scheme, netloc, path, params, query, frag = urlparse(url) + return urlunparse((scheme, netloc, quote(path), + params, query, frag)) + + result = set() + for match in self._href.finditer(self.data): + d = match.groupdict('') + rel = (d['rel1'] or d['rel2'] or d['rel3'] or + d['rel4'] or d['rel5'] or d['rel6']) + url = d['url1'] or d['url2'] or d['url3'] + url = urljoin(self.base_url, url) + url = unescape(url) + url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) + result.add((url, rel)) + # We sort the result, hoping to bring the most recent versions + # to the front + result = sorted(result, key=lambda t: t[0], reverse=True) + return result + + +class SimpleScrapingLocator(Locator): + """ + A locator which scrapes HTML pages to locate downloads for a distribution. + This runs multiple threads to do the I/O; performance is at least as good + as pip's PackageFinder, which works in an analogous fashion. + """ + + # These are used to deal with various Content-Encoding schemes. + decoders = { + 'deflate': zlib.decompress, + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), + 'none': lambda b: b, + } + + def __init__(self, url, timeout=None, num_workers=10, **kwargs): + """ + Initialise an instance. + :param url: The root URL to use for scraping. + :param timeout: The timeout, in seconds, to be applied to requests. + This defaults to ``None`` (no timeout specified). + :param num_workers: The number of worker threads you want to do I/O, + This defaults to 10. + :param kwargs: Passed to the superclass. + """ + super(SimpleScrapingLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + self.timeout = timeout + self._page_cache = {} + self._seen = set() + self._to_fetch = queue.Queue() + self._bad_hosts = set() + self.skip_externals = False + self.num_workers = num_workers + self._lock = threading.RLock() + # See issue #45: we need to be resilient when the locator is used + # in a thread, e.g. with concurrent.futures. We can't use self._lock + # as it is for coordinating our internal threads - the ones created + # in _prepare_threads. + self._gplock = threading.RLock() + self.platform_check = False # See issue #112 + + def _prepare_threads(self): + """ + Threads are created only when get_project is called, and terminate + before it returns. They are there primarily to parallelise I/O (i.e. + fetching web pages). + """ + self._threads = [] + for i in range(self.num_workers): + t = threading.Thread(target=self._fetch) + t.setDaemon(True) + t.start() + self._threads.append(t) + + def _wait_threads(self): + """ + Tell all the threads to terminate (by sending a sentinel value) and + wait for them to do so. + """ + # Note that you need two loops, since you can't say which + # thread will get each sentinel + for t in self._threads: + self._to_fetch.put(None) # sentinel + for t in self._threads: + t.join() + self._threads = [] + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + with self._gplock: + self.result = result + self.project_name = name + url = urljoin(self.base_url, '%s/' % quote(name)) + self._seen.clear() + self._page_cache.clear() + self._prepare_threads() + try: + logger.debug('Queueing %s', url) + self._to_fetch.put(url) + self._to_fetch.join() + finally: + self._wait_threads() + del self.result + return result + + platform_dependent = re.compile(r'\b(linux_(i\d86|x86_64|arm\w+)|' + r'win(32|_amd64)|macosx_?\d+)\b', re.I) + + def _is_platform_dependent(self, url): + """ + Does an URL refer to a platform-specific download? + """ + return self.platform_dependent.search(url) + + def _process_download(self, url): + """ + See if an URL is a suitable download for a project. + + If it is, register information in the result dictionary (for + _get_project) about the specific version it's for. + + Note that the return value isn't actually used other than as a boolean + value. + """ + if self.platform_check and self._is_platform_dependent(url): + info = None + else: + info = self.convert_url_to_download_info(url, self.project_name) + logger.debug('process_download: %s -> %s', url, info) + if info: + with self._lock: # needed because self.result is shared + self._update_version_data(self.result, info) + return info + + def _should_queue(self, link, referrer, rel): + """ + Determine whether a link URL from a referring page and with a + particular "rel" attribute should be queued for scraping. + """ + scheme, netloc, path, _, _, _ = urlparse(link) + if path.endswith(self.source_extensions + self.binary_extensions + + self.excluded_extensions): + result = False + elif self.skip_externals and not link.startswith(self.base_url): + result = False + elif not referrer.startswith(self.base_url): + result = False + elif rel not in ('homepage', 'download'): + result = False + elif scheme not in ('http', 'https', 'ftp'): + result = False + elif self._is_platform_dependent(link): + result = False + else: + host = netloc.split(':', 1)[0] + if host.lower() == 'localhost': + result = False + else: + result = True + logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, + referrer, result) + return result + + def _fetch(self): + """ + Get a URL to fetch from the work queue, get the HTML page, examine its + links for download candidates and candidates for further scraping. + + This is a handy method to run in a thread. + """ + while True: + url = self._to_fetch.get() + try: + if url: + page = self.get_page(url) + if page is None: # e.g. after an error + continue + for link, rel in page.links: + if link not in self._seen: + try: + self._seen.add(link) + if (not self._process_download(link) and + self._should_queue(link, url, rel)): + logger.debug('Queueing %s from %s', link, url) + self._to_fetch.put(link) + except MetadataInvalidError: # e.g. invalid versions + pass + except Exception as e: # pragma: no cover + self.errors.put(text_type(e)) + finally: + # always do this, to avoid hangs :-) + self._to_fetch.task_done() + if not url: + #logger.debug('Sentinel seen, quitting.') + break + + def get_page(self, url): + """ + Get the HTML for an URL, possibly from an in-memory cache. + + XXX TODO Note: this cache is never actually cleared. It's assumed that + the data won't get stale over the lifetime of a locator instance (not + necessarily true for the default_locator). + """ + # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api + scheme, netloc, path, _, _, _ = urlparse(url) + if scheme == 'file' and os.path.isdir(url2pathname(path)): + url = urljoin(ensure_slash(url), 'index.html') + + if url in self._page_cache: + result = self._page_cache[url] + logger.debug('Returning %s from cache: %s', url, result) + else: + host = netloc.split(':', 1)[0] + result = None + if host in self._bad_hosts: + logger.debug('Skipping %s due to bad host %s', url, host) + else: + req = Request(url, headers={'Accept-encoding': 'identity'}) + try: + logger.debug('Fetching %s', url) + resp = self.opener.open(req, timeout=self.timeout) + logger.debug('Fetched %s', url) + headers = resp.info() + content_type = headers.get('Content-Type', '') + if HTML_CONTENT_TYPE.match(content_type): + final_url = resp.geturl() + data = resp.read() + encoding = headers.get('Content-Encoding') + if encoding: + decoder = self.decoders[encoding] # fail if not found + data = decoder(data) + encoding = 'utf-8' + m = CHARSET.search(content_type) + if m: + encoding = m.group(1) + try: + data = data.decode(encoding) + except UnicodeError: # pragma: no cover + data = data.decode('latin-1') # fallback + result = Page(data, final_url) + self._page_cache[final_url] = result + except HTTPError as e: + if e.code != 404: + logger.exception('Fetch failed: %s: %s', url, e) + except URLError as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + with self._lock: + self._bad_hosts.add(host) + except Exception as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + finally: + self._page_cache[url] = result # even if None (failure) + return result + + _distname_re = re.compile(']*>([^<]+)<') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + page = self.get_page(self.base_url) + if not page: + raise DistlibException('Unable to get %s' % self.base_url) + for match in self._distname_re.finditer(page.data): + result.add(match.group(1)) + return result + +class DirectoryLocator(Locator): + """ + This class locates distributions in a directory tree. + """ + + def __init__(self, path, **kwargs): + """ + Initialise an instance. + :param path: The root of the directory tree to search. + :param kwargs: Passed to the superclass constructor, + except for: + * recursive - if True (the default), subdirectories are + recursed into. If False, only the top-level directory + is searched, + """ + self.recursive = kwargs.pop('recursive', True) + super(DirectoryLocator, self).__init__(**kwargs) + path = os.path.abspath(path) + if not os.path.isdir(path): # pragma: no cover + raise DistlibException('Not a directory: %r' % path) + self.base_dir = path + + def should_include(self, filename, parent): + """ + Should a filename be considered as a candidate for a distribution + archive? As well as the filename, the directory which contains it + is provided, though not used by the current implementation. + """ + return filename.endswith(self.downloadable_extensions) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, name) + if info: + self._update_version_data(result, info) + if not self.recursive: + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, None) + if info: + result.add(info['name']) + if not self.recursive: + break + return result + +class JSONLocator(Locator): + """ + This locator uses special extended metadata (not available on PyPI) and is + the basis of performant dependency resolution in distlib. Other locators + require archive downloads before dependencies can be determined! As you + might imagine, that can be slow. + """ + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + data = get_project_data(name) + if data: + for info in data.get('files', []): + if info['ptype'] != 'sdist' or info['pyversion'] != 'source': + continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution + dist = make_dist(data['name'], info['version'], + summary=data.get('summary', + 'Placeholder for summary'), + scheme=self.scheme) + md = dist.metadata + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) + md.dependencies = info.get('requirements', {}) + dist.exports = info.get('exports', {}) + result[dist.version] = dist + result['urls'].setdefault(dist.version, set()).add(info['url']) + return result + +class DistPathLocator(Locator): + """ + This locator finds installed distributions in a path. It can be useful for + adding to an :class:`AggregatingLocator`. + """ + def __init__(self, distpath, **kwargs): + """ + Initialise an instance. + + :param distpath: A :class:`DistributionPath` instance to search. + """ + super(DistPathLocator, self).__init__(**kwargs) + assert isinstance(distpath, DistributionPath) + self.distpath = distpath + + def _get_project(self, name): + dist = self.distpath.get_distribution(name) + if dist is None: + result = {'urls': {}, 'digests': {}} + else: + result = { + dist.version: dist, + 'urls': {dist.version: set([dist.source_url])}, + 'digests': {dist.version: set([None])} + } + return result + + +class AggregatingLocator(Locator): + """ + This class allows you to chain and/or merge a list of locators. + """ + def __init__(self, *locators, **kwargs): + """ + Initialise an instance. + + :param locators: The list of locators to search. + :param kwargs: Passed to the superclass constructor, + except for: + * merge - if False (the default), the first successful + search from any of the locators is returned. If True, + the results from all locators are merged (this can be + slow). + """ + self.merge = kwargs.pop('merge', False) + self.locators = locators + super(AggregatingLocator, self).__init__(**kwargs) + + def clear_cache(self): + super(AggregatingLocator, self).clear_cache() + for locator in self.locators: + locator.clear_cache() + + def _set_scheme(self, value): + self._scheme = value + for locator in self.locators: + locator.scheme = value + + scheme = property(Locator.scheme.fget, _set_scheme) + + def _get_project(self, name): + result = {} + for locator in self.locators: + d = locator.get_project(name) + if d: + if self.merge: + files = result.get('urls', {}) + digests = result.get('digests', {}) + # next line could overwrite result['urls'], result['digests'] + result.update(d) + df = result.get('urls') + if files and df: + for k, v in files.items(): + if k in df: + df[k] |= v + else: + df[k] = v + dd = result.get('digests') + if digests and dd: + dd.update(digests) + else: + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for locator in self.locators: + try: + result |= locator.get_distribution_names() + except NotImplementedError: + pass + return result + + +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 426 / PEP 440. +default_locator = AggregatingLocator( + JSONLocator(), + SimpleScrapingLocator('https://pypi.org/simple/', + timeout=3.0), + scheme='legacy') + +locate = default_locator.locate + +NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*' + r'\(\s*(==\s*)?(?P[^)]+)\)$') + +class DependencyFinder(object): + """ + Locate dependencies for distributions. + """ + + def __init__(self, locator=None): + """ + Initialise an instance, using the specified locator + to locate distributions. + """ + self.locator = locator or default_locator + self.scheme = get_scheme(self.locator.scheme) + + def add_distribution(self, dist): + """ + Add a distribution to the finder. This will update internal information + about who provides what. + :param dist: The distribution to add. + """ + logger.debug('adding distribution %s', dist) + name = dist.key + self.dists_by_name[name] = dist + self.dists[(name, dist.version)] = dist + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + self.provided.setdefault(name, set()).add((version, dist)) + + def remove_distribution(self, dist): + """ + Remove a distribution from the finder. This will update internal + information about who provides what. + :param dist: The distribution to remove. + """ + logger.debug('removing distribution %s', dist) + name = dist.key + del self.dists_by_name[name] + del self.dists[(name, dist.version)] + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Remove from provided: %s, %s, %s', name, version, dist) + s = self.provided[name] + s.remove((version, dist)) + if not s: + del self.provided[name] + + def get_matcher(self, reqt): + """ + Get a version matcher for a requirement. + :param reqt: The requirement + :type reqt: str + :return: A version matcher (an instance of + :class:`distlib.version.Matcher`). + """ + try: + matcher = self.scheme.matcher(reqt) + except UnsupportedVersionError: # pragma: no cover + # XXX compat-mode if cannot read the version + name = reqt.split()[0] + matcher = self.scheme.matcher(name) + return matcher + + def find_providers(self, reqt): + """ + Find the distributions which can fulfill a requirement. + + :param reqt: The requirement. + :type reqt: str + :return: A set of distribution which can fulfill the requirement. + """ + matcher = self.get_matcher(reqt) + name = matcher.key # case-insensitive + result = set() + provided = self.provided + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + result.add(provider) + break + return result + + def try_to_replace(self, provider, other, problems): + """ + Attempt to replace one provider with another. This is typically used + when resolving dependencies from multiple sources, e.g. A requires + (B >= 1.0) while C requires (B >= 1.1). + + For successful replacement, ``provider`` must meet all the requirements + which ``other`` fulfills. + + :param provider: The provider we are trying to replace with. + :param other: The provider we're trying to replace. + :param problems: If False is returned, this will contain what + problems prevented replacement. This is currently + a tuple of the literal string 'cantreplace', + ``provider``, ``other`` and the set of requirements + that ``provider`` couldn't fulfill. + :return: True if we can replace ``other`` with ``provider``, else + False. + """ + rlist = self.reqts[other] + unmatched = set() + for s in rlist: + matcher = self.get_matcher(s) + if not matcher.match(provider.version): + unmatched.add(s) + if unmatched: + # can't replace other with provider + problems.add(('cantreplace', provider, other, + frozenset(unmatched))) + result = False + else: + # can replace other with provider + self.remove_distribution(other) + del self.reqts[other] + for s in rlist: + self.reqts.setdefault(provider, set()).add(s) + self.add_distribution(provider) + result = True + return result + + def find(self, requirement, meta_extras=None, prereleases=False): + """ + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. + + Return a set of :class:`Distribution` instances and a set of + problems. + + The distributions returned should be such that they have the + :attr:`required` attribute set to ``True`` if they were + from the ``requirement`` passed to ``find()``, and they have the + :attr:`build_time_dependency` attribute set to ``True`` unless they + are post-installation dependencies of the ``requirement``. + + The problems should be a tuple consisting of the string + ``'unsatisfied'`` and the requirement which couldn't be satisfied + by any distribution known to the locator. + """ + + self.provided = {} + self.dists = {} + self.dists_by_name = {} + self.reqts = {} + + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + + if isinstance(requirement, Distribution): + dist = odist = requirement + logger.debug('passed %s as requirement', odist) + else: + dist = odist = self.locator.locate(requirement, + prereleases=prereleases) + if dist is None: + raise DistlibException('Unable to locate %r' % requirement) + logger.debug('located %s', odist) + dist.requested = True + problems = set() + todo = set([dist]) + install_dists = set([odist]) + while todo: + dist = todo.pop() + name = dist.key # case-insensitive + if name not in self.dists_by_name: + self.add_distribution(dist) + else: + #import pdb; pdb.set_trace() + other = self.dists_by_name[name] + if other != dist: + self.try_to_replace(dist, other, problems) + + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires + ereqts = set() + if meta_extras and dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts + for r in all_reqts: + providers = self.find_providers(r) + if not providers: + logger.debug('No providers found for %r', r) + provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) + if provider is None: + logger.debug('Cannot satisfy %r', r) + problems.add(('unsatisfied', r)) + else: + n, v = provider.key, provider.version + if (n, v) not in self.dists: + todo.add(provider) + providers.add(provider) + if r in ireqts and dist in install_dists: + install_dists.add(provider) + logger.debug('Adding %s to install_dists', + provider.name_and_version) + for p in providers: + name = p.key + if name not in self.dists_by_name: + self.reqts.setdefault(p, set()).add(r) + else: + other = self.dists_by_name[name] + if other != p: + # see if other can be replaced by p + self.try_to_replace(p, other, problems) + + dists = set(self.dists.values()) + for dist in dists: + dist.build_time_dependency = dist not in install_dists + if dist.build_time_dependency: + logger.debug('%s is a build-time dependency only.', + dist.name_and_version) + logger.debug('find done for %s', odist) + return dists, problems diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/manifest.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/manifest.py new file mode 100644 index 00000000..ca0fe442 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/manifest.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Class representing the list of files in a distribution. + +Equivalent to distutils.filelist, but fixes some problems. +""" +import fnmatch +import logging +import os +import re +import sys + +from . import DistlibException +from .compat import fsdecode +from .util import convert_path + + +__all__ = ['Manifest'] + +logger = logging.getLogger(__name__) + +# a \ followed by some spaces + EOL +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) +_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) + +# +# Due to the different results returned by fnmatch.translate, we need +# to do slightly different processing for Python 2.7 and 3.2 ... this needed +# to be brought in for Python 3.6 onwards. +# +_PYTHON_VERSION = sys.version_info[:2] + +class Manifest(object): + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + """ + + def __init__(self, base=None): + """ + Initialise an instance. + + :param base: The base directory to explore under. + """ + self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) + self.prefix = self.base + os.sep + self.allfiles = None + self.files = set() + + # + # Public API + # + + def findall(self): + """Find all files under the base and set ``allfiles`` to the absolute + pathnames of files found. + """ + from stat import S_ISREG, S_ISDIR, S_ISLNK + + self.allfiles = allfiles = [] + root = self.base + stack = [root] + pop = stack.pop + push = stack.append + + while stack: + root = pop() + names = os.listdir(root) + + for name in names: + fullname = os.path.join(root, name) + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat.st_mode + if S_ISREG(mode): + allfiles.append(fsdecode(fullname)) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + def add(self, item): + """ + Add a file to the manifest. + + :param item: The pathname to add. This can be relative to the base. + """ + if not item.startswith(self.prefix): + item = os.path.join(self.base, item) + self.files.add(os.path.normpath(item)) + + def add_many(self, items): + """ + Add a list of files to the manifest. + + :param items: The pathnames to add. These can be relative to the base. + """ + for item in items: + self.add(item) + + def sorted(self, wantdirs=False): + """ + Return sorted files in directory order + """ + + def add_dir(dirs, d): + dirs.add(d) + logger.debug('add_dir added %s', d) + if d != self.base: + parent, _ = os.path.split(d) + assert parent not in ('', '/') + add_dir(dirs, parent) + + result = set(self.files) # make a copy! + if wantdirs: + dirs = set() + for f in result: + add_dir(dirs, os.path.dirname(f)) + result |= dirs + return [os.path.join(*path_tuple) for path_tuple in + sorted(os.path.split(path) for path in result)] + + def clear(self): + """Clear all collected files.""" + self.files = set() + self.allfiles = [] + + def process_directive(self, directive): + """ + Process a directive which either adds some files from ``allfiles`` to + ``files``, or removes some files from ``files``. + + :param directive: The directive to process. This should be in a format + compatible with distutils ``MANIFEST.in`` files: + + http://docs.python.org/distutils/sourcedist.html#commands + """ + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dirpattern). + action, patterns, thedir, dirpattern = self._parse_directive(directive) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=True): + logger.warning('no files found matching %r', pattern) + + elif action == 'exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=True) + #if not found: + # logger.warning('no previously-included files ' + # 'found matching %r', pattern) + + elif action == 'global-include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=False): + logger.warning('no files found matching %r ' + 'anywhere in distribution', pattern) + + elif action == 'global-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=False) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found anywhere in ' + # 'distribution', pattern) + + elif action == 'recursive-include': + for pattern in patterns: + if not self._include_pattern(pattern, prefix=thedir): + logger.warning('no files found matching %r ' + 'under directory %r', pattern, thedir) + + elif action == 'recursive-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, prefix=thedir) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found under directory %r', + # pattern, thedir) + + elif action == 'graft': + if not self._include_pattern(None, prefix=dirpattern): + logger.warning('no directories found matching %r', + dirpattern) + + elif action == 'prune': + if not self._exclude_pattern(None, prefix=dirpattern): + logger.warning('no previously-included directories found ' + 'matching %r', dirpattern) + else: # pragma: no cover + # This should never happen, as it should be caught in + # _parse_template_line + raise DistlibException( + 'invalid action %r' % action) + + # + # Private API + # + + def _parse_directive(self, directive): + """ + Validate a directive. + :param directive: The directive to validate. + :return: A tuple of action, patterns, thedir, dir_patterns + """ + words = directive.split() + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): + # no action given, let's use the default 'include' + words.insert(0, 'include') + + action = words[0] + patterns = thedir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistlibException( + '%r expects ...' % action) + + patterns = [convert_path(word) for word in words[1:]] + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistlibException( + '%r expects

...' % action) + + thedir = convert_path(words[1]) + patterns = [convert_path(word) for word in words[2:]] + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistlibException( + '%r expects a single ' % action) + + dir_pattern = convert_path(words[1]) + + else: + raise DistlibException('unknown action %r' % action) + + return action, patterns, thedir, dir_pattern + + def _include_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found. + """ + # XXX docstring lying about what the special chars are? + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.files.add(name) + found = True + return found + + def _exclude_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return True if files are + found. + + This API is public to allow e.g. exclusion of SCM subdirs, e.g. when + packaging source distributions + """ + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + for f in list(self.files): + if pattern_re.search(f): + self.files.remove(f) + found = True + return found + + def _translate_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Translate a shell-like wildcard pattern to a compiled regular + expression. + + Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if isinstance(pattern, str): + return re.compile(pattern) + else: + return pattern + + if _PYTHON_VERSION > (3, 2): + # ditch start and end characters + start, _, end = self._glob_to_re('_').partition('_') + + if pattern: + pattern_re = self._glob_to_re(pattern) + if _PYTHON_VERSION > (3, 2): + assert pattern_re.startswith(start) and pattern_re.endswith(end) + else: + pattern_re = '' + + base = re.escape(os.path.join(self.base, '')) + if prefix is not None: + # ditch end of pattern character + if _PYTHON_VERSION <= (3, 2): + empty_pattern = self._glob_to_re('') + prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] + else: + prefix_re = self._glob_to_re(prefix) + assert prefix_re.startswith(start) and prefix_re.endswith(end) + prefix_re = prefix_re[len(start): len(prefix_re) - len(end)] + sep = os.sep + if os.sep == '\\': + sep = r'\\' + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + sep.join((prefix_re, + '.*' + pattern_re)) + else: + pattern_re = pattern_re[len(start): len(pattern_re) - len(end)] + pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep, + pattern_re, end) + else: # no prefix -- respect anchor flag + if anchor: + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + pattern_re + else: + pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):]) + + return re.compile(pattern_re) + + def _glob_to_re(self, pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((? y, + '!=': lambda x, y: x != y, + '<': lambda x, y: x < y, + '<=': lambda x, y: x == y or x < y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x == y or x > y, + 'and': lambda x, y: x and y, + 'or': lambda x, y: x or y, + 'in': lambda x, y: x in y, + 'not in': lambda x, y: x not in y, + } + + def evaluate(self, expr, context): + """ + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. + """ + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] + else: + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] + else: + assert isinstance(expr, dict) + op = expr['op'] + if op not in self.operations: + raise NotImplementedError('op not implemented: %s' % op) + elhs = expr['lhs'] + erhs = expr['rhs'] + if _is_literal(expr['lhs']) and _is_literal(expr['rhs']): + raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs)) + + lhs = self.evaluate(elhs, context) + rhs = self.evaluate(erhs, context) + result = self.operations[op](lhs, rhs) + return result + +def default_context(): + def format_full_version(info): + version = '%s.%s.%s' % (info.major, info.minor, info.micro) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' + + result = { + 'implementation_name': implementation_name, + 'implementation_version': implementation_version, + 'os_name': os.name, + 'platform_machine': platform.machine(), + 'platform_python_implementation': platform.python_implementation(), + 'platform_release': platform.release(), + 'platform_system': platform.system(), + 'platform_version': platform.version(), + 'platform_in_venv': str(in_venv()), + 'python_full_version': platform.python_version(), + 'python_version': platform.python_version()[:3], + 'sys_platform': sys.platform, + } + return result + +DEFAULT_CONTEXT = default_context() +del default_context + +evaluator = Evaluator() + +def interpret(marker, execution_context=None): + """ + Interpret a marker and return a result depending on environment. + + :param marker: The marker to interpret. + :type marker: str + :param execution_context: The context used for name lookup. + :type execution_context: mapping + """ + try: + expr, rest = parse_marker(marker) + except Exception as e: + raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e)) + if rest and rest[0] != '#': + raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest)) + context = dict(DEFAULT_CONTEXT) + if execution_context: + context.update(execution_context) + return evaluator.evaluate(expr, context) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/metadata.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/metadata.py new file mode 100644 index 00000000..2d61378e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/metadata.py @@ -0,0 +1,1096 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Implementation of the Metadata for Python packages PEPs. + +Supports all metadata formats (1.0, 1.1, 1.2, and 2.0 experimental). +""" +from __future__ import unicode_literals + +import codecs +from email import message_from_file +import json +import logging +import re + + +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type +from .markers import interpret +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP440_VERSION_RE + +logger = logging.getLogger(__name__) + + +class MetadataMissingError(DistlibException): + """A required metadata is missing""" + + +class MetadataConflictError(DistlibException): + """Attempt to read or write metadata fields that are conflictual.""" + + +class MetadataUnrecognizedVersionError(DistlibException): + """Unknown metadata version number.""" + + +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" + +# public API of this module +__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# preferred version. Hopefully will be changed +# to 1.2 once PEP 345 is supported everywhere +PKG_INFO_PREFERRED_VERSION = '1.1' + +_LINE_PREFIX_1_2 = re.compile('\n \\|') +_LINE_PREFIX_PRE_1_2 = re.compile('\n ') +_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License') + +_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License', 'Classifier', 'Download-URL', 'Obsoletes', + 'Provides', 'Requires') + +_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', + 'Download-URL') + +_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External') + +_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', + 'Obsoletes-Dist', 'Requires-External', 'Maintainer', + 'Maintainer-email', 'Project-URL') + +_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External', 'Private-Version', + 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', + 'Provides-Extra') + +_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', + 'Setup-Requires-Dist', 'Extension') + +# See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in +# the metadata. Include them in the tuple literal below to allow them +# (for now). +_566_FIELDS = _426_FIELDS + ('Description-Content-Type', + 'Requires', 'Provides') + +_566_MARKERS = ('Description-Content-Type',) + +_ALL_FIELDS = set() +_ALL_FIELDS.update(_241_FIELDS) +_ALL_FIELDS.update(_314_FIELDS) +_ALL_FIELDS.update(_345_FIELDS) +_ALL_FIELDS.update(_426_FIELDS) +_ALL_FIELDS.update(_566_FIELDS) + +EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + + +def _version2fieldlist(version): + if version == '1.0': + return _241_FIELDS + elif version == '1.1': + return _314_FIELDS + elif version == '1.2': + return _345_FIELDS + elif version in ('1.3', '2.1'): + return _345_FIELDS + _566_FIELDS + elif version == '2.0': + return _426_FIELDS + raise MetadataUnrecognizedVersionError(version) + + +def _best_version(fields): + """Detect the best version depending on the fields used.""" + def _has_marker(keys, markers): + for marker in markers: + if marker in keys: + return True + return False + + keys = [] + for key, value in fields.items(): + if value in ([], 'UNKNOWN', None): + continue + keys.append(key) + + possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.0', '2.1'] + + # first let's try to see if a field is not part of one of the version + for key in keys: + if key not in _241_FIELDS and '1.0' in possible_versions: + possible_versions.remove('1.0') + logger.debug('Removed 1.0 due to %s', key) + if key not in _314_FIELDS and '1.1' in possible_versions: + possible_versions.remove('1.1') + logger.debug('Removed 1.1 due to %s', key) + if key not in _345_FIELDS and '1.2' in possible_versions: + possible_versions.remove('1.2') + logger.debug('Removed 1.2 due to %s', key) + if key not in _566_FIELDS and '1.3' in possible_versions: + possible_versions.remove('1.3') + logger.debug('Removed 1.3 due to %s', key) + if key not in _566_FIELDS and '2.1' in possible_versions: + if key != 'Description': # In 2.1, description allowed after headers + possible_versions.remove('2.1') + logger.debug('Removed 2.1 due to %s', key) + if key not in _426_FIELDS and '2.0' in possible_versions: + possible_versions.remove('2.0') + logger.debug('Removed 2.0 due to %s', key) + + # possible_version contains qualified versions + if len(possible_versions) == 1: + return possible_versions[0] # found ! + elif len(possible_versions) == 0: + logger.debug('Out of options - unknown metadata set: %s', fields) + raise MetadataConflictError('Unknown metadata set') + + # let's see if one unique marker is found + is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) + is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) + is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS) + is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) + if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_0) > 1: + raise MetadataConflictError('You used incompatible 1.1/1.2/2.0/2.1 fields') + + # we have the choice, 1.0, or 1.2, or 2.0 + # - 1.0 has a broken Summary field but works with all tools + # - 1.1 is to avoid + # - 1.2 fixes Summary but has little adoption + # - 2.0 adds more features and is very new + if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_0: + # we couldn't find any specific marker + if PKG_INFO_PREFERRED_VERSION in possible_versions: + return PKG_INFO_PREFERRED_VERSION + if is_1_1: + return '1.1' + if is_1_2: + return '1.2' + if is_2_1: + return '2.1' + + return '2.0' + +_ATTR2FIELD = { + 'metadata_version': 'Metadata-Version', + 'name': 'Name', + 'version': 'Version', + 'platform': 'Platform', + 'supported_platform': 'Supported-Platform', + 'summary': 'Summary', + 'description': 'Description', + 'keywords': 'Keywords', + 'home_page': 'Home-page', + 'author': 'Author', + 'author_email': 'Author-email', + 'maintainer': 'Maintainer', + 'maintainer_email': 'Maintainer-email', + 'license': 'License', + 'classifier': 'Classifier', + 'download_url': 'Download-URL', + 'obsoletes_dist': 'Obsoletes-Dist', + 'provides_dist': 'Provides-Dist', + 'requires_dist': 'Requires-Dist', + 'setup_requires_dist': 'Setup-Requires-Dist', + 'requires_python': 'Requires-Python', + 'requires_external': 'Requires-External', + 'requires': 'Requires', + 'provides': 'Provides', + 'obsoletes': 'Obsoletes', + 'project_url': 'Project-URL', + 'private_version': 'Private-Version', + 'obsoleted_by': 'Obsoleted-By', + 'extension': 'Extension', + 'provides_extra': 'Provides-Extra', +} + +_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') +_VERSIONS_FIELDS = ('Requires-Python',) +_VERSION_FIELDS = ('Version',) +_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', + 'Requires', 'Provides', 'Obsoletes-Dist', + 'Provides-Dist', 'Requires-Dist', 'Requires-External', + 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', + 'Provides-Extra', 'Extension') +_LISTTUPLEFIELDS = ('Project-URL',) + +_ELEMENTSFIELD = ('Keywords',) + +_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') + +_MISSING = object() + +_FILESAFE = re.compile('[^A-Za-z0-9.]+') + + +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. + + Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can + instantiate the class with one of these arguments (or none): + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content + - *mapping* is a dict-like object + - *scheme* is a version scheme name + """ + # TODO document the mapping API and UNKNOWN default key + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme + if path is not None: + self.read(path) + elif fileobj is not None: + self.read_file(fileobj) + elif mapping is not None: + self.update(mapping) + self.set_metadata_version() + + def set_metadata_version(self): + self._fields['Metadata-Version'] = _best_version(self._fields) + + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) + + def __getitem__(self, name): + return self.get(name) + + def __setitem__(self, name, value): + return self.set(name, value) + + def __delitem__(self, name): + field_name = self._convert_name(name) + try: + del self._fields[field_name] + except KeyError: + raise KeyError(name) + + def __contains__(self, name): + return (name in self._fields or + self._convert_name(name) in self._fields) + + def _convert_name(self, name): + if name in _ALL_FIELDS: + return name + name = name.replace('-', '_').lower() + return _ATTR2FIELD.get(name, name) + + def _default_value(self, name): + if name in _LISTFIELDS or name in _ELEMENTSFIELD: + return [] + return 'UNKNOWN' + + def _remove_line_prefix(self, value): + if self.metadata_version in ('1.0', '1.1'): + return _LINE_PREFIX_PRE_1_2.sub('\n', value) + else: + return _LINE_PREFIX_1_2.sub('\n', value) + + def __getattr__(self, name): + if name in _ATTR2FIELD: + return self[name] + raise AttributeError(name) + + # + # Public API + # + +# dependencies = property(_get_dependencies, _set_dependencies) + + def get_fullname(self, filesafe=False): + """Return the distribution name with version. + + If filesafe is true, return a filename-escaped form.""" + return _get_name_and_version(self['Name'], self['Version'], filesafe) + + def is_field(self, name): + """return True if name is a valid metadata key""" + name = self._convert_name(name) + return name in _ALL_FIELDS + + def is_multi_field(self, name): + name = self._convert_name(name) + return name in _LISTFIELDS + + def read(self, filepath): + """Read the metadata values from a file path.""" + fp = codecs.open(filepath, 'r', encoding='utf-8') + try: + self.read_file(fp) + finally: + fp.close() + + def read_file(self, fileob): + """Read the metadata values from a file object.""" + msg = message_from_file(fileob) + self._fields['Metadata-Version'] = msg['metadata-version'] + + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue + if field in _LISTFIELDS: + # we can have multiple lines + values = msg.get_all(field) + if field in _LISTTUPLEFIELDS and values is not None: + values = [tuple(value.split(',')) for value in values] + self.set(field, values) + else: + # single line + value = msg[field] + if value is not None and value != 'UNKNOWN': + self.set(field, value) + # logger.debug('Attempting to set metadata for %s', self) + # self.set_metadata_version() + + def write(self, filepath, skip_unknown=False): + """Write the metadata fields to filepath.""" + fp = codecs.open(filepath, 'w', encoding='utf-8') + try: + self.write_file(fp, skip_unknown) + finally: + fp.close() + + def write_file(self, fileobject, skip_unknown=False): + """Write the PKG-INFO format data to a file object.""" + self.set_metadata_version() + + for field in _version2fieldlist(self['Metadata-Version']): + values = self.get(field) + if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): + continue + if field in _ELEMENTSFIELD: + self._write_field(fileobject, field, ','.join(values)) + continue + if field not in _LISTFIELDS: + if field == 'Description': + if self.metadata_version in ('1.0', '1.1'): + values = values.replace('\n', '\n ') + else: + values = values.replace('\n', '\n |') + values = [values] + + if field in _LISTTUPLEFIELDS: + values = [','.join(value) for value in values] + + for value in values: + self._write_field(fileobject, field, value) + + def update(self, other=None, **kwargs): + """Set metadata values from the given iterable `other` and kwargs. + + Behavior is like `dict.update`: If `other` has a ``keys`` method, + they are looped over and ``self[key]`` is assigned ``other[key]``. + Else, ``other`` is an iterable of ``(key, value)`` iterables. + + Keys that don't match a metadata field or that have an empty value are + dropped. + """ + def _set(key, value): + if key in _ATTR2FIELD and value: + self.set(self._convert_name(key), value) + + if not other: + # other is None or empty container + pass + elif hasattr(other, 'keys'): + for k in other.keys(): + _set(k, other[k]) + else: + for k, v in other: + _set(k, v) + + if kwargs: + for k, v in kwargs.items(): + _set(k, v) + + def set(self, name, value): + """Control then set a metadata field.""" + name = self._convert_name(name) + + if ((name in _ELEMENTSFIELD or name == 'Platform') and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [v.strip() for v in value.split(',')] + else: + value = [] + elif (name in _LISTFIELDS and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [value] + else: + value = [] + + if logger.isEnabledFor(logging.WARNING): + project_name = self['Name'] + + scheme = get_scheme(self.scheme) + if name in _PREDICATE_FIELDS and value is not None: + for v in value: + # check that the values are valid + if not scheme.is_valid_matcher(v.split(';')[0]): + logger.warning( + "'%s': '%s' is not valid (field '%s')", + project_name, v, name) + # FIXME this rejects UNKNOWN, is that right? + elif name in _VERSIONS_FIELDS and value is not None: + if not scheme.is_valid_constraint_list(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + elif name in _VERSION_FIELDS and value is not None: + if not scheme.is_valid_version(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + + if name in _UNICODEFIELDS: + if name == 'Description': + value = self._remove_line_prefix(value) + + self._fields[name] = value + + def get(self, name, default=_MISSING): + """Get a metadata field.""" + name = self._convert_name(name) + if name not in self._fields: + if default is _MISSING: + default = self._default_value(name) + return default + if name in _UNICODEFIELDS: + value = self._fields[name] + return value + elif name in _LISTFIELDS: + value = self._fields[name] + if value is None: + return [] + res = [] + for val in value: + if name not in _LISTTUPLEFIELDS: + res.append(val) + else: + # That's for Project-URL + res.append((val[0], val[1])) + return res + + elif name in _ELEMENTSFIELD: + value = self._fields[name] + if isinstance(value, string_types): + return value.split(',') + return self._fields[name] + + def check(self, strict=False): + """Check if the metadata is compliant. If strict is True then raise if + no Name or Version are provided""" + self.set_metadata_version() + + # XXX should check the versions (if the file was loaded) + missing, warnings = [], [] + + for attr in ('Name', 'Version'): # required by PEP 345 + if attr not in self: + missing.append(attr) + + if strict and missing != []: + msg = 'missing required metadata: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + + for attr in ('Home-page', 'Author'): + if attr not in self: + missing.append(attr) + + # checking metadata 1.2 (XXX needs to check 1.1, 1.0) + if self['Metadata-Version'] != '1.2': + return missing, warnings + + scheme = get_scheme(self.scheme) + + def are_valid_constraints(value): + for v in value: + if not scheme.is_valid_matcher(v.split(';')[0]): + return False + return True + + for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), + (_VERSIONS_FIELDS, + scheme.is_valid_constraint_list), + (_VERSION_FIELDS, + scheme.is_valid_version)): + for field in fields: + value = self.get(field, None) + if value is not None and not controller(value): + warnings.append("Wrong value for '%s': %s" % (field, value)) + + return missing, warnings + + def todict(self, skip_missing=False): + """Return fields as a dict. + + Field names will be converted to use the underscore-lowercase style + instead of hyphen-mixed case (i.e. home_page instead of Home-page). + """ + self.set_metadata_version() + + mapping_1_0 = ( + ('metadata_version', 'Metadata-Version'), + ('name', 'Name'), + ('version', 'Version'), + ('summary', 'Summary'), + ('home_page', 'Home-page'), + ('author', 'Author'), + ('author_email', 'Author-email'), + ('license', 'License'), + ('description', 'Description'), + ('keywords', 'Keywords'), + ('platform', 'Platform'), + ('classifiers', 'Classifier'), + ('download_url', 'Download-URL'), + ) + + data = {} + for key, field_name in mapping_1_0: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + if self['Metadata-Version'] == '1.2': + mapping_1_2 = ( + ('requires_dist', 'Requires-Dist'), + ('requires_python', 'Requires-Python'), + ('requires_external', 'Requires-External'), + ('provides_dist', 'Provides-Dist'), + ('obsoletes_dist', 'Obsoletes-Dist'), + ('project_url', 'Project-URL'), + ('maintainer', 'Maintainer'), + ('maintainer_email', 'Maintainer-email'), + ) + for key, field_name in mapping_1_2: + if not skip_missing or field_name in self._fields: + if key != 'project_url': + data[key] = self[field_name] + else: + data[key] = [','.join(u) for u in self[field_name]] + + elif self['Metadata-Version'] == '1.1': + mapping_1_1 = ( + ('provides', 'Provides'), + ('requires', 'Requires'), + ('obsoletes', 'Obsoletes'), + ) + for key, field_name in mapping_1_1: + if not skip_missing or field_name in self._fields: + data[key] = self[field_name] + + return data + + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + + # Mapping API + # TODO could add iter* variants + + def keys(self): + return list(_version2fieldlist(self['Metadata-Version'])) + + def __iter__(self): + for key in self.keys(): + yield key + + def values(self): + return [self[key] for key in self.keys()] + + def items(self): + return [(key, self[key]) for key in self.keys()] + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, self.name, + self.version) + + +METADATA_FILENAME = 'pydist.json' +WHEEL_METADATA_FILENAME = 'metadata.json' +LEGACY_METADATA_FILENAME = 'METADATA' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.0 (JSON) + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP440_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy',), + } + + INDEX_KEYS = ('name version license summary description author ' + 'author_email keywords platform home_page classifiers ' + 'download_url') + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy',)), + 'version': (VERSION_MATCHER, ('legacy',)), + 'summary': (SUMMARY_MATCHER, ('legacy',)), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + #import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), + scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + if key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + result = self._data.get(key, value) + else: + # special cases for PEP 459 + sentinel = object() + result = sentinel + d = self._data.get('extensions') + if d: + if key == 'commands': + result = d.get('python.commands', value) + elif key == 'classifiers': + d = d.get('python.details') + if d: + result = d.get(key, value) + else: + d = d.get('python.exports') + if not d: + d = self._data.get('python.exports') + if d: + result = d.get(key, value) + if result is sentinel: + result = value + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError("'%s' is an invalid value for " + "the '%s' property" % (value, + key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + elif key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + self._data[key] = value + else: + # special cases for PEP 459 + d = self._data.setdefault('extensions', {}) + if key == 'commands': + d['python.commands'] = value + elif key == 'classifiers': + d = d.setdefault('python.details', {}) + d[key] = value + else: + d = d.setdefault('python.exports', {}) + d[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, + env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', + missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', + 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), + ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + author = {} + maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + 'license': 'License', + 'summary': 'Summary', + 'description': 'Description', + 'classifiers': 'Classifier', + } + + def _to_legacy(self): + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + for nk, ok in self.LEGACY_MAPPING.items(): + if nk in nmd: + result[ok] = nmd[nk] + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: other fields such as contacts + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, + sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, + sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + run_requires = self._data.setdefault('run_requires', []) + always = None + for entry in run_requires: + if 'environment' not in entry and 'extra' not in entry: + always = entry + break + if always is None: + always = { 'requires': requirements } + run_requires.insert(0, always) + else: + rset = set(always['requires']) | set(requirements) + always['requires'] = sorted(rset) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, + self.metadata_version, name, version) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/resources.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/resources.py new file mode 100644 index 00000000..18840167 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/resources.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import bisect +import io +import logging +import os +import pkgutil +import shutil +import sys +import types +import zipimport + +from . import DistlibException +from .util import cached_property, get_cache_base, path_to_cache_dir, Cache + +logger = logging.getLogger(__name__) + + +cache = None # created when needed + + +class ResourceCache(Cache): + def __init__(self, base=None): + if base is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('resource-cache')) + super(ResourceCache, self).__init__(base) + + def is_stale(self, resource, path): + """ + Is the cache stale for the given resource? + + :param resource: The :class:`Resource` being cached. + :param path: The path of the resource in the cache. + :return: True if the cache is stale. + """ + # Cache invalidation is a hard problem :-) + return True + + def get(self, resource): + """ + Get a resource into the cache, + + :param resource: A :class:`Resource` instance. + :return: The pathname of the resource in the cache. + """ + prefix, path = resource.finder.get_cache_info(resource) + if prefix is None: + result = path + else: + result = os.path.join(self.base, self.prefix_to_dir(prefix), path) + dirname = os.path.dirname(result) + if not os.path.isdir(dirname): + os.makedirs(dirname) + if not os.path.exists(result): + stale = True + else: + stale = self.is_stale(resource, path) + if stale: + # write the bytes of the resource to the cache location + with open(result, 'wb') as f: + f.write(resource.bytes) + return result + + +class ResourceBase(object): + def __init__(self, finder, name): + self.finder = finder + self.name = name + + +class Resource(ResourceBase): + """ + A class representing an in-package resource, such as a data file. This is + not normally instantiated by user code, but rather by a + :class:`ResourceFinder` which manages the resource. + """ + is_container = False # Backwards compatibility + + def as_stream(self): + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ + return self.finder.get_stream(self) + + @cached_property + def file_path(self): + global cache + if cache is None: + cache = ResourceCache() + return cache.get(self) + + @cached_property + def bytes(self): + return self.finder.get_bytes(self) + + @cached_property + def size(self): + return self.finder.get_size(self) + + +class ResourceContainer(ResourceBase): + is_container = True # Backwards compatibility + + @cached_property + def resources(self): + return self.finder.get_resources(self) + + +class ResourceFinder(object): + """ + Resource finder for file system resources. + """ + + if sys.platform.startswith('java'): + skipped_extensions = ('.pyc', '.pyo', '.class') + else: + skipped_extensions = ('.pyc', '.pyo') + + def __init__(self, module): + self.module = module + self.loader = getattr(module, '__loader__', None) + self.base = os.path.dirname(getattr(module, '__file__', '')) + + def _adjust_path(self, path): + return os.path.realpath(path) + + def _make_path(self, resource_name): + # Issue #50: need to preserve type of path on Python 2.x + # like os.path._get_sep + if isinstance(resource_name, bytes): # should only happen on 2.x + sep = b'/' + else: + sep = '/' + parts = resource_name.split(sep) + parts.insert(0, self.base) + result = os.path.join(*parts) + return self._adjust_path(result) + + def _find(self, path): + return os.path.exists(path) + + def get_cache_info(self, resource): + return None, resource.path + + def find(self, resource_name): + path = self._make_path(resource_name) + if not self._find(path): + result = None + else: + if self._is_directory(path): + result = ResourceContainer(self, resource_name) + else: + result = Resource(self, resource_name) + result.path = path + return result + + def get_stream(self, resource): + return open(resource.path, 'rb') + + def get_bytes(self, resource): + with open(resource.path, 'rb') as f: + return f.read() + + def get_size(self, resource): + return os.path.getsize(resource.path) + + def get_resources(self, resource): + def allowed(f): + return (f != '__pycache__' and not + f.endswith(self.skipped_extensions)) + return set([f for f in os.listdir(resource.path) if allowed(f)]) + + def is_container(self, resource): + return self._is_directory(resource.path) + + _is_directory = staticmethod(os.path.isdir) + + def iterator(self, resource_name): + resource = self.find(resource_name) + if resource is not None: + todo = [resource] + while todo: + resource = todo.pop(0) + yield resource + if resource.is_container: + rname = resource.name + for name in resource.resources: + if not rname: + new_name = name + else: + new_name = '/'.join([rname, name]) + child = self.find(new_name) + if child.is_container: + todo.append(child) + else: + yield child + + +class ZipResourceFinder(ResourceFinder): + """ + Resource finder for resources in .zip files. + """ + def __init__(self, module): + super(ZipResourceFinder, self).__init__(module) + archive = self.loader.archive + self.prefix_len = 1 + len(archive) + # PyPy doesn't have a _files attr on zipimporter, and you can't set one + if hasattr(self.loader, '_files'): + self._files = self.loader._files + else: + self._files = zipimport._zip_directory_cache[archive] + self.index = sorted(self._files) + + def _adjust_path(self, path): + return path + + def _find(self, path): + path = path[self.prefix_len:] + if path in self._files: + result = True + else: + if path and path[-1] != os.sep: + path = path + os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + if not result: + logger.debug('_find failed: %r %r', path, self.loader.prefix) + else: + logger.debug('_find worked: %r %r', path, self.loader.prefix) + return result + + def get_cache_info(self, resource): + prefix = self.loader.archive + path = resource.path[1 + len(prefix):] + return prefix, path + + def get_bytes(self, resource): + return self.loader.get_data(resource.path) + + def get_stream(self, resource): + return io.BytesIO(self.get_bytes(resource)) + + def get_size(self, resource): + path = resource.path[self.prefix_len:] + return self._files[path][3] + + def get_resources(self, resource): + path = resource.path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + plen = len(path) + result = set() + i = bisect.bisect(self.index, path) + while i < len(self.index): + if not self.index[i].startswith(path): + break + s = self.index[i][plen:] + result.add(s.split(os.sep, 1)[0]) # only immediate children + i += 1 + return result + + def _is_directory(self, path): + path = path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + return result + +_finder_registry = { + type(None): ResourceFinder, + zipimport.zipimporter: ZipResourceFinder +} + +try: + # In Python 3.6, _frozen_importlib -> _frozen_importlib_external + try: + import _frozen_importlib_external as _fi + except ImportError: + import _frozen_importlib as _fi + _finder_registry[_fi.SourceFileLoader] = ResourceFinder + _finder_registry[_fi.FileFinder] = ResourceFinder + del _fi +except (ImportError, AttributeError): + pass + + +def register_finder(loader, finder_maker): + _finder_registry[type(loader)] = finder_maker + +_finder_cache = {} + + +def finder(package): + """ + Return a resource finder for a package. + :param package: The name of the package. + :return: A :class:`ResourceFinder` instance for the package. + """ + if package in _finder_cache: + result = _finder_cache[package] + else: + if package not in sys.modules: + __import__(package) + module = sys.modules[package] + path = getattr(module, '__path__', None) + if path is None: + raise DistlibException('You cannot get a finder for a module, ' + 'only for a package') + loader = getattr(module, '__loader__', None) + finder_maker = _finder_registry.get(type(loader)) + if finder_maker is None: + raise DistlibException('Unable to locate finder for %r' % package) + result = finder_maker(module) + _finder_cache[package] = result + return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/scripts.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/scripts.py new file mode 100644 index 00000000..51859741 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/scripts.py @@ -0,0 +1,416 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from io import BytesIO +import logging +import os +import re +import struct +import sys + +from .compat import sysconfig, detect_encoding, ZipFile +from .resources import finder +from .util import (FileOperator, get_export_entry, convert_path, + get_executable, in_venv) + +logger = logging.getLogger(__name__) + +_DEFAULT_MANIFEST = ''' + + + + + + + + + + + + +'''.strip() + +# check if Python is called on the first line with this expression +FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- +import re +import sys +from %(module)s import %(import_name)s +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +''' + + +def _enquote_executable(executable): + if ' ' in executable: + # make sure we quote only the executable in case of env + # for example /usr/bin/env "/dir with spaces/bin/jython" + # instead of "/usr/bin/env /dir with spaces/bin/jython" + # otherwise whole + if executable.startswith('/usr/bin/env '): + env, _executable = executable.split(' ', 1) + if ' ' in _executable and not _executable.startswith('"'): + executable = '%s "%s"' % (env, _executable) + else: + if not executable.startswith('"'): + executable = '"%s"' % executable + return executable + + +class ScriptMaker(object): + """ + A class to copy or create scripts from source scripts or callable + specifications. + """ + script_template = SCRIPT_TEMPLATE + + executable = None # for shebangs + + def __init__(self, source_dir, target_dir, add_launchers=True, + dry_run=False, fileop=None): + self.source_dir = source_dir + self.target_dir = target_dir + self.add_launchers = add_launchers + self.force = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') or (os.name == 'java' and + os._name == 'posix') + self.variants = set(('', 'X.Y')) + self._fileop = fileop or FileOperator(dry_run) + + self._is_nt = os.name == 'nt' or ( + os.name == 'java' and os._name == 'nt') + + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and self._is_nt: # pragma: no cover + dn, fn = os.path.split(executable) + fn = fn.replace('python', 'pythonw') + executable = os.path.join(dn, fn) + return executable + + if sys.platform.startswith('java'): # pragma: no cover + def _is_shell(self, executable): + """ + Determine if the specified executable is a script + (contains a #! line) + """ + try: + with open(executable) as fp: + return fp.read(2) == '#!' + except (OSError, IOError): + logger.warning('Failed to open %s', executable) + return False + + def _fix_jython_executable(self, executable): + if self._is_shell(executable): + # Workaround for Jython is not needed on Linux systems. + import java + + if java.lang.System.getProperty('os.name') == 'Linux': + return executable + elif executable.lower().endswith('jython.exe'): + # Use wrapper exe for Jython on Windows + return executable + return '/usr/bin/env %s' % executable + + def _build_shebang(self, executable, post_interp): + """ + Build a shebang line. In the simple case (on Windows, or a shebang line + which is not too long or contains spaces) use a simple formulation for + the shebang. Otherwise, use /bin/sh as the executable, with a contrived + shebang which allows the script to run either under Python or sh, using + suitable quoting. Thanks to Harald Nordgren for his input. + + See also: http://www.in-ulm.de/~mascheck/various/shebang/#length + https://hg.mozilla.org/mozilla-central/file/tip/mach + """ + if os.name != 'posix': + simple_shebang = True + else: + # Add 3 for '#!' prefix and newline suffix. + shebang_length = len(executable) + len(post_interp) + 3 + if sys.platform == 'darwin': + max_shebang_length = 512 + else: + max_shebang_length = 127 + simple_shebang = ((b' ' not in executable) and + (shebang_length <= max_shebang_length)) + + if simple_shebang: + result = b'#!' + executable + post_interp + b'\n' + else: + result = b'#!/bin/sh\n' + result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n' + result += b"' '''" + return result + + def _get_shebang(self, encoding, post_interp=b'', options=None): + enquote = True + if self.executable: + executable = self.executable + enquote = False # assume this will be taken care of + elif not sysconfig.is_python_build(): + executable = get_executable() + elif in_venv(): # pragma: no cover + executable = os.path.join(sysconfig.get_path('scripts'), + 'python%s' % sysconfig.get_config_var('EXE')) + else: # pragma: no cover + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), + sysconfig.get_config_var('EXE'))) + if options: + executable = self._get_alternate_executable(executable, options) + + if sys.platform.startswith('java'): # pragma: no cover + executable = self._fix_jython_executable(executable) + + # Normalise case for Windows - COMMENTED OUT + # executable = os.path.normcase(executable) + # N.B. The normalising operation above has been commented out: See + # issue #124. Although paths in Windows are generally case-insensitive, + # they aren't always. For example, a path containing a ẞ (which is a + # LATIN CAPITAL LETTER SHARP S - U+1E9E) is normcased to ß (which is a + # LATIN SMALL LETTER SHARP S' - U+00DF). The two are not considered by + # Windows as equivalent in path names. + + # If the user didn't specify an executable, it may be necessary to + # cater for executable paths with spaces (not uncommon on Windows) + if enquote: + executable = _enquote_executable(executable) + # Issue #51: don't use fsencode, since we later try to + # check that the shebang is decodable using utf-8. + executable = executable.encode('utf-8') + # in case of IronPython, play safe and enable frames support + if (sys.platform == 'cli' and '-X:Frames' not in post_interp + and '-X:FullFrames' not in post_interp): # pragma: no cover + post_interp += b' -X:Frames' + shebang = self._build_shebang(executable, post_interp) + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable from utf-8' % shebang) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + if encoding != 'utf-8': + try: + shebang.decode(encoding) + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable ' + 'from the script encoding (%r)' % (shebang, encoding)) + return shebang + + def _get_script_text(self, entry): + return self.script_template % dict(module=entry.prefix, + import_name=entry.suffix.split('.')[0], + func=entry.suffix) + + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): + use_launcher = self.add_launchers and self._is_nt + linesep = os.linesep.encode('utf-8') + if not shebang.endswith(linesep): + shebang += linesep + if not use_launcher: + script_bytes = shebang + script_bytes + else: # pragma: no cover + if ext == 'py': + launcher = self._get_launcher('t') + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: # pragma: no cover + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + def _make_script(self, entry, filenames, options=None): + post_interp = b'' + if options: + args = options.get('interpreter_args', []) + if args: + args = ' %s' % ' '.join(args) + post_interp = args.encode('utf-8') + shebang = self._get_shebang('utf-8', post_interp, options=options) + script = self._get_script_text(entry).encode('utf-8') + name = entry.name + scriptnames = set() + if '' in self.variants: + scriptnames.add(name) + if 'X' in self.variants: + scriptnames.add('%s%s' % (name, sys.version_info[0])) + if 'X.Y' in self.variants: + scriptnames.add('%s-%s.%s' % (name, sys.version_info[0], + sys.version_info[1])) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) + + def _copy_script(self, script, filenames): + adjust = False + script = os.path.join(self.source_dir, convert_path(script)) + outname = os.path.join(self.target_dir, os.path.basename(script)) + if not self.force and not self._fileop.newer(script, outname): + logger.debug('not copying %s (up-to-date)', script) + return + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, 'rb') + except IOError: # pragma: no cover + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: # pragma: no cover + logger.warning('%s: %s is an empty file (skipping)', + self.get_command_name(), script) + return + + match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if not adjust: + if f: + f.close() + self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + else: + logger.info('copying and adjusting %s -> %s', script, + self.target_dir) + if not self._fileop.dry_run: + encoding, lines = detect_encoding(f.readline) + f.seek(0) + shebang = self._get_shebang(encoding, post_interp) + if b'pythonw' in first_line: # pragma: no cover + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) + if f: + f.close() + + @property + def dry_run(self): + return self._fileop.dry_run + + @dry_run.setter + def dry_run(self, value): + self._fileop.dry_run = value + + if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): # pragma: no cover + # Executable launcher support. + # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ + + def _get_launcher(self, kind): + if struct.calcsize('P') == 8: # 64-bit + bits = '64' + else: + bits = '32' + name = '%s%s.exe' % (kind, bits) + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + resource = finder(distlib_package).find(name) + if not resource: + msg = ('Unable to find resource %s in package %s' % (name, + distlib_package)) + raise ValueError(msg) + return resource.bytes + + # Public API follows + + def make(self, specification, options=None): + """ + Make a script. + + :param specification: The specification, which is either a valid export + entry specification (to make a script from a + callable) or a filename (to make a script by + copying from a source location). + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. + """ + filenames = [] + entry = get_export_entry(specification) + if entry is None: + self._copy_script(specification, filenames) + else: + self._make_script(entry, filenames, options=options) + return filenames + + def make_multiple(self, specifications, options=None): + """ + Take a list of specifications and make scripts from them, + :param specifications: A list of specifications. + :return: A list of all absolute pathnames written to, + """ + filenames = [] + for specification in specifications: + filenames.extend(self.make(specification, options)) + return filenames diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/util.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/util.py new file mode 100644 index 00000000..01324eae --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/util.py @@ -0,0 +1,1761 @@ +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import codecs +from collections import deque +import contextlib +import csv +from glob import iglob as std_iglob +import io +import json +import logging +import os +import py_compile +import re +import socket +try: + import ssl +except ImportError: # pragma: no cover + ssl = None +import subprocess +import sys +import tarfile +import tempfile +import textwrap + +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import time + +from . import DistlibException +from .compat import (string_types, text_type, shutil, raw_input, StringIO, + cache_from_source, urlopen, urljoin, httplib, xmlrpclib, + splittype, HTTPHandler, BaseConfigurator, valid_ident, + Container, configparser, URLError, ZipFile, fsdecode, + unquote, urlparse) + +logger = logging.getLogger(__name__) + +# +# Requirement parsing code as per PEP 508 +# + +IDENTIFIER = re.compile(r'^([\w\.-]+)\s*') +VERSION_IDENTIFIER = re.compile(r'^([\w\.*+-]+)\s*') +COMPARE_OP = re.compile(r'^(<=?|>=?|={2,3}|[~!]=)\s*') +MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*') +OR = re.compile(r'^or\b\s*') +AND = re.compile(r'^and\b\s*') +NON_SPACE = re.compile(r'(\S+)\s*') +STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') + + +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. + + The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in + the expression grammar, or strings. A string contained in quotes is to be + interpreted as a literal string, and a string not contained in quotes is a + variable (such as os_name). + """ + def marker_var(remaining): + # either identifier, or literal string + m = IDENTIFIER.match(remaining) + if m: + result = m.groups()[0] + remaining = remaining[m.end():] + elif not remaining: + raise SyntaxError('unexpected end of input') + else: + q = remaining[0] + if q not in '\'"': + raise SyntaxError('invalid expression: %s' % remaining) + oq = '\'"'.replace(q, '') + remaining = remaining[1:] + parts = [q] + while remaining: + # either a string chunk, or oq, or q to terminate + if remaining[0] == q: + break + elif remaining[0] == oq: + parts.append(oq) + remaining = remaining[1:] + else: + m = STRING_CHUNK.match(remaining) + if not m: + raise SyntaxError('error in string literal: %s' % remaining) + parts.append(m.groups()[0]) + remaining = remaining[m.end():] + else: + s = ''.join(parts) + raise SyntaxError('unterminated string: %s' % s) + parts.append(q) + result = ''.join(parts) + remaining = remaining[1:].lstrip() # skip past closing quote + return result, remaining + + def marker_expr(remaining): + if remaining and remaining[0] == '(': + result, remaining = marker(remaining[1:].lstrip()) + if remaining[0] != ')': + raise SyntaxError('unterminated parenthesis: %s' % remaining) + remaining = remaining[1:].lstrip() + else: + lhs, remaining = marker_var(remaining) + while remaining: + m = MARKER_OP.match(remaining) + if not m: + break + op = m.groups()[0] + remaining = remaining[m.end():] + rhs, remaining = marker_var(remaining) + lhs = {'op': op, 'lhs': lhs, 'rhs': rhs} + result = lhs + return result, remaining + + def marker_and(remaining): + lhs, remaining = marker_expr(remaining) + while remaining: + m = AND.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_expr(remaining) + lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + def marker(remaining): + lhs, remaining = marker_and(remaining) + while remaining: + m = OR.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_and(remaining) + lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + return marker(marker_string) + + +def parse_requirement(req): + """ + Parse a requirement passed in as a string. Return a Container + whose attributes contain the various parts of the requirement. + """ + remaining = req.strip() + if not remaining or remaining.startswith('#'): + return None + m = IDENTIFIER.match(remaining) + if not m: + raise SyntaxError('name expected: %s' % remaining) + distname = m.groups()[0] + remaining = remaining[m.end():] + extras = mark_expr = versions = uri = None + if remaining and remaining[0] == '[': + i = remaining.find(']', 1) + if i < 0: + raise SyntaxError('unterminated extra: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + extras = [] + while s: + m = IDENTIFIER.match(s) + if not m: + raise SyntaxError('malformed extra: %s' % s) + extras.append(m.groups()[0]) + s = s[m.end():] + if not s: + break + if s[0] != ',': + raise SyntaxError('comma expected in extras: %s' % s) + s = s[1:].lstrip() + if not extras: + extras = None + if remaining: + if remaining[0] == '@': + # it's a URI + remaining = remaining[1:].lstrip() + m = NON_SPACE.match(remaining) + if not m: + raise SyntaxError('invalid URI: %s' % remaining) + uri = m.groups()[0] + t = urlparse(uri) + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not (t.scheme and t.netloc): + raise SyntaxError('Invalid URL: %s' % uri) + remaining = remaining[m.end():].lstrip() + else: + + def get_versions(ver_remaining): + """ + Return a list of operator, version tuples if any are + specified, else None. + """ + m = COMPARE_OP.match(ver_remaining) + versions = None + if m: + versions = [] + while True: + op = m.groups()[0] + ver_remaining = ver_remaining[m.end():] + m = VERSION_IDENTIFIER.match(ver_remaining) + if not m: + raise SyntaxError('invalid version: %s' % ver_remaining) + v = m.groups()[0] + versions.append((op, v)) + ver_remaining = ver_remaining[m.end():] + if not ver_remaining or ver_remaining[0] != ',': + break + ver_remaining = ver_remaining[1:].lstrip() + m = COMPARE_OP.match(ver_remaining) + if not m: + raise SyntaxError('invalid constraint: %s' % ver_remaining) + if not versions: + versions = None + return versions, ver_remaining + + if remaining[0] != '(': + versions, remaining = get_versions(remaining) + else: + i = remaining.find(')', 1) + if i < 0: + raise SyntaxError('unterminated parenthesis: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + # As a special diversion from PEP 508, allow a version number + # a.b.c in parentheses as a synonym for ~= a.b.c (because this + # is allowed in earlier PEPs) + if COMPARE_OP.match(s): + versions, _ = get_versions(s) + else: + m = VERSION_IDENTIFIER.match(s) + if not m: + raise SyntaxError('invalid constraint: %s' % s) + v = m.groups()[0] + s = s[m.end():].lstrip() + if s: + raise SyntaxError('invalid constraint: %s' % s) + versions = [('~=', v)] + + if remaining: + if remaining[0] != ';': + raise SyntaxError('invalid requirement: %s' % remaining) + remaining = remaining[1:].lstrip() + + mark_expr, remaining = parse_marker(remaining) + + if remaining and remaining[0] != '#': + raise SyntaxError('unexpected trailing data: %s' % remaining) + + if not versions: + rs = distname + else: + rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions])) + return Container(name=distname, extras=extras, constraints=versions, + marker=mark_expr, url=uri, requirement=rs) + + +def get_resources_dests(resources_root, rules): + """Find destinations for resources files""" + + def get_rel_path(root, path): + # normalizes and returns a lstripped-/-separated path + root = root.replace(os.path.sep, '/') + path = path.replace(os.path.sep, '/') + assert path.startswith(root) + return path[len(root):].lstrip('/') + + destinations = {} + for base, suffix, dest in rules: + prefix = os.path.join(resources_root, base) + for abs_base in iglob(prefix): + abs_glob = os.path.join(abs_base, suffix) + for abs_path in iglob(abs_glob): + resource_file = get_rel_path(resources_root, abs_path) + if dest is None: # remove the entry if it was here + destinations.pop(resource_file, None) + else: + rel_path = get_rel_path(abs_base, abs_path) + rel_dest = dest.replace(os.path.sep, '/').rstrip('/') + destinations[resource_file] = rel_dest + '/' + rel_path + return destinations + + +def in_venv(): + if hasattr(sys, 'real_prefix'): + # virtualenv venvs + result = True + else: + # PEP 405 venvs + result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) + return result + + +def get_executable(): +# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as +# changes to the stub launcher mean that sys.executable always points +# to the stub on OS X +# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' +# in os.environ): +# result = os.environ['__PYVENV_LAUNCHER__'] +# else: +# result = sys.executable +# return result + result = os.path.normcase(sys.executable) + if not isinstance(result, text_type): + result = fsdecode(result) + return result + + +def proceed(prompt, allowed_chars, error_prompt=None, default=None): + p = prompt + while True: + s = raw_input(p) + p = prompt + if not s and default: + s = default + if s: + c = s[0].lower() + if c in allowed_chars: + break + if error_prompt: + p = '%c: %s\n%s' % (c, error_prompt, prompt) + return c + + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + jdata = json.load(stream) + result = jdata['extensions']['python.exports']['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + + def read_stream(cp, stream): + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + + cp = configparser.ConfigParser() + try: + read_stream(cp, stream) + except configparser.MissingSectionHeaderError: + stream.close() + data = textwrap.dedent(data) + stream = StringIO(data) + read_stream(cp, stream) + + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + #entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + +@contextlib.contextmanager +def tempdir(): + td = tempfile.mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +@contextlib.contextmanager +def chdir(d): + cwd = os.getcwd() + try: + os.chdir(d) + yield + finally: + os.chdir(cwd) + + +@contextlib.contextmanager +def socket_timeout(seconds=15): + cto = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(seconds) + yield + finally: + socket.setdefaulttimeout(cto) + + +class cached_property(object): + def __init__(self, func): + self.func = func + #for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) + + def __get__(self, obj, cls=None): + if obj is None: + return self + value = self.func(obj) + object.__setattr__(obj, self.func.__name__, value) + #obj.__dict__[self.func.__name__] = value = self.func(obj) + return value + +def convert_path(pathname): + """Return 'pathname' as a name that will work on the native filesystem. + + The path is split on '/' and put back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while os.curdir in paths: + paths.remove(os.curdir) + if not paths: + return os.curdir + return os.path.join(*paths) + + +class FileOperator(object): + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.ensured = set() + self._init_record() + + def _init_record(self): + self.record = False + self.files_written = set() + self.dirs_created = set() + + def record_as_written(self, path): + if self.record: + self.files_written.add(path) + + def newer(self, source, target): + """Tell if the target is newer than the source. + + Returns true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Returns false if both exist and 'target' is the same age or younger + than 'source'. Raise PackagingFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same + second will have the same "age". + """ + if not os.path.exists(source): + raise DistlibException("file '%r' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source).st_mtime > os.stat(target).st_mtime + + def copy_file(self, infile, outfile, check=True): + """Copy a file respecting dry-run and force flags. + """ + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying %s to %s', infile, outfile) + if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') + shutil.copyfile(infile, outfile) + self.record_as_written(outfile) + + def copy_stream(self, instream, outfile, encoding=None): + assert not os.path.isdir(outfile) + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying stream %s to %s', instream, outfile) + if not self.dry_run: + if encoding is None: + outstream = open(outfile, 'wb') + else: + outstream = codecs.open(outfile, 'w', encoding=encoding) + try: + shutil.copyfileobj(instream, outstream) + finally: + outstream.close() + self.record_as_written(outfile) + + def write_binary_file(self, path, data): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + if os.path.exists(path): + os.remove(path) + with open(path, 'wb') as f: + f.write(data) + self.record_as_written(path) + + def write_text_file(self, path, data, encoding): + self.write_binary_file(path, data.encode(encoding)) + + def set_mode(self, bits, mask, files): + if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): + # Set the executable bits (owner, group, and world) on + # all the files specified. + for f in files: + if self.dry_run: + logger.info("changing mode of %s", f) + else: + mode = (os.stat(f).st_mode | bits) & mask + logger.info("changing mode of %s to %o", f, mode) + os.chmod(f, mode) + + set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) + + def ensure_dir(self, path): + path = os.path.abspath(path) + if path not in self.ensured and not os.path.exists(path): + self.ensured.add(path) + d, f = os.path.split(path) + self.ensure_dir(d) + logger.info('Creating %s' % path) + if not self.dry_run: + os.mkdir(path) + if self.record: + self.dirs_created.add(path) + + def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_invalidation=False): + dpath = cache_from_source(path, not optimize) + logger.info('Byte-compiling %s to %s', path, dpath) + if not self.dry_run: + if force or self.newer(path, dpath): + if not prefix: + diagpath = None + else: + assert path.startswith(prefix) + diagpath = path[len(prefix):] + compile_kwargs = {} + if hashed_invalidation and hasattr(py_compile, 'PycInvalidationMode'): + compile_kwargs['invalidation_mode'] = py_compile.PycInvalidationMode.CHECKED_HASH + py_compile.compile(path, dpath, diagpath, True, **compile_kwargs) # raise error + self.record_as_written(dpath) + return dpath + + def ensure_removed(self, path): + if os.path.exists(path): + if os.path.isdir(path) and not os.path.islink(path): + logger.debug('Removing directory tree at %s', path) + if not self.dry_run: + shutil.rmtree(path) + if self.record: + if path in self.dirs_created: + self.dirs_created.remove(path) + else: + if os.path.islink(path): + s = 'link' + else: + s = 'file' + logger.debug('Removing %s %s', s, path) + if not self.dry_run: + os.remove(path) + if self.record: + if path in self.files_written: + self.files_written.remove(path) + + def is_writable(self, path): + result = False + while not result: + if os.path.exists(path): + result = os.access(path, os.W_OK) + break + parent = os.path.dirname(path) + if parent == path: + break + path = parent + return result + + def commit(self): + """ + Commit recorded changes, turn off recording, return + changes. + """ + assert self.record + result = self.files_written, self.dirs_created + self._init_record() + return result + + def rollback(self): + if not self.dry_run: + for f in list(self.files_written): + if os.path.exists(f): + os.remove(f) + # dirs should all be empty now, except perhaps for + # __pycache__ subdirs + # reverse so that subdirs appear before their parents + dirs = sorted(self.dirs_created, reverse=True) + for d in dirs: + flist = os.listdir(d) + if flist: + assert flist == ['__pycache__'] + sd = os.path.join(d, flist[0]) + os.rmdir(sd) + os.rmdir(d) # should fail if non-empty + self._init_record() + +def resolve(module_name, dotted_path): + if module_name in sys.modules: + mod = sys.modules[module_name] + else: + mod = __import__(module_name) + if dotted_path is None: + result = mod + else: + parts = dotted_path.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + +class ExportEntry(object): + def __init__(self, name, prefix, suffix, flags): + self.name = name + self.prefix = prefix + self.suffix = suffix + self.flags = flags + + @cached_property + def value(self): + return resolve(self.prefix, self.suffix) + + def __repr__(self): # pragma: no cover + return '' % (self.name, self.prefix, + self.suffix, self.flags) + + def __eq__(self, other): + if not isinstance(other, ExportEntry): + result = False + else: + result = (self.name == other.name and + self.prefix == other.prefix and + self.suffix == other.suffix and + self.flags == other.flags) + return result + + __hash__ = object.__hash__ + + +ENTRY_RE = re.compile(r'''(?P(\w|[-.+])+) + \s*=\s*(?P(\w+)([:\.]\w+)*) + \s*(\[\s*(?P[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? + ''', re.VERBOSE) + +def get_export_entry(specification): + m = ENTRY_RE.search(specification) + if not m: + result = None + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + else: + d = m.groupdict() + name = d['name'] + path = d['callable'] + colons = path.count(':') + if colons == 0: + prefix, suffix = path, None + else: + if colons != 1: + raise DistlibException("Invalid specification " + "'%s'" % specification) + prefix, suffix = path.split(':') + flags = d['flags'] + if flags is None: + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + flags = [] + else: + flags = [f.strip() for f in flags.split(',')] + result = ExportEntry(name, prefix, suffix, flags) + return result + + +def get_cache_base(suffix=None): + """ + Return the default base location for distlib caches. If the directory does + not exist, it is created. Use the suffix provided for the base directory, + and default to '.distlib' if it isn't provided. + + On Windows, if LOCALAPPDATA is defined in the environment, then it is + assumed to be a directory, and will be the parent directory of the result. + On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home + directory - using os.expanduser('~') - will be the parent directory of + the result. + + The result is just the directory '.distlib' in the parent directory as + determined above, or with the name specified with ``suffix``. + """ + if suffix is None: + suffix = '.distlib' + if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: + result = os.path.expandvars('$localappdata') + else: + # Assume posix, or old Windows + result = os.path.expanduser('~') + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if os.path.isdir(result): + usable = os.access(result, os.W_OK) + if not usable: + logger.warning('Directory exists but is not writable: %s', result) + else: + try: + os.makedirs(result) + usable = True + except OSError: + logger.warning('Unable to create %s', result, exc_info=True) + usable = False + if not usable: + result = tempfile.mkdtemp() + logger.warning('Default location unusable, using %s', result) + return os.path.join(result, suffix) + + +def path_to_cache_dir(path): + """ + Convert an absolute path to a directory name for use in a cache. + + The algorithm used is: + + #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. + #. Any occurrence of ``os.sep`` is replaced with ``'--'``. + #. ``'.cache'`` is appended. + """ + d, p = os.path.splitdrive(os.path.abspath(path)) + if d: + d = d.replace(':', '---') + p = p.replace(os.sep, '--') + return d + p + '.cache' + + +def ensure_slash(s): + if not s.endswith('/'): + return s + '/' + return s + + +def parse_credentials(netloc): + username = password = None + if '@' in netloc: + prefix, netloc = netloc.rsplit('@', 1) + if ':' not in prefix: + username = prefix + else: + username, password = prefix.split(':', 1) + if username: + username = unquote(username) + if password: + password = unquote(password) + return username, password, netloc + + +def get_process_umask(): + result = os.umask(0o22) + os.umask(result) + return result + +def is_string_sequence(seq): + result = True + i = None + for i, s in enumerate(seq): + if not isinstance(s, string_types): + result = False + break + assert i is not None + return result + +PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') + + +def split_filename(filename, project_name=None): + """ + Extract name, version, python version from a filename (no extension) + + Return name, version, pyver or None + """ + result = None + pyver = None + filename = unquote(filename).replace(' ', '-') + m = PYTHON_VERSION.search(filename) + if m: + pyver = m.group(1) + filename = filename[:m.start()] + if project_name and len(filename) > len(project_name) + 1: + m = re.match(re.escape(project_name) + r'\b', filename) + if m: + n = m.end() + result = filename[:n], filename[n + 1:], pyver + if result is None: + m = PROJECT_NAME_AND_VERSION.match(filename) + if m: + result = m.group(1), m.group(3), pyver + return result + +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' + r'\(\s*(?P[^\s)]+)\)$') + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result +# +# Extended metadata functionality +# + +def _get_external_data(url): + result = {} + try: + # urlopen might fail if it runs into redirections, + # because of Python issue #13696. Fixed in locators + # using a custom redirect handler. + resp = urlopen(url) + headers = resp.info() + ct = headers.get('Content-Type') + if not ct.startswith('application/json'): + logger.debug('Unexpected response for JSON request: %s', ct) + else: + reader = codecs.getreader('utf-8')(resp) + #data = reader.read().decode('utf-8') + #result = json.loads(data) + result = json.load(reader) + except Exception as e: + logger.exception('Failed to get external data for %s: %s', url, e) + return result + +_external_data_base_url = 'https://www.red-dove.com/pypi/projects/' + +def get_project_data(name): + url = '%s/%s/project.json' % (name[0].upper(), name) + url = urljoin(_external_data_base_url, url) + result = _get_external_data(url) + return result + +def get_package_data(name, version): + url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) + url = urljoin(_external_data_base_url, url) + return _get_external_data(url) + + +class Cache(object): + """ + A class implementing a cache for resources that need to live in the file system + e.g. shared libraries. This class was moved from resources to here because it + could be used by other modules, e.g. the wheel module. + """ + + def __init__(self, base): + """ + Initialise an instance. + + :param base: The base directory where the cache should be located. + """ + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if not os.path.isdir(base): # pragma: no cover + os.makedirs(base) + if (os.stat(base).st_mode & 0o77) != 0: + logger.warning('Directory \'%s\' is not private', base) + self.base = os.path.abspath(os.path.normpath(base)) + + def prefix_to_dir(self, prefix): + """ + Converts a resource prefix to a directory name in the cache. + """ + return path_to_cache_dir(prefix) + + def clear(self): + """ + Clear the cache. + """ + not_removed = [] + for fn in os.listdir(self.base): + fn = os.path.join(self.base, fn) + try: + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + except Exception: + not_removed.append(fn) + return not_removed + + +class EventMixin(object): + """ + A very simple publish/subscribe system. + """ + def __init__(self): + self._subscribers = {} + + def add(self, event, subscriber, append=True): + """ + Add a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be added (and called when the + event is published). + :param append: Whether to append or prepend the subscriber to an + existing subscriber list for the event. + """ + subs = self._subscribers + if event not in subs: + subs[event] = deque([subscriber]) + else: + sq = subs[event] + if append: + sq.append(subscriber) + else: + sq.appendleft(subscriber) + + def remove(self, event, subscriber): + """ + Remove a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be removed. + """ + subs = self._subscribers + if event not in subs: + raise ValueError('No subscribers: %r' % event) + subs[event].remove(subscriber) + + def get_subscribers(self, event): + """ + Return an iterator for the subscribers for an event. + :param event: The event to return subscribers for. + """ + return iter(self._subscribers.get(event, ())) + + def publish(self, event, *args, **kwargs): + """ + Publish a event and return a list of values returned by its + subscribers. + + :param event: The event to publish. + :param args: The positional arguments to pass to the event's + subscribers. + :param kwargs: The keyword arguments to pass to the event's + subscribers. + """ + result = [] + for subscriber in self.get_subscribers(event): + try: + value = subscriber(event, *args, **kwargs) + except Exception: + logger.exception('Exception during event publication') + value = None + result.append(value) + logger.debug('publish %s: args = %s, kwargs = %s, result = %s', + event, args, kwargs, result) + return result + +# +# Simple sequencing +# +class Sequencer(object): + def __init__(self): + self._preds = {} + self._succs = {} + self._nodes = set() # nodes with no preds/succs + + def add_node(self, node): + self._nodes.add(node) + + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] + + def add(self, pred, succ): + assert pred != succ + self._preds.setdefault(succ, set()).add(pred) + self._succs.setdefault(pred, set()).add(succ) + + def remove(self, pred, succ): + assert pred != succ + try: + preds = self._preds[succ] + succs = self._succs[pred] + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of anything' % succ) + try: + preds.remove(pred) + succs.remove(succ) + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of %r' % (succ, pred)) + + def is_step(self, step): + return (step in self._preds or step in self._succs or + step in self._nodes) + + def get_steps(self, final): + if not self.is_step(final): + raise ValueError('Unknown: %r' % final) + result = [] + todo = [] + seen = set() + todo.append(final) + while todo: + step = todo.pop(0) + if step in seen: + # if a step was already seen, + # move it to the end (so it will appear earlier + # when reversed on return) ... but not for the + # final step, as that would be confusing for + # users + if step != final: + result.remove(step) + result.append(step) + else: + seen.add(step) + result.append(step) + preds = self._preds.get(step, ()) + todo.extend(preds) + return reversed(result) + + @property + def strong_connections(self): + #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + index_counter = [0] + stack = [] + lowlinks = {} + index = {} + result = [] + + graph = self._succs + + def strongconnect(node): + # set the depth index for this node to the smallest unused index + index[node] = index_counter[0] + lowlinks[node] = index_counter[0] + index_counter[0] += 1 + stack.append(node) + + # Consider successors + try: + successors = graph[node] + except Exception: + successors = [] + for successor in successors: + if successor not in lowlinks: + # Successor has not yet been visited + strongconnect(successor) + lowlinks[node] = min(lowlinks[node],lowlinks[successor]) + elif successor in stack: + # the successor is in the stack and hence in the current + # strongly connected component (SCC) + lowlinks[node] = min(lowlinks[node],index[successor]) + + # If `node` is a root node, pop the stack and generate an SCC + if lowlinks[node] == index[node]: + connected_component = [] + + while True: + successor = stack.pop() + connected_component.append(successor) + if successor == node: break + component = tuple(connected_component) + # storing the result + result.append(component) + + for node in graph: + if node not in lowlinks: + strongconnect(node) + + return result + + @property + def dot(self): + result = ['digraph G {'] + for succ in self._preds: + preds = self._preds[succ] + for pred in preds: + result.append(' %s -> %s;' % (pred, succ)) + for node in self._nodes: + result.append(' %s;' % node) + result.append('}') + return '\n'.join(result) + +# +# Unarchiving functionality for zip, tar, tgz, tbz, whl +# + +ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', + '.tgz', '.tbz', '.whl') + +def unarchive(archive_filename, dest_dir, format=None, check=True): + + def check_path(path): + if not isinstance(path, text_type): + path = path.decode('utf-8') + p = os.path.abspath(os.path.join(dest_dir, path)) + if not p.startswith(dest_dir) or p[plen] != os.sep: + raise ValueError('path outside destination: %r' % p) + + dest_dir = os.path.abspath(dest_dir) + plen = len(dest_dir) + archive = None + if format is None: + if archive_filename.endswith(('.zip', '.whl')): + format = 'zip' + elif archive_filename.endswith(('.tar.gz', '.tgz')): + format = 'tgz' + mode = 'r:gz' + elif archive_filename.endswith(('.tar.bz2', '.tbz')): + format = 'tbz' + mode = 'r:bz2' + elif archive_filename.endswith('.tar'): + format = 'tar' + mode = 'r' + else: # pragma: no cover + raise ValueError('Unknown format for %r' % archive_filename) + try: + if format == 'zip': + archive = ZipFile(archive_filename, 'r') + if check: + names = archive.namelist() + for name in names: + check_path(name) + else: + archive = tarfile.open(archive_filename, mode) + if check: + names = archive.getnames() + for name in names: + check_path(name) + if format != 'zip' and sys.version_info[0] < 3: + # See Python issue 17153. If the dest path contains Unicode, + # tarfile extraction fails on Python 2.x if a member path name + # contains non-ASCII characters - it leads to an implicit + # bytes -> unicode conversion using ASCII to decode. + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') + archive.extractall(dest_dir) + + finally: + if archive: + archive.close() + + +def zip_dir(directory): + """zip a directory tree into a BytesIO object""" + result = io.BytesIO() + dlen = len(directory) + with ZipFile(result, "w") as zf: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + rel = root[dlen:] + dest = os.path.join(rel, name) + zf.write(full, dest) + return result + +# +# Simple progress bar +# + +UNITS = ('', 'K', 'M', 'G','T','P') + + +class Progress(object): + unknown = 'UNKNOWN' + + def __init__(self, minval=0, maxval=100): + assert maxval is None or maxval >= minval + self.min = self.cur = minval + self.max = maxval + self.started = None + self.elapsed = 0 + self.done = False + + def update(self, curval): + assert self.min <= curval + assert self.max is None or curval <= self.max + self.cur = curval + now = time.time() + if self.started is None: + self.started = now + else: + self.elapsed = now - self.started + + def increment(self, incr): + assert incr >= 0 + self.update(self.cur + incr) + + def start(self): + self.update(self.min) + return self + + def stop(self): + if self.max is not None: + self.update(self.max) + self.done = True + + @property + def maximum(self): + return self.unknown if self.max is None else self.max + + @property + def percentage(self): + if self.done: + result = '100 %' + elif self.max is None: + result = ' ?? %' + else: + v = 100.0 * (self.cur - self.min) / (self.max - self.min) + result = '%3d %%' % v + return result + + def format_duration(self, duration): + if (duration <= 0) and self.max is None or self.cur == self.min: + result = '??:??:??' + #elif duration < 1: + # result = '--:--:--' + else: + result = time.strftime('%H:%M:%S', time.gmtime(duration)) + return result + + @property + def ETA(self): + if self.done: + prefix = 'Done' + t = self.elapsed + #import pdb; pdb.set_trace() + else: + prefix = 'ETA ' + if self.max is None: + t = -1 + elif self.elapsed == 0 or (self.cur == self.min): + t = 0 + else: + #import pdb; pdb.set_trace() + t = float(self.max - self.min) + t /= self.cur - self.min + t = (t - 1) * self.elapsed + return '%s: %s' % (prefix, self.format_duration(t)) + + @property + def speed(self): + if self.elapsed == 0: + result = 0.0 + else: + result = (self.cur - self.min) / self.elapsed + for unit in UNITS: + if result < 1000: + break + result /= 1000.0 + return '%d %sB/s' % (result, unit) + +# +# Glob functionality +# + +RICH_GLOB = re.compile(r'\{([^}]*)\}') +_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') +_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') + + +def iglob(path_glob): + """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" + if _CHECK_RECURSIVE_GLOB.search(path_glob): + msg = """invalid glob %r: recursive glob "**" must be used alone""" + raise ValueError(msg % path_glob) + if _CHECK_MISMATCH_SET.search(path_glob): + msg = """invalid glob %r: mismatching set marker '{' or '}'""" + raise ValueError(msg % path_glob) + return _iglob(path_glob) + + +def _iglob(path_glob): + rich_path_glob = RICH_GLOB.split(path_glob, 1) + if len(rich_path_glob) > 1: + assert len(rich_path_glob) == 3, rich_path_glob + prefix, set, suffix = rich_path_glob + for item in set.split(','): + for path in _iglob(''.join((prefix, item, suffix))): + yield path + else: + if '**' not in path_glob: + for item in std_iglob(path_glob): + yield item + else: + prefix, radical = path_glob.split('**', 1) + if prefix == '': + prefix = '.' + if radical == '': + radical = '*' + else: + # we support both + radical = radical.lstrip('/') + radical = radical.lstrip('\\') + for path, dir, files in os.walk(prefix): + path = os.path.normpath(path) + for fn in _iglob(os.path.join(path, radical)): + yield fn + +if ssl: + from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, + CertificateError) + + +# +# HTTPSConnection which verifies certificates/matches domains +# + + class HTTPSConnection(httplib.HTTPSConnection): + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None + + # noinspection PyPropertyAccess + def connect(self): + sock = socket.create_connection((self.host, self.port), self.timeout) + if getattr(self, '_tunnel_host', False): + self.sock = sock + self._tunnel() + + if not hasattr(ssl, 'SSLContext'): + # For 2.x + if self.ca_certs: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + cert_reqs=cert_reqs, + ssl_version=ssl.PROTOCOL_SSLv23, + ca_certs=self.ca_certs) + else: # pragma: no cover + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + if hasattr(ssl, 'OP_NO_SSLv2'): + context.options |= ssl.OP_NO_SSLv2 + if self.cert_file: + context.load_cert_chain(self.cert_file, self.key_file) + kwargs = {} + if self.ca_certs: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=self.ca_certs) + if getattr(ssl, 'HAS_SNI', False): + kwargs['server_hostname'] = self.host + self.sock = context.wrap_socket(sock, **kwargs) + if self.ca_certs and self.check_domain: + try: + match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) + except CertificateError: # pragma: no cover + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + class HTTPSHandler(BaseHTTPSHandler): + def __init__(self, ca_certs, check_domain=True): + BaseHTTPSHandler.__init__(self) + self.ca_certs = ca_certs + self.check_domain = check_domain + + def _conn_maker(self, *args, **kwargs): + """ + This is called to create a connection instance. Normally you'd + pass a connection class to do_open, but it doesn't actually check for + a class, and just expects a callable. As long as we behave just as a + constructor would have, we should be OK. If it ever changes so that + we *must* pass a class, we'll create an UnsafeHTTPSConnection class + which just sets check_domain to False in the class definition, and + choose which one to pass to do_open. + """ + result = HTTPSConnection(*args, **kwargs) + if self.ca_certs: + result.ca_certs = self.ca_certs + result.check_domain = self.check_domain + return result + + def https_open(self, req): + try: + return self.do_open(self._conn_maker, req) + except URLError as e: + if 'certificate verify failed' in str(e.reason): + raise CertificateError('Unable to verify server certificate ' + 'for %s' % req.host) + else: + raise + + # + # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- + # Middle proxy using HTTP listens on port 443, or an index mistakenly serves + # HTML containing a http://xyz link when it should be https://xyz), + # you can use the following handler class, which does not allow HTTP traffic. + # + # It works by inheriting from HTTPHandler - so build_opener won't add a + # handler for HTTP itself. + # + class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): + def http_open(self, req): + raise URLError('Unexpected HTTP request on what should be a secure ' + 'connection: %s' % req) + +# +# XML-RPC with timeouts +# + +_ver_info = sys.version_info[:2] + +if _ver_info == (2, 6): + class HTTP(httplib.HTTP): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + + if ssl: + class HTTPS(httplib.HTTPS): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + +class Transport(xmlrpclib.Transport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.Transport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, x509 = self.get_host_info(host) + if _ver_info == (2, 6): + result = HTTP(h, timeout=self.timeout) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPConnection(h) + result = self._connection[1] + return result + +if ssl: + class SafeTransport(xmlrpclib.SafeTransport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.SafeTransport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, kwargs = self.get_host_info(host) + if not kwargs: + kwargs = {} + kwargs['timeout'] = self.timeout + if _ver_info == (2, 6): + result = HTTPS(host, None, **kwargs) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPSConnection(h, None, + **kwargs) + result = self._connection[1] + return result + + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, **kwargs): + self.timeout = timeout = kwargs.pop('timeout', None) + # The above classes only come into play if a timeout + # is specified + if timeout is not None: + scheme, _ = splittype(uri) + use_datetime = kwargs.get('use_datetime', 0) + if scheme == 'https': + tcls = SafeTransport + else: + tcls = Transport + kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) + self.transport = t + xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) + +# +# CSV functionality. This is provided because on 2.x, the csv module can't +# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. +# + +def _csv_open(fn, mode, **kwargs): + if sys.version_info[0] < 3: + mode += 'b' + else: + kwargs['newline'] = '' + # Python 3 determines encoding from locale. Force 'utf-8' + # file encoding to match other forced utf-8 encoding + kwargs['encoding'] = 'utf-8' + return open(fn, mode, **kwargs) + + +class CSVBase(object): + defaults = { + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) + } + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.stream.close() + + +class CSVReader(CSVBase): + def __init__(self, **kwargs): + if 'stream' in kwargs: + stream = kwargs['stream'] + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + self.stream = stream + else: + self.stream = _csv_open(kwargs['path'], 'r') + self.reader = csv.reader(self.stream, **self.defaults) + + def __iter__(self): + return self + + def next(self): + result = next(self.reader) + if sys.version_info[0] < 3: + for i, item in enumerate(result): + if not isinstance(item, text_type): + result[i] = item.decode('utf-8') + return result + + __next__ = next + +class CSVWriter(CSVBase): + def __init__(self, fn, **kwargs): + self.stream = _csv_open(fn, 'w') + self.writer = csv.writer(self.stream, **self.defaults) + + def writerow(self, row): + if sys.version_info[0] < 3: + r = [] + for item in row: + if isinstance(item, text_type): + item = item.encode('utf-8') + r.append(item) + row = r + self.writer.writerow(row) + +# +# Configurator functionality +# + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + + +class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p + + +def normalize_name(name): + """Normalize a python package name a la PEP 503""" + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return re.sub('[-_.]+', '-', name).lower() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/version.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/version.py new file mode 100644 index 00000000..3eebe18e --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/version.py @@ -0,0 +1,736 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Implementation of a flexible versioning scheme providing support for PEP-440, +setuptools-compatible and semantic versioning. +""" + +import logging +import re + +from .compat import string_types +from .util import parse_requirement + +__all__ = ['NormalizedVersion', 'NormalizedMatcher', + 'LegacyVersion', 'LegacyMatcher', + 'SemanticVersion', 'SemanticMatcher', + 'UnsupportedVersionError', 'get_scheme'] + +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): + """This is an unsupported version.""" + pass + + +class Version(object): + def __init__(self, s): + self._string = s = s.strip() + self._parts = parts = self.parse(s) + assert isinstance(parts, tuple) + assert len(parts) > 0 + + def parse(self, s): + raise NotImplementedError('please implement in a subclass') + + def _check_compatible(self, other): + if type(self) != type(other): + raise TypeError('cannot compare %r and %r' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + self._check_compatible(other) + return self._parts < other._parts + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self._parts) + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + @property + def is_prerelease(self): + raise NotImplementedError('Please implement in subclasses.') + + +class Matcher(object): + version_class = None + + # value is either a callable or the name of a method + _operators = { + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + '===': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, + } + + # this is a method only to support alternative implementations + # via overriding + def parse_requirement(self, s): + return parse_requirement(s) + + def __init__(self, s): + if self.version_class is None: + raise ValueError('Please specify a version class') + self._string = s = s.strip() + r = self.parse_requirement(s) + if not r: + raise ValueError('Not valid: %r' % s) + self.name = r.name + self.key = self.name.lower() # for case-insensitive comparisons + clist = [] + if r.constraints: + # import pdb; pdb.set_trace() + for op, s in r.constraints: + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) + self._parts = tuple(clist) + + def match(self, version): + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: String or :class:`Version` instance. + """ + if isinstance(version, string_types): + version = self.version_class(version) + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): + return False + return True + + @property + def exact_version(self): + result = None + if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): + result = self._parts[0][1] + return result + + def _check_compatible(self, other): + if type(self) != type(other) or self.name != other.name: + raise TypeError('cannot compare %s and %s' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self.key == other.key and self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self.key) + hash(self._parts) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + +PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?' + r'(\.(post)(\d+))?(\.(dev)(\d+))?' + r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$') + + +def _pep_440_key(s): + s = s.strip() + m = PEP440_VERSION_RE.match(s) + if not m: + raise UnsupportedVersionError('Not a valid version: %s' % s) + groups = m.groups() + nums = tuple(int(v) for v in groups[1].split('.')) + while len(nums) > 1 and nums[-1] == 0: + nums = nums[:-1] + + if not groups[0]: + epoch = 0 + else: + epoch = int(groups[0]) + pre = groups[4:6] + post = groups[7:9] + dev = groups[10:12] + local = groups[13] + if pre == (None, None): + pre = () + else: + pre = pre[0], int(pre[1]) + if post == (None, None): + post = () + else: + post = post[0], int(post[1]) + if dev == (None, None): + dev = () + else: + dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + parts = [] + for part in local.split('.'): + # to ensure that numeric compares as > lexicographic, avoid + # comparing them directly, but encode a tuple which ensures + # correct sorting + if part.isdigit(): + part = (1, int(part)) + else: + part = (0, part) + parts.append(part) + local = tuple(parts) + if not pre: + # either before pre-release, or final release and after + if not post and dev: + # before pre-release + pre = ('a', -1) # to sort before a0 + else: + pre = ('z',) # to sort after all pre-releases + # now look at the state of post and dev. + if not post: + post = ('_',) # sort before 'a' + if not dev: + dev = ('final',) + + #print('%s -> %s' % (s, m.groups())) + return epoch, nums, pre, post, dev, local + + +_normalized_key = _pep_440_key + + +class NormalizedVersion(Version): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # minimum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP440_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[1].split('.')) + return result + + PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) + + @property + def is_prerelease(self): + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) + + +def _match_prefix(x, y): + x = str(x) + y = str(y) + if x == y: + return True + if not x.startswith(y): + return False + n = len(y) + return x[n] == '.' + + +class NormalizedMatcher(Matcher): + version_class = NormalizedVersion + + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '===': '_match_arbitrary', + '!=': '_match_ne', + } + + def _adjust_local(self, version, constraint, prefix): + if prefix: + strip_local = '+' not in constraint and version._parts[-1] + else: + # both constraint and version are + # NormalizedVersion instances. + # If constraint does not have a local component, + # ensure the version doesn't, either. + strip_local = not constraint._parts[-1] and version._parts[-1] + if strip_local: + s = version._string.split('+', 1)[0] + version = self.version_class(s) + return version, constraint + + def _match_lt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_arbitrary(self, version, constraint, prefix): + return str(version) == str(constraint) + + def _match_ne(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version == constraint: + return True + if version < constraint: + return False +# if not prefix: +# return True + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) + +_REPLACEMENTS = ( + (re.compile('[.+-]$'), ''), # remove trailing puncts + (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start + (re.compile('^[.-]'), ''), # remove leading puncts + (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses + (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha + (re.compile(r'\b(pre-alpha|prealpha)\b'), + 'pre.alpha'), # standardise + (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses +) + +_SUFFIX_REPLACEMENTS = ( + (re.compile('^[:~._+-]+'), ''), # remove leading puncts + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars + (re.compile('[~:+_ -]'), '.'), # replace illegal chars + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\.$'), ''), # trailing '.' +) + +_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') + + +def _suggest_semantic_version(s): + """ + Try to suggest a semantic form for a version for which + _suggest_normalized_version couldn't come up with anything. + """ + result = s.strip().lower() + for pat, repl in _REPLACEMENTS: + result = pat.sub(repl, result) + if not result: + result = '0.0.0' + + # Now look for numeric prefix, and separate it out from + # the rest. + #import pdb; pdb.set_trace() + m = _NUMERIC_PREFIX.match(result) + if not m: + prefix = '0.0.0' + suffix = result + else: + prefix = m.groups()[0].split('.') + prefix = [int(i) for i in prefix] + while len(prefix) < 3: + prefix.append(0) + if len(prefix) == 3: + suffix = result[m.end():] + else: + suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] + prefix = prefix[:3] + prefix = '.'.join([str(i) for i in prefix]) + suffix = suffix.strip() + if suffix: + #import pdb; pdb.set_trace() + # massage the suffix. + for pat, repl in _SUFFIX_REPLACEMENTS: + suffix = pat.sub(repl, suffix) + + if not suffix: + result = prefix + else: + sep = '-' if 'dev' in suffix else '+' + result = prefix + sep + suffix + if not is_semver(result): + result = None + return result + + +def _suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + @param s {str} An irrational version string. + @returns A rational version string, or None, if couldn't determine one. + """ + try: + _normalized_key(s) + return s # already rational + except UnsupportedVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is probably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + #TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.33.post17222 + # 0.9.33-r17222 -> 0.9.33.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.33.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + _normalized_key(rs) + except UnsupportedVersionError: + rs = None + return rs + +# +# Legacy version processing (distribute-compatible) +# + +_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) +_VERSION_REPLACE = { + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', + '': None, + '.': None, +} + + +def _legacy_key(s): + def get_parts(s): + result = [] + for p in _VERSION_PART.split(s.lower()): + p = _VERSION_REPLACE.get(p, p) + if p: + if '0' <= p[:1] <= '9': + p = p.zfill(8) + else: + p = '*' + p + result.append(p) + result.append('*final') + return result + + result = [] + for p in get_parts(s): + if p.startswith('*'): + if p < '*final': + while result and result[-1] == '*final-': + result.pop() + while result and result[-1] == '00000000': + result.pop() + result.append(p) + return tuple(result) + + +class LegacyVersion(Version): + def parse(self, s): + return _legacy_key(s) + + @property + def is_prerelease(self): + result = False + for x in self._parts: + if (isinstance(x, string_types) and x.startswith('*') and + x < '*final'): + result = True + break + return result + + +class LegacyMatcher(Matcher): + version_class = LegacyVersion + + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile(r'^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + +# +# Semantic versioning +# + +_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' + r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' + r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + + +def is_semver(s): + return _SEMVER_RE.match(s) + + +def _semantic_key(s): + def make_tuple(s, absent): + if s is None: + result = (absent,) + else: + parts = s[1:].split('.') + # We can't compare ints and strings on Python 3, so fudge it + # by zero-filling numeric values so simulate a numeric comparison + result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) + return result + + m = is_semver(s) + if not m: + raise UnsupportedVersionError(s) + groups = m.groups() + major, minor, patch = [int(i) for i in groups[:3]] + # choose the '|' and '*' so that versions sort correctly + pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') + return (major, minor, patch), pre, build + + +class SemanticVersion(Version): + def parse(self, s): + return _semantic_key(s) + + @property + def is_prerelease(self): + return self._parts[1][0] != '|' + + +class SemanticMatcher(Matcher): + version_class = SemanticVersion + + +class VersionScheme(object): + def __init__(self, key, matcher, suggester=None): + self.key = key + self.matcher = matcher + self.suggester = suggester + + def is_valid_version(self, s): + try: + self.matcher.version_class(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_matcher(self, s): + try: + self.matcher(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_constraint_list(self, s): + """ + Used for processing some metadata fields + """ + return self.is_valid_matcher('dummy_name (%s)' % s) + + def suggest(self, s): + if self.suggester is None: + result = None + else: + result = self.suggester(s) + return result + +_SCHEMES = { + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), +} + +_SCHEMES['default'] = _SCHEMES['normalized'] + + +def get_scheme(name): + if name not in _SCHEMES: + raise ValueError('unknown scheme name: %r' % name) + return _SCHEMES[name] diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/wheel.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/wheel.py new file mode 100644 index 00000000..bd179383 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distlib/wheel.py @@ -0,0 +1,1004 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import base64 +import codecs +import datetime +import distutils.util +from email import message_from_file +import hashlib +import imp +import json +import logging +import os +import posixpath +import re +import shutil +import sys +import tempfile +import zipfile + +from . import __version__, DistlibException +from .compat import sysconfig, ZipFile, fsdecode, text_type, filter +from .database import InstalledDistribution +from .metadata import Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME +from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, + cached_property, get_cache_base, read_exports, tempdir) +from .version import NormalizedVersion, UnsupportedVersionError + +logger = logging.getLogger(__name__) + +cache = None # created when needed + +if hasattr(sys, 'pypy_version_info'): # pragma: no cover + IMP_PREFIX = 'pp' +elif sys.platform.startswith('java'): # pragma: no cover + IMP_PREFIX = 'jy' +elif sys.platform == 'cli': # pragma: no cover + IMP_PREFIX = 'ip' +else: + IMP_PREFIX = 'cp' + +VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') +if not VER_SUFFIX: # pragma: no cover + VER_SUFFIX = '%s%s' % sys.version_info[:2] +PYVER = 'py' + VER_SUFFIX +IMPVER = IMP_PREFIX + VER_SUFFIX + +ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_') + +ABI = sysconfig.get_config_var('SOABI') +if ABI and ABI.startswith('cpython-'): + ABI = ABI.replace('cpython-', 'cp') +else: + def _derive_abi(): + parts = ['cp', VER_SUFFIX] + if sysconfig.get_config_var('Py_DEBUG'): + parts.append('d') + if sysconfig.get_config_var('WITH_PYMALLOC'): + parts.append('m') + if sysconfig.get_config_var('Py_UNICODE_SIZE') == 4: + parts.append('u') + return ''.join(parts) + ABI = _derive_abi() + del _derive_abi + +FILENAME_RE = re.compile(r''' +(?P[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))? +-(?P\w+\d+(\.\w+\d+)*) +-(?P\w+) +-(?P\w+(\.\w+)*) +\.whl$ +''', re.IGNORECASE | re.VERBOSE) + +NAME_VERSION_RE = re.compile(r''' +(?P[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))?$ +''', re.IGNORECASE | re.VERBOSE) + +SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') +SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') +SHEBANG_PYTHON = b'#!python' +SHEBANG_PYTHONW = b'#!pythonw' + +if os.sep == '/': + to_posix = lambda o: o +else: + to_posix = lambda o: o.replace(os.sep, '/') + + +class Mounter(object): + def __init__(self): + self.impure_wheels = {} + self.libs = {} + + def add(self, pathname, extensions): + self.impure_wheels[pathname] = extensions + self.libs.update(extensions) + + def remove(self, pathname): + extensions = self.impure_wheels.pop(pathname) + for k, v in extensions: + if k in self.libs: + del self.libs[k] + + def find_module(self, fullname, path=None): + if fullname in self.libs: + result = self + else: + result = None + return result + + def load_module(self, fullname): + if fullname in sys.modules: + result = sys.modules[fullname] + else: + if fullname not in self.libs: + raise ImportError('unable to find extension for %s' % fullname) + result = imp.load_dynamic(fullname, self.libs[fullname]) + result.__loader__ = self + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] + return result + +_hook = Mounter() + + +class Wheel(object): + """ + Class to build and install from Wheel files (PEP 427). + """ + + wheel_version = (1, 1) + hash_kind = 'sha256' + + def __init__(self, filename=None, sign=False, verify=False): + """ + Initialise an instance using a (valid) filename. + """ + self.sign = sign + self.should_verify = verify + self.buildver = '' + self.pyver = [PYVER] + self.abi = ['none'] + self.arch = ['any'] + self.dirname = os.getcwd() + if filename is None: + self.name = 'dummy' + self.version = '0.1' + self._filename = self.filename + else: + m = NAME_VERSION_RE.match(filename) + if m: + info = m.groupdict('') + self.name = info['nm'] + # Reinstate the local version separator + self.version = info['vn'].replace('_', '-') + self.buildver = info['bn'] + self._filename = self.filename + else: + dirname, filename = os.path.split(filename) + m = FILENAME_RE.match(filename) + if not m: + raise DistlibException('Invalid name or ' + 'filename: %r' % filename) + if dirname: + self.dirname = os.path.abspath(dirname) + self._filename = filename + info = m.groupdict('') + self.name = info['nm'] + self.version = info['vn'] + self.buildver = info['bn'] + self.pyver = info['py'].split('.') + self.abi = info['bi'].split('.') + self.arch = info['ar'].split('.') + + @property + def filename(self): + """ + Build and return a filename from the various components. + """ + if self.buildver: + buildver = '-' + self.buildver + else: + buildver = '' + pyver = '.'.join(self.pyver) + abi = '.'.join(self.abi) + arch = '.'.join(self.arch) + # replace - with _ as a local version separator + version = self.version.replace('-', '_') + return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, + pyver, abi, arch) + + @property + def exists(self): + path = os.path.join(self.dirname, self.filename) + return os.path.isfile(path) + + @property + def tags(self): + for pyver in self.pyver: + for abi in self.abi: + for arch in self.arch: + yield pyver, abi, arch + + @cached_property + def metadata(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + wrapper = codecs.getreader('utf-8') + with ZipFile(pathname, 'r') as zf: + wheel_metadata = self.get_wheel_metadata(zf) + wv = wheel_metadata['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if file_version < (1, 1): + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, 'METADATA'] + else: + fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME] + result = None + for fn in fns: + try: + metadata_filename = posixpath.join(info_dir, fn) + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + if result: + break + except KeyError: + pass + if not result: + raise ValueError('Invalid wheel, because metadata is ' + 'missing: looked in %s' % ', '.join(fns)) + return result + + def get_wheel_metadata(self, zf): + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + metadata_filename = posixpath.join(info_dir, 'WHEEL') + with zf.open(metadata_filename) as bf: + wf = codecs.getreader('utf-8')(bf) + message = message_from_file(wf) + return dict(message) + + @cached_property + def info(self): + pathname = os.path.join(self.dirname, self.filename) + with ZipFile(pathname, 'r') as zf: + result = self.get_wheel_metadata(zf) + return result + + def process_shebang(self, data): + m = SHEBANG_RE.match(data) + if m: + end = m.end() + shebang, data_after_shebang = data[:end], data[end:] + # Preserve any arguments after the interpreter + if b'pythonw' in shebang.lower(): + shebang_python = SHEBANG_PYTHONW + else: + shebang_python = SHEBANG_PYTHON + m = SHEBANG_DETAIL_RE.match(shebang) + if m: + args = b' ' + m.groups()[-1] + else: + args = b'' + shebang = shebang_python + args + data = shebang + data_after_shebang + else: + cr = data.find(b'\r') + lf = data.find(b'\n') + if cr < 0 or cr > lf: + term = b'\n' + else: + if data[cr:cr + 2] == b'\r\n': + term = b'\r\n' + else: + term = b'\r' + data = SHEBANG_PYTHON + term + data + return data + + def get_hash(self, data, hash_kind=None): + if hash_kind is None: + hash_kind = self.hash_kind + try: + hasher = getattr(hashlib, hash_kind) + except AttributeError: + raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) + result = hasher(data).digest() + result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') + return hash_kind, result + + def write_record(self, records, record_path, base): + records = list(records) # make a copy for sorting + p = to_posix(os.path.relpath(record_path, base)) + records.append((p, '', '')) + records.sort() + with CSVWriter(record_path) as writer: + for row in records: + writer.writerow(row) + + def write_records(self, info, libdir, archive_paths): + records = [] + distinfo, info_dir = info + hasher = getattr(hashlib, self.hash_kind) + for ap, p in archive_paths: + with open(p, 'rb') as f: + data = f.read() + digest = '%s=%s' % self.get_hash(data) + size = os.path.getsize(p) + records.append((ap, digest, size)) + + p = os.path.join(distinfo, 'RECORD') + self.write_record(records, p, libdir) + ap = to_posix(os.path.join(info_dir, 'RECORD')) + archive_paths.append((ap, p)) + + def build_zip(self, pathname, archive_paths): + with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: + for ap, p in archive_paths: + logger.debug('Wrote %s to %s in wheel', p, ap) + zf.write(p, ap) + + def build(self, paths, tags=None, wheel_version=None): + """ + Build a wheel from files in specified paths, and use any specified tags + when determining the name of the wheel. + """ + if tags is None: + tags = {} + + libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] + if libkey == 'platlib': + is_pure = 'false' + default_pyver = [IMPVER] + default_abi = [ABI] + default_arch = [ARCH] + else: + is_pure = 'true' + default_pyver = [PYVER] + default_abi = ['none'] + default_arch = ['any'] + + self.pyver = tags.get('pyver', default_pyver) + self.abi = tags.get('abi', default_abi) + self.arch = tags.get('arch', default_arch) + + libdir = paths[libkey] + + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + archive_paths = [] + + # First, stuff which is not in site-packages + for key in ('data', 'headers', 'scripts'): + if key not in paths: + continue + path = paths[key] + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for fn in files: + p = fsdecode(os.path.join(root, fn)) + rp = os.path.relpath(p, path) + ap = to_posix(os.path.join(data_dir, key, rp)) + archive_paths.append((ap, p)) + if key == 'scripts' and not p.endswith('.exe'): + with open(p, 'rb') as f: + data = f.read() + data = self.process_shebang(data) + with open(p, 'wb') as f: + f.write(data) + + # Now, stuff which is in site-packages, other than the + # distinfo stuff. + path = libdir + distinfo = None + for root, dirs, files in os.walk(path): + if root == path: + # At the top level only, save distinfo for later + # and skip it for now + for i, dn in enumerate(dirs): + dn = fsdecode(dn) + if dn.endswith('.dist-info'): + distinfo = os.path.join(root, dn) + del dirs[i] + break + assert distinfo, '.dist-info directory expected, not found' + + for fn in files: + # comment out next suite to leave .pyc files in + if fsdecode(fn).endswith(('.pyc', '.pyo')): + continue + p = os.path.join(root, fn) + rp = to_posix(os.path.relpath(p, path)) + archive_paths.append((rp, p)) + + # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. + files = os.listdir(distinfo) + for fn in files: + if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): + p = fsdecode(os.path.join(distinfo, fn)) + ap = to_posix(os.path.join(info_dir, fn)) + archive_paths.append((ap, p)) + + wheel_metadata = [ + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, + 'Root-Is-Purelib: %s' % is_pure, + ] + for pyver, abi, arch in self.tags: + wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) + p = os.path.join(distinfo, 'WHEEL') + with open(p, 'w') as f: + f.write('\n'.join(wheel_metadata)) + ap = to_posix(os.path.join(info_dir, 'WHEEL')) + archive_paths.append((ap, p)) + + # Now, at last, RECORD. + # Paths in here are archive paths - nothing else makes sense. + self.write_records((distinfo, info_dir), libdir, archive_paths) + # Now, ready to build the zip file + pathname = os.path.join(self.dirname, self.filename) + self.build_zip(pathname, archive_paths) + return pathname + + def skip_entry(self, arcname): + """ + Determine whether an archive entry should be skipped when verifying + or installing. + """ + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + # We also skip directories, as they won't be in RECORD + # either. See: + # + # https://github.com/pypa/wheel/issues/294 + # https://github.com/pypa/wheel/issues/287 + # https://github.com/pypa/wheel/pull/289 + # + return arcname.endswith(('/', '/RECORD.jws')) + + def install(self, paths, maker, **kwargs): + """ + Install a wheel to the specified paths. If kwarg ``warner`` is + specified, it should be a callable, which will be called with two + tuples indicating the wheel version of this software and the wheel + version in the file, if there is a discrepancy in the versions. + This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. If kwarg ``bytecode_hashed_invalidation`` is True, written + bytecode will try to use file-hash based invalidation (PEP-552) on + supported interpreter versions (CPython 2.7+). + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. + """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if (file_version != self.wheel_version) and warner: + warner(self.wheel_version, file_version) + + if message['Root-Is-Purelib'] == 'true': + libdir = paths['purelib'] + else: + libdir = paths['platlib'] + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') + script_pfx = posixpath.join(data_dir, 'scripts', '') + + # make a new instance rather than a copy of maker's, + # as we mutate it + fileop = FileOperator(dry_run=dry_run) + fileop.record = True # so we can rollback if needed + + bc = not sys.dont_write_bytecode # Double negatives. Lovely! + + outfiles = [] # for RECORD writing + + # for script copying/shebang processing + workdir = tempfile.mkdtemp() + # set target dir later + # we default add_launchers to False, as the + # Python Launcher should be used instead + maker.source_dir = workdir + maker.target_dir = None + try: + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue + is_script = (u_arcname.startswith(script_pfx) + and not u_arcname.endswith('.exe')) + + if u_arcname.startswith(data_pfx): + _, where, rp = u_arcname.split('/', 2) + outfile = os.path.join(paths[where], convert_path(rp)) + else: + # meant for site-packages. + if u_arcname in (wheel_metadata_name, record_name): + continue + outfile = os.path.join(libdir, convert_path(u_arcname)) + if not is_script: + with zf.open(arcname) as bf: + fileop.copy_stream(bf, outfile) + outfiles.append(outfile) + # Double check the digest of the written file + if not dry_run and row[1]: + with open(outfile, 'rb') as bf: + data = bf.read() + _, newdigest = self.get_hash(data, kind) + if newdigest != digest: + raise DistlibException('digest mismatch ' + 'on write for ' + '%s' % outfile) + if bc and outfile.endswith('.py'): + try: + pyc = fileop.byte_compile(outfile, + hashed_invalidation=bc_hashed_invalidation) + outfiles.append(pyc) + except Exception: + # Don't give up if byte-compilation fails, + # but log it and perhaps warn the user + logger.warning('Byte-compilation failed', + exc_info=True) + else: + fn = os.path.basename(convert_path(arcname)) + workname = os.path.join(workdir, fn) + with zf.open(arcname) as bf: + fileop.copy_stream(bf, workname) + + dn, fn = os.path.split(outfile) + maker.target_dir = dn + filenames = maker.make(fn) + fileop.set_executable_mode(filenames) + outfiles.extend(filenames) + + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts + + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' %s' % v.flags + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('extensions') + if commands: + commands = commands.get('python.commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) + + if gui_scripts: + options = {'gui': True } + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], + dry_run) + return dist + except Exception: # pragma: no cover + logger.exception('installation failed.') + fileop.rollback() + raise + finally: + shutil.rmtree(workdir) + + def _get_dylib_cache(self): + global cache + if cache is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('dylib-cache'), + '%s.%s' % sys.version_info[:2]) + cache = Cache(base) + return cache + + def _get_extensions(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + arcname = posixpath.join(info_dir, 'EXTENSIONS') + wrapper = codecs.getreader('utf-8') + result = [] + with ZipFile(pathname, 'r') as zf: + try: + with zf.open(arcname) as bf: + wf = wrapper(bf) + extensions = json.load(wf) + cache = self._get_dylib_cache() + prefix = cache.prefix_to_dir(pathname) + cache_base = os.path.join(cache.base, prefix) + if not os.path.isdir(cache_base): + os.makedirs(cache_base) + for name, relpath in extensions.items(): + dest = os.path.join(cache_base, convert_path(relpath)) + if not os.path.exists(dest): + extract = True + else: + file_time = os.stat(dest).st_mtime + file_time = datetime.datetime.fromtimestamp(file_time) + info = zf.getinfo(relpath) + wheel_time = datetime.datetime(*info.date_time) + extract = wheel_time > file_time + if extract: + zf.extract(relpath, cache_base) + result.append((name, dest)) + except KeyError: + pass + return result + + def is_compatible(self): + """ + Determine if a wheel is compatible with the running system. + """ + return is_compatible(self) + + def is_mountable(self): + """ + Determine if a wheel is asserted as mountable by its metadata. + """ + return True # for now - metadata details TBD + + def mount(self, append=False): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if not self.is_compatible(): + msg = 'Wheel %s not compatible with this Python.' % pathname + raise DistlibException(msg) + if not self.is_mountable(): + msg = 'Wheel %s is marked as not mountable.' % pathname + raise DistlibException(msg) + if pathname in sys.path: + logger.debug('%s already in path', pathname) + else: + if append: + sys.path.append(pathname) + else: + sys.path.insert(0, pathname) + extensions = self._get_extensions() + if extensions: + if _hook not in sys.meta_path: + sys.meta_path.append(_hook) + _hook.add(pathname, extensions) + + def unmount(self): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if pathname not in sys.path: + logger.debug('%s not in path', pathname) + else: + sys.path.remove(pathname) + if pathname in _hook.impure_wheels: + _hook.remove(pathname) + if not _hook.impure_wheels: + if _hook in sys.meta_path: + sys.meta_path.remove(_hook) + + def verify(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + # TODO version verification + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + # See issue #115: some wheels have .. in their entries, but + # in the filename ... e.g. __main__..py ! So the check is + # updated to look for .. in the directory portions + p = u_arcname.split('/') + if '..' in p: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + def update(self, modifier, dest_dir=None, **kwargs): + """ + Update the contents of a wheel in a generic way. The modifier should + be a callable which expects a dictionary argument: its keys are + archive-entry paths, and its values are absolute filesystem paths + where the contents the corresponding archive entries can be found. The + modifier is free to change the contents of the files pointed to, add + new entries and remove entries, before returning. This method will + extract the entire contents of the wheel to a temporary location, call + the modifier, and then use the passed (and possibly updated) + dictionary to write a new wheel. If ``dest_dir`` is specified, the new + wheel is written there -- otherwise, the original wheel is overwritten. + + The modifier should return True if it updated the wheel, else False. + This method returns the same value the modifier returns. + """ + + def get_version(path_map, info_dir): + version = path = None + key = '%s/%s' % (info_dir, METADATA_FILENAME) + if key not in path_map: + key = '%s/PKG-INFO' % info_dir + if key in path_map: + path = path_map[key] + version = Metadata(path=path).version + return version, path + + def update_version(version, path): + updated = None + try: + v = NormalizedVersion(version) + i = version.find('-') + if i < 0: + updated = '%s+1' % version + else: + parts = [int(s) for s in version[i + 1:].split('.')] + parts[-1] += 1 + updated = '%s+%s' % (version[:i], + '.'.join(str(i) for i in parts)) + except UnsupportedVersionError: + logger.debug('Cannot update non-compliant (PEP-440) ' + 'version %r', version) + if updated: + md = Metadata(path=path) + md.version = updated + legacy = not path.endswith(METADATA_FILENAME) + md.write(path=path, legacy=legacy) + logger.debug('Version updated from %r to %r', version, + updated) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + record_name = posixpath.join(info_dir, 'RECORD') + with tempdir() as workdir: + with ZipFile(pathname, 'r') as zf: + path_map = {} + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if u_arcname == record_name: + continue + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + zf.extract(zinfo, workdir) + path = os.path.join(workdir, convert_path(u_arcname)) + path_map[u_arcname] = path + + # Remember the version. + original_version, _ = get_version(path_map, info_dir) + # Files extracted. Call the modifier. + modified = modifier(path_map, **kwargs) + if modified: + # Something changed - need to build a new wheel. + current_version, path = get_version(path_map, info_dir) + if current_version and (current_version == original_version): + # Add or update local version to signify changes. + update_version(current_version, path) + # Decide where the new wheel goes. + if dest_dir is None: + fd, newpath = tempfile.mkstemp(suffix='.whl', + prefix='wheel-update-', + dir=workdir) + os.close(fd) + else: + if not os.path.isdir(dest_dir): + raise DistlibException('Not a directory: %r' % dest_dir) + newpath = os.path.join(dest_dir, self.filename) + archive_paths = list(path_map.items()) + distinfo = os.path.join(workdir, info_dir) + info = distinfo, info_dir + self.write_records(info, workdir, archive_paths) + self.build_zip(newpath, archive_paths) + if dest_dir is None: + shutil.copyfile(newpath, pathname) + return modified + +def compatible_tags(): + """ + Return (pyver, abi, arch) tuples compatible with this Python. + """ + versions = [VER_SUFFIX] + major = VER_SUFFIX[0] + for minor in range(sys.version_info[1] - 1, - 1, -1): + versions.append(''.join([major, str(minor)])) + + abis = [] + for suffix, _, _ in imp.get_suffixes(): + if suffix.startswith('.abi'): + abis.append(suffix.split('.', 2)[1]) + abis.sort() + if ABI != 'none': + abis.insert(0, ABI) + abis.append('none') + result = [] + + arches = [ARCH] + if sys.platform == 'darwin': + m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) + if m: + name, major, minor, arch = m.groups() + minor = int(minor) + matches = [arch] + if arch in ('i386', 'ppc'): + matches.append('fat') + if arch in ('i386', 'ppc', 'x86_64'): + matches.append('fat3') + if arch in ('ppc64', 'x86_64'): + matches.append('fat64') + if arch in ('i386', 'x86_64'): + matches.append('intel') + if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): + matches.append('universal') + while minor >= 0: + for match in matches: + s = '%s_%s_%s_%s' % (name, major, minor, match) + if s != ARCH: # already there + arches.append(s) + minor -= 1 + + # Most specific - our Python version, ABI and arch + for abi in abis: + for arch in arches: + result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) + + # where no ABI / arch dependency, but IMP_PREFIX dependency + for i, version in enumerate(versions): + result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) + if i == 0: + result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) + + # no IMP_PREFIX, ABI or arch dependency + for i, version in enumerate(versions): + result.append((''.join(('py', version)), 'none', 'any')) + if i == 0: + result.append((''.join(('py', version[0])), 'none', 'any')) + return set(result) + + +COMPATIBLE_TAGS = compatible_tags() + +del compatible_tags + + +def is_compatible(wheel, tags=None): + if not isinstance(wheel, Wheel): + wheel = Wheel(wheel) # assume it's a filename + result = False + if tags is None: + tags = COMPATIBLE_TAGS + for ver, abi, arch in tags: + if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: + result = True + break + return result diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/METADATA new file mode 100644 index 00000000..b34cf620 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/METADATA @@ -0,0 +1,170 @@ +Metadata-Version: 2.1 +Name: distro +Version: 1.4.0 +Summary: Distro - an OS platform information API +Home-page: https://github.com/nir0s/distro +Author: Nir Cohen +Author-email: nir36g@gmail.com +License: Apache License, Version 2.0 +Platform: All +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: BSD :: FreeBSD +Classifier: Operating System :: POSIX :: BSD :: NetBSD +Classifier: Operating System :: POSIX :: BSD :: OpenBSD +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Operating System +Description-Content-Type: text/markdown + +Distro - an OS platform information API +======================================= + +[![Build Status](https://travis-ci.org/nir0s/distro.svg?branch=master)](https://travis-ci.org/nir0s/distro) +[![Build status](https://ci.appveyor.com/api/projects/status/e812qjk1gf0f74r5/branch/master?svg=true)](https://ci.appveyor.com/project/nir0s/distro/branch/master) +[![PyPI version](http://img.shields.io/pypi/v/distro.svg)](https://pypi.python.org/pypi/distro) +[![Supported Python Versions](https://img.shields.io/pypi/pyversions/distro.svg)](https://img.shields.io/pypi/pyversions/distro.svg) +[![Requirements Status](https://requires.io/github/nir0s/distro/requirements.svg?branch=master)](https://requires.io/github/nir0s/distro/requirements/?branch=master) +[![Code Coverage](https://codecov.io/github/nir0s/distro/coverage.svg?branch=master)](https://codecov.io/github/nir0s/distro?branch=master) +[![Code Quality](https://landscape.io/github/nir0s/distro/master/landscape.svg?style=flat)](https://landscape.io/github/nir0s/distro) +[![Is Wheel](https://img.shields.io/pypi/wheel/distro.svg?style=flat)](https://pypi.python.org/pypi/distro) +[![Latest Github Release](https://readthedocs.org/projects/distro/badge/?version=stable)](http://distro.readthedocs.io/en/latest/) +[![Join the chat at https://gitter.im/nir0s/distro](https://badges.gitter.im/nir0s/distro.svg)](https://gitter.im/nir0s/distro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +`distro` provides information about the +OS distribution it runs on, such as a reliable machine-readable ID, or +version information. + +It is the recommended replacement for Python's original +[`platform.linux_distribution`](https://docs.python.org/3.7/library/platform.html#platform.linux_distribution) +function (which will be removed in Python 3.8). +It also provides much more functionality which isn't necessarily Python bound, +like a command-line interface. + +Distro currently supports Linux and BSD based systems but [Windows and OS X support](https://github.com/nir0s/distro/issues/177) is also planned. + +For Python 2.6 support, see https://github.com/nir0s/distro/tree/python2.6-support + +## Installation + +Installation of the latest released version from PyPI: + +```shell +pip install distro +``` + +Installation of the latest development version: + +```shell +pip install https://github.com/nir0s/distro/archive/master.tar.gz +``` + + +## Usage + +```bash +$ distro +Name: Antergos Linux +Version: 2015.10 (ISO-Rolling) +Codename: ISO-Rolling + +$ distro -j +{ + "codename": "ISO-Rolling", + "id": "antergos", + "like": "arch", + "version": "16.9", + "version_parts": { + "build_number": "", + "major": "16", + "minor": "9" + } +} + + +$ python +>>> import distro +>>> distro.linux_distribution(full_distribution_name=False) +('centos', '7.1.1503', 'Core') +``` + + +## Documentation + +On top of the aforementioned API, several more functions are available. For a complete description of the +API, see the [latest API documentation](http://distro.readthedocs.org/en/latest/). + +## Background + +An alternative implementation became necessary because Python 3.5 deprecated +this function, and Python 3.8 will remove it altogether. +Its predecessor function `platform.dist` was already deprecated since +Python 2.6 and will also be removed in Python 3.8. +Still, there are many cases in which access to that information is needed. +See [Python issue 1322](https://bugs.python.org/issue1322) for more +information. + +The `distro` package implements a robust and inclusive way of retrieving the +information about a distribution based on new standards and old methods, +namely from these data sources (from high to low precedence): + +* The os-release file `/etc/os-release`, if present. +* The output of the `lsb_release` command, if available. +* The distro release file (`/etc/*(-|_)(release|version)`), if present. +* The `uname` command for BSD based distrubtions. + + +## Python and Distribution Support + +`distro` is supported and tested on Python 2.7, 3.4+ and PyPy and on +any distribution that provides one or more of the data sources +covered. + +This package is tested with test data that mimics the exact behavior of the data sources of [a number of Linux distributions](https://github.com/nir0s/distro/tree/master/tests/resources/distros). + + +## Testing + +```shell +git clone git@github.com:nir0s/distro.git +cd distro +pip install tox +tox +``` + + +## Contributions + +Pull requests are always welcome to deal with specific distributions or just +for general merriment. + +See [CONTRIBUTIONS](https://github.com/nir0s/distro/blob/master/CONTRIBUTING.md) for contribution info. + +Reference implementations for supporting additional distributions and file +formats can be found here: + +* https://github.com/saltstack/salt/blob/develop/salt/grains/core.py#L1172 +* https://github.com/chef/ohai/blob/master/lib/ohai/plugins/linux/platform.rb +* https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts/system/distribution.py +* https://github.com/puppetlabs/facter/blob/master/lib/src/facts/linux/os_linux.cc + +## Package manager distributions + +* https://src.fedoraproject.org/rpms/python-distro +* https://www.archlinux.org/packages/community/any/python-distro/ +* https://launchpad.net/ubuntu/+source/python-distro +* https://packages.debian.org/sid/python-distro +* https://packages.gentoo.org/packages/dev-python/distro +* https://pkgs.org/download/python2-distro +* https://slackbuilds.org/repository/14.2/python/python-distro/ + + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/RECORD b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/RECORD new file mode 100644 index 00000000..0ad02097 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/RECORD @@ -0,0 +1,15 @@ +distro.py,sha256=X2So5kjrRKyMbQJ90Xgy93HU5eFtujCzKaYNeoy1k1c,43251 +distro-1.4.0.dist-info/AUTHORS.txt,sha256=RtqU9KfonVGhI48DAA4-yTOBUhBtQTjFhaDzHoyh7uU,21518 +distro-1.4.0.dist-info/LICENSE.txt,sha256=W6Ifuwlk-TatfRU2LR7W1JMcyMj5_y1NkRkOEJvnRDE,1090 +distro-1.4.0.dist-info/METADATA,sha256=7u13dPkDA9zu5ahg3Ns-H2vfMpR6gBBS55EaBzlXIeg,6648 +distro-1.4.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 +distro-1.4.0.dist-info/entry_points.txt,sha256=mDMyvS_AzB0WhRYe_6xrRkAAET1LwFiDTL5Sx57UFiY,40 +distro-1.4.0.dist-info/top_level.txt,sha256=ikde_V_XEdSBqaGd5tEriN_wzYHLgTX_zVtlsGLHvwQ,7 +distro-1.4.0.dist-info/RECORD,, +distro-1.4.0.dist-info/INSTALLER,, +distro-1.4.0.virtualenv,, +../../../bin/distro3,, +distro-1.4.0.dist-info/__pycache__,, +../../../bin/distro,, +distro.cpython-38.pyc,, +../../../bin/distro-3.8,, \ No newline at end of file diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/WHEEL b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.34.2) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/entry_points.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/entry_points.txt new file mode 100644 index 00000000..dd402399 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +distro = distro:main + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/top_level.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/top_level.txt new file mode 100644 index 00000000..0e093317 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.dist-info/top_level.txt @@ -0,0 +1 @@ +distro diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.virtualenv b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro-1.4.0.virtualenv new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro.py new file mode 100644 index 00000000..33061633 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/distro.py @@ -0,0 +1,1216 @@ +# Copyright 2015,2016,2017 Nir Cohen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +The ``distro`` package (``distro`` stands for Linux Distribution) provides +information about the Linux distribution it runs on, such as a reliable +machine-readable distro ID, or version information. + +It is the recommended replacement for Python's original +:py:func:`platform.linux_distribution` function, but it provides much more +functionality. An alternative implementation became necessary because Python +3.5 deprecated this function, and Python 3.8 will remove it altogether. +Its predecessor function :py:func:`platform.dist` was already +deprecated since Python 2.6 and will also be removed in Python 3.8. +Still, there are many cases in which access to OS distribution information +is needed. See `Python issue 1322 `_ for +more information. +""" + +import os +import re +import sys +import json +import shlex +import logging +import argparse +import subprocess + + +_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc') +_OS_RELEASE_BASENAME = 'os-release' + +#: Translation table for normalizing the "ID" attribute defined in os-release +#: files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as defined in the os-release file, translated to lower case, +#: with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_OS_ID = { + 'ol': 'oracle', # Oracle Enterprise Linux +} + +#: Translation table for normalizing the "Distributor ID" attribute returned by +#: the lsb_release command, for use by the :func:`distro.id` method. +#: +#: * Key: Value as returned by the lsb_release command, translated to lower +#: case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_LSB_ID = { + 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux + 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation + 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server +} + +#: Translation table for normalizing the distro ID derived from the file name +#: of distro release files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as derived from the file name of a distro release file, +#: translated to lower case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_DISTRO_ID = { + 'redhat': 'rhel', # RHEL 6.x, 7.x +} + +# Pattern for content of distro release file (reversed) +_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( + r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)') + +# Pattern for base file name of distro release file +_DISTRO_RELEASE_BASENAME_PATTERN = re.compile( + r'(\w+)[-_](release|version)$') + +# Base file names to be ignored when searching for distro release file +_DISTRO_RELEASE_IGNORE_BASENAMES = ( + 'debian_version', + 'lsb-release', + 'oem-release', + _OS_RELEASE_BASENAME, + 'system-release' +) + + +def linux_distribution(full_distribution_name=True): + """ + Return information about the current OS distribution as a tuple + ``(id_name, version, codename)`` with items as follows: + + * ``id_name``: If *full_distribution_name* is false, the result of + :func:`distro.id`. Otherwise, the result of :func:`distro.name`. + + * ``version``: The result of :func:`distro.version`. + + * ``codename``: The result of :func:`distro.codename`. + + The interface of this function is compatible with the original + :py:func:`platform.linux_distribution` function, supporting a subset of + its parameters. + + The data it returns may not exactly be the same, because it uses more data + sources than the original function, and that may lead to different data if + the OS distribution is not consistent across multiple data sources it + provides (there are indeed such distributions ...). + + Another reason for differences is the fact that the :func:`distro.id` + method normalizes the distro ID string to a reliable machine-readable value + for a number of popular OS distributions. + """ + return _distro.linux_distribution(full_distribution_name) + + +def id(): + """ + Return the distro ID of the current distribution, as a + machine-readable string. + + For a number of OS distributions, the returned distro ID value is + *reliable*, in the sense that it is documented and that it does not change + across releases of the distribution. + + This package maintains the following reliable distro ID values: + + ============== ========================================= + Distro ID Distribution + ============== ========================================= + "ubuntu" Ubuntu + "debian" Debian + "rhel" RedHat Enterprise Linux + "centos" CentOS + "fedora" Fedora + "sles" SUSE Linux Enterprise Server + "opensuse" openSUSE + "amazon" Amazon Linux + "arch" Arch Linux + "cloudlinux" CloudLinux OS + "exherbo" Exherbo Linux + "gentoo" GenToo Linux + "ibm_powerkvm" IBM PowerKVM + "kvmibm" KVM for IBM z Systems + "linuxmint" Linux Mint + "mageia" Mageia + "mandriva" Mandriva Linux + "parallels" Parallels + "pidora" Pidora + "raspbian" Raspbian + "oracle" Oracle Linux (and Oracle Enterprise Linux) + "scientific" Scientific Linux + "slackware" Slackware + "xenserver" XenServer + "openbsd" OpenBSD + "netbsd" NetBSD + "freebsd" FreeBSD + ============== ========================================= + + If you have a need to get distros for reliable IDs added into this set, + or if you find that the :func:`distro.id` function returns a different + distro ID for one of the listed distros, please create an issue in the + `distro issue tracker`_. + + **Lookup hierarchy and transformations:** + + First, the ID is obtained from the following sources, in the specified + order. The first available and non-empty value is used: + + * the value of the "ID" attribute of the os-release file, + + * the value of the "Distributor ID" attribute returned by the lsb_release + command, + + * the first part of the file name of the distro release file, + + The so determined ID value then passes the following transformations, + before it is returned by this method: + + * it is translated to lower case, + + * blanks (which should not be there anyway) are translated to underscores, + + * a normalization of the ID is performed, based upon + `normalization tables`_. The purpose of this normalization is to ensure + that the ID is as reliable as possible, even across incompatible changes + in the OS distributions. A common reason for an incompatible change is + the addition of an os-release file, or the addition of the lsb_release + command, with ID values that differ from what was previously determined + from the distro release file name. + """ + return _distro.id() + + +def name(pretty=False): + """ + Return the name of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the name is returned without version or codename. + (e.g. "CentOS Linux") + + If *pretty* is true, the version and codename are appended. + (e.g. "CentOS Linux 7.1.1503 (Core)") + + **Lookup hierarchy:** + + The name is obtained from the following sources, in the specified order. + The first available and non-empty value is used: + + * If *pretty* is false: + + - the value of the "NAME" attribute of the os-release file, + + - the value of the "Distributor ID" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file. + + * If *pretty* is true: + + - the value of the "PRETTY_NAME" attribute of the os-release file, + + - the value of the "Description" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file, appended + with the value of the pretty version ("" and "" + fields) of the distro release file, if available. + """ + return _distro.name(pretty) + + +def version(pretty=False, best=False): + """ + Return the version of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the version is returned without codename (e.g. + "7.0"). + + If *pretty* is true, the codename in parenthesis is appended, if the + codename is non-empty (e.g. "7.0 (Maipo)"). + + Some distributions provide version numbers with different precisions in + the different sources of distribution information. Examining the different + sources in a fixed priority order does not always yield the most precise + version (e.g. for Debian 8.2, or CentOS 7.1). + + The *best* parameter can be used to control the approach for the returned + version: + + If *best* is false, the first non-empty version number in priority order of + the examined sources is returned. + + If *best* is true, the most precise version number out of all examined + sources is returned. + + **Lookup hierarchy:** + + In all cases, the version number is obtained from the following sources. + If *best* is false, this order represents the priority order: + + * the value of the "VERSION_ID" attribute of the os-release file, + * the value of the "Release" attribute returned by the lsb_release + command, + * the version number parsed from the "" field of the first line + of the distro release file, + * the version number parsed from the "PRETTY_NAME" attribute of the + os-release file, if it follows the format of the distro release files. + * the version number parsed from the "Description" attribute returned by + the lsb_release command, if it follows the format of the distro release + files. + """ + return _distro.version(pretty, best) + + +def version_parts(best=False): + """ + Return the version of the current OS distribution as a tuple + ``(major, minor, build_number)`` with items as follows: + + * ``major``: The result of :func:`distro.major_version`. + + * ``minor``: The result of :func:`distro.minor_version`. + + * ``build_number``: The result of :func:`distro.build_number`. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.version_parts(best) + + +def major_version(best=False): + """ + Return the major version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The major version is the first + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.major_version(best) + + +def minor_version(best=False): + """ + Return the minor version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The minor version is the second + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.minor_version(best) + + +def build_number(best=False): + """ + Return the build number of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The build number is the third part + of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.build_number(best) + + +def like(): + """ + Return a space-separated list of distro IDs of distributions that are + closely related to the current OS distribution in regards to packaging + and programming interfaces, for example distributions the current + distribution is a derivative from. + + **Lookup hierarchy:** + + This information item is only provided by the os-release file. + For details, see the description of the "ID_LIKE" attribute in the + `os-release man page + `_. + """ + return _distro.like() + + +def codename(): + """ + Return the codename for the release of the current OS distribution, + as a string. + + If the distribution does not have a codename, an empty string is returned. + + Note that the returned codename is not always really a codename. For + example, openSUSE returns "x86_64". This function does not handle such + cases in any special way and just returns the string it finds, if any. + + **Lookup hierarchy:** + + * the codename within the "VERSION" attribute of the os-release file, if + provided, + + * the value of the "Codename" attribute returned by the lsb_release + command, + + * the value of the "" field of the distro release file. + """ + return _distro.codename() + + +def info(pretty=False, best=False): + """ + Return certain machine-readable information items about the current OS + distribution in a dictionary, as shown in the following example: + + .. sourcecode:: python + + { + 'id': 'rhel', + 'version': '7.0', + 'version_parts': { + 'major': '7', + 'minor': '0', + 'build_number': '' + }, + 'like': 'fedora', + 'codename': 'Maipo' + } + + The dictionary structure and keys are always the same, regardless of which + information items are available in the underlying data sources. The values + for the various keys are as follows: + + * ``id``: The result of :func:`distro.id`. + + * ``version``: The result of :func:`distro.version`. + + * ``version_parts -> major``: The result of :func:`distro.major_version`. + + * ``version_parts -> minor``: The result of :func:`distro.minor_version`. + + * ``version_parts -> build_number``: The result of + :func:`distro.build_number`. + + * ``like``: The result of :func:`distro.like`. + + * ``codename``: The result of :func:`distro.codename`. + + For a description of the *pretty* and *best* parameters, see the + :func:`distro.version` method. + """ + return _distro.info(pretty, best) + + +def os_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the os-release file data source of the current OS distribution. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_info() + + +def lsb_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the lsb_release command data source of the current OS distribution. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_info() + + +def distro_release_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_info() + + +def uname_info(): + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + """ + return _distro.uname_info() + + +def os_release_attr(attribute): + """ + Return a single named information item from the os-release file data source + of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_attr(attribute) + + +def lsb_release_attr(attribute): + """ + Return a single named information item from the lsb_release command output + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_attr(attribute) + + +def distro_release_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_attr(attribute) + + +def uname_attr(attribute): + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + """ + return _distro.uname_attr(attribute) + + +class cached_property(object): + """A version of @property which caches the value. On access, it calls the + underlying function and sets the value in `__dict__` so future accesses + will not re-call the property. + """ + def __init__(self, f): + self._fname = f.__name__ + self._f = f + + def __get__(self, obj, owner): + assert obj is not None, 'call {} on an instance'.format(self._fname) + ret = obj.__dict__[self._fname] = self._f(obj) + return ret + + +class LinuxDistribution(object): + """ + Provides information about a OS distribution. + + This package creates a private module-global instance of this class with + default initialization arguments, that is used by the + `consolidated accessor functions`_ and `single source accessor functions`_. + By using default initialization arguments, that module-global instance + returns data about the current OS distribution (i.e. the distro this + package runs on). + + Normally, it is not necessary to create additional instances of this class. + However, in situations where control is needed over the exact data sources + that are used, instances of this class can be created with a specific + distro release file, or a specific os-release file, or without invoking the + lsb_release command. + """ + + def __init__(self, + include_lsb=True, + os_release_file='', + distro_release_file='', + include_uname=True): + """ + The initialization method of this class gathers information from the + available data sources, and stores that in private instance attributes. + Subsequent access to the information items uses these private instance + attributes, so that the data sources are read only once. + + Parameters: + + * ``include_lsb`` (bool): Controls whether the + `lsb_release command output`_ is included as a data source. + + If the lsb_release command is not available in the program execution + path, the data source for the lsb_release command will be empty. + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is to be used as a data source. + + An empty string (the default) will cause the default path name to + be used (see `os-release file`_ for details). + + If the specified or defaulted os-release file does not exist, the + data source for the os-release file will be empty. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is to be used as a data source. + + An empty string (the default) will cause a default search algorithm + to be used (see `distro release file`_ for details). + + If the specified distro release file does not exist, or if no default + distro release file can be found, the data source for the distro + release file will be empty. + + * ``include_name`` (bool): Controls whether uname command output is + included as a data source. If the uname command is not available in + the program execution path the data source for the uname command will + be empty. + + Public instance attributes: + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. + This controls whether the lsb information will be loaded. + + * ``include_uname`` (bool): The result of the ``include_uname`` + parameter. This controls whether the uname information will + be loaded. + + Raises: + + * :py:exc:`IOError`: Some I/O issue with an os-release file or distro + release file. + + * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had + some issue (other than not being available in the program execution + path). + + * :py:exc:`UnicodeError`: A data source has unexpected characters or + uses an unexpected encoding. + """ + self.os_release_file = os_release_file or \ + os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME) + self.distro_release_file = distro_release_file or '' # updated later + self.include_lsb = include_lsb + self.include_uname = include_uname + + def __repr__(self): + """Return repr of all info + """ + return \ + "LinuxDistribution(" \ + "os_release_file={self.os_release_file!r}, " \ + "distro_release_file={self.distro_release_file!r}, " \ + "include_lsb={self.include_lsb!r}, " \ + "include_uname={self.include_uname!r}, " \ + "_os_release_info={self._os_release_info!r}, " \ + "_lsb_release_info={self._lsb_release_info!r}, " \ + "_distro_release_info={self._distro_release_info!r}, " \ + "_uname_info={self._uname_info!r})".format( + self=self) + + def linux_distribution(self, full_distribution_name=True): + """ + Return information about the OS distribution that is compatible + with Python's :func:`platform.linux_distribution`, supporting a subset + of its parameters. + + For details, see :func:`distro.linux_distribution`. + """ + return ( + self.name() if full_distribution_name else self.id(), + self.version(), + self.codename() + ) + + def id(self): + """Return the distro ID of the OS distribution, as a string. + + For details, see :func:`distro.id`. + """ + def normalize(distro_id, table): + distro_id = distro_id.lower().replace(' ', '_') + return table.get(distro_id, distro_id) + + distro_id = self.os_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_OS_ID) + + distro_id = self.lsb_release_attr('distributor_id') + if distro_id: + return normalize(distro_id, NORMALIZED_LSB_ID) + + distro_id = self.distro_release_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + distro_id = self.uname_attr('id') + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + return '' + + def name(self, pretty=False): + """ + Return the name of the OS distribution, as a string. + + For details, see :func:`distro.name`. + """ + name = self.os_release_attr('name') \ + or self.lsb_release_attr('distributor_id') \ + or self.distro_release_attr('name') \ + or self.uname_attr('name') + if pretty: + name = self.os_release_attr('pretty_name') \ + or self.lsb_release_attr('description') + if not name: + name = self.distro_release_attr('name') \ + or self.uname_attr('name') + version = self.version(pretty=True) + if version: + name = name + ' ' + version + return name or '' + + def version(self, pretty=False, best=False): + """ + Return the version of the OS distribution, as a string. + + For details, see :func:`distro.version`. + """ + versions = [ + self.os_release_attr('version_id'), + self.lsb_release_attr('release'), + self.distro_release_attr('version_id'), + self._parse_distro_release_content( + self.os_release_attr('pretty_name')).get('version_id', ''), + self._parse_distro_release_content( + self.lsb_release_attr('description')).get('version_id', ''), + self.uname_attr('release') + ] + version = '' + if best: + # This algorithm uses the last version in priority order that has + # the best precision. If the versions are not in conflict, that + # does not matter; otherwise, using the last one instead of the + # first one might be considered a surprise. + for v in versions: + if v.count(".") > version.count(".") or version == '': + version = v + else: + for v in versions: + if v != '': + version = v + break + if pretty and version and self.codename(): + version = u'{0} ({1})'.format(version, self.codename()) + return version + + def version_parts(self, best=False): + """ + Return the version of the OS distribution, as a tuple of version + numbers. + + For details, see :func:`distro.version_parts`. + """ + version_str = self.version(best=best) + if version_str: + version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?') + matches = version_regex.match(version_str) + if matches: + major, minor, build_number = matches.groups() + return major, minor or '', build_number or '' + return '', '', '' + + def major_version(self, best=False): + """ + Return the major version number of the current distribution. + + For details, see :func:`distro.major_version`. + """ + return self.version_parts(best)[0] + + def minor_version(self, best=False): + """ + Return the minor version number of the current distribution. + + For details, see :func:`distro.minor_version`. + """ + return self.version_parts(best)[1] + + def build_number(self, best=False): + """ + Return the build number of the current distribution. + + For details, see :func:`distro.build_number`. + """ + return self.version_parts(best)[2] + + def like(self): + """ + Return the IDs of distributions that are like the OS distribution. + + For details, see :func:`distro.like`. + """ + return self.os_release_attr('id_like') or '' + + def codename(self): + """ + Return the codename of the OS distribution. + + For details, see :func:`distro.codename`. + """ + try: + # Handle os_release specially since distros might purposefully set + # this to empty string to have no codename + return self._os_release_info['codename'] + except KeyError: + return self.lsb_release_attr('codename') \ + or self.distro_release_attr('codename') \ + or '' + + def info(self, pretty=False, best=False): + """ + Return certain machine-readable information about the OS + distribution. + + For details, see :func:`distro.info`. + """ + return dict( + id=self.id(), + version=self.version(pretty, best), + version_parts=dict( + major=self.major_version(best), + minor=self.minor_version(best), + build_number=self.build_number(best) + ), + like=self.like(), + codename=self.codename(), + ) + + def os_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the os-release file data source of the OS distribution. + + For details, see :func:`distro.os_release_info`. + """ + return self._os_release_info + + def lsb_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the lsb_release command data source of the OS + distribution. + + For details, see :func:`distro.lsb_release_info`. + """ + return self._lsb_release_info + + def distro_release_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the distro release file data source of the OS + distribution. + + For details, see :func:`distro.distro_release_info`. + """ + return self._distro_release_info + + def uname_info(self): + """ + Return a dictionary containing key-value pairs for the information + items from the uname command data source of the OS distribution. + + For details, see :func:`distro.uname_info`. + """ + return self._uname_info + + def os_release_attr(self, attribute): + """ + Return a single named information item from the os-release file data + source of the OS distribution. + + For details, see :func:`distro.os_release_attr`. + """ + return self._os_release_info.get(attribute, '') + + def lsb_release_attr(self, attribute): + """ + Return a single named information item from the lsb_release command + output data source of the OS distribution. + + For details, see :func:`distro.lsb_release_attr`. + """ + return self._lsb_release_info.get(attribute, '') + + def distro_release_attr(self, attribute): + """ + Return a single named information item from the distro release file + data source of the OS distribution. + + For details, see :func:`distro.distro_release_attr`. + """ + return self._distro_release_info.get(attribute, '') + + def uname_attr(self, attribute): + """ + Return a single named information item from the uname command + output data source of the OS distribution. + + For details, see :func:`distro.uname_release_attr`. + """ + return self._uname_info.get(attribute, '') + + @cached_property + def _os_release_info(self): + """ + Get the information items from the specified os-release file. + + Returns: + A dictionary containing all information items. + """ + if os.path.isfile(self.os_release_file): + with open(self.os_release_file) as release_file: + return self._parse_os_release_content(release_file) + return {} + + @staticmethod + def _parse_os_release_content(lines): + """ + Parse the lines of an os-release file. + + Parameters: + + * lines: Iterable through the lines in the os-release file. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + lexer = shlex.shlex(lines, posix=True) + lexer.whitespace_split = True + + # The shlex module defines its `wordchars` variable using literals, + # making it dependent on the encoding of the Python source file. + # In Python 2.6 and 2.7, the shlex source file is encoded in + # 'iso-8859-1', and the `wordchars` variable is defined as a byte + # string. This causes a UnicodeDecodeError to be raised when the + # parsed content is a unicode object. The following fix resolves that + # (... but it should be fixed in shlex...): + if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): + lexer.wordchars = lexer.wordchars.decode('iso-8859-1') + + tokens = list(lexer) + for token in tokens: + # At this point, all shell-like parsing has been done (i.e. + # comments processed, quotes and backslash escape sequences + # processed, multi-line values assembled, trailing newlines + # stripped, etc.), so the tokens are now either: + # * variable assignments: var=value + # * commands or their arguments (not allowed in os-release) + if '=' in token: + k, v = token.split('=', 1) + if isinstance(v, bytes): + v = v.decode('utf-8') + props[k.lower()] = v + else: + # Ignore any tokens that are not variable assignments + pass + + if 'version_codename' in props: + # os-release added a version_codename field. Use that in + # preference to anything else Note that some distros purposefully + # do not have code names. They should be setting + # version_codename="" + props['codename'] = props['version_codename'] + elif 'ubuntu_codename' in props: + # Same as above but a non-standard field name used on older Ubuntus + props['codename'] = props['ubuntu_codename'] + elif 'version' in props: + # If there is no version_codename, parse it from the version + codename = re.search(r'(\(\D+\))|,(\s+)?\D+', props['version']) + if codename: + codename = codename.group() + codename = codename.strip('()') + codename = codename.strip(',') + codename = codename.strip() + # codename appears within paranthese. + props['codename'] = codename + + return props + + @cached_property + def _lsb_release_info(self): + """ + Get the information items from the lsb_release command output. + + Returns: + A dictionary containing all information items. + """ + if not self.include_lsb: + return {} + with open(os.devnull, 'w') as devnull: + try: + cmd = ('lsb_release', '-a') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: # Command not found + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_lsb_release_content(content) + + @staticmethod + def _parse_lsb_release_content(lines): + """ + Parse the output of the lsb_release command. + + Parameters: + + * lines: Iterable through the lines of the lsb_release output. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + for line in lines: + kv = line.strip('\n').split(':', 1) + if len(kv) != 2: + # Ignore lines without colon. + continue + k, v = kv + props.update({k.replace(' ', '_').lower(): v.strip()}) + return props + + @cached_property + def _uname_info(self): + with open(os.devnull, 'w') as devnull: + try: + cmd = ('uname', '-rs') + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: + return {} + content = stdout.decode(sys.getfilesystemencoding()).splitlines() + return self._parse_uname_content(content) + + @staticmethod + def _parse_uname_content(lines): + props = {} + match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip()) + if match: + name, version = match.groups() + + # This is to prevent the Linux kernel version from + # appearing as the 'best' version on otherwise + # identifiable distributions. + if name == 'Linux': + return {} + props['id'] = name.lower() + props['name'] = name + props['release'] = version + return props + + @cached_property + def _distro_release_info(self): + """ + Get the information items from the specified distro release file. + + Returns: + A dictionary containing all information items. + """ + if self.distro_release_file: + # If it was specified, we use it and parse what we can, even if + # its file name or content does not match the expected pattern. + distro_info = self._parse_distro_release_file( + self.distro_release_file) + basename = os.path.basename(self.distro_release_file) + # The file name pattern for user-specified distro release files + # is somewhat more tolerant (compared to when searching for the + # file), because we want to use what was specified as best as + # possible. + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if 'name' in distro_info \ + and 'cloudlinux' in distro_info['name'].lower(): + distro_info['id'] = 'cloudlinux' + elif match: + distro_info['id'] = match.group(1) + return distro_info + else: + try: + basenames = os.listdir(_UNIXCONFDIR) + # We sort for repeatability in cases where there are multiple + # distro specific files; e.g. CentOS, Oracle, Enterprise all + # containing `redhat-release` on top of their own. + basenames.sort() + except OSError: + # This may occur when /etc is not readable but we can't be + # sure about the *-release files. Check common entries of + # /etc for information. If they turn out to not be there the + # error is handled in `_parse_distro_release_file()`. + basenames = ['SuSE-release', + 'arch-release', + 'base-release', + 'centos-release', + 'fedora-release', + 'gentoo-release', + 'mageia-release', + 'mandrake-release', + 'mandriva-release', + 'mandrivalinux-release', + 'manjaro-release', + 'oracle-release', + 'redhat-release', + 'sl-release', + 'slackware-version'] + for basename in basenames: + if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: + continue + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + filepath = os.path.join(_UNIXCONFDIR, basename) + distro_info = self._parse_distro_release_file(filepath) + if 'name' in distro_info: + # The name is always present if the pattern matches + self.distro_release_file = filepath + distro_info['id'] = match.group(1) + if 'cloudlinux' in distro_info['name'].lower(): + distro_info['id'] = 'cloudlinux' + return distro_info + return {} + + def _parse_distro_release_file(self, filepath): + """ + Parse a distro release file. + + Parameters: + + * filepath: Path name of the distro release file. + + Returns: + A dictionary containing all information items. + """ + try: + with open(filepath) as fp: + # Only parse the first line. For instance, on SLES there + # are multiple lines. We don't want them... + return self._parse_distro_release_content(fp.readline()) + except (OSError, IOError): + # Ignore not being able to read a specific, seemingly version + # related file. + # See https://github.com/nir0s/distro/issues/162 + return {} + + @staticmethod + def _parse_distro_release_content(line): + """ + Parse a line from a distro release file. + + Parameters: + * line: Line from the distro release file. Must be a unicode string + or a UTF-8 encoded byte string. + + Returns: + A dictionary containing all information items. + """ + if isinstance(line, bytes): + line = line.decode('utf-8') + matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match( + line.strip()[::-1]) + distro_info = {} + if matches: + # regexp ensures non-None + distro_info['name'] = matches.group(3)[::-1] + if matches.group(2): + distro_info['version_id'] = matches.group(2)[::-1] + if matches.group(1): + distro_info['codename'] = matches.group(1)[::-1] + elif line: + distro_info['name'] = line.strip() + return distro_info + + +_distro = LinuxDistribution() + + +def main(): + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + + parser = argparse.ArgumentParser(description="OS distro info tool") + parser.add_argument( + '--json', + '-j', + help="Output in machine readable format", + action="store_true") + args = parser.parse_args() + + if args.json: + logger.info(json.dumps(info(), indent=4, sort_keys=True)) + else: + logger.info('Name: %s', name(pretty=True)) + distribution_version = version(pretty=True) + logger.info('Version: %s', distribution_version) + distribution_codename = codename() + logger.info('Codename: %s', distribution_codename) + + +if __name__ == '__main__': + main() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/easy_install.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/easy_install.py new file mode 100644 index 00000000..d87e9840 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/easy_install.py @@ -0,0 +1,5 @@ +"""Run the EasyInstall command""" + +if __name__ == '__main__': + from setuptools.command.easy_install import main + main() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/__init__.py new file mode 100644 index 00000000..ecd917aa --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/__init__.py @@ -0,0 +1,33 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Copyright 2007 Google Inc. All Rights Reserved. + +__version__ = '3.15.4' diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/any_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/any_pb2.py new file mode 100644 index 00000000..e3b6ad81 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/any_pb2.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/any.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/any.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\010AnyProtoP\001Z,google.golang.org/protobuf/types/known/anypb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x19google/protobuf/any.proto\x12\x0fgoogle.protobuf\"&\n\x03\x41ny\x12\x10\n\x08type_url\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x42v\n\x13\x63om.google.protobufB\x08\x41nyProtoP\x01Z,google.golang.org/protobuf/types/known/anypb\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_ANY = _descriptor.Descriptor( + name='Any', + full_name='google.protobuf.Any', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='type_url', full_name='google.protobuf.Any.type_url', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Any.value', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=46, + serialized_end=84, +) + +DESCRIPTOR.message_types_by_name['Any'] = _ANY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Any = _reflection.GeneratedProtocolMessageType('Any', (_message.Message,), { + 'DESCRIPTOR' : _ANY, + '__module__' : 'google.protobuf.any_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Any) + }) +_sym_db.RegisterMessage(Any) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/api_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/api_pb2.py new file mode 100644 index 00000000..5ecc0649 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/api_pb2.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/api.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import source_context_pb2 as google_dot_protobuf_dot_source__context__pb2 +from google.protobuf import type_pb2 as google_dot_protobuf_dot_type__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/api.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\010ApiProtoP\001Z,google.golang.org/protobuf/types/known/apipb\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x19google/protobuf/api.proto\x12\x0fgoogle.protobuf\x1a$google/protobuf/source_context.proto\x1a\x1agoogle/protobuf/type.proto\"\x81\x02\n\x03\x41pi\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x07methods\x18\x02 \x03(\x0b\x32\x17.google.protobuf.Method\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x36\n\x0esource_context\x18\x05 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12&\n\x06mixins\x18\x06 \x03(\x0b\x32\x16.google.protobuf.Mixin\x12\'\n\x06syntax\x18\x07 \x01(\x0e\x32\x17.google.protobuf.Syntax\"\xd5\x01\n\x06Method\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x18\n\x10request_type_url\x18\x02 \x01(\t\x12\x19\n\x11request_streaming\x18\x03 \x01(\x08\x12\x19\n\x11response_type_url\x18\x04 \x01(\t\x12\x1a\n\x12response_streaming\x18\x05 \x01(\x08\x12(\n\x07options\x18\x06 \x03(\x0b\x32\x17.google.protobuf.Option\x12\'\n\x06syntax\x18\x07 \x01(\x0e\x32\x17.google.protobuf.Syntax\"#\n\x05Mixin\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04root\x18\x02 \x01(\tBv\n\x13\x63om.google.protobufB\x08\x41piProtoP\x01Z,google.golang.org/protobuf/types/known/apipb\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' + , + dependencies=[google_dot_protobuf_dot_source__context__pb2.DESCRIPTOR,google_dot_protobuf_dot_type__pb2.DESCRIPTOR,]) + + + + +_API = _descriptor.Descriptor( + name='Api', + full_name='google.protobuf.Api', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Api.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='methods', full_name='google.protobuf.Api.methods', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Api.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='version', full_name='google.protobuf.Api.version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Api.source_context', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='mixins', full_name='google.protobuf.Api.mixins', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Api.syntax', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=370, +) + + +_METHOD = _descriptor.Descriptor( + name='Method', + full_name='google.protobuf.Method', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Method.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='request_type_url', full_name='google.protobuf.Method.request_type_url', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='request_streaming', full_name='google.protobuf.Method.request_streaming', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='response_type_url', full_name='google.protobuf.Method.response_type_url', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='response_streaming', full_name='google.protobuf.Method.response_streaming', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Method.options', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Method.syntax', index=6, + number=7, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=373, + serialized_end=586, +) + + +_MIXIN = _descriptor.Descriptor( + name='Mixin', + full_name='google.protobuf.Mixin', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Mixin.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='root', full_name='google.protobuf.Mixin.root', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=588, + serialized_end=623, +) + +_API.fields_by_name['methods'].message_type = _METHOD +_API.fields_by_name['options'].message_type = google_dot_protobuf_dot_type__pb2._OPTION +_API.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_API.fields_by_name['mixins'].message_type = _MIXIN +_API.fields_by_name['syntax'].enum_type = google_dot_protobuf_dot_type__pb2._SYNTAX +_METHOD.fields_by_name['options'].message_type = google_dot_protobuf_dot_type__pb2._OPTION +_METHOD.fields_by_name['syntax'].enum_type = google_dot_protobuf_dot_type__pb2._SYNTAX +DESCRIPTOR.message_types_by_name['Api'] = _API +DESCRIPTOR.message_types_by_name['Method'] = _METHOD +DESCRIPTOR.message_types_by_name['Mixin'] = _MIXIN +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Api = _reflection.GeneratedProtocolMessageType('Api', (_message.Message,), { + 'DESCRIPTOR' : _API, + '__module__' : 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Api) + }) +_sym_db.RegisterMessage(Api) + +Method = _reflection.GeneratedProtocolMessageType('Method', (_message.Message,), { + 'DESCRIPTOR' : _METHOD, + '__module__' : 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Method) + }) +_sym_db.RegisterMessage(Method) + +Mixin = _reflection.GeneratedProtocolMessageType('Mixin', (_message.Message,), { + 'DESCRIPTOR' : _MIXIN, + '__module__' : 'google.protobuf.api_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Mixin) + }) +_sym_db.RegisterMessage(Mixin) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/plugin_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/plugin_pb2.py new file mode 100644 index 00000000..ff90d18f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/compiler/plugin_pb2.py @@ -0,0 +1,301 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/compiler/plugin.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/compiler/plugin.proto', + package='google.protobuf.compiler', + syntax='proto2', + serialized_options=b'\n\034com.google.protobuf.compilerB\014PluginProtosZ)google.golang.org/protobuf/types/pluginpb', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n%google/protobuf/compiler/plugin.proto\x12\x18google.protobuf.compiler\x1a google/protobuf/descriptor.proto\"F\n\x07Version\x12\r\n\x05major\x18\x01 \x01(\x05\x12\r\n\x05minor\x18\x02 \x01(\x05\x12\r\n\x05patch\x18\x03 \x01(\x05\x12\x0e\n\x06suffix\x18\x04 \x01(\t\"\xba\x01\n\x14\x43odeGeneratorRequest\x12\x18\n\x10\x66ile_to_generate\x18\x01 \x03(\t\x12\x11\n\tparameter\x18\x02 \x01(\t\x12\x38\n\nproto_file\x18\x0f \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\x12;\n\x10\x63ompiler_version\x18\x03 \x01(\x0b\x32!.google.protobuf.compiler.Version\"\xc1\x02\n\x15\x43odeGeneratorResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\x12\x1a\n\x12supported_features\x18\x02 \x01(\x04\x12\x42\n\x04\x66ile\x18\x0f \x03(\x0b\x32\x34.google.protobuf.compiler.CodeGeneratorResponse.File\x1a\x7f\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\t\x12?\n\x13generated_code_info\x18\x10 \x01(\x0b\x32\".google.protobuf.GeneratedCodeInfo\"8\n\x07\x46\x65\x61ture\x12\x10\n\x0c\x46\x45\x41TURE_NONE\x10\x00\x12\x1b\n\x17\x46\x45\x41TURE_PROTO3_OPTIONAL\x10\x01\x42W\n\x1c\x63om.google.protobuf.compilerB\x0cPluginProtosZ)google.golang.org/protobuf/types/pluginpb' + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + + + +_CODEGENERATORRESPONSE_FEATURE = _descriptor.EnumDescriptor( + name='Feature', + full_name='google.protobuf.compiler.CodeGeneratorResponse.Feature', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='FEATURE_NONE', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='FEATURE_PROTO3_OPTIONAL', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=628, + serialized_end=684, +) +_sym_db.RegisterEnumDescriptor(_CODEGENERATORRESPONSE_FEATURE) + + +_VERSION = _descriptor.Descriptor( + name='Version', + full_name='google.protobuf.compiler.Version', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='major', full_name='google.protobuf.compiler.Version.major', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='minor', full_name='google.protobuf.compiler.Version.minor', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='patch', full_name='google.protobuf.compiler.Version.patch', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='suffix', full_name='google.protobuf.compiler.Version.suffix', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=101, + serialized_end=171, +) + + +_CODEGENERATORREQUEST = _descriptor.Descriptor( + name='CodeGeneratorRequest', + full_name='google.protobuf.compiler.CodeGeneratorRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='file_to_generate', full_name='google.protobuf.compiler.CodeGeneratorRequest.file_to_generate', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='parameter', full_name='google.protobuf.compiler.CodeGeneratorRequest.parameter', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='proto_file', full_name='google.protobuf.compiler.CodeGeneratorRequest.proto_file', index=2, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='compiler_version', full_name='google.protobuf.compiler.CodeGeneratorRequest.compiler_version', index=3, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=174, + serialized_end=360, +) + + +_CODEGENERATORRESPONSE_FILE = _descriptor.Descriptor( + name='File', + full_name='google.protobuf.compiler.CodeGeneratorResponse.File', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='insertion_point', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='content', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.content', index=2, + number=15, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='generated_code_info', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info', index=3, + number=16, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=499, + serialized_end=626, +) + +_CODEGENERATORRESPONSE = _descriptor.Descriptor( + name='CodeGeneratorResponse', + full_name='google.protobuf.compiler.CodeGeneratorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='error', full_name='google.protobuf.compiler.CodeGeneratorResponse.error', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supported_features', full_name='google.protobuf.compiler.CodeGeneratorResponse.supported_features', index=1, + number=2, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.compiler.CodeGeneratorResponse.file', index=2, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_CODEGENERATORRESPONSE_FILE, ], + enum_types=[ + _CODEGENERATORRESPONSE_FEATURE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=363, + serialized_end=684, +) + +_CODEGENERATORREQUEST.fields_by_name['proto_file'].message_type = google_dot_protobuf_dot_descriptor__pb2._FILEDESCRIPTORPROTO +_CODEGENERATORREQUEST.fields_by_name['compiler_version'].message_type = _VERSION +_CODEGENERATORRESPONSE_FILE.fields_by_name['generated_code_info'].message_type = google_dot_protobuf_dot_descriptor__pb2._GENERATEDCODEINFO +_CODEGENERATORRESPONSE_FILE.containing_type = _CODEGENERATORRESPONSE +_CODEGENERATORRESPONSE.fields_by_name['file'].message_type = _CODEGENERATORRESPONSE_FILE +_CODEGENERATORRESPONSE_FEATURE.containing_type = _CODEGENERATORRESPONSE +DESCRIPTOR.message_types_by_name['Version'] = _VERSION +DESCRIPTOR.message_types_by_name['CodeGeneratorRequest'] = _CODEGENERATORREQUEST +DESCRIPTOR.message_types_by_name['CodeGeneratorResponse'] = _CODEGENERATORRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Version = _reflection.GeneratedProtocolMessageType('Version', (_message.Message,), { + 'DESCRIPTOR' : _VERSION, + '__module__' : 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) + }) +_sym_db.RegisterMessage(Version) + +CodeGeneratorRequest = _reflection.GeneratedProtocolMessageType('CodeGeneratorRequest', (_message.Message,), { + 'DESCRIPTOR' : _CODEGENERATORREQUEST, + '__module__' : 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) + }) +_sym_db.RegisterMessage(CodeGeneratorRequest) + +CodeGeneratorResponse = _reflection.GeneratedProtocolMessageType('CodeGeneratorResponse', (_message.Message,), { + + 'File' : _reflection.GeneratedProtocolMessageType('File', (_message.Message,), { + 'DESCRIPTOR' : _CODEGENERATORRESPONSE_FILE, + '__module__' : 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) + }) + , + 'DESCRIPTOR' : _CODEGENERATORRESPONSE, + '__module__' : 'google.protobuf.compiler.plugin_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) + }) +_sym_db.RegisterMessage(CodeGeneratorResponse) +_sym_db.RegisterMessage(CodeGeneratorResponse.File) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor.py new file mode 100644 index 00000000..190b8953 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor.py @@ -0,0 +1,1165 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Descriptors essentially contain exactly the information found in a .proto +file, in types that make this information accessible in Python. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import threading +import warnings +import six + +from google.protobuf.internal import api_implementation + +_USE_C_DESCRIPTORS = False +if api_implementation.Type() == 'cpp': + # Used by MakeDescriptor in cpp mode + import binascii + import os + from google.protobuf.pyext import _message + _USE_C_DESCRIPTORS = True + + +class Error(Exception): + """Base error for this module.""" + + +class TypeTransformationError(Error): + """Error transforming between python proto type and corresponding C++ type.""" + + +if _USE_C_DESCRIPTORS: + # This metaclass allows to override the behavior of code like + # isinstance(my_descriptor, FieldDescriptor) + # and make it return True when the descriptor is an instance of the extension + # type written in C++. + class DescriptorMetaclass(type): + def __instancecheck__(cls, obj): + if super(DescriptorMetaclass, cls).__instancecheck__(obj): + return True + if isinstance(obj, cls._C_DESCRIPTOR_CLASS): + return True + return False +else: + # The standard metaclass; nothing changes. + DescriptorMetaclass = type + + +class _Lock(object): + """Wrapper class of threading.Lock(), which is allowed by 'with'.""" + + def __new__(cls): + self = object.__new__(cls) + self._lock = threading.Lock() # pylint: disable=protected-access + return self + + def __enter__(self): + self._lock.acquire() + + def __exit__(self, exc_type, exc_value, exc_tb): + self._lock.release() + + +_lock = threading.Lock() + + +def _Deprecated(name): + if _Deprecated.count > 0: + _Deprecated.count -= 1 + warnings.warn( + 'Call to deprecated create function %s(). Note: Create unlinked ' + 'descriptors is going to go away. Please use get/find descriptors from ' + 'generated code or query the descriptor_pool.' + % name, + category=DeprecationWarning, stacklevel=3) + + +# Deprecated warnings will print 100 times at most which should be enough for +# users to notice and do not cause timeout. +_Deprecated.count = 100 + + +_internal_create_key = object() + + +class DescriptorBase(six.with_metaclass(DescriptorMetaclass)): + + """Descriptors base class. + + This class is the base of all descriptor classes. It provides common options + related functionality. + + Attributes: + has_options: True if the descriptor has non-default options. Usually it + is not necessary to read this -- just call GetOptions() which will + happily return the default instance. However, it's sometimes useful + for efficiency, and also useful inside the protobuf implementation to + avoid some bootstrapping issues. + """ + + if _USE_C_DESCRIPTORS: + # The class, or tuple of classes, that are considered as "virtual + # subclasses" of this descriptor class. + _C_DESCRIPTOR_CLASS = () + + def __init__(self, options, serialized_options, options_class_name): + """Initialize the descriptor given its options message and the name of the + class of the options message. The name of the class is required in case + the options message is None and has to be created. + """ + self._options = options + self._options_class_name = options_class_name + self._serialized_options = serialized_options + + # Does this descriptor have non-default options? + self.has_options = (options is not None) or (serialized_options is not None) + + def _SetOptions(self, options, options_class_name): + """Sets the descriptor's options + + This function is used in generated proto2 files to update descriptor + options. It must not be used outside proto2. + """ + self._options = options + self._options_class_name = options_class_name + + # Does this descriptor have non-default options? + self.has_options = options is not None + + def GetOptions(self): + """Retrieves descriptor options. + + This method returns the options set or creates the default options for the + descriptor. + """ + if self._options: + return self._options + + from google.protobuf import descriptor_pb2 + try: + options_class = getattr(descriptor_pb2, + self._options_class_name) + except AttributeError: + raise RuntimeError('Unknown options class name %s!' % + (self._options_class_name)) + + with _lock: + if self._serialized_options is None: + self._options = options_class() + else: + self._options = _ParseOptions(options_class(), + self._serialized_options) + + return self._options + + +class _NestedDescriptorBase(DescriptorBase): + """Common class for descriptors that can be nested.""" + + def __init__(self, options, options_class_name, name, full_name, + file, containing_type, serialized_start=None, + serialized_end=None, serialized_options=None): + """Constructor. + + Args: + options: Protocol message options or None + to use default message options. + options_class_name (str): The class name of the above options. + name (str): Name of this protocol message type. + full_name (str): Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + file (FileDescriptor): Reference to file info. + containing_type: if provided, this is a nested descriptor, with this + descriptor as parent, otherwise None. + serialized_start: The start index (inclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_end: The end index (exclusive) in block in the + file.serialized_pb that describes this descriptor. + serialized_options: Protocol message serialized options or None. + """ + super(_NestedDescriptorBase, self).__init__( + options, serialized_options, options_class_name) + + self.name = name + # TODO(falk): Add function to calculate full_name instead of having it in + # memory? + self.full_name = full_name + self.file = file + self.containing_type = containing_type + + self._serialized_start = serialized_start + self._serialized_end = serialized_end + + def CopyToProto(self, proto): + """Copies this to the matching proto in descriptor_pb2. + + Args: + proto: An empty proto instance from descriptor_pb2. + + Raises: + Error: If self couldn't be serialized, due to to few constructor + arguments. + """ + if (self.file is not None and + self._serialized_start is not None and + self._serialized_end is not None): + proto.ParseFromString(self.file.serialized_pb[ + self._serialized_start:self._serialized_end]) + else: + raise Error('Descriptor does not contain serialization.') + + +class Descriptor(_NestedDescriptorBase): + + """Descriptor for a protocol message type. + + Attributes: + name (str): Name of this protocol message type. + full_name (str): Fully-qualified name of this protocol message type, + which will include protocol "package" name and the name of any + enclosing types. + containing_type (Descriptor): Reference to the descriptor of the type + containing us, or None if this is top-level. + fields (list[FieldDescriptor]): Field descriptors for all fields in + this type. + fields_by_number (dict(int, FieldDescriptor)): Same + :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed + by "number" attribute in each FieldDescriptor. + fields_by_name (dict(str, FieldDescriptor)): Same + :class:`FieldDescriptor` objects as in :attr:`fields`, but indexed by + "name" attribute in each :class:`FieldDescriptor`. + nested_types (list[Descriptor]): Descriptor references + for all protocol message types nested within this one. + nested_types_by_name (dict(str, Descriptor)): Same Descriptor + objects as in :attr:`nested_types`, but indexed by "name" attribute + in each Descriptor. + enum_types (list[EnumDescriptor]): :class:`EnumDescriptor` references + for all enums contained within this type. + enum_types_by_name (dict(str, EnumDescriptor)): Same + :class:`EnumDescriptor` objects as in :attr:`enum_types`, but + indexed by "name" attribute in each EnumDescriptor. + enum_values_by_name (dict(str, EnumValueDescriptor)): Dict mapping + from enum value name to :class:`EnumValueDescriptor` for that value. + extensions (list[FieldDescriptor]): All extensions defined directly + within this message type (NOT within a nested type). + extensions_by_name (dict(str, FieldDescriptor)): Same FieldDescriptor + objects as :attr:`extensions`, but indexed by "name" attribute of each + FieldDescriptor. + is_extendable (bool): Does this type define any extension ranges? + oneofs (list[OneofDescriptor]): The list of descriptors for oneof fields + in this message. + oneofs_by_name (dict(str, OneofDescriptor)): Same objects as in + :attr:`oneofs`, but indexed by "name" attribute. + file (FileDescriptor): Reference to file descriptor. + + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.Descriptor + + def __new__( + cls, + name=None, + full_name=None, + filename=None, + containing_type=None, + fields=None, + nested_types=None, + enum_types=None, + extensions=None, + options=None, + serialized_options=None, + is_extendable=True, + extension_ranges=None, + oneofs=None, + file=None, # pylint: disable=redefined-builtin + serialized_start=None, + serialized_end=None, + syntax=None, + create_key=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindMessageTypeByName(full_name) + + # NOTE(tmarek): The file argument redefining a builtin is nothing we can + # fix right now since we don't know how many clients already rely on the + # name of the argument. + def __init__(self, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + serialized_options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, # pylint: disable=redefined-builtin + syntax=None, create_key=None): + """Arguments to __init__() are as described in the description + of Descriptor fields above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + if create_key is not _internal_create_key: + _Deprecated('Descriptor') + + super(Descriptor, self).__init__( + options, 'MessageOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + # We have fields in addition to fields_by_name and fields_by_number, + # so that: + # 1. Clients can index fields by "order in which they're listed." + # 2. Clients can easily iterate over all fields with the terse + # syntax: for f in descriptor.fields: ... + self.fields = fields + for field in self.fields: + field.containing_type = self + self.fields_by_number = dict((f.number, f) for f in fields) + self.fields_by_name = dict((f.name, f) for f in fields) + self._fields_by_camelcase_name = None + + self.nested_types = nested_types + for nested_type in nested_types: + nested_type.containing_type = self + self.nested_types_by_name = dict((t.name, t) for t in nested_types) + + self.enum_types = enum_types + for enum_type in self.enum_types: + enum_type.containing_type = self + self.enum_types_by_name = dict((t.name, t) for t in enum_types) + self.enum_values_by_name = dict( + (v.name, v) for t in enum_types for v in t.values) + + self.extensions = extensions + for extension in self.extensions: + extension.extension_scope = self + self.extensions_by_name = dict((f.name, f) for f in extensions) + self.is_extendable = is_extendable + self.extension_ranges = extension_ranges + self.oneofs = oneofs if oneofs is not None else [] + self.oneofs_by_name = dict((o.name, o) for o in self.oneofs) + for oneof in self.oneofs: + oneof.containing_type = self + self.syntax = syntax or "proto2" + + @property + def fields_by_camelcase_name(self): + """Same FieldDescriptor objects as in :attr:`fields`, but indexed by + :attr:`FieldDescriptor.camelcase_name`. + """ + if self._fields_by_camelcase_name is None: + self._fields_by_camelcase_name = dict( + (f.camelcase_name, f) for f in self.fields) + return self._fields_by_camelcase_name + + def EnumValueName(self, enum, value): + """Returns the string name of an enum value. + + This is just a small helper method to simplify a common operation. + + Args: + enum: string name of the Enum. + value: int, value of the enum. + + Returns: + string name of the enum value. + + Raises: + KeyError if either the Enum doesn't exist or the value is not a valid + value for the enum. + """ + return self.enum_types_by_name[enum].values_by_number[value].name + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.DescriptorProto. + + Args: + proto: An empty descriptor_pb2.DescriptorProto. + """ + # This function is overridden to give a better doc comment. + super(Descriptor, self).CopyToProto(proto) + + +# TODO(robinson): We should have aggressive checking here, +# for example: +# * If you specify a repeated field, you should not be allowed +# to specify a default value. +# * [Other examples here as needed]. +# +# TODO(robinson): for this and other *Descriptor classes, we +# might also want to lock things down aggressively (e.g., +# prevent clients from setting the attributes). Having +# stronger invariants here in general will reduce the number +# of runtime checks we must do in reflection.py... +class FieldDescriptor(DescriptorBase): + + """Descriptor for a single field in a .proto file. + + Attributes: + name (str): Name of this field, exactly as it appears in .proto. + full_name (str): Name of this field, including containing scope. This is + particularly relevant for extensions. + index (int): Dense, 0-indexed index giving the order that this + field textually appears within its message in the .proto file. + number (int): Tag number declared for this field in the .proto file. + + type (int): (One of the TYPE_* constants below) Declared type. + cpp_type (int): (One of the CPPTYPE_* constants below) C++ type used to + represent this field. + + label (int): (One of the LABEL_* constants below) Tells whether this + field is optional, required, or repeated. + has_default_value (bool): True if this field has a default value defined, + otherwise false. + default_value (Varies): Default value of this field. Only + meaningful for non-repeated scalar fields. Repeated fields + should always set this to [], and non-repeated composite + fields should always set this to None. + + containing_type (Descriptor): Descriptor of the protocol message + type that contains this field. Set by the Descriptor constructor + if we're passed into one. + Somewhat confusingly, for extension fields, this is the + descriptor of the EXTENDED message, not the descriptor + of the message containing this field. (See is_extension and + extension_scope below). + message_type (Descriptor): If a composite field, a descriptor + of the message type contained in this field. Otherwise, this is None. + enum_type (EnumDescriptor): If this field contains an enum, a + descriptor of that enum. Otherwise, this is None. + + is_extension: True iff this describes an extension field. + extension_scope (Descriptor): Only meaningful if is_extension is True. + Gives the message that immediately contains this extension field. + Will be None iff we're a top-level (file-level) extension field. + + options (descriptor_pb2.FieldOptions): Protocol message field options or + None to use default field options. + + containing_oneof (OneofDescriptor): If the field is a member of a oneof + union, contains its descriptor. Otherwise, None. + + file (FileDescriptor): Reference to file descriptor. + """ + + # Must be consistent with C++ FieldDescriptor::Type enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + TYPE_DOUBLE = 1 + TYPE_FLOAT = 2 + TYPE_INT64 = 3 + TYPE_UINT64 = 4 + TYPE_INT32 = 5 + TYPE_FIXED64 = 6 + TYPE_FIXED32 = 7 + TYPE_BOOL = 8 + TYPE_STRING = 9 + TYPE_GROUP = 10 + TYPE_MESSAGE = 11 + TYPE_BYTES = 12 + TYPE_UINT32 = 13 + TYPE_ENUM = 14 + TYPE_SFIXED32 = 15 + TYPE_SFIXED64 = 16 + TYPE_SINT32 = 17 + TYPE_SINT64 = 18 + MAX_TYPE = 18 + + # Must be consistent with C++ FieldDescriptor::CppType enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + CPPTYPE_INT32 = 1 + CPPTYPE_INT64 = 2 + CPPTYPE_UINT32 = 3 + CPPTYPE_UINT64 = 4 + CPPTYPE_DOUBLE = 5 + CPPTYPE_FLOAT = 6 + CPPTYPE_BOOL = 7 + CPPTYPE_ENUM = 8 + CPPTYPE_STRING = 9 + CPPTYPE_MESSAGE = 10 + MAX_CPPTYPE = 10 + + _PYTHON_TO_CPP_PROTO_TYPE_MAP = { + TYPE_DOUBLE: CPPTYPE_DOUBLE, + TYPE_FLOAT: CPPTYPE_FLOAT, + TYPE_ENUM: CPPTYPE_ENUM, + TYPE_INT64: CPPTYPE_INT64, + TYPE_SINT64: CPPTYPE_INT64, + TYPE_SFIXED64: CPPTYPE_INT64, + TYPE_UINT64: CPPTYPE_UINT64, + TYPE_FIXED64: CPPTYPE_UINT64, + TYPE_INT32: CPPTYPE_INT32, + TYPE_SFIXED32: CPPTYPE_INT32, + TYPE_SINT32: CPPTYPE_INT32, + TYPE_UINT32: CPPTYPE_UINT32, + TYPE_FIXED32: CPPTYPE_UINT32, + TYPE_BYTES: CPPTYPE_STRING, + TYPE_STRING: CPPTYPE_STRING, + TYPE_BOOL: CPPTYPE_BOOL, + TYPE_MESSAGE: CPPTYPE_MESSAGE, + TYPE_GROUP: CPPTYPE_MESSAGE + } + + # Must be consistent with C++ FieldDescriptor::Label enum in + # descriptor.h. + # + # TODO(robinson): Find a way to eliminate this repetition. + LABEL_OPTIONAL = 1 + LABEL_REQUIRED = 2 + LABEL_REPEATED = 3 + MAX_LABEL = 3 + + # Must be consistent with C++ constants kMaxNumber, kFirstReservedNumber, + # and kLastReservedNumber in descriptor.h + MAX_FIELD_NUMBER = (1 << 29) - 1 + FIRST_RESERVED_FIELD_NUMBER = 19000 + LAST_RESERVED_FIELD_NUMBER = 19999 + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FieldDescriptor + + def __new__(cls, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None, create_key=None): # pylint: disable=redefined-builtin + _message.Message._CheckCalledFromGeneratedFile() + if is_extension: + return _message.default_pool.FindExtensionByName(full_name) + else: + return _message.default_pool.FindFieldByName(full_name) + + def __init__(self, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + serialized_options=None, + has_default_value=True, containing_oneof=None, json_name=None, + file=None, create_key=None): # pylint: disable=redefined-builtin + """The arguments are as described in the description of FieldDescriptor + attributes above. + + Note that containing_type may be None, and may be set later if necessary + (to deal with circular references between message types, for example). + Likewise for extension_scope. + """ + if create_key is not _internal_create_key: + _Deprecated('FieldDescriptor') + + super(FieldDescriptor, self).__init__( + options, serialized_options, 'FieldOptions') + self.name = name + self.full_name = full_name + self.file = file + self._camelcase_name = None + if json_name is None: + self.json_name = _ToJsonName(name) + else: + self.json_name = json_name + self.index = index + self.number = number + self.type = type + self.cpp_type = cpp_type + self.label = label + self.has_default_value = has_default_value + self.default_value = default_value + self.containing_type = containing_type + self.message_type = message_type + self.enum_type = enum_type + self.is_extension = is_extension + self.extension_scope = extension_scope + self.containing_oneof = containing_oneof + if api_implementation.Type() == 'cpp': + if is_extension: + self._cdescriptor = _message.default_pool.FindExtensionByName(full_name) + else: + self._cdescriptor = _message.default_pool.FindFieldByName(full_name) + else: + self._cdescriptor = None + + @property + def camelcase_name(self): + """Camelcase name of this field. + + Returns: + str: the name in CamelCase. + """ + if self._camelcase_name is None: + self._camelcase_name = _ToCamelCase(self.name) + return self._camelcase_name + + @staticmethod + def ProtoTypeToCppProtoType(proto_type): + """Converts from a Python proto type to a C++ Proto Type. + + The Python ProtocolBuffer classes specify both the 'Python' datatype and the + 'C++' datatype - and they're not the same. This helper method should + translate from one to another. + + Args: + proto_type: the Python proto type (descriptor.FieldDescriptor.TYPE_*) + Returns: + int: descriptor.FieldDescriptor.CPPTYPE_*, the C++ type. + Raises: + TypeTransformationError: when the Python proto type isn't known. + """ + try: + return FieldDescriptor._PYTHON_TO_CPP_PROTO_TYPE_MAP[proto_type] + except KeyError: + raise TypeTransformationError('Unknown proto_type: %s' % proto_type) + + +class EnumDescriptor(_NestedDescriptorBase): + + """Descriptor for an enum defined in a .proto file. + + Attributes: + name (str): Name of the enum type. + full_name (str): Full name of the type, including package name + and any enclosing type(s). + + values (list[EnumValueDescriptors]): List of the values + in this enum. + values_by_name (dict(str, EnumValueDescriptor)): Same as :attr:`values`, + but indexed by the "name" field of each EnumValueDescriptor. + values_by_number (dict(int, EnumValueDescriptor)): Same as :attr:`values`, + but indexed by the "number" field of each EnumValueDescriptor. + containing_type (Descriptor): Descriptor of the immediate containing + type of this enum, or None if this is an enum defined at the + top level in a .proto file. Set by Descriptor's constructor + if we're passed into one. + file (FileDescriptor): Reference to file descriptor. + options (descriptor_pb2.EnumOptions): Enum options message or + None to use default enum options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumDescriptor + + def __new__(cls, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindEnumTypeByName(full_name) + + def __init__(self, name, full_name, filename, values, + containing_type=None, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): + """Arguments are as described in the attribute description above. + + Note that filename is an obsolete argument, that is not used anymore. + Please use file.name to access this as an attribute. + """ + if create_key is not _internal_create_key: + _Deprecated('EnumDescriptor') + + super(EnumDescriptor, self).__init__( + options, 'EnumOptions', name, full_name, file, + containing_type, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + + self.values = values + for value in self.values: + value.type = self + self.values_by_name = dict((v.name, v) for v in values) + # Values are reversed to ensure that the first alias is retained. + self.values_by_number = dict((v.number, v) for v in reversed(values)) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.EnumDescriptorProto. + + Args: + proto (descriptor_pb2.EnumDescriptorProto): An empty descriptor proto. + """ + # This function is overridden to give a better doc comment. + super(EnumDescriptor, self).CopyToProto(proto) + + +class EnumValueDescriptor(DescriptorBase): + + """Descriptor for a single value within an enum. + + Attributes: + name (str): Name of this value. + index (int): Dense, 0-indexed index giving the order that this + value appears textually within its enum in the .proto file. + number (int): Actual number assigned to this enum value. + type (EnumDescriptor): :class:`EnumDescriptor` to which this value + belongs. Set by :class:`EnumDescriptor`'s constructor if we're + passed into one. + options (descriptor_pb2.EnumValueOptions): Enum value options message or + None to use default enum value options options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor + + def __new__(cls, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None, create_key=None): + _message.Message._CheckCalledFromGeneratedFile() + # There is no way we can build a complete EnumValueDescriptor with the + # given parameters (the name of the Enum is not known, for example). + # Fortunately generated files just pass it to the EnumDescriptor() + # constructor, which will ignore it, so returning None is good enough. + return None + + def __init__(self, name, index, number, + type=None, # pylint: disable=redefined-builtin + options=None, serialized_options=None, create_key=None): + """Arguments are as described in the attribute description above.""" + if create_key is not _internal_create_key: + _Deprecated('EnumValueDescriptor') + + super(EnumValueDescriptor, self).__init__( + options, serialized_options, 'EnumValueOptions') + self.name = name + self.index = index + self.number = number + self.type = type + + +class OneofDescriptor(DescriptorBase): + """Descriptor for a oneof field. + + Attributes: + name (str): Name of the oneof field. + full_name (str): Full name of the oneof field, including package name. + index (int): 0-based index giving the order of the oneof field inside + its containing type. + containing_type (Descriptor): :class:`Descriptor` of the protocol message + type that contains this field. Set by the :class:`Descriptor` constructor + if we're passed into one. + fields (list[FieldDescriptor]): The list of field descriptors this + oneof can contain. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.OneofDescriptor + + def __new__( + cls, name, full_name, index, containing_type, fields, options=None, + serialized_options=None, create_key=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.default_pool.FindOneofByName(full_name) + + def __init__( + self, name, full_name, index, containing_type, fields, options=None, + serialized_options=None, create_key=None): + """Arguments are as described in the attribute description above.""" + if create_key is not _internal_create_key: + _Deprecated('OneofDescriptor') + + super(OneofDescriptor, self).__init__( + options, serialized_options, 'OneofOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_type = containing_type + self.fields = fields + + +class ServiceDescriptor(_NestedDescriptorBase): + + """Descriptor for a service. + + Attributes: + name (str): Name of the service. + full_name (str): Full name of the service, including package name. + index (int): 0-indexed index giving the order that this services + definition appears within the .proto file. + methods (list[MethodDescriptor]): List of methods provided by this + service. + methods_by_name (dict(str, MethodDescriptor)): Same + :class:`MethodDescriptor` objects as in :attr:`methods_by_name`, but + indexed by "name" attribute in each :class:`MethodDescriptor`. + options (descriptor_pb2.ServiceOptions): Service options message or + None to use default service options. + file (FileDescriptor): Reference to file info. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.ServiceDescriptor + + def __new__( + cls, + name=None, + full_name=None, + index=None, + methods=None, + options=None, + serialized_options=None, + file=None, # pylint: disable=redefined-builtin + serialized_start=None, + serialized_end=None, + create_key=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindServiceByName(full_name) + + def __init__(self, name, full_name, index, methods, options=None, + serialized_options=None, file=None, # pylint: disable=redefined-builtin + serialized_start=None, serialized_end=None, create_key=None): + if create_key is not _internal_create_key: + _Deprecated('ServiceDescriptor') + + super(ServiceDescriptor, self).__init__( + options, 'ServiceOptions', name, full_name, file, + None, serialized_start=serialized_start, + serialized_end=serialized_end, serialized_options=serialized_options) + self.index = index + self.methods = methods + self.methods_by_name = dict((m.name, m) for m in methods) + # Set the containing service for each method in this service. + for method in self.methods: + method.containing_service = self + + def FindMethodByName(self, name): + """Searches for the specified method, and returns its descriptor. + + Args: + name (str): Name of the method. + Returns: + MethodDescriptor or None: the descriptor for the requested method, if + found. + """ + return self.methods_by_name.get(name, None) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.ServiceDescriptorProto. + + Args: + proto (descriptor_pb2.ServiceDescriptorProto): An empty descriptor proto. + """ + # This function is overridden to give a better doc comment. + super(ServiceDescriptor, self).CopyToProto(proto) + + +class MethodDescriptor(DescriptorBase): + + """Descriptor for a method in a service. + + Attributes: + name (str): Name of the method within the service. + full_name (str): Full name of method. + index (int): 0-indexed index of the method inside the service. + containing_service (ServiceDescriptor): The service that contains this + method. + input_type (Descriptor): The descriptor of the message that this method + accepts. + output_type (Descriptor): The descriptor of the message that this method + returns. + options (descriptor_pb2.MethodOptions or None): Method options message, or + None to use default method options. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.MethodDescriptor + + def __new__(cls, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None, + create_key=None): + _message.Message._CheckCalledFromGeneratedFile() # pylint: disable=protected-access + return _message.default_pool.FindMethodByName(full_name) + + def __init__(self, name, full_name, index, containing_service, + input_type, output_type, options=None, serialized_options=None, + create_key=None): + """The arguments are as described in the description of MethodDescriptor + attributes above. + + Note that containing_service may be None, and may be set later if necessary. + """ + if create_key is not _internal_create_key: + _Deprecated('MethodDescriptor') + + super(MethodDescriptor, self).__init__( + options, serialized_options, 'MethodOptions') + self.name = name + self.full_name = full_name + self.index = index + self.containing_service = containing_service + self.input_type = input_type + self.output_type = output_type + + +class FileDescriptor(DescriptorBase): + """Descriptor for a file. Mimics the descriptor_pb2.FileDescriptorProto. + + Note that :attr:`enum_types_by_name`, :attr:`extensions_by_name`, and + :attr:`dependencies` fields are only set by the + :py:mod:`google.protobuf.message_factory` module, and not by the generated + proto code. + + Attributes: + name (str): Name of file, relative to root of source tree. + package (str): Name of the package + syntax (str): string indicating syntax of the file (can be "proto2" or + "proto3") + serialized_pb (bytes): Byte string of serialized + :class:`descriptor_pb2.FileDescriptorProto`. + dependencies (list[FileDescriptor]): List of other :class:`FileDescriptor` + objects this :class:`FileDescriptor` depends on. + public_dependencies (list[FileDescriptor]): A subset of + :attr:`dependencies`, which were declared as "public". + message_types_by_name (dict(str, Descriptor)): Mapping from message names + to their :class:`Desctiptor`. + enum_types_by_name (dict(str, EnumDescriptor)): Mapping from enum names to + their :class:`EnumDescriptor`. + extensions_by_name (dict(str, FieldDescriptor)): Mapping from extension + names declared at file scope to their :class:`FieldDescriptor`. + services_by_name (dict(str, ServiceDescriptor)): Mapping from services' + names to their :class:`ServiceDescriptor`. + pool (DescriptorPool): The pool this descriptor belongs to. When not + passed to the constructor, the global default pool is used. + """ + + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FileDescriptor + + def __new__(cls, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None, create_key=None): + # FileDescriptor() is called from various places, not only from generated + # files, to register dynamic proto files and messages. + # pylint: disable=g-explicit-bool-comparison + if serialized_pb == b'': + # Cpp generated code must be linked in if serialized_pb is '' + try: + return _message.default_pool.FindFileByName(name) + except KeyError: + raise RuntimeError('Please link in cpp generated lib for %s' % (name)) + elif serialized_pb: + return _message.default_pool.AddSerializedFile(serialized_pb) + else: + return super(FileDescriptor, cls).__new__(cls) + + def __init__(self, name, package, options=None, + serialized_options=None, serialized_pb=None, + dependencies=None, public_dependencies=None, + syntax=None, pool=None, create_key=None): + """Constructor.""" + if create_key is not _internal_create_key: + _Deprecated('FileDescriptor') + + super(FileDescriptor, self).__init__( + options, serialized_options, 'FileOptions') + + if pool is None: + from google.protobuf import descriptor_pool + pool = descriptor_pool.Default() + self.pool = pool + self.message_types_by_name = {} + self.name = name + self.package = package + self.syntax = syntax or "proto2" + self.serialized_pb = serialized_pb + + self.enum_types_by_name = {} + self.extensions_by_name = {} + self.services_by_name = {} + self.dependencies = (dependencies or []) + self.public_dependencies = (public_dependencies or []) + + def CopyToProto(self, proto): + """Copies this to a descriptor_pb2.FileDescriptorProto. + + Args: + proto: An empty descriptor_pb2.FileDescriptorProto. + """ + proto.ParseFromString(self.serialized_pb) + + +def _ParseOptions(message, string): + """Parses serialized options. + + This helper function is used to parse serialized options in generated + proto2 files. It must not be used outside proto2. + """ + message.ParseFromString(string) + return message + + +def _ToCamelCase(name): + """Converts name to camel-case and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + if result: + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + # Lower-case the first letter. + if result and result[0].isupper(): + result[0] = result[0].lower() + return ''.join(result) + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _ToJsonName(name): + """Converts name to Json name and returns it.""" + capitalize_next = False + result = [] + + for c in name: + if c == '_': + capitalize_next = True + elif capitalize_next: + result.append(c.upper()) + capitalize_next = False + else: + result += c + + return ''.join(result) + + +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, + syntax=None): + """Make a protobuf Descriptor given a DescriptorProto protobuf. + + Handles nested descriptors. Note that this is limited to the scope of defining + a message inside of another message. Composite fields can currently only be + resolved if the message is defined in the same scope as the field. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: Optional package name for the new message Descriptor (string). + build_file_if_cpp: Update the C++ descriptor pool if api matches. + Set to False on recursion, so no duplicates are created. + syntax: The syntax/semantics that should be used. Set to "proto3" to get + proto3 field presence semantics. + Returns: + A Descriptor for protobuf messages. + """ + if api_implementation.Type() == 'cpp' and build_file_if_cpp: + # The C++ implementation requires all descriptors to be backed by the same + # definition in the C++ descriptor pool. To do this, we build a + # FileDescriptorProto with the same definition as this descriptor and build + # it into the pool. + from google.protobuf import descriptor_pb2 + file_descriptor_proto = descriptor_pb2.FileDescriptorProto() + file_descriptor_proto.message_type.add().MergeFrom(desc_proto) + + # Generate a random name for this proto file to prevent conflicts with any + # imported ones. We need to specify a file name so the descriptor pool + # accepts our FileDescriptorProto, but it is not important what that file + # name is actually set to. + proto_name = binascii.hexlify(os.urandom(16)).decode('ascii') + + if package: + file_descriptor_proto.name = os.path.join(package.replace('.', '/'), + proto_name + '.proto') + file_descriptor_proto.package = package + else: + file_descriptor_proto.name = proto_name + '.proto' + + _message.default_pool.Add(file_descriptor_proto) + result = _message.default_pool.FindFileByName(file_descriptor_proto.name) + + if _USE_C_DESCRIPTORS: + return result.message_types_by_name[desc_proto.name] + + full_message_name = [desc_proto.name] + if package: full_message_name.insert(0, package) + + # Create Descriptors for enum types + enum_types = {} + for enum_proto in desc_proto.enum_type: + full_name = '.'.join(full_message_name + [enum_proto.name]) + enum_desc = EnumDescriptor( + enum_proto.name, full_name, None, [ + EnumValueDescriptor(enum_val.name, ii, enum_val.number, + create_key=_internal_create_key) + for ii, enum_val in enumerate(enum_proto.value)], + create_key=_internal_create_key) + enum_types[full_name] = enum_desc + + # Create Descriptors for nested types + nested_types = {} + for nested_proto in desc_proto.nested_type: + full_name = '.'.join(full_message_name + [nested_proto.name]) + # Nested types are just those defined inside of the message, not all types + # used by fields in the message, so no loops are possible here. + nested_desc = MakeDescriptor(nested_proto, + package='.'.join(full_message_name), + build_file_if_cpp=False, + syntax=syntax) + nested_types[full_name] = nested_desc + + fields = [] + for field_proto in desc_proto.field: + full_name = '.'.join(full_message_name + [field_proto.name]) + enum_desc = None + nested_desc = None + if field_proto.json_name: + json_name = field_proto.json_name + else: + json_name = None + if field_proto.HasField('type_name'): + type_name = field_proto.type_name + full_type_name = '.'.join(full_message_name + + [type_name[type_name.rfind('.')+1:]]) + if full_type_name in nested_types: + nested_desc = nested_types[full_type_name] + elif full_type_name in enum_types: + enum_desc = enum_types[full_type_name] + # Else type_name references a non-local type, which isn't implemented + field = FieldDescriptor( + field_proto.name, full_name, field_proto.number - 1, + field_proto.number, field_proto.type, + FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type), + field_proto.label, None, nested_desc, enum_desc, None, False, None, + options=_OptionsOrNone(field_proto), has_default_value=False, + json_name=json_name, create_key=_internal_create_key) + fields.append(field) + + desc_name = '.'.join(full_message_name) + return Descriptor(desc_proto.name, desc_name, None, None, fields, + list(nested_types.values()), list(enum_types.values()), [], + options=_OptionsOrNone(desc_proto), + create_key=_internal_create_key) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_database.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_database.py new file mode 100644 index 00000000..073eddc7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_database.py @@ -0,0 +1,177 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides a container for DescriptorProtos.""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import warnings + + +class Error(Exception): + pass + + +class DescriptorDatabaseConflictingDefinitionError(Error): + """Raised when a proto is added with the same name & different descriptor.""" + + +class DescriptorDatabase(object): + """A container accepting FileDescriptorProtos and maps DescriptorProtos.""" + + def __init__(self): + self._file_desc_protos_by_file = {} + self._file_desc_protos_by_symbol = {} + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this database. + + Args: + file_desc_proto: The FileDescriptorProto to add. + Raises: + DescriptorDatabaseConflictingDefinitionError: if an attempt is made to + add a proto with the same name but different definition than an + existing proto in the database. + """ + proto_name = file_desc_proto.name + if proto_name not in self._file_desc_protos_by_file: + self._file_desc_protos_by_file[proto_name] = file_desc_proto + elif self._file_desc_protos_by_file[proto_name] != file_desc_proto: + raise DescriptorDatabaseConflictingDefinitionError( + '%s already added, but with different descriptor.' % proto_name) + else: + return + + # Add all the top-level descriptors to the index. + package = file_desc_proto.package + for message in file_desc_proto.message_type: + for name in _ExtractSymbols(message, package): + self._AddSymbol(name, file_desc_proto) + for enum in file_desc_proto.enum_type: + self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + for enum_value in enum.value: + self._file_desc_protos_by_symbol[ + '.'.join((package, enum_value.name))] = file_desc_proto + for extension in file_desc_proto.extension: + self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + for service in file_desc_proto.service: + self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) + + def FindFileByName(self, name): + """Finds the file descriptor proto by file name. + + Typically the file name is a relative path ending to a .proto file. The + proto with the given name will have to have been added to this database + using the Add method or else an error will be raised. + + Args: + name: The file name to find. + + Returns: + The file descriptor proto matching the name. + + Raises: + KeyError if no file by the given name was added. + """ + + return self._file_desc_protos_by_file[name] + + def FindFileContainingSymbol(self, symbol): + """Finds the file descriptor proto containing the specified symbol. + + The symbol should be a fully qualified name including the file descriptor's + package and any containing messages. Some examples: + + 'some.package.name.Message' + 'some.package.name.Message.NestedEnum' + 'some.package.name.Message.some_field' + + The file descriptor proto containing the specified symbol must be added to + this database using the Add method or else an error will be raised. + + Args: + symbol: The fully qualified symbol name. + + Returns: + The file descriptor proto containing the symbol. + + Raises: + KeyError if no file contains the specified symbol. + """ + try: + return self._file_desc_protos_by_symbol[symbol] + except KeyError: + # Fields, enum values, and nested extensions are not in + # _file_desc_protos_by_symbol. Try to find the top level + # descriptor. Non-existent nested symbol under a valid top level + # descriptor can also be found. The behavior is the same with + # protobuf C++. + top_level, _, _ = symbol.rpartition('.') + try: + return self._file_desc_protos_by_symbol[top_level] + except KeyError: + # Raise the original symbol as a KeyError for better diagnostics. + raise KeyError(symbol) + + def FindFileContainingExtension(self, extendee_name, extension_number): + # TODO(jieluo): implement this API. + return None + + def FindAllExtensionNumbers(self, extendee_name): + # TODO(jieluo): implement this API. + return [] + + def _AddSymbol(self, name, file_desc_proto): + if name in self._file_desc_protos_by_symbol: + warn_msg = ('Conflict register for file "' + file_desc_proto.name + + '": ' + name + + ' is already defined in file "' + + self._file_desc_protos_by_symbol[name].name + '"') + warnings.warn(warn_msg, RuntimeWarning) + self._file_desc_protos_by_symbol[name] = file_desc_proto + + +def _ExtractSymbols(desc_proto, package): + """Pulls out all the symbols from a descriptor proto. + + Args: + desc_proto: The proto to extract symbols from. + package: The package containing the descriptor type. + + Yields: + The fully qualified name found in the descriptor. + """ + message_name = package + '.' + desc_proto.name if package else desc_proto.name + yield message_name + for nested_type in desc_proto.nested_type: + for symbol in _ExtractSymbols(nested_type, message_name): + yield symbol + for enum_type in desc_proto.enum_type: + yield '.'.join((message_name, enum_type.name)) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pb2.py new file mode 100644 index 00000000..0de963f8 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pb2.py @@ -0,0 +1,2106 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/descriptor.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/descriptor.proto', + package='google.protobuf', + syntax='proto2', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n google/protobuf/descriptor.proto\x12\x0fgoogle.protobuf\"G\n\x11\x46ileDescriptorSet\x12\x32\n\x04\x66ile\x18\x01 \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xdb\x03\n\x13\x46ileDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07package\x18\x02 \x01(\t\x12\x12\n\ndependency\x18\x03 \x03(\t\x12\x19\n\x11public_dependency\x18\n \x03(\x05\x12\x17\n\x0fweak_dependency\x18\x0b \x03(\x05\x12\x36\n\x0cmessage_type\x18\x04 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x05 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12\x38\n\x07service\x18\x06 \x03(\x0b\x32\'.google.protobuf.ServiceDescriptorProto\x12\x38\n\textension\x18\x07 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12-\n\x07options\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.FileOptions\x12\x39\n\x10source_code_info\x18\t \x01(\x0b\x32\x1f.google.protobuf.SourceCodeInfo\x12\x0e\n\x06syntax\x18\x0c \x01(\t\"\xa9\x05\n\x0f\x44\x65scriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x34\n\x05\x66ield\x18\x02 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x38\n\textension\x18\x06 \x03(\x0b\x32%.google.protobuf.FieldDescriptorProto\x12\x35\n\x0bnested_type\x18\x03 \x03(\x0b\x32 .google.protobuf.DescriptorProto\x12\x37\n\tenum_type\x18\x04 \x03(\x0b\x32$.google.protobuf.EnumDescriptorProto\x12H\n\x0f\x65xtension_range\x18\x05 \x03(\x0b\x32/.google.protobuf.DescriptorProto.ExtensionRange\x12\x39\n\noneof_decl\x18\x08 \x03(\x0b\x32%.google.protobuf.OneofDescriptorProto\x12\x30\n\x07options\x18\x07 \x01(\x0b\x32\x1f.google.protobuf.MessageOptions\x12\x46\n\x0ereserved_range\x18\t \x03(\x0b\x32..google.protobuf.DescriptorProto.ReservedRange\x12\x15\n\rreserved_name\x18\n \x03(\t\x1a\x65\n\x0e\x45xtensionRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\x12\x37\n\x07options\x18\x03 \x01(\x0b\x32&.google.protobuf.ExtensionRangeOptions\x1a+\n\rReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"g\n\x15\x45xtensionRangeOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xd5\x05\n\x14\x46ieldDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12:\n\x05label\x18\x04 \x01(\x0e\x32+.google.protobuf.FieldDescriptorProto.Label\x12\x38\n\x04type\x18\x05 \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x11\n\ttype_name\x18\x06 \x01(\t\x12\x10\n\x08\x65xtendee\x18\x02 \x01(\t\x12\x15\n\rdefault_value\x18\x07 \x01(\t\x12\x13\n\x0boneof_index\x18\t \x01(\x05\x12\x11\n\tjson_name\x18\n \x01(\t\x12.\n\x07options\x18\x08 \x01(\x0b\x32\x1d.google.protobuf.FieldOptions\x12\x17\n\x0fproto3_optional\x18\x11 \x01(\x08\"\xb6\x02\n\x04Type\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"C\n\x05Label\x12\x12\n\x0eLABEL_OPTIONAL\x10\x01\x12\x12\n\x0eLABEL_REQUIRED\x10\x02\x12\x12\n\x0eLABEL_REPEATED\x10\x03\"T\n\x14OneofDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12.\n\x07options\x18\x02 \x01(\x0b\x32\x1d.google.protobuf.OneofOptions\"\xa4\x02\n\x13\x45numDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x38\n\x05value\x18\x02 \x03(\x0b\x32).google.protobuf.EnumValueDescriptorProto\x12-\n\x07options\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.EnumOptions\x12N\n\x0ereserved_range\x18\x04 \x03(\x0b\x32\x36.google.protobuf.EnumDescriptorProto.EnumReservedRange\x12\x15\n\rreserved_name\x18\x05 \x03(\t\x1a/\n\x11\x45numReservedRange\x12\r\n\x05start\x18\x01 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x05\"l\n\x18\x45numValueDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12\x32\n\x07options\x18\x03 \x01(\x0b\x32!.google.protobuf.EnumValueOptions\"\x90\x01\n\x16ServiceDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x36\n\x06method\x18\x02 \x03(\x0b\x32&.google.protobuf.MethodDescriptorProto\x12\x30\n\x07options\x18\x03 \x01(\x0b\x32\x1f.google.protobuf.ServiceOptions\"\xc1\x01\n\x15MethodDescriptorProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\ninput_type\x18\x02 \x01(\t\x12\x13\n\x0boutput_type\x18\x03 \x01(\t\x12/\n\x07options\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.MethodOptions\x12\x1f\n\x10\x63lient_streaming\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1f\n\x10server_streaming\x18\x06 \x01(\x08:\x05\x66\x61lse\"\xa5\x06\n\x0b\x46ileOptions\x12\x14\n\x0cjava_package\x18\x01 \x01(\t\x12\x1c\n\x14java_outer_classname\x18\x08 \x01(\t\x12\"\n\x13java_multiple_files\x18\n \x01(\x08:\x05\x66\x61lse\x12)\n\x1djava_generate_equals_and_hash\x18\x14 \x01(\x08\x42\x02\x18\x01\x12%\n\x16java_string_check_utf8\x18\x1b \x01(\x08:\x05\x66\x61lse\x12\x46\n\x0coptimize_for\x18\t \x01(\x0e\x32).google.protobuf.FileOptions.OptimizeMode:\x05SPEED\x12\x12\n\ngo_package\x18\x0b \x01(\t\x12\"\n\x13\x63\x63_generic_services\x18\x10 \x01(\x08:\x05\x66\x61lse\x12$\n\x15java_generic_services\x18\x11 \x01(\x08:\x05\x66\x61lse\x12\"\n\x13py_generic_services\x18\x12 \x01(\x08:\x05\x66\x61lse\x12#\n\x14php_generic_services\x18* \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x10\x63\x63_enable_arenas\x18\x1f \x01(\x08:\x04true\x12\x19\n\x11objc_class_prefix\x18$ \x01(\t\x12\x18\n\x10\x63sharp_namespace\x18% \x01(\t\x12\x14\n\x0cswift_prefix\x18\' \x01(\t\x12\x18\n\x10php_class_prefix\x18( \x01(\t\x12\x15\n\rphp_namespace\x18) \x01(\t\x12\x1e\n\x16php_metadata_namespace\x18, \x01(\t\x12\x14\n\x0cruby_package\x18- \x01(\t\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\":\n\x0cOptimizeMode\x12\t\n\x05SPEED\x10\x01\x12\r\n\tCODE_SIZE\x10\x02\x12\x10\n\x0cLITE_RUNTIME\x10\x03*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08&\x10\'\"\xf2\x01\n\x0eMessageOptions\x12&\n\x17message_set_wire_format\x18\x01 \x01(\x08:\x05\x66\x61lse\x12.\n\x1fno_standard_descriptor_accessor\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x11\n\tmap_entry\x18\x07 \x01(\x08\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x08\x10\tJ\x04\x08\t\x10\n\"\x9e\x03\n\x0c\x46ieldOptions\x12:\n\x05\x63type\x18\x01 \x01(\x0e\x32#.google.protobuf.FieldOptions.CType:\x06STRING\x12\x0e\n\x06packed\x18\x02 \x01(\x08\x12?\n\x06jstype\x18\x06 \x01(\x0e\x32$.google.protobuf.FieldOptions.JSType:\tJS_NORMAL\x12\x13\n\x04lazy\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x04weak\x18\n \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"/\n\x05\x43Type\x12\n\n\x06STRING\x10\x00\x12\x08\n\x04\x43ORD\x10\x01\x12\x10\n\x0cSTRING_PIECE\x10\x02\"5\n\x06JSType\x12\r\n\tJS_NORMAL\x10\x00\x12\r\n\tJS_STRING\x10\x01\x12\r\n\tJS_NUMBER\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x04\x10\x05\"^\n\x0cOneofOptions\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x93\x01\n\x0b\x45numOptions\x12\x13\n\x0b\x61llow_alias\x18\x02 \x01(\x08\x12\x19\n\ndeprecated\x18\x03 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02J\x04\x08\x05\x10\x06\"}\n\x10\x45numValueOptions\x12\x19\n\ndeprecated\x18\x01 \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"{\n\x0eServiceOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\xad\x02\n\rMethodOptions\x12\x19\n\ndeprecated\x18! \x01(\x08:\x05\x66\x61lse\x12_\n\x11idempotency_level\x18\" \x01(\x0e\x32/.google.protobuf.MethodOptions.IdempotencyLevel:\x13IDEMPOTENCY_UNKNOWN\x12\x43\n\x14uninterpreted_option\x18\xe7\x07 \x03(\x0b\x32$.google.protobuf.UninterpretedOption\"P\n\x10IdempotencyLevel\x12\x17\n\x13IDEMPOTENCY_UNKNOWN\x10\x00\x12\x13\n\x0fNO_SIDE_EFFECTS\x10\x01\x12\x0e\n\nIDEMPOTENT\x10\x02*\t\x08\xe8\x07\x10\x80\x80\x80\x80\x02\"\x9e\x02\n\x13UninterpretedOption\x12;\n\x04name\x18\x02 \x03(\x0b\x32-.google.protobuf.UninterpretedOption.NamePart\x12\x18\n\x10identifier_value\x18\x03 \x01(\t\x12\x1a\n\x12positive_int_value\x18\x04 \x01(\x04\x12\x1a\n\x12negative_int_value\x18\x05 \x01(\x03\x12\x14\n\x0c\x64ouble_value\x18\x06 \x01(\x01\x12\x14\n\x0cstring_value\x18\x07 \x01(\x0c\x12\x17\n\x0f\x61ggregate_value\x18\x08 \x01(\t\x1a\x33\n\x08NamePart\x12\x11\n\tname_part\x18\x01 \x02(\t\x12\x14\n\x0cis_extension\x18\x02 \x02(\x08\"\xd5\x01\n\x0eSourceCodeInfo\x12:\n\x08location\x18\x01 \x03(\x0b\x32(.google.protobuf.SourceCodeInfo.Location\x1a\x86\x01\n\x08Location\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x10\n\x04span\x18\x02 \x03(\x05\x42\x02\x10\x01\x12\x18\n\x10leading_comments\x18\x03 \x01(\t\x12\x19\n\x11trailing_comments\x18\x04 \x01(\t\x12!\n\x19leading_detached_comments\x18\x06 \x03(\t\"\xa7\x01\n\x11GeneratedCodeInfo\x12\x41\n\nannotation\x18\x01 \x03(\x0b\x32-.google.protobuf.GeneratedCodeInfo.Annotation\x1aO\n\nAnnotation\x12\x10\n\x04path\x18\x01 \x03(\x05\x42\x02\x10\x01\x12\x13\n\x0bsource_file\x18\x02 \x01(\t\x12\r\n\x05\x62\x65gin\x18\x03 \x01(\x05\x12\x0b\n\x03\x65nd\x18\x04 \x01(\x05\x42~\n\x13\x63om.google.protobufB\x10\x44\x65scriptorProtosH\x01Z-google.golang.org/protobuf/types/descriptorpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1aGoogle.Protobuf.Reflection' +) + + + +_FIELDDESCRIPTORPROTO_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='google.protobuf.FieldDescriptorProto.Type', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=0, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=1, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=2, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=3, number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=4, number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=5, number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=6, number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=7, number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=8, number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=9, number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=10, number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=11, number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=12, number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=13, number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=14, number=15, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=15, number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=16, number=17, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=17, number=18, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1740, + serialized_end=2050, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_TYPE) + +_FIELDDESCRIPTORPROTO_LABEL = _descriptor.EnumDescriptor( + name='Label', + full_name='google.protobuf.FieldDescriptorProto.Label', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='LABEL_OPTIONAL', index=0, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='LABEL_REQUIRED', index=1, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='LABEL_REPEATED', index=2, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2052, + serialized_end=2119, +) +_sym_db.RegisterEnumDescriptor(_FIELDDESCRIPTORPROTO_LABEL) + +_FILEOPTIONS_OPTIMIZEMODE = _descriptor.EnumDescriptor( + name='OptimizeMode', + full_name='google.protobuf.FileOptions.OptimizeMode', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='SPEED', index=0, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CODE_SIZE', index=1, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='LITE_RUNTIME', index=2, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3686, + serialized_end=3744, +) +_sym_db.RegisterEnumDescriptor(_FILEOPTIONS_OPTIMIZEMODE) + +_FIELDOPTIONS_CTYPE = _descriptor.EnumDescriptor( + name='CType', + full_name='google.protobuf.FieldOptions.CType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='STRING', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CORD', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='STRING_PIECE', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4304, + serialized_end=4351, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_CTYPE) + +_FIELDOPTIONS_JSTYPE = _descriptor.EnumDescriptor( + name='JSType', + full_name='google.protobuf.FieldOptions.JSType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='JS_NORMAL', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='JS_STRING', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='JS_NUMBER', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4353, + serialized_end=4406, +) +_sym_db.RegisterEnumDescriptor(_FIELDOPTIONS_JSTYPE) + +_METHODOPTIONS_IDEMPOTENCYLEVEL = _descriptor.EnumDescriptor( + name='IdempotencyLevel', + full_name='google.protobuf.MethodOptions.IdempotencyLevel', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='IDEMPOTENCY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NO_SIDE_EFFECTS', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='IDEMPOTENT', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=5134, + serialized_end=5214, +) +_sym_db.RegisterEnumDescriptor(_METHODOPTIONS_IDEMPOTENCYLEVEL) + + +_FILEDESCRIPTORSET = _descriptor.Descriptor( + name='FileDescriptorSet', + full_name='google.protobuf.FileDescriptorSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='file', full_name='google.protobuf.FileDescriptorSet.file', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=124, +) + + +_FILEDESCRIPTORPROTO = _descriptor.Descriptor( + name='FileDescriptorProto', + full_name='google.protobuf.FileDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FileDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='package', full_name='google.protobuf.FileDescriptorProto.package', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='dependency', full_name='google.protobuf.FileDescriptorProto.dependency', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='public_dependency', full_name='google.protobuf.FileDescriptorProto.public_dependency', index=3, + number=10, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='weak_dependency', full_name='google.protobuf.FileDescriptorProto.weak_dependency', index=4, + number=11, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='message_type', full_name='google.protobuf.FileDescriptorProto.message_type', index=5, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.FileDescriptorProto.enum_type', index=6, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='service', full_name='google.protobuf.FileDescriptorProto.service', index=7, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.FileDescriptorProto.extension', index=8, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FileDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='source_code_info', full_name='google.protobuf.FileDescriptorProto.source_code_info', index=10, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.FileDescriptorProto.syntax', index=11, + number=12, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=127, + serialized_end=602, +) + + +_DESCRIPTORPROTO_EXTENSIONRANGE = _descriptor.Descriptor( + name='ExtensionRange', + full_name='google.protobuf.DescriptorProto.ExtensionRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ExtensionRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ExtensionRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.ExtensionRange.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1140, + serialized_end=1241, +) + +_DESCRIPTORPROTO_RESERVEDRANGE = _descriptor.Descriptor( + name='ReservedRange', + full_name='google.protobuf.DescriptorProto.ReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.DescriptorProto.ReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.DescriptorProto.ReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1243, + serialized_end=1286, +) + +_DESCRIPTORPROTO = _descriptor.Descriptor( + name='DescriptorProto', + full_name='google.protobuf.DescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.DescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='field', full_name='google.protobuf.DescriptorProto.field', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='extension', full_name='google.protobuf.DescriptorProto.extension', index=2, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='nested_type', full_name='google.protobuf.DescriptorProto.nested_type', index=3, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enum_type', full_name='google.protobuf.DescriptorProto.enum_type', index=4, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='extension_range', full_name='google.protobuf.DescriptorProto.extension_range', index=5, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_decl', full_name='google.protobuf.DescriptorProto.oneof_decl', index=6, + number=8, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.DescriptorProto.options', index=7, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.DescriptorProto.reserved_range', index=8, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.DescriptorProto.reserved_name', index=9, + number=10, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_DESCRIPTORPROTO_EXTENSIONRANGE, _DESCRIPTORPROTO_RESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=605, + serialized_end=1286, +) + + +_EXTENSIONRANGEOPTIONS = _descriptor.Descriptor( + name='ExtensionRangeOptions', + full_name='google.protobuf.ExtensionRangeOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ExtensionRangeOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=1288, + serialized_end=1391, +) + + +_FIELDDESCRIPTORPROTO = _descriptor.Descriptor( + name='FieldDescriptorProto', + full_name='google.protobuf.FieldDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.FieldDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.FieldDescriptorProto.number', index=1, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='label', full_name='google.protobuf.FieldDescriptorProto.label', index=2, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type', full_name='google.protobuf.FieldDescriptorProto.type', index=3, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type_name', full_name='google.protobuf.FieldDescriptorProto.type_name', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='extendee', full_name='google.protobuf.FieldDescriptorProto.extendee', index=5, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.FieldDescriptorProto.default_value', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.FieldDescriptorProto.oneof_index', index=7, + number=9, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.FieldDescriptorProto.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.FieldDescriptorProto.options', index=9, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='proto3_optional', full_name='google.protobuf.FieldDescriptorProto.proto3_optional', index=10, + number=17, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDDESCRIPTORPROTO_TYPE, + _FIELDDESCRIPTORPROTO_LABEL, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1394, + serialized_end=2119, +) + + +_ONEOFDESCRIPTORPROTO = _descriptor.Descriptor( + name='OneofDescriptorProto', + full_name='google.protobuf.OneofDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.OneofDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.OneofDescriptorProto.options', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2121, + serialized_end=2205, +) + + +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE = _descriptor.Descriptor( + name='EnumReservedRange', + full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='start', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.start', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.EnumDescriptorProto.EnumReservedRange.end', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2453, + serialized_end=2500, +) + +_ENUMDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumDescriptorProto', + full_name='google.protobuf.EnumDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.EnumDescriptorProto.value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reserved_range', full_name='google.protobuf.EnumDescriptorProto.reserved_range', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reserved_name', full_name='google.protobuf.EnumDescriptorProto.reserved_name', index=4, + number=5, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2208, + serialized_end=2500, +) + + +_ENUMVALUEDESCRIPTORPROTO = _descriptor.Descriptor( + name='EnumValueDescriptorProto', + full_name='google.protobuf.EnumValueDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValueDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValueDescriptorProto.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValueDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2502, + serialized_end=2610, +) + + +_SERVICEDESCRIPTORPROTO = _descriptor.Descriptor( + name='ServiceDescriptorProto', + full_name='google.protobuf.ServiceDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.ServiceDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='method', full_name='google.protobuf.ServiceDescriptorProto.method', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.ServiceDescriptorProto.options', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2613, + serialized_end=2757, +) + + +_METHODDESCRIPTORPROTO = _descriptor.Descriptor( + name='MethodDescriptorProto', + full_name='google.protobuf.MethodDescriptorProto', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.MethodDescriptorProto.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='input_type', full_name='google.protobuf.MethodDescriptorProto.input_type', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='output_type', full_name='google.protobuf.MethodDescriptorProto.output_type', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.MethodDescriptorProto.options', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='client_streaming', full_name='google.protobuf.MethodDescriptorProto.client_streaming', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='server_streaming', full_name='google.protobuf.MethodDescriptorProto.server_streaming', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2760, + serialized_end=2953, +) + + +_FILEOPTIONS = _descriptor.Descriptor( + name='FileOptions', + full_name='google.protobuf.FileOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='java_package', full_name='google.protobuf.FileOptions.java_package', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='java_outer_classname', full_name='google.protobuf.FileOptions.java_outer_classname', index=1, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='java_multiple_files', full_name='google.protobuf.FileOptions.java_multiple_files', index=2, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='java_generate_equals_and_hash', full_name='google.protobuf.FileOptions.java_generate_equals_and_hash', index=3, + number=20, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='java_string_check_utf8', full_name='google.protobuf.FileOptions.java_string_check_utf8', index=4, + number=27, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='optimize_for', full_name='google.protobuf.FileOptions.optimize_for', index=5, + number=9, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='go_package', full_name='google.protobuf.FileOptions.go_package', index=6, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cc_generic_services', full_name='google.protobuf.FileOptions.cc_generic_services', index=7, + number=16, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='java_generic_services', full_name='google.protobuf.FileOptions.java_generic_services', index=8, + number=17, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='py_generic_services', full_name='google.protobuf.FileOptions.py_generic_services', index=9, + number=18, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='php_generic_services', full_name='google.protobuf.FileOptions.php_generic_services', index=10, + number=42, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FileOptions.deprecated', index=11, + number=23, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cc_enable_arenas', full_name='google.protobuf.FileOptions.cc_enable_arenas', index=12, + number=31, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='objc_class_prefix', full_name='google.protobuf.FileOptions.objc_class_prefix', index=13, + number=36, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='csharp_namespace', full_name='google.protobuf.FileOptions.csharp_namespace', index=14, + number=37, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='swift_prefix', full_name='google.protobuf.FileOptions.swift_prefix', index=15, + number=39, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='php_class_prefix', full_name='google.protobuf.FileOptions.php_class_prefix', index=16, + number=40, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='php_namespace', full_name='google.protobuf.FileOptions.php_namespace', index=17, + number=41, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='php_metadata_namespace', full_name='google.protobuf.FileOptions.php_metadata_namespace', index=18, + number=44, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ruby_package', full_name='google.protobuf.FileOptions.ruby_package', index=19, + number=45, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FileOptions.uninterpreted_option', index=20, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FILEOPTIONS_OPTIMIZEMODE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=2956, + serialized_end=3761, +) + + +_MESSAGEOPTIONS = _descriptor.Descriptor( + name='MessageOptions', + full_name='google.protobuf.MessageOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='message_set_wire_format', full_name='google.protobuf.MessageOptions.message_set_wire_format', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='no_standard_descriptor_accessor', full_name='google.protobuf.MessageOptions.no_standard_descriptor_accessor', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MessageOptions.deprecated', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='map_entry', full_name='google.protobuf.MessageOptions.map_entry', index=3, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MessageOptions.uninterpreted_option', index=4, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=3764, + serialized_end=4006, +) + + +_FIELDOPTIONS = _descriptor.Descriptor( + name='FieldOptions', + full_name='google.protobuf.FieldOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='ctype', full_name='google.protobuf.FieldOptions.ctype', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.FieldOptions.packed', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='jstype', full_name='google.protobuf.FieldOptions.jstype', index=2, + number=6, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lazy', full_name='google.protobuf.FieldOptions.lazy', index=3, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.FieldOptions.deprecated', index=4, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='weak', full_name='google.protobuf.FieldOptions.weak', index=5, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.FieldOptions.uninterpreted_option', index=6, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELDOPTIONS_CTYPE, + _FIELDOPTIONS_JSTYPE, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4009, + serialized_end=4423, +) + + +_ONEOFOPTIONS = _descriptor.Descriptor( + name='OneofOptions', + full_name='google.protobuf.OneofOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.OneofOptions.uninterpreted_option', index=0, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4425, + serialized_end=4519, +) + + +_ENUMOPTIONS = _descriptor.Descriptor( + name='EnumOptions', + full_name='google.protobuf.EnumOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='allow_alias', full_name='google.protobuf.EnumOptions.allow_alias', index=0, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumOptions.deprecated', index=1, + number=3, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4522, + serialized_end=4669, +) + + +_ENUMVALUEOPTIONS = _descriptor.Descriptor( + name='EnumValueOptions', + full_name='google.protobuf.EnumValueOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.EnumValueOptions.deprecated', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.EnumValueOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4671, + serialized_end=4796, +) + + +_SERVICEOPTIONS = _descriptor.Descriptor( + name='ServiceOptions', + full_name='google.protobuf.ServiceOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.ServiceOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.ServiceOptions.uninterpreted_option', index=1, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4798, + serialized_end=4921, +) + + +_METHODOPTIONS = _descriptor.Descriptor( + name='MethodOptions', + full_name='google.protobuf.MethodOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='deprecated', full_name='google.protobuf.MethodOptions.deprecated', index=0, + number=33, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='idempotency_level', full_name='google.protobuf.MethodOptions.idempotency_level', index=1, + number=34, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uninterpreted_option', full_name='google.protobuf.MethodOptions.uninterpreted_option', index=2, + number=999, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _METHODOPTIONS_IDEMPOTENCYLEVEL, + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(1000, 536870912), ], + oneofs=[ + ], + serialized_start=4924, + serialized_end=5225, +) + + +_UNINTERPRETEDOPTION_NAMEPART = _descriptor.Descriptor( + name='NamePart', + full_name='google.protobuf.UninterpretedOption.NamePart', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name_part', full_name='google.protobuf.UninterpretedOption.NamePart.name_part', index=0, + number=1, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_extension', full_name='google.protobuf.UninterpretedOption.NamePart.is_extension', index=1, + number=2, type=8, cpp_type=7, label=2, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5463, + serialized_end=5514, +) + +_UNINTERPRETEDOPTION = _descriptor.Descriptor( + name='UninterpretedOption', + full_name='google.protobuf.UninterpretedOption', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.UninterpretedOption.name', index=0, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='identifier_value', full_name='google.protobuf.UninterpretedOption.identifier_value', index=1, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='positive_int_value', full_name='google.protobuf.UninterpretedOption.positive_int_value', index=2, + number=4, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='negative_int_value', full_name='google.protobuf.UninterpretedOption.negative_int_value', index=3, + number=5, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='double_value', full_name='google.protobuf.UninterpretedOption.double_value', index=4, + number=6, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_value', full_name='google.protobuf.UninterpretedOption.string_value', index=5, + number=7, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='aggregate_value', full_name='google.protobuf.UninterpretedOption.aggregate_value', index=6, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_UNINTERPRETEDOPTION_NAMEPART, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5228, + serialized_end=5514, +) + + +_SOURCECODEINFO_LOCATION = _descriptor.Descriptor( + name='Location', + full_name='google.protobuf.SourceCodeInfo.Location', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.SourceCodeInfo.Location.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='span', full_name='google.protobuf.SourceCodeInfo.Location.span', index=1, + number=2, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='leading_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_comments', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='trailing_comments', full_name='google.protobuf.SourceCodeInfo.Location.trailing_comments', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='leading_detached_comments', full_name='google.protobuf.SourceCodeInfo.Location.leading_detached_comments', index=4, + number=6, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5596, + serialized_end=5730, +) + +_SOURCECODEINFO = _descriptor.Descriptor( + name='SourceCodeInfo', + full_name='google.protobuf.SourceCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='location', full_name='google.protobuf.SourceCodeInfo.location', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_SOURCECODEINFO_LOCATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5517, + serialized_end=5730, +) + + +_GENERATEDCODEINFO_ANNOTATION = _descriptor.Descriptor( + name='Annotation', + full_name='google.protobuf.GeneratedCodeInfo.Annotation', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='path', full_name='google.protobuf.GeneratedCodeInfo.Annotation.path', index=0, + number=1, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='source_file', full_name='google.protobuf.GeneratedCodeInfo.Annotation.source_file', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='begin', full_name='google.protobuf.GeneratedCodeInfo.Annotation.begin', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end', full_name='google.protobuf.GeneratedCodeInfo.Annotation.end', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5821, + serialized_end=5900, +) + +_GENERATEDCODEINFO = _descriptor.Descriptor( + name='GeneratedCodeInfo', + full_name='google.protobuf.GeneratedCodeInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='annotation', full_name='google.protobuf.GeneratedCodeInfo.annotation', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_GENERATEDCODEINFO_ANNOTATION, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=5733, + serialized_end=5900, +) + +_FILEDESCRIPTORSET.fields_by_name['file'].message_type = _FILEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['message_type'].message_type = _DESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['service'].message_type = _SERVICEDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_FILEDESCRIPTORPROTO.fields_by_name['options'].message_type = _FILEOPTIONS +_FILEDESCRIPTORPROTO.fields_by_name['source_code_info'].message_type = _SOURCECODEINFO +_DESCRIPTORPROTO_EXTENSIONRANGE.fields_by_name['options'].message_type = _EXTENSIONRANGEOPTIONS +_DESCRIPTORPROTO_EXTENSIONRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO_RESERVEDRANGE.containing_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['field'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension'].message_type = _FIELDDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['nested_type'].message_type = _DESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['enum_type'].message_type = _ENUMDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['extension_range'].message_type = _DESCRIPTORPROTO_EXTENSIONRANGE +_DESCRIPTORPROTO.fields_by_name['oneof_decl'].message_type = _ONEOFDESCRIPTORPROTO +_DESCRIPTORPROTO.fields_by_name['options'].message_type = _MESSAGEOPTIONS +_DESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _DESCRIPTORPROTO_RESERVEDRANGE +_EXTENSIONRANGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDDESCRIPTORPROTO.fields_by_name['label'].enum_type = _FIELDDESCRIPTORPROTO_LABEL +_FIELDDESCRIPTORPROTO.fields_by_name['type'].enum_type = _FIELDDESCRIPTORPROTO_TYPE +_FIELDDESCRIPTORPROTO.fields_by_name['options'].message_type = _FIELDOPTIONS +_FIELDDESCRIPTORPROTO_TYPE.containing_type = _FIELDDESCRIPTORPROTO +_FIELDDESCRIPTORPROTO_LABEL.containing_type = _FIELDDESCRIPTORPROTO +_ONEOFDESCRIPTORPROTO.fields_by_name['options'].message_type = _ONEOFOPTIONS +_ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE.containing_type = _ENUMDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['value'].message_type = _ENUMVALUEDESCRIPTORPROTO +_ENUMDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMOPTIONS +_ENUMDESCRIPTORPROTO.fields_by_name['reserved_range'].message_type = _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE +_ENUMVALUEDESCRIPTORPROTO.fields_by_name['options'].message_type = _ENUMVALUEOPTIONS +_SERVICEDESCRIPTORPROTO.fields_by_name['method'].message_type = _METHODDESCRIPTORPROTO +_SERVICEDESCRIPTORPROTO.fields_by_name['options'].message_type = _SERVICEOPTIONS +_METHODDESCRIPTORPROTO.fields_by_name['options'].message_type = _METHODOPTIONS +_FILEOPTIONS.fields_by_name['optimize_for'].enum_type = _FILEOPTIONS_OPTIMIZEMODE +_FILEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FILEOPTIONS_OPTIMIZEMODE.containing_type = _FILEOPTIONS +_MESSAGEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS.fields_by_name['ctype'].enum_type = _FIELDOPTIONS_CTYPE +_FIELDOPTIONS.fields_by_name['jstype'].enum_type = _FIELDOPTIONS_JSTYPE +_FIELDOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_FIELDOPTIONS_CTYPE.containing_type = _FIELDOPTIONS +_FIELDOPTIONS_JSTYPE.containing_type = _FIELDOPTIONS +_ONEOFOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_ENUMVALUEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_SERVICEOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS.fields_by_name['idempotency_level'].enum_type = _METHODOPTIONS_IDEMPOTENCYLEVEL +_METHODOPTIONS.fields_by_name['uninterpreted_option'].message_type = _UNINTERPRETEDOPTION +_METHODOPTIONS_IDEMPOTENCYLEVEL.containing_type = _METHODOPTIONS +_UNINTERPRETEDOPTION_NAMEPART.containing_type = _UNINTERPRETEDOPTION +_UNINTERPRETEDOPTION.fields_by_name['name'].message_type = _UNINTERPRETEDOPTION_NAMEPART +_SOURCECODEINFO_LOCATION.containing_type = _SOURCECODEINFO +_SOURCECODEINFO.fields_by_name['location'].message_type = _SOURCECODEINFO_LOCATION +_GENERATEDCODEINFO_ANNOTATION.containing_type = _GENERATEDCODEINFO +_GENERATEDCODEINFO.fields_by_name['annotation'].message_type = _GENERATEDCODEINFO_ANNOTATION +DESCRIPTOR.message_types_by_name['FileDescriptorSet'] = _FILEDESCRIPTORSET +DESCRIPTOR.message_types_by_name['FileDescriptorProto'] = _FILEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['DescriptorProto'] = _DESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ExtensionRangeOptions'] = _EXTENSIONRANGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldDescriptorProto'] = _FIELDDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['OneofDescriptorProto'] = _ONEOFDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumDescriptorProto'] = _ENUMDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['EnumValueDescriptorProto'] = _ENUMVALUEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['ServiceDescriptorProto'] = _SERVICEDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['MethodDescriptorProto'] = _METHODDESCRIPTORPROTO +DESCRIPTOR.message_types_by_name['FileOptions'] = _FILEOPTIONS +DESCRIPTOR.message_types_by_name['MessageOptions'] = _MESSAGEOPTIONS +DESCRIPTOR.message_types_by_name['FieldOptions'] = _FIELDOPTIONS +DESCRIPTOR.message_types_by_name['OneofOptions'] = _ONEOFOPTIONS +DESCRIPTOR.message_types_by_name['EnumOptions'] = _ENUMOPTIONS +DESCRIPTOR.message_types_by_name['EnumValueOptions'] = _ENUMVALUEOPTIONS +DESCRIPTOR.message_types_by_name['ServiceOptions'] = _SERVICEOPTIONS +DESCRIPTOR.message_types_by_name['MethodOptions'] = _METHODOPTIONS +DESCRIPTOR.message_types_by_name['UninterpretedOption'] = _UNINTERPRETEDOPTION +DESCRIPTOR.message_types_by_name['SourceCodeInfo'] = _SOURCECODEINFO +DESCRIPTOR.message_types_by_name['GeneratedCodeInfo'] = _GENERATEDCODEINFO +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FileDescriptorSet = _reflection.GeneratedProtocolMessageType('FileDescriptorSet', (_message.Message,), { + 'DESCRIPTOR' : _FILEDESCRIPTORSET, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + }) +_sym_db.RegisterMessage(FileDescriptorSet) + +FileDescriptorProto = _reflection.GeneratedProtocolMessageType('FileDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _FILEDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + }) +_sym_db.RegisterMessage(FileDescriptorProto) + +DescriptorProto = _reflection.GeneratedProtocolMessageType('DescriptorProto', (_message.Message,), { + + 'ExtensionRange' : _reflection.GeneratedProtocolMessageType('ExtensionRange', (_message.Message,), { + 'DESCRIPTOR' : _DESCRIPTORPROTO_EXTENSIONRANGE, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + }) + , + + 'ReservedRange' : _reflection.GeneratedProtocolMessageType('ReservedRange', (_message.Message,), { + 'DESCRIPTOR' : _DESCRIPTORPROTO_RESERVEDRANGE, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + }) + , + 'DESCRIPTOR' : _DESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + }) +_sym_db.RegisterMessage(DescriptorProto) +_sym_db.RegisterMessage(DescriptorProto.ExtensionRange) +_sym_db.RegisterMessage(DescriptorProto.ReservedRange) + +ExtensionRangeOptions = _reflection.GeneratedProtocolMessageType('ExtensionRangeOptions', (_message.Message,), { + 'DESCRIPTOR' : _EXTENSIONRANGEOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions) + }) +_sym_db.RegisterMessage(ExtensionRangeOptions) + +FieldDescriptorProto = _reflection.GeneratedProtocolMessageType('FieldDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _FIELDDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) + }) +_sym_db.RegisterMessage(FieldDescriptorProto) + +OneofDescriptorProto = _reflection.GeneratedProtocolMessageType('OneofDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _ONEOFDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + }) +_sym_db.RegisterMessage(OneofDescriptorProto) + +EnumDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumDescriptorProto', (_message.Message,), { + + 'EnumReservedRange' : _reflection.GeneratedProtocolMessageType('EnumReservedRange', (_message.Message,), { + 'DESCRIPTOR' : _ENUMDESCRIPTORPROTO_ENUMRESERVEDRANGE, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange) + }) + , + 'DESCRIPTOR' : _ENUMDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + }) +_sym_db.RegisterMessage(EnumDescriptorProto) +_sym_db.RegisterMessage(EnumDescriptorProto.EnumReservedRange) + +EnumValueDescriptorProto = _reflection.GeneratedProtocolMessageType('EnumValueDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _ENUMVALUEDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) + }) +_sym_db.RegisterMessage(EnumValueDescriptorProto) + +ServiceDescriptorProto = _reflection.GeneratedProtocolMessageType('ServiceDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _SERVICEDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) + }) +_sym_db.RegisterMessage(ServiceDescriptorProto) + +MethodDescriptorProto = _reflection.GeneratedProtocolMessageType('MethodDescriptorProto', (_message.Message,), { + 'DESCRIPTOR' : _METHODDESCRIPTORPROTO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) + }) +_sym_db.RegisterMessage(MethodDescriptorProto) + +FileOptions = _reflection.GeneratedProtocolMessageType('FileOptions', (_message.Message,), { + 'DESCRIPTOR' : _FILEOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) + }) +_sym_db.RegisterMessage(FileOptions) + +MessageOptions = _reflection.GeneratedProtocolMessageType('MessageOptions', (_message.Message,), { + 'DESCRIPTOR' : _MESSAGEOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) + }) +_sym_db.RegisterMessage(MessageOptions) + +FieldOptions = _reflection.GeneratedProtocolMessageType('FieldOptions', (_message.Message,), { + 'DESCRIPTOR' : _FIELDOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) + }) +_sym_db.RegisterMessage(FieldOptions) + +OneofOptions = _reflection.GeneratedProtocolMessageType('OneofOptions', (_message.Message,), { + 'DESCRIPTOR' : _ONEOFOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.OneofOptions) + }) +_sym_db.RegisterMessage(OneofOptions) + +EnumOptions = _reflection.GeneratedProtocolMessageType('EnumOptions', (_message.Message,), { + 'DESCRIPTOR' : _ENUMOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) + }) +_sym_db.RegisterMessage(EnumOptions) + +EnumValueOptions = _reflection.GeneratedProtocolMessageType('EnumValueOptions', (_message.Message,), { + 'DESCRIPTOR' : _ENUMVALUEOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) + }) +_sym_db.RegisterMessage(EnumValueOptions) + +ServiceOptions = _reflection.GeneratedProtocolMessageType('ServiceOptions', (_message.Message,), { + 'DESCRIPTOR' : _SERVICEOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) + }) +_sym_db.RegisterMessage(ServiceOptions) + +MethodOptions = _reflection.GeneratedProtocolMessageType('MethodOptions', (_message.Message,), { + 'DESCRIPTOR' : _METHODOPTIONS, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) + }) +_sym_db.RegisterMessage(MethodOptions) + +UninterpretedOption = _reflection.GeneratedProtocolMessageType('UninterpretedOption', (_message.Message,), { + + 'NamePart' : _reflection.GeneratedProtocolMessageType('NamePart', (_message.Message,), { + 'DESCRIPTOR' : _UNINTERPRETEDOPTION_NAMEPART, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) + }) + , + 'DESCRIPTOR' : _UNINTERPRETEDOPTION, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) + }) +_sym_db.RegisterMessage(UninterpretedOption) +_sym_db.RegisterMessage(UninterpretedOption.NamePart) + +SourceCodeInfo = _reflection.GeneratedProtocolMessageType('SourceCodeInfo', (_message.Message,), { + + 'Location' : _reflection.GeneratedProtocolMessageType('Location', (_message.Message,), { + 'DESCRIPTOR' : _SOURCECODEINFO_LOCATION, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + }) + , + 'DESCRIPTOR' : _SOURCECODEINFO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + }) +_sym_db.RegisterMessage(SourceCodeInfo) +_sym_db.RegisterMessage(SourceCodeInfo.Location) + +GeneratedCodeInfo = _reflection.GeneratedProtocolMessageType('GeneratedCodeInfo', (_message.Message,), { + + 'Annotation' : _reflection.GeneratedProtocolMessageType('Annotation', (_message.Message,), { + 'DESCRIPTOR' : _GENERATEDCODEINFO_ANNOTATION, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation) + }) + , + 'DESCRIPTOR' : _GENERATEDCODEINFO, + '__module__' : 'google.protobuf.descriptor_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo) + }) +_sym_db.RegisterMessage(GeneratedCodeInfo) +_sym_db.RegisterMessage(GeneratedCodeInfo.Annotation) + + +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pool.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pool.py new file mode 100644 index 00000000..de9100b0 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/descriptor_pool.py @@ -0,0 +1,1271 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides DescriptorPool to use as a container for proto2 descriptors. + +The DescriptorPool is used in conjection with a DescriptorDatabase to maintain +a collection of protocol buffer descriptors for use when dynamically creating +message types at runtime. + +For most applications protocol buffers should be used via modules generated by +the protocol buffer compiler tool. This should only be used when the type of +protocol buffers used in an application or library cannot be predetermined. + +Below is a straightforward example on how to use this class:: + + pool = DescriptorPool() + file_descriptor_protos = [ ... ] + for file_descriptor_proto in file_descriptor_protos: + pool.Add(file_descriptor_proto) + my_message_descriptor = pool.FindMessageTypeByName('some.package.MessageType') + +The message descriptor can be used in conjunction with the message_factory +module in order to create a protocol buffer class that can be encoded and +decoded. + +If you want to get a Python class for the specified proto, use the +helper functions inside google.protobuf.message_factory +directly instead of this class. +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +import collections +import warnings + +from google.protobuf import descriptor +from google.protobuf import descriptor_database +from google.protobuf import text_encoding + + +_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS # pylint: disable=protected-access + + +def _Deprecated(func): + """Mark functions as deprecated.""" + + def NewFunc(*args, **kwargs): + warnings.warn( + 'Call to deprecated function %s(). Note: Do add unlinked descriptors ' + 'to descriptor_pool is wrong. Use Add() or AddSerializedFile() ' + 'instead.' % func.__name__, + category=DeprecationWarning) + return func(*args, **kwargs) + NewFunc.__name__ = func.__name__ + NewFunc.__doc__ = func.__doc__ + NewFunc.__dict__.update(func.__dict__) + return NewFunc + + +def _NormalizeFullyQualifiedName(name): + """Remove leading period from fully-qualified type name. + + Due to b/13860351 in descriptor_database.py, types in the root namespace are + generated with a leading period. This function removes that prefix. + + Args: + name (str): The fully-qualified symbol name. + + Returns: + str: The normalized fully-qualified symbol name. + """ + return name.lstrip('.') + + +def _OptionsOrNone(descriptor_proto): + """Returns the value of the field `options`, or None if it is not set.""" + if descriptor_proto.HasField('options'): + return descriptor_proto.options + else: + return None + + +def _IsMessageSetExtension(field): + return (field.is_extension and + field.containing_type.has_options and + field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL) + + +class DescriptorPool(object): + """A collection of protobufs dynamically constructed by descriptor protos.""" + + if _USE_C_DESCRIPTORS: + + def __new__(cls, descriptor_db=None): + # pylint: disable=protected-access + return descriptor._message.DescriptorPool(descriptor_db) + + def __init__(self, descriptor_db=None): + """Initializes a Pool of proto buffs. + + The descriptor_db argument to the constructor is provided to allow + specialized file descriptor proto lookup code to be triggered on demand. An + example would be an implementation which will read and compile a file + specified in a call to FindFileByName() and not require the call to Add() + at all. Results from this database will be cached internally here as well. + + Args: + descriptor_db: A secondary source of file descriptors. + """ + + self._internal_db = descriptor_database.DescriptorDatabase() + self._descriptor_db = descriptor_db + self._descriptors = {} + self._enum_descriptors = {} + self._service_descriptors = {} + self._file_descriptors = {} + self._toplevel_extensions = {} + # TODO(jieluo): Remove _file_desc_by_toplevel_extension after + # maybe year 2020 for compatibility issue (with 3.4.1 only). + self._file_desc_by_toplevel_extension = {} + self._top_enum_values = {} + # We store extensions in two two-level mappings: The first key is the + # descriptor of the message being extended, the second key is the extension + # full name or its tag number. + self._extensions_by_name = collections.defaultdict(dict) + self._extensions_by_number = collections.defaultdict(dict) + + def _CheckConflictRegister(self, desc, desc_name, file_name): + """Check if the descriptor name conflicts with another of the same name. + + Args: + desc: Descriptor of a message, enum, service, extension or enum value. + desc_name (str): the full name of desc. + file_name (str): The file name of descriptor. + """ + for register, descriptor_type in [ + (self._descriptors, descriptor.Descriptor), + (self._enum_descriptors, descriptor.EnumDescriptor), + (self._service_descriptors, descriptor.ServiceDescriptor), + (self._toplevel_extensions, descriptor.FieldDescriptor), + (self._top_enum_values, descriptor.EnumValueDescriptor)]: + if desc_name in register: + old_desc = register[desc_name] + if isinstance(old_desc, descriptor.EnumValueDescriptor): + old_file = old_desc.type.file.name + else: + old_file = old_desc.file.name + + if not isinstance(desc, descriptor_type) or ( + old_file != file_name): + error_msg = ('Conflict register for file "' + file_name + + '": ' + desc_name + + ' is already defined in file "' + + old_file + '". Please fix the conflict by adding ' + 'package name on the proto file, or use different ' + 'name for the duplication.') + if isinstance(desc, descriptor.EnumValueDescriptor): + error_msg += ('\nNote: enum values appear as ' + 'siblings of the enum type instead of ' + 'children of it.') + + raise TypeError(error_msg) + + return + + def Add(self, file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + file_desc_proto (FileDescriptorProto): The file descriptor to add. + """ + + self._internal_db.Add(file_desc_proto) + + def AddSerializedFile(self, serialized_file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + serialized_file_desc_proto (bytes): A bytes string, serialization of the + :class:`FileDescriptorProto` to add. + """ + + # pylint: disable=g-import-not-at-top + from google.protobuf import descriptor_pb2 + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + serialized_file_desc_proto) + self.Add(file_desc_proto) + + # Add Descriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated + def AddDescriptor(self, desc): + self._AddDescriptor(desc) + + # Never call this method. It is for internal usage only. + def _AddDescriptor(self, desc): + """Adds a Descriptor to the pool, non-recursively. + + If the Descriptor contains nested messages or enums, the caller must + explicitly register them. This method also registers the FileDescriptor + associated with the message. + + Args: + desc: A Descriptor. + """ + if not isinstance(desc, descriptor.Descriptor): + raise TypeError('Expected instance of descriptor.Descriptor.') + + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) + + self._descriptors[desc.full_name] = desc + self._AddFileDescriptor(desc.file) + + # Add EnumDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated + def AddEnumDescriptor(self, enum_desc): + self._AddEnumDescriptor(enum_desc) + + # Never call this method. It is for internal usage only. + def _AddEnumDescriptor(self, enum_desc): + """Adds an EnumDescriptor to the pool. + + This method also registers the FileDescriptor associated with the enum. + + Args: + enum_desc: An EnumDescriptor. + """ + + if not isinstance(enum_desc, descriptor.EnumDescriptor): + raise TypeError('Expected instance of descriptor.EnumDescriptor.') + + file_name = enum_desc.file.name + self._CheckConflictRegister(enum_desc, enum_desc.full_name, file_name) + self._enum_descriptors[enum_desc.full_name] = enum_desc + + # Top enum values need to be indexed. + # Count the number of dots to see whether the enum is toplevel or nested + # in a message. We cannot use enum_desc.containing_type at this stage. + if enum_desc.file.package: + top_level = (enum_desc.full_name.count('.') + - enum_desc.file.package.count('.') == 1) + else: + top_level = enum_desc.full_name.count('.') == 0 + if top_level: + file_name = enum_desc.file.name + package = enum_desc.file.package + for enum_value in enum_desc.values: + full_name = _NormalizeFullyQualifiedName( + '.'.join((package, enum_value.name))) + self._CheckConflictRegister(enum_value, full_name, file_name) + self._top_enum_values[full_name] = enum_value + self._AddFileDescriptor(enum_desc.file) + + # Add ServiceDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated + def AddServiceDescriptor(self, service_desc): + self._AddServiceDescriptor(service_desc) + + # Never call this method. It is for internal usage only. + def _AddServiceDescriptor(self, service_desc): + """Adds a ServiceDescriptor to the pool. + + Args: + service_desc: A ServiceDescriptor. + """ + + if not isinstance(service_desc, descriptor.ServiceDescriptor): + raise TypeError('Expected instance of descriptor.ServiceDescriptor.') + + self._CheckConflictRegister(service_desc, service_desc.full_name, + service_desc.file.name) + self._service_descriptors[service_desc.full_name] = service_desc + + # Add ExtensionDescriptor to descriptor pool is dreprecated. Please use Add() + # or AddSerializedFile() to add a FileDescriptorProto instead. + @_Deprecated + def AddExtensionDescriptor(self, extension): + self._AddExtensionDescriptor(extension) + + # Never call this method. It is for internal usage only. + def _AddExtensionDescriptor(self, extension): + """Adds a FieldDescriptor describing an extension to the pool. + + Args: + extension: A FieldDescriptor. + + Raises: + AssertionError: when another extension with the same number extends the + same message. + TypeError: when the specified extension is not a + descriptor.FieldDescriptor. + """ + if not (isinstance(extension, descriptor.FieldDescriptor) and + extension.is_extension): + raise TypeError('Expected an extension descriptor.') + + if extension.extension_scope is None: + self._toplevel_extensions[extension.full_name] = extension + + try: + existing_desc = self._extensions_by_number[ + extension.containing_type][extension.number] + except KeyError: + pass + else: + if extension is not existing_desc: + raise AssertionError( + 'Extensions "%s" and "%s" both try to extend message type "%s" ' + 'with field number %d.' % + (extension.full_name, existing_desc.full_name, + extension.containing_type.full_name, extension.number)) + + self._extensions_by_number[extension.containing_type][ + extension.number] = extension + self._extensions_by_name[extension.containing_type][ + extension.full_name] = extension + + # Also register MessageSet extensions with the type name. + if _IsMessageSetExtension(extension): + self._extensions_by_name[extension.containing_type][ + extension.message_type.full_name] = extension + + @_Deprecated + def AddFileDescriptor(self, file_desc): + self._InternalAddFileDescriptor(file_desc) + + # Never call this method. It is for internal usage only. + def _InternalAddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + self._AddFileDescriptor(file_desc) + # TODO(jieluo): This is a temporary solution for FieldDescriptor.file. + # FieldDescriptor.file is added in code gen. Remove this solution after + # maybe 2020 for compatibility reason (with 3.4.1 only). + for extension in file_desc.extensions_by_name.values(): + self._file_desc_by_toplevel_extension[ + extension.full_name] = file_desc + + def _AddFileDescriptor(self, file_desc): + """Adds a FileDescriptor to the pool, non-recursively. + + If the FileDescriptor contains messages or enums, the caller must explicitly + register them. + + Args: + file_desc: A FileDescriptor. + """ + + if not isinstance(file_desc, descriptor.FileDescriptor): + raise TypeError('Expected instance of descriptor.FileDescriptor.') + self._file_descriptors[file_desc.name] = file_desc + + def FindFileByName(self, file_name): + """Gets a FileDescriptor by file name. + + Args: + file_name (str): The path to the file to get a descriptor for. + + Returns: + FileDescriptor: The descriptor for the named file. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + try: + return self._file_descriptors[file_name] + except KeyError: + pass + + try: + file_proto = self._internal_db.FindFileByName(file_name) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileByName(file_name) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file named %s' % file_name) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def FindFileContainingSymbol(self, symbol): + """Gets the FileDescriptor for the file containing the specified symbol. + + Args: + symbol (str): The name of the symbol to search for. + + Returns: + FileDescriptor: Descriptor for the file that contains the specified + symbol. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + + symbol = _NormalizeFullyQualifiedName(symbol) + try: + return self._InternalFindFileContainingSymbol(symbol) + except KeyError: + pass + + try: + # Try fallback database. Build and find again if possible. + self._FindFileContainingSymbolInDb(symbol) + return self._InternalFindFileContainingSymbol(symbol) + except KeyError: + raise KeyError('Cannot find a file containing %s' % symbol) + + def _InternalFindFileContainingSymbol(self, symbol): + """Gets the already built FileDescriptor containing the specified symbol. + + Args: + symbol (str): The name of the symbol to search for. + + Returns: + FileDescriptor: Descriptor for the file that contains the specified + symbol. + + Raises: + KeyError: if the file cannot be found in the pool. + """ + try: + return self._descriptors[symbol].file + except KeyError: + pass + + try: + return self._enum_descriptors[symbol].file + except KeyError: + pass + + try: + return self._service_descriptors[symbol].file + except KeyError: + pass + + try: + return self._top_enum_values[symbol].type.file + except KeyError: + pass + + try: + return self._file_desc_by_toplevel_extension[symbol] + except KeyError: + pass + + # Try fields, enum values and nested extensions inside a message. + top_name, _, sub_name = symbol.rpartition('.') + try: + message = self.FindMessageTypeByName(top_name) + assert (sub_name in message.extensions_by_name or + sub_name in message.fields_by_name or + sub_name in message.enum_values_by_name) + return message.file + except (KeyError, AssertionError): + raise KeyError('Cannot find a file containing %s' % symbol) + + def FindMessageTypeByName(self, full_name): + """Loads the named descriptor from the pool. + + Args: + full_name (str): The full name of the descriptor to load. + + Returns: + Descriptor: The descriptor for the named type. + + Raises: + KeyError: if the message cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._descriptors[full_name] + + def FindEnumTypeByName(self, full_name): + """Loads the named enum descriptor from the pool. + + Args: + full_name (str): The full name of the enum descriptor to load. + + Returns: + EnumDescriptor: The enum descriptor for the named type. + + Raises: + KeyError: if the enum cannot be found in the pool. + """ + + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._enum_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._enum_descriptors[full_name] + + def FindFieldByName(self, full_name): + """Loads the named field descriptor from the pool. + + Args: + full_name (str): The full name of the field descriptor to load. + + Returns: + FieldDescriptor: The field descriptor for the named field. + + Raises: + KeyError: if the field cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, field_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.fields_by_name[field_name] + + def FindOneofByName(self, full_name): + """Loads the named oneof descriptor from the pool. + + Args: + full_name (str): The full name of the oneof descriptor to load. + + Returns: + OneofDescriptor: The oneof descriptor for the named oneof. + + Raises: + KeyError: if the oneof cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + message_name, _, oneof_name = full_name.rpartition('.') + message_descriptor = self.FindMessageTypeByName(message_name) + return message_descriptor.oneofs_by_name[oneof_name] + + def FindExtensionByName(self, full_name): + """Loads the named extension descriptor from the pool. + + Args: + full_name (str): The full name of the extension descriptor to load. + + Returns: + FieldDescriptor: The field descriptor for the named extension. + + Raises: + KeyError: if the extension cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + try: + # The proto compiler does not give any link between the FileDescriptor + # and top-level extensions unless the FileDescriptorProto is added to + # the DescriptorDatabase, but this can impact memory usage. + # So we registered these extensions by name explicitly. + return self._toplevel_extensions[full_name] + except KeyError: + pass + message_name, _, extension_name = full_name.rpartition('.') + try: + # Most extensions are nested inside a message. + scope = self.FindMessageTypeByName(message_name) + except KeyError: + # Some extensions are defined at file scope. + scope = self._FindFileContainingSymbolInDb(full_name) + return scope.extensions_by_name[extension_name] + + def FindExtensionByNumber(self, message_descriptor, number): + """Gets the extension of the specified message with the specified number. + + Extensions have to be registered to this pool by calling :func:`Add` or + :func:`AddExtensionDescriptor`. + + Args: + message_descriptor (Descriptor): descriptor of the extended message. + number (int): Number of the extension field. + + Returns: + FieldDescriptor: The descriptor for the extension. + + Raises: + KeyError: when no extension with the given number is known for the + specified message. + """ + try: + return self._extensions_by_number[message_descriptor][number] + except KeyError: + self._TryLoadExtensionFromDB(message_descriptor, number) + return self._extensions_by_number[message_descriptor][number] + + def FindAllExtensions(self, message_descriptor): + """Gets all the known extensions of a given message. + + Extensions have to be registered to this pool by build related + :func:`Add` or :func:`AddExtensionDescriptor`. + + Args: + message_descriptor (Descriptor): Descriptor of the extended message. + + Returns: + list[FieldDescriptor]: Field descriptors describing the extensions. + """ + # Fallback to descriptor db if FindAllExtensionNumbers is provided. + if self._descriptor_db and hasattr( + self._descriptor_db, 'FindAllExtensionNumbers'): + full_name = message_descriptor.full_name + all_numbers = self._descriptor_db.FindAllExtensionNumbers(full_name) + for number in all_numbers: + if number in self._extensions_by_number[message_descriptor]: + continue + self._TryLoadExtensionFromDB(message_descriptor, number) + + return list(self._extensions_by_number[message_descriptor].values()) + + def _TryLoadExtensionFromDB(self, message_descriptor, number): + """Try to Load extensions from descriptor db. + + Args: + message_descriptor: descriptor of the extended message. + number: the extension number that needs to be loaded. + """ + if not self._descriptor_db: + return + # Only supported when FindFileContainingExtension is provided. + if not hasattr( + self._descriptor_db, 'FindFileContainingExtension'): + return + + full_name = message_descriptor.full_name + file_proto = self._descriptor_db.FindFileContainingExtension( + full_name, number) + + if file_proto is None: + return + + try: + self._ConvertFileProtoToFileDescriptor(file_proto) + except: + warn_msg = ('Unable to load proto file %s for extension number %d.' % + (file_proto.name, number)) + warnings.warn(warn_msg, RuntimeWarning) + + def FindServiceByName(self, full_name): + """Loads the named service descriptor from the pool. + + Args: + full_name (str): The full name of the service descriptor to load. + + Returns: + ServiceDescriptor: The service descriptor for the named service. + + Raises: + KeyError: if the service cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + if full_name not in self._service_descriptors: + self._FindFileContainingSymbolInDb(full_name) + return self._service_descriptors[full_name] + + def FindMethodByName(self, full_name): + """Loads the named service method descriptor from the pool. + + Args: + full_name (str): The full name of the method descriptor to load. + + Returns: + MethodDescriptor: The method descriptor for the service method. + + Raises: + KeyError: if the method cannot be found in the pool. + """ + full_name = _NormalizeFullyQualifiedName(full_name) + service_name, _, method_name = full_name.rpartition('.') + service_descriptor = self.FindServiceByName(service_name) + return service_descriptor.methods_by_name[method_name] + + def _FindFileContainingSymbolInDb(self, symbol): + """Finds the file in descriptor DB containing the specified symbol. + + Args: + symbol (str): The name of the symbol to search for. + + Returns: + FileDescriptor: The file that contains the specified symbol. + + Raises: + KeyError: if the file cannot be found in the descriptor database. + """ + try: + file_proto = self._internal_db.FindFileContainingSymbol(symbol) + except KeyError as error: + if self._descriptor_db: + file_proto = self._descriptor_db.FindFileContainingSymbol(symbol) + else: + raise error + if not file_proto: + raise KeyError('Cannot find a file containing %s' % symbol) + return self._ConvertFileProtoToFileDescriptor(file_proto) + + def _ConvertFileProtoToFileDescriptor(self, file_proto): + """Creates a FileDescriptor from a proto or returns a cached copy. + + This method also has the side effect of loading all the symbols found in + the file into the appropriate dictionaries in the pool. + + Args: + file_proto: The proto to convert. + + Returns: + A FileDescriptor matching the passed in proto. + """ + if file_proto.name not in self._file_descriptors: + built_deps = list(self._GetDeps(file_proto.dependency)) + direct_deps = [self.FindFileByName(n) for n in file_proto.dependency] + public_deps = [direct_deps[i] for i in file_proto.public_dependency] + + file_descriptor = descriptor.FileDescriptor( + pool=self, + name=file_proto.name, + package=file_proto.package, + syntax=file_proto.syntax, + options=_OptionsOrNone(file_proto), + serialized_pb=file_proto.SerializeToString(), + dependencies=direct_deps, + public_dependencies=public_deps, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + scope = {} + + # This loop extracts all the message and enum types from all the + # dependencies of the file_proto. This is necessary to create the + # scope of available message types when defining the passed in + # file proto. + for dependency in built_deps: + scope.update(self._ExtractSymbols( + dependency.message_types_by_name.values())) + scope.update((_PrefixWithDot(enum.full_name), enum) + for enum in dependency.enum_types_by_name.values()) + + for message_type in file_proto.message_type: + message_desc = self._ConvertMessageDescriptor( + message_type, file_proto.package, file_descriptor, scope, + file_proto.syntax) + file_descriptor.message_types_by_name[message_desc.name] = ( + message_desc) + + for enum_type in file_proto.enum_type: + file_descriptor.enum_types_by_name[enum_type.name] = ( + self._ConvertEnumDescriptor(enum_type, file_proto.package, + file_descriptor, None, scope, True)) + + for index, extension_proto in enumerate(file_proto.extension): + extension_desc = self._MakeFieldDescriptor( + extension_proto, file_proto.package, index, file_descriptor, + is_extension=True) + extension_desc.containing_type = self._GetTypeFromScope( + file_descriptor.package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, + file_descriptor.package, scope) + file_descriptor.extensions_by_name[extension_desc.name] = ( + extension_desc) + self._file_desc_by_toplevel_extension[extension_desc.full_name] = ( + file_descriptor) + + for desc_proto in file_proto.message_type: + self._SetAllFieldTypes(file_proto.package, desc_proto, scope) + + if file_proto.package: + desc_proto_prefix = _PrefixWithDot(file_proto.package) + else: + desc_proto_prefix = '' + + for desc_proto in file_proto.message_type: + desc = self._GetTypeFromScope( + desc_proto_prefix, desc_proto.name, scope) + file_descriptor.message_types_by_name[desc_proto.name] = desc + + for index, service_proto in enumerate(file_proto.service): + file_descriptor.services_by_name[service_proto.name] = ( + self._MakeServiceDescriptor(service_proto, index, scope, + file_proto.package, file_descriptor)) + + self.Add(file_proto) + self._file_descriptors[file_proto.name] = file_descriptor + + # Add extensions to the pool + file_desc = self._file_descriptors[file_proto.name] + for extension in file_desc.extensions_by_name.values(): + self._AddExtensionDescriptor(extension) + for message_type in file_desc.message_types_by_name.values(): + for extension in message_type.extensions: + self._AddExtensionDescriptor(extension) + + return file_desc + + def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, + scope=None, syntax=None): + """Adds the proto to the pool in the specified package. + + Args: + desc_proto: The descriptor_pb2.DescriptorProto protobuf message. + package: The package the proto should be located in. + file_desc: The file containing this message. + scope: Dict mapping short and full symbols to message and enum types. + syntax: string indicating syntax of the file ("proto2" or "proto3") + + Returns: + The added descriptor. + """ + + if package: + desc_name = '.'.join((package, desc_proto.name)) + else: + desc_name = desc_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + if scope is None: + scope = {} + + nested = [ + self._ConvertMessageDescriptor( + nested, desc_name, file_desc, scope, syntax) + for nested in desc_proto.nested_type] + enums = [ + self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, + scope, False) + for enum in desc_proto.enum_type] + fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc) + for index, field in enumerate(desc_proto.field)] + extensions = [ + self._MakeFieldDescriptor(extension, desc_name, index, file_desc, + is_extension=True) + for index, extension in enumerate(desc_proto.extension)] + oneofs = [ + # pylint: disable=g-complex-comprehension + descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), + index, None, [], desc.options, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + for index, desc in enumerate(desc_proto.oneof_decl)] + extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range] + if extension_ranges: + is_extendable = True + else: + is_extendable = False + desc = descriptor.Descriptor( + name=desc_proto.name, + full_name=desc_name, + filename=file_name, + containing_type=None, + fields=fields, + oneofs=oneofs, + nested_types=nested, + enum_types=enums, + extensions=extensions, + options=_OptionsOrNone(desc_proto), + is_extendable=is_extendable, + extension_ranges=extension_ranges, + file=file_desc, + serialized_start=None, + serialized_end=None, + syntax=syntax, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + for nested in desc.nested_types: + nested.containing_type = desc + for enum in desc.enum_types: + enum.containing_type = desc + for field_index, field_desc in enumerate(desc_proto.field): + if field_desc.HasField('oneof_index'): + oneof_index = field_desc.oneof_index + oneofs[oneof_index].fields.append(fields[field_index]) + fields[field_index].containing_oneof = oneofs[oneof_index] + + scope[_PrefixWithDot(desc_name)] = desc + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) + self._descriptors[desc_name] = desc + return desc + + def _ConvertEnumDescriptor(self, enum_proto, package=None, file_desc=None, + containing_type=None, scope=None, top_level=False): + """Make a protobuf EnumDescriptor given an EnumDescriptorProto protobuf. + + Args: + enum_proto: The descriptor_pb2.EnumDescriptorProto protobuf message. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the enum descriptor. + containing_type: The type containing this enum. + scope: Scope containing available types. + top_level: If True, the enum is a top level symbol. If False, the enum + is defined inside a message. + + Returns: + The added descriptor + """ + + if package: + enum_name = '.'.join((package, enum_proto.name)) + else: + enum_name = enum_proto.name + + if file_desc is None: + file_name = None + else: + file_name = file_desc.name + + values = [self._MakeEnumValueDescriptor(value, index) + for index, value in enumerate(enum_proto.value)] + desc = descriptor.EnumDescriptor(name=enum_proto.name, + full_name=enum_name, + filename=file_name, + file=file_desc, + values=values, + containing_type=containing_type, + options=_OptionsOrNone(enum_proto), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + scope['.%s' % enum_name] = desc + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) + self._enum_descriptors[enum_name] = desc + + # Add top level enum values. + if top_level: + for value in values: + full_name = _NormalizeFullyQualifiedName( + '.'.join((package, value.name))) + self._CheckConflictRegister(value, full_name, file_name) + self._top_enum_values[full_name] = value + + return desc + + def _MakeFieldDescriptor(self, field_proto, message_name, index, + file_desc, is_extension=False): + """Creates a field descriptor from a FieldDescriptorProto. + + For message and enum type fields, this method will do a look up + in the pool for the appropriate descriptor for that type. If it + is unavailable, it will fall back to the _source function to + create it. If this type is still unavailable, construction will + fail. + + Args: + field_proto: The proto describing the field. + message_name: The name of the containing message. + index: Index of the field + file_desc: The file containing the field descriptor. + is_extension: Indication that this field is for an extension. + + Returns: + An initialized FieldDescriptor object + """ + + if message_name: + full_name = '.'.join((message_name, field_proto.name)) + else: + full_name = field_proto.name + + return descriptor.FieldDescriptor( + name=field_proto.name, + full_name=full_name, + index=index, + number=field_proto.number, + type=field_proto.type, + cpp_type=None, + message_type=None, + enum_type=None, + containing_type=None, + label=field_proto.label, + has_default_value=False, + default_value=None, + is_extension=is_extension, + extension_scope=None, + options=_OptionsOrNone(field_proto), + file=file_desc, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + + def _SetAllFieldTypes(self, package, desc_proto, scope): + """Sets all the descriptor's fields's types. + + This method also sets the containing types on any extensions. + + Args: + package: The current package of desc_proto. + desc_proto: The message descriptor to update. + scope: Enclosing scope of available types. + """ + + package = _PrefixWithDot(package) + + main_desc = self._GetTypeFromScope(package, desc_proto.name, scope) + + if package == '.': + nested_package = _PrefixWithDot(desc_proto.name) + else: + nested_package = '.'.join([package, desc_proto.name]) + + for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): + self._SetFieldType(field_proto, field_desc, nested_package, scope) + + for extension_proto, extension_desc in ( + zip(desc_proto.extension, main_desc.extensions)): + extension_desc.containing_type = self._GetTypeFromScope( + nested_package, extension_proto.extendee, scope) + self._SetFieldType(extension_proto, extension_desc, nested_package, scope) + + for nested_type in desc_proto.nested_type: + self._SetAllFieldTypes(nested_package, nested_type, scope) + + def _SetFieldType(self, field_proto, field_desc, package, scope): + """Sets the field's type, cpp_type, message_type and enum_type. + + Args: + field_proto: Data about the field in proto format. + field_desc: The descriptor to modify. + package: The package the field's container is in. + scope: Enclosing scope of available types. + """ + if field_proto.type_name: + desc = self._GetTypeFromScope(package, field_proto.type_name, scope) + else: + desc = None + + if not field_proto.HasField('type'): + if isinstance(desc, descriptor.Descriptor): + field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE + else: + field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM + + field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType( + field_proto.type) + + if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE + or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP): + field_desc.message_type = desc + + if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.enum_type = desc + + if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED: + field_desc.has_default_value = False + field_desc.default_value = [] + elif field_proto.HasField('default_value'): + field_desc.has_default_value = True + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = float(field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = field_proto.default_value + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = field_proto.default_value.lower() == 'true' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values_by_name[ + field_proto.default_value].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = text_encoding.CUnescape( + field_proto.default_value) + elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE: + field_desc.default_value = None + else: + # All other types are of the "int" type. + field_desc.default_value = int(field_proto.default_value) + else: + field_desc.has_default_value = False + if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or + field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT): + field_desc.default_value = 0.0 + elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING: + field_desc.default_value = u'' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL: + field_desc.default_value = False + elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM: + field_desc.default_value = field_desc.enum_type.values[0].number + elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES: + field_desc.default_value = b'' + elif field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE: + field_desc.default_value = None + else: + # All other types are of the "int" type. + field_desc.default_value = 0 + + field_desc.type = field_proto.type + + def _MakeEnumValueDescriptor(self, value_proto, index): + """Creates a enum value descriptor object from a enum value proto. + + Args: + value_proto: The proto describing the enum value. + index: The index of the enum value. + + Returns: + An initialized EnumValueDescriptor object. + """ + + return descriptor.EnumValueDescriptor( + name=value_proto.name, + index=index, + number=value_proto.number, + options=_OptionsOrNone(value_proto), + type=None, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + + def _MakeServiceDescriptor(self, service_proto, service_index, scope, + package, file_desc): + """Make a protobuf ServiceDescriptor given a ServiceDescriptorProto. + + Args: + service_proto: The descriptor_pb2.ServiceDescriptorProto protobuf message. + service_index: The index of the service in the File. + scope: Dict mapping short and full symbols to message and enum types. + package: Optional package name for the new message EnumDescriptor. + file_desc: The file containing the service descriptor. + + Returns: + The added descriptor. + """ + + if package: + service_name = '.'.join((package, service_proto.name)) + else: + service_name = service_proto.name + + methods = [self._MakeMethodDescriptor(method_proto, service_name, package, + scope, index) + for index, method_proto in enumerate(service_proto.method)] + desc = descriptor.ServiceDescriptor( + name=service_proto.name, + full_name=service_name, + index=service_index, + methods=methods, + options=_OptionsOrNone(service_proto), + file=file_desc, + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + self._CheckConflictRegister(desc, desc.full_name, desc.file.name) + self._service_descriptors[service_name] = desc + return desc + + def _MakeMethodDescriptor(self, method_proto, service_name, package, scope, + index): + """Creates a method descriptor from a MethodDescriptorProto. + + Args: + method_proto: The proto describing the method. + service_name: The name of the containing service. + package: Optional package name to look up for types. + scope: Scope containing available types. + index: Index of the method in the service. + + Returns: + An initialized MethodDescriptor object. + """ + full_name = '.'.join((service_name, method_proto.name)) + input_type = self._GetTypeFromScope( + package, method_proto.input_type, scope) + output_type = self._GetTypeFromScope( + package, method_proto.output_type, scope) + return descriptor.MethodDescriptor( + name=method_proto.name, + full_name=full_name, + index=index, + containing_service=None, + input_type=input_type, + output_type=output_type, + options=_OptionsOrNone(method_proto), + # pylint: disable=protected-access + create_key=descriptor._internal_create_key) + + def _ExtractSymbols(self, descriptors): + """Pulls out all the symbols from descriptor protos. + + Args: + descriptors: The messages to extract descriptors from. + Yields: + A two element tuple of the type name and descriptor object. + """ + + for desc in descriptors: + yield (_PrefixWithDot(desc.full_name), desc) + for symbol in self._ExtractSymbols(desc.nested_types): + yield symbol + for enum in desc.enum_types: + yield (_PrefixWithDot(enum.full_name), enum) + + def _GetDeps(self, dependencies): + """Recursively finds dependencies for file protos. + + Args: + dependencies: The names of the files being depended on. + + Yields: + Each direct and indirect dependency. + """ + + for dependency in dependencies: + dep_desc = self.FindFileByName(dependency) + yield dep_desc + for parent_dep in dep_desc.dependencies: + yield parent_dep + + def _GetTypeFromScope(self, package, type_name, scope): + """Finds a given type name in the current scope. + + Args: + package: The package the proto should be located in. + type_name: The name of the type to be found in the scope. + scope: Dict mapping short and full symbols to message and enum types. + + Returns: + The descriptor for the requested type. + """ + if type_name not in scope: + components = _PrefixWithDot(package).split('.') + while components: + possible_match = '.'.join(components + [type_name]) + if possible_match in scope: + type_name = possible_match + break + else: + components.pop(-1) + return scope[type_name] + + +def _PrefixWithDot(name): + return name if name.startswith('.') else '.%s' % name + + +if _USE_C_DESCRIPTORS: + # TODO(amauryfa): This pool could be constructed from Python code, when we + # support a flag like 'use_cpp_generated_pool=True'. + # pylint: disable=protected-access + _DEFAULT = descriptor._message.default_pool +else: + _DEFAULT = DescriptorPool() + + +def Default(): + return _DEFAULT diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/duration_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/duration_pb2.py new file mode 100644 index 00000000..813a92df --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/duration_pb2.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/duration.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/duration.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\rDurationProtoP\001Z1google.golang.org/protobuf/types/known/durationpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x1egoogle/protobuf/duration.proto\x12\x0fgoogle.protobuf\"*\n\x08\x44uration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42\x83\x01\n\x13\x63om.google.protobufB\rDurationProtoP\x01Z1google.golang.org/protobuf/types/known/durationpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_DURATION = _descriptor.Descriptor( + name='Duration', + full_name='google.protobuf.Duration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Duration.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Duration.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=93, +) + +DESCRIPTOR.message_types_by_name['Duration'] = _DURATION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Duration = _reflection.GeneratedProtocolMessageType('Duration', (_message.Message,), { + 'DESCRIPTOR' : _DURATION, + '__module__' : 'google.protobuf.duration_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Duration) + }) +_sym_db.RegisterMessage(Duration) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/empty_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/empty_pb2.py new file mode 100644 index 00000000..009d4d58 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/empty_pb2.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/empty.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/empty.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\nEmptyProtoP\001Z.google.golang.org/protobuf/types/known/emptypb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x1bgoogle/protobuf/empty.proto\x12\x0fgoogle.protobuf\"\x07\n\x05\x45mptyB}\n\x13\x63om.google.protobufB\nEmptyProtoP\x01Z.google.golang.org/protobuf/types/known/emptypb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_EMPTY = _descriptor.Descriptor( + name='Empty', + full_name='google.protobuf.Empty', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=48, + serialized_end=55, +) + +DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), { + 'DESCRIPTOR' : _EMPTY, + '__module__' : 'google.protobuf.empty_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Empty) + }) +_sym_db.RegisterMessage(Empty) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/field_mask_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/field_mask_pb2.py new file mode 100644 index 00000000..c7494248 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/field_mask_pb2.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/field_mask.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/field_mask.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\016FieldMaskProtoP\001Z2google.golang.org/protobuf/types/known/fieldmaskpb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n google/protobuf/field_mask.proto\x12\x0fgoogle.protobuf\"\x1a\n\tFieldMask\x12\r\n\x05paths\x18\x01 \x03(\tB\x85\x01\n\x13\x63om.google.protobufB\x0e\x46ieldMaskProtoP\x01Z2google.golang.org/protobuf/types/known/fieldmaskpb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_FIELDMASK = _descriptor.Descriptor( + name='FieldMask', + full_name='google.protobuf.FieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='paths', full_name='google.protobuf.FieldMask.paths', index=0, + number=1, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=53, + serialized_end=79, +) + +DESCRIPTOR.message_types_by_name['FieldMask'] = _FIELDMASK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +FieldMask = _reflection.GeneratedProtocolMessageType('FieldMask', (_message.Message,), { + 'DESCRIPTOR' : _FIELDMASK, + '__module__' : 'google.protobuf.field_mask_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FieldMask) + }) +_sym_db.RegisterMessage(FieldMask) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/__init__.py new file mode 100644 index 00000000..7d2e571a --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/__init__.py @@ -0,0 +1,30 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/_api_implementation.cpython-38-x86_64-linux-gnu.so b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/_api_implementation.cpython-38-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..255ab1a7e7a4db8f025e40ceb82f71c9b2ad2621 GIT binary patch literal 5504 zcmcgwZ)_Y#6`woX$@Sttr>aobsgj{`!AbDSK4NOMF}d`TW?ho{Fb)JNvsvG+y<6Sw z9=CIeZ7N~m1oeb0S^atdv3zgdpWl0L-t4@cyRV-(^+Ym}U^H6TXBcuX?usNisaWZh6CgP@%yz-& zUe*)Zwr#2Im>o$+BBG4(P=GNoL{92+=}1mA)e@SqjHHB1N}MBcj>HjVXn;e~RK&4X zp!mNmm#WfUX-5=oaTIO}3+FG~6S8+uvL{No&jC)BFaqA?Gb8ngzYqR#*(aYm!=66) zap*!(CG(|m@fa>_%3Qx4Q=ISVGhyO14zw)=|pUt26e&ZhUixR}o4lZdT~v(nCach4TBEuE=YkzL)J`E4w4RF^TGsepGwR<=$=T z_R&z@&NB2MN0V-#mibYPa;c`$tPyfH34WRGXL8>04SeP@8+h(cc7g@=j3WQZWbVv()?bFDXo3oi>(Fl+m zM0rIx;MYQa0Qq8MXV{i0OsK_F5JaV5hV5DG^Fw}ea^ke}Fd`l& zYE3Ap#N^Eu2lCmNJlBih2-Qa053}5JCltYm><|5i|jEkvVUc>MX&!#f8`%X^~9R~ z+GZ^Te`G8Kzb@XH)a%z8e?|PlNCI%I_6dD)^J`Tyf(HgC)=M3PlfEau=)+RT;2oAdTFEAJzpN07reEIWW z*$s}bz6&K=zxn}G?9z%}UlkwImxhi4K(GJi3RZW$3OZE1AyWF{p@irdZ0PmPr?GU$ zK^=hl&0A4@v7#6Z2DXaxb~V5rv0dNTM#kNMo4g#h6D}N6aC^4mL;vALzg%%kcE51T zHZV~~2|}B+WkahgyPgfK%`JP{td#^mRv6{CcPcJ?UJGnK?N@nWPB^~DD^*|kSuLF& z6=8^|uR#)bv^lLZ$EW6aU<=`TGZZBNhseg$OK+tIxjXbcvPQm8 zFh)-oP8naw9?+oniM=h4aiFlX>=*Ah8b^S({-@En2(%Zr%L0mb1ssX_ah90PB=)xN zPT}3A7i9RZtpKio2A!EFI=i3j+H)bbz>fAjcJNcZ51|-sVEfr+@EgA4j&)`hlgV7V zGj(zg$k9K>nFT+1r%(s=QRL(jj?z z&pse|>ic_1FKLgY)aS7dIH>o%`#}S{8@ntMrCvOXn*oD*@TSzu>nJ-Yd8{3d?udkY zh|^`+Pw`0NI2V3y?c;9A-!JKP8JOhjt&xKAd|TR4Z>D(gc!c@?R@y_?2zjde+mio* z)c;%Zv`*>v|4y3scqQ_*EckgzzbWarX(JSSVrjj^-;L6H8|oE~yV*DOC-eD7c^_Qa z5Aegm@#xd=h?XNq8kP>cg!!ko;q zTZE*1@D3kZ7&3AXcSWW_lf}zxv;6<-1kWj+Ejo`oeJ>>c^0*Mo_QC8uI6H)=enIqz zw3Kb5*PKJ_4)r|X_bzzQoB2~e zAj%_Hvwu+>q9;I)y@q(|H$(}K`D1L#AEx1$fKOT*3aGykrT(VYkJkSc1yB8w=s9!> z1M%3SDL&yHkYQfbM(BGlQT5BRy8lH5UyzQP6!h_tkql7}_;`GJj}omY8%8+ti6G=^Sbd<655g0D9hC9>>3*{;@z`JDgK$Lu z1j;!6hP)r$ka#B!hB;UGzW|TEX#MoNj4m&P6o+6`2jc$@6O6A8!q*jrYKuI@j+?$F M 2: + raise TypeError("update() takes at most 2 positional " + "arguments ({} given)".format(len(args))) + elif not args: + raise TypeError("update() takes at least 1 argument (0 given)") + self = args[0] + other = args[1] if len(args) >= 2 else () + + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + def setdefault(self, key, default=None): + try: + return self[key] + except KeyError: + self[key] = default + return default + + collections_abc.Mapping.register(Mapping) + collections_abc.MutableMapping.register(MutableMapping) + +else: + # In Python 3 we can just use MutableMapping directly, because it defines + # __slots__. + MutableMapping = collections_abc.MutableMapping + + +class BaseContainer(object): + + """Base container class.""" + + # Minimizes memory usage and disallows assignment to other attributes. + __slots__ = ['_message_listener', '_values'] + + def __init__(self, message_listener): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + Modified() method when it is modified. + """ + self._message_listener = message_listener + self._values = [] + + def __getitem__(self, key): + """Retrieves item by the specified key.""" + return self._values[key] + + def __len__(self): + """Returns the number of elements in the container.""" + return len(self._values) + + def __ne__(self, other): + """Checks if another instance isn't equal to this one.""" + # The concrete classes should define __eq__. + return not self == other + + def __hash__(self): + raise TypeError('unhashable object') + + def __repr__(self): + return repr(self._values) + + def sort(self, *args, **kwargs): + # Continue to support the old sort_function keyword argument. + # This is expected to be a rare occurrence, so use LBYL to avoid + # the overhead of actually catching KeyError. + if 'sort_function' in kwargs: + kwargs['cmp'] = kwargs.pop('sort_function') + self._values.sort(*args, **kwargs) + + def reverse(self): + self._values.reverse() + + +collections_abc.MutableSequence.register(BaseContainer) + + +class RepeatedScalarFieldContainer(BaseContainer): + """Simple, type-checked, list-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_type_checker'] + + def __init__(self, message_listener, type_checker): + """Args: + + message_listener: A MessageListener implementation. The + RepeatedScalarFieldContainer will call this object's Modified() method + when it is modified. + type_checker: A type_checkers.ValueChecker instance to run on elements + inserted into this container. + """ + super(RepeatedScalarFieldContainer, self).__init__(message_listener) + self._type_checker = type_checker + + def append(self, value): + """Appends an item to the list. Similar to list.append().""" + self._values.append(self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def insert(self, key, value): + """Inserts the item at the specified position. Similar to list.insert().""" + self._values.insert(key, self._type_checker.CheckValue(value)) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def extend(self, elem_seq): + """Extends by appending the given iterable. Similar to list.extend().""" + + if elem_seq is None: + return + try: + elem_seq_iter = iter(elem_seq) + except TypeError: + if not elem_seq: + # silently ignore falsy inputs :-/. + # TODO(ptucker): Deprecate this behavior. b/18413862 + return + raise + + new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] + if new_values: + self._values.extend(new_values) + self._message_listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one. We do not check the types of the individual fields. + """ + self._values.extend(other._values) + self._message_listener.Modified() + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __setitem__(self, key, value): + """Sets the item on the specified position.""" + if isinstance(key, slice): # PY3 + if key.step is not None: + raise ValueError('Extended slices not supported') + self.__setslice__(key.start, key.stop, value) + else: + self._values[key] = self._type_checker.CheckValue(value) + self._message_listener.Modified() + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __setslice__(self, start, stop, values): + """Sets the subset of items from between the specified indices.""" + new_values = [] + for value in values: + new_values.append(self._type_checker.CheckValue(value)) + self._values[start:stop] = new_values + self._message_listener.Modified() + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + # Special case for the same type which should be common and fast. + if isinstance(other, self.__class__): + return other._values == self._values + # We are presumably comparing against some other sequence type. + return other == self._values + + +class RepeatedCompositeFieldContainer(BaseContainer): + + """Simple, list-like container for holding repeated composite fields.""" + + # Disallows assignment to other attributes. + __slots__ = ['_message_descriptor'] + + def __init__(self, message_listener, message_descriptor): + """ + Note that we pass in a descriptor instead of the generated directly, + since at the time we construct a _RepeatedCompositeFieldContainer we + haven't yet necessarily initialized the type that will be contained in the + container. + + Args: + message_listener: A MessageListener implementation. + The RepeatedCompositeFieldContainer will call this object's + Modified() method when it is modified. + message_descriptor: A Descriptor instance describing the protocol type + that should be present in this container. We'll use the + _concrete_class field of this descriptor when the client calls add(). + """ + super(RepeatedCompositeFieldContainer, self).__init__(message_listener) + self._message_descriptor = message_descriptor + + def add(self, **kwargs): + """Adds a new element at the end of the list and returns it. Keyword + arguments may be used to initialize the element. + """ + new_element = self._message_descriptor._concrete_class(**kwargs) + new_element._SetListener(self._message_listener) + self._values.append(new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + return new_element + + def append(self, value): + """Appends one element by copying the message.""" + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + new_element.CopyFrom(value) + self._values.append(new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def insert(self, key, value): + """Inserts the item at the specified position by copying.""" + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + new_element.CopyFrom(value) + self._values.insert(key, new_element) + if not self._message_listener.dirty: + self._message_listener.Modified() + + def extend(self, elem_seq): + """Extends by appending the given sequence of elements of the same type + + as this one, copying each individual message. + """ + message_class = self._message_descriptor._concrete_class + listener = self._message_listener + values = self._values + for message in elem_seq: + new_element = message_class() + new_element._SetListener(listener) + new_element.MergeFrom(message) + values.append(new_element) + listener.Modified() + + def MergeFrom(self, other): + """Appends the contents of another repeated field of the same type to this + one, copying each individual message. + """ + self.extend(other._values) + + def remove(self, elem): + """Removes an item from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.Modified() + + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + + def __getslice__(self, start, stop): + """Retrieves the subset of items from between the specified indices.""" + return self._values[start:stop] + + def __delitem__(self, key): + """Deletes the item at the specified position.""" + del self._values[key] + self._message_listener.Modified() + + def __delslice__(self, start, stop): + """Deletes the subset of items from between the specified indices.""" + del self._values[start:stop] + self._message_listener.Modified() + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + if not isinstance(other, self.__class__): + raise TypeError('Can only compare repeated composite fields against ' + 'other repeated composite fields.') + return self._values == other._values + + +class ScalarMap(MutableMapping): + + """Simple, type-checked, dict-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener', + '_entry_descriptor'] + + def __init__(self, message_listener, key_checker, value_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._key_checker = key_checker + self._value_checker = value_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + try: + return self._values[key] + except KeyError: + key = self._key_checker.CheckValue(key) + val = self._value_checker.DefaultValue() + self._values[key] = val + return val + + def __contains__(self, item): + # We check the key's type to match the strong-typing flavor of the API. + # Also this makes it easier to match the behavior of the C++ implementation. + self._key_checker.CheckValue(item) + return item in self._values + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __setitem__(self, key, value): + checked_key = self._key_checker.CheckValue(key) + checked_value = self._value_checker.CheckValue(value) + self._values[checked_key] = checked_value + self._message_listener.Modified() + + def __delitem__(self, key): + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + self._values.update(other._values) + self._message_listener.Modified() + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class + + +class MessageMap(MutableMapping): + + """Simple, type-checked, dict-like container for with submessage values.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_values', '_message_listener', + '_message_descriptor', '_entry_descriptor'] + + def __init__(self, message_listener, message_descriptor, key_checker, + entry_descriptor): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + entry_descriptor: The MessageDescriptor of a map entry: key and value. + """ + self._message_listener = message_listener + self._message_descriptor = message_descriptor + self._key_checker = key_checker + self._entry_descriptor = entry_descriptor + self._values = {} + + def __getitem__(self, key): + key = self._key_checker.CheckValue(key) + try: + return self._values[key] + except KeyError: + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + self._values[key] = new_element + self._message_listener.Modified() + + return new_element + + def get_or_create(self, key): + """get_or_create() is an alias for getitem (ie. map[key]). + + Args: + key: The key to get or create in the map. + + This is useful in cases where you want to be explicit that the call is + mutating the map. This can avoid lint errors for statements like this + that otherwise would appear to be pointless statements: + + msg.my_map[key] + """ + return self[key] + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __contains__(self, item): + item = self._key_checker.CheckValue(item) + return item in self._values + + def __setitem__(self, key, value): + raise ValueError('May not set values directly, call my_map[key].foo = 5') + + def __delitem__(self, key): + key = self._key_checker.CheckValue(key) + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def __repr__(self): + return repr(self._values) + + def MergeFrom(self, other): + # pylint: disable=protected-access + for key in other._values: + # According to documentation: "When parsing from the wire or when merging, + # if there are duplicate map keys the last key seen is used". + if key in self: + del self[key] + self[key].CopyFrom(other[key]) + # self._message_listener.Modified() not required here, because + # mutations to submessages already propagate. + + def InvalidateIterators(self): + # It appears that the only way to reliably invalidate iterators to + # self._values is to ensure that its size changes. + original = self._values + self._values = original.copy() + original[None] = None + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + def GetEntryClass(self): + return self._entry_descriptor._concrete_class + + +class _UnknownField(object): + + """A parsed unknown field.""" + + # Disallows assignment to other attributes. + __slots__ = ['_field_number', '_wire_type', '_data'] + + def __init__(self, field_number, wire_type, data): + self._field_number = field_number + self._wire_type = wire_type + self._data = data + return + + def __lt__(self, other): + # pylint: disable=protected-access + return self._field_number < other._field_number + + def __eq__(self, other): + if self is other: + return True + # pylint: disable=protected-access + return (self._field_number == other._field_number and + self._wire_type == other._wire_type and + self._data == other._data) + + +class UnknownFieldRef(object): + + def __init__(self, parent, index): + self._parent = parent + self._index = index + return + + def _check_valid(self): + if not self._parent: + raise ValueError('UnknownField does not exist. ' + 'The parent message might be cleared.') + if self._index >= len(self._parent): + raise ValueError('UnknownField does not exist. ' + 'The parent message might be cleared.') + + @property + def field_number(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._field_number + + @property + def wire_type(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._wire_type + + @property + def data(self): + self._check_valid() + # pylint: disable=protected-access + return self._parent._internal_get(self._index)._data + + +class UnknownFieldSet(object): + + """UnknownField container""" + + # Disallows assignment to other attributes. + __slots__ = ['_values'] + + def __init__(self): + self._values = [] + + def __getitem__(self, index): + if self._values is None: + raise ValueError('UnknownFields does not exist. ' + 'The parent message might be cleared.') + size = len(self._values) + if index < 0: + index += size + if index < 0 or index >= size: + raise IndexError('index %d out of range'.index) + + return UnknownFieldRef(self, index) + + def _internal_get(self, index): + return self._values[index] + + def __len__(self): + if self._values is None: + raise ValueError('UnknownFields does not exist. ' + 'The parent message might be cleared.') + return len(self._values) + + def _add(self, field_number, wire_type, data): + unknown_field = _UnknownField(field_number, wire_type, data) + self._values.append(unknown_field) + return unknown_field + + def __iter__(self): + for i in range(len(self)): + yield UnknownFieldRef(self, i) + + def _extend(self, other): + if other is None: + return + # pylint: disable=protected-access + self._values.extend(other._values) + + def __eq__(self, other): + if self is other: + return True + # Sort unknown fields because their order shouldn't + # affect equality test. + values = list(self._values) + if other is None: + return not values + values.sort() + # pylint: disable=protected-access + other_values = sorted(other._values) + return values == other_values + + def _clear(self): + for value in self._values: + # pylint: disable=protected-access + if isinstance(value._data, UnknownFieldSet): + value._data._clear() # pylint: disable=protected-access + self._values = None diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/decoder.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/decoder.py new file mode 100644 index 00000000..6804986b --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/decoder.py @@ -0,0 +1,1057 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Code for decoding protocol buffer primitives. + +This code is very similar to encoder.py -- read the docs for that module first. + +A "decoder" is a function with the signature: + Decode(buffer, pos, end, message, field_dict) +The arguments are: + buffer: The string containing the encoded message. + pos: The current position in the string. + end: The position in the string where the current message ends. May be + less than len(buffer) if we're reading a sub-message. + message: The message object into which we're parsing. + field_dict: message._fields (avoids a hashtable lookup). +The decoder reads the field and stores it into field_dict, returning the new +buffer position. A decoder for a repeated field may proactively decode all of +the elements of that field, if they appear consecutively. + +Note that decoders may throw any of the following: + IndexError: Indicates a truncated message. + struct.error: Unpacking of a fixed-width field failed. + message.DecodeError: Other errors. + +Decoders are expected to raise an exception if they are called with pos > end. +This allows callers to be lax about bounds checking: it's fineto read past +"end" as long as you are sure that someone else will notice and throw an +exception later on. + +Something up the call stack is expected to catch IndexError and struct.error +and convert them to message.DecodeError. + +Decoders are constructed using decoder constructors with the signature: + MakeDecoder(field_number, is_repeated, is_packed, key, new_default) +The arguments are: + field_number: The field number of the field we want to decode. + is_repeated: Is the field a repeated field? (bool) + is_packed: Is the field a packed field? (bool) + key: The key to use when looking up the field within field_dict. + (This is actually the FieldDescriptor but nothing in this + file should depend on that.) + new_default: A function which takes a message object as a parameter and + returns a new instance of the default value for this field. + (This is called for repeated fields and sub-messages, when an + instance does not already exist.) + +As with encoders, we define a decoder constructor for every type of field. +Then, for every field of every message class we construct an actual decoder. +That decoder goes into a dict indexed by tag, so when we decode a message +we repeatedly read a tag, look up the corresponding decoder, and invoke it. +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +import struct +import sys +import six + +_UCS2_MAXUNICODE = 65535 +if six.PY3: + long = int +else: + import re # pylint: disable=g-import-not-at-top + _SURROGATE_PATTERN = re.compile(six.u(r'[\ud800-\udfff]')) + +from google.protobuf.internal import containers +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import message + + +# This will overflow and thus become IEEE-754 "infinity". We would use +# "float('inf')" but it doesn't work on Windows pre-Python-2.6. +_POS_INF = 1e10000 +_NEG_INF = -_POS_INF +_NAN = _POS_INF * 0 + + +# This is not for optimization, but rather to avoid conflicts with local +# variables named "message". +_DecodeError = message.DecodeError + + +def _VarintDecoder(mask, result_type): + """Return an encoder for a basic varint value (does not include tag). + + Decoded values will be bitwise-anded with the given mask before being + returned, e.g. to limit them to 32 bits. The returned decoder does not + take the usual "end" parameter -- the caller is expected to do bounds checking + after the fact (often the caller can defer such checking until later). The + decoder returns a (value, new_pos) pair. + """ + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + + +def _SignedVarintDecoder(bits, result_type): + """Like _VarintDecoder() but decodes signed values.""" + + signbit = 1 << (bits - 1) + mask = (1 << bits) - 1 + + def DecodeVarint(buffer, pos): + result = 0 + shift = 0 + while 1: + b = six.indexbytes(buffer, pos) + result |= ((b & 0x7f) << shift) + pos += 1 + if not (b & 0x80): + result &= mask + result = (result ^ signbit) - signbit + result = result_type(result) + return (result, pos) + shift += 7 + if shift >= 64: + raise _DecodeError('Too many bytes when decoding varint.') + return DecodeVarint + +# We force 32-bit values to int and 64-bit values to long to make +# alternate implementations where the distinction is more significant +# (e.g. the C++ implementation) simpler. + +_DecodeVarint = _VarintDecoder((1 << 64) - 1, long) +_DecodeSignedVarint = _SignedVarintDecoder(64, long) + +# Use these versions for values which must be limited to 32 bits. +_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int) +_DecodeSignedVarint32 = _SignedVarintDecoder(32, int) + + +def ReadTag(buffer, pos): + """Read a tag from the memoryview, and return a (tag_bytes, new_pos) tuple. + + We return the raw bytes of the tag rather than decoding them. The raw + bytes can then be used to look up the proper decoder. This effectively allows + us to trade some work that would be done in pure-python (decoding a varint) + for work that is done in C (searching for a byte string in a hash table). + In a low-level language it would be much cheaper to decode the varint and + use that, but not in Python. + + Args: + buffer: memoryview object of the encoded bytes + pos: int of the current position to start from + + Returns: + Tuple[bytes, int] of the tag data and new position. + """ + start = pos + while six.indexbytes(buffer, pos) & 0x80: + pos += 1 + pos += 1 + + tag_bytes = buffer[start:pos].tobytes() + return tag_bytes, pos + + +# -------------------------------------------------------------------- + + +def _SimpleDecoder(wire_type, decode_value): + """Return a constructor for a decoder for fields of a particular type. + + Args: + wire_type: The field's wire type. + decode_value: A function which decodes an individual value, e.g. + _DecodeVarint() + """ + + def SpecificDecoder(field_number, is_repeated, is_packed, key, new_default, + clear_if_default=False): + if is_packed: + local_DecodeVarint = _DecodeVarint + def DecodePackedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + (endpoint, pos) = local_DecodeVarint(buffer, pos) + endpoint += pos + if endpoint > end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + (element, pos) = decode_value(buffer, pos) + value.append(element) + if pos > endpoint: + del value[-1] # Discard corrupt value. + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_type) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = decode_value(buffer, pos) + value.append(element) + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (new_value, pos) = decode_value(buffer, pos) + if pos > end: + raise _DecodeError('Truncated message.') + if clear_if_default and not new_value: + field_dict.pop(key, None) + else: + field_dict[key] = new_value + return pos + return DecodeField + + return SpecificDecoder + + +def _ModifiedDecoder(wire_type, decode_value, modify_value): + """Like SimpleDecoder but additionally invokes modify_value on every value + before storing it. Usually modify_value is ZigZagDecode. + """ + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + def InnerDecode(buffer, pos): + (result, new_pos) = decode_value(buffer, pos) + return (modify_value(result), new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _StructPackDecoder(wire_type, format): + """Return a constructor for a decoder for a fixed-width field. + + Args: + wire_type: The field's wire type. + format: The format string to pass to struct.unpack(). + """ + + value_size = struct.calcsize(format) + local_unpack = struct.unpack + + # Reusing _SimpleDecoder is slightly slower than copying a bunch of code, but + # not enough to make a significant difference. + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + + def InnerDecode(buffer, pos): + new_pos = pos + value_size + result = local_unpack(format, buffer[pos:new_pos])[0] + return (result, new_pos) + return _SimpleDecoder(wire_type, InnerDecode) + + +def _FloatDecoder(): + """Returns a decoder for a float field. + + This code works around a bug in struct.unpack for non-finite 32-bit + floating-point values. + """ + + local_unpack = struct.unpack + + def InnerDecode(buffer, pos): + """Decode serialized float to a float and new position. + + Args: + buffer: memoryview of the serialized bytes + pos: int, position in the memory view to start at. + + Returns: + Tuple[float, int] of the deserialized float value and new position + in the serialized data. + """ + # We expect a 32-bit value in little-endian byte order. Bit 1 is the sign + # bit, bits 2-9 represent the exponent, and bits 10-32 are the significand. + new_pos = pos + 4 + float_bytes = buffer[pos:new_pos].tobytes() + + # If this value has all its exponent bits set, then it's non-finite. + # In Python 2.4, struct.unpack will convert it to a finite 64-bit value. + # To avoid that, we parse it specially. + if (float_bytes[3:4] in b'\x7F\xFF' and float_bytes[2:3] >= b'\x80'): + # If at least one significand bit is set... + if float_bytes[0:3] != b'\x00\x00\x80': + return (_NAN, new_pos) + # If sign bit is set... + if float_bytes[3:4] == b'\xFF': + return (_NEG_INF, new_pos) + return (_POS_INF, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack('= b'\xF0') + and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')): + return (_NAN, new_pos) + + # Note that we expect someone up-stack to catch struct.error and convert + # it to _DecodeError -- this way we don't have to set up exception- + # handling blocks every time we parse one value. + result = local_unpack(' end: + raise _DecodeError('Truncated message.') + while pos < endpoint: + value_start_pos = pos + (element, pos) = _DecodeSignedVarint32(buffer, pos) + # pylint: disable=protected-access + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, element) + # pylint: enable=protected-access + if pos > endpoint: + if element in enum_type.values_by_number: + del value[-1] # Discard corrupt value. + else: + del message._unknown_fields[-1] + # pylint: disable=protected-access + del message._unknown_field_set._values[-1] + # pylint: enable=protected-access + raise _DecodeError('Packed element was truncated.') + return pos + return DecodePackedField + elif is_repeated: + tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + """Decode serialized repeated enum to its value and a new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (element, new_pos) = _DecodeSignedVarint32(buffer, pos) + # pylint: disable=protected-access + if element in enum_type.values_by_number: + value.append(element) + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append( + (tag_bytes, buffer[pos:new_pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, element) + # pylint: enable=protected-access + # Predict that the next tag is another copy of the same repeated + # field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos >= end: + # Prediction failed. Return. + if new_pos > end: + raise _DecodeError('Truncated message.') + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + """Decode serialized repeated enum to its value and a new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ + value_start_pos = pos + (enum_value, pos) = _DecodeSignedVarint32(buffer, pos) + if pos > end: + raise _DecodeError('Truncated message.') + if clear_if_default and not enum_value: + field_dict.pop(key, None) + return pos + # pylint: disable=protected-access + if enum_value in enum_type.values_by_number: + field_dict[key] = enum_value + else: + if not message._unknown_fields: + message._unknown_fields = [] + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_VARINT) + message._unknown_fields.append( + (tag_bytes, buffer[value_start_pos:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + field_number, wire_format.WIRETYPE_VARINT, enum_value) + # pylint: enable=protected-access + return pos + return DecodeField + + +# -------------------------------------------------------------------- + + +Int32Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32) + +Int64Decoder = _SimpleDecoder( + wire_format.WIRETYPE_VARINT, _DecodeSignedVarint) + +UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32) +UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint) + +SInt32Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode) +SInt64Decoder = _ModifiedDecoder( + wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, ' _UCS2_MAXUNICODE: + # Only do the check for python2 ucs4 when is_strict_utf8 enabled + if _SURROGATE_PATTERN.search(value): + reason = ('String field %s contains invalid UTF-8 data when parsing' + 'a protocol buffer: surrogates not allowed. Use' + 'the bytes type if you intend to send raw bytes.') % ( + key.full_name) + raise message.DecodeError(reason) + + return value + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + value.append(_ConvertToUnicode(buffer[pos:new_pos])) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + if clear_if_default and not size: + field_dict.pop(key, None) + else: + field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos]) + return new_pos + return DecodeField + + +def BytesDecoder(field_number, is_repeated, is_packed, key, new_default, + clear_if_default=False): + """Returns a decoder for a bytes field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + value.append(buffer[pos:new_pos].tobytes()) + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated string.') + if clear_if_default and not size: + field_dict.pop(key, None) + else: + field_dict[key] = buffer[pos:new_pos].tobytes() + return new_pos + return DecodeField + + +def GroupDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a group field.""" + + end_tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_END_GROUP) + end_tag_len = len(end_tag_bytes) + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_START_GROUP) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value.add()._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read sub-message. + pos = value._InternalParse(buffer, pos, end) + # Read end tag. + new_pos = pos+end_tag_len + if buffer[pos:new_pos] != end_tag_bytes or new_pos > end: + raise _DecodeError('Missing group end tag.') + return new_pos + return DecodeField + + +def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): + """Returns a decoder for a message field.""" + + local_DecodeVarint = _DecodeVarint + + assert not is_packed + if is_repeated: + tag_bytes = encoder.TagBytes(field_number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + def DecodeRepeatedField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value.add()._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + return DecodeRepeatedField + else: + def DecodeField(buffer, pos, end, message, field_dict): + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + if value._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + return new_pos + return DecodeField + + +# -------------------------------------------------------------------- + +MESSAGE_SET_ITEM_TAG = encoder.TagBytes(1, wire_format.WIRETYPE_START_GROUP) + +def MessageSetItemDecoder(descriptor): + """Returns a decoder for a MessageSet item. + + The parameter is the message Descriptor. + + The message set message looks like this: + message MessageSet { + repeated group Item = 1 { + required int32 type_id = 2; + required string message = 3; + } + } + """ + + type_id_tag_bytes = encoder.TagBytes(2, wire_format.WIRETYPE_VARINT) + message_tag_bytes = encoder.TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED) + item_end_tag_bytes = encoder.TagBytes(1, wire_format.WIRETYPE_END_GROUP) + + local_ReadTag = ReadTag + local_DecodeVarint = _DecodeVarint + local_SkipField = SkipField + + def DecodeItem(buffer, pos, end, message, field_dict): + """Decode serialized message set to its value and new position. + + Args: + buffer: memoryview of the serialized bytes. + pos: int, position in the memory view to start at. + end: int, end position of serialized data + message: Message object to store unknown fields in + field_dict: Map[Descriptor, Any] to store decoded values in. + + Returns: + int, new position in serialized data. + """ + message_set_item_start = pos + type_id = -1 + message_start = -1 + message_end = -1 + + # Technically, type_id and message can appear in any order, so we need + # a little loop here. + while 1: + (tag_bytes, pos) = local_ReadTag(buffer, pos) + if tag_bytes == type_id_tag_bytes: + (type_id, pos) = local_DecodeVarint(buffer, pos) + elif tag_bytes == message_tag_bytes: + (size, message_start) = local_DecodeVarint(buffer, pos) + pos = message_end = message_start + size + elif tag_bytes == item_end_tag_bytes: + break + else: + pos = SkipField(buffer, pos, end, tag_bytes) + if pos == -1: + raise _DecodeError('Missing group end tag.') + + if pos > end: + raise _DecodeError('Truncated message.') + + if type_id == -1: + raise _DecodeError('MessageSet item missing type_id.') + if message_start == -1: + raise _DecodeError('MessageSet item missing message.') + + extension = message.Extensions._FindExtensionByNumber(type_id) + # pylint: disable=protected-access + if extension is not None: + value = field_dict.get(extension) + if value is None: + message_type = extension.message_type + if not hasattr(message_type, '_concrete_class'): + # pylint: disable=protected-access + message._FACTORY.GetPrototype(message_type) + value = field_dict.setdefault( + extension, message_type._concrete_class()) + if value._InternalParse(buffer, message_start,message_end) != message_end: + # The only reason _InternalParse would return early is if it encountered + # an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + else: + if not message._unknown_fields: + message._unknown_fields = [] + message._unknown_fields.append( + (MESSAGE_SET_ITEM_TAG, buffer[message_set_item_start:pos].tobytes())) + if message._unknown_field_set is None: + message._unknown_field_set = containers.UnknownFieldSet() + message._unknown_field_set._add( + type_id, + wire_format.WIRETYPE_LENGTH_DELIMITED, + buffer[message_start:message_end].tobytes()) + # pylint: enable=protected-access + + return pos + + return DecodeItem + +# -------------------------------------------------------------------- + +def MapDecoder(field_descriptor, new_default, is_message_map): + """Returns a decoder for a map field.""" + + key = field_descriptor + tag_bytes = encoder.TagBytes(field_descriptor.number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + local_DecodeVarint = _DecodeVarint + # Can't read _concrete_class yet; might not be initialized. + message_type = field_descriptor.message_type + + def DecodeMap(buffer, pos, end, message, field_dict): + submsg = message_type._concrete_class() + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + submsg.Clear() + if submsg._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + + if is_message_map: + value[submsg.key].CopyFrom(submsg.value) + else: + value[submsg.key] = submsg.value + + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + + return DecodeMap + +# -------------------------------------------------------------------- +# Optimization is not as heavy here because calls to SkipField() are rare, +# except for handling end-group tags. + +def _SkipVarint(buffer, pos, end): + """Skip a varint value. Returns the new position.""" + # Previously ord(buffer[pos]) raised IndexError when pos is out of range. + # With this code, ord(b'') raises TypeError. Both are handled in + # python_message.py to generate a 'Truncated message' error. + while ord(buffer[pos:pos+1].tobytes()) & 0x80: + pos += 1 + pos += 1 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + +def _SkipFixed64(buffer, pos, end): + """Skip a fixed64 value. Returns the new position.""" + + pos += 8 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + + +def _DecodeFixed64(buffer, pos): + """Decode a fixed64.""" + new_pos = pos + 8 + return (struct.unpack(' end: + raise _DecodeError('Truncated message.') + return pos + + +def _SkipGroup(buffer, pos, end): + """Skip sub-group. Returns the new position.""" + + while 1: + (tag_bytes, pos) = ReadTag(buffer, pos) + new_pos = SkipField(buffer, pos, end, tag_bytes) + if new_pos == -1: + return pos + pos = new_pos + + +def _DecodeUnknownFieldSet(buffer, pos, end_pos=None): + """Decode UnknownFieldSet. Returns the UnknownFieldSet and new position.""" + + unknown_field_set = containers.UnknownFieldSet() + while end_pos is None or pos < end_pos: + (tag_bytes, pos) = ReadTag(buffer, pos) + (tag, _) = _DecodeVarint(tag_bytes, 0) + field_number, wire_type = wire_format.UnpackTag(tag) + if wire_type == wire_format.WIRETYPE_END_GROUP: + break + (data, pos) = _DecodeUnknownField(buffer, pos, wire_type) + # pylint: disable=protected-access + unknown_field_set._add(field_number, wire_type, data) + + return (unknown_field_set, pos) + + +def _DecodeUnknownField(buffer, pos, wire_type): + """Decode a unknown field. Returns the UnknownField and new position.""" + + if wire_type == wire_format.WIRETYPE_VARINT: + (data, pos) = _DecodeVarint(buffer, pos) + elif wire_type == wire_format.WIRETYPE_FIXED64: + (data, pos) = _DecodeFixed64(buffer, pos) + elif wire_type == wire_format.WIRETYPE_FIXED32: + (data, pos) = _DecodeFixed32(buffer, pos) + elif wire_type == wire_format.WIRETYPE_LENGTH_DELIMITED: + (size, pos) = _DecodeVarint(buffer, pos) + data = buffer[pos:pos+size].tobytes() + pos += size + elif wire_type == wire_format.WIRETYPE_START_GROUP: + (data, pos) = _DecodeUnknownFieldSet(buffer, pos) + elif wire_type == wire_format.WIRETYPE_END_GROUP: + return (0, -1) + else: + raise _DecodeError('Wrong wire type in tag.') + + return (data, pos) + + +def _EndGroup(buffer, pos, end): + """Skipping an END_GROUP tag returns -1 to tell the parent loop to break.""" + + return -1 + + +def _SkipFixed32(buffer, pos, end): + """Skip a fixed32 value. Returns the new position.""" + + pos += 4 + if pos > end: + raise _DecodeError('Truncated message.') + return pos + + +def _DecodeFixed32(buffer, pos): + """Decode a fixed32.""" + + new_pos = pos + 4 + return (struct.unpack('>= 7 + while value: + write(local_int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(local_int2byte(bits)) + + return EncodeVarint + + +def _SignedVarintEncoder(): + """Return an encoder for a basic signed varint value (does not include + tag).""" + + local_int2byte = six.int2byte + def EncodeSignedVarint(write, value, unused_deterministic=None): + if value < 0: + value += (1 << 64) + bits = value & 0x7f + value >>= 7 + while value: + write(local_int2byte(0x80|bits)) + bits = value & 0x7f + value >>= 7 + return write(local_int2byte(bits)) + + return EncodeSignedVarint + + +_EncodeVarint = _VarintEncoder() +_EncodeSignedVarint = _SignedVarintEncoder() + + +def _VarintBytes(value): + """Encode the given integer as a varint and return the bytes. This is only + called at startup time so it doesn't need to be fast.""" + + pieces = [] + _EncodeVarint(pieces.append, value, True) + return b"".join(pieces) + + +def TagBytes(field_number, wire_type): + """Encode the given tag and return the bytes. Only called at startup.""" + + return six.binary_type( + _VarintBytes(wire_format.PackTag(field_number, wire_type))) + +# -------------------------------------------------------------------- +# As with sizers (see above), we have a number of common encoder +# implementations. + + +def _SimpleEncoder(wire_type, encode_value, compute_value_size): + """Return a constructor for an encoder for fields of a particular type. + + Args: + wire_type: The field's wire type, for encoding tags. + encode_value: A function which encodes an individual value, e.g. + _EncodeVarint(). + compute_value_size: A function which computes the size of an individual + value, e.g. _VarintSize(). + """ + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(element) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, element, deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, element, deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, value, deterministic) + return EncodeField + + return SpecificEncoder + + +def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value): + """Like SimpleEncoder but additionally invokes modify_value on every value + before passing it to encode_value. Usually modify_value is ZigZagEncode.""" + + def SpecificEncoder(field_number, is_repeated, is_packed): + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + size = 0 + for element in value: + size += compute_value_size(modify_value(element)) + local_EncodeVarint(write, size, deterministic) + for element in value: + encode_value(write, modify_value(element), deterministic) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, deterministic): + for element in value: + write(tag_bytes) + encode_value(write, modify_value(element), deterministic) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, deterministic): + write(tag_bytes) + return encode_value(write, modify_value(value), deterministic) + return EncodeField + + return SpecificEncoder + + +def _StructPackEncoder(wire_type, format): + """Return a constructor for an encoder for a fixed-width field. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + write(local_struct_pack(format, element)) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + write(local_struct_pack(format, element)) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + return write(local_struct_pack(format, value)) + return EncodeField + + return SpecificEncoder + + +def _FloatingPointEncoder(wire_type, format): + """Return a constructor for an encoder for float fields. + + This is like StructPackEncoder, but catches errors that may be due to + passing non-finite floating-point values to struct.pack, and makes a + second attempt to encode those values. + + Args: + wire_type: The field's wire type, for encoding tags. + format: The format string to pass to struct.pack(). + """ + + value_size = struct.calcsize(format) + if value_size == 4: + def EncodeNonFiniteOrRaise(write, value): + # Remember that the serialized form uses little-endian byte order. + if value == _POS_INF: + write(b'\x00\x00\x80\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x80\xFF') + elif value != value: # NaN + write(b'\x00\x00\xC0\x7F') + else: + raise + elif value_size == 8: + def EncodeNonFiniteOrRaise(write, value): + if value == _POS_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') + elif value == _NEG_INF: + write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') + elif value != value: # NaN + write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') + else: + raise + else: + raise ValueError('Can\'t encode floating-point values that are ' + '%d bytes long (only 4 or 8)' % value_size) + + def SpecificEncoder(field_number, is_repeated, is_packed): + local_struct_pack = struct.pack + if is_packed: + tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) + local_EncodeVarint = _EncodeVarint + def EncodePackedField(write, value, deterministic): + write(tag_bytes) + local_EncodeVarint(write, len(value) * value_size, deterministic) + for element in value: + # This try/except block is going to be faster than any code that + # we could write to check whether element is finite. + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodePackedField + elif is_repeated: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeRepeatedField(write, value, unused_deterministic=None): + for element in value: + write(tag_bytes) + try: + write(local_struct_pack(format, element)) + except SystemError: + EncodeNonFiniteOrRaise(write, element) + return EncodeRepeatedField + else: + tag_bytes = TagBytes(field_number, wire_type) + def EncodeField(write, value, unused_deterministic=None): + write(tag_bytes) + try: + write(local_struct_pack(format, value)) + except SystemError: + EncodeNonFiniteOrRaise(write, value) + return EncodeField + + return SpecificEncoder + + +# ==================================================================== +# Here we declare an encoder constructor for each field type. These work +# very similarly to sizer constructors, described earlier. + + +Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) + +UInt32Encoder = UInt64Encoder = _SimpleEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) + +SInt32Encoder = SInt64Encoder = _ModifiedEncoder( + wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, + wire_format.ZigZagEncode) + +# Note that Python conveniently guarantees that when using the '<' prefix on +# formats, they will also have the same size across all platforms (as opposed +# to without the prefix, where their sizes depend on the C compiler's basic +# type sizes). +Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, ' 0 + self._fields = {} + # Contains a mapping from oneof field descriptors to the descriptor + # of the currently set field in that oneof field. + self._oneofs = {} + + # _unknown_fields is () when empty for efficiency, and will be turned into + # a list if fields are added. + self._unknown_fields = () + # _unknown_field_set is None when empty for efficiency, and will be + # turned into UnknownFieldSet struct if fields are added. + self._unknown_field_set = None # pylint: disable=protected-access + self._is_present_in_parent = False + self._listener = message_listener_mod.NullMessageListener() + self._listener_for_children = _Listener(self) + for field_name, field_value in kwargs.items(): + field = _GetFieldByName(message_descriptor, field_name) + if field is None: + raise TypeError('%s() got an unexpected keyword argument "%s"' % + (message_descriptor.name, field_name)) + if field_value is None: + # field=None is the same as no field at all. + continue + if field.label == _FieldDescriptor.LABEL_REPEATED: + copy = field._default_constructor(self) + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite + if _IsMapField(field): + if _IsMessageMapField(field): + for key in field_value: + copy[key].MergeFrom(field_value[key]) + else: + copy.update(field_value) + else: + for val in field_value: + if isinstance(val, dict): + copy.add(**val) + else: + copy.add().MergeFrom(val) + else: # Scalar + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = [_GetIntegerEnumValue(field.enum_type, val) + for val in field_value] + copy.extend(field_value) + self._fields[field] = copy + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + copy = field._default_constructor(self) + new_val = field_value + if isinstance(field_value, dict): + new_val = field.message_type._concrete_class(**field_value) + try: + copy.MergeFrom(new_val) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + self._fields[field] = copy + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = _GetIntegerEnumValue(field.enum_type, field_value) + try: + setattr(self, field_name, field_value) + except TypeError: + _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) + + init.__module__ = None + init.__doc__ = None + cls.__init__ = init + + +def _GetFieldByName(message_descriptor, field_name): + """Returns a field descriptor by field name. + + Args: + message_descriptor: A Descriptor describing all fields in message. + field_name: The name of the field to retrieve. + Returns: + The field descriptor associated with the field name. + """ + try: + return message_descriptor.fields_by_name[field_name] + except KeyError: + raise ValueError('Protocol message %s has no "%s" field.' % + (message_descriptor.name, field_name)) + + +def _AddPropertiesForFields(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + for field in descriptor.fields: + _AddPropertiesForField(field, cls) + + if descriptor.is_extendable: + # _ExtensionDict is just an adaptor with no state so we allocate a new one + # every time it is accessed. + cls.Extensions = property(lambda self: _ExtensionDict(self)) + + +def _AddPropertiesForField(field, cls): + """Adds a public property for a protocol message field. + Clients can use this property to get and (in the case + of non-repeated scalar fields) directly set the value + of a protocol message field. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # Catch it if we add other types that we should + # handle specially here. + assert _FieldDescriptor.MAX_CPPTYPE == 10 + + constant_name = field.name.upper() + '_FIELD_NUMBER' + setattr(cls, constant_name, field.number) + + if field.label == _FieldDescriptor.LABEL_REPEATED: + _AddPropertiesForRepeatedField(field, cls) + elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + _AddPropertiesForNonRepeatedCompositeField(field, cls) + else: + _AddPropertiesForNonRepeatedScalarField(field, cls) + + +class _FieldProperty(property): + __slots__ = ('DESCRIPTOR',) + + def __init__(self, descriptor, getter, setter, doc): + property.__init__(self, getter, setter, doc=doc) + self.DESCRIPTOR = descriptor + + +def _AddPropertiesForRepeatedField(field, cls): + """Adds a public property for a "repeated" protocol message field. Clients + can use this property to get the value of the field, which will be either a + RepeatedScalarFieldContainer or RepeatedCompositeFieldContainer (see + below). + + Note that when clients add values to these containers, we perform + type-checking in the case of repeated scalar fields, and we also set any + necessary "has" bits as a side-effect. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to repeated field ' + '"%s" in protocol message object.' % proto_field_name) + + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedScalarField(field, cls): + """Adds a public property for a nonrepeated, scalar protocol message field. + Clients can use this property to get and directly set the value of the field. + Note that when the client sets the value of a field by using this property, + all necessary "has" bits are set as a side-effect, and we also perform + type-checking. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + type_checker = type_checkers.GetTypeChecker(field) + default_value = field.default_value + is_proto3 = field.containing_type.syntax == 'proto3' + + def getter(self): + # TODO(protobuf-team): This may be broken since there may not be + # default_value. Combine with has_default_value somehow. + return self._fields.get(field, default_value) + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + clear_when_set_to_default = is_proto3 and not field.containing_oneof + + def field_setter(self, new_value): + # pylint: disable=protected-access + # Testing the value for truthiness captures all of the proto3 defaults + # (0, 0.0, enum 0, and False). + try: + new_value = type_checker.CheckValue(new_value) + except TypeError as e: + raise TypeError( + 'Cannot set %s to %.1024r: %s' % (field.full_name, new_value, e)) + if clear_when_set_to_default and not new_value: + self._fields.pop(field, None) + else: + self._fields[field] = new_value + # Check _cached_byte_size_dirty inline to improve performance, since scalar + # setters are called frequently. + if not self._cached_byte_size_dirty: + self._Modified() + + if field.containing_oneof: + def setter(self, new_value): + field_setter(self, new_value) + self._UpdateOneofState(field) + else: + setter = field_setter + + setter.__module__ = None + setter.__doc__ = 'Setter for %s.' % proto_field_name + + # Add a property to encapsulate the getter/setter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) + + +def _AddPropertiesForNonRepeatedCompositeField(field, cls): + """Adds a public property for a nonrepeated, composite protocol message field. + A composite field is a "group" or "message" field. + + Clients can use this property to get the value of the field, but cannot + assign to the property directly. + + Args: + field: A FieldDescriptor for this field. + cls: The class we're constructing. + """ + # TODO(robinson): Remove duplication with similar method + # for non-repeated scalars. + proto_field_name = field.name + property_name = _PropertyName(proto_field_name) + + def getter(self): + field_value = self._fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + + # Atomically check if another thread has preempted us and, if not, swap + # in the new object we just created. If someone has preempted us, we + # take that object and discard ours. + # WARNING: We are relying on setdefault() being atomic. This is true + # in CPython but we haven't investigated others. This warning appears + # in several other locations in this file. + field_value = self._fields.setdefault(field, field_value) + return field_value + getter.__module__ = None + getter.__doc__ = 'Getter for %s.' % proto_field_name + + # We define a setter just so we can throw an exception with a more + # helpful error message. + def setter(self, new_value): + raise AttributeError('Assignment not allowed to composite field ' + '"%s" in protocol message object.' % proto_field_name) + + # Add a property to encapsulate the getter. + doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name + setattr(cls, property_name, _FieldProperty(field, getter, setter, doc=doc)) + + +def _AddPropertiesForExtensions(descriptor, cls): + """Adds properties for all fields in this protocol message type.""" + extensions = descriptor.extensions_by_name + for extension_name, extension_field in extensions.items(): + constant_name = extension_name.upper() + '_FIELD_NUMBER' + setattr(cls, constant_name, extension_field.number) + + # TODO(amauryfa): Migrate all users of these attributes to functions like + # pool.FindExtensionByNumber(descriptor). + if descriptor.file is not None: + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + pool = descriptor.file.pool + cls._extensions_by_number = pool._extensions_by_number[descriptor] + cls._extensions_by_name = pool._extensions_by_name[descriptor] + +def _AddStaticMethods(cls): + # TODO(robinson): This probably needs to be thread-safe(?) + def RegisterExtension(extension_handle): + extension_handle.containing_type = cls.DESCRIPTOR + # TODO(amauryfa): Use cls.MESSAGE_FACTORY.pool when available. + # pylint: disable=protected-access + cls.DESCRIPTOR.file.pool._AddExtensionDescriptor(extension_handle) + _AttachFieldHelpers(cls, extension_handle) + cls.RegisterExtension = staticmethod(RegisterExtension) + + def FromString(s): + message = cls() + message.MergeFromString(s) + return message + cls.FromString = staticmethod(FromString) + + +def _IsPresent(item): + """Given a (FieldDescriptor, value) tuple from _fields, return true if the + value should be included in the list returned by ListFields().""" + + if item[0].label == _FieldDescriptor.LABEL_REPEATED: + return bool(item[1]) + elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + return item[1]._is_present_in_parent + else: + return True + + +def _AddListFieldsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ListFields(self): + all_fields = [item for item in self._fields.items() if _IsPresent(item)] + all_fields.sort(key = lambda item: item[0].number) + return all_fields + + cls.ListFields = ListFields + +_PROTO3_ERROR_TEMPLATE = \ + ('Protocol message %s has no non-repeated submessage field "%s" ' + 'nor marked as optional') +_PROTO2_ERROR_TEMPLATE = 'Protocol message %s has no non-repeated field "%s"' + +def _AddHasFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + is_proto3 = (message_descriptor.syntax == "proto3") + error_msg = _PROTO3_ERROR_TEMPLATE if is_proto3 else _PROTO2_ERROR_TEMPLATE + + hassable_fields = {} + for field in message_descriptor.fields: + if field.label == _FieldDescriptor.LABEL_REPEATED: + continue + # For proto3, only submessages and fields inside a oneof have presence. + if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and + not field.containing_oneof): + continue + hassable_fields[field.name] = field + + # Has methods are supported for oneof descriptors. + for oneof in message_descriptor.oneofs: + hassable_fields[oneof.name] = oneof + + def HasField(self, field_name): + try: + field = hassable_fields[field_name] + except KeyError: + raise ValueError(error_msg % (message_descriptor.full_name, field_name)) + + if isinstance(field, descriptor_mod.OneofDescriptor): + try: + return HasField(self, self._oneofs[field].name) + except KeyError: + return False + else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(field) + return value is not None and value._is_present_in_parent + else: + return field in self._fields + + cls.HasField = HasField + + +def _AddClearFieldMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def ClearField(self, field_name): + try: + field = message_descriptor.fields_by_name[field_name] + except KeyError: + try: + field = message_descriptor.oneofs_by_name[field_name] + if field in self._oneofs: + field = self._oneofs[field] + else: + return + except KeyError: + raise ValueError('Protocol message %s has no "%s" field.' % + (message_descriptor.name, field_name)) + + if field in self._fields: + # To match the C++ implementation, we need to invalidate iterators + # for map fields when ClearField() happens. + if hasattr(self._fields[field], 'InvalidateIterators'): + self._fields[field].InvalidateIterators() + + # Note: If the field is a sub-message, its listener will still point + # at us. That's fine, because the worst than can happen is that it + # will call _Modified() and invalidate our byte size. Big deal. + del self._fields[field] + + if self._oneofs.get(field.containing_oneof, None) is field: + del self._oneofs[field.containing_oneof] + + # Always call _Modified() -- even if nothing was changed, this is + # a mutating method, and thus calling it should cause the field to become + # present in the parent message. + self._Modified() + + cls.ClearField = ClearField + + +def _AddClearExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def ClearExtension(self, extension_handle): + extension_dict._VerifyExtensionHandle(self, extension_handle) + + # Similar to ClearField(), above. + if extension_handle in self._fields: + del self._fields[extension_handle] + self._Modified() + cls.ClearExtension = ClearExtension + + +def _AddHasExtensionMethod(cls): + """Helper for _AddMessageMethods().""" + def HasExtension(self, extension_handle): + extension_dict._VerifyExtensionHandle(self, extension_handle) + if extension_handle.label == _FieldDescriptor.LABEL_REPEATED: + raise KeyError('"%s" is repeated.' % extension_handle.full_name) + + if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + value = self._fields.get(extension_handle) + return value is not None and value._is_present_in_parent + else: + return extension_handle in self._fields + cls.HasExtension = HasExtension + +def _InternalUnpackAny(msg): + """Unpacks Any message and returns the unpacked message. + + This internal method is different from public Any Unpack method which takes + the target message as argument. _InternalUnpackAny method does not have + target message type and need to find the message type in descriptor pool. + + Args: + msg: An Any message to be unpacked. + + Returns: + The unpacked message. + """ + # TODO(amauryfa): Don't use the factory of generated messages. + # To make Any work with custom factories, use the message factory of the + # parent message. + # pylint: disable=g-import-not-at-top + from google.protobuf import symbol_database + factory = symbol_database.Default() + + type_url = msg.type_url + + if not type_url: + return None + + # TODO(haberman): For now we just strip the hostname. Better logic will be + # required. + type_name = type_url.split('/')[-1] + descriptor = factory.pool.FindMessageTypeByName(type_name) + + if descriptor is None: + return None + + message_class = factory.GetPrototype(descriptor) + message = message_class() + + message.ParseFromString(msg.value) + return message + + +def _AddEqualsMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __eq__(self, other): + if (not isinstance(other, message_mod.Message) or + other.DESCRIPTOR != self.DESCRIPTOR): + return False + + if self is other: + return True + + if self.DESCRIPTOR.full_name == _AnyFullTypeName: + any_a = _InternalUnpackAny(self) + any_b = _InternalUnpackAny(other) + if any_a and any_b: + return any_a == any_b + + if not self.ListFields() == other.ListFields(): + return False + + # TODO(jieluo): Fix UnknownFieldSet to consider MessageSet extensions, + # then use it for the comparison. + unknown_fields = list(self._unknown_fields) + unknown_fields.sort() + other_unknown_fields = list(other._unknown_fields) + other_unknown_fields.sort() + return unknown_fields == other_unknown_fields + + cls.__eq__ = __eq__ + + +def _AddStrMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __str__(self): + return text_format.MessageToString(self) + cls.__str__ = __str__ + + +def _AddReprMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def __repr__(self): + return text_format.MessageToString(self) + cls.__repr__ = __repr__ + + +def _AddUnicodeMethod(unused_message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def __unicode__(self): + return text_format.MessageToString(self, as_utf8=True).decode('utf-8') + cls.__unicode__ = __unicode__ + + +def _BytesForNonRepeatedElement(value, field_number, field_type): + """Returns the number of bytes needed to serialize a non-repeated element. + The returned byte count includes space for tag information and any + other additional space associated with serializing value. + + Args: + value: Value we're serializing. + field_number: Field number of this value. (Since the field number + is stored as part of a varint-encoded tag, this has an impact + on the total bytes required to serialize the value). + field_type: The type of the field. One of the TYPE_* constants + within FieldDescriptor. + """ + try: + fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type] + return fn(field_number, value) + except KeyError: + raise message_mod.EncodeError('Unrecognized field type: %d' % field_type) + + +def _AddByteSizeMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def ByteSize(self): + if not self._cached_byte_size_dirty: + return self._cached_byte_size + + size = 0 + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + size = descriptor.fields_by_name['key']._sizer(self.key) + size += descriptor.fields_by_name['value']._sizer(self.value) + else: + for field_descriptor, field_value in self.ListFields(): + size += field_descriptor._sizer(field_value) + for tag_bytes, value_bytes in self._unknown_fields: + size += len(tag_bytes) + len(value_bytes) + + self._cached_byte_size = size + self._cached_byte_size_dirty = False + self._listener_for_children.dirty = False + return size + + cls.ByteSize = ByteSize + + +def _AddSerializeToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializeToString(self, **kwargs): + # Check if the message has all of its required fields set. + if not self.IsInitialized(): + raise message_mod.EncodeError( + 'Message %s is missing required fields: %s' % ( + self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors()))) + return self.SerializePartialToString(**kwargs) + cls.SerializeToString = SerializeToString + + +def _AddSerializePartialToStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + + def SerializePartialToString(self, **kwargs): + out = BytesIO() + self._InternalSerialize(out.write, **kwargs) + return out.getvalue() + cls.SerializePartialToString = SerializePartialToString + + def InternalSerialize(self, write_bytes, deterministic=None): + if deterministic is None: + deterministic = ( + api_implementation.IsPythonDefaultSerializationDeterministic()) + else: + deterministic = bool(deterministic) + + descriptor = self.DESCRIPTOR + if descriptor.GetOptions().map_entry: + # Fields of map entry should always be serialized. + descriptor.fields_by_name['key']._encoder( + write_bytes, self.key, deterministic) + descriptor.fields_by_name['value']._encoder( + write_bytes, self.value, deterministic) + else: + for field_descriptor, field_value in self.ListFields(): + field_descriptor._encoder(write_bytes, field_value, deterministic) + for tag_bytes, value_bytes in self._unknown_fields: + write_bytes(tag_bytes) + write_bytes(value_bytes) + cls._InternalSerialize = InternalSerialize + + +def _AddMergeFromStringMethod(message_descriptor, cls): + """Helper for _AddMessageMethods().""" + def MergeFromString(self, serialized): + if isinstance(serialized, memoryview) and six.PY2: + raise TypeError( + 'memoryview not supported in Python 2 with the pure Python proto ' + 'implementation: this is to maintain compatibility with the C++ ' + 'implementation') + + serialized = memoryview(serialized) + length = len(serialized) + try: + if self._InternalParse(serialized, 0, length) != length: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise message_mod.DecodeError('Unexpected end-group tag.') + except (IndexError, TypeError): + # Now ord(buf[p:p+1]) == ord('') gets TypeError. + raise message_mod.DecodeError('Truncated message.') + except struct.error as e: + raise message_mod.DecodeError(e) + return length # Return this for legacy reasons. + cls.MergeFromString = MergeFromString + + local_ReadTag = decoder.ReadTag + local_SkipField = decoder.SkipField + decoders_by_tag = cls._decoders_by_tag + + def InternalParse(self, buffer, pos, end): + """Create a message from serialized bytes. + + Args: + self: Message, instance of the proto message object. + buffer: memoryview of the serialized data. + pos: int, position to start in the serialized data. + end: int, end position of the serialized data. + + Returns: + Message object. + """ + # Guard against internal misuse, since this function is called internally + # quite extensively, and its easy to accidentally pass bytes. + assert isinstance(buffer, memoryview) + self._Modified() + field_dict = self._fields + # pylint: disable=protected-access + unknown_field_set = self._unknown_field_set + while pos != end: + (tag_bytes, new_pos) = local_ReadTag(buffer, pos) + field_decoder, field_desc = decoders_by_tag.get(tag_bytes, (None, None)) + if field_decoder is None: + if not self._unknown_fields: # pylint: disable=protected-access + self._unknown_fields = [] # pylint: disable=protected-access + if unknown_field_set is None: + # pylint: disable=protected-access + self._unknown_field_set = containers.UnknownFieldSet() + # pylint: disable=protected-access + unknown_field_set = self._unknown_field_set + # pylint: disable=protected-access + (tag, _) = decoder._DecodeVarint(tag_bytes, 0) + field_number, wire_type = wire_format.UnpackTag(tag) + if field_number == 0: + raise message_mod.DecodeError('Field number 0 is illegal.') + # TODO(jieluo): remove old_pos. + old_pos = new_pos + (data, new_pos) = decoder._DecodeUnknownField( + buffer, new_pos, wire_type) # pylint: disable=protected-access + if new_pos == -1: + return pos + # pylint: disable=protected-access + unknown_field_set._add(field_number, wire_type, data) + # TODO(jieluo): remove _unknown_fields. + new_pos = local_SkipField(buffer, old_pos, end, tag_bytes) + if new_pos == -1: + return pos + self._unknown_fields.append( + (tag_bytes, buffer[old_pos:new_pos].tobytes())) + pos = new_pos + else: + pos = field_decoder(buffer, new_pos, end, self, field_dict) + if field_desc: + self._UpdateOneofState(field_desc) + return pos + cls._InternalParse = InternalParse + + +def _AddIsInitializedMethod(message_descriptor, cls): + """Adds the IsInitialized and FindInitializationError methods to the + protocol message class.""" + + required_fields = [field for field in message_descriptor.fields + if field.label == _FieldDescriptor.LABEL_REQUIRED] + + def IsInitialized(self, errors=None): + """Checks if all required fields of a message are set. + + Args: + errors: A list which, if provided, will be populated with the field + paths of all missing required fields. + + Returns: + True iff the specified message has all required fields set. + """ + + # Performance is critical so we avoid HasField() and ListFields(). + + for field in required_fields: + if (field not in self._fields or + (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and + not self._fields[field]._is_present_in_parent)): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + for field, value in list(self._fields.items()): # dict can change size! + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.label == _FieldDescriptor.LABEL_REPEATED: + if (field.message_type.has_options and + field.message_type.GetOptions().map_entry): + continue + for element in value: + if not element.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + elif value._is_present_in_parent and not value.IsInitialized(): + if errors is not None: + errors.extend(self.FindInitializationErrors()) + return False + + return True + + cls.IsInitialized = IsInitialized + + def FindInitializationErrors(self): + """Finds required fields which are not initialized. + + Returns: + A list of strings. Each string is a path to an uninitialized field from + the top-level message, e.g. "foo.bar[5].baz". + """ + + errors = [] # simplify things + + for field in required_fields: + if not self.HasField(field.name): + errors.append(field.name) + + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if field.is_extension: + name = '(%s)' % field.full_name + else: + name = field.name + + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + element = value[key] + prefix = '%s[%s].' % (name, key) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + # ScalarMaps can't have any initialization errors. + pass + elif field.label == _FieldDescriptor.LABEL_REPEATED: + for i in range(len(value)): + element = value[i] + prefix = '%s[%d].' % (name, i) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + prefix = name + '.' + sub_errors = value.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + + return errors + + cls.FindInitializationErrors = FindInitializationErrors + + +def _AddMergeFromMethod(cls): + LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED + CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE + + def MergeFrom(self, msg): + if not isinstance(msg, cls): + raise TypeError( + 'Parameter to MergeFrom() must be instance of same class: ' + 'expected %s got %s.' % (cls.__name__, msg.__class__.__name__)) + + assert msg is not self + self._Modified() + + fields = self._fields + + for field, value in msg._fields.items(): + if field.label == LABEL_REPEATED: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + elif field.cpp_type == CPPTYPE_MESSAGE: + if value._is_present_in_parent: + field_value = fields.get(field) + if field_value is None: + # Construct a new object to represent this field. + field_value = field._default_constructor(self) + fields[field] = field_value + field_value.MergeFrom(value) + else: + self._fields[field] = value + if field.containing_oneof: + self._UpdateOneofState(field) + + if msg._unknown_fields: + if not self._unknown_fields: + self._unknown_fields = [] + self._unknown_fields.extend(msg._unknown_fields) + # pylint: disable=protected-access + if self._unknown_field_set is None: + self._unknown_field_set = containers.UnknownFieldSet() + self._unknown_field_set._extend(msg._unknown_field_set) + + cls.MergeFrom = MergeFrom + + +def _AddWhichOneofMethod(message_descriptor, cls): + def WhichOneof(self, oneof_name): + """Returns the name of the currently set field inside a oneof, or None.""" + try: + field = message_descriptor.oneofs_by_name[oneof_name] + except KeyError: + raise ValueError( + 'Protocol message has no oneof "%s" field.' % oneof_name) + + nested_field = self._oneofs.get(field, None) + if nested_field is not None and self.HasField(nested_field.name): + return nested_field.name + else: + return None + + cls.WhichOneof = WhichOneof + + +def _Clear(self): + # Clear fields. + self._fields = {} + self._unknown_fields = () + # pylint: disable=protected-access + if self._unknown_field_set is not None: + self._unknown_field_set._clear() + self._unknown_field_set = None + + self._oneofs = {} + self._Modified() + + +def _UnknownFields(self): + if self._unknown_field_set is None: # pylint: disable=protected-access + # pylint: disable=protected-access + self._unknown_field_set = containers.UnknownFieldSet() + return self._unknown_field_set # pylint: disable=protected-access + + +def _DiscardUnknownFields(self): + self._unknown_fields = [] + self._unknown_field_set = None # pylint: disable=protected-access + for field, value in self.ListFields(): + if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + value[key].DiscardUnknownFields() + elif field.label == _FieldDescriptor.LABEL_REPEATED: + for sub_message in value: + sub_message.DiscardUnknownFields() + else: + value.DiscardUnknownFields() + + +def _SetListener(self, listener): + if listener is None: + self._listener = message_listener_mod.NullMessageListener() + else: + self._listener = listener + + +def _AddMessageMethods(message_descriptor, cls): + """Adds implementations of all Message methods to cls.""" + _AddListFieldsMethod(message_descriptor, cls) + _AddHasFieldMethod(message_descriptor, cls) + _AddClearFieldMethod(message_descriptor, cls) + if message_descriptor.is_extendable: + _AddClearExtensionMethod(cls) + _AddHasExtensionMethod(cls) + _AddEqualsMethod(message_descriptor, cls) + _AddStrMethod(message_descriptor, cls) + _AddReprMethod(message_descriptor, cls) + _AddUnicodeMethod(message_descriptor, cls) + _AddByteSizeMethod(message_descriptor, cls) + _AddSerializeToStringMethod(message_descriptor, cls) + _AddSerializePartialToStringMethod(message_descriptor, cls) + _AddMergeFromStringMethod(message_descriptor, cls) + _AddIsInitializedMethod(message_descriptor, cls) + _AddMergeFromMethod(cls) + _AddWhichOneofMethod(message_descriptor, cls) + # Adds methods which do not depend on cls. + cls.Clear = _Clear + cls.UnknownFields = _UnknownFields + cls.DiscardUnknownFields = _DiscardUnknownFields + cls._SetListener = _SetListener + + +def _AddPrivateHelperMethods(message_descriptor, cls): + """Adds implementation of private helper methods to cls.""" + + def Modified(self): + """Sets the _cached_byte_size_dirty bit to true, + and propagates this to our listener iff this was a state change. + """ + + # Note: Some callers check _cached_byte_size_dirty before calling + # _Modified() as an extra optimization. So, if this method is ever + # changed such that it does stuff even when _cached_byte_size_dirty is + # already true, the callers need to be updated. + if not self._cached_byte_size_dirty: + self._cached_byte_size_dirty = True + self._listener_for_children.dirty = True + self._is_present_in_parent = True + self._listener.Modified() + + def _UpdateOneofState(self, field): + """Sets field as the active field in its containing oneof. + + Will also delete currently active field in the oneof, if it is different + from the argument. Does not mark the message as modified. + """ + other_field = self._oneofs.setdefault(field.containing_oneof, field) + if other_field is not field: + del self._fields[other_field] + self._oneofs[field.containing_oneof] = field + + cls._Modified = Modified + cls.SetInParent = Modified + cls._UpdateOneofState = _UpdateOneofState + + +class _Listener(object): + + """MessageListener implementation that a parent message registers with its + child message. + + In order to support semantics like: + + foo.bar.baz.qux = 23 + assert foo.HasField('bar') + + ...child objects must have back references to their parents. + This helper class is at the heart of this support. + """ + + def __init__(self, parent_message): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + """ + # This listener establishes a back reference from a child (contained) object + # to its parent (containing) object. We make this a weak reference to avoid + # creating cyclic garbage when the client finishes with the 'parent' object + # in the tree. + if isinstance(parent_message, weakref.ProxyType): + self._parent_message_weakref = parent_message + else: + self._parent_message_weakref = weakref.proxy(parent_message) + + # As an optimization, we also indicate directly on the listener whether + # or not the parent message is dirty. This way we can avoid traversing + # up the tree in the common case. + self.dirty = False + + def Modified(self): + if self.dirty: + return + try: + # Propagate the signal to our parents iff this is the first field set. + self._parent_message_weakref._Modified() + except ReferenceError: + # We can get here if a client has kept a reference to a child object, + # and is now setting a field on it, but the child's parent has been + # garbage-collected. This is not an error. + pass + + +class _OneofListener(_Listener): + """Special listener implementation for setting composite oneof fields.""" + + def __init__(self, parent_message, field): + """Args: + parent_message: The message whose _Modified() method we should call when + we receive Modified() messages. + field: The descriptor of the field being set in the parent message. + """ + super(_OneofListener, self).__init__(parent_message) + self._field = field + + def Modified(self): + """Also updates the state of the containing oneof in the parent message.""" + try: + self._parent_message_weakref._UpdateOneofState(self._field) + super(_OneofListener, self).Modified() + except ReferenceError: + pass diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/type_checkers.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/type_checkers.py new file mode 100644 index 00000000..eb66f9f6 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/type_checkers.py @@ -0,0 +1,426 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides type checking routines. + +This module defines type checking utilities in the forms of dictionaries: + +VALUE_CHECKERS: A dictionary of field types and a value validation object. +TYPE_TO_BYTE_SIZE_FN: A dictionary with field types and a size computing + function. +TYPE_TO_SERIALIZE_METHOD: A dictionary with field types and serialization + function. +FIELD_TYPE_TO_WIRE_TYPE: A dictionary with field typed and their + corresponding wire types. +TYPE_TO_DESERIALIZE_METHOD: A dictionary with field types and deserialization + function. +""" + +__author__ = 'robinson@google.com (Will Robinson)' + +try: + import ctypes +except Exception: # pylint: disable=broad-except + ctypes = None + import struct +import numbers +import six + +if six.PY3: + long = int + +from google.protobuf.internal import api_implementation +from google.protobuf.internal import decoder +from google.protobuf.internal import encoder +from google.protobuf.internal import wire_format +from google.protobuf import descriptor + +_FieldDescriptor = descriptor.FieldDescriptor + + +def TruncateToFourByteFloat(original): + if ctypes: + return ctypes.c_float(original).value + else: + return struct.unpack(' _FLOAT_MAX: + return _INF + if converted_value < _FLOAT_MIN: + return _NEG_INF + + return TruncateToFourByteFloat(converted_value) + + def DefaultValue(self): + return 0.0 + + +# Type-checkers for all scalar CPPTYPEs. +_VALUE_CHECKERS = { + _FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), + _FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), + _FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), + _FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( + 0.0, float, numbers.Real), + _FieldDescriptor.CPPTYPE_FLOAT: FloatValueChecker(), + _FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( + False, bool, numbers.Integral), + _FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), + } + + +# Map from field type to a function F, such that F(field_num, value) +# gives the total byte size for a value of the given type. This +# byte size includes tag information and any other additional space +# associated with serializing "value". +TYPE_TO_BYTE_SIZE_FN = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.DoubleByteSize, + _FieldDescriptor.TYPE_FLOAT: wire_format.FloatByteSize, + _FieldDescriptor.TYPE_INT64: wire_format.Int64ByteSize, + _FieldDescriptor.TYPE_UINT64: wire_format.UInt64ByteSize, + _FieldDescriptor.TYPE_INT32: wire_format.Int32ByteSize, + _FieldDescriptor.TYPE_FIXED64: wire_format.Fixed64ByteSize, + _FieldDescriptor.TYPE_FIXED32: wire_format.Fixed32ByteSize, + _FieldDescriptor.TYPE_BOOL: wire_format.BoolByteSize, + _FieldDescriptor.TYPE_STRING: wire_format.StringByteSize, + _FieldDescriptor.TYPE_GROUP: wire_format.GroupByteSize, + _FieldDescriptor.TYPE_MESSAGE: wire_format.MessageByteSize, + _FieldDescriptor.TYPE_BYTES: wire_format.BytesByteSize, + _FieldDescriptor.TYPE_UINT32: wire_format.UInt32ByteSize, + _FieldDescriptor.TYPE_ENUM: wire_format.EnumByteSize, + _FieldDescriptor.TYPE_SFIXED32: wire_format.SFixed32ByteSize, + _FieldDescriptor.TYPE_SFIXED64: wire_format.SFixed64ByteSize, + _FieldDescriptor.TYPE_SINT32: wire_format.SInt32ByteSize, + _FieldDescriptor.TYPE_SINT64: wire_format.SInt64ByteSize + } + + +# Maps from field types to encoder constructors. +TYPE_TO_ENCODER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleEncoder, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatEncoder, + _FieldDescriptor.TYPE_INT64: encoder.Int64Encoder, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Encoder, + _FieldDescriptor.TYPE_INT32: encoder.Int32Encoder, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Encoder, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Encoder, + _FieldDescriptor.TYPE_BOOL: encoder.BoolEncoder, + _FieldDescriptor.TYPE_STRING: encoder.StringEncoder, + _FieldDescriptor.TYPE_GROUP: encoder.GroupEncoder, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageEncoder, + _FieldDescriptor.TYPE_BYTES: encoder.BytesEncoder, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Encoder, + _FieldDescriptor.TYPE_ENUM: encoder.EnumEncoder, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Encoder, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Encoder, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Encoder, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Encoder, + } + + +# Maps from field types to sizer constructors. +TYPE_TO_SIZER = { + _FieldDescriptor.TYPE_DOUBLE: encoder.DoubleSizer, + _FieldDescriptor.TYPE_FLOAT: encoder.FloatSizer, + _FieldDescriptor.TYPE_INT64: encoder.Int64Sizer, + _FieldDescriptor.TYPE_UINT64: encoder.UInt64Sizer, + _FieldDescriptor.TYPE_INT32: encoder.Int32Sizer, + _FieldDescriptor.TYPE_FIXED64: encoder.Fixed64Sizer, + _FieldDescriptor.TYPE_FIXED32: encoder.Fixed32Sizer, + _FieldDescriptor.TYPE_BOOL: encoder.BoolSizer, + _FieldDescriptor.TYPE_STRING: encoder.StringSizer, + _FieldDescriptor.TYPE_GROUP: encoder.GroupSizer, + _FieldDescriptor.TYPE_MESSAGE: encoder.MessageSizer, + _FieldDescriptor.TYPE_BYTES: encoder.BytesSizer, + _FieldDescriptor.TYPE_UINT32: encoder.UInt32Sizer, + _FieldDescriptor.TYPE_ENUM: encoder.EnumSizer, + _FieldDescriptor.TYPE_SFIXED32: encoder.SFixed32Sizer, + _FieldDescriptor.TYPE_SFIXED64: encoder.SFixed64Sizer, + _FieldDescriptor.TYPE_SINT32: encoder.SInt32Sizer, + _FieldDescriptor.TYPE_SINT64: encoder.SInt64Sizer, + } + + +# Maps from field type to a decoder constructor. +TYPE_TO_DECODER = { + _FieldDescriptor.TYPE_DOUBLE: decoder.DoubleDecoder, + _FieldDescriptor.TYPE_FLOAT: decoder.FloatDecoder, + _FieldDescriptor.TYPE_INT64: decoder.Int64Decoder, + _FieldDescriptor.TYPE_UINT64: decoder.UInt64Decoder, + _FieldDescriptor.TYPE_INT32: decoder.Int32Decoder, + _FieldDescriptor.TYPE_FIXED64: decoder.Fixed64Decoder, + _FieldDescriptor.TYPE_FIXED32: decoder.Fixed32Decoder, + _FieldDescriptor.TYPE_BOOL: decoder.BoolDecoder, + _FieldDescriptor.TYPE_STRING: decoder.StringDecoder, + _FieldDescriptor.TYPE_GROUP: decoder.GroupDecoder, + _FieldDescriptor.TYPE_MESSAGE: decoder.MessageDecoder, + _FieldDescriptor.TYPE_BYTES: decoder.BytesDecoder, + _FieldDescriptor.TYPE_UINT32: decoder.UInt32Decoder, + _FieldDescriptor.TYPE_ENUM: decoder.EnumDecoder, + _FieldDescriptor.TYPE_SFIXED32: decoder.SFixed32Decoder, + _FieldDescriptor.TYPE_SFIXED64: decoder.SFixed64Decoder, + _FieldDescriptor.TYPE_SINT32: decoder.SInt32Decoder, + _FieldDescriptor.TYPE_SINT64: decoder.SInt64Decoder, + } + +# Maps from field type to expected wiretype. +FIELD_TYPE_TO_WIRE_TYPE = { + _FieldDescriptor.TYPE_DOUBLE: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FLOAT: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_INT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_UINT64: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_INT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_FIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_FIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_BOOL: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_STRING: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_GROUP: wire_format.WIRETYPE_START_GROUP, + _FieldDescriptor.TYPE_MESSAGE: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_BYTES: + wire_format.WIRETYPE_LENGTH_DELIMITED, + _FieldDescriptor.TYPE_UINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_ENUM: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SFIXED32: wire_format.WIRETYPE_FIXED32, + _FieldDescriptor.TYPE_SFIXED64: wire_format.WIRETYPE_FIXED64, + _FieldDescriptor.TYPE_SINT32: wire_format.WIRETYPE_VARINT, + _FieldDescriptor.TYPE_SINT64: wire_format.WIRETYPE_VARINT, + } diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/well_known_types.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/well_known_types.py new file mode 100644 index 00000000..6f55d6b1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/well_known_types.py @@ -0,0 +1,863 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Contains well known classes. + +This files defines well known classes which need extra maintenance including: + - Any + - Duration + - FieldMask + - Struct + - Timestamp +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +import calendar +from datetime import datetime +from datetime import timedelta +import six + +try: + # Since python 3 + import collections.abc as collections_abc +except ImportError: + # Won't work after python 3.8 + import collections as collections_abc + +from google.protobuf.descriptor import FieldDescriptor + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_NANOS_PER_SECOND = 1000000000 +_NANOS_PER_MILLISECOND = 1000000 +_NANOS_PER_MICROSECOND = 1000 +_MILLIS_PER_SECOND = 1000 +_MICROS_PER_SECOND = 1000000 +_SECONDS_PER_DAY = 24 * 3600 +_DURATION_SECONDS_MAX = 315576000000 + + +class Any(object): + """Class for Any Message type.""" + + __slots__ = () + + def Pack(self, msg, type_url_prefix='type.googleapis.com/', + deterministic=None): + """Packs the specified message into current Any message.""" + if len(type_url_prefix) < 1 or type_url_prefix[-1] != '/': + self.type_url = '%s/%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + else: + self.type_url = '%s%s' % (type_url_prefix, msg.DESCRIPTOR.full_name) + self.value = msg.SerializeToString(deterministic=deterministic) + + def Unpack(self, msg): + """Unpacks the current Any message into specified message.""" + descriptor = msg.DESCRIPTOR + if not self.Is(descriptor): + return False + msg.ParseFromString(self.value) + return True + + def TypeName(self): + """Returns the protobuf type name of the inner message.""" + # Only last part is to be used: b/25630112 + return self.type_url.split('/')[-1] + + def Is(self, descriptor): + """Checks if this Any represents the given protobuf type.""" + return '/' in self.type_url and self.TypeName() == descriptor.full_name + + +_EPOCH_DATETIME = datetime.utcfromtimestamp(0) + + +class Timestamp(object): + """Class for Timestamp message type.""" + + __slots__ = () + + def ToJsonString(self): + """Converts Timestamp to RFC 3339 date string format. + + Returns: + A string converted from timestamp. The string is always Z-normalized + and uses 3, 6 or 9 fractional digits as required to represent the + exact time. Example of the return format: '1972-01-01T10:00:20.021Z' + """ + nanos = self.nanos % _NANOS_PER_SECOND + total_sec = self.seconds + (self.nanos - nanos) // _NANOS_PER_SECOND + seconds = total_sec % _SECONDS_PER_DAY + days = (total_sec - seconds) // _SECONDS_PER_DAY + dt = datetime(1970, 1, 1) + timedelta(days, seconds) + + result = dt.isoformat() + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 'Z' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03dZ' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06dZ' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09dZ' % nanos + + def FromJsonString(self, value): + """Parse a RFC 3339 date string format to Timestamp. + + Args: + value: A date string. Any fractional digits (or none) and any offset are + accepted as long as they fit into nano-seconds precision. + Example of accepted format: '1972-01-01T10:00:20.021-05:00' + + Raises: + ValueError: On parsing problems. + """ + timezone_offset = value.find('Z') + if timezone_offset == -1: + timezone_offset = value.find('+') + if timezone_offset == -1: + timezone_offset = value.rfind('-') + if timezone_offset == -1: + raise ValueError( + 'Failed to parse timestamp: missing valid timezone offset.') + time_value = value[0:timezone_offset] + # Parse datetime and nanos. + point_position = time_value.find('.') + if point_position == -1: + second_value = time_value + nano_value = '' + else: + second_value = time_value[:point_position] + nano_value = time_value[point_position + 1:] + if 't' in second_value: + raise ValueError( + 'time data \'{0}\' does not match format \'%Y-%m-%dT%H:%M:%S\', ' + 'lowercase \'t\' is not accepted'.format(second_value)) + date_object = datetime.strptime(second_value, _TIMESTAMPFOMAT) + td = date_object - datetime(1970, 1, 1) + seconds = td.seconds + td.days * _SECONDS_PER_DAY + if len(nano_value) > 9: + raise ValueError( + 'Failed to parse Timestamp: nanos {0} more than ' + '9 fractional digits.'.format(nano_value)) + if nano_value: + nanos = round(float('0.' + nano_value) * 1e9) + else: + nanos = 0 + # Parse timezone offsets. + if value[timezone_offset] == 'Z': + if len(value) != timezone_offset + 1: + raise ValueError('Failed to parse timestamp: invalid trailing' + ' data {0}.'.format(value)) + else: + timezone = value[timezone_offset:] + pos = timezone.find(':') + if pos == -1: + raise ValueError( + 'Invalid timezone offset value: {0}.'.format(timezone)) + if timezone[0] == '+': + seconds -= (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + else: + seconds += (int(timezone[1:pos])*60+int(timezone[pos+1:]))*60 + # Set seconds and nanos + self.seconds = int(seconds) + self.nanos = int(nanos) + + def GetCurrentTime(self): + """Get the current UTC into Timestamp.""" + self.FromDatetime(datetime.utcnow()) + + def ToNanoseconds(self): + """Converts Timestamp to nanoseconds since epoch.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts Timestamp to microseconds since epoch.""" + return (self.seconds * _MICROS_PER_SECOND + + self.nanos // _NANOS_PER_MICROSECOND) + + def ToMilliseconds(self): + """Converts Timestamp to milliseconds since epoch.""" + return (self.seconds * _MILLIS_PER_SECOND + + self.nanos // _NANOS_PER_MILLISECOND) + + def ToSeconds(self): + """Converts Timestamp to seconds since epoch.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds since epoch to Timestamp.""" + self.seconds = nanos // _NANOS_PER_SECOND + self.nanos = nanos % _NANOS_PER_SECOND + + def FromMicroseconds(self, micros): + """Converts microseconds since epoch to Timestamp.""" + self.seconds = micros // _MICROS_PER_SECOND + self.nanos = (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND + + def FromMilliseconds(self, millis): + """Converts milliseconds since epoch to Timestamp.""" + self.seconds = millis // _MILLIS_PER_SECOND + self.nanos = (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND + + def FromSeconds(self, seconds): + """Converts seconds since epoch to Timestamp.""" + self.seconds = seconds + self.nanos = 0 + + def ToDatetime(self): + """Converts Timestamp to datetime.""" + return _EPOCH_DATETIME + timedelta( + seconds=self.seconds, microseconds=_RoundTowardZero( + self.nanos, _NANOS_PER_MICROSECOND)) + + def FromDatetime(self, dt): + """Converts datetime to Timestamp.""" + # Using this guide: http://wiki.python.org/moin/WorkingWithTime + # And this conversion guide: http://docs.python.org/library/time.html + + # Turn the date parameter into a tuple (struct_time) that can then be + # manipulated into a long value of seconds. During the conversion from + # struct_time to long, the source date in UTC, and so it follows that the + # correct transformation is calendar.timegm() + self.seconds = calendar.timegm(dt.utctimetuple()) + self.nanos = dt.microsecond * _NANOS_PER_MICROSECOND + + +class Duration(object): + """Class for Duration message type.""" + + __slots__ = () + + def ToJsonString(self): + """Converts Duration to string format. + + Returns: + A string converted from self. The string format will contains + 3, 6, or 9 fractional digits depending on the precision required to + represent the exact Duration value. For example: "1s", "1.010s", + "1.000000100s", "-3.100s" + """ + _CheckDurationValid(self.seconds, self.nanos) + if self.seconds < 0 or self.nanos < 0: + result = '-' + seconds = - self.seconds + int((0 - self.nanos) // 1e9) + nanos = (0 - self.nanos) % 1e9 + else: + result = '' + seconds = self.seconds + int(self.nanos // 1e9) + nanos = self.nanos % 1e9 + result += '%d' % seconds + if (nanos % 1e9) == 0: + # If there are 0 fractional digits, the fractional + # point '.' should be omitted when serializing. + return result + 's' + if (nanos % 1e6) == 0: + # Serialize 3 fractional digits. + return result + '.%03ds' % (nanos / 1e6) + if (nanos % 1e3) == 0: + # Serialize 6 fractional digits. + return result + '.%06ds' % (nanos / 1e3) + # Serialize 9 fractional digits. + return result + '.%09ds' % nanos + + def FromJsonString(self, value): + """Converts a string to Duration. + + Args: + value: A string to be converted. The string must end with 's'. Any + fractional digits (or none) are accepted as long as they fit into + precision. For example: "1s", "1.01s", "1.0000001s", "-3.100s + + Raises: + ValueError: On parsing problems. + """ + if len(value) < 1 or value[-1] != 's': + raise ValueError( + 'Duration must end with letter "s": {0}.'.format(value)) + try: + pos = value.find('.') + if pos == -1: + seconds = int(value[:-1]) + nanos = 0 + else: + seconds = int(value[:pos]) + if value[0] == '-': + nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9)) + else: + nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9)) + _CheckDurationValid(seconds, nanos) + self.seconds = seconds + self.nanos = nanos + except ValueError as e: + raise ValueError( + 'Couldn\'t parse duration: {0} : {1}.'.format(value, e)) + + def ToNanoseconds(self): + """Converts a Duration to nanoseconds.""" + return self.seconds * _NANOS_PER_SECOND + self.nanos + + def ToMicroseconds(self): + """Converts a Duration to microseconds.""" + micros = _RoundTowardZero(self.nanos, _NANOS_PER_MICROSECOND) + return self.seconds * _MICROS_PER_SECOND + micros + + def ToMilliseconds(self): + """Converts a Duration to milliseconds.""" + millis = _RoundTowardZero(self.nanos, _NANOS_PER_MILLISECOND) + return self.seconds * _MILLIS_PER_SECOND + millis + + def ToSeconds(self): + """Converts a Duration to seconds.""" + return self.seconds + + def FromNanoseconds(self, nanos): + """Converts nanoseconds to Duration.""" + self._NormalizeDuration(nanos // _NANOS_PER_SECOND, + nanos % _NANOS_PER_SECOND) + + def FromMicroseconds(self, micros): + """Converts microseconds to Duration.""" + self._NormalizeDuration( + micros // _MICROS_PER_SECOND, + (micros % _MICROS_PER_SECOND) * _NANOS_PER_MICROSECOND) + + def FromMilliseconds(self, millis): + """Converts milliseconds to Duration.""" + self._NormalizeDuration( + millis // _MILLIS_PER_SECOND, + (millis % _MILLIS_PER_SECOND) * _NANOS_PER_MILLISECOND) + + def FromSeconds(self, seconds): + """Converts seconds to Duration.""" + self.seconds = seconds + self.nanos = 0 + + def ToTimedelta(self): + """Converts Duration to timedelta.""" + return timedelta( + seconds=self.seconds, microseconds=_RoundTowardZero( + self.nanos, _NANOS_PER_MICROSECOND)) + + def FromTimedelta(self, td): + """Converts timedelta to Duration.""" + self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY, + td.microseconds * _NANOS_PER_MICROSECOND) + + def _NormalizeDuration(self, seconds, nanos): + """Set Duration by seconds and nanos.""" + # Force nanos to be negative if the duration is negative. + if seconds < 0 and nanos > 0: + seconds += 1 + nanos -= _NANOS_PER_SECOND + self.seconds = seconds + self.nanos = nanos + + +def _CheckDurationValid(seconds, nanos): + if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: + raise ValueError( + 'Duration is not valid: Seconds {0} must be in range ' + '[-315576000000, 315576000000].'.format(seconds)) + if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND: + raise ValueError( + 'Duration is not valid: Nanos {0} must be in range ' + '[-999999999, 999999999].'.format(nanos)) + if (nanos < 0 and seconds > 0) or (nanos > 0 and seconds < 0): + raise ValueError( + 'Duration is not valid: Sign mismatch.') + + +def _RoundTowardZero(value, divider): + """Truncates the remainder part after division.""" + # For some languages, the sign of the remainder is implementation + # dependent if any of the operands is negative. Here we enforce + # "rounded toward zero" semantics. For example, for (-5) / 2 an + # implementation may give -3 as the result with the remainder being + # 1. This function ensures we always return -2 (closer to zero). + result = value // divider + remainder = value % divider + if result < 0 and remainder > 0: + return result + 1 + else: + return result + + +class FieldMask(object): + """Class for FieldMask message type.""" + + __slots__ = () + + def ToJsonString(self): + """Converts FieldMask to string according to proto3 JSON spec.""" + camelcase_paths = [] + for path in self.paths: + camelcase_paths.append(_SnakeCaseToCamelCase(path)) + return ','.join(camelcase_paths) + + def FromJsonString(self, value): + """Converts string to FieldMask according to proto3 JSON spec.""" + self.Clear() + if value: + for path in value.split(','): + self.paths.append(_CamelCaseToSnakeCase(path)) + + def IsValidForDescriptor(self, message_descriptor): + """Checks whether the FieldMask is valid for Message Descriptor.""" + for path in self.paths: + if not _IsValidPath(message_descriptor, path): + return False + return True + + def AllFieldsFromDescriptor(self, message_descriptor): + """Gets all direct fields of Message Descriptor to FieldMask.""" + self.Clear() + for field in message_descriptor.fields: + self.paths.append(field.name) + + def CanonicalFormFromMask(self, mask): + """Converts a FieldMask to the canonical form. + + Removes paths that are covered by another path. For example, + "foo.bar" is covered by "foo" and will be removed if "foo" + is also in the FieldMask. Then sorts all paths in alphabetical order. + + Args: + mask: The original FieldMask to be converted. + """ + tree = _FieldMaskTree(mask) + tree.ToFieldMask(self) + + def Union(self, mask1, mask2): + """Merges mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + tree.MergeFromFieldMask(mask2) + tree.ToFieldMask(self) + + def Intersect(self, mask1, mask2): + """Intersects mask1 and mask2 into this FieldMask.""" + _CheckFieldMaskMessage(mask1) + _CheckFieldMaskMessage(mask2) + tree = _FieldMaskTree(mask1) + intersection = _FieldMaskTree() + for path in mask2.paths: + tree.IntersectPath(path, intersection) + intersection.ToFieldMask(self) + + def MergeMessage( + self, source, destination, + replace_message_field=False, replace_repeated_field=False): + """Merges fields specified in FieldMask from source to destination. + + Args: + source: Source message. + destination: The destination message to be merged into. + replace_message_field: Replace message field if True. Merge message + field if False. + replace_repeated_field: Replace repeated field if True. Append + elements of repeated field if False. + """ + tree = _FieldMaskTree(self) + tree.MergeMessage( + source, destination, replace_message_field, replace_repeated_field) + + +def _IsValidPath(message_descriptor, path): + """Checks whether the path is valid for Message Descriptor.""" + parts = path.split('.') + last = parts.pop() + for name in parts: + field = message_descriptor.fields_by_name.get(name) + if (field is None or + field.label == FieldDescriptor.LABEL_REPEATED or + field.type != FieldDescriptor.TYPE_MESSAGE): + return False + message_descriptor = field.message_type + return last in message_descriptor.fields_by_name + + +def _CheckFieldMaskMessage(message): + """Raises ValueError if message is not a FieldMask.""" + message_descriptor = message.DESCRIPTOR + if (message_descriptor.name != 'FieldMask' or + message_descriptor.file.name != 'google/protobuf/field_mask.proto'): + raise ValueError('Message {0} is not a FieldMask.'.format( + message_descriptor.full_name)) + + +def _SnakeCaseToCamelCase(path_name): + """Converts a path name from snake_case to camelCase.""" + result = [] + after_underscore = False + for c in path_name: + if c.isupper(): + raise ValueError( + 'Fail to print FieldMask to Json string: Path name ' + '{0} must not contain uppercase letters.'.format(path_name)) + if after_underscore: + if c.islower(): + result.append(c.upper()) + after_underscore = False + else: + raise ValueError( + 'Fail to print FieldMask to Json string: The ' + 'character after a "_" must be a lowercase letter ' + 'in path name {0}.'.format(path_name)) + elif c == '_': + after_underscore = True + else: + result += c + + if after_underscore: + raise ValueError('Fail to print FieldMask to Json string: Trailing "_" ' + 'in path name {0}.'.format(path_name)) + return ''.join(result) + + +def _CamelCaseToSnakeCase(path_name): + """Converts a field name from camelCase to snake_case.""" + result = [] + for c in path_name: + if c == '_': + raise ValueError('Fail to parse FieldMask: Path name ' + '{0} must not contain "_"s.'.format(path_name)) + if c.isupper(): + result += '_' + result += c.lower() + else: + result += c + return ''.join(result) + + +class _FieldMaskTree(object): + """Represents a FieldMask in a tree structure. + + For example, given a FieldMask "foo.bar,foo.baz,bar.baz", + the FieldMaskTree will be: + [_root] -+- foo -+- bar + | | + | +- baz + | + +- bar --- baz + In the tree, each leaf node represents a field path. + """ + + __slots__ = ('_root',) + + def __init__(self, field_mask=None): + """Initializes the tree by FieldMask.""" + self._root = {} + if field_mask: + self.MergeFromFieldMask(field_mask) + + def MergeFromFieldMask(self, field_mask): + """Merges a FieldMask to the tree.""" + for path in field_mask.paths: + self.AddPath(path) + + def AddPath(self, path): + """Adds a field path into the tree. + + If the field path to add is a sub-path of an existing field path + in the tree (i.e., a leaf node), it means the tree already matches + the given path so nothing will be added to the tree. If the path + matches an existing non-leaf node in the tree, that non-leaf node + will be turned into a leaf node with all its children removed because + the path matches all the node's children. Otherwise, a new path will + be added. + + Args: + path: The field path to add. + """ + node = self._root + for name in path.split('.'): + if name not in node: + node[name] = {} + elif not node[name]: + # Pre-existing empty node implies we already have this entire tree. + return + node = node[name] + # Remove any sub-trees we might have had. + node.clear() + + def ToFieldMask(self, field_mask): + """Converts the tree to a FieldMask.""" + field_mask.Clear() + _AddFieldPaths(self._root, '', field_mask) + + def IntersectPath(self, path, intersection): + """Calculates the intersection part of a field path with this tree. + + Args: + path: The field path to calculates. + intersection: The out tree to record the intersection part. + """ + node = self._root + for name in path.split('.'): + if name not in node: + return + elif not node[name]: + intersection.AddPath(path) + return + node = node[name] + intersection.AddLeafNodes(path, node) + + def AddLeafNodes(self, prefix, node): + """Adds leaf nodes begin with prefix to this tree.""" + if not node: + self.AddPath(prefix) + for name in node: + child_path = prefix + '.' + name + self.AddLeafNodes(child_path, node[name]) + + def MergeMessage( + self, source, destination, + replace_message, replace_repeated): + """Merge all fields specified by this tree from source to destination.""" + _MergeMessage( + self._root, source, destination, replace_message, replace_repeated) + + +def _StrConvert(value): + """Converts value to str if it is not.""" + # This file is imported by c extension and some methods like ClearField + # requires string for the field name. py2/py3 has different text + # type and may use unicode. + if not isinstance(value, str): + return value.encode('utf-8') + return value + + +def _MergeMessage( + node, source, destination, replace_message, replace_repeated): + """Merge all fields specified by a sub-tree from source to destination.""" + source_descriptor = source.DESCRIPTOR + for name in node: + child = node[name] + field = source_descriptor.fields_by_name[name] + if field is None: + raise ValueError('Error: Can\'t find field {0} in message {1}.'.format( + name, source_descriptor.full_name)) + if child: + # Sub-paths are only allowed for singular message fields. + if (field.label == FieldDescriptor.LABEL_REPEATED or + field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE): + raise ValueError('Error: Field {0} in message {1} is not a singular ' + 'message field and cannot have sub-fields.'.format( + name, source_descriptor.full_name)) + if source.HasField(name): + _MergeMessage( + child, getattr(source, name), getattr(destination, name), + replace_message, replace_repeated) + continue + if field.label == FieldDescriptor.LABEL_REPEATED: + if replace_repeated: + destination.ClearField(_StrConvert(name)) + repeated_source = getattr(source, name) + repeated_destination = getattr(destination, name) + repeated_destination.MergeFrom(repeated_source) + else: + if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE: + if replace_message: + destination.ClearField(_StrConvert(name)) + if source.HasField(name): + getattr(destination, name).MergeFrom(getattr(source, name)) + else: + setattr(destination, name, getattr(source, name)) + + +def _AddFieldPaths(node, prefix, field_mask): + """Adds the field paths descended from node to field_mask.""" + if not node and prefix: + field_mask.paths.append(prefix) + return + for name in sorted(node): + if prefix: + child_path = prefix + '.' + name + else: + child_path = name + _AddFieldPaths(node[name], child_path, field_mask) + + +_INT_OR_FLOAT = six.integer_types + (float,) + + +def _SetStructValue(struct_value, value): + if value is None: + struct_value.null_value = 0 + elif isinstance(value, bool): + # Note: this check must come before the number check because in Python + # True and False are also considered numbers. + struct_value.bool_value = value + elif isinstance(value, six.string_types): + struct_value.string_value = value + elif isinstance(value, _INT_OR_FLOAT): + struct_value.number_value = value + elif isinstance(value, (dict, Struct)): + struct_value.struct_value.Clear() + struct_value.struct_value.update(value) + elif isinstance(value, (list, ListValue)): + struct_value.list_value.Clear() + struct_value.list_value.extend(value) + else: + raise ValueError('Unexpected type') + + +def _GetStructValue(struct_value): + which = struct_value.WhichOneof('kind') + if which == 'struct_value': + return struct_value.struct_value + elif which == 'null_value': + return None + elif which == 'number_value': + return struct_value.number_value + elif which == 'string_value': + return struct_value.string_value + elif which == 'bool_value': + return struct_value.bool_value + elif which == 'list_value': + return struct_value.list_value + elif which is None: + raise ValueError('Value not set') + + +class Struct(object): + """Class for Struct message type.""" + + __slots__ = () + + def __getitem__(self, key): + return _GetStructValue(self.fields[key]) + + def __contains__(self, item): + return item in self.fields + + def __setitem__(self, key, value): + _SetStructValue(self.fields[key], value) + + def __delitem__(self, key): + del self.fields[key] + + def __len__(self): + return len(self.fields) + + def __iter__(self): + return iter(self.fields) + + def keys(self): # pylint: disable=invalid-name + return self.fields.keys() + + def values(self): # pylint: disable=invalid-name + return [self[key] for key in self] + + def items(self): # pylint: disable=invalid-name + return [(key, self[key]) for key in self] + + def get_or_create_list(self, key): + """Returns a list for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('list_value'): + # Clear will mark list_value modified which will indeed create a list. + self.fields[key].list_value.Clear() + return self.fields[key].list_value + + def get_or_create_struct(self, key): + """Returns a struct for this key, creating if it didn't exist already.""" + if not self.fields[key].HasField('struct_value'): + # Clear will mark struct_value modified which will indeed create a struct. + self.fields[key].struct_value.Clear() + return self.fields[key].struct_value + + def update(self, dictionary): # pylint: disable=invalid-name + for key, value in dictionary.items(): + _SetStructValue(self.fields[key], value) + +collections_abc.MutableMapping.register(Struct) + + +class ListValue(object): + """Class for ListValue message type.""" + + __slots__ = () + + def __len__(self): + return len(self.values) + + def append(self, value): + _SetStructValue(self.values.add(), value) + + def extend(self, elem_seq): + for value in elem_seq: + self.append(value) + + def __getitem__(self, index): + """Retrieves item by the specified index.""" + return _GetStructValue(self.values.__getitem__(index)) + + def __setitem__(self, index, value): + _SetStructValue(self.values.__getitem__(index), value) + + def __delitem__(self, key): + del self.values[key] + + def items(self): + for i in range(len(self)): + yield self[i] + + def add_struct(self): + """Appends and returns a struct value as the next value in the list.""" + struct_value = self.values.add().struct_value + # Clear will mark struct_value modified which will indeed create a struct. + struct_value.Clear() + return struct_value + + def add_list(self): + """Appends and returns a list value as the next value in the list.""" + list_value = self.values.add().list_value + # Clear will mark list_value modified which will indeed create a list. + list_value.Clear() + return list_value + +collections_abc.MutableSequence.register(ListValue) + + +WKTBASES = { + 'google.protobuf.Any': Any, + 'google.protobuf.Duration': Duration, + 'google.protobuf.FieldMask': FieldMask, + 'google.protobuf.ListValue': ListValue, + 'google.protobuf.Struct': Struct, + 'google.protobuf.Timestamp': Timestamp, +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/wire_format.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/wire_format.py new file mode 100644 index 00000000..883f5255 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/internal/wire_format.py @@ -0,0 +1,268 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Constants and static functions to support protocol buffer wire format.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +import struct +from google.protobuf import descriptor +from google.protobuf import message + + +TAG_TYPE_BITS = 3 # Number of bits used to hold type info in a proto tag. +TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1 # 0x7 + +# These numbers identify the wire type of a protocol buffer value. +# We use the least-significant TAG_TYPE_BITS bits of the varint-encoded +# tag-and-type to store one of these WIRETYPE_* constants. +# These values must match WireType enum in google/protobuf/wire_format.h. +WIRETYPE_VARINT = 0 +WIRETYPE_FIXED64 = 1 +WIRETYPE_LENGTH_DELIMITED = 2 +WIRETYPE_START_GROUP = 3 +WIRETYPE_END_GROUP = 4 +WIRETYPE_FIXED32 = 5 +_WIRETYPE_MAX = 5 + + +# Bounds for various integer types. +INT32_MAX = int((1 << 31) - 1) +INT32_MIN = int(-(1 << 31)) +UINT32_MAX = (1 << 32) - 1 + +INT64_MAX = (1 << 63) - 1 +INT64_MIN = -(1 << 63) +UINT64_MAX = (1 << 64) - 1 + +# "struct" format strings that will encode/decode the specified formats. +FORMAT_UINT32_LITTLE_ENDIAN = '> TAG_TYPE_BITS), (tag & TAG_TYPE_MASK) + + +def ZigZagEncode(value): + """ZigZag Transform: Encodes signed integers so that they can be + effectively used with varint encoding. See wire_format.h for + more details. + """ + if value >= 0: + return value << 1 + return (value << 1) ^ (~0) + + +def ZigZagDecode(value): + """Inverse of ZigZagEncode().""" + if not value & 0x1: + return value >> 1 + return (value >> 1) ^ (~0) + + + +# The *ByteSize() functions below return the number of bytes required to +# serialize "field number + type" information and then serialize the value. + + +def Int32ByteSize(field_number, int32): + return Int64ByteSize(field_number, int32) + + +def Int32ByteSizeNoTag(int32): + return _VarUInt64ByteSizeNoTag(0xffffffffffffffff & int32) + + +def Int64ByteSize(field_number, int64): + # Have to convert to uint before calling UInt64ByteSize(). + return UInt64ByteSize(field_number, 0xffffffffffffffff & int64) + + +def UInt32ByteSize(field_number, uint32): + return UInt64ByteSize(field_number, uint32) + + +def UInt64ByteSize(field_number, uint64): + return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64) + + +def SInt32ByteSize(field_number, int32): + return UInt32ByteSize(field_number, ZigZagEncode(int32)) + + +def SInt64ByteSize(field_number, int64): + return UInt64ByteSize(field_number, ZigZagEncode(int64)) + + +def Fixed32ByteSize(field_number, fixed32): + return TagByteSize(field_number) + 4 + + +def Fixed64ByteSize(field_number, fixed64): + return TagByteSize(field_number) + 8 + + +def SFixed32ByteSize(field_number, sfixed32): + return TagByteSize(field_number) + 4 + + +def SFixed64ByteSize(field_number, sfixed64): + return TagByteSize(field_number) + 8 + + +def FloatByteSize(field_number, flt): + return TagByteSize(field_number) + 4 + + +def DoubleByteSize(field_number, double): + return TagByteSize(field_number) + 8 + + +def BoolByteSize(field_number, b): + return TagByteSize(field_number) + 1 + + +def EnumByteSize(field_number, enum): + return UInt32ByteSize(field_number, enum) + + +def StringByteSize(field_number, string): + return BytesByteSize(field_number, string.encode('utf-8')) + + +def BytesByteSize(field_number, b): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(len(b)) + + len(b)) + + +def GroupByteSize(field_number, message): + return (2 * TagByteSize(field_number) # START and END group. + + message.ByteSize()) + + +def MessageByteSize(field_number, message): + return (TagByteSize(field_number) + + _VarUInt64ByteSizeNoTag(message.ByteSize()) + + message.ByteSize()) + + +def MessageSetItemByteSize(field_number, msg): + # First compute the sizes of the tags. + # There are 2 tags for the beginning and ending of the repeated group, that + # is field number 1, one with field number 2 (type_id) and one with field + # number 3 (message). + total_size = (2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3)) + + # Add the number of bytes for type_id. + total_size += _VarUInt64ByteSizeNoTag(field_number) + + message_size = msg.ByteSize() + + # The number of bytes for encoding the length of the message. + total_size += _VarUInt64ByteSizeNoTag(message_size) + + # The size of the message. + total_size += message_size + return total_size + + +def TagByteSize(field_number): + """Returns the bytes required to serialize a tag with this field number.""" + # Just pass in type 0, since the type won't affect the tag+type size. + return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0)) + + +# Private helper function for the *ByteSize() functions above. + +def _VarUInt64ByteSizeNoTag(uint64): + """Returns the number of bytes required to serialize a single varint + using boundary value comparisons. (unrolled loop optimization -WPierce) + uint64 must be unsigned. + """ + if uint64 <= 0x7f: return 1 + if uint64 <= 0x3fff: return 2 + if uint64 <= 0x1fffff: return 3 + if uint64 <= 0xfffffff: return 4 + if uint64 <= 0x7ffffffff: return 5 + if uint64 <= 0x3ffffffffff: return 6 + if uint64 <= 0x1ffffffffffff: return 7 + if uint64 <= 0xffffffffffffff: return 8 + if uint64 <= 0x7fffffffffffffff: return 9 + if uint64 > UINT64_MAX: + raise message.EncodeError('Value out of range: %d' % uint64) + return 10 + + +NON_PACKABLE_TYPES = ( + descriptor.FieldDescriptor.TYPE_STRING, + descriptor.FieldDescriptor.TYPE_GROUP, + descriptor.FieldDescriptor.TYPE_MESSAGE, + descriptor.FieldDescriptor.TYPE_BYTES +) + + +def IsTypePackable(field_type): + """Return true iff packable = true is valid for fields of this type. + + Args: + field_type: a FieldDescriptor::Type value. + + Returns: + True iff fields of this type are packable. + """ + return field_type not in NON_PACKABLE_TYPES diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/json_format.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/json_format.py new file mode 100644 index 00000000..c8f5602f --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/json_format.py @@ -0,0 +1,865 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Contains routines for printing protocol messages in JSON format. + +Simple usage example: + + # Create a proto object and serialize it to a json format string. + message = my_proto_pb2.MyMessage(foo='bar') + json_string = json_format.MessageToJson(message) + + # Parse a json format string to proto object. + message = json_format.Parse(json_string, my_proto_pb2.MyMessage()) +""" + +__author__ = 'jieluo@google.com (Jie Luo)' + +# pylint: disable=g-statement-before-imports,g-import-not-at-top +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict # PY26 +# pylint: enable=g-statement-before-imports,g-import-not-at-top + +import base64 +import json +import math + +from operator import methodcaller + +import re +import sys + +import six + +from google.protobuf.internal import type_checkers +from google.protobuf import descriptor +from google.protobuf import symbol_database + + +_TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S' +_INT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT32, + descriptor.FieldDescriptor.CPPTYPE_UINT32, + descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_INT64_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_INT64, + descriptor.FieldDescriptor.CPPTYPE_UINT64]) +_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, + descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) +_INFINITY = 'Infinity' +_NEG_INFINITY = '-Infinity' +_NAN = 'NaN' + +_UNPAIRED_SURROGATE_PATTERN = re.compile(six.u( + r'[\ud800-\udbff](?![\udc00-\udfff])|(? 0: + raise ParseError('Couldn\'t parse Infinity or value too large, ' + 'use quoted "Infinity" instead.') + else: + raise ParseError('Couldn\'t parse -Infinity or value too small, ' + 'use quoted "-Infinity" instead.') + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT: + # pylint: disable=protected-access + if value > type_checkers._FLOAT_MAX: + raise ParseError('Float value too large') + # pylint: disable=protected-access + if value < type_checkers._FLOAT_MIN: + raise ParseError('Float value too small') + if value == 'nan': + raise ParseError('Couldn\'t parse float "nan", use "NaN" instead.') + try: + # Assume Python compatible syntax. + return float(value) + except ValueError: + # Check alternative spellings. + if value == _NEG_INFINITY: + return float('-inf') + elif value == _INFINITY: + return float('inf') + elif value == _NAN: + return float('nan') + else: + raise ParseError('Couldn\'t parse float: {0}.'.format(value)) + + +def _ConvertBool(value, require_str): + """Convert a boolean value. + + Args: + value: A scalar value to convert. + require_str: If True, value must be a str. + + Returns: + The bool parsed. + + Raises: + ParseError: If a boolean value couldn't be consumed. + """ + if require_str: + if value == 'true': + return True + elif value == 'false': + return False + else: + raise ParseError('Expected "true" or "false", not {0}.'.format(value)) + + if not isinstance(value, bool): + raise ParseError('Expected true or false without quotes.') + return value + +_WKTJSONMETHODS = { + 'google.protobuf.Any': ['_AnyMessageToJsonObject', + '_ConvertAnyMessage'], + 'google.protobuf.Duration': ['_GenericMessageToJsonObject', + '_ConvertGenericMessage'], + 'google.protobuf.FieldMask': ['_GenericMessageToJsonObject', + '_ConvertGenericMessage'], + 'google.protobuf.ListValue': ['_ListValueMessageToJsonObject', + '_ConvertListValueMessage'], + 'google.protobuf.Struct': ['_StructMessageToJsonObject', + '_ConvertStructMessage'], + 'google.protobuf.Timestamp': ['_GenericMessageToJsonObject', + '_ConvertGenericMessage'], + 'google.protobuf.Value': ['_ValueMessageToJsonObject', + '_ConvertValueMessage'] +} diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message.py new file mode 100644 index 00000000..224d2fc4 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message.py @@ -0,0 +1,413 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# TODO(robinson): We should just make these methods all "pure-virtual" and move +# all implementation out, into reflection.py for now. + + +"""Contains an abstract base class for protocol messages.""" + +__author__ = 'robinson@google.com (Will Robinson)' + +class Error(Exception): + """Base error type for this module.""" + pass + + +class DecodeError(Error): + """Exception raised when deserializing messages.""" + pass + + +class EncodeError(Error): + """Exception raised when serializing messages.""" + pass + + +class Message(object): + + """Abstract base class for protocol messages. + + Protocol message classes are almost always generated by the protocol + compiler. These generated types subclass Message and implement the methods + shown below. + """ + + # TODO(robinson): Link to an HTML document here. + + # TODO(robinson): Document that instances of this class will also + # have an Extensions attribute with __getitem__ and __setitem__. + # Again, not sure how to best convey this. + + # TODO(robinson): Document that the class must also have a static + # RegisterExtension(extension_field) method. + # Not sure how to best express at this point. + + # TODO(robinson): Document these fields and methods. + + __slots__ = [] + + #: The :class:`google.protobuf.descriptor.Descriptor` for this message type. + DESCRIPTOR = None + + def __deepcopy__(self, memo=None): + clone = type(self)() + clone.MergeFrom(self) + return clone + + def __eq__(self, other_msg): + """Recursively compares two messages by value and structure.""" + raise NotImplementedError + + def __ne__(self, other_msg): + # Can't just say self != other_msg, since that would infinitely recurse. :) + return not self == other_msg + + def __hash__(self): + raise TypeError('unhashable object') + + def __str__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def __unicode__(self): + """Outputs a human-readable representation of the message.""" + raise NotImplementedError + + def MergeFrom(self, other_msg): + """Merges the contents of the specified message into current message. + + This method merges the contents of the specified message into the current + message. Singular fields that are set in the specified message overwrite + the corresponding fields in the current message. Repeated fields are + appended. Singular sub-messages and groups are recursively merged. + + Args: + other_msg (Message): A message to merge into the current message. + """ + raise NotImplementedError + + def CopyFrom(self, other_msg): + """Copies the content of the specified message into the current message. + + The method clears the current message and then merges the specified + message using MergeFrom. + + Args: + other_msg (Message): A message to copy into the current one. + """ + if self is other_msg: + return + self.Clear() + self.MergeFrom(other_msg) + + def Clear(self): + """Clears all data that was set in the message.""" + raise NotImplementedError + + def SetInParent(self): + """Mark this as present in the parent. + + This normally happens automatically when you assign a field of a + sub-message, but sometimes you want to make the sub-message + present while keeping it empty. If you find yourself using this, + you may want to reconsider your design. + """ + raise NotImplementedError + + def IsInitialized(self): + """Checks if the message is initialized. + + Returns: + bool: The method returns True if the message is initialized (i.e. all of + its required fields are set). + """ + raise NotImplementedError + + # TODO(robinson): MergeFromString() should probably return None and be + # implemented in terms of a helper that returns the # of bytes read. Our + # deserialization routines would use the helper when recursively + # deserializing, but the end user would almost always just want the no-return + # MergeFromString(). + + def MergeFromString(self, serialized): + """Merges serialized protocol buffer data into this message. + + When we find a field in `serialized` that is already present + in this message: + + - If it's a "repeated" field, we append to the end of our list. + - Else, if it's a scalar, we overwrite our field. + - Else, (it's a nonrepeated composite), we recursively merge + into the existing composite. + + Args: + serialized (bytes): Any object that allows us to call + ``memoryview(serialized)`` to access a string of bytes using the + buffer interface. + + Returns: + int: The number of bytes read from `serialized`. + For non-group messages, this will always be `len(serialized)`, + but for messages which are actually groups, this will + generally be less than `len(serialized)`, since we must + stop when we reach an ``END_GROUP`` tag. Note that if + we *do* stop because of an ``END_GROUP`` tag, the number + of bytes returned does not include the bytes + for the ``END_GROUP`` tag information. + + Raises: + DecodeError: if the input cannot be parsed. + """ + # TODO(robinson): Document handling of unknown fields. + # TODO(robinson): When we switch to a helper, this will return None. + raise NotImplementedError + + def ParseFromString(self, serialized): + """Parse serialized protocol buffer data into this message. + + Like :func:`MergeFromString()`, except we clear the object first. + """ + self.Clear() + return self.MergeFromString(serialized) + + def SerializeToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + Keyword Args: + deterministic (bool): If true, requests deterministic serialization + of the protobuf, with predictable ordering of map keys. + + Returns: + A binary string representation of the message if all of the required + fields in the message are set (i.e. the message is initialized). + + Raises: + EncodeError: if the message isn't initialized (see :func:`IsInitialized`). + """ + raise NotImplementedError + + def SerializePartialToString(self, **kwargs): + """Serializes the protocol message to a binary string. + + This method is similar to SerializeToString but doesn't check if the + message is initialized. + + Keyword Args: + deterministic (bool): If true, requests deterministic serialization + of the protobuf, with predictable ordering of map keys. + + Returns: + bytes: A serialized representation of the partial message. + """ + raise NotImplementedError + + # TODO(robinson): Decide whether we like these better + # than auto-generated has_foo() and clear_foo() methods + # on the instances themselves. This way is less consistent + # with C++, but it makes reflection-type access easier and + # reduces the number of magically autogenerated things. + # + # TODO(robinson): Be sure to document (and test) exactly + # which field names are accepted here. Are we case-sensitive? + # What do we do with fields that share names with Python keywords + # like 'lambda' and 'yield'? + # + # nnorwitz says: + # """ + # Typically (in python), an underscore is appended to names that are + # keywords. So they would become lambda_ or yield_. + # """ + def ListFields(self): + """Returns a list of (FieldDescriptor, value) tuples for present fields. + + A message field is non-empty if HasField() would return true. A singular + primitive field is non-empty if HasField() would return true in proto2 or it + is non zero in proto3. A repeated field is non-empty if it contains at least + one element. The fields are ordered by field number. + + Returns: + list[tuple(FieldDescriptor, value)]: field descriptors and values + for all fields in the message which are not empty. The values vary by + field type. + """ + raise NotImplementedError + + def HasField(self, field_name): + """Checks if a certain field is set for the message. + + For a oneof group, checks if any field inside is set. Note that if the + field_name is not defined in the message descriptor, :exc:`ValueError` will + be raised. + + Args: + field_name (str): The name of the field to check for presence. + + Returns: + bool: Whether a value has been set for the named field. + + Raises: + ValueError: if the `field_name` is not a member of this message. + """ + raise NotImplementedError + + def ClearField(self, field_name): + """Clears the contents of a given field. + + Inside a oneof group, clears the field set. If the name neither refers to a + defined field or oneof group, :exc:`ValueError` is raised. + + Args: + field_name (str): The name of the field to check for presence. + + Raises: + ValueError: if the `field_name` is not a member of this message. + """ + raise NotImplementedError + + def WhichOneof(self, oneof_group): + """Returns the name of the field that is set inside a oneof group. + + If no field is set, returns None. + + Args: + oneof_group (str): the name of the oneof group to check. + + Returns: + str or None: The name of the group that is set, or None. + + Raises: + ValueError: no group with the given name exists + """ + raise NotImplementedError + + def HasExtension(self, extension_handle): + """Checks if a certain extension is present for this message. + + Extensions are retrieved using the :attr:`Extensions` mapping (if present). + + Args: + extension_handle: The handle for the extension to check. + + Returns: + bool: Whether the extension is present for this message. + + Raises: + KeyError: if the extension is repeated. Similar to repeated fields, + there is no separate notion of presence: a "not present" repeated + extension is an empty list. + """ + raise NotImplementedError + + def ClearExtension(self, extension_handle): + """Clears the contents of a given extension. + + Args: + extension_handle: The handle for the extension to clear. + """ + raise NotImplementedError + + def UnknownFields(self): + """Returns the UnknownFieldSet. + + Returns: + UnknownFieldSet: The unknown fields stored in this message. + """ + raise NotImplementedError + + def DiscardUnknownFields(self): + """Clears all fields in the :class:`UnknownFieldSet`. + + This operation is recursive for nested message. + """ + raise NotImplementedError + + def ByteSize(self): + """Returns the serialized size of this message. + + Recursively calls ByteSize() on all contained messages. + + Returns: + int: The number of bytes required to serialize this message. + """ + raise NotImplementedError + + def _SetListener(self, message_listener): + """Internal method used by the protocol message implementation. + Clients should not call this directly. + + Sets a listener that this message will call on certain state transitions. + + The purpose of this method is to register back-edges from children to + parents at runtime, for the purpose of setting "has" bits and + byte-size-dirty bits in the parent and ancestor objects whenever a child or + descendant object is modified. + + If the client wants to disconnect this Message from the object tree, she + explicitly sets callback to None. + + If message_listener is None, unregisters any existing listener. Otherwise, + message_listener must implement the MessageListener interface in + internal/message_listener.py, and we discard any listener registered + via a previous _SetListener() call. + """ + raise NotImplementedError + + def __getstate__(self): + """Support the pickle protocol.""" + return dict(serialized=self.SerializePartialToString()) + + def __setstate__(self, state): + """Support the pickle protocol.""" + self.__init__() + serialized = state['serialized'] + # On Python 3, using encoding='latin1' is required for unpickling + # protos pickled by Python 2. + if not isinstance(serialized, bytes): + serialized = serialized.encode('latin1') + self.ParseFromString(serialized) + + def __reduce__(self): + message_descriptor = self.DESCRIPTOR + if message_descriptor.containing_type is None: + return type(self), (), self.__getstate__() + # the message type must be nested. + # Python does not pickle nested classes; use the symbol_database on the + # receiving end. + container = message_descriptor + return (_InternalConstructMessage, (container.full_name,), + self.__getstate__()) + + +def _InternalConstructMessage(full_name): + """Constructs a nested message.""" + from google.protobuf import symbol_database # pylint:disable=g-import-not-at-top + + return symbol_database.Default().GetSymbol(full_name)() diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message_factory.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message_factory.py new file mode 100644 index 00000000..7dfaec88 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/message_factory.py @@ -0,0 +1,187 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Provides a factory class for generating dynamic messages. + +The easiest way to use this class is if you have access to the FileDescriptor +protos containing the messages you want to create you can just do the following: + +message_classes = message_factory.GetMessages(iterable_of_file_descriptors) +my_proto_instance = message_classes['some.proto.package.MessageName']() +""" + +__author__ = 'matthewtoia@google.com (Matt Toia)' + +from google.protobuf.internal import api_implementation +from google.protobuf import descriptor_pool +from google.protobuf import message + +if api_implementation.Type() == 'cpp': + from google.protobuf.pyext import cpp_message as message_impl +else: + from google.protobuf.internal import python_message as message_impl + + +# The type of all Message classes. +_GENERATED_PROTOCOL_MESSAGE_TYPE = message_impl.GeneratedProtocolMessageType + + +class MessageFactory(object): + """Factory for creating Proto2 messages from descriptors in a pool.""" + + def __init__(self, pool=None): + """Initializes a new factory.""" + self.pool = pool or descriptor_pool.DescriptorPool() + + # local cache of all classes built from protobuf descriptors + self._classes = {} + + def GetPrototype(self, descriptor): + """Obtains a proto2 message class based on the passed in descriptor. + + Passing a descriptor with a fully qualified name matching a previous + invocation will cause the same class to be returned. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + if descriptor not in self._classes: + result_class = self.CreatePrototype(descriptor) + # The assignment to _classes is redundant for the base implementation, but + # might avoid confusion in cases where CreatePrototype gets overridden and + # does not call the base implementation. + self._classes[descriptor] = result_class + return result_class + return self._classes[descriptor] + + def CreatePrototype(self, descriptor): + """Builds a proto2 message class based on the passed in descriptor. + + Don't call this function directly, it always creates a new class. Call + GetPrototype() instead. This method is meant to be overridden in subblasses + to perform additional operations on the newly constructed class. + + Args: + descriptor: The descriptor to build from. + + Returns: + A class describing the passed in descriptor. + """ + descriptor_name = descriptor.name + if str is bytes: # PY2 + descriptor_name = descriptor.name.encode('ascii', 'ignore') + result_class = _GENERATED_PROTOCOL_MESSAGE_TYPE( + descriptor_name, + (message.Message,), + { + 'DESCRIPTOR': descriptor, + # If module not set, it wrongly points to message_factory module. + '__module__': None, + }) + result_class._FACTORY = self # pylint: disable=protected-access + # Assign in _classes before doing recursive calls to avoid infinite + # recursion. + self._classes[descriptor] = result_class + for field in descriptor.fields: + if field.message_type: + self.GetPrototype(field.message_type) + for extension in result_class.DESCRIPTOR.extensions: + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return result_class + + def GetMessages(self, files): + """Gets all the messages from a specified file. + + This will find and resolve dependencies, failing if the descriptor + pool cannot satisfy them. + + Args: + files: The file names to extract messages from. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + result = {} + for file_name in files: + file_desc = self.pool.FindFileByName(file_name) + for desc in file_desc.message_types_by_name.values(): + result[desc.full_name] = self.GetPrototype(desc) + + # While the extension FieldDescriptors are created by the descriptor pool, + # the python classes created in the factory need them to be registered + # explicitly, which is done below. + # + # The call to RegisterExtension will specifically check if the + # extension was already registered on the object and either + # ignore the registration if the original was the same, or raise + # an error if they were different. + + for extension in file_desc.extensions_by_name.values(): + if extension.containing_type not in self._classes: + self.GetPrototype(extension.containing_type) + extended_class = self._classes[extension.containing_type] + extended_class.RegisterExtension(extension) + return result + + +_FACTORY = MessageFactory() + + +def GetMessages(file_protos): + """Builds a dictionary of all the messages available in a set of files. + + Args: + file_protos: Iterable of FileDescriptorProto to build messages out of. + + Returns: + A dictionary mapping proto names to the message classes. This will include + any dependent messages as well as any messages defined in the same file as + a specified message. + """ + # The cpp implementation of the protocol buffer library requires to add the + # message in topological order of the dependency graph. + file_by_name = {file_proto.name: file_proto for file_proto in file_protos} + def _AddFile(file_proto): + for dependency in file_proto.dependency: + if dependency in file_by_name: + # Remove from elements to be visited, in order to cut cycles. + _AddFile(file_by_name.pop(dependency)) + _FACTORY.pool.Add(file_proto) + while file_by_name: + _AddFile(file_by_name.popitem()[1]) + return _FACTORY.GetMessages([file_proto.name for file_proto in file_protos]) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/proto_builder.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/proto_builder.py new file mode 100644 index 00000000..736caed3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/proto_builder.py @@ -0,0 +1,130 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Dynamic Protobuf class creator.""" + +try: + from collections import OrderedDict +except ImportError: + from ordereddict import OrderedDict #PY26 +import hashlib +import os + +from google.protobuf import descriptor_pb2 +from google.protobuf import message_factory + + +def _GetMessageFromFactory(factory, full_name): + """Get a proto class from the MessageFactory by name. + + Args: + factory: a MessageFactory instance. + full_name: str, the fully qualified name of the proto type. + Returns: + A class, for the type identified by full_name. + Raises: + KeyError, if the proto is not found in the factory's descriptor pool. + """ + proto_descriptor = factory.pool.FindMessageTypeByName(full_name) + proto_cls = factory.GetPrototype(proto_descriptor) + return proto_cls + + +def MakeSimpleProtoClass(fields, full_name=None, pool=None): + """Create a Protobuf class whose fields are basic types. + + Note: this doesn't validate field names! + + Args: + fields: dict of {name: field_type} mappings for each field in the proto. If + this is an OrderedDict the order will be maintained, otherwise the + fields will be sorted by name. + full_name: optional str, the fully-qualified name of the proto type. + pool: optional DescriptorPool instance. + Returns: + a class, the new protobuf class with a FileDescriptor. + """ + factory = message_factory.MessageFactory(pool=pool) + + if full_name is not None: + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # Get a list of (name, field_type) tuples from the fields dict. If fields was + # an OrderedDict we keep the order, but otherwise we sort the field to ensure + # consistent ordering. + field_items = fields.items() + if not isinstance(fields, OrderedDict): + field_items = sorted(field_items) + + # Use a consistent file name that is unlikely to conflict with any imported + # proto files. + fields_hash = hashlib.sha1() + for f_name, f_type in field_items: + fields_hash.update(f_name.encode('utf-8')) + fields_hash.update(str(f_type).encode('utf-8')) + proto_file_name = fields_hash.hexdigest() + '.proto' + + # If the proto is anonymous, use the same hash to name it. + if full_name is None: + full_name = ('net.proto2.python.public.proto_builder.AnonymousProto_' + + fields_hash.hexdigest()) + try: + proto_cls = _GetMessageFromFactory(factory, full_name) + return proto_cls + except KeyError: + # The factory's DescriptorPool doesn't know about this class yet. + pass + + # This is the first time we see this proto: add a new descriptor to the pool. + factory.pool.Add( + _MakeFileDescriptorProto(proto_file_name, full_name, field_items)) + return _GetMessageFromFactory(factory, full_name) + + +def _MakeFileDescriptorProto(proto_file_name, full_name, field_items): + """Populate FileDescriptorProto for MessageFactory's DescriptorPool.""" + package, name = full_name.rsplit('.', 1) + file_proto = descriptor_pb2.FileDescriptorProto() + file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name) + file_proto.package = package + desc_proto = file_proto.message_type.add() + desc_proto.name = name + for f_number, (f_name, f_type) in enumerate(field_items, 1): + field_proto = desc_proto.field.add() + field_proto.name = f_name + field_proto.number = f_number + field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL + field_proto.type = f_type + return file_proto diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/_message.cpython-38-x86_64-linux-gnu.so b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/pyext/_message.cpython-38-x86_64-linux-gnu.so new file mode 100755 index 0000000000000000000000000000000000000000..5e77c633f0d3df7910413eed356dbc9b03400ceb GIT binary patch literal 2474096 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

xm7pg%fK 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ř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

xG+Xz@8g1s3Qr)ampUfOc??z{} z;#w8GfLk`7H&3CndaYM+mwZT5nKEpNZ~hCa%kplav}xHGnt7+K95Ytbh}_e~_#}?< z<&|Mn$Z*dwR2B_&H7VB^U&WY^BPt11_$7C?W_v)UXSF*i8?xPlK?VC#k98^dW&^;x zOO=Ur82M+$@-rKi@>ml+!(D%y5$dJe%+u{U)w-QqGUR5^sf12ShLyq$i!(PFC$uK} zh*2TOk9~xJL)Dz-BkDtr7DY^1C>->@8@!;GaV3EBFONFSx-=g3{o$yo-GS5I8Q|>< z^o2y%f1!$jgtm`_gn_^M1wZa0q=o`jgov9US*{{k0!%6T57;zGGonxk}bR4NIeF7p<8UyXjs;@73+*WG10Mrf@=AoJkXAD7G`xMVnUYVS0X>6Aidh;P$ay9v<~qfvhA!wi zSWGg*&g`J; zFX4@g9m0D`5;7-3WRTCnlbjrS7nd_HCLWGHs9}9hp5Gs=4dro7!dO`}>uj&#X zgxbDEfk;Ij+smKYT1cyftXFs;gVN|2>y{W)pM?&>Wn--M3(X#D>5HRBv1I2T@XCxa zYk?cT;qw)^@dzJL;Kl=pFclH(s%KBa&LMyOSx@|?Yt^CB5?f75?C z{)@c_m*ephs}C&Bl%&$6Vn904deD1DIl}h}rgGgpz(M>(reiXY&eB&Kf4fvm7}{Kqj1fyR`AIz+LQ!D;XYKZ2U(#TLRgr}K_hyFEzE}O zG5z#PlsE9ms-r)tVrzUDm>dqpz4|T`M|4lff-0)2ma7eZWhn^PVCY&KPA%ERznc+` z*6vii2IF5c`eoc%Gd7Q0AG_?ZryX7ZBhf9~tZ3KzO7{y5qP^Bj<`6e3#1XCz;p}X8 zl#IBN5Jz|^W%TDSyO`-eRn3?XW{YJdSrn%x^oL%n?JTvf)ddLj{@rC{Am244NYy0R z=7Tz?2_%$3rT|iEi_8*_Hn*=|!^OXylQv_w;9Mibn$swB4+ePC5cXT$qt^(8cXIrk zAIY1Q`gOMvUE-req@vzg*6kIja~09=W!-?OPmyrNersvrHs1wo%V@8Bz7-s_ZmNlB zPuhyqpK!dy1?i66=DXB?Mx9Q$e#nd{3-)|vrx9g0uYfwu4Cj@PU41Z%vI=$3 z%I0-nuDh^K&r+3Y+B_6fs(K@O30AQiiDRyo)_S4oh7PqMIpvFJJphuq~ zfk5~8ew#qwe*N(+^=qWExG}kVe65U~qyAMt*D29{Xki=Q>hf6Jhd$qoSm*z#IM$$a zuGgLb98)t8rN!@cu8!`@_n<+640jE;&Rhv4D21RZ(_VSFyNDa#h^lDJ`W}A|cd72- zF6SO@U}nvRlU>=Gr@Le%7mC5)D9JpG(Po4YZRk&QvQodcvgcNDNbwrdM4;jW(VzYZ zio6s}2~o31$8LEDgie+~j4By;fnaHufxQS88Nmn?C0H2(I}!{` zqv$Xh5DaWppyf7YDD%8Zu-vm!fy5#90hQ6mSn+aOn*p^`gBC=m@+IVU5e05is$y!cWUSzZ)j0qcGOZjU>2%iN9`sH zbQSIMW$Nj0`6m?f59pi!esoaf|8P(8&$3e*W*ju$N3I(0YthvPorEdejDuH8&C9yE zSmUn`bd!X_>PN)S1I-ffuuwiSI_eN%ZQ#ARgINquOnRTBskEU#^=3vad`$=& z5MevM)p94l@==ms(o73GzoZ)pM|W;hbVpiael{HDp&RIt1_FAejVxB)s_IrXt0yDo zehdmoYqcKh=63Zs8P$Jv9XEI#UPz*g|1a)?8E8GC8NxLLP1M>Lude_r4ymI^h~6+) z&ez|i6?HA>HhLX?=nd)I`@8Q#-WYk5oT6jftmVsGY zs-|p`8&T*rOosw7YtS$&EO*$*G$pfUGD_w{G7q?G_LqM}x1L}heOmhW9;Grtwo|qx+fmxSSFnFlerB=! z6S$BR$~W=;GhLG$(x08PzC-*B6s^tdC^JsXB(a6bGuKW|UvGv5kh;tomntL;^hdCb zps@qtm7u~$OAQOr!jO-i8;h1?@zGOb(IR0VJu((8I`+|3vFJ5^Ftpx7Ff=K)^SPJA zqGuGN0~<%Lzbcx6JW!aS@O`j674$DS&-AZRWDwRyQQoOtxG3=5X5X5S5e5~>OfYgN z1XDISwH#(NwLEC+s4c@VdjfTVG&R3pU8Ah?3(Rzn3{CX|M)papz=C zkTfQCv<6E%??QKZrmZZKnJb+ddXKF94z7Ozu2KYk@R(BsL`%*O@8owx^=$fO?lQrY z&JA84&FVIP-R_sL)!@?4)*r`RyVp+|!aSxGLI3f#h^@tAbMObz<)-e|EWW_6o~5); zdXd#LXHA<^54Seejjo=&M01f^-~v~x&#t=-fCnV?vGB+cPR%dv#;?GwBK6x!%H%zB zE2zlxZ9{5tzh>vZ)KoW~dp{o{ZFu^iqD6T#_8EhNq?p3d%d0!I~hC7YzW*Bj9^ab>s+&<);kvVSv05X6N$hseq zJ}|jFKhD-)4XKA2_d+$;R5y12N&nTto?rjQwvE-=S*}@T@wmsdcG&0@AE7Ouf;gy{FgE#4)JubY*Jl;4mu=Vpo6!fH%_!F7PQBz=%5Nu z1=Uc&A(J1?G=hDNX4v5MoNt`|OZt%eEC0=)`NvciDA1|Z(czR$W>TGe9-o=O?G(^R z&`uPV4ACFuN-3wP{|(}ST7w=$@P8s2DAvRH#O(w(A`Y4}$CUnuwUC01(AX4ov&x8W z$6#XkHwrWo0Qu&$5#5O)1=M(&lFHarx5m9Z7cX*5D^%3Ja2R(Abhj{dve#~JP05bi zJ%3UHTx>p8i(Srl;Z`Y9yj3WIJcjS=j`fMn1BphZ{}hgAd&|GmZ=;(G@!?#7KQlMY zB3*USuO3ELQa{Qs_ z3M*4w+&vIY0h{@`syFLbQ^+{Mg{i(Y+RHo*+ytur8o*?odX!=+p{Z0IPv&p6zEM_? zF3i_AlFw>-?gNdh?{uD0HH^~FF^R5Mp_J%N%&EEOrQ~}1QEmq~B3H|Q)`+K+6mOCJ zx35<0Tv-26Y3>zQTuqLoMgwN4_O|1Pbj{JA+U-!Ce|6ROU{_Xf5{Km%G_hz}4%vYPaPEluDej@pC z@?PRb=-sGjVg>gp>K$n$NQPN;@FS_7&DyvA&S}Z?l7>^wU##<@MziE66HSj2OPs^c zChC9x%dY+dHmHBUPpf}e@A`Qk%smeF9`|Ra-l*cfGiJ0d^ZQ9Zs|Oa+&qUAShK^HG z`<5+3MzvxKK>FDRLT5)3Ex$(sLH=PYq9+7Rc`q$WbiGV;rn8g(bp^oF{HCIQx)%Un z4h$`9Jnt~SC3{F~^Mcp<=XVPBfhiA3uGpcSnFP2ht-1e?T3d#Ezg7Du6P*%-n?w6) zXh4&eNq;ey>!!+b=|1m0;S`+#>=d@7YZdk3Q!eUlO!4SGKY7OKJ~#4iSl^ig#&ZoIo~P~R@TzRfpL zAJpHR{sb_J`s^n|J@q-u zvnpC9`KSzB&U&CSwSPzUvhEi;hBSjw9Sf5Xcq>XDtBftwgmIb+m(vh&qWjk(_SC}q zu$}ji-%sTIZ$Gw%hzVkL;1jOW>RPEXix)tN>-~lw+nMa2n5UCHvUI<7s>!*i(AI9W zHEv>I9J$jdYI-;_>&dgUvVKQ{y#On5Zd=kcmPGeqmaCK2N^mAm4Ly`v&{!|T3GJuE zr5;(&p3}Bmo-+OG^rYX; zovq?}6UWByDz>HiEfmS$6W{omKvsCPzQk{}csE=W&ts}OJ2>djm0_Ssr^rhZ*0*FT zh7Ep`gOuAggY>8&apfYmn>)V2y1%L^oiokrb#9(4i$25$HPzG4z4n^w8Ib6@#OfL` zCfU8LecNQ}Uafv;LO+nem;woie!%~3qV3gD!)x?PRi|Ly%N?jOFK(=re{C{7VodHwMDWdNeSNp(z9smj z?w!gvy*tQM-t*0e82Pj++EWIP#SfBc{k#LoqPQny155SbC3zg#jg`2hVDK_+v}bNt zO-XfJRQhF|X3Ewa@B_cnQrxyrP#mY?%mM9xK_aW$Qjegf`egRxa>R9{_c7#~EdMcW zJS*B@k!I)Yt>|$sWfsCo2ybcLZ5A;zO*kj4TYW^eCM~IqR};}9)*YVtJ}=z8+QE&& zja7Fu0tUr?(JO|>!7L4tbM4>rb`O6*+qP}D*CRd^5THs^cBjSzao4)!-j^f(MAKlF6a@;H3I+QeBfY_9kl=H z(8cUHUA&@IO17r)WJeb%SpouGTns&kE{?#Cr|#!kgnAYVe?Q3*q(_%V6_!dU|7sp# zhQ8km&L^0JjKR6yM-<@vH6KwC0KdB;P#Z3=W>EAQQ2t(3Z6P)rAId+O8&78fymFe7 zHw4WTLt?6HCumXO1?^NKn$8IGh z^H9xUgVoV(k}uhsAtyPw9fxQX-1ZPZ9lw=>+ZVI}PNm~+H?toYzY+Ohf&rmm8e!wk zuKai-zQ*#wkHkd8v*?x*5#2hzkW6oHcby3Sr^$ca?N^pYGrjYm!QY=3$z8|(a(uit zpS|zZ0)}1DlG$7DS$_$+JLz%cZo7CVx*0Wq*{l1zS|z0>mX?qqGYkl@nN@DaH2Wxz zw&DX1V)h)yy2l@%7hE#qDvr(WaPZ(qlIdM5TWl|{?&)N9o(x-K(dFRX0qJC7-d6a& z^h@?zkgR)p+#Be%gO?@O&XHX#Dc$mw=*>p}uJq08tyZQ>!X^hZyg!#2S%HMyHT6+x z;*!x6N-qUN=YJnSjvnye$$k&6e`N;B5_g;+Z&FmC*>xA~w|CEna@xmg++Sqe7eA(P zvl?C%y&+0VErbI7$&H579sV=lDa-$b_vy1W*Y4yj%ulUko%Kbdy?RDGXz+NB=4W<0 zh#z}0&CQ$UH$Sp0e+4Yvgvl;54%OHna(~?V#B6BK_C1APg`PRRmRJYTvw`TFiK%zn z*bSol38JS~f}(TqpDKcM*FgW9glkJyyEz5mwxl17W-KvKv@?s9X{y13auh)Qb_Mjg zQ>v%*!Y=~OW4^adNqT+(po3q?J!~@UJ5{;+Ezl@Dl;vjWBU>|JN0IT0X!Z(#Qz2^2 z*0d2Pv+PX89jv&_zyTK-umM@F5*6b*HA1K;^cRb)-pP2fT2d|tX%bWYH zfb;5D)d1x{u)7!KM<4i-)6?xn;9I@e6R(@kMZE2k0akfSrlX?!g>n1BCJ^Tb?O*a! z$?KZqwqzPN`oytg+~%DuI!eZUH&E(}OA2r~N|wmf!dgxzrauZQ0S`+%Is@!)?;xc$H`s@%o+pCa^`VA7Pk%Qg^5dkB>-jz?)%+sN{$`9 z!^~vArR!HBk4`R2){Uq)4Ose5Y5SmLc6_UD0GV+hO=m}pOx8Wvj*-9&n2L|~HcXc# z=Tf8FB2K^lozq(Oj9Ru>*>GyZX(pq*zK|J4cUsHxKlgNyIk_r7t=NBrIQ-gLW@j~# z!-JQZT1RGIKK**`R3i%a-SExCoMmwnfX$WVQ9G9oq!(!=&v@TzKb~VnogGyr?ZZ-^ zAdI!&$lE$&9VHMfZwmi@)^12;+uwhgMrN@4oMvzopo|IHdOn6>eW%#3ci5*>g=YwWKt+6@cI1{gPz%lKJ$qIlXr92SS9cMw`=r zJ-I2pNU{${!%H*_{h22ZmX793_k2DPiDiQyX#&(cfb%H26ZKgSmf8D3TXfbQnCRL8 zX*hV9*UzzEO3}*<+HoP;b?QM5LBWZr(bb8rMkxZ>Q?*VoeSMvnWD-kNuf+2N?AqwZ zFpYp*ubi!61vc_;^4oh&1-4<0TA!G+NZ8LG4gJ9~iLS#C+O`5ZP=S@7*dpl5gtZWD zg=7&+54P;{id+aTd5w6l9Ic4{{x}_stufTbSv2R?7_vk8Duz?Vqse_9Ox7()T(Zil zFgLIj(a%+dG}U{wNU@CqYH7)gilWIN(pIZ0BE9dcB`RamR5lKqp@cMMtdS;NT3AA7 z&WoBeiDafZO4dD@`0qVQU|X!LpI&YmjaKCzl?fPC_cyPiasPVQviFD$;9W&PkO! zP}b&W@{=`pyhbDhdZWQQZ$l7pFHLf9pUQYZoa4&)0csy!OM4sLcc0Pd__CFxU#B?h ziP~Emje^~+o!m?EKE=Mq3ht$-ndsb!)`y`teT$`i1kp%9Kvfe#Bcu}zw7SL3ZkbW7 zbaxc$^}mvvo*qR{rLPVBFV%6g>JT;M|CC>wf4?B_dM{LHf#u$5tv}-WHjbIi>Gw`fKhcz4Ff1`=fwvrRUT|B7o%!Rw z%4yZk$@`YH?>0QMe`Q!>*2qYp#bs3fG;E6wmReZKB}auxKr_JnhEtPUENM8c&^~kD zhg)mzTNMp9Vj5DY=BZ^?P5#eu|5fQz&c6HC!kKdEQ>jV1UhZKreWrgin<7{<<}-Pf zN&#Kbl$ev;M@K;$Qg8QTRF6dO?XS^{g9(@i_Q77Y7d$o`vadh_mfk(k5g$dHQ!Cd+ zbB2QA%ZQs{Y`>GKWG7Wtw6MxT>#F%7?qPzCID?efXqOyL+h}UBxvW5cW+vxC!TKa{X~|R%&-~aa{kuqZWhdf_ z`ynETNg_Jo0Z7ix&Gk-P9!Z{NIIJqb?I67->EZTe+`0kfxKm=+J45Dwes^WH?Tu9q*x|8Iqe7Cj0V-dOfNtIr?b~CC&Xw zLC@DhI&;#}(MCY{fyN=*A1RbXH~me*q28tP7~z&|BBsP2oHFzy8NX2OslUInB8 z+%qfFAaTy9`g|xp%;+j2s%6KxabpVY*W+uF*ly>vm;KfNIJazC9)?CjW&cE-Y+h{?8n zkO)-`&Iu(mLN*4;&0*|LGq~oE z(11iY3+fVYnT=mYI{nXr-1X)eCcl4qh{>Hu{#)AVTKh-0)3v$b#2!2Qc#eyDPZu$y zhEBMLg%Hy7*Zg8lO>`Yvrtg~j`PN!;w|&)Do|aSe=*HS)W}9Vm4=%|Jn3C$j{pZJY z-Sw3<8Rbq!GI1QrL|M&M4;F<}w^|*fm*1M*KPGtS%p4pmV^i^8YML3vv#mJ6?|B$oW4cbNMa{bHBb^{hNhx?i36m-mC zm~y%gFfqk?yM=X&NX$m)$jj!6>knlx%NTV*Zn1u#)l-Pd<%MCj715GEXTwsmQ3^q5g! zqI;>L;V9o1Rz-v9OF>e-$80X^%hn*cb9^IY{X0lW$w=v!qJfy2NbbId$l+*frJ2U2 z0u5(Iw1S7`?7Uf^2q!`bBQF(nyN19S4Y&s}k26%)?cC~#AqYjTu@&P>qHBuXLpuhY zo@-vBmggB29$qS>KZV8LAuK8g;Tf^;s93n#hbbC7O9}pa_c1aAZ&HG_)WB52_>Zp2 zjOF?VAZn7Xgamn~GQ3iPq$9++ra;q&%dwQ+`5enFsFfMnXBOjcB^ces24gboshFXU zN^-_UnRHE(n$az9R#~=Y@la_T(shXw1k46zd!TlBW>jg&ASfajN+xb{VH@8SMea_Ojvh8stA3}JD+3&QkGj(-7(N){mWM=^0pW^{(M&+TqJ;?GhVUIK5ng<>kgVwF6&$sVsC9`+40&f9 zj(iL_m9h<`_=mOZ6ss;p)oBU2A%m7c2BT-ME$X|OfiM3-vgqiJ+)#^l_Br^R>7g|M6N2!Zt%U_Tj+d6%xwC*n^!p5s zcVg-q)Hk>sEyr{DAw+P$k8yc@bS6tjNg07Sa5}-jt%?>L^hfY>Af4R*QDi5&4yGRk zHs@yX=IjMqZ<^KXH^%DMNPX2AIPfj+qt@s(_Ck9heAB$&Sofdd{p}@hj5K=j{yBb6 zuT`W0eXwrbVxi;y`oR4?4?!!x>=CViRQBbhS7-{4=@m`bmU9DJ0$O zpxZU%&!GPQmRFo1=Wv<_E>-zXICcCouyv8 zTi^Q@;U}3|wJth>Eo`Zc^VF>C`Bv(AtQ#-jNRk^zH{80NGYz@L=nF;riCl-WHGdr< z?7kkIiq@N3U>Q28w1lLydbVavtD|4ho7@`i4NyNHZUhe4Q6|jCWL=LBOk!FYjVS6Y zqL_j)iaURp9>8qMCw2YEH}gIYr@3|ts6QvTf@W8U_OsG5M7Cn9?7h3GUKYFcZ}s)nE`9AKzkBNuE0dgXS&gSE`?7;p_v0dfNiuffCQ12qqUf( zT7_||*TOVvWFbdpWpT_~a|Wga<CiOXGP2MBOP%+}m6n4XG0j(<;k(TT2C z-olA}6<}`3{E*Q>T`X>+`LfwzeylZzS8b^#omWzB7d zObr1T^OOf}Z1ui?59QwumHTQ{UC2Gdat96H*^DO;m;0)8S9im!CY1d1`Dx|>Vs-SI ziH7@5x%WqUb-aMdeaMqfZCG|YYo5)u+&lv{oyGozS&V9IdnqUg5mw&(Gq%S)BlkFY zWA;b8o;Ln1w8i%;uuq2jB)swL8is`NtODZYkXNGXUn~%sGT+g2;fZN4LbU9~4}Mc{ z8%0jtuv9G|aC!=P%(0*PtUMvm|Yy&CGy zt)2WZmd5FyY~9OJ$$ffa(rnFJC5|Is(i%Jcu#A@fKxGrpUWbQaK3%Y%QA@LGiPDpJtV_9c~z-^epYc-NoR6P<%ANWXgxg%tJjMB$S0HG8fD`EC-tU5MxP8AQ?qvCc_ zUFPI+(d{<~4$uBcj)M)^mdf=l{np?XP@f#qHWHs*HOrbzjH^F|#k>~g%-Dg<14Nbh zD1vPSwVWncTMU-^pfWF|zgFIEeqPR(@+)PgPa$|~EP6~ax+4~?aqExV$yjt*F}gfN z>*`sVfUxT8OyEe}e=sVU`J%k&+ccl9q@HBv#7Nq(7Q$u#y3${R$KzZ?kup~)z*W!? zT&wgUaOi`1(E&mqw%*r3^tx=wZKSX%w*U?fnRLQoTW)ep|*n8GSuWQ#_da`@c-cEj?oBV;qEIhk#$oD6~69XPYi3e0giYtr3;Jk!U`jKy7Q zarp4;*H)ce@X3I)-n{*`+ipvaev{gMRFYh{Sltq#e9ExpAO#hb5 zPsg3($XhR|whCq*sv1rJwNZLNLVbQm$vJnvc9G84o|BliBPCnXZzlVnU5yK!&S~C9 zGsEg`QEQ25i@{lQ=8~CwG>`tPDYmleG%aPVX3!dDxN40i$I(*i)1$wAdlU z$_)@S)^gAZPx8`ebGhiJCRWkQVHJyql`{@>c)M9NGw||jF<9G~^F^r0!>SA-)8Aqm z7o0MUZG)E${-AlT(4s$S)~i+C-Rp+okE79$AJY}CbzIAs1eXoqvS&bZ;?DWWYm(Uk z^#PB`(aG|rY;(W#Hz2W&il%fD?QbaRYsY6z z4|?H6pB7z)sXq6lfE4Hh+`A97ng4tK!-7bpq97GD788xvS}pprDC+BkI&Ap|SC22GB35UT5G3juzL|UEzoNx~ zlh;$=#{3zhstmBjSj_0it0lDQDL<+nqPzLLkF7e%J1BzF$P z;_As9SF0)L{Y?(J!MB&`Hd~z^@?D)2=r!tp!9$Fi8##VUl16=MxTj;tua$ekee`+J zn!W=c`$rpirSJ0&@jmb5`}~(@>GMVEbHV>u<5yk1$M5Qz`>r3q9dZogU+%}Ry3Qz$ ze?+yk!++925!r?)uMOiLHnMRIxR8}D-S?epV(0Xz%eS5QwJ-;IZ8cKR&i9a9)@ zN3ZejiJgt{9@2Zf)r_~z#{2SHeaAc9n7O9j_p>_Q&x3tG^MCC--fLA)ukjw^>RArq zYiN@oU-R25B)#qV@7!ig4|1^?gmXW&7`I0wsY(LeTx<}} zuf^m|{yF@co+;8}{*n9x`9-nsyYqME{}lWFZT^P*uVdfW=BMYcihZYZ6C6=?L5dhs zFVI&pJ*QKj8uUC05zEVTuwnVQ*rYg*iaT?PoM`zu5vOK9`atH?R}?bPA3 zwoF{|I>x-r4zuuqA1hm0@PI#a1~yXm>tzl->fIjsr@B>iY{oC}T^VlrA3TUzJ;~l& z>J_{h_S9DVl#W(L+nLBtlZy2;Q=u8HUQkS%oZ@(5^x;$Sp%tqQAstjw-uV{t32a zcw$oSHdA-SD8$`0}BA%9(Z0>;o$iko@;#Gw7>g&)V7^I4U~Ts z1#SeC*K;95PUnI8_NV(GZOO*adA@J{+phUanlGU93zvTubhd7y59RbB*dK~YNU$E> zc8luPRwy<*ty``oV(|Rji7elQe;_TotVndvM0F5>cHLr>(CR2*9{VBhBoq5Cdnd7- zT)|m)mdc+1l3&kI97YCGnezjT)mIVfJIv~GKIpd7sWle}j@YhWs0tig=7!6E*INHZ2 z&{5W`ZOR`p^KrB!(RCFgl3Or_D;Zau!`F|OsW z$6Ma@Gqrr?CR#pFE$>XrAj|0&@i}VLrSunfSvLn2=cuKZxQS>b$7%Y^QBP!C(jq0L zh7PA)*k#ZKYF~5I_BN^1OygUW@YXt$Ki%uS{MlfR`UM7M$35?wQxBE3)jFgmQ~z8S zowkN{*v&&lJBVrBWnB{U{|V#iV9uRE=QcK;5)7WGxxDQL%Je*UcNBWipFxn$EhBaY>m!fL=Io&Z1Tt9 zu+k2YuZlW_+-%LUl@2WDv3~w^5R4bmZUh94?Cj(Y#K9-t($T)99bHQ+_i`<5{+U|Z zZWAp%r@gU-pjW_p@u>o^T60e_wV89ws%Z9An#C699s#KF9{tt#sEcP_82j*J zEMuQ60^i8kk5P{fqDS$TF83{c$+h$t2vWzCNx`&m3(#M4K9bMTlr*BmKcilkkDC+&Ikxp?1 zvBLDh^e+?}QxH3Rgmp_A;}3iU`xQ=wJjF-UhlpW5qB=wzLIg_Yo4C=m3^}8mP3S~d zyD*wLyHrP<9HgO`wcLgxh&Hk&;qy&~YA!^ITYa&5CMchr-UO8I&?R4T%fQW#;)^__ z2pbmMW0JS{dK{?jewhNO&n{K~cxyi9%u5{9_Z)<7AD!tc_`L9*%BMR_d=p!lu0`4LL1f27>XnSeum43;mqU07!B_?~$ zOjNB!Qet6wCoxhX^iI?3b9>1*C;eb*CD~t3Zt{NF@0Wc`w!UmI4t~KT&ka|TG-aXMEMAAh6(jODNIxczA2pbmww9%Y z)~QvrxfLhB*!4m_bZ~tDYwRs)oRh&vNR#&c`r3Ayi&sZqi}g#IQ?GuV{{qxK+Q=9` zBH25ulbOxe&(H>)a>`rXG_fecWXI{JWO|26E|2M*G0lQFb$BHk9q-FdgsEF%zrS6n z^}3uAmQ$Vn6kg+k3~sSLd%`E-5(cV2XCb{n>T>2_(*Q^;3yFlwW8n%PZr;b zhHWg-y*;oRyngTt+Le5yx!>bQpe zqszt)D3*(9GBpYwgC80E0eH(?GGE=Cve%-krt+UQ6p(XQuNXL6K2-Er~6Iezm z1OnY?^igj6q8ucxNKAWztcKy1(f>L&)6`SS{Rp;a-P)Xbb)CCVVn=6_&emLnp6@Vo z`ebnb0`8S%iK)vNcthRkRMr7K>Ew=8)Y(x1a)ugN^A;G$sr#v@gXcrmN2jCL6LaUS zzCy)qNu4&yGabn@5A&s{kX6g5DFyW~T8NubfvT~SFh&%UC$Cgl1{+-Z?zaeTO9p`M zd>sev>~@Lh%V=<1!RxNIZimW5_oHx9rk+z6Twg%7*gDmn zXe_sc2w`9;+q%B)`NZ_6h~|)P-9w4&p;o2C*+ww7`A;3#zF(F|k4GNZ-l4{r9W>$D z-kSq!qkXS27~T7vHU~IQrgr5Lw>nyi8%qy)cyZOyBR*q9fJeqZoE^{%XnGY=oghcZKbT%_nHNd~@YWQ4H;CV^zlQ3omr5 z?Mnnm#Gy;KgN*ItUD7#9;{K~iZXv$gWJp?uh1+EM&(zfLEtFmbal-uFKO?$%G_wH9 z|K^DYm!uA#!7}sdM7VG?n-q8CRBD zcmcVKi{3FpkbTjJIyYEwF#JE=nq35=NPIK01Z9b);#B@F0_eqzwx%HN_>F#XFh3ckM7 zs?~E;JQyK~p5$zY1ihB@^8e|Y&+Q#u)kx6?%88D?ZYJK@t~ZN`QPu~Oi|YX)!Nv7u zE{eym7Do4j2Uo!~h+D@-)I`e=*Mz&{STfa-KENYfZERp-w|FYB+%Qb<*N4&d75kQ{yARRMfn(V$W-fOHBw6k^?=8#Hn>s=k4bCHOd zyXYlw-KqB9I^RSgTCveSpi74Wrcv%@Qpyj5CD;9c=#GQD+Wv?T`eWM=D1 z4#aEdbqf+*9rOf8CGxeBU!E8`sg|jYevfHYUHzsqpu3a-T72zlqp#Qw`l@Isoz0!Z zsEYK1?^mWQG3VR+cD=wYB_t&?o%4lR_ax07CYq%txbKzpQ}VY{Szz+g-WTewjV?0t z?yz9dw54jzSKJ*eE!nyADfhpqI}`Y*s`KwB5F{>j;)2GNs8JJ93lx+opa}%HgA+wX z#RbK>6zhgCBdDwZMY#=8#GBI!L+~UZ5K*eebk)# zVMuqC`7^>sMPnIgvmPfE87JOJ^*y>+g56c-(l7S#h5FKa6HTppIMWcr)*pN z<(%YjR|M}&#<%|CSA{N_Eh(b^xK*J`ALOrII0{y~Wklo}UD<=~RNtv9wUvW_$w1W) z@2T&`yzjD(BFS0ll7jOC1$_zBNS#+1yHQT+?5W0SiSCioN9~O9SLyA&d+LFIud{b= zT;N{o<@VhXfqRS1J!7q~5&KVjg+vCwvRT|q@5haqCU?M<{5AdI%lQ}4r>!Xk<-bvu-TzW7{SW@~{JgN1 z!9507sN|k0Be;jZ=}WOO`u<>n$93g5n(taBt3iwg`N$gM_I;hVQhoR83WM#VA}G&q z#8s0RY}h2rV3vM1K$H&noa0_=y;@?hd$>bpN;MIxh>jc)OxT`f`WWNK)7?ID>t)%UJ0 zP-HjrBKbRFK1KSn5(m2bFG{V&*8_OVz0SU}!QFjSazmiI>WAU$Ba!La^Yy{ry_tcI z_26FmZ&D%|?R$72zQg*}cL8IoVIBUO>DZa-*dBV$y-z2Yj&;;ZEAT^jmX5iL8(YuO3wZP~x#9k_eKX;IylVx@epJrGUW?ri2<(wgbIs8#Q&CLifo1$n9Dm;G+4VoP;sR{@ zPSQ%R=jh8_{4cwE8>BIh`Y!HFwzIj-YG~h9{?_XIfG*A2#l>q=%(Is^x6l4!o|)8Z z*D@hg&^P5&ux3koCMMIjd$y+s62Cr7UU8$ zv&=!V?kvhDOH#uN6Nm*?2bYv9CE8nrNa#bjb0;#!)HN2V&C=7;7sPd$Z*6wB{<9s+r$=)5@MGLbSMV^?=%1j{ zAu0?s)X0axO7C6}6}stT_o2a1Zw5Jus8#+^l_ThfKMz_PM4-T0x76IQOTJ&|Y3`-R zdR4t(t4a-gQEW5qPa?aiRx{3jjuJ`VZ3zQpYYPKXZjSO~K6&kt?_udRn z-~;sLOM(`9#xW?(>3eMhgEjQ@YbaJ}QQl4mvBs_cw5*Xnm-jL&GVl2EUS@IT)%0=P zG^0exi@cJW7u|_R$$Xk&uZ`xe(Tm;V^*oVD_X@l-%&&canwUv@B${v9V-04eXXEPC z2nI6%O($?K{kfn?JtJOuKdMN-s~cu6tMTq#UgMwVc4kHTDO=pMCq17FcN0Z8={DPklQ#C~j1XBo7O=t`s205JKj>htZAXF3 zGsYf8K1EWdk%gAypXh{BN5l%raP+5=2SyT~kS0|rFF6l*s)%wC{-Zc*Y`P{vp8l?D zMwF4fwTyL+5|2Mii5YWLk#FGi^CvToji!F3<*V?MGLB*I4q(JF8v9~lkn1@0;B@Hg z7OATsObE51v><+?PaosFU*`U2u6Z1~x;b;Hp_BL3UW?m*7yH*EQkz$}=fOH0rva^K z>9%Sqhf@JpX$x z)MS&q)NitFZ)C=kYO4ElnjHmZ?j|xc3}YghvqP|Bvl}TL;W|5BHeY;fn;M;T z@~%7icYIRW!Jdpa+gloqp)V<7>U|RV{>y3C1jjbP@tSbgINqlTKl7RpYPf)}>8r}4 z4F>J>sXhQVK4}u4e{q(^#!&NQJ>g>)d`t#^zkPvt{s=jMorKAMJ_^RBmBwmo2ztM% zh9PFXf6tnV4n?tzD3gDveh$PTQF0m3;kd(zCG;*z-GSy}N^xy+beTz;e?3KO?Z!?b z$r5g4^{Pm6@FbSu`H{o|aeTx{7CQ~|V%6loB~95pPhSat5UO9JmkG0PIEFu*@Yi28tX^*(I?<$-rM$lOz{3EUvSm%Dlu_HSBJ# zaKAi9oPLGn^rzyDHHpue!ZL##p*Rn}n)pLrJe6uQgsDwlGMyF~`V2MnaS|^=9}=dU z&eP0^wC$4^yJ2h8@(|Pr)sHj}a}*(QdZh3w27lU0r=9Gr2~a%jV3B{`}PIn`<`W z0$a2E^qC(w=h|xMSNC4AOu=WJZ0)_1Z_|e$E72oK((cYFUK7Y>DgL$P2YBV98(4k| zul&v%SpM}fwmt6=eY)QEB)jxFMM_&E;L|n?*nC!9@&&>*L%eXsG29h10 zo_}H68oPFD2U2okl{;0My>M%ARjgZR)?g8UZ3_XK`RA_O{~$)@eK1XB&t2&)KTxXg z%MVM_YIR?nrAzPJm4&zJldbL*H^UL6XKr!(u&i)L$WZJ~5Tuu>H5V2cUZ;1{WXSjQwtnio~{ecmJ=c>G<@q7+L`Zi${!0-gsv->cg0vdR$*Gb1$WPncq=p z38gLlN1AO5_Gq+e{}BB`?idyO3&mz-i~TZCEOezk979F>Qq+uca(G+nyfumOZHcEd zGlS!ETkv9bmVRDRT^*QI>K=TVNZjf^@JIdPise8i^7ov~6;hx%LWl9~Z(1iEODDY^ zB119n+`LjVrNGAn&~Fo`WtjD`B*(gdi+?gw9Ccd!yhpz`SUMJkL4ac)}n7-{axJSdAVKnZ~4`4ZK@AbB0FB$`j>h22Tp$^=pjq( zBm8)JOK%p#R`(t$dHlK)@;)huSmcu#{ZQO1m`*pUT=r6cka?Z;0sQ)ylTolqon$Ix z<-CTHwmt3fOJ|F0qq(C52NF5Fb|H6Ie(}y9uzP;sJRa zj&{Od2N%T{krRhPS&qa!808v5J{zrk->GaPyF@3l5_EFHPfk29njB29N29rIZ|$l? zCk_7*D<>2f5In9+@-;eJD%MaCYIs;hI3*)B;BKesvrf`Mo^?{&rZfwptR266khbDN zP7SzCHR%LR^FC=*TJ@?yPym@V|4EJx(OaoLvN!PdYIlowc)Q_!e8D8&RdFi{baCH8 z_dFyupieZh2i4N8i;7L)pwBl=?-1MoIaj(5Jz$9CbVd%QP%plfTcc=cgZZ^SUJ<%P?_ydqQ&H+{lFcr&zV++8cZak z{>k#c-TIyG>%ZqF5jJwondwKOow5`@sv@`i>HS9+PXTUN=8`pw1kUD&Qe=?nrrqpl zE5lkm=f3dEWxakicejIOSIaeJV@Uo&>PIg5I-{XJGmsdD`MXP$lk{ViIn zzxM)gjPEI4JC6*u^JuS~TdvjLNAGUm-{07JzJSrywatU|Z0XfAm*pzk-!q7k5A^pA zo_+uQ-B#@k#Ko;}XUme8>N~+}=P6RGeVjQR9#i9Yr7ijM_nCjS@9%}Sp3S{_b_&+B zt5?s$s{;MKU|C*&ALiNj-`{ezGq1l3&Ncn5V?wHH6J!|h`+Gj)s+;@Mmi+#{{?GRP z{jIHMC$F9!!Fu-h>UsAMf&L~4mI;jS(>(kB``btD%7 z)y;!wOMZXfyQ_VF|7`2&;nmYWSkFOTJ)izQ(BD5T$?NZHJX=qH{S)AY1v>XB$9R^?569N!|dw=eIC4=3Om zTH%Htpq}KJh{X7xPFH`Rv(dY-2cRD`eCi*r`7wrj>~T)=7z%%-)BBn}@9cyZPVB{* zcUHgg4ZDg|ty@_bZ*`j9>g*Jb_H-;x#`MZ14|EP%b)~69HcgUHWhF zcz6-P_K_A0dI*Z4!Sgvmc)~Qbc<)!$;yA+nQP`)SbSghmLn1iVl(CJIb2m4#b*uXU zLe3$nn!e~Hgz3+gJyf~qG=FB(zO>pWeLJ=DB5QAW>@=+Sh3`cZXYK~GrUxsx zho25zI!O&`SP9aSek)Z)UbYr&mJO_gmrHaNmjS;JG&Cm|@j@U+H* z{skt9TNq!-vC1gfACkyapG%RS%1IQJTRvmLHR^aS%&Nw`^_#;mZ=ET{Zrrb+b)5RLH#Ig)_ zK5QrHv>EZbfk*L83-48RPkW}?(3NJILMW?OE~po1pkdm>+EWAfTMj=wT5IO2S!vVC z)fQYQ9~OUhz#rsMoMz^1RAv!|GRq%r>*SBs9)EbVG><>p*2f>_&{Q)|+w;eK2E*`& z=IJ&swPO%7QQ;8rs^t(fUhC%%F^A!b$~BRuRx!p`hFL6g2tU`yAF*TMcVkCg+m5Kw z$ByV5H%E?Hd-RuTxOE=v-rhXk(GI$d9~$&0y+N1R9DKE7_Jv+b4IHzS!E8MwXdCfx z>Hm}QJ95EKY5cml_no-b`%Y90@KgfF*gjKsYv*| zYdd&0>*d<`?4*i51fvbm#m?0{k0yI4AgDx<61UwA#__xSgtdkgJNQ9X@@dvX6AX~p zA4rZQ&LMVdXt6n_Me|A8x*auokk0?&gT-xf4g2)wfM}+=wmSTYr6lsKwg@B!jsGqt~Fv`K-w;9b&G* zg{Zd2fV(y+?;V@@E4{ww9Zb#Id~R^;^JJuQo@BB2+UM-tt(B=>i!*~?8*U5L>(JP! ziEZ%xCBn}d$Cq?k23f7iTW^!>nPuhXB_KO_0W3aU(MeaV9_0f;B+DXua;y* zXJ?m2!=J_Ph|qJvc5P*g58I_$<9*n!GPn)h?7H6m^NK~UW1Tm2vuk}*Y_!Es-+q4c zaqtIzF&@h=<^#dy+-?s9%BYp?ulVLgF#_wjhv#qT5=8ANDRz2nZ*&h*-8Jak;_Ogt@vOvEoF<6G-bh3%n=rz2i!IOF zK5J-OI6rp2*|BU)?d=m6Oni>lN7&lGb@>NcuE8momDT%CpG=e(+8zFfSoIpNa|1TN7hI*0={!0M)a=Xrem5`ZT6{P_qz|S^B`z zhOSPe<;gbD^;6~$@SM39tI$Dw60vw zPrM!VI@0t`k%=fyj&G|;4P8@{7}S>dC^O5$2bi({u#(tzj040qR5glGVpuWyPx=ew znt=Y>@pv+)eV(@CDc#vbh{LRIzj^HjbP{90gLRMSo!Jrn#_=SgsQq{@txZj4JomKv zjTaYi^HDS+r_4mdAIINfBRzxmsRnJedocyFg9i86K?{icRxkI)Yb$@ewu9!iiMg2v zvXj9Oez{M0jpxSGFFPMZzqS@jKTQU$P$^}DF!W;&+d5~3)>u0$)~`31d12;*H#huw zk*ax#`L#@%VyutPuhHZ$L@`ilwOfMeS-;N6cBK6xz9?@#?5zUHA|kxKIl+9e+IBv9 zC116tZ*D&LV3SYZh3)B^FPh{qCyz%ZCMcG4iWd0Pz6C@zhc0=P3#X+;@D_Q@7c8t5 zB|cZMJOoUN3zIAev$3V}9u_-I>CVidXL=IJ8me!Gk#czD%M(W)L6eauC=y?3 zjBsXY9l&iYc9;bi>u3TqMXG2HgDn8eA8c=Zc#Iwv9Fm%h!LDgVXOoWI$iKj70f-3R z8WEP}C>_M=%pZlob00%sBQx$`c8>^ z{1^9arYUIU$n&q$pj^C5NY-FQivE2BAa3w}?RXbIzVA&;r>5`)wy+(a_T{TN&uaC< zUC#)$ zLfMHQ;v{#{gTZ>BAn>PnKN4OT?;Qz06JHWhK#LBJIEE;!quuy3?i0i~AeJ`s9>QIr z936A~c|sge{2t1)Ne%L`uwe>TM4KEU*lS+vZpJ&eDD_IBCUqbU|c=4pSV zv_xa3#NaQ-d?b&6Uoe-3hnG#kZhZt)SP=gx5^jub6?V#|ZJ~00oDnaY^=1Rw^VyJG zdmcNqU3;`%M-s*ZATNTGI=5JXnNZO>a*l~6H_7arTcCtOHgOBXg;`JmrAL-w0-i{G z``}XcBXB?N4ym6PNi2!)#)I)yqA3AGy%q$>3jZ5^t4*F&4n{1A?FG4b#a)cTQA>Q4 zQV#&2;n@=!HTGS5EzUe3`8xc5Yy!!1wSyuO-lRJ8`<5pv;2HO0ZJt+Xb8~FZb*PUm zRi%_Le7foPMvUJDns}c7=BwyWef)MpcltKt_lqaK z%lP#raN+-E{LK8pbQNXh7~p5}V7@A;mH1$COeeRCCNi4nOkl9hYyydG>+~N{Hu1v= z)65Jq`$XdJMG~(^`k#nqKeZxMzW{#g)ff%G72h(W!!a!0YTW==y0F#GgtIL}3v~Cs z9@??&EyKR1L{C!oqha)|p%wAxB9%m<;T7=1AY~Z~=odPVh}2CC}dapLon7yF=4= z@K#o0JAp~dGB3p`@)-Zh3_EY8=Lcj^wFN zscK#F)J4D9KzS;8zFF}%*ViRe9l_U5pV?kMLUNRy3ma#0Vu`zyI7Cx;PYRp)(!RXb z=V)qTu_smLR%TLE8Ft*OHt|UaEh&9P^5BMWQLe&+SF|XGWkN)OrDuKx3|w$`Rl65YKS~llW1#bykKs|kE6Es zup-_G*u#8#Ai=~7;#0D=z=DUMUXoowSY%}pi)jxnq0I8LcS;_Bs@On11(Cv+V@1^o z!U-fEJTJ2!WO&Z~cT%s*>{n#1TsKNkTDO&Jx+=r+Z0vrrbFnj3*`FZQ!>)_`pH?c4m@wr@etb+m8ZZKiz{Yw1__NUQFMe(zG%y4rUpI@5aet98?_ z_d46RF1#vPSNn#pr+xoLT3lcIj=>@%`(3u7tf9EO!7dW|$(X@kHRYw4DMIzn!|>7M zUXsz>%0{!JC7m^n}x8msCtcdU#izKWj$TuC-4u&?|)TA6WXkgWiS!H+Sg z0vRDsmoWO%3@!ZACx;S?Xxghed5Q5o5`7^v*Xno5oyMAt99E+hZY=(euh?IoKpy$Z zJxSUTk^b0O#+A{ZXmU68#q?je7gldxPLI}<52Lq)>i?qNQzeRfyv#ib<3@F2PIc3J z-Jj^m6Zb?`O@lhkSdUflT50V(oy5~v~%svs?gx+kanQ0vLazkbK{WE)$-_r9LAi;o-Z z%WFCN%MSfS$&30Kd@x3;YY#SeJm*J3SI8_g^b0%95rI*@r$gGc>;W83ZSDu`JCQrR z+N8so`VaJK{JB@7QH-gP^-#irF&q)%!(?RSi^{cs`L1%iU-(f;X9;tH*1s$4t=o00 zZeXu{1zO2&$MK8jLtE1No^SqM<}O6eV2*9d>?t|E*=7gd`ahCSJbS$?R_riDNbrFG zhl)-%o=+c*X;wKornnh`f^7c+IDjA*zyZ0XjKt8I#Q_xi*K0#VS74@edw_N{#ponC z9H5E-4p1(VcuzQBQU$fy)`J6NA@Ok_p_6vn+YGBn#QOy;o<6y&#etbBLUnm29T_>Y z`jo+e@YvE=Ps9Sg>K=y@CDB(HVER&NF<=S;`WI0`u|h*%Gza_jLYi2ap2XbBE$>-+ zMiT$ahJL!2o`qhPc)8aCx$Gwa2+>rWW1K`tYge!)jGp)KWoyFd`%NYcS@sQ5EUvUj z5rI+6?lI!-j7ekngxF#Tu#i~fVMKcs5Pqu-e-f&fzes!ZjHH*G=1SC~r}S5ybtnDV z3>nq8fuvdV4qd5al#XG9>IVu#mmk1oliR%-ldQ6|8-BL@MV6SHp`HEU;@AcZfG@?S z(cx;dh=l4dgC3R=d)=L-#6GA-W$UK~Y~q$n8%fn7e!f{9nuS|;sk_@{J^>I*1Gwm$ zbnJS@vv!M#hK1E1t1pL?)t{+8CdZTa0hhSw0)29f;GTft2zIVS3}!2rCkcnHR7jI2 z`g*;)e0Odk?HU5jO>e7e(W`d;2aN<=%KM{IJz;R6**%bjPd8it74)rHdK!Ou87&OR z$G&f^3&bQFEf2FY^6MyEdH!M+XwP4~T>j!ctfvUCDXF?}89Vrk`2__==$Zv*1WRN~ zY*@g5ysM|@CgnMh7eO8ac@M@@{5+QE*=0m8$S4?}@1%y6*|^Z<@+VhW06gHA>fkyY z>~>rN{^aG*D!q>g=DT>h2K>pJq!qT3o6p3drcf9VNjMj8OWEDV|7PMOB6q@*DkhJa zc1|>jwIw+Y1?N*RGJI&+#IED3`%kTyGC-lS(&8FEjjzCb6W=~FeCEVWs{2o>n6@=k ztK~&*$3hY6obWD}NJ*sgP(UuMaeis$F8s@0l8;L<2%7te+1x70WK@dzCi@{YG4|i1 z)jnLgJMsR+&1#ZEi)+GzDkhUU}^yg<4OUe2`ol>AHqe)07we6j80EAC>k`o7~U9E??Y@f8PZ#a-9%dv^HmDZauu zp5?#ZOUR1<+A=x=px|EP!#3kWUX%AFN2VV+CphQ8bNm^SmBDZAt$yYqNmPP%CpE3i zTQrYplWQYN!Wnnx877%;{p*y{I3`|n|5Wr9-H+qSz$QM|-$@ZoapDo2wqxc5BfloQ zI*CmpMA;^K%csqJd(KG?EoG5|NmhScn<`ouAz=wSI5=P(vrhsecD$rk3HA;mTa8II z)iCdnM4#s(i5KEcx%n`qz->8zK{X2|G4E6sMH%MAmk18ES~BvKVpGC715eJ2{oF}z z6~W$wO)8pT8V@OzMVuwn>=>vXZLEjztL#&m$HnhQ5l6PIT({(u;XND}-S8`_;j0ze zfH|*xq0?DzX*!%J$=qq^O(U}ySo$|LFJ9q3VPFCLvt|)@%}ugrN>Il<#?JcI-3hVy z8QA82(iga#sp545`|V-0HIiiPolBBIsFU(8JVxM(NsZ^4^GU$ezucam7vsg;;+?fG zKCbzqA^*y==puak7;EDfWL=ZZQ1K`ipkGFkXBR6vOc|6@xZhD^DisXh<|JN-7JepS zjDYUsp8L@Qg{UO9^0K^c7s0daSr+#U@zl8FKdZ%9XwC!Bn0R)@Xks(puIPkU#@~sg zM)4sxYVC@P90I)~shXCYT`|ItrVeMddNY2U6V7lFMcnlxyM89Y(*0K-&CH_m+QP4E z6H{pY5K>OZ+Xtf<{`Bzp&`8T%nN!nW8<(k#Lz%Uk8G-R7vEc@xu`6!bFmGBisua`A z0Y)&IAl3BG6&R!OjLNiVPEzp^-8k)URt{?RJfv@u_3*s5)YLVJ3)&JNX70`Da~cRg z9);{Ujb*+W*6~j|!eL^NLrT{sp zNZ__-?=smZ%!cbsj^`ZQpT_pPBGfQdpQa|oo~$6~uHAM6(?3uwni@c+?zy2W4pRBV z$KJZ~3z@ZKO(u-Zjhl9SKs(fg+VGd5`cg_0kQYsSV#c%KeVVSsXXHjpk(-@qF` z)h}JB(#J|-Nh~x;(%e40Vyx=vLEP5v`tB_KjEB3UoHyZ2>~vT`c3KSt9O3?+?quF| zFS>@usS`|b_XCut2sYV0jSq7vVHvjU>85PbF}Y>NwI!ZPU&L43b3w^KTA6e|-8_z) zGQ}^rTEENO-(tws^=$u|Z)79YQa!=h3h#{@y%M8%!(U%K{jpvA9*Sf>UgpJnIXCmg zU;y8b6YsT`;rs0V1u|0x^Pp(bz3F>hfUDK+?|!aj$%{x@N5B_6YUA_PiuZajE36u5 zTfUBXFC>XiBt;-aTZj9||;zu<%pn;Quoh9dY8Yq$1mI;oS2tz5+$;gb;4UyHr1!9N?dgIANa1=io5c{B%2 z23M?^FrdwrxMvuv#R6}$knreil-W9(XjL7f!db3Akp*0Gm!bqlmKT4MXTF-H$av8TKEytnXZ+Z6lFvBnG=6AB_v|0i@z-bnz>>lcu5JGa^IpLI zAr;lLe{|6-J{7f5YI5RBl;WtoijPY zWV&%Nov}3vhcl9so589fO-2L8b*RDY^F$0phOtKVs3}Vlq37MlP2u>?k;?ZYo|mtb zKj`=L(B)d*YUD2rT{eq9nO5>}b~qANNW_gM&%tZ? zzU=nyJ(v2V3pJ<-%6nv~61qZhXTk@Q-FCJ6$&uopyof}LpX5KTD2TnPoOQB-;9GV0 z0*R^+v)Q`(CjEZd9cDfhFO5{b7nvb1;k0T0;1525VX`K%91q2{vL3#cz8oRK%5Qd5 zAcqDd5$7dJ)LmrA@hT)~Qt{D}IkJ224W7YP&q-Cmz*hZe8K01DYP=6xR?6JP(xnUp z$NEN7W3Xc#@J-gV74AY|Ld)O^s)HhLnn;sYclsHs%9!m?L>pypi~ZWfMXBRh-0qHv zYBD+2&0!3(o`^sYolyo@yUKDY2yd_8Ee3Bl{fejcwm<5C{B*SfgHP-#+2IVy6UxS9 zRBmXW_y{AW8Q|v|>;UsLzI$!u2ZV{ufMQ}fZO`C>n&5n$$X%0ICC=BBK`89c5Av9s zQt}Jha`oQGJw5l;MYDU`<@V+nNNJS^ssD-9*y=xakN@OLT3uU$@sCgvKTSev3d;Sw z_%4}ay!JV_o z1@A->TOd_0j6Z4R81(wqz0@$XjlIA)C77>?g_#@Fljh%p!K|mmh*Y?z_pm)#%F3ed zUGry@BoCjm@qbx+HR)8N$?{bSpq&&+?##(R&jMi4jaIhjX<4==|jBL0K3#M-7?oqF?ni-$PXd`ar zn-{8(@7u*;dUVwK?Zqp8b9>7=Y%lqPzeRf|)P1Y=O0*+{ve&%YL{qf$p{Qa{P1s)c z!c9H^4_kL`g+3cHm#*SZUZTOk|@f*STi3fAzcMxR=AMwV|j2r5(ji`OvJ^Nx&A>L#M z&Gl!giRQ5LwEegR;i`tUpYhAaviunSrbjTyZKV8lnSJF)lD}4>W_%a<>wA_jlG8=6 z4U{iVG=+aC`C|V5qRe{ai)GWy*mnQX_->>hj)BfF^v$g>_WCfzY zR)4HD)3bjEOyB)FG<~;Qn`9x7-8}bR{Hb->z}5JUZQy@n@wNJg?BH8?!bb_Kv$2Ce zum{|M;PG?TNG;c^v1!Wcy=GUWl0SP7xAq=B%|f38*^TvAoHf>tmxR-tiBGBYaeiL9 zKiUcAMp55WI&t!922CwYe@4UUV>NHlYD%)#!i`|jGPcrNK3%4aj^Ak zX!}OiuTh&UM!fOmo_xQ?Ep}WZi9R~wkc9_xpSyY&(Zi*V4*eM=xxx9~{26L+$75;z z88j{}y~O=5E2QMF!6=PpFjwwo2lH3v!7_Ir9t52lJ8tGXHOlCg`-qB@|CqZ72^~5$ z+=G3m#+F{4b7$rm`Z6zO`Ky{O9nwE>URim`=$^Q?(LJX_+nVI=HT_R7n{pr)J2cW& z1UAPI-B-IuR<^CF=|6_QXHOk3Y2!kxnW2ijsMX&t{moO)VfvRj;g4c*y|sh|!Fy}U zfSdv|+X>YK-^%f;)u#x!KBlZ1|4DdI+2nn#9!AW0tNWEi@Z8sAZtQv0>6v&_obQ7Dwe{A_GeLkh4-wPa=>$9)_7X|d6A0~?@!n)cJfchn5{f$gX3 z)CYbb`FEmOdB2HwufFe;bv>u6LTh3dZvF`s$+Jb#gXm${ennSg$cezsBmoJp)`{~!2sn!5c+c=V&{w~NP{8NM<8 zh1={aKazgCnFJbiqHh~dY2}yi&3=C8d7{?_>bFx(;U7xBU4>e*Uj25>I5W20e>DAe zSC+SR>$l@fb2do7z14)~d|Uf@SKIF&MZf(f`}tp_W*NC~Bkbqb?9NMT+0Pri7XXQ18e}|CA=1B^Gj)h3+}4jLoPaR~@94h76B0G0f+d*; zB;72$fNm>Khm8|#`MfuAg3=$K{TX~Xc54x3V96J~*P&8(b+7K}tJIIMII2$*Faif+ zXN*d1?AJu}aqI_qlbb#(%7%r0sc2BiuOD|zwJt=yVHRt6OwwC86W=L)Gk?hsz*&PF zv`V@Bwl{GS@NtZzYr4=Hv|3p?3T}4(@qLy$5D%r>W({HyfKT-Pq(P)J~d3*C4oqrViebauRe1GT`>`RnCG_W6N-V5K}A6kKo zo%Nf2>-|6vbP}c3=|8LZM*mqmrzmplH|+;f!`J6O3+@LhMh!Ktv%5hQiIIEDw}Kei zdbS>{a90;1WB%TIxS98GHqxv1GjH7ZoOQ@r;}d@V+mDaVCjai^vpxM=&-j%60OO;E zZ|L}pJws>v|F-Mxa;Kor(sV(KRczStxm8 zMI?Dn83uK@%^WSW(!CG8u)Z<=N<^DtiPC!oCHS~rjkV#4Y>xXV7M5|nJGzf{fXN6G zNlv7aX$1C~4;iOL+C7_EdM&7LM6JV-Iy({?vJiDWKk?;s+KB#3j+&)xG~!eQ(*I#g%Ncu0^1Yf|@@TMCdBu;P4)H`O&6C^v> z2{%nVms4cCVyoSg&oyPzN(+$n&ztaFlLVvpm#YnE?8C3V2H?qK?&X;?`#4VEO$N)1 z5?i1dxCs^RK2#f;)n+ooxuZ{}$ygs=_7;I9U#wo^P6B=eORL7{cbR*e-th3^2g8Ry zuxNb~KCD5*SU*10Qp^86KD4mTc7zWH)Bd&b;ZLUYx5J0g_Dk*Y;Tna^@D}!WN z)SS+h>UQu9otsIXtkx*fO_{sRa8Ydz+}@8};N|^%04Fp%nxx(gDFKj^90U*TUY?u2 zcPlF|S0|oV_ZC(kReOr-M=@afAHt4Z(!G4b=~l;PEEhVHd^NM)-W0*9sse5EC_w(x`6!gsv* zzHs{LA|pH<_(#0Wp*z01sa zoLl_FZTdsfpMt!wc-NGdy7Tyu31XDY5#3+1Y^=P>Nj8)a?dbGx&_?M{{Y9O*AV33E zhyBPZpo9^r6Zj)xO6tU&D~vNF)bLk*CUsVMPn%7JCs#>3N%dWJ!4?H33`5It<1%ru z$*|Vy{sA!KP_<~P%R{3%(zL5-=u#tZj#O*9b$YWmo#*711npkwHcR4wyj9vb^K&^m z+;N|%z8b!oSZZ#Zq#HBlsP}>4H+1%bL#{teMCLQA-A?;vD^$ag7*yxZUY!WF_o$xg znm?loS?YHHPEd6Q7gnHkmpMNId_sC6MFy?x6qK8;qgt?ta|Rk*v2Bh8naL&)wN9 z(R0~f9SIL*TkAjBKjb9q%NuEA)aJlqu3ivgYzz0(3|!-eKUE!&=8)9Lf%HV}sfsdn zoJja(C-wLU>YcE&?@zJ&K598(gvnFbL=kiwyYXYzC`y_*s@L38m(o&bRlk@I+XyF{ zj}MWVLzKpr)qPHrL$ofE+>V^T9C9-s`jVF~bj4?1apXkm(emlM+H0}JV`O3Na1mnSB#%CCUL-aTtsdBZ`v<4+_fSg|i>1}9p4j*CkGp-~tLUO;~@RQz) z8ZAzlnU;F2*pOtY`}PN`$xFjDOxLra&OHr(8t1%xsl#8=hiQz+6%JD``4FD1G({%+>^GS}qW)@H`M$<~>tnY(Q?mpgYJd`4A= zn$LI@c`Wss*M#1=XIcJxoM)LAa=n+nx?cR!WNMFJo1PlLue;Vjmv4<7dUtol8(2e!t*AiAa z55ETOovko{Unh8Vf?wl^DDD8fK9_co1+VwG+Boo<4M%Uf!Efp zmO5GHnc>~Yg4Z~1_~3Ont#VJouE(O51+RP74PG@B7Q80Ik>3bj-E$o4?OXds{JP~; zTK|LM*Z2qo?Fhdr2Yg5Tx(&T?-S}0~9=~q?t--H5_*pl8-H!kqz^_}6pz%I_MRWMI z%lnWG{Q86@2y23~V}^Ow>b}aej_~Vb@7;%T?*@d0!9304*CtO|{JO#v&Bw1Dy=uni zo@H6^>-RPiza#^+$FImq0sPwHo$rEQA7F;)7{9jt3PPs(o-{6iUsVe=qdffD1{AgU z6&~3keqFpM55EQ@kha6GRTczD8!di4XNufKpFXrJ_-LF(WPo(X+LiGjktGjNj7r#bVYitaD&1ScnS789ZUVqotDf}u1zj{g` z$x|LLl;tLiUuSXkqu^I_54C)K__dpuDkp#ao|Q@c%Q8=)*R?Eut)fI8el26rHW0t& z>}v7rOGy4h;8*#4TK|LM*GC6K(2nryc8rMMNq?+Bx!VZ*s+?i)Yaf2rjbHzJGY`M^ zl+ zvscYWN2>|uS(XK-s*>-DU-OO%;MWNxy7~6{<8x@`9pl$kGQD8`Iz512jn8n;$FDzt zqMrS0c!&7a>G?eTYL>+|AHT*irg`{vl5VUQzph6&@bIhC4%rF=__ecFr|_$yL;QMJ zW`Zn!-Nn_9f?u7b?yeWVP8L(;@N2~V1nmgF())c!{2GgLw-NYt#$;>%;%7bh#o8axA5Sx$7tj6` z&>xq`Y$*Ge^vibmRW0+g>|Z?V2)}kS&#`~y-VNYaXP##9Ywj$IUx%8a`S|sk*M#1= zXIU0}oM#(_Ume=N4iDlNUW{*#UmwuMj`8aykWKclUj^{1;3@9;`1K+v>e;`BbckPr zp3cLs&c~{Jp8R#s64e)wzi!Zt_2So(12wKj{u-p+HMYV4ex2aexgPtM^!qG+y~ov$ zf?tEB?yeWVZW2@F@N4VWEp@WYGsC-)mA}SuBM-k$l0j_4@T;bqXa9mDe+c}#WiGA% zLGf$+0T8q!{Hm<{j`(#O%H2lb*X>}!H-KM*d78zqP42b$b%iOKk6$}_)r`+Q%d+6tST(;henp}I z{5ngx{;lozAK=637{9iau?71VzQwHnv8q`!%C~=kqMrS$xwi%Ey0;eu?FhflDF2T5 z6wSx4|X;q#IMM0v<5Wl+X#(MEdF4jMo34`1O(EXF9^K+q-{9{Hj2?+X(!sJjdF< z_*pl8l_QS^UNA@SIPQ<{p-j8 zel8uTGEV;a9UFAM){Q-1Dk0Ab*{t8|%fd>(LE-`C+{nYP z?lOpN7=9IX_3U48Sdv!U!?(l6WLSGCN~vVZZcBmCOUJjec(dpCezoq3wYuemo{{5sSW z&Bw3Tye9O{Jk7ql z7h}N=FPYX_-7>^PP7?6z*kDhSH%t+#WlpNwoSy+IpKVf5@Hla-1tQ6K&Foa)T`+v; za+|JD$R0;D*WHc~M%{c)R{LCqijY1Nh~trs?E9CVgBit{w=*kEoL+7dk~zbK6L-k< z4Og9{2+SS*tf18CC5%ij?ySui(ofC-^2?lrI4 zY#9R#nelEzQQMk2cB3U;j_p#{Rv4?$78`TaaDHO)g6S6yE?_fF{LRb~(|Czn5UA4#%bL$4=T!YMzg+L9sZ}DPrX%#p>{rPL~S@$J|e!14ikN= zP*;MWW1~6yH+)}j;!02T4r12fuXq2ecfskWJMI&oNZ9VDTle2dO&usZl55`Hq& zFq|9d0{*eb#AX=(-0;k-9!bsTQZu2}j6xaS`>+dT91nM$VP9=NlaL&v8NYFWL8uLr(wp0{Ke#Kf}W)4Q(qTtl*s>{`sSu<=i&eEUC=VDMAUY?bUgg_)OE|SD*bS&z!S^0EyKp>@0MZX z^uwfJLkj1J51V8zTP~fcU;cAiE)~q^KhCu**7+8Yz9uV)msvT#;}IRU4rJhO+%2gP|a z+3^W`-G5lcv_C}?1IoSKJMpWXWKp>jriGz;8_(icwm8;RN^3e= zVm`l!&-RJ?Up^ z1^a`x=%xN4^sZ(G66p_{B!P3c1a%<;6c%q!$`e8&qm5j zOakxC{NaA)9u}0hsEQfL!Kr(gNPmuWEJ@5~O}k0^PYyQ6IgUZy*GZ0;u71cR6~*Y_a(3 z7n`#bavsebeQ8QrZSq{6y+4WlzaK>tZ?I(n4009eN$CHD#hfT+bv*UsjY-+<_gC`5!ZM&N#n#{f*M%fu} zPfD8B;+>K-mCx!yX{70^B1SB9MUD1TrRvM=D@+B4U20%Yjl@-U`RK1I6)?N7 zxag;g<>mtl!s6l{?_xyyQU3DwwIq)M-UqqJoEPlI;GXr_=Cp{7C?mC}si@rj%WM`7 zn4+hdEQv==1EPsr$_18A;;Ql+&2N3Vpi#5Nu+XGlpSmB)#>Om3cvS11eo; z9vWZjlLSfx z45iKs9LgChpX9XEmrv(K{pYX%aVbF7e@@doMNa3lv_VQlJ7oy97ge$8rnA$zFq)iH zQp*8U{-imh%}$z|FyV7A)Ub&7a@djsYIB8Zyh4*H6m3rxzI>zkE??$vf6+)Up(1a- z)P`4tF0T}7T)7SZYKxR1C;&MrRDTZLG_5rK3pRBOO$Ds{JyegaR$JG&pEPQe@`v&! zp5+bYd{f99N+(fYUMglx4ZIL3!AW)bD?ik$F*Q6Cs%dlR*>ZZ~HW;Ht6sCd|9GNdh zXlSd%2x2Rd;6Z*>tE(4cOr$6!#)xQS$`c_kTVa?V*}gXXKM+WRZW0l2wCzY1Mw?bP zblGx>RX;&31@W$wtPb74p}-dip!dI{cR{G(WT?YQ@EDHjUtu?u0OZOQ`U932C6+)Q zyG-*Wwz*Tspu;BS!E{4m+Rk&*_its0yop|59nZ3ZlN`khXEGz+4_)@8X))ZVG!(VT z)5Ij9%dRza>vA@ZKgic#KMgFIw-|y(Q@0rUMH6?eO~-)>?nv25+I~OaT2i9KAoeiAz_OniS(BNitcfr2+czcckrlJW3L5~)D)5K zyAO^daCK&drs?fS$E|TS&dpD8v9Dt-5Mo@>#20~2=osNDVEdGF2B z{k^^WMwU+h8}6}qD2kCB_Ubcd6^$25)es%^vkL2NPsqt$P=e1=J>IcsKhpCtoZx4T*j;*2MUWpGI z=7p{t!|hUr6g9Z*Sq=^qcrTGtg#l9M8fogP~v{TJI0w^JjUKI3@udGX=3g>y&+g6c7tiFFF{3di0g zYm0lmZ_|dTP;5IVwePd4g_Iu3-2b<)rLr_e3W2-9I=r_U+2O%uD32E==3 zg*$_YYUKd=z59ysjhkLS(?=w4b^Abi$(aFtlRkXR-fT^|PluHhhUyD6nUmXi%Xg^Z zGM+?||5?P3HdB{Sk5l*V*RCU*kIBX34#cdE$+oK3VkgD%z2rJQWk^3V>AV(A?b}RZ z)!457K3k)%3s02HR9ZZlP2*`z%@Xk(h;q{{LX>y(wHb5NDvK!en)w__rgH5-;)Q2u z%o|@joYt4PynMReN=6X0SDZ;R zBl@Q9DxYo&cB^FldWchBe3KpdTQmbxefw#BgQjC7$|LHJ&<6Qa6sXG0ouEj1mYG*A z?&JFy>Kl2(E#!%TB^m27%bB-Z(qp~|APhCb%Dgq_T7Rk6L2)(2{Vfp%>6QLOHRQ5S z%vAkymOi`89m$t6mj@H%&YEe)J1g&NC%&<~b!ogFhL;MSJh#*^eV853T|@OBnep$h z!Ewt~FC)|{0}_h241guvt3@3wmH=6Q3#Dt5k1eN-wU$Y0!>dE}Pn$}1d5I|#Ngd4& z{b+f2bH;f+1vMIOl%40vqE2Si!^=Vq7iitAd$KeVZjCRGBp);5Y(99yf5ct?5idki zkKM+P`wStmeD#m~%~!Q3o39>hzj|W3uPVRQTHn)&@qCX2zxI2o#CGuK=6msREOBGp zH~*n8P2ohoxMRNYmdYh}`5aUW_RN!e*Z$5{`QMr1*pEDYzdD6wE;Xgp-47ogA3+p| z+m2jfKXSGG2vft7FRQ<-)t~sOKJDJl9ld@!-;mkkM19NO)2}t`G3^?wn^O^3tl^&Y z&af9^U-}d8_Xy@F*O`Co<~Z?Q-N2J+63jXgeY*=i^BHy%mhLMr(43amZI&6tua_5! z*L8(Hnm&%lJ`U6kEX`H4gx=;=^o-&2Kt-45Rixej9=+=Z&c89+pntTlM;*#*P)%Mv zUuD;4I(C^~Pi#e+Y7O$7N;LTQt|AI*1m3zn>F(rS$g6Kr^iGml03UOl2qbu z8Go9-Mqim&WsEG!OVC*o>!p%LC;XBeQ6ELapTzcyCimRs25j9xTF+?WW2>Jh$?QFe z!*o}K8akVaYV5D^6}5>tgIh!0$+0~_kur%F7!5-8MkY+1Kpo1AK~@Qt&K&gEA7sP~HS_VkCDQ+-nyI!$}D;k1azkbu0cU?p_n=jN5@US)a*q zMoUcA0M?OX|EhIlAI-i*Yjxe6!U!~TPf?f$r;lUa2sNB9eodaB#t(*K$B!^s*YxlN zj&QEm_WRmX-j?sib|RXZR2*q~yR%-l{vT1Y2QL^wj@qViwrkg5cP6aNb_dx8iQ2vC zKHD8W$|Y-t*PUbUQg>GP-PxyIcYX_6#}6=og*@Yg!Qc1{=CBi-!<8f^YjxLb!$S6J zxDbk))6d}UJ9yo!F`;^8#ql|ub!OU~N?G3HMXWA(YzEHo3&zF<3WctGfcjLh69vxXe`O)GYraVHyL8&VWEXP^7?!PwMwf)PueOqk3CtS!ljJ=;wIoqs-| z56Li?0$;`UiYEK+cpa;wh21Y$Kaht~gW&&F@$)?2Lp)O}-w-FcmXS211oskhPLC{K zv_?7)AT`j0GKQ?!oh-MW)@OzWcMigK9KYe5ih#}C%Z2ClPb0a)?YlMfxgJVq{$hr2 zTuH2lZ};0y8pAkoun-qnG0I#yRly)qRntd{cH`SpQ`aOeY)gEUc_9y9I8Nc*Vu6e? z`X#%ZdM&;6#aFBzEZF*|y*)f3Q>2M# z2oR)|xV;TJV5r2+RqesVbR*-jA~l@anQ}(BOirJ#cXZQ82{Y!Xj=<#ca83r}+l{RD(4BYK|Dc;p zv`%P8wx?6eM}+F{ z@J4imz!;@$_iH4@@}_5}obJ7COp`{Y<4M2tf4MEW9x=8bHloK_7SOP)mhYP#-D~!e zbx9}zDkuAtCovT!uqCY~9Z)oM*h*?DlMCbPVq;M}D85;=|Ea7L-3uo7c9KftBX@?o z%sdWV*1|Z%H@8Kue3%RI0G7Cl&=q&-O6I~i+8|o>ur~KtJn(!_VjR~XJnK?z>et9w zD_L+^yr2hU2-V-lWi)waMQ#{nLDG0#+MtnVS*cP#oopvX6Ls=3e%*iLb#@ZCD+WW- zvzd6Tv2?5gS}we*H=J;q8%_4iRc;tzjsQQ^_tv*8BP?O9N-K>?7LUab(d0uC$fL>I zMfYgpi{R{ex`?JR=A}F`e=x3Utd{xYs7YiD8cW8bF_AFYqcEn1>Nhogfn95rxQszj z*o9}EE-H@?Opjv>{qO6L%7`K6ifUeOb2sk<&>HD}X#}OUI5s>|HwOdZSE2fT5(yYB zFTtLB;{)0)8GqE9UEr>*;;BM2zs&1y5AAYEG}FBJtlCO+&L=q|oc}ki!H&LW>fRpi z(~dTi)62}zOH_jzVgBD*7+>!77l4i?Z!}a&-X@wk31eB*wBj^yjvT+tyL%%KIfx{= z-*2yGY!JyH!R4N@{H=ifBC#l1iPnVhAuT%G8fy4h1h)s6#Ft}VRLZm!?vb}?fjB`# zpD@lzT{Olm{EOs{3D~&@kK<#E+kMmdaa!ucF8VM1@aMj~?ITcXN^xRHfqQF#A(8s% zZb}-WNEm6RIsR(;Rl^%qK4QreR$L9!xf6H;&I92Y4;Woz^}M!rFfS00n&Z!^b+Dfg zCKMxyRz?K(5M>dT*{MIb@;~IZCJ0+oH`P9bk(q-=t9evYzRIb~6vki45*}o~aS@%0 zCU0BL50uuG2tUda-n;8^m-M^I{kGDi&}ta<46M<_TQkYqW$C?1mfnvDnChC*UzY^v z{np>J^uF&weJJ(FZTz^KzpMLlGqlv{zW(FS`SvfGm2A|VMDi(q(uaPgsaBI+0dn-* z1N)mLW{G<#CITzlHj|f6a;=ERBowEbWemc>snp}~X_nVtmz9YLB2F~~V^KCUQ>hJ; zV;t<%BbmSm06@mAX3^ z50O&x4z3VY_^mR(i9=wYL;9uJsFK4Ue@P2D;pWh#muM`oWy?Q~tzMYS??%ISykO7e|Z2G^jWfCI;jMHXPJ(u6+Qamd1>{oZ!@-}`#| z?DxP|7UAso=KSs(z86hC_(xg;cM2WSuQT(EobaHxwr*zn_jl1SweRtC5M`v*P31nw zu$+bCf&T4G|3+rN*HTr|uA58|y2+_frkj^7=dqK#&CCWm+cSMifWBF5v}@Hrzg+Fj zVl7qfmfAv-Xiht@si&8x`d+Zat`+}g2Bd#&7`Tc?_dVI%U*rBs_v=^N{`vUri8i&= zFIG(N?L9XOK)NoALlOqc(xs>t_IpM+NH^heMp%A)W>(j^7_2v};oHvIzsWhE=C*4i{@w$OW`{iTP^1iXFr~bV1BxSdf`ommA zUOBb=T#30X?4vM{8FCK>&W+Xc&MT#@DrdDYB=eeH0da0IQ187}8XJxr=f80QZxAm5 z!slsF=?f*Z)eU@z$B-MN;=V+T+3rt!K}VEU(X0&F(6yEr``W>O)9|&r+mn|%sBS$+ zHRH3@RAj3OT{((xsH#u!)u#{92dQlYwZ-qv{3lq&0`~|sAKk%CF|I8!KRr>B1f3(! zFt2kJd7ZoNijF%cj}WbToyWFwJ+iH`ojXO*1EzCjG$+*1oyH-b88tZAu;=sRX>5X3 zC-Jf|yzH+X#ggSvQkJKV7P>Lj@%5_~KDCp_lb0eP#*QpT7N30Km-uu7BcnOpvKqClL)9l7c zeLQiIrUClG$_lqZaYf;mV&jwy#XA;#EWXqu0e#kyEg%7`Gj!r>w_rBI8N?9+4l4 zZZg?rmH++7_5<+6B0B)TFwK}!Ttfhd9fJ?^#-I+j8Rm_fr0%^@ z3ZJNOw=mF=vh@FtNGoqcPscM`V?XNGYcbMpPo5xAorOe>?(FV)14QZHpz^2~p?aAe zlzBW=#X13n7@8vzS$(D?*B&!l6%_Y4{nvlfjQM<9Y)yj@_f{FxSy$6%MncXHsw;K- z-lRd$CGY)=As&@jB09dIy3F>sh3Q*Tr6j8S#sl!U0{wa0)5rDNIc5MXLVFlgr z>yKbimUvpj3Y(eF_}ckJG^?@QKp2iI9G#tByS!pY_b6D~gtnSV^?|0?#kbJqy6mLN zvyT!i<4tkn0%58^6C^u#AgBSfveKW)O5g13Ee(sObxU7DgJ;IOM8Y3TK2@UrI24-* zKJlE%?*&pKe~DeNsJ8GuLkiB+MIU?a{2f^C#xK+|NNQ)O9lK=Jh-lc2ZG(P>&B;Q|BveAhz}C&F&;$*P z8z27cWlN)8`X;j0s~SUcHor@1S&gBYcq`oA=Ckof@Yun_)=Q4HLVwStd_9&XAAR!`e$ zJ@<0)wTWdJ?4zmyGmcr3@8VspAN5;${@TF#Ddwow8Sk}WT5^=!xd%Gm<>g9eY;<`i z^=SDha}gz^1{?nwjYshx9{bhv6ZN)Sipi6DGHH`#*I9Gka)qMFBTP~8^ z-bApZie~>m_WnG+>f-w2#}gKfir%=Ov2}?WKZfE0YAO+^iEQ^uf+(Q0h@iM&#fqA+ zD3Z{dNN%qeVzpL3F4bx)R;*f=s#RG6320T^Dryx9BJVdB3~B{j`95D~-gikL*!J`J z{C?j*zIi<0ec$t*IWu$S%sFSyoH>IIj1Q>Iz)-^v_m_tHgjEyx1%?{-AQ5+;M~I+> z_saEp)W25|d!i@@vyJ@! zwtAn7I1(j)KHBZ%-ikLYTM3$tf0-+o<}2Im%@KPb`(Rs=9Jjq*EZTX6rI&v{F90No zhWgYRyoAKiQ?!MxY>ijeG;(@tBtDL9#vv2ckzVpRs;ld+rb#8&AlW#=LG^M^@KT@` ztqzo}&|Yl$0qOf+lC1SYW^{grZxJ3n*Ik&-q0wRT6JK z)hoQ_;mLOl#&G7iUg0>mSQ#81V@tff^`&%!?yQw#_prB2cDH!-pNmI^8V=o$Zq{uT z4xE#BsBQ~m>N?qM94wtaX|rRYQ8e|Nu)m~(Gd7uR5RYL6&++X+$n({CY5 zfBuVR=3qTt5uafD3rHwn+z`OXMuy4>8T!+2Aw+-vN5E)=2qP=RuknAq9i95u2Dl8W zE$JPkU#9c{CNs;hDQ^nRJ!oGIcCDaXd<@Q+(YZts> zHJh(+tsSk_+E|*0Z>Zq}5}3*Bh$Y2Leq0avp*>O57|i6`vS#vletXYjLNn8V#uAde zrAWz|v%U0WZcpT?iR<3y7xhuG-*1ul7SRQK$q^n#J`rA46YJ?lhNOdLj+R|J(e+2J zncXtYEbOAX?k_6lnPNDbRo{VXX5zV`d%&1@rZTFr`l!Y()RV?;ySe$k@>%JXSG1MXkTZ!h+w z8;sRzB79s<03bS*;v%DJrZsoL}bh&pBVYot+Om9|-cms6Y!*B0eEe4^@g#kL0QM9R# zLdRr1q0M_7Rjn#7jI-Us7!3m*%c)xgwI|@?d zb_GI51a>h@G@yXpvnXI;n;t)hA!)}R|5B-mu8$sQJ)WtDdVGJ;M6nmv`j4t@Fp=@% zEoo7?#uh?y5Og%TxC+nLN3uSNx7 zY-L)s|NJ>#fOhJ$N({W;Q}SNhea(n_40mR@qFp6dy{H91tM}l|@bBqnQ!7*YkAw7^ zl)fmH&YYEW5rc6e(}~b<{5dD8OV{aEFeIWk{bMH!FW3_k7r4cIv=aMQq;#YFWnbo} z`LUIJvfRm)9;)Y(j2-TsAbnq@?-`^o@(%YW%ZipLd4}&=l6~?^zTbj{%WZBeViDq` zOPDi}g*l-)bB#096_trfDTSv;T~T51f}3bv(dGc&XnPSIk!`%+1B^O-OH87!+7O&l zUjqf^#Xx~^@a7j416SnQ%bo}<)x$hzDJrYIT#D1a-E9>NQ*l(!xgtyzfi>i%HKpl6 zMXnd~i^4%g!-I-OTSd2614MPb(3HN}Bdsa1C2@G-{*1N2HY!%W*CgjJ0c#~v%S+`tAby>re%;&aHBLR&1kPQLaP`y9HMB-~l0D2gw2 zAgVj)eeA!bha^g_YjITfcq7vUWYot=7gdj@H5qNI%TBN^?MPVHpMDGT`tz>`L~38b zp>;e{_}9E%gTm=@Im+8(W#p zDgA2hvwYEf*KkR{5`Bc~mWV5NNEKNc%zYxp3@rp=qFSkmuGj5rOf#Z~)3i1Ro!O=g z0kd4lZ*K%!@EV-)A`Qs=mLesKtu^WiuUy7c0>Zt|FS<>|`fZ|EYUqrBv&S#1oi9ne zv|rlYtzIU&zDaN^6vE%?;hI?+3||A!R5OS3+nfI|^&!o2M0@adWmIGJQH?Fslg5tb zsm8i@W*zU|Tv-WVgeokO(X8%R)4GaKW74#IxWm7uX`MDLOVc`?Ig-%_{s}XcApEN= z{5k;Q>j&dj9O-Kus%kf#{U}C7a?Go}j@4Nm;=(Xy3o=^0M_f(g8LC??_GO?riy!ch zM3__4F4Do!-^^7bG5;(ytOF{|M3#R{Axmbmp<-j7caPEfyg5e9mbA z8NDl)%GTf)U$SDT7SBLbanQ2r9YKPk61eEf2Dh= zcCr2s(l1l`_p|i06RoN`6KM2zkD$JCC*4^Rr=J7zP2dH z|3w4oks$qPs4K^x_DO2LmHKYCe5<_Il<#+Zk$xCSj2j=02WR>6)y+;CXl`(3IVyXk zxx0EVE9go5xTmf@F~|QCC@}j+Q12|@X&6?k#$KPM@zx{weu3({DX5Qj>>IQrqVx$t zx-GK(Wt-FOW%j|dHTw!R`!IsEHEAvoKT@VP%eY@DHPQ9GJs{dd{|EJOvo9<$$*fyJ zBc&yli6aEFFQ4DuL%*ko2tND31XQ9XiiAM0s3{N(SdPgBCZNYB?`Eh=6EMe3!1?g{ zXYS;8dQo#a!$q&ZCtU&bu3f0t%%bL`_wDl%$p|Lk5B5M^4_ zJSxDo^yg;dmuICcj z3K~3G4@ZOZ5K*GRUStpr-jk&SOqTdM=6;R%jqU?9s6^39nF_jv^)&kl67&fg4D<9t z1a%S();bz2R?MO{H24Cjqtmxa{z5h5*ijYSln{92UHe=nVFeAA*@i3o-!0z7)9lN* z-Q1V|Qo$4r_7Lp>?H?w$SOQqToikhA1B|!7#RjPsdZ8O72mi$l$60lt_gtxIiIT3Q z2}XaV9p}>*dmx2l;Z9rqv4Yo(%GBijsDLOS?D7_l~7O zSL90s`Iah;Sl|*^eSVe}Sbv}^&tUzN8%A){^EkL(IF8U_QPszL_&(bz>f;}nk_XZL z+pb8LuV5ga4$9lfuzBl)(%vgQg54bW76gNs$4~OxrR)+jXSn? z{XaA9o#cJPt~!J|$zMUT&Ch86aHjnGJCvXE5J@Rr-oH`6qWurdlvvJ~w#Cq#Uz4N~ zjXeF$8z{kQ72c%zD)00fF(|Kdtw^Y@sFqy9=Wt8iRO3=d2YIJj>f1_X)KBHvs)~)97p^oZ5@~zxPP+2o@yir>EjQfq2=*Wu6*S- z|3rojt3K6vdGkQ|aC^79)iHHsn$>+Ob-Ucr{@+|441Lw$=<+P0IXjsdggkE=byH`a z-&e`5Kbr%XGYsZO=v@8>G`LNdl22s!=V2_!Z9e;ZXZ3KBw_nghLAD`(6_K3X!^4!_ z&en!wN$;o!9Om8Ztty&n4H>J3=*%?DOs)>vx;kj#DJ$8u;s3s=b{)b1-h1E32!09_?g4>&`fcXJB#ST_TFw+GPV zAKI?9fYwQ0jlpkz=kS&vQ2+JT$9HDX$JfLY-58{DUlrtD5n%aR%l(jY6Hd?NcJYL? zC*OOME^;=zUHnXxr7Lk#BOHST718!{F+1=RfrPmQFK+!{dy_r#mt}rw&^v$nR+jn^ zwjZ#;X<-(mwY=%`aF>c#Iolp4hbpA1$O0wzq~zfNzl)z&R3`UU9kM{*Jg+Fs`3L%K zhaj2Ag+e8}iv$NNCK%1DvTl{hn-G@*RoMe4(Qml^nC&!G?SD>L={b0@n3qhb?kZ9i z6!XnH28*j41&)gE-=gNxP{~bu<_FILJ!8YER^C;y=JL=}-^yYe!M*rx3tP&3#xV1-_Xn24W5${uPl$mrV|y>;!6b9*%k21#c9T2Q#-tJv zv5{EC)ML)}0_!$;`=ox9*$)T|B)qbHc(1yJ<*}Af-CmTgNK9hLP+#vMPwy=hpJth1 z6SexmUnDUIYFjVPp#jyOScJHUo{c=co3Bw9bU+gl=u=VpS@m=Hk-ab|utU@T_A zEwEGPwDUozZan~`(6czIKJKc}aCoQUn|wd%&IR zTF&3zH9_ZZsXc{%{E)byVBcuZ^Z5k%AVRF7(c7vK3=>SN6fcs_ZZpc#Lv)tWG?*=+ z9DR`vx{x|B7t!H7CGaQu6HV%Q4^MBetJM903ZOR$iKHW*V7%(u0RQ4m4Qxkp2Q=|+ zz#}Zrs4P^sSzyp$^-RalkgeX+2V!W1iJ?LK#;T(vm%z9->s{DOBkA7HNu6*cu{tdi zsuOBWp@v-Tj4)B#jQLPjIcikX0=1jn12So()-Kb#iAM>_()UAkzt^Yu(R*CrXmY&i z`)PU%)h|;!g9fa3%+naN$JEq%`fxF1+MGp|;lz3942kY9f4f(knYGHB;8uvYYc1ERi&`JU)L=^GGy0{WA&E)8&}sT50;OaSwGy-)i|U=?@J zX7Bg7!zuCnJD8z&I7E8)J}=y~dS9%wkED7(()YF5^Hu)3pO=rUn6PG)^PvZfjuv~L z!3=1+8$;9Iyjpi+7mwfpg`6MKv0)rjrTg^42Nzw9H}(l&PXh{K_!+PAUXU!~OqZh| z`bgNIxXni|2_|^;RsY!DzV4lpsK1v8HM=1KB{(tJE=(jafs>8$th^_O!_w%j9?A^0! zY6VNi;k^l(xz)Q>!~llu;+_Zbr>R@W3A&^7DT#GX@@1`5ky%UB{fuLGQ=_JQ4rw+_ z#Paz&(>~df`<=7O?JHth%g zzgA7a^SQ|zOKXyAv*&~HbBj+ZA8)y|!uw`zG@chf7gjYSKitEGsNi7tk$zklIUKcq zB!1IyHk`|wa#J}=@~oezXs8}sJ()Ont77OW)42yfErt?qIOQRBGFM3{EA z=ffs7R63t{i@#1vjAO4qkRk^)ccKfNM^OB)6MoF@rl^%oOoF^VVr`87Mr}|WFwi+U zRX_6CDP~8#0hkuH5y%tB$hDF9b540MF}a9ItU#dCv9s(w zdEUvqjv33WrLo&QYhm)~R6Ofr+{7E>{|u0sxh(o4K3jGI^q4teE6r+4qzB4XWYM>s zD?*QKHYJO*F07iuI!_duQz|wX@A~99@I86#^1saEXhvoF)hD^1TaQO#A5bVXXAk2o zpJ`MI!wX<{`m0e$&G^O0r7mL#wb6{qP1$43yPhA=;SgM9CUSJ*8#_92%I_qj&>5NT z-cJ#aQfVL|@S>Gyui(Ivlohg+d2fHDEFugp1S@^B93B#htzeN?85)Lp^dij7v{rvllWww2_)XPs z*qni^%g2_VkE2ij-vbJ@p7?+VJxhCKSlqY%^_rIyv!G{!`MoH9hJyUXuHF`VF}W_& zL_2TgRPPh8-R{8(Ycw9KDgYh_cOb6{N>!^KG0M$|ZzWT*~*uKRhJ80h*X6@Yx{_eT71N{9B zP#v{z%y+a8YA$~+53Y-p~36_;1-6OMf=s#`W+1JYMZ zHYY3oEaO$IXGJbPo|jV(bd*tg9e;&&?iVgyJmsKB%aUzO;UK0O4Q)ZzC+|t0N;^Ef zXib+OQ@C^)(a+cT$5SAX|84odcn{nLR44>E*DO@TPY82}FC2TPqK9A6V}tcWh#}Mv z@_~OVFm9E88miOAP47*zbZrUMzrqVzML5x~I8?XJ@P~G~NPLTa9~I_EM*O%%XG@0k zj$fS@y9%A=YHGO(23E}+<#&`*_|Zk2YkQ;mB`{N9NAZ#%apX$efQ}^$Is82mlbLa( ze&DiQNzk&B06Y=Em5GZvILC5^P|mhKP@D#jpif=IB5|#+{xM>h7!4m(f5^EN#l&d! zPQ$8ahOZ2|gJ4X=+02}~Z=O1WrMMeuN*%nCb>Kdrlu)Mr1$svN52Oi>B2UWZus7=D z`10Azn4fDUyI{rE?cN5Y3agkK-MD%^(LA!b@A3@yP3ey*389!xVXfI%Hp;dQBJ#bz zR6{$70TT)4KbdtzAEQTP92iDWbB<8_nOOw#lT9$U+W^@uXxaSb0ub__-1xL$0?;T6-AfkUaGUp+ni+SE& z8T&RB&i~eM9NV~DfBN>nZMcrai@++llLc$=pZTfo;4M6}kmW)gjqzM^p5s+b3h0^< zG*<6~o)mIPc8)mbh5MH0>-rl`r=C-6XZ`F8hyB8_a>!t-7nZv?;vA}KuHv}qG(;A;l*Vzc_&7rv%!(X_)v$F2qf%JHa4my&M3((5IHfczYO>#o=5ci&Xx)wx=SoYR=hoDf03z5dZE{RGIs2Wvm~)0fCjw$b8!)4(cym z7MiW?7zUtv+@RiDum$^j2|KaYPW*_R8@tuRuU0PF@NcbNo5lHo3}TzfIp3`y}}U=c)fadDo9+ z%m22#TlqURK1<%UXx;YzD|r{e5|Ifi)MGoVo<-ZW+SwNHRa@`S9>v*)r51)6)6kqV z-NNU&2=wDtJ?xwXtDauT15)!N5^IIWhUREnxgtiqs*{VtuYE(#E1;^A2`0v3pdwz# z4Oi*NF*SCiikc91O;hlKEg5o~Gf34ySX^M0msvPvuZoT!SFkF|^F|sCYUaXuV27Be z+OLWh!HE#UNL20(3>HK(=7fe}t*|u_w6z%GJw)rGeD8?oY)wSWDNM#%6XjQTCA48p zFSi`h(&JmqIdXyA4FV(vT4}N|bmNzzIe@@G3qo@?@)qgQ8c7UhJ=Ds2h$bL<=B_3k zWdYEA!lm7iMNeqn3p?R>@xZtux&_WqYwSbU0b%B4oUgi4CF>N$L;8#iEJNA^J;o

R>>n0I3Fg`ioE3uA<%W|#_h*hWX#g-1QdItxc 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

#RC!;Nyg8ue;#oQc&AEe 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%0D=I{qgNCeE4_jkD4z=)E`m$ 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

Hello World!") + +By default, the ``document`` will be an ``xml.etree`` element instance. +Whenever possible, html5lib chooses the accelerated ``ElementTree`` +implementation (i.e. ``xml.etree.cElementTree`` on Python 2.x). + +Two other tree types are supported: ``xml.dom.minidom`` and +``lxml.etree``. To use an alternative format, specify the name of +a treebuilder: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + lxml_etree_document = html5lib.parse(f, treebuilder="lxml") + +When using with ``urllib2`` (Python 2), the charset from HTTP should be +pass into html5lib as follows: + +.. code-block:: python + + from contextlib import closing + from urllib2 import urlopen + import html5lib + + with closing(urlopen("http://example.com/")) as f: + document = html5lib.parse(f, transport_encoding=f.info().getparam("charset")) + +When using with ``urllib.request`` (Python 3), the charset from HTTP +should be pass into html5lib as follows: + +.. code-block:: python + + from urllib.request import urlopen + import html5lib + + with urlopen("http://example.com/") as f: + document = html5lib.parse(f, transport_encoding=f.info().get_content_charset()) + +To have more control over the parser, create a parser object explicitly. +For instance, to make the parser raise exceptions on parse errors, use: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + parser = html5lib.HTMLParser(strict=True) + document = parser.parse(f) + +When you're instantiating parser objects explicitly, pass a treebuilder +class as the ``tree`` keyword argument to use an alternative document +format: + +.. code-block:: python + + import html5lib + parser = html5lib.HTMLParser(tree=html5lib.getTreeBuilder("dom")) + minidom_document = parser.parse("

Hello World!") + +More documentation is available at https://html5lib.readthedocs.io/. + + +Installation +------------ + +html5lib works on CPython 2.7+, CPython 3.3+ and PyPy. To install it, +use: + +.. code-block:: bash + + $ pip install html5lib + + +Optional Dependencies +--------------------- + +The following third-party libraries may be used for additional +functionality: + +- ``datrie`` can be used under CPython to improve parsing performance + (though in almost all cases the improvement is marginal); + +- ``lxml`` is supported as a tree format (for both building and + walking) under CPython (but *not* PyPy where it is known to cause + segfaults); + +- ``genshi`` has a treewalker (but not builder); and + +- ``chardet`` can be used as a fallback when character encoding cannot + be determined. + + +Bugs +---- + +Please report any bugs on the `issue tracker +`_. + + +Tests +----- + +Unit tests require the ``pytest`` and ``mock`` libraries and can be +run using the ``py.test`` command in the root directory. + +Test data are contained in a separate `html5lib-tests +`_ repository and included +as a submodule, thus for git checkouts they must be initialized:: + + $ git submodule init + $ git submodule update + +If you have all compatible Python implementations available on your +system, you can run tests on all of them using the ``tox`` utility, +which can be found on PyPI. + + +Questions? +---------- + +There's a mailing list available for support on Google Groups, +`html5lib-discuss `_, +though you may get a quicker response asking on IRC in `#whatwg on +irc.freenode.net `_. + +Change Log +---------- + +1.0.1 +~~~~~ + +Released on December 7, 2017 + +Breaking changes: + +* Drop support for Python 2.6. (#330) (Thank you, Hugo, Will Kahn-Greene!) +* Remove ``utils/spider.py`` (#353) (Thank you, Jon Dufresne!) + +Features: + +* Improve documentation. (#300, #307) (Thank you, Jon Dufresne, Tom Most, + Will Kahn-Greene!) +* Add iframe seamless boolean attribute. (Thank you, Ritwik Gupta!) +* Add itemscope as a boolean attribute. (#194) (Thank you, Jonathan Vanasco!) +* Support Python 3.6. (#333) (Thank you, Jon Dufresne!) +* Add CI support for Windows using AppVeyor. (Thank you, John Vandenberg!) +* Improve testing and CI and add code coverage (#323, #334), (Thank you, Jon + Dufresne, John Vandenberg, Geoffrey Sneddon, Will Kahn-Greene!) +* Semver-compliant version number. + +Bug fixes: + +* Add support for setuptools < 18.5 to support environment markers. (Thank you, + John Vandenberg!) +* Add explicit dependency for six >= 1.9. (Thank you, Eric Amorde!) +* Fix regexes to work with Python 3.7 regex adjustments. (#318, #379) (Thank + you, Benedikt Morbach, Ville Skyttä, Mark Vasilkov!) +* Fix alphabeticalattributes filter namespace bug. (#324) (Thank you, Will + Kahn-Greene!) +* Include license file in generated wheel package. (#350) (Thank you, Jon + Dufresne!) +* Fix annotation-xml typo. (#339) (Thank you, Will Kahn-Greene!) +* Allow uppercase hex chararcters in CSS colour check. (#377) (Thank you, + Komal Dembla, Hugo!) + + +1.0 +~~~ + +Released and unreleased on December 7, 2017. Badly packaged release. + + +0.999999999/1.0b10 +~~~~~~~~~~~~~~~~~~ + +Released on July 15, 2016 + +* Fix attribute order going to the tree builder to be document order + instead of reverse document order(!). + + +0.99999999/1.0b9 +~~~~~~~~~~~~~~~~ + +Released on July 14, 2016 + +* **Added ordereddict as a mandatory dependency on Python 2.6.** + +* Added ``lxml``, ``genshi``, ``datrie``, ``charade``, and ``all`` + extras that will do the right thing based on the specific + interpreter implementation. + +* Now requires the ``mock`` package for the testsuite. + +* Cease supporting DATrie under PyPy. + +* **Remove PullDOM support, as this hasn't ever been properly + tested, doesn't entirely work, and as far as I can tell is + completely unused by anyone.** + +* Move testsuite to ``py.test``. + +* **Fix #124: move to webencodings for decoding the input byte stream; + this makes html5lib compliant with the Encoding Standard, and + introduces a required dependency on webencodings.** + +* **Cease supporting Python 3.2 (in both CPython and PyPy forms).** + +* **Fix comments containing double-dash with lxml 3.5 and above.** + +* **Use scripting disabled by default (as we don't implement + scripting).** + +* **Fix #11, avoiding the XSS bug potentially caused by serializer + allowing attribute values to be escaped out of in old browser versions, + changing the quote_attr_values option on serializer to take one of + three values, "always" (the old True value), "legacy" (the new option, + and the new default), and "spec" (the old False value, and the old + default).** + +* **Fix #72 by rewriting the sanitizer to apply only to treewalkers + (instead of the tokenizer); as such, this will require amending all + callers of it to use it via the treewalker API.** + +* **Drop support of charade, now that chardet is supported once more.** + +* **Replace the charset keyword argument on parse and related methods + with a set of keyword arguments: override_encoding, transport_encoding, + same_origin_parent_encoding, likely_encoding, and default_encoding.** + +* **Move filters._base, treebuilder._base, and treewalkers._base to .base + to clarify their status as public.** + +* **Get rid of the sanitizer package. Merge sanitizer.sanitize into the + sanitizer.htmlsanitizer module and move that to sanitizer. This means + anyone who used sanitizer.sanitize or sanitizer.HTMLSanitizer needs no + code changes.** + +* **Rename treewalkers.lxmletree to .etree_lxml and + treewalkers.genshistream to .genshi to have a consistent API.** + +* Move a whole load of stuff (inputstream, ihatexml, trie, tokenizer, + utils) to be underscore prefixed to clarify their status as private. + + +0.9999999/1.0b8 +~~~~~~~~~~~~~~~ + +Released on September 10, 2015 + +* Fix #195: fix the sanitizer to drop broken URLs (it threw an + exception between 0.9999 and 0.999999). + + +0.999999/1.0b7 +~~~~~~~~~~~~~~ + +Released on July 7, 2015 + +* Fix #189: fix the sanitizer to allow relative URLs again (as it did + prior to 0.9999/1.0b5). + + +0.99999/1.0b6 +~~~~~~~~~~~~~ + +Released on April 30, 2015 + +* Fix #188: fix the sanitizer to not throw an exception when sanitizing + bogus data URLs. + + +0.9999/1.0b5 +~~~~~~~~~~~~ + +Released on April 29, 2015 + +* Fix #153: Sanitizer fails to treat some attributes as URLs. Despite how + this sounds, this has no known security implications. No known version + of IE (5.5 to current), Firefox (3 to current), Safari (6 to current), + Chrome (1 to current), or Opera (12 to current) will run any script + provided in these attributes. + +* Pass error message to the ParseError exception in strict parsing mode. + +* Allow data URIs in the sanitizer, with a whitelist of content-types. + +* Add support for Python implementations that don't support lone + surrogates (read: Jython). Fixes #2. + +* Remove localization of error messages. This functionality was totally + unused (and untested that everything was localizable), so we may as + well follow numerous browsers in not supporting translating technical + strings. + +* Expose treewalkers.pprint as a public API. + +* Add a documentEncoding property to HTML5Parser, fix #121. + + +0.999 +~~~~~ + +Released on December 23, 2013 + +* Fix #127: add work-around for CPython issue #20007: .read(0) on + http.client.HTTPResponse drops the rest of the content. + +* Fix #115: lxml treewalker can now deal with fragments containing, at + their root level, text nodes with non-ASCII characters on Python 2. + + +0.99 +~~~~ + +Released on September 10, 2013 + +* No library changes from 1.0b3; released as 0.99 as pip has changed + behaviour from 1.4 to avoid installing pre-release versions per + PEP 440. + + +1.0b3 +~~~~~ + +Released on July 24, 2013 + +* Removed ``RecursiveTreeWalker`` from ``treewalkers._base``. Any + implementation using it should be moved to + ``NonRecursiveTreeWalker``, as everything bundled with html5lib has + for years. + +* Fix #67 so that ``BufferedStream`` to correctly returns a bytes + object, thereby fixing any case where html5lib is passed a + non-seekable RawIOBase-like object. + + +1.0b2 +~~~~~ + +Released on June 27, 2013 + +* Removed reordering of attributes within the serializer. There is now + an ``alphabetical_attributes`` option which preserves the previous + behaviour through a new filter. This allows attribute order to be + preserved through html5lib if the tree builder preserves order. + +* Removed ``dom2sax`` from DOM treebuilders. It has been replaced by + ``treeadapters.sax.to_sax`` which is generic and supports any + treewalker; it also resolves all known bugs with ``dom2sax``. + +* Fix treewalker assertions on hitting bytes strings on + Python 2. Previous to 1.0b1, treewalkers coped with mixed + bytes/unicode data on Python 2; this reintroduces this prior + behaviour on Python 2. Behaviour is unchanged on Python 3. + + +1.0b1 +~~~~~ + +Released on May 17, 2013 + +* Implementation updated to implement the `HTML specification + `_ as of 5th May + 2013 (`SVN `_ revision r7867). + +* Python 3.2+ supported in a single codebase using the ``six`` library. + +* Removed support for Python 2.5 and older. + +* Removed the deprecated Beautiful Soup 3 treebuilder. + ``beautifulsoup4`` can use ``html5lib`` as a parser instead. Note that + since it doesn't support namespaces, foreign content like SVG and + MathML is parsed incorrectly. + +* Removed ``simpletree`` from the package. The default tree builder is + now ``etree`` (using the ``xml.etree.cElementTree`` implementation if + available, and ``xml.etree.ElementTree`` otherwise). + +* Removed the ``XHTMLSerializer`` as it never actually guaranteed its + output was well-formed XML, and hence provided little of use. + +* Removed default DOM treebuilder, so ``html5lib.treebuilders.dom`` is no + longer supported. ``html5lib.treebuilders.getTreeBuilder("dom")`` will + return the default DOM treebuilder, which uses ``xml.dom.minidom``. + +* Optional heuristic character encoding detection now based on + ``charade`` for Python 2.6 - 3.3 compatibility. + +* Optional ``Genshi`` treewalker support fixed. + +* Many bugfixes, including: + + * #33: null in attribute value breaks XML AttValue; + + * #4: nested, indirect descendant,

XY&OjX=>r|e;D@s>d@ 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≪-q|TQ%RiOx)BI<6F${G2(Qm_FgZaZ9@11$q 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%0Ar%B6m4kc<6eL=pQ;piKI5*6!}pHV`iUc1gHX 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%0DHirUF8xM9$@DdRHp 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 127 or o < 32) +_cescape_byte_to_str = ([r'\%03o' % i for i in range(0, 32)] + + [chr(i) for i in range(32, 127)] + + [r'\%03o' % i for i in range(127, 256)]) +for byte, string in _cescape_chr_to_symbol_map.items(): + _cescape_byte_to_str[byte] = string +del byte, string + + +def CEscape(text, as_utf8): + # type: (...) -> str + """Escape a bytes string for use in an text protocol buffer. + + Args: + text: A byte string to be escaped. + as_utf8: Specifies if result may contain non-ASCII characters. + In Python 3 this allows unescaped non-ASCII Unicode characters. + In Python 2 the return value will be valid UTF-8 rather than only ASCII. + Returns: + Escaped string (str). + """ + # Python's text.encode() 'string_escape' or 'unicode_escape' codecs do not + # satisfy our needs; they encodes unprintable characters using two-digit hex + # escapes whereas our C++ unescaping function allows hex escapes to be any + # length. So, "\0011".encode('string_escape') ends up being "\\x011", which + # will be decoded in C++ as a single-character string with char code 0x11. + if six.PY3: + text_is_unicode = isinstance(text, str) + if as_utf8 and text_is_unicode: + # We're already unicode, no processing beyond control char escapes. + return text.translate(_cescape_chr_to_symbol_map) + ord_ = ord if text_is_unicode else lambda x: x # bytes iterate as ints. + else: + ord_ = ord # PY2 + if as_utf8: + return ''.join(_cescape_unicode_to_str[ord_(c)] for c in text) + return ''.join(_cescape_byte_to_str[ord_(c)] for c in text) + + +_CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])') + + +def CUnescape(text): + # type: (str) -> bytes + """Unescape a text string with C-style escape sequences to UTF-8 bytes. + + Args: + text: The data to parse in a str. + Returns: + A byte string. + """ + + def ReplaceHex(m): + # Only replace the match if the number of leading back slashes is odd. i.e. + # the slash itself is not escaped. + if len(m.group(1)) & 1: + return m.group(1) + 'x0' + m.group(2) + return m.group(0) + + # This is required because the 'string_escape' encoding doesn't + # allow single-digit hex escapes (like '\xf'). + result = _CUNESCAPE_HEX.sub(ReplaceHex, text) + + if six.PY2: + return result.decode('string_escape') + return (result.encode('utf-8') # PY3: Make it bytes to allow decode. + .decode('unicode_escape') + # Make it bytes again to return the proper type. + .encode('raw_unicode_escape')) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/text_format.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/text_format.py new file mode 100644 index 00000000..c376c7ba --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/text_format.py @@ -0,0 +1,1828 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# https://developers.google.com/protocol-buffers/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Contains routines for printing protocol messages in text format. + +Simple usage example:: + + # Create a proto object and serialize it to a text proto string. + message = my_proto_pb2.MyMessage(foo='bar') + text_proto = text_format.MessageToString(message) + + # Parse a text proto string. + message = text_format.Parse(text_proto, my_proto_pb2.MyMessage()) +""" + +__author__ = 'kenton@google.com (Kenton Varda)' + +# TODO(b/129989314) Import thread contention leads to test failures. +import encodings.raw_unicode_escape # pylint: disable=unused-import +import encodings.unicode_escape # pylint: disable=unused-import +import io +import math +import re +import six + +from google.protobuf.internal import decoder +from google.protobuf.internal import type_checkers +from google.protobuf import descriptor +from google.protobuf import text_encoding + +if six.PY3: + long = int # pylint: disable=redefined-builtin,invalid-name + +# pylint: disable=g-import-not-at-top +__all__ = ['MessageToString', 'Parse', 'PrintMessage', 'PrintField', + 'PrintFieldValue', 'Merge', 'MessageToBytes'] + +_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), + type_checkers.Int32ValueChecker(), + type_checkers.Uint64ValueChecker(), + type_checkers.Int64ValueChecker()) +_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?$', re.IGNORECASE) +_FLOAT_NAN = re.compile('nanf?$', re.IGNORECASE) +_QUOTES = frozenset(("'", '"')) +_ANY_FULL_TYPE_NAME = 'google.protobuf.Any' + + +class Error(Exception): + """Top-level module error for text_format.""" + + +class ParseError(Error): + """Thrown in case of text parsing or tokenizing error.""" + + def __init__(self, message=None, line=None, column=None): + if message is not None and line is not None: + loc = str(line) + if column is not None: + loc += ':{0}'.format(column) + message = '{0} : {1}'.format(loc, message) + if message is not None: + super(ParseError, self).__init__(message) + else: + super(ParseError, self).__init__() + self._line = line + self._column = column + + def GetLine(self): + return self._line + + def GetColumn(self): + return self._column + + +class TextWriter(object): + + def __init__(self, as_utf8): + if six.PY2: + self._writer = io.BytesIO() + else: + self._writer = io.StringIO() + + def write(self, val): + if six.PY2: + if isinstance(val, six.text_type): + val = val.encode('utf-8') + return self._writer.write(val) + + def close(self): + return self._writer.close() + + def getvalue(self): + return self._writer.getvalue() + + +def MessageToString( + message, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + use_field_number=False, + descriptor_pool=None, + indent=0, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + # type: (...) -> str + """Convert protobuf message to text format. + + Double values can be formatted compactly with 15 digits of + precision (which is the most that IEEE 754 "double" can guarantee) + using double_format='.15g'. To ensure that converting to text and back to a + proto will result in an identical value, double_format='.17g' should be used. + + Args: + message: The protocol buffers message. + as_utf8: Return unescaped Unicode for non-ASCII characters. + In Python 3 actual Unicode characters may appear as is in strings. + In Python 2 the return value will be valid UTF-8 rather than only ASCII. + as_one_line: Don't introduce newlines between fields. + use_short_repeated_primitives: Use short repeated format for primitives. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, fields of a proto message will be printed using + the order defined in source code instead of the field number, extensions + will be printed at the end of the message and their relative order is + determined by the extension number. By default, use the field number + order. + float_format (str): If set, use this to specify float field formatting + (per the "Format Specification Mini-Language"); otherwise, shortest float + that has same value in wire will be printed. Also affect double field + if double_format is not set but float_format is set. + double_format (str): If set, use this to specify double field formatting + (per the "Format Specification Mini-Language"); if it is not set but + float_format is set, use float_format. Otherwise, use ``str()`` + use_field_number: If True, print field numbers instead of names. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + indent (int): The initial indent level, in terms of spaces, for pretty + print. + message_formatter (function(message, indent, as_one_line) -> unicode|None): + Custom formatter for selected sub-messages (usually based on message + type). Use to pretty print parts of the protobuf for easier diffing. + print_unknown_fields: If True, unknown fields will be printed. + force_colon: If set, a colon will be added after the field name even if the + field is a proto message. + + Returns: + str: A string of the text formatted protocol buffer message. + """ + out = TextWriter(as_utf8) + printer = _Printer( + out, + indent, + as_utf8, + as_one_line, + use_short_repeated_primitives, + pointy_brackets, + use_index_order, + float_format, + double_format, + use_field_number, + descriptor_pool, + message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) + printer.PrintMessage(message) + result = out.getvalue() + out.close() + if as_one_line: + return result.rstrip() + return result + + +def MessageToBytes(message, **kwargs): + # type: (...) -> bytes + """Convert protobuf message to encoded text format. See MessageToString.""" + text = MessageToString(message, **kwargs) + if isinstance(text, bytes): + return text + codec = 'utf-8' if kwargs.get('as_utf8') else 'ascii' + return text.encode(codec) + + +def _IsMapEntry(field): + return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def PrintMessage(message, + out, + indent=0, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + printer = _Printer( + out=out, indent=indent, as_utf8=as_utf8, + as_one_line=as_one_line, + use_short_repeated_primitives=use_short_repeated_primitives, + pointy_brackets=pointy_brackets, + use_index_order=use_index_order, + float_format=float_format, + double_format=double_format, + use_field_number=use_field_number, + descriptor_pool=descriptor_pool, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) + printer.PrintMessage(message) + + +def PrintField(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + """Print a single field name/value pair.""" + printer = _Printer(out, indent, as_utf8, as_one_line, + use_short_repeated_primitives, pointy_brackets, + use_index_order, float_format, double_format, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) + printer.PrintField(field, value) + + +def PrintFieldValue(field, + value, + out, + indent=0, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + """Print a single field value (not including name).""" + printer = _Printer(out, indent, as_utf8, as_one_line, + use_short_repeated_primitives, pointy_brackets, + use_index_order, float_format, double_format, + message_formatter=message_formatter, + print_unknown_fields=print_unknown_fields, + force_colon=force_colon) + printer.PrintFieldValue(field, value) + + +def _BuildMessageFromTypeName(type_name, descriptor_pool): + """Returns a protobuf message instance. + + Args: + type_name: Fully-qualified protobuf message type name string. + descriptor_pool: DescriptorPool instance. + + Returns: + A Message instance of type matching type_name, or None if the a Descriptor + wasn't found matching type_name. + """ + # pylint: disable=g-import-not-at-top + if descriptor_pool is None: + from google.protobuf import descriptor_pool as pool_mod + descriptor_pool = pool_mod.Default() + from google.protobuf import symbol_database + database = symbol_database.Default() + try: + message_descriptor = descriptor_pool.FindMessageTypeByName(type_name) + except KeyError: + return None + message_type = database.GetPrototype(message_descriptor) + return message_type() + + +# These values must match WireType enum in google/protobuf/wire_format.h. +WIRETYPE_LENGTH_DELIMITED = 2 +WIRETYPE_START_GROUP = 3 + + +class _Printer(object): + """Text format printer for protocol message.""" + + def __init__( + self, + out, + indent=0, + as_utf8=False, + as_one_line=False, + use_short_repeated_primitives=False, + pointy_brackets=False, + use_index_order=False, + float_format=None, + double_format=None, + use_field_number=False, + descriptor_pool=None, + message_formatter=None, + print_unknown_fields=False, + force_colon=False): + """Initialize the Printer. + + Double values can be formatted compactly with 15 digits of precision + (which is the most that IEEE 754 "double" can guarantee) using + double_format='.15g'. To ensure that converting to text and back to a proto + will result in an identical value, double_format='.17g' should be used. + + Args: + out: To record the text format result. + indent: The initial indent level for pretty print. + as_utf8: Return unescaped Unicode for non-ASCII characters. + In Python 3 actual Unicode characters may appear as is in strings. + In Python 2 the return value will be valid UTF-8 rather than ASCII. + as_one_line: Don't introduce newlines between fields. + use_short_repeated_primitives: Use short repeated format for primitives. + pointy_brackets: If True, use angle brackets instead of curly braces for + nesting. + use_index_order: If True, print fields of a proto message using the order + defined in source code instead of the field number. By default, use the + field number order. + float_format: If set, use this to specify float field formatting + (per the "Format Specification Mini-Language"); otherwise, shortest + float that has same value in wire will be printed. Also affect double + field if double_format is not set but float_format is set. + double_format: If set, use this to specify double field formatting + (per the "Format Specification Mini-Language"); if it is not set but + float_format is set, use float_format. Otherwise, str() is used. + use_field_number: If True, print field numbers instead of names. + descriptor_pool: A DescriptorPool used to resolve Any types. + message_formatter: A function(message, indent, as_one_line): unicode|None + to custom format selected sub-messages (usually based on message type). + Use to pretty print parts of the protobuf for easier diffing. + print_unknown_fields: If True, unknown fields will be printed. + force_colon: If set, a colon will be added after the field name even if + the field is a proto message. + """ + self.out = out + self.indent = indent + self.as_utf8 = as_utf8 + self.as_one_line = as_one_line + self.use_short_repeated_primitives = use_short_repeated_primitives + self.pointy_brackets = pointy_brackets + self.use_index_order = use_index_order + self.float_format = float_format + if double_format is not None: + self.double_format = double_format + else: + self.double_format = float_format + self.use_field_number = use_field_number + self.descriptor_pool = descriptor_pool + self.message_formatter = message_formatter + self.print_unknown_fields = print_unknown_fields + self.force_colon = force_colon + + def _TryPrintAsAnyMessage(self, message): + """Serializes if message is a google.protobuf.Any field.""" + if '/' not in message.type_url: + return False + packed_message = _BuildMessageFromTypeName(message.TypeName(), + self.descriptor_pool) + if packed_message: + packed_message.MergeFromString(message.value) + colon = ':' if self.force_colon else '' + self.out.write('%s[%s]%s ' % (self.indent * ' ', message.type_url, colon)) + self._PrintMessageFieldValue(packed_message) + self.out.write(' ' if self.as_one_line else '\n') + return True + else: + return False + + def _TryCustomFormatMessage(self, message): + formatted = self.message_formatter(message, self.indent, self.as_one_line) + if formatted is None: + return False + + out = self.out + out.write(' ' * self.indent) + out.write(formatted) + out.write(' ' if self.as_one_line else '\n') + return True + + def PrintMessage(self, message): + """Convert protobuf message to text format. + + Args: + message: The protocol buffers message. + """ + if self.message_formatter and self._TryCustomFormatMessage(message): + return + if (message.DESCRIPTOR.full_name == _ANY_FULL_TYPE_NAME and + self._TryPrintAsAnyMessage(message)): + return + fields = message.ListFields() + if self.use_index_order: + fields.sort( + key=lambda x: x[0].number if x[0].is_extension else x[0].index) + for field, value in fields: + if _IsMapEntry(field): + for key in sorted(value): + # This is slow for maps with submessage entries because it copies the + # entire tree. Unfortunately this would take significant refactoring + # of this file to work around. + # + # TODO(haberman): refactor and optimize if this becomes an issue. + entry_submsg = value.GetEntryClass()(key=key, value=value[key]) + self.PrintField(field, entry_submsg) + elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if (self.use_short_repeated_primitives + and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE + and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_STRING): + self._PrintShortRepeatedPrimitivesValue(field, value) + else: + for element in value: + self.PrintField(field, element) + else: + self.PrintField(field, value) + + if self.print_unknown_fields: + self._PrintUnknownFields(message.UnknownFields()) + + def _PrintUnknownFields(self, unknown_fields): + """Print unknown fields.""" + out = self.out + for field in unknown_fields: + out.write(' ' * self.indent) + out.write(str(field.field_number)) + if field.wire_type == WIRETYPE_START_GROUP: + if self.as_one_line: + out.write(' { ') + else: + out.write(' {\n') + self.indent += 2 + + self._PrintUnknownFields(field.data) + + if self.as_one_line: + out.write('} ') + else: + self.indent -= 2 + out.write(' ' * self.indent + '}\n') + elif field.wire_type == WIRETYPE_LENGTH_DELIMITED: + try: + # If this field is parseable as a Message, it is probably + # an embedded message. + # pylint: disable=protected-access + (embedded_unknown_message, pos) = decoder._DecodeUnknownFieldSet( + memoryview(field.data), 0, len(field.data)) + except Exception: # pylint: disable=broad-except + pos = 0 + + if pos == len(field.data): + if self.as_one_line: + out.write(' { ') + else: + out.write(' {\n') + self.indent += 2 + + self._PrintUnknownFields(embedded_unknown_message) + + if self.as_one_line: + out.write('} ') + else: + self.indent -= 2 + out.write(' ' * self.indent + '}\n') + else: + # A string or bytes field. self.as_utf8 may not work. + out.write(': \"') + out.write(text_encoding.CEscape(field.data, False)) + out.write('\" ' if self.as_one_line else '\"\n') + else: + # varint, fixed32, fixed64 + out.write(': ') + out.write(str(field.data)) + out.write(' ' if self.as_one_line else '\n') + + def _PrintFieldName(self, field): + """Print field name.""" + out = self.out + out.write(' ' * self.indent) + if self.use_field_number: + out.write(str(field.number)) + else: + if field.is_extension: + out.write('[') + if (field.containing_type.GetOptions().message_set_wire_format and + field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): + out.write(field.message_type.full_name) + else: + out.write(field.full_name) + out.write(']') + elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: + # For groups, use the capitalized name. + out.write(field.message_type.name) + else: + out.write(field.name) + + if (self.force_colon or + field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE): + # The colon is optional in this case, but our cross-language golden files + # don't include it. Here, the colon is only included if force_colon is + # set to True + out.write(':') + + def PrintField(self, field, value): + """Print a single field name/value pair.""" + self._PrintFieldName(field) + self.out.write(' ') + self.PrintFieldValue(field, value) + self.out.write(' ' if self.as_one_line else '\n') + + def _PrintShortRepeatedPrimitivesValue(self, field, value): + """"Prints short repeated primitives value.""" + # Note: this is called only when value has at least one element. + self._PrintFieldName(field) + self.out.write(' [') + for i in six.moves.range(len(value) - 1): + self.PrintFieldValue(field, value[i]) + self.out.write(', ') + self.PrintFieldValue(field, value[-1]) + self.out.write(']') + if self.force_colon: + self.out.write(':') + self.out.write(' ' if self.as_one_line else '\n') + + def _PrintMessageFieldValue(self, value): + if self.pointy_brackets: + openb = '<' + closeb = '>' + else: + openb = '{' + closeb = '}' + + if self.as_one_line: + self.out.write('%s ' % openb) + self.PrintMessage(value) + self.out.write(closeb) + else: + self.out.write('%s\n' % openb) + self.indent += 2 + self.PrintMessage(value) + self.indent -= 2 + self.out.write(' ' * self.indent + closeb) + + def PrintFieldValue(self, field, value): + """Print a single field value (not including name). + + For repeated fields, the value should be a single element. + + Args: + field: The descriptor of the field to be printed. + value: The value of the field. + """ + out = self.out + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + self._PrintMessageFieldValue(value) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: + enum_value = field.enum_type.values_by_number.get(value, None) + if enum_value is not None: + out.write(enum_value.name) + else: + out.write(str(value)) + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: + out.write('\"') + if isinstance(value, six.text_type) and (six.PY2 or not self.as_utf8): + out_value = value.encode('utf-8') + else: + out_value = value + if field.type == descriptor.FieldDescriptor.TYPE_BYTES: + # We always need to escape all binary data in TYPE_BYTES fields. + out_as_utf8 = False + else: + out_as_utf8 = self.as_utf8 + out.write(text_encoding.CEscape(out_value, out_as_utf8)) + out.write('\"') + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: + if value: + out.write('true') + else: + out.write('false') + elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT: + if self.float_format is not None: + out.write('{1:{0}}'.format(self.float_format, value)) + else: + if math.isnan(value): + out.write(str(value)) + else: + out.write(str(type_checkers.ToShortestFloat(value))) + elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and + self.double_format is not None): + out.write('{1:{0}}'.format(self.double_format, value)) + else: + out.write(str(value)) + + +def Parse(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None, + allow_unknown_field=False): + """Parses a text representation of a protocol message into a message. + + NOTE: for historical reasons this function does not clear the input + message. This is different from what the binary msg.ParseFrom(...) does. + If text contains a field already set in message, the value is appended if the + field is repeated. Otherwise, an error is raised. + + Example:: + + a = MyProto() + a.repeated_field.append('test') + b = MyProto() + + # Repeated fields are combined + text_format.Parse(repr(a), b) + text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"] + + # Non-repeated fields cannot be overwritten + a.singular_field = 1 + b.singular_field = 2 + text_format.Parse(repr(a), b) # ParseError + + # Binary version: + b.ParseFromString(a.SerializeToString()) # repeated_field is now "test" + + Caller is responsible for clearing the message as needed. + + Args: + text (str): Message text representation. + message (Message): A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) + + Returns: + Message: The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + return ParseLines(text.split(b'\n' if isinstance(text, bytes) else u'\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) + + +def Merge(text, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None, + allow_unknown_field=False): + """Parses a text representation of a protocol message into a message. + + Like Parse(), but allows repeated values for a non-repeated field, and uses + the last one. This means any non-repeated, top-level fields specified in text + replace those in the message. + + Args: + text (str): Message text representation. + message (Message): A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) + + Returns: + Message: The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + return MergeLines( + text.split(b'\n' if isinstance(text, bytes) else u'\n'), + message, + allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) + + +def ParseLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None, + allow_unknown_field=False): + """Parses a text representation of a protocol message into a message. + + See Parse() for caveats. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) + return parser.ParseLines(lines, message) + + +def MergeLines(lines, + message, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None, + allow_unknown_field=False): + """Parses a text representation of a protocol message into a message. + + See Merge() for more details. + + Args: + lines: An iterable of lines of a message's text representation. + message: A protocol buffer message to merge into. + allow_unknown_extension: if True, skip over missing extensions and keep + parsing + allow_field_number: if True, both field number and field name are allowed. + descriptor_pool: A DescriptorPool used to resolve Any types. + allow_unknown_field: if True, skip over unknown field and keep + parsing. Avoid to use this option if possible. It may hide some + errors (e.g. spelling error on field name) + + Returns: + The same message passed as argument. + + Raises: + ParseError: On text parsing problems. + """ + parser = _Parser(allow_unknown_extension, + allow_field_number, + descriptor_pool=descriptor_pool, + allow_unknown_field=allow_unknown_field) + return parser.MergeLines(lines, message) + + +class _Parser(object): + """Text format parser for protocol message.""" + + def __init__(self, + allow_unknown_extension=False, + allow_field_number=False, + descriptor_pool=None, + allow_unknown_field=False): + self.allow_unknown_extension = allow_unknown_extension + self.allow_field_number = allow_field_number + self.descriptor_pool = descriptor_pool + self.allow_unknown_field = allow_unknown_field + + def ParseLines(self, lines, message): + """Parses a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = False + self._ParseOrMerge(lines, message) + return message + + def MergeLines(self, lines, message): + """Merges a text representation of a protocol message into a message.""" + self._allow_multiple_scalars = True + self._ParseOrMerge(lines, message) + return message + + def _ParseOrMerge(self, lines, message): + """Converts a text representation of a protocol message into a message. + + Args: + lines: Lines of a message's text representation. + message: A protocol buffer message to merge into. + + Raises: + ParseError: On text parsing problems. + """ + # Tokenize expects native str lines. + if six.PY2: + str_lines = (line if isinstance(line, str) else line.encode('utf-8') + for line in lines) + else: + str_lines = (line if isinstance(line, str) else line.decode('utf-8') + for line in lines) + tokenizer = Tokenizer(str_lines) + while not tokenizer.AtEnd(): + self._MergeField(tokenizer, message) + + def _MergeField(self, tokenizer, message): + """Merges a single protocol message field into a message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + message: A protocol message to record the data. + + Raises: + ParseError: In case of text parsing problems. + """ + message_descriptor = message.DESCRIPTOR + if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and + tokenizer.TryConsume('[')): + type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer) + tokenizer.Consume(']') + tokenizer.TryConsume(':') + if tokenizer.TryConsume('<'): + expanded_any_end_token = '>' + else: + tokenizer.Consume('{') + expanded_any_end_token = '}' + expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name, + self.descriptor_pool) + if not expanded_any_sub_message: + raise ParseError('Type %s not found in descriptor pool' % + packed_type_name) + while not tokenizer.TryConsume(expanded_any_end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % + (expanded_any_end_token,)) + self._MergeField(tokenizer, expanded_any_sub_message) + deterministic = False + + message.Pack(expanded_any_sub_message, + type_url_prefix=type_url_prefix, + deterministic=deterministic) + return + + if tokenizer.TryConsume('['): + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + name = '.'.join(name) + + if not message_descriptor.is_extendable: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" does not have extensions.' % + message_descriptor.full_name) + # pylint: disable=protected-access + field = message.Extensions._FindExtensionByName(name) + # pylint: enable=protected-access + + + if not field: + if self.allow_unknown_extension: + field = None + else: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" not registered. ' + 'Did you import the _pb2 module which defines it? ' + 'If you are trying to place the extension in the MessageSet ' + 'field of another message that is in an Any or MessageSet field, ' + 'that message\'s _pb2 module must be imported as well' % name) + elif message_descriptor != field.containing_type: + raise tokenizer.ParseErrorPreviousToken( + 'Extension "%s" does not extend message type "%s".' % + (name, message_descriptor.full_name)) + + tokenizer.Consume(']') + + else: + name = tokenizer.ConsumeIdentifierOrNumber() + if self.allow_field_number and name.isdigit(): + number = ParseInteger(name, True, True) + field = message_descriptor.fields_by_number.get(number, None) + if not field and message_descriptor.is_extendable: + field = message.Extensions._FindExtensionByNumber(number) + else: + field = message_descriptor.fields_by_name.get(name, None) + + # Group names are expected to be capitalized as they appear in the + # .proto file, which actually matches their type names, not their field + # names. + if not field: + field = message_descriptor.fields_by_name.get(name.lower(), None) + if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: + field = None + + if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and + field.message_type.name != name): + field = None + + if not field and not self.allow_unknown_field: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" has no field named "%s".' % + (message_descriptor.full_name, name)) + + if field: + if not self._allow_multiple_scalars and field.containing_oneof: + # Check if there's a different field set in this oneof. + # Note that we ignore the case if the same field was set before, and we + # apply _allow_multiple_scalars to non-scalar fields as well. + which_oneof = message.WhichOneof(field.containing_oneof.name) + if which_oneof is not None and which_oneof != field.name: + raise tokenizer.ParseErrorPreviousToken( + 'Field "%s" is specified along with field "%s", another member ' + 'of oneof "%s" for message type "%s".' % + (field.name, which_oneof, field.containing_oneof.name, + message_descriptor.full_name)) + + if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + tokenizer.TryConsume(':') + merger = self._MergeMessageField + else: + tokenizer.Consume(':') + merger = self._MergeScalarField + + if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and + tokenizer.TryConsume('[')): + # Short repeated format, e.g. "foo: [1, 2, 3]" + if not tokenizer.TryConsume(']'): + while True: + merger(tokenizer, message, field) + if tokenizer.TryConsume(']'): + break + tokenizer.Consume(',') + + else: + merger(tokenizer, message, field) + + else: # Proto field is unknown. + assert (self.allow_unknown_extension or self.allow_unknown_field) + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + + def _ConsumeAnyTypeUrl(self, tokenizer): + """Consumes a google.protobuf.Any type URL and returns the type name.""" + # Consume "type.googleapis.com/". + prefix = [tokenizer.ConsumeIdentifier()] + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('.') + prefix.append(tokenizer.ConsumeIdentifier()) + tokenizer.Consume('/') + # Consume the fully-qualified type name. + name = [tokenizer.ConsumeIdentifier()] + while tokenizer.TryConsume('.'): + name.append(tokenizer.ConsumeIdentifier()) + return '.'.join(prefix), '.'.join(name) + + def _MergeMessageField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: The message of which field is a member. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + """ + is_map_entry = _IsMapEntry(field) + + if tokenizer.TryConsume('<'): + end_token = '>' + else: + tokenizer.Consume('{') + end_token = '}' + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + sub_message = message.Extensions[field].add() + elif is_map_entry: + sub_message = getattr(message, field.name).GetEntryClass()() + else: + sub_message = getattr(message, field.name).add() + else: + if field.is_extension: + if (not self._allow_multiple_scalars and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + sub_message = message.Extensions[field] + else: + # Also apply _allow_multiple_scalars to message field. + # TODO(jieluo): Change to _allow_singular_overwrites. + if (not self._allow_multiple_scalars and + message.HasField(field.name)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + sub_message = getattr(message, field.name) + sub_message.SetInParent() + + while not tokenizer.TryConsume(end_token): + if tokenizer.AtEnd(): + raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,)) + self._MergeField(tokenizer, sub_message) + + if is_map_entry: + value_cpptype = field.message_type.fields_by_name['value'].cpp_type + if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + value = getattr(message, field.name)[sub_message.key] + value.MergeFrom(sub_message.value) + else: + getattr(message, field.name)[sub_message.key] = sub_message.value + + @staticmethod + def _IsProto3Syntax(message): + message_descriptor = message.DESCRIPTOR + return (hasattr(message_descriptor, 'syntax') and + message_descriptor.syntax == 'proto3') + + def _MergeScalarField(self, tokenizer, message, field): + """Merges a single scalar field into a message. + + Args: + tokenizer: A tokenizer to parse the field value. + message: A protocol message to record the data. + field: The descriptor of the field to be merged. + + Raises: + ParseError: In case of text parsing problems. + RuntimeError: On runtime errors. + """ + _ = self.allow_unknown_extension + value = None + + if field.type in (descriptor.FieldDescriptor.TYPE_INT32, + descriptor.FieldDescriptor.TYPE_SINT32, + descriptor.FieldDescriptor.TYPE_SFIXED32): + value = _ConsumeInt32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, + descriptor.FieldDescriptor.TYPE_SINT64, + descriptor.FieldDescriptor.TYPE_SFIXED64): + value = _ConsumeInt64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, + descriptor.FieldDescriptor.TYPE_FIXED32): + value = _ConsumeUint32(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, + descriptor.FieldDescriptor.TYPE_FIXED64): + value = _ConsumeUint64(tokenizer) + elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, + descriptor.FieldDescriptor.TYPE_DOUBLE): + value = tokenizer.ConsumeFloat() + elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: + value = tokenizer.ConsumeBool() + elif field.type == descriptor.FieldDescriptor.TYPE_STRING: + value = tokenizer.ConsumeString() + elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: + value = tokenizer.ConsumeByteString() + elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: + value = tokenizer.ConsumeEnum(field) + else: + raise RuntimeError('Unknown field type %d' % field.type) + + if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if field.is_extension: + message.Extensions[field].append(value) + else: + getattr(message, field.name).append(value) + else: + if field.is_extension: + if (not self._allow_multiple_scalars and + not self._IsProto3Syntax(message) and + message.HasExtension(field)): + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" extensions.' % + (message.DESCRIPTOR.full_name, field.full_name)) + else: + message.Extensions[field] = value + else: + duplicate_error = False + if not self._allow_multiple_scalars: + if self._IsProto3Syntax(message): + # Proto3 doesn't represent presence so we try best effort to check + # multiple scalars by compare to default values. + duplicate_error = bool(getattr(message, field.name)) + else: + duplicate_error = message.HasField(field.name) + + if duplicate_error: + raise tokenizer.ParseErrorPreviousToken( + 'Message type "%s" should not have multiple "%s" fields.' % + (message.DESCRIPTOR.full_name, field.name)) + else: + setattr(message, field.name, value) + + +def _SkipFieldContents(tokenizer): + """Skips over contents (value or message) of a field. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + # Try to guess the type of this field. + # If this field is not a message, there should be a ":" between the + # field name and the field value and also the field value should not + # start with "{" or "<" which indicates the beginning of a message body. + # If there is no ":" or there is a "{" or "<" after ":", this field has + # to be a message or the input is ill-formed. + if tokenizer.TryConsume(':') and not tokenizer.LookingAt( + '{') and not tokenizer.LookingAt('<'): + _SkipFieldValue(tokenizer) + else: + _SkipFieldMessage(tokenizer) + + +def _SkipField(tokenizer): + """Skips over a complete field (name and value/message). + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + if tokenizer.TryConsume('['): + # Consume extension name. + tokenizer.ConsumeIdentifier() + while tokenizer.TryConsume('.'): + tokenizer.ConsumeIdentifier() + tokenizer.Consume(']') + else: + tokenizer.ConsumeIdentifierOrNumber() + + _SkipFieldContents(tokenizer) + + # For historical reasons, fields may optionally be separated by commas or + # semicolons. + if not tokenizer.TryConsume(','): + tokenizer.TryConsume(';') + + +def _SkipFieldMessage(tokenizer): + """Skips over a field message. + + Args: + tokenizer: A tokenizer to parse the field name and values. + """ + + if tokenizer.TryConsume('<'): + delimiter = '>' + else: + tokenizer.Consume('{') + delimiter = '}' + + while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'): + _SkipField(tokenizer) + + tokenizer.Consume(delimiter) + + +def _SkipFieldValue(tokenizer): + """Skips over a field value. + + Args: + tokenizer: A tokenizer to parse the field name and values. + + Raises: + ParseError: In case an invalid field value is found. + """ + # String/bytes tokens can come in multiple adjacent string literals. + # If we can consume one, consume as many as we can. + if tokenizer.TryConsumeByteString(): + while tokenizer.TryConsumeByteString(): + pass + return + + if (not tokenizer.TryConsumeIdentifier() and + not _TryConsumeInt64(tokenizer) and not _TryConsumeUint64(tokenizer) and + not tokenizer.TryConsumeFloat()): + raise ParseError('Invalid field value: ' + tokenizer.token) + + +class Tokenizer(object): + """Protocol buffer text representation tokenizer. + + This class handles the lower level string parsing by splitting it into + meaningful tokens. + + It was directly ported from the Java protocol buffer API. + """ + + _WHITESPACE = re.compile(r'\s+') + _COMMENT = re.compile(r'(\s*#.*$)', re.MULTILINE) + _WHITESPACE_OR_COMMENT = re.compile(r'(\s|(#.*$))+', re.MULTILINE) + _TOKEN = re.compile('|'.join([ + r'[a-zA-Z_][0-9a-zA-Z_+-]*', # an identifier + r'([0-9+-]|(\.[0-9]))[0-9a-zA-Z_.+-]*', # a number + ] + [ # quoted str for each quote mark + # Avoid backtracking! https://stackoverflow.com/a/844267 + r'{qt}[^{qt}\n\\]*((\\.)+[^{qt}\n\\]*)*({qt}|\\?$)'.format(qt=mark) + for mark in _QUOTES + ])) + + _IDENTIFIER = re.compile(r'[^\d\W]\w*') + _IDENTIFIER_OR_NUMBER = re.compile(r'\w+') + + def __init__(self, lines, skip_comments=True): + self._position = 0 + self._line = -1 + self._column = 0 + self._token_start = None + self.token = '' + self._lines = iter(lines) + self._current_line = '' + self._previous_line = 0 + self._previous_column = 0 + self._more_lines = True + self._skip_comments = skip_comments + self._whitespace_pattern = (skip_comments and self._WHITESPACE_OR_COMMENT + or self._WHITESPACE) + self._SkipWhitespace() + self.NextToken() + + def LookingAt(self, token): + return self.token == token + + def AtEnd(self): + """Checks the end of the text was reached. + + Returns: + True iff the end was reached. + """ + return not self.token + + def _PopLine(self): + while len(self._current_line) <= self._column: + try: + self._current_line = next(self._lines) + except StopIteration: + self._current_line = '' + self._more_lines = False + return + else: + self._line += 1 + self._column = 0 + + def _SkipWhitespace(self): + while True: + self._PopLine() + match = self._whitespace_pattern.match(self._current_line, self._column) + if not match: + break + length = len(match.group(0)) + self._column += length + + def TryConsume(self, token): + """Tries to consume a given piece of text. + + Args: + token: Text to consume. + + Returns: + True iff the text was consumed. + """ + if self.token == token: + self.NextToken() + return True + return False + + def Consume(self, token): + """Consumes a piece of text. + + Args: + token: Text to consume. + + Raises: + ParseError: If the text couldn't be consumed. + """ + if not self.TryConsume(token): + raise self.ParseError('Expected "%s".' % token) + + def ConsumeComment(self): + result = self.token + if not self._COMMENT.match(result): + raise self.ParseError('Expected comment.') + self.NextToken() + return result + + def ConsumeCommentOrTrailingComment(self): + """Consumes a comment, returns a 2-tuple (trailing bool, comment str).""" + + # Tokenizer initializes _previous_line and _previous_column to 0. As the + # tokenizer starts, it looks like there is a previous token on the line. + just_started = self._line == 0 and self._column == 0 + + before_parsing = self._previous_line + comment = self.ConsumeComment() + + # A trailing comment is a comment on the same line than the previous token. + trailing = (self._previous_line == before_parsing + and not just_started) + + return trailing, comment + + def TryConsumeIdentifier(self): + try: + self.ConsumeIdentifier() + return True + except ParseError: + return False + + def ConsumeIdentifier(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER.match(result): + raise self.ParseError('Expected identifier.') + self.NextToken() + return result + + def TryConsumeIdentifierOrNumber(self): + try: + self.ConsumeIdentifierOrNumber() + return True + except ParseError: + return False + + def ConsumeIdentifierOrNumber(self): + """Consumes protocol message field identifier. + + Returns: + Identifier string. + + Raises: + ParseError: If an identifier couldn't be consumed. + """ + result = self.token + if not self._IDENTIFIER_OR_NUMBER.match(result): + raise self.ParseError('Expected identifier or number, got %s.' % result) + self.NextToken() + return result + + def TryConsumeInteger(self): + try: + # Note: is_long only affects value type, not whether an error is raised. + self.ConsumeInteger() + return True + except ParseError: + return False + + def ConsumeInteger(self, is_long=False): + """Consumes an integer number. + + Args: + is_long: True if the value should be returned as a long integer. + Returns: + The integer parsed. + + Raises: + ParseError: If an integer couldn't be consumed. + """ + try: + result = _ParseAbstractInteger(self.token, is_long=is_long) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeFloat(self): + try: + self.ConsumeFloat() + return True + except ParseError: + return False + + def ConsumeFloat(self): + """Consumes an floating point number. + + Returns: + The number parsed. + + Raises: + ParseError: If a floating point number couldn't be consumed. + """ + try: + result = ParseFloat(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeBool(self): + """Consumes a boolean value. + + Returns: + The bool parsed. + + Raises: + ParseError: If a boolean value couldn't be consumed. + """ + try: + result = ParseBool(self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def TryConsumeByteString(self): + try: + self.ConsumeByteString() + return True + except ParseError: + return False + + def ConsumeString(self): + """Consumes a string value. + + Returns: + The string parsed. + + Raises: + ParseError: If a string value couldn't be consumed. + """ + the_bytes = self.ConsumeByteString() + try: + return six.text_type(the_bytes, 'utf-8') + except UnicodeDecodeError as e: + raise self._StringParseError(e) + + def ConsumeByteString(self): + """Consumes a byte array value. + + Returns: + The array parsed (as a string). + + Raises: + ParseError: If a byte array value couldn't be consumed. + """ + the_list = [self._ConsumeSingleByteString()] + while self.token and self.token[0] in _QUOTES: + the_list.append(self._ConsumeSingleByteString()) + return b''.join(the_list) + + def _ConsumeSingleByteString(self): + """Consume one token of a string literal. + + String literals (whether bytes or text) can come in multiple adjacent + tokens which are automatically concatenated, like in C or Python. This + method only consumes one token. + + Returns: + The token parsed. + Raises: + ParseError: When the wrong format data is found. + """ + text = self.token + if len(text) < 1 or text[0] not in _QUOTES: + raise self.ParseError('Expected string but found: %r' % (text,)) + + if len(text) < 2 or text[-1] != text[0]: + raise self.ParseError('String missing ending quote: %r' % (text,)) + + try: + result = text_encoding.CUnescape(text[1:-1]) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ConsumeEnum(self, field): + try: + result = ParseEnum(field, self.token) + except ValueError as e: + raise self.ParseError(str(e)) + self.NextToken() + return result + + def ParseErrorPreviousToken(self, message): + """Creates and *returns* a ParseError for the previously read token. + + Args: + message: A message to set for the exception. + + Returns: + A ParseError instance. + """ + return ParseError(message, self._previous_line + 1, + self._previous_column + 1) + + def ParseError(self, message): + """Creates and *returns* a ParseError for the current token.""" + return ParseError('\'' + self._current_line + '\': ' + message, + self._line + 1, self._column + 1) + + def _StringParseError(self, e): + return self.ParseError('Couldn\'t parse string: ' + str(e)) + + def NextToken(self): + """Reads the next meaningful token.""" + self._previous_line = self._line + self._previous_column = self._column + + self._column += len(self.token) + self._SkipWhitespace() + + if not self._more_lines: + self.token = '' + return + + match = self._TOKEN.match(self._current_line, self._column) + if not match and not self._skip_comments: + match = self._COMMENT.match(self._current_line, self._column) + if match: + token = match.group(0) + self.token = token + else: + self.token = self._current_line[self._column] + +# Aliased so it can still be accessed by current visibility violators. +# TODO(dbarnett): Migrate violators to textformat_tokenizer. +_Tokenizer = Tokenizer # pylint: disable=invalid-name + + +def _ConsumeInt32(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=False) + + +def _ConsumeUint32(tokenizer): + """Consumes an unsigned 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=False) + + +def _TryConsumeInt64(tokenizer): + try: + _ConsumeInt64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeInt64(tokenizer): + """Consumes a signed 32bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If a signed 32bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=True, is_long=True) + + +def _TryConsumeUint64(tokenizer): + try: + _ConsumeUint64(tokenizer) + return True + except ParseError: + return False + + +def _ConsumeUint64(tokenizer): + """Consumes an unsigned 64bit integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + + Returns: + The integer parsed. + + Raises: + ParseError: If an unsigned 64bit integer couldn't be consumed. + """ + return _ConsumeInteger(tokenizer, is_signed=False, is_long=True) + + +def _TryConsumeInteger(tokenizer, is_signed=False, is_long=False): + try: + _ConsumeInteger(tokenizer, is_signed=is_signed, is_long=is_long) + return True + except ParseError: + return False + + +def _ConsumeInteger(tokenizer, is_signed=False, is_long=False): + """Consumes an integer number from tokenizer. + + Args: + tokenizer: A tokenizer used to parse the number. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer parsed. + + Raises: + ParseError: If an integer with given characteristics couldn't be consumed. + """ + try: + result = ParseInteger(tokenizer.token, is_signed=is_signed, is_long=is_long) + except ValueError as e: + raise tokenizer.ParseError(str(e)) + tokenizer.NextToken() + return result + + +def ParseInteger(text, is_signed=False, is_long=False): + """Parses an integer. + + Args: + text: The text to parse. + is_signed: True if a signed integer must be parsed. + is_long: True if a long integer must be parsed. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + result = _ParseAbstractInteger(text, is_long=is_long) + + # Check if the integer is sane. Exceptions handled by callers. + checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] + checker.CheckValue(result) + return result + + +def _ParseAbstractInteger(text, is_long=False): + """Parses an integer without checking size/signedness. + + Args: + text: The text to parse. + is_long: True if the value should be returned as a long integer. + + Returns: + The integer value. + + Raises: + ValueError: Thrown Iff the text is not a valid integer. + """ + # Do the actual parsing. Exception handling is propagated to caller. + orig_text = text + c_octal_match = re.match(r'(-?)0(\d+)$', text) + if c_octal_match: + # Python 3 no longer supports 0755 octal syntax without the 'o', so + # we always use the '0o' prefix for multi-digit numbers starting with 0. + text = c_octal_match.group(1) + '0o' + c_octal_match.group(2) + try: + # We force 32-bit values to int and 64-bit values to long to make + # alternate implementations where the distinction is more significant + # (e.g. the C++ implementation) simpler. + if is_long: + return long(text, 0) + else: + return int(text, 0) + except ValueError: + raise ValueError('Couldn\'t parse integer: %s' % orig_text) + + +def ParseFloat(text): + """Parse a floating point number. + + Args: + text: Text to parse. + + Returns: + The number parsed. + + Raises: + ValueError: If a floating point number couldn't be parsed. + """ + try: + # Assume Python compatible syntax. + return float(text) + except ValueError: + # Check alternative spellings. + if _FLOAT_INFINITY.match(text): + if text[0] == '-': + return float('-inf') + else: + return float('inf') + elif _FLOAT_NAN.match(text): + return float('nan') + else: + # assume '1.0f' format + try: + return float(text.rstrip('f')) + except ValueError: + raise ValueError('Couldn\'t parse float: %s' % text) + + +def ParseBool(text): + """Parse a boolean value. + + Args: + text: Text to parse. + + Returns: + Boolean values parsed + + Raises: + ValueError: If text is not a valid boolean. + """ + if text in ('true', 't', '1', 'True'): + return True + elif text in ('false', 'f', '0', 'False'): + return False + else: + raise ValueError('Expected "true" or "false".') + + +def ParseEnum(field, value): + """Parse an enum value. + + The value can be specified by a number (the enum value), or by + a string literal (the enum name). + + Args: + field: Enum field descriptor. + value: String value. + + Returns: + Enum value number. + + Raises: + ValueError: If the enum value could not be parsed. + """ + enum_descriptor = field.enum_type + try: + number = int(value, 0) + except ValueError: + # Identifier. + enum_value = enum_descriptor.values_by_name.get(value, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value named %s.' % + (enum_descriptor.full_name, value)) + else: + # Numeric value. + if hasattr(field.file, 'syntax'): + # Attribute is checked for compatibility. + if field.file.syntax == 'proto3': + # Proto3 accept numeric unknown enums. + return number + enum_value = enum_descriptor.values_by_number.get(number, None) + if enum_value is None: + raise ValueError('Enum type "%s" has no value with number %d.' % + (enum_descriptor.full_name, number)) + return enum_value.number diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/timestamp_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/timestamp_pb2.py new file mode 100644 index 00000000..6fb22d2c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/timestamp_pb2.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/timestamp.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/timestamp.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\016TimestampProtoP\001Z2google.golang.org/protobuf/types/known/timestamppb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x1fgoogle/protobuf/timestamp.proto\x12\x0fgoogle.protobuf\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x42\x85\x01\n\x13\x63om.google.protobufB\x0eTimestampProtoP\x01Z2google.golang.org/protobuf/types/known/timestamppb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_TIMESTAMP = _descriptor.Descriptor( + name='Timestamp', + full_name='google.protobuf.Timestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='seconds', full_name='google.protobuf.Timestamp.seconds', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='nanos', full_name='google.protobuf.Timestamp.nanos', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=52, + serialized_end=95, +) + +DESCRIPTOR.message_types_by_name['Timestamp'] = _TIMESTAMP +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Timestamp = _reflection.GeneratedProtocolMessageType('Timestamp', (_message.Message,), { + 'DESCRIPTOR' : _TIMESTAMP, + '__module__' : 'google.protobuf.timestamp_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) + }) +_sym_db.RegisterMessage(Timestamp) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/type_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/type_pb2.py new file mode 100644 index 00000000..bec1a1e1 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/type_pb2.py @@ -0,0 +1,573 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/type.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import source_context_pb2 as google_dot_protobuf_dot_source__context__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/type.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\tTypeProtoP\001Z-google.golang.org/protobuf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x1agoogle/protobuf/type.proto\x12\x0fgoogle.protobuf\x1a\x19google/protobuf/any.proto\x1a$google/protobuf/source_context.proto\"\xd7\x01\n\x04Type\x12\x0c\n\x04name\x18\x01 \x01(\t\x12&\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Field\x12\x0e\n\x06oneofs\x18\x03 \x03(\t\x12(\n\x07options\x18\x04 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x05 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x06 \x01(\x0e\x32\x17.google.protobuf.Syntax\"\xd5\x05\n\x05\x46ield\x12)\n\x04kind\x18\x01 \x01(\x0e\x32\x1b.google.protobuf.Field.Kind\x12\x37\n\x0b\x63\x61rdinality\x18\x02 \x01(\x0e\x32\".google.protobuf.Field.Cardinality\x12\x0e\n\x06number\x18\x03 \x01(\x05\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x10\n\x08type_url\x18\x06 \x01(\t\x12\x13\n\x0boneof_index\x18\x07 \x01(\x05\x12\x0e\n\x06packed\x18\x08 \x01(\x08\x12(\n\x07options\x18\t \x03(\x0b\x32\x17.google.protobuf.Option\x12\x11\n\tjson_name\x18\n \x01(\t\x12\x15\n\rdefault_value\x18\x0b \x01(\t\"\xc8\x02\n\x04Kind\x12\x10\n\x0cTYPE_UNKNOWN\x10\x00\x12\x0f\n\x0bTYPE_DOUBLE\x10\x01\x12\x0e\n\nTYPE_FLOAT\x10\x02\x12\x0e\n\nTYPE_INT64\x10\x03\x12\x0f\n\x0bTYPE_UINT64\x10\x04\x12\x0e\n\nTYPE_INT32\x10\x05\x12\x10\n\x0cTYPE_FIXED64\x10\x06\x12\x10\n\x0cTYPE_FIXED32\x10\x07\x12\r\n\tTYPE_BOOL\x10\x08\x12\x0f\n\x0bTYPE_STRING\x10\t\x12\x0e\n\nTYPE_GROUP\x10\n\x12\x10\n\x0cTYPE_MESSAGE\x10\x0b\x12\x0e\n\nTYPE_BYTES\x10\x0c\x12\x0f\n\x0bTYPE_UINT32\x10\r\x12\r\n\tTYPE_ENUM\x10\x0e\x12\x11\n\rTYPE_SFIXED32\x10\x0f\x12\x11\n\rTYPE_SFIXED64\x10\x10\x12\x0f\n\x0bTYPE_SINT32\x10\x11\x12\x0f\n\x0bTYPE_SINT64\x10\x12\"t\n\x0b\x43\x61rdinality\x12\x17\n\x13\x43\x41RDINALITY_UNKNOWN\x10\x00\x12\x18\n\x14\x43\x41RDINALITY_OPTIONAL\x10\x01\x12\x18\n\x14\x43\x41RDINALITY_REQUIRED\x10\x02\x12\x18\n\x14\x43\x41RDINALITY_REPEATED\x10\x03\"\xce\x01\n\x04\x45num\x12\x0c\n\x04name\x18\x01 \x01(\t\x12-\n\tenumvalue\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.EnumValue\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\x12\x36\n\x0esource_context\x18\x04 \x01(\x0b\x32\x1e.google.protobuf.SourceContext\x12\'\n\x06syntax\x18\x05 \x01(\x0e\x32\x17.google.protobuf.Syntax\"S\n\tEnumValue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0e\n\x06number\x18\x02 \x01(\x05\x12(\n\x07options\x18\x03 \x03(\x0b\x32\x17.google.protobuf.Option\";\n\x06Option\x12\x0c\n\x04name\x18\x01 \x01(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.google.protobuf.Any*.\n\x06Syntax\x12\x11\n\rSYNTAX_PROTO2\x10\x00\x12\x11\n\rSYNTAX_PROTO3\x10\x01\x42{\n\x13\x63om.google.protobufB\tTypeProtoP\x01Z-google.golang.org/protobuf/types/known/typepb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_source__context__pb2.DESCRIPTOR,]) + +_SYNTAX = _descriptor.EnumDescriptor( + name='Syntax', + full_name='google.protobuf.Syntax', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO2', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SYNTAX_PROTO3', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1413, + serialized_end=1459, +) +_sym_db.RegisterEnumDescriptor(_SYNTAX) + +Syntax = enum_type_wrapper.EnumTypeWrapper(_SYNTAX) +SYNTAX_PROTO2 = 0 +SYNTAX_PROTO3 = 1 + + +_FIELD_KIND = _descriptor.EnumDescriptor( + name='Kind', + full_name='google.protobuf.Field.Kind', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='TYPE_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_DOUBLE', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FLOAT', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_INT64', index=3, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT64', index=4, number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_INT32', index=5, number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED64', index=6, number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_FIXED32', index=7, number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_BOOL', index=8, number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_STRING', index=9, number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_GROUP', index=10, number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_MESSAGE', index=11, number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_BYTES', index=12, number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_UINT32', index=13, number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_ENUM', index=14, number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED32', index=15, number=15, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SFIXED64', index=16, number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT32', index=17, number=17, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TYPE_SINT64', index=18, number=18, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=610, + serialized_end=938, +) +_sym_db.RegisterEnumDescriptor(_FIELD_KIND) + +_FIELD_CARDINALITY = _descriptor.EnumDescriptor( + name='Cardinality', + full_name='google.protobuf.Field.Cardinality', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='CARDINALITY_UNKNOWN', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_OPTIONAL', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REQUIRED', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CARDINALITY_REPEATED', index=3, number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=940, + serialized_end=1056, +) +_sym_db.RegisterEnumDescriptor(_FIELD_CARDINALITY) + + +_TYPE = _descriptor.Descriptor( + name='Type', + full_name='google.protobuf.Type', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Type.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fields', full_name='google.protobuf.Type.fields', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneofs', full_name='google.protobuf.Type.oneofs', index=2, + number=3, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Type.options', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Type.source_context', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Type.syntax', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=113, + serialized_end=328, +) + + +_FIELD = _descriptor.Descriptor( + name='Field', + full_name='google.protobuf.Field', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='kind', full_name='google.protobuf.Field.kind', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cardinality', full_name='google.protobuf.Field.cardinality', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.Field.number', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Field.name', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type_url', full_name='google.protobuf.Field.type_url', index=4, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_index', full_name='google.protobuf.Field.oneof_index', index=5, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='packed', full_name='google.protobuf.Field.packed', index=6, + number=8, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Field.options', index=7, + number=9, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='json_name', full_name='google.protobuf.Field.json_name', index=8, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='default_value', full_name='google.protobuf.Field.default_value', index=9, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _FIELD_KIND, + _FIELD_CARDINALITY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=331, + serialized_end=1056, +) + + +_ENUM = _descriptor.Descriptor( + name='Enum', + full_name='google.protobuf.Enum', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Enum.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enumvalue', full_name='google.protobuf.Enum.enumvalue', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.Enum.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='source_context', full_name='google.protobuf.Enum.source_context', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='syntax', full_name='google.protobuf.Enum.syntax', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1059, + serialized_end=1265, +) + + +_ENUMVALUE = _descriptor.Descriptor( + name='EnumValue', + full_name='google.protobuf.EnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.EnumValue.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', full_name='google.protobuf.EnumValue.number', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', full_name='google.protobuf.EnumValue.options', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1267, + serialized_end=1350, +) + + +_OPTION = _descriptor.Descriptor( + name='Option', + full_name='google.protobuf.Option', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='google.protobuf.Option.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Option.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1352, + serialized_end=1411, +) + +_TYPE.fields_by_name['fields'].message_type = _FIELD +_TYPE.fields_by_name['options'].message_type = _OPTION +_TYPE.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_TYPE.fields_by_name['syntax'].enum_type = _SYNTAX +_FIELD.fields_by_name['kind'].enum_type = _FIELD_KIND +_FIELD.fields_by_name['cardinality'].enum_type = _FIELD_CARDINALITY +_FIELD.fields_by_name['options'].message_type = _OPTION +_FIELD_KIND.containing_type = _FIELD +_FIELD_CARDINALITY.containing_type = _FIELD +_ENUM.fields_by_name['enumvalue'].message_type = _ENUMVALUE +_ENUM.fields_by_name['options'].message_type = _OPTION +_ENUM.fields_by_name['source_context'].message_type = google_dot_protobuf_dot_source__context__pb2._SOURCECONTEXT +_ENUM.fields_by_name['syntax'].enum_type = _SYNTAX +_ENUMVALUE.fields_by_name['options'].message_type = _OPTION +_OPTION.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +DESCRIPTOR.message_types_by_name['Type'] = _TYPE +DESCRIPTOR.message_types_by_name['Field'] = _FIELD +DESCRIPTOR.message_types_by_name['Enum'] = _ENUM +DESCRIPTOR.message_types_by_name['EnumValue'] = _ENUMVALUE +DESCRIPTOR.message_types_by_name['Option'] = _OPTION +DESCRIPTOR.enum_types_by_name['Syntax'] = _SYNTAX +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Type = _reflection.GeneratedProtocolMessageType('Type', (_message.Message,), { + 'DESCRIPTOR' : _TYPE, + '__module__' : 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Type) + }) +_sym_db.RegisterMessage(Type) + +Field = _reflection.GeneratedProtocolMessageType('Field', (_message.Message,), { + 'DESCRIPTOR' : _FIELD, + '__module__' : 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Field) + }) +_sym_db.RegisterMessage(Field) + +Enum = _reflection.GeneratedProtocolMessageType('Enum', (_message.Message,), { + 'DESCRIPTOR' : _ENUM, + '__module__' : 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Enum) + }) +_sym_db.RegisterMessage(Enum) + +EnumValue = _reflection.GeneratedProtocolMessageType('EnumValue', (_message.Message,), { + 'DESCRIPTOR' : _ENUMVALUE, + '__module__' : 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.EnumValue) + }) +_sym_db.RegisterMessage(EnumValue) + +Option = _reflection.GeneratedProtocolMessageType('Option', (_message.Message,), { + 'DESCRIPTOR' : _OPTION, + '__module__' : 'google.protobuf.type_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Option) + }) +_sym_db.RegisterMessage(Option) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/__init__.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_pb2.py new file mode 100644 index 00000000..72be1609 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_pb2.py @@ -0,0 +1,983 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/util/json_format.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/util/json_format.proto', + package='protobuf_unittest', + syntax='proto2', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n&google/protobuf/util/json_format.proto\x12\x11protobuf_unittest\"\x89\x01\n\x13TestFlagsAndStrings\x12\t\n\x01\x41\x18\x01 \x02(\x05\x12K\n\rrepeatedgroup\x18\x02 \x03(\n24.protobuf_unittest.TestFlagsAndStrings.RepeatedGroup\x1a\x1a\n\rRepeatedGroup\x12\t\n\x01\x66\x18\x03 \x02(\t\"!\n\x14TestBase64ByteArrays\x12\t\n\x01\x61\x18\x01 \x02(\x0c\"G\n\x12TestJavaScriptJSON\x12\t\n\x01\x61\x18\x01 \x01(\x05\x12\r\n\x05\x66inal\x18\x02 \x01(\x02\x12\n\n\x02in\x18\x03 \x01(\t\x12\x0b\n\x03Var\x18\x04 \x01(\t\"Q\n\x18TestJavaScriptOrderJSON1\x12\t\n\x01\x64\x18\x01 \x01(\x05\x12\t\n\x01\x63\x18\x02 \x01(\x05\x12\t\n\x01x\x18\x03 \x01(\x08\x12\t\n\x01\x62\x18\x04 \x01(\x05\x12\t\n\x01\x61\x18\x05 \x01(\x05\"\x89\x01\n\x18TestJavaScriptOrderJSON2\x12\t\n\x01\x64\x18\x01 \x01(\x05\x12\t\n\x01\x63\x18\x02 \x01(\x05\x12\t\n\x01x\x18\x03 \x01(\x08\x12\t\n\x01\x62\x18\x04 \x01(\x05\x12\t\n\x01\x61\x18\x05 \x01(\x05\x12\x36\n\x01z\x18\x06 \x03(\x0b\x32+.protobuf_unittest.TestJavaScriptOrderJSON1\"$\n\x0cTestLargeInt\x12\t\n\x01\x61\x18\x01 \x02(\x03\x12\t\n\x01\x62\x18\x02 \x02(\x04\"\xa0\x01\n\x0bTestNumbers\x12\x30\n\x01\x61\x18\x01 \x01(\x0e\x32%.protobuf_unittest.TestNumbers.MyType\x12\t\n\x01\x62\x18\x02 \x01(\x05\x12\t\n\x01\x63\x18\x03 \x01(\x02\x12\t\n\x01\x64\x18\x04 \x01(\x08\x12\t\n\x01\x65\x18\x05 \x01(\x01\x12\t\n\x01\x66\x18\x06 \x01(\r\"(\n\x06MyType\x12\x06\n\x02OK\x10\x00\x12\x0b\n\x07WARNING\x10\x01\x12\t\n\x05\x45RROR\x10\x02\"T\n\rTestCamelCase\x12\x14\n\x0cnormal_field\x18\x01 \x01(\t\x12\x15\n\rCAPITAL_FIELD\x18\x02 \x01(\x05\x12\x16\n\x0e\x43\x61melCaseField\x18\x03 \x01(\x05\"|\n\x0bTestBoolMap\x12=\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32+.protobuf_unittest.TestBoolMap.BoolMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"O\n\rTestRecursion\x12\r\n\x05value\x18\x01 \x01(\x05\x12/\n\x05\x63hild\x18\x02 \x01(\x0b\x32 .protobuf_unittest.TestRecursion\"\x86\x01\n\rTestStringMap\x12\x43\n\nstring_map\x18\x01 \x03(\x0b\x32/.protobuf_unittest.TestStringMap.StringMapEntry\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xc4\x01\n\x14TestStringSerializer\x12\x15\n\rscalar_string\x18\x01 \x01(\t\x12\x17\n\x0frepeated_string\x18\x02 \x03(\t\x12J\n\nstring_map\x18\x03 \x03(\x0b\x32\x36.protobuf_unittest.TestStringSerializer.StringMapEntry\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"$\n\x18TestMessageWithExtension*\x08\x08\x64\x10\x80\x80\x80\x80\x02\"z\n\rTestExtension\x12\r\n\x05value\x18\x01 \x01(\t2Z\n\x03\x65xt\x12+.protobuf_unittest.TestMessageWithExtension\x18\x64 \x01(\x0b\x32 .protobuf_unittest.TestExtension' +) + + + +_TESTNUMBERS_MYTYPE = _descriptor.EnumDescriptor( + name='MyType', + full_name='protobuf_unittest.TestNumbers.MyType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='OK', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='WARNING', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ERROR', index=2, number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=691, + serialized_end=731, +) +_sym_db.RegisterEnumDescriptor(_TESTNUMBERS_MYTYPE) + + +_TESTFLAGSANDSTRINGS_REPEATEDGROUP = _descriptor.Descriptor( + name='RepeatedGroup', + full_name='protobuf_unittest.TestFlagsAndStrings.RepeatedGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='f', full_name='protobuf_unittest.TestFlagsAndStrings.RepeatedGroup.f', index=0, + number=3, type=9, cpp_type=9, label=2, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=173, + serialized_end=199, +) + +_TESTFLAGSANDSTRINGS = _descriptor.Descriptor( + name='TestFlagsAndStrings', + full_name='protobuf_unittest.TestFlagsAndStrings', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='A', full_name='protobuf_unittest.TestFlagsAndStrings.A', index=0, + number=1, type=5, cpp_type=1, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeatedgroup', full_name='protobuf_unittest.TestFlagsAndStrings.repeatedgroup', index=1, + number=2, type=10, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTFLAGSANDSTRINGS_REPEATEDGROUP, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=62, + serialized_end=199, +) + + +_TESTBASE64BYTEARRAYS = _descriptor.Descriptor( + name='TestBase64ByteArrays', + full_name='protobuf_unittest.TestBase64ByteArrays', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestBase64ByteArrays.a', index=0, + number=1, type=12, cpp_type=9, label=2, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=201, + serialized_end=234, +) + + +_TESTJAVASCRIPTJSON = _descriptor.Descriptor( + name='TestJavaScriptJSON', + full_name='protobuf_unittest.TestJavaScriptJSON', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestJavaScriptJSON.a', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='final', full_name='protobuf_unittest.TestJavaScriptJSON.final', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='in', full_name='protobuf_unittest.TestJavaScriptJSON.in', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='Var', full_name='protobuf_unittest.TestJavaScriptJSON.Var', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=236, + serialized_end=307, +) + + +_TESTJAVASCRIPTORDERJSON1 = _descriptor.Descriptor( + name='TestJavaScriptOrderJSON1', + full_name='protobuf_unittest.TestJavaScriptOrderJSON1', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest.TestJavaScriptOrderJSON1.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.TestJavaScriptOrderJSON1.c', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='x', full_name='protobuf_unittest.TestJavaScriptOrderJSON1.x', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestJavaScriptOrderJSON1.b', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestJavaScriptOrderJSON1.a', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=309, + serialized_end=390, +) + + +_TESTJAVASCRIPTORDERJSON2 = _descriptor.Descriptor( + name='TestJavaScriptOrderJSON2', + full_name='protobuf_unittest.TestJavaScriptOrderJSON2', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.d', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.c', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='x', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.x', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.b', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.a', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='z', full_name='protobuf_unittest.TestJavaScriptOrderJSON2.z', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=393, + serialized_end=530, +) + + +_TESTLARGEINT = _descriptor.Descriptor( + name='TestLargeInt', + full_name='protobuf_unittest.TestLargeInt', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestLargeInt.a', index=0, + number=1, type=3, cpp_type=2, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestLargeInt.b', index=1, + number=2, type=4, cpp_type=4, label=2, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=532, + serialized_end=568, +) + + +_TESTNUMBERS = _descriptor.Descriptor( + name='TestNumbers', + full_name='protobuf_unittest.TestNumbers', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='a', full_name='protobuf_unittest.TestNumbers.a', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='b', full_name='protobuf_unittest.TestNumbers.b', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='c', full_name='protobuf_unittest.TestNumbers.c', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='d', full_name='protobuf_unittest.TestNumbers.d', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='e', full_name='protobuf_unittest.TestNumbers.e', index=4, + number=5, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='f', full_name='protobuf_unittest.TestNumbers.f', index=5, + number=6, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _TESTNUMBERS_MYTYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=571, + serialized_end=731, +) + + +_TESTCAMELCASE = _descriptor.Descriptor( + name='TestCamelCase', + full_name='protobuf_unittest.TestCamelCase', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='normal_field', full_name='protobuf_unittest.TestCamelCase.normal_field', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='CAPITAL_FIELD', full_name='protobuf_unittest.TestCamelCase.CAPITAL_FIELD', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='CamelCaseField', full_name='protobuf_unittest.TestCamelCase.CamelCaseField', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=733, + serialized_end=817, +) + + +_TESTBOOLMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='protobuf_unittest.TestBoolMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestBoolMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestBoolMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=897, + serialized_end=943, +) + +_TESTBOOLMAP = _descriptor.Descriptor( + name='TestBoolMap', + full_name='protobuf_unittest.TestBoolMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='protobuf_unittest.TestBoolMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTBOOLMAP_BOOLMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=819, + serialized_end=943, +) + + +_TESTRECURSION = _descriptor.Descriptor( + name='TestRecursion', + full_name='protobuf_unittest.TestRecursion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestRecursion.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='child', full_name='protobuf_unittest.TestRecursion.child', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=945, + serialized_end=1024, +) + + +_TESTSTRINGMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='protobuf_unittest.TestStringMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestStringMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestStringMap.StringMapEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1113, + serialized_end=1161, +) + +_TESTSTRINGMAP = _descriptor.Descriptor( + name='TestStringMap', + full_name='protobuf_unittest.TestStringMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='string_map', full_name='protobuf_unittest.TestStringMap.string_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTSTRINGMAP_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1027, + serialized_end=1161, +) + + +_TESTSTRINGSERIALIZER_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='protobuf_unittest.TestStringSerializer.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='protobuf_unittest.TestStringSerializer.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestStringSerializer.StringMapEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1113, + serialized_end=1161, +) + +_TESTSTRINGSERIALIZER = _descriptor.Descriptor( + name='TestStringSerializer', + full_name='protobuf_unittest.TestStringSerializer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='scalar_string', full_name='protobuf_unittest.TestStringSerializer.scalar_string', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_string', full_name='protobuf_unittest.TestStringSerializer.repeated_string', index=1, + number=2, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_map', full_name='protobuf_unittest.TestStringSerializer.string_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTSTRINGSERIALIZER_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1164, + serialized_end=1360, +) + + +_TESTMESSAGEWITHEXTENSION = _descriptor.Descriptor( + name='TestMessageWithExtension', + full_name='protobuf_unittest.TestMessageWithExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=True, + syntax='proto2', + extension_ranges=[(100, 536870912), ], + oneofs=[ + ], + serialized_start=1362, + serialized_end=1398, +) + + +_TESTEXTENSION = _descriptor.Descriptor( + name='TestExtension', + full_name='protobuf_unittest.TestExtension', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='protobuf_unittest.TestExtension.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + _descriptor.FieldDescriptor( + name='ext', full_name='protobuf_unittest.TestExtension.ext', index=0, + number=100, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1400, + serialized_end=1522, +) + +_TESTFLAGSANDSTRINGS_REPEATEDGROUP.containing_type = _TESTFLAGSANDSTRINGS +_TESTFLAGSANDSTRINGS.fields_by_name['repeatedgroup'].message_type = _TESTFLAGSANDSTRINGS_REPEATEDGROUP +_TESTJAVASCRIPTORDERJSON2.fields_by_name['z'].message_type = _TESTJAVASCRIPTORDERJSON1 +_TESTNUMBERS.fields_by_name['a'].enum_type = _TESTNUMBERS_MYTYPE +_TESTNUMBERS_MYTYPE.containing_type = _TESTNUMBERS +_TESTBOOLMAP_BOOLMAPENTRY.containing_type = _TESTBOOLMAP +_TESTBOOLMAP.fields_by_name['bool_map'].message_type = _TESTBOOLMAP_BOOLMAPENTRY +_TESTRECURSION.fields_by_name['child'].message_type = _TESTRECURSION +_TESTSTRINGMAP_STRINGMAPENTRY.containing_type = _TESTSTRINGMAP +_TESTSTRINGMAP.fields_by_name['string_map'].message_type = _TESTSTRINGMAP_STRINGMAPENTRY +_TESTSTRINGSERIALIZER_STRINGMAPENTRY.containing_type = _TESTSTRINGSERIALIZER +_TESTSTRINGSERIALIZER.fields_by_name['string_map'].message_type = _TESTSTRINGSERIALIZER_STRINGMAPENTRY +DESCRIPTOR.message_types_by_name['TestFlagsAndStrings'] = _TESTFLAGSANDSTRINGS +DESCRIPTOR.message_types_by_name['TestBase64ByteArrays'] = _TESTBASE64BYTEARRAYS +DESCRIPTOR.message_types_by_name['TestJavaScriptJSON'] = _TESTJAVASCRIPTJSON +DESCRIPTOR.message_types_by_name['TestJavaScriptOrderJSON1'] = _TESTJAVASCRIPTORDERJSON1 +DESCRIPTOR.message_types_by_name['TestJavaScriptOrderJSON2'] = _TESTJAVASCRIPTORDERJSON2 +DESCRIPTOR.message_types_by_name['TestLargeInt'] = _TESTLARGEINT +DESCRIPTOR.message_types_by_name['TestNumbers'] = _TESTNUMBERS +DESCRIPTOR.message_types_by_name['TestCamelCase'] = _TESTCAMELCASE +DESCRIPTOR.message_types_by_name['TestBoolMap'] = _TESTBOOLMAP +DESCRIPTOR.message_types_by_name['TestRecursion'] = _TESTRECURSION +DESCRIPTOR.message_types_by_name['TestStringMap'] = _TESTSTRINGMAP +DESCRIPTOR.message_types_by_name['TestStringSerializer'] = _TESTSTRINGSERIALIZER +DESCRIPTOR.message_types_by_name['TestMessageWithExtension'] = _TESTMESSAGEWITHEXTENSION +DESCRIPTOR.message_types_by_name['TestExtension'] = _TESTEXTENSION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TestFlagsAndStrings = _reflection.GeneratedProtocolMessageType('TestFlagsAndStrings', (_message.Message,), { + + 'RepeatedGroup' : _reflection.GeneratedProtocolMessageType('RepeatedGroup', (_message.Message,), { + 'DESCRIPTOR' : _TESTFLAGSANDSTRINGS_REPEATEDGROUP, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFlagsAndStrings.RepeatedGroup) + }) + , + 'DESCRIPTOR' : _TESTFLAGSANDSTRINGS, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestFlagsAndStrings) + }) +_sym_db.RegisterMessage(TestFlagsAndStrings) +_sym_db.RegisterMessage(TestFlagsAndStrings.RepeatedGroup) + +TestBase64ByteArrays = _reflection.GeneratedProtocolMessageType('TestBase64ByteArrays', (_message.Message,), { + 'DESCRIPTOR' : _TESTBASE64BYTEARRAYS, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestBase64ByteArrays) + }) +_sym_db.RegisterMessage(TestBase64ByteArrays) + +TestJavaScriptJSON = _reflection.GeneratedProtocolMessageType('TestJavaScriptJSON', (_message.Message,), { + 'DESCRIPTOR' : _TESTJAVASCRIPTJSON, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestJavaScriptJSON) + }) +_sym_db.RegisterMessage(TestJavaScriptJSON) + +TestJavaScriptOrderJSON1 = _reflection.GeneratedProtocolMessageType('TestJavaScriptOrderJSON1', (_message.Message,), { + 'DESCRIPTOR' : _TESTJAVASCRIPTORDERJSON1, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestJavaScriptOrderJSON1) + }) +_sym_db.RegisterMessage(TestJavaScriptOrderJSON1) + +TestJavaScriptOrderJSON2 = _reflection.GeneratedProtocolMessageType('TestJavaScriptOrderJSON2', (_message.Message,), { + 'DESCRIPTOR' : _TESTJAVASCRIPTORDERJSON2, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestJavaScriptOrderJSON2) + }) +_sym_db.RegisterMessage(TestJavaScriptOrderJSON2) + +TestLargeInt = _reflection.GeneratedProtocolMessageType('TestLargeInt', (_message.Message,), { + 'DESCRIPTOR' : _TESTLARGEINT, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestLargeInt) + }) +_sym_db.RegisterMessage(TestLargeInt) + +TestNumbers = _reflection.GeneratedProtocolMessageType('TestNumbers', (_message.Message,), { + 'DESCRIPTOR' : _TESTNUMBERS, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestNumbers) + }) +_sym_db.RegisterMessage(TestNumbers) + +TestCamelCase = _reflection.GeneratedProtocolMessageType('TestCamelCase', (_message.Message,), { + 'DESCRIPTOR' : _TESTCAMELCASE, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestCamelCase) + }) +_sym_db.RegisterMessage(TestCamelCase) + +TestBoolMap = _reflection.GeneratedProtocolMessageType('TestBoolMap', (_message.Message,), { + + 'BoolMapEntry' : _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTBOOLMAP_BOOLMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestBoolMap.BoolMapEntry) + }) + , + 'DESCRIPTOR' : _TESTBOOLMAP, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestBoolMap) + }) +_sym_db.RegisterMessage(TestBoolMap) +_sym_db.RegisterMessage(TestBoolMap.BoolMapEntry) + +TestRecursion = _reflection.GeneratedProtocolMessageType('TestRecursion', (_message.Message,), { + 'DESCRIPTOR' : _TESTRECURSION, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestRecursion) + }) +_sym_db.RegisterMessage(TestRecursion) + +TestStringMap = _reflection.GeneratedProtocolMessageType('TestStringMap', (_message.Message,), { + + 'StringMapEntry' : _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTSTRINGMAP_STRINGMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestStringMap.StringMapEntry) + }) + , + 'DESCRIPTOR' : _TESTSTRINGMAP, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestStringMap) + }) +_sym_db.RegisterMessage(TestStringMap) +_sym_db.RegisterMessage(TestStringMap.StringMapEntry) + +TestStringSerializer = _reflection.GeneratedProtocolMessageType('TestStringSerializer', (_message.Message,), { + + 'StringMapEntry' : _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTSTRINGSERIALIZER_STRINGMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestStringSerializer.StringMapEntry) + }) + , + 'DESCRIPTOR' : _TESTSTRINGSERIALIZER, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestStringSerializer) + }) +_sym_db.RegisterMessage(TestStringSerializer) +_sym_db.RegisterMessage(TestStringSerializer.StringMapEntry) + +TestMessageWithExtension = _reflection.GeneratedProtocolMessageType('TestMessageWithExtension', (_message.Message,), { + 'DESCRIPTOR' : _TESTMESSAGEWITHEXTENSION, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestMessageWithExtension) + }) +_sym_db.RegisterMessage(TestMessageWithExtension) + +TestExtension = _reflection.GeneratedProtocolMessageType('TestExtension', (_message.Message,), { + 'DESCRIPTOR' : _TESTEXTENSION, + '__module__' : 'google.protobuf.util.json_format_pb2' + # @@protoc_insertion_point(class_scope:protobuf_unittest.TestExtension) + }) +_sym_db.RegisterMessage(TestExtension) + +_TESTEXTENSION.extensions_by_name['ext'].message_type = _TESTEXTENSION +TestMessageWithExtension.RegisterExtension(_TESTEXTENSION.extensions_by_name['ext']) + +_TESTBOOLMAP_BOOLMAPENTRY._options = None +_TESTSTRINGMAP_STRINGMAPENTRY._options = None +_TESTSTRINGSERIALIZER_STRINGMAPENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_proto3_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_proto3_pb2.py new file mode 100644 index 00000000..c3d4e484 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/util/json_format_proto3_pb2.py @@ -0,0 +1,2031 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/util/json_format_proto3.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import any_pb2 as google_dot_protobuf_dot_any__pb2 +from google.protobuf import duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import field_mask_pb2 as google_dot_protobuf_dot_field__mask__pb2 +from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2 +from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 +from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2 +from google.protobuf import unittest_pb2 as google_dot_protobuf_dot_unittest__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/util/json_format_proto3.proto', + package='proto3', + syntax='proto3', + serialized_options=b'\n\030com.google.protobuf.utilB\020JsonFormatProto3', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n-google/protobuf/util/json_format_proto3.proto\x12\x06proto3\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\x1a google/protobuf/field_mask.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1egoogle/protobuf/unittest.proto\"\x1c\n\x0bMessageType\x12\r\n\x05value\x18\x01 \x01(\x05\"\x94\x05\n\x0bTestMessage\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x13\n\x0bint32_value\x18\x02 \x01(\x05\x12\x13\n\x0bint64_value\x18\x03 \x01(\x03\x12\x14\n\x0cuint32_value\x18\x04 \x01(\r\x12\x14\n\x0cuint64_value\x18\x05 \x01(\x04\x12\x13\n\x0b\x66loat_value\x18\x06 \x01(\x02\x12\x14\n\x0c\x64ouble_value\x18\x07 \x01(\x01\x12\x14\n\x0cstring_value\x18\x08 \x01(\t\x12\x13\n\x0b\x62ytes_value\x18\t \x01(\x0c\x12$\n\nenum_value\x18\n \x01(\x0e\x32\x10.proto3.EnumType\x12*\n\rmessage_value\x18\x0b \x01(\x0b\x32\x13.proto3.MessageType\x12\x1b\n\x13repeated_bool_value\x18\x15 \x03(\x08\x12\x1c\n\x14repeated_int32_value\x18\x16 \x03(\x05\x12\x1c\n\x14repeated_int64_value\x18\x17 \x03(\x03\x12\x1d\n\x15repeated_uint32_value\x18\x18 \x03(\r\x12\x1d\n\x15repeated_uint64_value\x18\x19 \x03(\x04\x12\x1c\n\x14repeated_float_value\x18\x1a \x03(\x02\x12\x1d\n\x15repeated_double_value\x18\x1b \x03(\x01\x12\x1d\n\x15repeated_string_value\x18\x1c \x03(\t\x12\x1c\n\x14repeated_bytes_value\x18\x1d \x03(\x0c\x12-\n\x13repeated_enum_value\x18\x1e \x03(\x0e\x32\x10.proto3.EnumType\x12\x33\n\x16repeated_message_value\x18\x1f \x03(\x0b\x32\x13.proto3.MessageType\"\x8c\x02\n\tTestOneof\x12\x1b\n\x11oneof_int32_value\x18\x01 \x01(\x05H\x00\x12\x1c\n\x12oneof_string_value\x18\x02 \x01(\tH\x00\x12\x1b\n\x11oneof_bytes_value\x18\x03 \x01(\x0cH\x00\x12,\n\x10oneof_enum_value\x18\x04 \x01(\x0e\x32\x10.proto3.EnumTypeH\x00\x12\x32\n\x13oneof_message_value\x18\x05 \x01(\x0b\x32\x13.proto3.MessageTypeH\x00\x12\x36\n\x10oneof_null_value\x18\x06 \x01(\x0e\x32\x1a.google.protobuf.NullValueH\x00\x42\r\n\x0boneof_value\"\xe1\x04\n\x07TestMap\x12.\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\x1c.proto3.TestMap.BoolMapEntry\x12\x30\n\tint32_map\x18\x02 \x03(\x0b\x32\x1d.proto3.TestMap.Int32MapEntry\x12\x30\n\tint64_map\x18\x03 \x03(\x0b\x32\x1d.proto3.TestMap.Int64MapEntry\x12\x32\n\nuint32_map\x18\x04 \x03(\x0b\x32\x1e.proto3.TestMap.Uint32MapEntry\x12\x32\n\nuint64_map\x18\x05 \x03(\x0b\x32\x1e.proto3.TestMap.Uint64MapEntry\x12\x32\n\nstring_map\x18\x06 \x03(\x0b\x32\x1e.proto3.TestMap.StringMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"\x85\x06\n\rTestNestedMap\x12\x34\n\x08\x62ool_map\x18\x01 \x03(\x0b\x32\".proto3.TestNestedMap.BoolMapEntry\x12\x36\n\tint32_map\x18\x02 \x03(\x0b\x32#.proto3.TestNestedMap.Int32MapEntry\x12\x36\n\tint64_map\x18\x03 \x03(\x0b\x32#.proto3.TestNestedMap.Int64MapEntry\x12\x38\n\nuint32_map\x18\x04 \x03(\x0b\x32$.proto3.TestNestedMap.Uint32MapEntry\x12\x38\n\nuint64_map\x18\x05 \x03(\x0b\x32$.proto3.TestNestedMap.Uint64MapEntry\x12\x38\n\nstring_map\x18\x06 \x03(\x0b\x32$.proto3.TestNestedMap.StringMapEntry\x12\x32\n\x07map_map\x18\x07 \x03(\x0b\x32!.proto3.TestNestedMap.MapMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x05\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a/\n\rInt64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x03\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint32MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eUint64MapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x44\n\x0bMapMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12$\n\x05value\x18\x02 \x01(\x0b\x32\x15.proto3.TestNestedMap:\x02\x38\x01\"{\n\rTestStringMap\x12\x38\n\nstring_map\x18\x01 \x03(\x0b\x32$.proto3.TestStringMap.StringMapEntry\x1a\x30\n\x0eStringMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xee\x07\n\x0bTestWrapper\x12.\n\nbool_value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x30\n\x0bint32_value\x18\x02 \x01(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x30\n\x0bint64_value\x18\x03 \x01(\x0b\x32\x1b.google.protobuf.Int64Value\x12\x32\n\x0cuint32_value\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\x32\n\x0cuint64_value\x18\x05 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x30\n\x0b\x66loat_value\x18\x06 \x01(\x0b\x32\x1b.google.protobuf.FloatValue\x12\x32\n\x0c\x64ouble_value\x18\x07 \x01(\x0b\x32\x1c.google.protobuf.DoubleValue\x12\x32\n\x0cstring_value\x18\x08 \x01(\x0b\x32\x1c.google.protobuf.StringValue\x12\x30\n\x0b\x62ytes_value\x18\t \x01(\x0b\x32\x1b.google.protobuf.BytesValue\x12\x37\n\x13repeated_bool_value\x18\x0b \x03(\x0b\x32\x1a.google.protobuf.BoolValue\x12\x39\n\x14repeated_int32_value\x18\x0c \x03(\x0b\x32\x1b.google.protobuf.Int32Value\x12\x39\n\x14repeated_int64_value\x18\r \x03(\x0b\x32\x1b.google.protobuf.Int64Value\x12;\n\x15repeated_uint32_value\x18\x0e \x03(\x0b\x32\x1c.google.protobuf.UInt32Value\x12;\n\x15repeated_uint64_value\x18\x0f \x03(\x0b\x32\x1c.google.protobuf.UInt64Value\x12\x39\n\x14repeated_float_value\x18\x10 \x03(\x0b\x32\x1b.google.protobuf.FloatValue\x12;\n\x15repeated_double_value\x18\x11 \x03(\x0b\x32\x1c.google.protobuf.DoubleValue\x12;\n\x15repeated_string_value\x18\x12 \x03(\x0b\x32\x1c.google.protobuf.StringValue\x12\x39\n\x14repeated_bytes_value\x18\x13 \x03(\x0b\x32\x1b.google.protobuf.BytesValue\"n\n\rTestTimestamp\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.Timestamp\"k\n\x0cTestDuration\x12(\n\x05value\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x19.google.protobuf.Duration\":\n\rTestFieldMask\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.FieldMask\"e\n\nTestStruct\x12&\n\x05value\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\x12/\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x17.google.protobuf.Struct\"\\\n\x07TestAny\x12#\n\x05value\x18\x01 \x01(\x0b\x32\x14.google.protobuf.Any\x12,\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x14.google.protobuf.Any\"b\n\tTestValue\x12%\n\x05value\x18\x01 \x01(\x0b\x32\x16.google.protobuf.Value\x12.\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x16.google.protobuf.Value\"n\n\rTestListValue\x12)\n\x05value\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.ListValue\x12\x32\n\x0erepeated_value\x18\x02 \x03(\x0b\x32\x1a.google.protobuf.ListValue\"\x89\x01\n\rTestBoolValue\x12\x12\n\nbool_value\x18\x01 \x01(\x08\x12\x34\n\x08\x62ool_map\x18\x02 \x03(\x0b\x32\".proto3.TestBoolValue.BoolMapEntry\x1a.\n\x0c\x42oolMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\x08\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"+\n\x12TestCustomJsonName\x12\x15\n\x05value\x18\x01 \x01(\x05R\x06@value\"J\n\x0eTestExtensions\x12\x38\n\nextensions\x18\x01 \x01(\x0b\x32$.protobuf_unittest.TestAllExtensions\"\x84\x01\n\rTestEnumValue\x12%\n\x0b\x65num_value1\x18\x01 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value2\x18\x02 \x01(\x0e\x32\x10.proto3.EnumType\x12%\n\x0b\x65num_value3\x18\x03 \x01(\x0e\x32\x10.proto3.EnumType*\x1c\n\x08\x45numType\x12\x07\n\x03\x46OO\x10\x00\x12\x07\n\x03\x42\x41R\x10\x01\x42,\n\x18\x63om.google.protobuf.utilB\x10JsonFormatProto3b\x06proto3' + , + dependencies=[google_dot_protobuf_dot_any__pb2.DESCRIPTOR,google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,google_dot_protobuf_dot_field__mask__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_unittest__pb2.DESCRIPTOR,]) + +_ENUMTYPE = _descriptor.EnumDescriptor( + name='EnumType', + full_name='proto3.EnumType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='FOO', index=0, number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BAR', index=1, number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4849, + serialized_end=4877, +) +_sym_db.RegisterEnumDescriptor(_ENUMTYPE) + +EnumType = enum_type_wrapper.EnumTypeWrapper(_ENUMTYPE) +FOO = 0 +BAR = 1 + + + +_MESSAGETYPE = _descriptor.Descriptor( + name='MessageType', + full_name='proto3.MessageType', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.MessageType.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=277, + serialized_end=305, +) + + +_TESTMESSAGE = _descriptor.Descriptor( + name='TestMessage', + full_name='proto3.TestMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestMessage.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestMessage.int32_value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestMessage.int64_value', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestMessage.uint32_value', index=3, + number=4, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestMessage.uint64_value', index=4, + number=5, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestMessage.float_value', index=5, + number=6, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestMessage.double_value', index=6, + number=7, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestMessage.string_value', index=7, + number=8, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestMessage.bytes_value', index=8, + number=9, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enum_value', full_name='proto3.TestMessage.enum_value', index=9, + number=10, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='message_value', full_name='proto3.TestMessage.message_value', index=10, + number=11, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestMessage.repeated_bool_value', index=11, + number=21, type=8, cpp_type=7, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestMessage.repeated_int32_value', index=12, + number=22, type=5, cpp_type=1, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestMessage.repeated_int64_value', index=13, + number=23, type=3, cpp_type=2, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestMessage.repeated_uint32_value', index=14, + number=24, type=13, cpp_type=3, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestMessage.repeated_uint64_value', index=15, + number=25, type=4, cpp_type=4, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestMessage.repeated_float_value', index=16, + number=26, type=2, cpp_type=6, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestMessage.repeated_double_value', index=17, + number=27, type=1, cpp_type=5, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestMessage.repeated_string_value', index=18, + number=28, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestMessage.repeated_bytes_value', index=19, + number=29, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_enum_value', full_name='proto3.TestMessage.repeated_enum_value', index=20, + number=30, type=14, cpp_type=8, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_message_value', full_name='proto3.TestMessage.repeated_message_value', index=21, + number=31, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=308, + serialized_end=968, +) + + +_TESTONEOF = _descriptor.Descriptor( + name='TestOneof', + full_name='proto3.TestOneof', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='oneof_int32_value', full_name='proto3.TestOneof.oneof_int32_value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_string_value', full_name='proto3.TestOneof.oneof_string_value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_bytes_value', full_name='proto3.TestOneof.oneof_bytes_value', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_enum_value', full_name='proto3.TestOneof.oneof_enum_value', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_message_value', full_name='proto3.TestOneof.oneof_message_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='oneof_null_value', full_name='proto3.TestOneof.oneof_null_value', index=5, + number=6, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='oneof_value', full_name='proto3.TestOneof.oneof_value', + index=0, containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=971, + serialized_end=1239, +) + + +_TESTMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1557, + serialized_end=1603, +) + +_TESTMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1605, + serialized_end=1652, +) + +_TESTMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1654, + serialized_end=1701, +) + +_TESTMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1703, + serialized_end=1751, +) + +_TESTMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1753, + serialized_end=1801, +) + +_TESTMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1803, + serialized_end=1851, +) + +_TESTMAP = _descriptor.Descriptor( + name='TestMap', + full_name='proto3.TestMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTMAP_BOOLMAPENTRY, _TESTMAP_INT32MAPENTRY, _TESTMAP_INT64MAPENTRY, _TESTMAP_UINT32MAPENTRY, _TESTMAP_UINT64MAPENTRY, _TESTMAP_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1242, + serialized_end=1851, +) + + +_TESTNESTEDMAP_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestNestedMap.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1557, + serialized_end=1603, +) + +_TESTNESTEDMAP_INT32MAPENTRY = _descriptor.Descriptor( + name='Int32MapEntry', + full_name='proto3.TestNestedMap.Int32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int32MapEntry.key', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1605, + serialized_end=1652, +) + +_TESTNESTEDMAP_INT64MAPENTRY = _descriptor.Descriptor( + name='Int64MapEntry', + full_name='proto3.TestNestedMap.Int64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Int64MapEntry.key', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Int64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1654, + serialized_end=1701, +) + +_TESTNESTEDMAP_UINT32MAPENTRY = _descriptor.Descriptor( + name='Uint32MapEntry', + full_name='proto3.TestNestedMap.Uint32MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint32MapEntry.key', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint32MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1703, + serialized_end=1751, +) + +_TESTNESTEDMAP_UINT64MAPENTRY = _descriptor.Descriptor( + name='Uint64MapEntry', + full_name='proto3.TestNestedMap.Uint64MapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.Uint64MapEntry.key', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.Uint64MapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1753, + serialized_end=1801, +) + +_TESTNESTEDMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestNestedMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.StringMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1803, + serialized_end=1851, +) + +_TESTNESTEDMAP_MAPMAPENTRY = _descriptor.Descriptor( + name='MapMapEntry', + full_name='proto3.TestNestedMap.MapMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestNestedMap.MapMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestNestedMap.MapMapEntry.value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2559, + serialized_end=2627, +) + +_TESTNESTEDMAP = _descriptor.Descriptor( + name='TestNestedMap', + full_name='proto3.TestNestedMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestNestedMap.bool_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int32_map', full_name='proto3.TestNestedMap.int32_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int64_map', full_name='proto3.TestNestedMap.int64_map', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint32_map', full_name='proto3.TestNestedMap.uint32_map', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint64_map', full_name='proto3.TestNestedMap.uint64_map', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestNestedMap.string_map', index=5, + number=6, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='map_map', full_name='proto3.TestNestedMap.map_map', index=6, + number=7, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTNESTEDMAP_BOOLMAPENTRY, _TESTNESTEDMAP_INT32MAPENTRY, _TESTNESTEDMAP_INT64MAPENTRY, _TESTNESTEDMAP_UINT32MAPENTRY, _TESTNESTEDMAP_UINT64MAPENTRY, _TESTNESTEDMAP_STRINGMAPENTRY, _TESTNESTEDMAP_MAPMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1854, + serialized_end=2627, +) + + +_TESTSTRINGMAP_STRINGMAPENTRY = _descriptor.Descriptor( + name='StringMapEntry', + full_name='proto3.TestStringMap.StringMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestStringMap.StringMapEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestStringMap.StringMapEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2704, + serialized_end=2752, +) + +_TESTSTRINGMAP = _descriptor.Descriptor( + name='TestStringMap', + full_name='proto3.TestStringMap', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='string_map', full_name='proto3.TestStringMap.string_map', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTSTRINGMAP_STRINGMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2629, + serialized_end=2752, +) + + +_TESTWRAPPER = _descriptor.Descriptor( + name='TestWrapper', + full_name='proto3.TestWrapper', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestWrapper.bool_value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int32_value', full_name='proto3.TestWrapper.int32_value', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='int64_value', full_name='proto3.TestWrapper.int64_value', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint32_value', full_name='proto3.TestWrapper.uint32_value', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uint64_value', full_name='proto3.TestWrapper.uint64_value', index=4, + number=5, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='float_value', full_name='proto3.TestWrapper.float_value', index=5, + number=6, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='double_value', full_name='proto3.TestWrapper.double_value', index=6, + number=7, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='string_value', full_name='proto3.TestWrapper.string_value', index=7, + number=8, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='bytes_value', full_name='proto3.TestWrapper.bytes_value', index=8, + number=9, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_bool_value', full_name='proto3.TestWrapper.repeated_bool_value', index=9, + number=11, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_int32_value', full_name='proto3.TestWrapper.repeated_int32_value', index=10, + number=12, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_int64_value', full_name='proto3.TestWrapper.repeated_int64_value', index=11, + number=13, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_uint32_value', full_name='proto3.TestWrapper.repeated_uint32_value', index=12, + number=14, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_uint64_value', full_name='proto3.TestWrapper.repeated_uint64_value', index=13, + number=15, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_float_value', full_name='proto3.TestWrapper.repeated_float_value', index=14, + number=16, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_double_value', full_name='proto3.TestWrapper.repeated_double_value', index=15, + number=17, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_string_value', full_name='proto3.TestWrapper.repeated_string_value', index=16, + number=18, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_bytes_value', full_name='proto3.TestWrapper.repeated_bytes_value', index=17, + number=19, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2755, + serialized_end=3761, +) + + +_TESTTIMESTAMP = _descriptor.Descriptor( + name='TestTimestamp', + full_name='proto3.TestTimestamp', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestTimestamp.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestTimestamp.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3763, + serialized_end=3873, +) + + +_TESTDURATION = _descriptor.Descriptor( + name='TestDuration', + full_name='proto3.TestDuration', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestDuration.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestDuration.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3875, + serialized_end=3982, +) + + +_TESTFIELDMASK = _descriptor.Descriptor( + name='TestFieldMask', + full_name='proto3.TestFieldMask', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestFieldMask.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3984, + serialized_end=4042, +) + + +_TESTSTRUCT = _descriptor.Descriptor( + name='TestStruct', + full_name='proto3.TestStruct', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestStruct.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestStruct.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4044, + serialized_end=4145, +) + + +_TESTANY = _descriptor.Descriptor( + name='TestAny', + full_name='proto3.TestAny', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestAny.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestAny.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4147, + serialized_end=4239, +) + + +_TESTVALUE = _descriptor.Descriptor( + name='TestValue', + full_name='proto3.TestValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4241, + serialized_end=4339, +) + + +_TESTLISTVALUE = _descriptor.Descriptor( + name='TestListValue', + full_name='proto3.TestListValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestListValue.value', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeated_value', full_name='proto3.TestListValue.repeated_value', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4341, + serialized_end=4451, +) + + +_TESTBOOLVALUE_BOOLMAPENTRY = _descriptor.Descriptor( + name='BoolMapEntry', + full_name='proto3.TestBoolValue.BoolMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='proto3.TestBoolValue.BoolMapEntry.key', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestBoolValue.BoolMapEntry.value', index=1, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1557, + serialized_end=1603, +) + +_TESTBOOLVALUE = _descriptor.Descriptor( + name='TestBoolValue', + full_name='proto3.TestBoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='bool_value', full_name='proto3.TestBoolValue.bool_value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='bool_map', full_name='proto3.TestBoolValue.bool_map', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[_TESTBOOLVALUE_BOOLMAPENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4454, + serialized_end=4591, +) + + +_TESTCUSTOMJSONNAME = _descriptor.Descriptor( + name='TestCustomJsonName', + full_name='proto3.TestCustomJsonName', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='proto3.TestCustomJsonName.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, json_name='@value', file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4593, + serialized_end=4636, +) + + +_TESTEXTENSIONS = _descriptor.Descriptor( + name='TestExtensions', + full_name='proto3.TestExtensions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='extensions', full_name='proto3.TestExtensions.extensions', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4638, + serialized_end=4712, +) + + +_TESTENUMVALUE = _descriptor.Descriptor( + name='TestEnumValue', + full_name='proto3.TestEnumValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='enum_value1', full_name='proto3.TestEnumValue.enum_value1', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enum_value2', full_name='proto3.TestEnumValue.enum_value2', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='enum_value3', full_name='proto3.TestEnumValue.enum_value3', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=4715, + serialized_end=4847, +) + +_TESTMESSAGE.fields_by_name['enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['message_value'].message_type = _MESSAGETYPE +_TESTMESSAGE.fields_by_name['repeated_enum_value'].enum_type = _ENUMTYPE +_TESTMESSAGE.fields_by_name['repeated_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.fields_by_name['oneof_enum_value'].enum_type = _ENUMTYPE +_TESTONEOF.fields_by_name['oneof_message_value'].message_type = _MESSAGETYPE +_TESTONEOF.fields_by_name['oneof_null_value'].enum_type = google_dot_protobuf_dot_struct__pb2._NULLVALUE +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_int32_value']) +_TESTONEOF.fields_by_name['oneof_int32_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_string_value']) +_TESTONEOF.fields_by_name['oneof_string_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_bytes_value']) +_TESTONEOF.fields_by_name['oneof_bytes_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_enum_value']) +_TESTONEOF.fields_by_name['oneof_enum_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_message_value']) +_TESTONEOF.fields_by_name['oneof_message_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTONEOF.oneofs_by_name['oneof_value'].fields.append( + _TESTONEOF.fields_by_name['oneof_null_value']) +_TESTONEOF.fields_by_name['oneof_null_value'].containing_oneof = _TESTONEOF.oneofs_by_name['oneof_value'] +_TESTMAP_BOOLMAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_INT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT32MAPENTRY.containing_type = _TESTMAP +_TESTMAP_UINT64MAPENTRY.containing_type = _TESTMAP +_TESTMAP_STRINGMAPENTRY.containing_type = _TESTMAP +_TESTMAP.fields_by_name['bool_map'].message_type = _TESTMAP_BOOLMAPENTRY +_TESTMAP.fields_by_name['int32_map'].message_type = _TESTMAP_INT32MAPENTRY +_TESTMAP.fields_by_name['int64_map'].message_type = _TESTMAP_INT64MAPENTRY +_TESTMAP.fields_by_name['uint32_map'].message_type = _TESTMAP_UINT32MAPENTRY +_TESTMAP.fields_by_name['uint64_map'].message_type = _TESTMAP_UINT64MAPENTRY +_TESTMAP.fields_by_name['string_map'].message_type = _TESTMAP_STRINGMAPENTRY +_TESTNESTEDMAP_BOOLMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_INT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT32MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_UINT64MAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_STRINGMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.fields_by_name['value'].message_type = _TESTNESTEDMAP +_TESTNESTEDMAP_MAPMAPENTRY.containing_type = _TESTNESTEDMAP +_TESTNESTEDMAP.fields_by_name['bool_map'].message_type = _TESTNESTEDMAP_BOOLMAPENTRY +_TESTNESTEDMAP.fields_by_name['int32_map'].message_type = _TESTNESTEDMAP_INT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['int64_map'].message_type = _TESTNESTEDMAP_INT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint32_map'].message_type = _TESTNESTEDMAP_UINT32MAPENTRY +_TESTNESTEDMAP.fields_by_name['uint64_map'].message_type = _TESTNESTEDMAP_UINT64MAPENTRY +_TESTNESTEDMAP.fields_by_name['string_map'].message_type = _TESTNESTEDMAP_STRINGMAPENTRY +_TESTNESTEDMAP.fields_by_name['map_map'].message_type = _TESTNESTEDMAP_MAPMAPENTRY +_TESTSTRINGMAP_STRINGMAPENTRY.containing_type = _TESTSTRINGMAP +_TESTSTRINGMAP.fields_by_name['string_map'].message_type = _TESTSTRINGMAP_STRINGMAPENTRY +_TESTWRAPPER.fields_by_name['bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTWRAPPER.fields_by_name['repeated_bool_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE +_TESTWRAPPER.fields_by_name['repeated_int32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT32VALUE +_TESTWRAPPER.fields_by_name['repeated_int64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._INT64VALUE +_TESTWRAPPER.fields_by_name['repeated_uint32_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT32VALUE +_TESTWRAPPER.fields_by_name['repeated_uint64_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._UINT64VALUE +_TESTWRAPPER.fields_by_name['repeated_float_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._FLOATVALUE +_TESTWRAPPER.fields_by_name['repeated_double_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._DOUBLEVALUE +_TESTWRAPPER.fields_by_name['repeated_string_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._STRINGVALUE +_TESTWRAPPER.fields_by_name['repeated_bytes_value'].message_type = google_dot_protobuf_dot_wrappers__pb2._BYTESVALUE +_TESTTIMESTAMP.fields_by_name['value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTTIMESTAMP.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP +_TESTDURATION.fields_by_name['value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTDURATION.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +_TESTFIELDMASK.fields_by_name['value'].message_type = google_dot_protobuf_dot_field__mask__pb2._FIELDMASK +_TESTSTRUCT.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTSTRUCT.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._STRUCT +_TESTANY.fields_by_name['value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTANY.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_any__pb2._ANY +_TESTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._VALUE +_TESTLISTVALUE.fields_by_name['value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTLISTVALUE.fields_by_name['repeated_value'].message_type = google_dot_protobuf_dot_struct__pb2._LISTVALUE +_TESTBOOLVALUE_BOOLMAPENTRY.containing_type = _TESTBOOLVALUE +_TESTBOOLVALUE.fields_by_name['bool_map'].message_type = _TESTBOOLVALUE_BOOLMAPENTRY +_TESTEXTENSIONS.fields_by_name['extensions'].message_type = google_dot_protobuf_dot_unittest__pb2._TESTALLEXTENSIONS +_TESTENUMVALUE.fields_by_name['enum_value1'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value2'].enum_type = _ENUMTYPE +_TESTENUMVALUE.fields_by_name['enum_value3'].enum_type = _ENUMTYPE +DESCRIPTOR.message_types_by_name['MessageType'] = _MESSAGETYPE +DESCRIPTOR.message_types_by_name['TestMessage'] = _TESTMESSAGE +DESCRIPTOR.message_types_by_name['TestOneof'] = _TESTONEOF +DESCRIPTOR.message_types_by_name['TestMap'] = _TESTMAP +DESCRIPTOR.message_types_by_name['TestNestedMap'] = _TESTNESTEDMAP +DESCRIPTOR.message_types_by_name['TestStringMap'] = _TESTSTRINGMAP +DESCRIPTOR.message_types_by_name['TestWrapper'] = _TESTWRAPPER +DESCRIPTOR.message_types_by_name['TestTimestamp'] = _TESTTIMESTAMP +DESCRIPTOR.message_types_by_name['TestDuration'] = _TESTDURATION +DESCRIPTOR.message_types_by_name['TestFieldMask'] = _TESTFIELDMASK +DESCRIPTOR.message_types_by_name['TestStruct'] = _TESTSTRUCT +DESCRIPTOR.message_types_by_name['TestAny'] = _TESTANY +DESCRIPTOR.message_types_by_name['TestValue'] = _TESTVALUE +DESCRIPTOR.message_types_by_name['TestListValue'] = _TESTLISTVALUE +DESCRIPTOR.message_types_by_name['TestBoolValue'] = _TESTBOOLVALUE +DESCRIPTOR.message_types_by_name['TestCustomJsonName'] = _TESTCUSTOMJSONNAME +DESCRIPTOR.message_types_by_name['TestExtensions'] = _TESTEXTENSIONS +DESCRIPTOR.message_types_by_name['TestEnumValue'] = _TESTENUMVALUE +DESCRIPTOR.enum_types_by_name['EnumType'] = _ENUMTYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +MessageType = _reflection.GeneratedProtocolMessageType('MessageType', (_message.Message,), { + 'DESCRIPTOR' : _MESSAGETYPE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.MessageType) + }) +_sym_db.RegisterMessage(MessageType) + +TestMessage = _reflection.GeneratedProtocolMessageType('TestMessage', (_message.Message,), { + 'DESCRIPTOR' : _TESTMESSAGE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMessage) + }) +_sym_db.RegisterMessage(TestMessage) + +TestOneof = _reflection.GeneratedProtocolMessageType('TestOneof', (_message.Message,), { + 'DESCRIPTOR' : _TESTONEOF, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestOneof) + }) +_sym_db.RegisterMessage(TestOneof) + +TestMap = _reflection.GeneratedProtocolMessageType('TestMap', (_message.Message,), { + + 'BoolMapEntry' : _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_BOOLMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.BoolMapEntry) + }) + , + + 'Int32MapEntry' : _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_INT32MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int32MapEntry) + }) + , + + 'Int64MapEntry' : _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_INT64MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Int64MapEntry) + }) + , + + 'Uint32MapEntry' : _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_UINT32MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint32MapEntry) + }) + , + + 'Uint64MapEntry' : _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_UINT64MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.Uint64MapEntry) + }) + , + + 'StringMapEntry' : _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTMAP_STRINGMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap.StringMapEntry) + }) + , + 'DESCRIPTOR' : _TESTMAP, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestMap) + }) +_sym_db.RegisterMessage(TestMap) +_sym_db.RegisterMessage(TestMap.BoolMapEntry) +_sym_db.RegisterMessage(TestMap.Int32MapEntry) +_sym_db.RegisterMessage(TestMap.Int64MapEntry) +_sym_db.RegisterMessage(TestMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestMap.StringMapEntry) + +TestNestedMap = _reflection.GeneratedProtocolMessageType('TestNestedMap', (_message.Message,), { + + 'BoolMapEntry' : _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_BOOLMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.BoolMapEntry) + }) + , + + 'Int32MapEntry' : _reflection.GeneratedProtocolMessageType('Int32MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_INT32MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int32MapEntry) + }) + , + + 'Int64MapEntry' : _reflection.GeneratedProtocolMessageType('Int64MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_INT64MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Int64MapEntry) + }) + , + + 'Uint32MapEntry' : _reflection.GeneratedProtocolMessageType('Uint32MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_UINT32MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint32MapEntry) + }) + , + + 'Uint64MapEntry' : _reflection.GeneratedProtocolMessageType('Uint64MapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_UINT64MAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.Uint64MapEntry) + }) + , + + 'StringMapEntry' : _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_STRINGMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.StringMapEntry) + }) + , + + 'MapMapEntry' : _reflection.GeneratedProtocolMessageType('MapMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTNESTEDMAP_MAPMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap.MapMapEntry) + }) + , + 'DESCRIPTOR' : _TESTNESTEDMAP, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestNestedMap) + }) +_sym_db.RegisterMessage(TestNestedMap) +_sym_db.RegisterMessage(TestNestedMap.BoolMapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Int64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint32MapEntry) +_sym_db.RegisterMessage(TestNestedMap.Uint64MapEntry) +_sym_db.RegisterMessage(TestNestedMap.StringMapEntry) +_sym_db.RegisterMessage(TestNestedMap.MapMapEntry) + +TestStringMap = _reflection.GeneratedProtocolMessageType('TestStringMap', (_message.Message,), { + + 'StringMapEntry' : _reflection.GeneratedProtocolMessageType('StringMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTSTRINGMAP_STRINGMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestStringMap.StringMapEntry) + }) + , + 'DESCRIPTOR' : _TESTSTRINGMAP, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestStringMap) + }) +_sym_db.RegisterMessage(TestStringMap) +_sym_db.RegisterMessage(TestStringMap.StringMapEntry) + +TestWrapper = _reflection.GeneratedProtocolMessageType('TestWrapper', (_message.Message,), { + 'DESCRIPTOR' : _TESTWRAPPER, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestWrapper) + }) +_sym_db.RegisterMessage(TestWrapper) + +TestTimestamp = _reflection.GeneratedProtocolMessageType('TestTimestamp', (_message.Message,), { + 'DESCRIPTOR' : _TESTTIMESTAMP, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestTimestamp) + }) +_sym_db.RegisterMessage(TestTimestamp) + +TestDuration = _reflection.GeneratedProtocolMessageType('TestDuration', (_message.Message,), { + 'DESCRIPTOR' : _TESTDURATION, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestDuration) + }) +_sym_db.RegisterMessage(TestDuration) + +TestFieldMask = _reflection.GeneratedProtocolMessageType('TestFieldMask', (_message.Message,), { + 'DESCRIPTOR' : _TESTFIELDMASK, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestFieldMask) + }) +_sym_db.RegisterMessage(TestFieldMask) + +TestStruct = _reflection.GeneratedProtocolMessageType('TestStruct', (_message.Message,), { + 'DESCRIPTOR' : _TESTSTRUCT, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestStruct) + }) +_sym_db.RegisterMessage(TestStruct) + +TestAny = _reflection.GeneratedProtocolMessageType('TestAny', (_message.Message,), { + 'DESCRIPTOR' : _TESTANY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestAny) + }) +_sym_db.RegisterMessage(TestAny) + +TestValue = _reflection.GeneratedProtocolMessageType('TestValue', (_message.Message,), { + 'DESCRIPTOR' : _TESTVALUE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestValue) + }) +_sym_db.RegisterMessage(TestValue) + +TestListValue = _reflection.GeneratedProtocolMessageType('TestListValue', (_message.Message,), { + 'DESCRIPTOR' : _TESTLISTVALUE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestListValue) + }) +_sym_db.RegisterMessage(TestListValue) + +TestBoolValue = _reflection.GeneratedProtocolMessageType('TestBoolValue', (_message.Message,), { + + 'BoolMapEntry' : _reflection.GeneratedProtocolMessageType('BoolMapEntry', (_message.Message,), { + 'DESCRIPTOR' : _TESTBOOLVALUE_BOOLMAPENTRY, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue.BoolMapEntry) + }) + , + 'DESCRIPTOR' : _TESTBOOLVALUE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestBoolValue) + }) +_sym_db.RegisterMessage(TestBoolValue) +_sym_db.RegisterMessage(TestBoolValue.BoolMapEntry) + +TestCustomJsonName = _reflection.GeneratedProtocolMessageType('TestCustomJsonName', (_message.Message,), { + 'DESCRIPTOR' : _TESTCUSTOMJSONNAME, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestCustomJsonName) + }) +_sym_db.RegisterMessage(TestCustomJsonName) + +TestExtensions = _reflection.GeneratedProtocolMessageType('TestExtensions', (_message.Message,), { + 'DESCRIPTOR' : _TESTEXTENSIONS, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestExtensions) + }) +_sym_db.RegisterMessage(TestExtensions) + +TestEnumValue = _reflection.GeneratedProtocolMessageType('TestEnumValue', (_message.Message,), { + 'DESCRIPTOR' : _TESTENUMVALUE, + '__module__' : 'google.protobuf.util.json_format_proto3_pb2' + # @@protoc_insertion_point(class_scope:proto3.TestEnumValue) + }) +_sym_db.RegisterMessage(TestEnumValue) + + +DESCRIPTOR._options = None +_TESTMAP_BOOLMAPENTRY._options = None +_TESTMAP_INT32MAPENTRY._options = None +_TESTMAP_INT64MAPENTRY._options = None +_TESTMAP_UINT32MAPENTRY._options = None +_TESTMAP_UINT64MAPENTRY._options = None +_TESTMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_BOOLMAPENTRY._options = None +_TESTNESTEDMAP_INT32MAPENTRY._options = None +_TESTNESTEDMAP_INT64MAPENTRY._options = None +_TESTNESTEDMAP_UINT32MAPENTRY._options = None +_TESTNESTEDMAP_UINT64MAPENTRY._options = None +_TESTNESTEDMAP_STRINGMAPENTRY._options = None +_TESTNESTEDMAP_MAPMAPENTRY._options = None +_TESTSTRINGMAP_STRINGMAPENTRY._options = None +_TESTBOOLVALUE_BOOLMAPENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/wrappers_pb2.py b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/wrappers_pb2.py new file mode 100644 index 00000000..6e5e2bc7 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/google/protobuf/wrappers_pb2.py @@ -0,0 +1,391 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: google/protobuf/wrappers.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='google/protobuf/wrappers.proto', + package='google.protobuf', + syntax='proto3', + serialized_options=b'\n\023com.google.protobufB\rWrappersProtoP\001Z1google.golang.org/protobuf/types/known/wrapperspb\370\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTypes', + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x1egoogle/protobuf/wrappers.proto\x12\x0fgoogle.protobuf\"\x1c\n\x0b\x44oubleValue\x12\r\n\x05value\x18\x01 \x01(\x01\"\x1b\n\nFloatValue\x12\r\n\x05value\x18\x01 \x01(\x02\"\x1b\n\nInt64Value\x12\r\n\x05value\x18\x01 \x01(\x03\"\x1c\n\x0bUInt64Value\x12\r\n\x05value\x18\x01 \x01(\x04\"\x1b\n\nInt32Value\x12\r\n\x05value\x18\x01 \x01(\x05\"\x1c\n\x0bUInt32Value\x12\r\n\x05value\x18\x01 \x01(\r\"\x1a\n\tBoolValue\x12\r\n\x05value\x18\x01 \x01(\x08\"\x1c\n\x0bStringValue\x12\r\n\x05value\x18\x01 \x01(\t\"\x1b\n\nBytesValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x42\x83\x01\n\x13\x63om.google.protobufB\rWrappersProtoP\x01Z1google.golang.org/protobuf/types/known/wrapperspb\xf8\x01\x01\xa2\x02\x03GPB\xaa\x02\x1eGoogle.Protobuf.WellKnownTypesb\x06proto3' +) + + + + +_DOUBLEVALUE = _descriptor.Descriptor( + name='DoubleValue', + full_name='google.protobuf.DoubleValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.DoubleValue.value', index=0, + number=1, type=1, cpp_type=5, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=79, +) + + +_FLOATVALUE = _descriptor.Descriptor( + name='FloatValue', + full_name='google.protobuf.FloatValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.FloatValue.value', index=0, + number=1, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=81, + serialized_end=108, +) + + +_INT64VALUE = _descriptor.Descriptor( + name='Int64Value', + full_name='google.protobuf.Int64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int64Value.value', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=110, + serialized_end=137, +) + + +_UINT64VALUE = _descriptor.Descriptor( + name='UInt64Value', + full_name='google.protobuf.UInt64Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt64Value.value', index=0, + number=1, type=4, cpp_type=4, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=139, + serialized_end=167, +) + + +_INT32VALUE = _descriptor.Descriptor( + name='Int32Value', + full_name='google.protobuf.Int32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.Int32Value.value', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=169, + serialized_end=196, +) + + +_UINT32VALUE = _descriptor.Descriptor( + name='UInt32Value', + full_name='google.protobuf.UInt32Value', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.UInt32Value.value', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=198, + serialized_end=226, +) + + +_BOOLVALUE = _descriptor.Descriptor( + name='BoolValue', + full_name='google.protobuf.BoolValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BoolValue.value', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=228, + serialized_end=254, +) + + +_STRINGVALUE = _descriptor.Descriptor( + name='StringValue', + full_name='google.protobuf.StringValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.StringValue.value', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=256, + serialized_end=284, +) + + +_BYTESVALUE = _descriptor.Descriptor( + name='BytesValue', + full_name='google.protobuf.BytesValue', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='value', full_name='google.protobuf.BytesValue.value', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=286, + serialized_end=313, +) + +DESCRIPTOR.message_types_by_name['DoubleValue'] = _DOUBLEVALUE +DESCRIPTOR.message_types_by_name['FloatValue'] = _FLOATVALUE +DESCRIPTOR.message_types_by_name['Int64Value'] = _INT64VALUE +DESCRIPTOR.message_types_by_name['UInt64Value'] = _UINT64VALUE +DESCRIPTOR.message_types_by_name['Int32Value'] = _INT32VALUE +DESCRIPTOR.message_types_by_name['UInt32Value'] = _UINT32VALUE +DESCRIPTOR.message_types_by_name['BoolValue'] = _BOOLVALUE +DESCRIPTOR.message_types_by_name['StringValue'] = _STRINGVALUE +DESCRIPTOR.message_types_by_name['BytesValue'] = _BYTESVALUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DoubleValue = _reflection.GeneratedProtocolMessageType('DoubleValue', (_message.Message,), { + 'DESCRIPTOR' : _DOUBLEVALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.DoubleValue) + }) +_sym_db.RegisterMessage(DoubleValue) + +FloatValue = _reflection.GeneratedProtocolMessageType('FloatValue', (_message.Message,), { + 'DESCRIPTOR' : _FLOATVALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.FloatValue) + }) +_sym_db.RegisterMessage(FloatValue) + +Int64Value = _reflection.GeneratedProtocolMessageType('Int64Value', (_message.Message,), { + 'DESCRIPTOR' : _INT64VALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int64Value) + }) +_sym_db.RegisterMessage(Int64Value) + +UInt64Value = _reflection.GeneratedProtocolMessageType('UInt64Value', (_message.Message,), { + 'DESCRIPTOR' : _UINT64VALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value) + }) +_sym_db.RegisterMessage(UInt64Value) + +Int32Value = _reflection.GeneratedProtocolMessageType('Int32Value', (_message.Message,), { + 'DESCRIPTOR' : _INT32VALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.Int32Value) + }) +_sym_db.RegisterMessage(Int32Value) + +UInt32Value = _reflection.GeneratedProtocolMessageType('UInt32Value', (_message.Message,), { + 'DESCRIPTOR' : _UINT32VALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value) + }) +_sym_db.RegisterMessage(UInt32Value) + +BoolValue = _reflection.GeneratedProtocolMessageType('BoolValue', (_message.Message,), { + 'DESCRIPTOR' : _BOOLVALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BoolValue) + }) +_sym_db.RegisterMessage(BoolValue) + +StringValue = _reflection.GeneratedProtocolMessageType('StringValue', (_message.Message,), { + 'DESCRIPTOR' : _STRINGVALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.StringValue) + }) +_sym_db.RegisterMessage(StringValue) + +BytesValue = _reflection.GeneratedProtocolMessageType('BytesValue', (_message.Message,), { + 'DESCRIPTOR' : _BYTESVALUE, + '__module__' : 'google.protobuf.wrappers_pb2' + # @@protoc_insertion_point(class_scope:google.protobuf.BytesValue) + }) +_sym_db.RegisterMessage(BytesValue) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/AUTHORS.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/AUTHORS.txt new file mode 100644 index 00000000..72c87d7d --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/AUTHORS.txt @@ -0,0 +1,562 @@ +A_Rog +Aakanksha Agrawal <11389424+rasponic@users.noreply.github.com> +Abhinav Sagar <40603139+abhinavsagar@users.noreply.github.com> +ABHYUDAY PRATAP SINGH +abs51295 +AceGentile +Adam Chainz +Adam Tse +Adam Tse +Adam Wentz +admin +Adrien Morison +ahayrapetyan +Ahilya +AinsworthK +Akash Srivastava +Alan Yee +Albert Tugushev +Albert-Guan +albertg +Aleks Bunin +Alethea Flowers +Alex Gaynor +Alex Grönholm +Alex Loosley +Alex Morega +Alex Stachowiak +Alexander Shtyrov +Alexandre Conrad +Alexey Popravka +Alexey Popravka +Alli +Ami Fischman +Ananya Maiti +Anatoly Techtonik +Anders Kaseorg +Andreas Lutro +Andrei Geacar +Andrew Gaul +Andrey Bulgakov +Andrés Delfino <34587441+andresdelfino@users.noreply.github.com> +Andrés Delfino +Andy Freeland +Andy Freeland +Andy Kluger +Ani Hayrapetyan +Aniruddha Basak +Anish Tambe +Anrs Hu +Anthony Sottile +Antoine Musso +Anton Ovchinnikov +Anton Patrushev +Antonio Alvarado Hernandez +Antony Lee +Antti Kaihola +Anubhav Patel +Anuj Godase +AQNOUCH Mohammed +AraHaan +Arindam Choudhury +Armin Ronacher +Artem +Ashley Manton +Ashwin Ramaswami +atse +Atsushi Odagiri +Avner Cohen +Baptiste Mispelon +Barney Gale +barneygale +Bartek Ogryczak +Bastian Venthur +Ben Darnell +Ben Hoyt +Ben Rosser +Bence Nagy +Benjamin Peterson +Benjamin VanEvery +Benoit Pierre +Berker Peksag +Bernardo B. Marques +Bernhard M. Wiedemann +Bertil Hatt +Bogdan Opanchuk +BorisZZZ +Brad Erickson +Bradley Ayers +Brandon L. Reiss +Brandt Bucher +Brett Randall +Brian Cristante <33549821+brcrista@users.noreply.github.com> +Brian Cristante +Brian Rosner +BrownTruck +Bruno Oliveira +Bruno Renié +Bstrdsmkr +Buck Golemon +burrows +Bussonnier Matthias +c22 +Caleb Martinez +Calvin Smith +Carl Meyer +Carlos Liam +Carol Willing +Carter Thayer +Cass +Chandrasekhar Atina +Chih-Hsuan Yen +Chih-Hsuan Yen +Chris Brinker +Chris Hunt +Chris Jerdonek +Chris McDonough +Chris Wolfe +Christian Heimes +Christian Oudard +Christopher Hunt +Christopher Snyder +Clark Boylan +Clay McClure +Cody +Cody Soyland +Colin Watson +Connor Osborn +Cooper Lees +Cooper Ry Lees +Cory Benfield +Cory Wright +Craig Kerstiens +Cristian Sorinel +Curtis Doty +cytolentino +Damian Quiroga +Dan Black +Dan Savilonis +Dan Sully +daniel +Daniel Collins +Daniel Hahler +Daniel Holth +Daniel Jost +Daniel Shaulov +Daniele Esposti +Daniele Procida +Danny Hermes +Dav Clark +Dave Abrahams +Dave Jones +David Aguilar +David Black +David Bordeynik +David Bordeynik +David Caro +David Evans +David Linke +David Pursehouse +David Tucker +David Wales +Davidovich +derwolfe +Desetude +Diego Caraballo +DiegoCaraballo +Dmitry Gladkov +Domen Kožar +Donald Stufft +Dongweiming +Douglas Thor +DrFeathers +Dustin Ingram +Dwayne Bailey +Ed Morley <501702+edmorley@users.noreply.github.com> +Ed Morley +Eitan Adler +ekristina +elainechan +Eli Schwartz +Eli Schwartz +Emil Burzo +Emil Styrke +Endoh Takanao +enoch +Erdinc Mutlu +Eric Gillingham +Eric Hanchrow +Eric Hopper +Erik M. Bray +Erik Rose +Ernest W Durbin III +Ernest W. Durbin III +Erwin Janssen +Eugene Vereshchagin +everdimension +Felix Yan +fiber-space +Filip Kokosiński +Florian Briand +Florian Rathgeber +Francesco +Francesco Montesano +Frost Ming +Gabriel Curio +Gabriel de Perthuis +Garry Polley +gdanielson +Geoffrey Lehée +Geoffrey Sneddon +George Song +Georgi Valkov +Giftlin Rajaiah +gizmoguy1 +gkdoc <40815324+gkdoc@users.noreply.github.com> +Gopinath M <31352222+mgopi1990@users.noreply.github.com> +GOTO Hayato <3532528+gh640@users.noreply.github.com> +gpiks +Guilherme Espada +Guy Rozendorn +gzpan123 +Hanjun Kim +Hari Charan +Harsh Vardhan +Herbert Pfennig +Hsiaoming Yang +Hugo +Hugo Lopes Tavares +Hugo van Kemenade +hugovk +Hynek Schlawack +Ian Bicking +Ian Cordasco +Ian Lee +Ian Stapleton Cordasco +Ian Wienand +Ian Wienand +Igor Kuzmitshov +Igor Sobreira +Ilya Baryshev +INADA Naoki +Ionel Cristian Mărieș +Ionel Maries Cristian +Ivan Pozdeev +Jacob Kim +jakirkham +Jakub Stasiak +Jakub Vysoky +Jakub Wilk +James Cleveland +James Cleveland +James Firth +James Polley +Jan Pokorný +Jannis Leidel +jarondl +Jason R. Coombs +Jay Graves +Jean-Christophe Fillion-Robin +Jeff Barber +Jeff Dairiki +Jelmer Vernooij +jenix21 +Jeremy Stanley +Jeremy Zafran +Jiashuo Li +Jim Garrison +Jivan Amara +John Paton +John-Scott Atlakson +johnthagen +johnthagen +Jon Banafato +Jon Dufresne +Jon Parise +Jonas Nockert +Jonathan Herbert +Joost Molenaar +Jorge Niedbalski +Joseph Long +Josh Bronson +Josh Hansen +Josh Schneier +Juanjo Bazán +Julian Berman +Julian Gethmann +Julien Demoor +jwg4 +Jyrki Pulliainen +Kai Chen +Kamal Bin Mustafa +kaustav haldar +keanemind +Keith Maxwell +Kelsey Hightower +Kenneth Belitzky +Kenneth Reitz +Kenneth Reitz +Kevin Burke +Kevin Carter +Kevin Frommelt +Kevin R Patterson +Kexuan Sun +Kit Randel +kpinc +Krishna Oza +Kumar McMillan +Kyle Persohn +lakshmanaram +Laszlo Kiss-Kollar +Laurent Bristiel +Laurie Opperman +Leon Sasson +Lev Givon +Lincoln de Sousa +Lipis +Loren Carvalho +Lucas Cimon +Ludovic Gasc +Luke Macken +Luo Jiebin +luojiebin +luz.paz +László Kiss Kollár +László Kiss Kollár +Marc Abramowitz +Marc Tamlyn +Marcus Smith +Mariatta +Mark Kohler +Mark Williams +Mark Williams +Markus Hametner +Masaki +Masklinn +Matej Stuchlik +Mathew Jennings +Mathieu Bridon +Matt Good +Matt Maker +Matt Robenolt +matthew +Matthew Einhorn +Matthew Gilliard +Matthew Iversen +Matthew Trumbell +Matthew Willson +Matthias Bussonnier +mattip +Maxim Kurnikov +Maxime Rouyrre +mayeut +mbaluna <44498973+mbaluna@users.noreply.github.com> +mdebi <17590103+mdebi@users.noreply.github.com> +memoselyk +Michael +Michael Aquilina +Michael E. Karpeles +Michael Klich +Michael Williamson +michaelpacer +Mickaël Schoentgen +Miguel Araujo Perez +Mihir Singh +Mike +Mike Hendricks +Min RK +MinRK +Miro Hrončok +Monica Baluna +montefra +Monty Taylor +Nate Coraor +Nathaniel J. Smith +Nehal J Wani +Neil Botelho +Nick Coghlan +Nick Stenning +Nick Timkovich +Nicolas Bock +Nikhil Benesch +Nitesh Sharma +Nowell Strite +NtaleGrey +nvdv +Ofekmeister +ofrinevo +Oliver Jeeves +Oliver Tonnhofer +Olivier Girardot +Olivier Grisel +Ollie Rutherfurd +OMOTO Kenji +Omry Yadan +Oren Held +Oscar Benjamin +Oz N Tiram +Pachwenko <32424503+Pachwenko@users.noreply.github.com> +Patrick Dubroy +Patrick Jenkins +Patrick Lawson +patricktokeeffe +Patrik Kopkan +Paul Kehrer +Paul Moore +Paul Nasrat +Paul Oswald +Paul van der Linden +Paulus Schoutsen +Pavithra Eswaramoorthy <33131404+QueenCoffee@users.noreply.github.com> +Pawel Jasinski +Pekka Klärck +Peter Lisák +Peter Waller +petr-tik +Phaneendra Chiruvella +Phil Freo +Phil Pennock +Phil Whelan +Philip Jägenstedt +Philip Molloy +Philippe Ombredanne +Pi Delport +Pierre-Yves Rofes +pip +Prabakaran Kumaresshan +Prabhjyotsing Surjit Singh Sodhi +Prabhu Marappan +Pradyun Gedam +Pratik Mallya +Preet Thakkar +Preston Holmes +Przemek Wrzos +Pulkit Goyal <7895pulkit@gmail.com> +Qiangning Hong +Quentin Pradet +R. David Murray +Rafael Caricio +Ralf Schmitt +Razzi Abuissa +rdb +Remi Rampin +Remi Rampin +Rene Dudfield +Riccardo Magliocchetti +Richard Jones +RobberPhex +Robert Collins +Robert McGibbon +Robert T. McGibbon +robin elisha robinson +Roey Berman +Rohan Jain +Rohan Jain +Rohan Jain +Roman Bogorodskiy +Romuald Brunet +Ronny Pfannschmidt +Rory McCann +Ross Brattain +Roy Wellington Ⅳ +Roy Wellington Ⅳ +Ryan Wooden +ryneeverett +Sachi King +Salvatore Rinchiera +Savio Jomton +schlamar +Scott Kitterman +Sean +seanj +Sebastian Jordan +Sebastian Schaetz +Segev Finer +SeongSoo Cho +Sergey Vasilyev +Seth Woodworth +Shlomi Fish +Shovan Maity +Simeon Visser +Simon Cross +Simon Pichugin +sinoroc +Sorin Sbarnea +Stavros Korokithakis +Stefan Scherfke +Stephan Erb +stepshal +Steve (Gadget) Barnes +Steve Barnes +Steve Dower +Steve Kowalik +Steven Myint +stonebig +Stéphane Bidoul (ACSONE) +Stéphane Bidoul +Stéphane Klein +Sumana Harihareswara +Sviatoslav Sydorenko +Sviatoslav Sydorenko +Swat009 +Takayuki SHIMIZUKAWA +tbeswick +Thijs Triemstra +Thomas Fenzl +Thomas Grainger +Thomas Guettler +Thomas Johansson +Thomas Kluyver +Thomas Smith +Tim D. Smith +Tim Gates +Tim Harder +Tim Heap +tim smith +tinruufu +Tom Forbes +Tom Freudenheim +Tom V +Tomas Orsava +Tomer Chachamu +Tony Beswick +Tony Zhaocheng Tan +TonyBeswick +toonarmycaptain +Toshio Kuratomi +Travis Swicegood +Tzu-ping Chung +Valentin Haenel +Victor Stinner +victorvpaulo +Viktor Szépe +Ville Skyttä +Vinay Sajip +Vincent Philippon +Vinicyus Macedo <7549205+vinicyusmacedo@users.noreply.github.com> +Vitaly Babiy +Vladimir Rutsky +W. Trevor King +Wil Tan +Wilfred Hughes +William ML Leslie +William T Olson +Wilson Mo +wim glenn +Wolfgang Maier +Xavier Fernandez +Xavier Fernandez +xoviat +xtreak +YAMAMOTO Takashi +Yen Chi Hsuan +Yeray Diaz Diaz +Yoval P +Yu Jian +Yuan Jing Vincent Yan +Zearin +Zearin +Zhiping Deng +Zvezdan Petkovic +Łukasz Langa +Семён Марьясин diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/INSTALLER b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/LICENSE.txt b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/LICENSE.txt new file mode 100644 index 00000000..737fec5c --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/METADATA b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/METADATA new file mode 100644 index 00000000..a9b0bba2 --- /dev/null +++ b/hackfest_firewall_pnf/charms/vyos-config/venv/lib/python3.8/site-packages/html5lib-1.0.1.dist-info/METADATA @@ -0,0 +1,526 @@ +Metadata-Version: 2.1 +Name: html5lib +Version: 1.0.1 +Summary: HTML parser based on the WHATWG HTML specification +Home-page: https://github.com/html5lib/html5lib-python +Maintainer: James Graham +Maintainer-email: james@hoppipolla.co.uk +License: MIT License +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Provides-Extra: all +Requires-Dist: chardet (>=2.2) ; extra == 'all' +Requires-Dist: genshi ; extra == 'all' +Requires-Dist: datrie ; (platform_python_implementation == 'CPython') and extra == 'all' +Requires-Dist: lxml ; (platform_python_implementation == 'CPython') and extra == 'all' +Provides-Extra: chardet +Requires-Dist: chardet (>=2.2) ; extra == 'chardet' +Provides-Extra: datrie +Requires-Dist: datrie ; (platform_python_implementation == 'CPython') and extra == 'datrie' +Provides-Extra: genshi +Requires-Dist: genshi ; extra == 'genshi' +Provides-Extra: lxml +Requires-Dist: lxml ; (platform_python_implementation == 'CPython') and extra == 'lxml' + +html5lib +======== + +.. image:: https://travis-ci.org/html5lib/html5lib-python.png?branch=master + :target: https://travis-ci.org/html5lib/html5lib-python + +html5lib is a pure-python library for parsing HTML. It is designed to +conform to the WHATWG HTML specification, as is implemented by all major +web browsers. + + +Usage +----- + +Simple usage follows this pattern: + +.. code-block:: python + + import html5lib + with open("mydocument.html", "rb") as f: + document = html5lib.parse(f) + +or: + +.. code-block:: python + + import html5lib + document = html5lib.parse("