From 9c012576afd933a98165adb5374770e84dc685b8 Mon Sep 17 00:00:00 2001 From: David Garcia Date: Mon, 30 Nov 2020 16:58:23 +0100 Subject: [PATCH] Update squid charm --- magma/squid_cnf/charms/squid/actions/addurl | 13 - magma/squid_cnf/charms/squid/config.yaml | 6 +- magma/squid_cnf/charms/squid/dispatch | 3 + magma/squid_cnf/charms/squid/hooks/install | 2 +- magma/squid_cnf/charms/squid/hooks/start | 1 + .../charms/squid/hooks/upgrade-charm | 1 + magma/squid_cnf/charms/squid/lib/.empty | 0 .../charms/squid/lib/ops/__init__.py | 18 - magma/squid_cnf/charms/squid/lib/ops/charm.py | 562 ----- magma/squid_cnf/charms/squid/lib/ops/main.py | 235 --- magma/squid_cnf/charms/squid/metadata.yaml | 9 +- magma/squid_cnf/charms/squid/mod/.empty | 0 .../charms/squid/mod/operator/.flake8 | 2 - .../charms/squid/mod/operator/.gitignore | 4 - .../squid/mod/operator/.readthedocs.yaml | 7 - .../charms/squid/mod/operator/.travis.yml | 24 - .../charms/squid/mod/operator/README.md | 137 -- .../charms/squid/mod/operator/build_docs | 18 - .../charms/squid/mod/operator/docs/conf.py | 89 - .../charms/squid/mod/operator/docs/index.rst | 58 - .../squid/mod/operator/docs/requirements.txt | 1 - .../charms/squid/mod/operator/ops/charm.py | 562 ----- .../squid/mod/operator/ops/framework.py | 1134 ---------- .../squid/mod/operator/ops/jujuversion.py | 85 - .../charms/squid/mod/operator/ops/log.py | 47 - .../charms/squid/mod/operator/ops/main.py | 235 --- .../charms/squid/mod/operator/ops/model.py | 915 -------- .../charms/squid/mod/operator/ops/testing.py | 477 ----- .../squid/mod/operator/requirements.txt | 1 - .../charms/squid/mod/operator/run_tests | 3 - .../charms/squid/mod/operator/setup.py | 39 - .../squid/mod/operator/test/__init__.py | 0 .../squid/mod/operator/test/bin/relation-ids | 11 - .../squid/mod/operator/test/bin/relation-list | 16 - .../test/charms/test_main/config.yaml | 1 - .../test/charms/test_main/lib/__init__.py | 0 .../operator/test/charms/test_main/lib/ops | 1 - .../test/charms/test_main/metadata.yaml | 26 - .../test/charms/test_main/src/charm.py | 208 -- .../squid/mod/operator/test/test_charm.py | 323 --- .../squid/mod/operator/test/test_framework.py | 1727 --------------- .../squid/mod/operator/test/test_helpers.py | 81 - .../squid/mod/operator/test/test_infra.py | 130 -- .../mod/operator/test/test_jujuversion.py | 130 -- .../squid/mod/operator/test/test_log.py | 140 -- .../squid/mod/operator/test/test_main.py | 675 ------ .../squid/mod/operator/test/test_model.py | 1288 ------------ .../squid/mod/operator/test/test_testing.py | 756 ------- magma/squid_cnf/charms/squid/requirements.txt | 3 + magma/squid_cnf/charms/squid/squid.charm | Bin 0 -> 601730 bytes magma/squid_cnf/charms/squid/src/charm.py | 178 +- .../charms/squid/template/squid.conf | 26 + .../venv/Jinja2-2.11.2.dist-info/INSTALLER | 1 + .../venv/Jinja2-2.11.2.dist-info/LICENSE.rst | 28 + .../venv/Jinja2-2.11.2.dist-info/METADATA | 106 + .../squid/venv/Jinja2-2.11.2.dist-info/RECORD | 61 + .../squid/venv/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 + .../venv/MarkupSafe-1.1.1.dist-info/INSTALLER | 1 + .../MarkupSafe-1.1.1.dist-info/LICENSE.txt | 28 + .../venv/MarkupSafe-1.1.1.dist-info/METADATA | 105 + .../venv/MarkupSafe-1.1.1.dist-info/RECORD | 16 + .../venv/MarkupSafe-1.1.1.dist-info/WHEEL | 5 + .../MarkupSafe-1.1.1.dist-info/top_level.txt | 1 + .../venv/PyYAML-5.3.1.dist-info/INSTALLER | 1 + .../squid/venv/PyYAML-5.3.1.dist-info/LICENSE | 20 + .../venv/PyYAML-5.3.1.dist-info/METADATA | 41 + .../squid/venv/PyYAML-5.3.1.dist-info/RECORD | 40 + .../squid/venv/PyYAML-5.3.1.dist-info/WHEEL | 5 + .../venv/PyYAML-5.3.1.dist-info/top_level.txt | 2 + .../charms/squid/venv/jinja2/__init__.py | 44 + .../charms/squid/venv/jinja2/_compat.py | 132 ++ .../charms/squid/venv/jinja2/_identifier.py | 6 + .../charms/squid/venv/jinja2/asyncfilters.py | 158 ++ .../charms/squid/venv/jinja2/asyncsupport.py | 264 +++ .../charms/squid/venv/jinja2/bccache.py | 350 ++++ .../charms/squid/venv/jinja2/compiler.py | 1843 +++++++++++++++++ .../charms/squid/venv/jinja2/constants.py | 21 + .../charms/squid/venv/jinja2/debug.py | 268 +++ .../charms/squid/venv/jinja2/defaults.py | 44 + .../charms/squid/venv/jinja2/environment.py | 1362 ++++++++++++ .../charms/squid/venv/jinja2/exceptions.py | 177 ++ .../squid_cnf/charms/squid/venv/jinja2/ext.py | 704 +++++++ .../charms/squid/venv/jinja2/filters.py | 1382 ++++++++++++ .../charms/squid/venv/jinja2/idtracking.py | 290 +++ .../charms/squid/venv/jinja2/lexer.py | 848 ++++++++ .../charms/squid/venv/jinja2/loaders.py | 504 +++++ .../charms/squid/venv/jinja2/meta.py | 101 + .../charms/squid/venv/jinja2/nativetypes.py | 94 + .../charms/squid/venv/jinja2/nodes.py | 1088 ++++++++++ .../charms/squid/venv/jinja2/optimizer.py | 41 + .../charms/squid/venv/jinja2/parser.py | 939 +++++++++ .../charms/squid/venv/jinja2/runtime.py | 1011 +++++++++ .../charms/squid/venv/jinja2/sandbox.py | 510 +++++ .../charms/squid/venv/jinja2/tests.py | 215 ++ .../charms/squid/venv/jinja2/utils.py | 732 +++++++ .../charms/squid/venv/jinja2/visitor.py | 81 + .../charms/squid/venv/markupsafe/__init__.py | 327 +++ .../charms/squid/venv/markupsafe/_compat.py | 33 + .../squid/venv/markupsafe/_constants.py | 264 +++ .../charms/squid/venv/markupsafe/_native.py | 69 + .../charms/squid/venv/markupsafe/_speedups.c | 423 ++++ .../_speedups.cpython-38-x86_64-linux-gnu.so | Bin 0 -> 48016 bytes .../venv/oci_image-1.0.0.dist-info/INSTALLER | 1 + .../venv/oci_image-1.0.0.dist-info/METADATA | 63 + .../venv/oci_image-1.0.0.dist-info/RECORD | 7 + .../venv/oci_image-1.0.0.dist-info/WHEEL | 5 + .../oci_image-1.0.0.dist-info/top_level.txt | 1 + .../squid_cnf/charms/squid/venv/oci_image.py | 53 + .../squid/venv/ops-1.1.0.dist-info/INSTALLER | 1 + .../ops-1.1.0.dist-info}/LICENSE.txt | 0 .../squid/venv/ops-1.1.0.dist-info/METADATA | 263 +++ .../squid/venv/ops-1.1.0.dist-info/RECORD | 28 + .../squid/venv/ops-1.1.0.dist-info/WHEEL | 5 + .../venv/ops-1.1.0.dist-info/top_level.txt | 1 + .../{mod/operator => venv}/ops/__init__.py | 4 +- .../squid_cnf/charms/squid/venv/ops/charm.py | 823 ++++++++ .../squid/{lib => venv}/ops/framework.py | 385 ++-- .../squid/{lib => venv}/ops/jujuversion.py | 29 + .../charms/squid/venv/ops/lib/__init__.py | 264 +++ .../charms/squid/{lib => venv}/ops/log.py | 11 + magma/squid_cnf/charms/squid/venv/ops/main.py | 406 ++++ .../charms/squid/{lib => venv}/ops/model.py | 621 +++++- .../charms/squid/venv/ops/storage.py | 374 ++++ .../charms/squid/{lib => venv}/ops/testing.py | 407 +++- .../charms/squid/venv/ops/version.py | 3 + .../charms/squid/venv/yaml/__init__.py | 427 ++++ .../charms/squid/venv/yaml/composer.py | 139 ++ .../charms/squid/venv/yaml/constructor.py | 748 +++++++ .../squid_cnf/charms/squid/venv/yaml/cyaml.py | 101 + .../charms/squid/venv/yaml/dumper.py | 62 + .../charms/squid/venv/yaml/emitter.py | 1137 ++++++++++ .../squid_cnf/charms/squid/venv/yaml/error.py | 75 + .../charms/squid/venv/yaml/events.py | 86 + .../charms/squid/venv/yaml/loader.py | 63 + .../squid_cnf/charms/squid/venv/yaml/nodes.py | 49 + .../charms/squid/venv/yaml/parser.py | 589 ++++++ .../charms/squid/venv/yaml/reader.py | 185 ++ .../charms/squid/venv/yaml/representer.py | 389 ++++ .../charms/squid/venv/yaml/resolver.py | 227 ++ .../charms/squid/venv/yaml/scanner.py | 1435 +++++++++++++ .../charms/squid/venv/yaml/serializer.py | 111 + .../charms/squid/venv/yaml/tokens.py | 104 + magma/squid_cnf/charms/squid_src/README.md | 47 + magma/squid_cnf/charms/squid_src/actions.yaml | 14 + magma/squid_cnf/charms/squid_src/config.yaml | 5 + .../squid_cnf/charms/squid_src/metadata.yaml | 24 + .../charms/squid_src/requirements.txt | 3 + magma/squid_cnf/charms/squid_src/squid.charm | Bin 0 -> 601730 bytes magma/squid_cnf/charms/squid_src/src/charm.py | 114 + .../charms/squid_src/template/squid.conf | 26 + .../tests/functional/requirements.txt | 1 + .../functional/tests/bundles/bionic.yaml | 6 + .../functional/tests/bundles/xenial.yaml | 7 + .../tests/functional/tests/tests.yaml | 17 + .../squid_src/tests/unit/operator_fixtures.py | 113 + .../squid_src/tests/unit/requirements.txt | 3 + .../src => squid_src/tests/unit}/setuppath.py | 0 .../charms/squid_src/tests/unit/test_charm.py | 19 + magma/squid_cnf/charms/squid_src/tox.ini | 46 + magma/squid_cnf/juju-bundles/bundle.yaml | 2 + 162 files changed, 24751 insertions(+), 10582 deletions(-) delete mode 100755 magma/squid_cnf/charms/squid/actions/addurl create mode 100755 magma/squid_cnf/charms/squid/dispatch create mode 120000 magma/squid_cnf/charms/squid/hooks/start create mode 120000 magma/squid_cnf/charms/squid/hooks/upgrade-charm delete mode 100644 magma/squid_cnf/charms/squid/lib/.empty delete mode 100644 magma/squid_cnf/charms/squid/lib/ops/__init__.py delete mode 100755 magma/squid_cnf/charms/squid/lib/ops/charm.py delete mode 100755 magma/squid_cnf/charms/squid/lib/ops/main.py delete mode 100644 magma/squid_cnf/charms/squid/mod/.empty delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.flake8 delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.gitignore delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/.travis.yml delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/README.md delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/build_docs delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/conf.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/index.rst delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/charm.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/framework.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/log.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/ops/main.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/model.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/ops/testing.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/requirements.txt delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/run_tests delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/setup.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/__init__.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py delete mode 120000 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_log.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_main.py delete mode 100755 magma/squid_cnf/charms/squid/mod/operator/test/test_model.py delete mode 100644 magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py create mode 100644 magma/squid_cnf/charms/squid/requirements.txt create mode 100644 magma/squid_cnf/charms/squid/squid.charm create mode 100644 magma/squid_cnf/charms/squid/template/squid.conf create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/LICENSE.rst create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt create mode 100644 magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/_compat.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/bccache.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/compiler.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/constants.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/debug.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/defaults.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/environment.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/exceptions.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/ext.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/filters.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/idtracking.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/lexer.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/loaders.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/meta.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/nativetypes.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/nodes.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/optimizer.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/parser.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/runtime.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/sandbox.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/tests.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/utils.py create mode 100644 magma/squid_cnf/charms/squid/venv/jinja2/visitor.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_compat.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_constants.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_native.py create mode 100644 magma/squid_cnf/charms/squid/venv/markupsafe/_speedups.c create mode 100755 magma/squid_cnf/charms/squid/venv/markupsafe/_speedups.cpython-38-x86_64-linux-gnu.so create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/INSTALLER create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image-1.0.0.dist-info/top_level.txt create mode 100644 magma/squid_cnf/charms/squid/venv/oci_image.py create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/INSTALLER rename magma/squid_cnf/charms/squid/{mod/operator => venv/ops-1.1.0.dist-info}/LICENSE.txt (100%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/METADATA create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/RECORD create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/WHEEL create mode 100644 magma/squid_cnf/charms/squid/venv/ops-1.1.0.dist-info/top_level.txt rename magma/squid_cnf/charms/squid/{mod/operator => venv}/ops/__init__.py (83%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/charm.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/framework.py (78%) mode change 100755 => 100644 rename magma/squid_cnf/charms/squid/{lib => venv}/ops/jujuversion.py (73%) mode change 100755 => 100644 create mode 100644 magma/squid_cnf/charms/squid/venv/ops/lib/__init__.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/log.py (79%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/main.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/model.py (57%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/storage.py rename magma/squid_cnf/charms/squid/{lib => venv}/ops/testing.py (51%) create mode 100644 magma/squid_cnf/charms/squid/venv/ops/version.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/__init__.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/composer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/constructor.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/cyaml.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/dumper.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/emitter.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/error.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/events.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/loader.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/nodes.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/parser.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/reader.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/representer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/resolver.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/scanner.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/serializer.py create mode 100644 magma/squid_cnf/charms/squid/venv/yaml/tokens.py create mode 100644 magma/squid_cnf/charms/squid_src/README.md create mode 100644 magma/squid_cnf/charms/squid_src/actions.yaml create mode 100644 magma/squid_cnf/charms/squid_src/config.yaml create mode 100644 magma/squid_cnf/charms/squid_src/metadata.yaml create mode 100644 magma/squid_cnf/charms/squid_src/requirements.txt create mode 100644 magma/squid_cnf/charms/squid_src/squid.charm create mode 100755 magma/squid_cnf/charms/squid_src/src/charm.py create mode 100644 magma/squid_cnf/charms/squid_src/template/squid.conf create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/requirements.txt create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/bundles/bionic.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/bundles/xenial.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/functional/tests/tests.yaml create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/operator_fixtures.py create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/requirements.txt rename magma/squid_cnf/charms/{squid/src => squid_src/tests/unit}/setuppath.py (100%) create mode 100644 magma/squid_cnf/charms/squid_src/tests/unit/test_charm.py create mode 100644 magma/squid_cnf/charms/squid_src/tox.ini diff --git a/magma/squid_cnf/charms/squid/actions/addurl b/magma/squid_cnf/charms/squid/actions/addurl deleted file mode 100755 index e12bf9fe..00000000 --- a/magma/squid_cnf/charms/squid/actions/addurl +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -URL=`action-get url` - -if ! grep -Fxq "http_access allow allowedurls" /etc/squid/squid.conf -then - sed -i '/^# And finally deny all .*/i http_access allow allowedurls\n' /etc/squid/squid.conf -fi - -sed -i "/^http_access allow allowedurls.*/i acl allowedurls dstdomain \.$URL" /etc/squid/squid.conf - -kill -HUP `cat /var/run/squid.pid` - diff --git a/magma/squid_cnf/charms/squid/config.yaml b/magma/squid_cnf/charms/squid/config.yaml index 65c33a86..450525ee 100644 --- a/magma/squid_cnf/charms/squid/config.yaml +++ b/magma/squid_cnf/charms/squid/config.yaml @@ -1,9 +1,5 @@ options: - image: - type: string - description: 'Docker image for squid' - default: 'domfleischmann/squid-python' port: type: int - description: 'Port' + description: "Port" default: 3128 diff --git a/magma/squid_cnf/charms/squid/dispatch b/magma/squid_cnf/charms/squid/dispatch new file mode 100755 index 00000000..fe31c056 --- /dev/null +++ b/magma/squid_cnf/charms/squid/dispatch @@ -0,0 +1,3 @@ +#!/bin/sh + +JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py diff --git a/magma/squid_cnf/charms/squid/hooks/install b/magma/squid_cnf/charms/squid/hooks/install index 25b1f68f..8b970447 120000 --- a/magma/squid_cnf/charms/squid/hooks/install +++ b/magma/squid_cnf/charms/squid/hooks/install @@ -1 +1 @@ -../src/charm.py \ No newline at end of file +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/hooks/start b/magma/squid_cnf/charms/squid/hooks/start new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/magma/squid_cnf/charms/squid/hooks/start @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/hooks/upgrade-charm b/magma/squid_cnf/charms/squid/hooks/upgrade-charm new file mode 120000 index 00000000..8b970447 --- /dev/null +++ b/magma/squid_cnf/charms/squid/hooks/upgrade-charm @@ -0,0 +1 @@ +../dispatch \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/lib/.empty b/magma/squid_cnf/charms/squid/lib/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/lib/ops/__init__.py b/magma/squid_cnf/charms/squid/lib/ops/__init__.py deleted file mode 100644 index b2089e38..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - -"""The Operator Framework.""" - -# Import here the bare minimum to break the circular import between modules -from . import charm # NOQA diff --git a/magma/squid_cnf/charms/squid/lib/ops/charm.py b/magma/squid_cnf/charms/squid/lib/ops/charm.py deleted file mode 100755 index 4682c20e..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/charm.py +++ /dev/null @@ -1,562 +0,0 @@ -# Copyright 2019-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 pathlib -import typing - -import yaml - -from ops.framework import Object, EventSource, EventBase, Framework, ObjectEvents -from ops import model - - -class HookEvent(EventBase): - """A base class for events that trigger because of a Juju hook firing.""" - - -class ActionEvent(EventBase): - """A base class for events that trigger when a user asks for an Action to be run. - - To read the parameters for the action, see the instance variable `params`. - To respond with the result of the action, call `set_results`. To add progress - messages that are visible as the action is progressing use `log`. - - :ivar params: The parameters passed to the action (read by action-get) - """ - - def defer(self): - """Action events are not deferable like other events. - - This is because an action runs synchronously and the user is waiting for the result. - """ - raise RuntimeError('cannot defer action events') - - def restore(self, snapshot: dict) -> None: - """Used by the operator framework to record the action. - - Not meant to be called directly by Charm code. - """ - env_action_name = os.environ.get('JUJU_ACTION_NAME') - event_action_name = self.handle.kind[:-len('_action')].replace('_', '-') - if event_action_name != env_action_name: - # This could only happen if the dev manually emits the action, or from a bug. - raise RuntimeError('action event kind does not match current action') - # Params are loaded at restore rather than __init__ because - # the model is not available in __init__. - self.params = self.framework.model._backend.action_get() - - def set_results(self, results: typing.Mapping) -> None: - """Report the result of the action. - - Args: - results: The result of the action as a Dict - """ - self.framework.model._backend.action_set(results) - - def log(self, message: str) -> None: - """Send a message that a user will see while the action is running. - - Args: - message: The message for the user. - """ - self.framework.model._backend.action_log(message) - - def fail(self, message: str = '') -> None: - """Report that this action has failed. - - Args: - message: Optional message to record why it has failed. - """ - self.framework.model._backend.action_fail(message) - - -class InstallEvent(HookEvent): - """Represents the `install` hook from Juju.""" - - -class StartEvent(HookEvent): - """Represents the `start` hook from Juju.""" - - -class StopEvent(HookEvent): - """Represents the `stop` hook from Juju.""" - - -class RemoveEvent(HookEvent): - """Represents the `remove` hook from Juju. """ - - -class ConfigChangedEvent(HookEvent): - """Represents the `config-changed` hook from Juju.""" - - -class UpdateStatusEvent(HookEvent): - """Represents the `update-status` hook from Juju.""" - - -class UpgradeCharmEvent(HookEvent): - """Represents the `upgrade-charm` hook from Juju. - - This will be triggered when a user has run `juju upgrade-charm`. It is run after Juju - has unpacked the upgraded charm code, and so this event will be handled with new code. - """ - - -class PreSeriesUpgradeEvent(HookEvent): - """Represents the `pre-series-upgrade` hook from Juju. - - This happens when a user has run `juju upgrade-series MACHINE prepare` and - will fire for each unit that is running on the machine, telling them that - the user is preparing to upgrade the Machine's series (eg trusty->bionic). - The charm should take actions to prepare for the upgrade (a database charm - would want to write out a version-independent dump of the database, so that - when a new version of the database is available in a new series, it can be - used.) - Once all units on a machine have run `pre-series-upgrade`, the user will - initiate the steps to actually upgrade the machine (eg `do-release-upgrade`). - When the upgrade has been completed, the :class:`PostSeriesUpgradeEvent` will fire. - """ - - -class PostSeriesUpgradeEvent(HookEvent): - """Represents the `post-series-upgrade` hook from Juju. - - This is run after the user has done a distribution upgrade (or rolled back - and kept the same series). It is called in response to - `juju upgrade-series MACHINE complete`. Charms are expected to do whatever - steps are necessary to reconfigure their applications for the new series. - """ - - -class LeaderElectedEvent(HookEvent): - """Represents the `leader-elected` hook from Juju. - - Juju will trigger this when a new lead unit is chosen for a given application. - This represents the leader of the charm information (not necessarily the primary - of a running application). The main utility is that charm authors can know - that only one unit will be a leader at any given time, so they can do - configuration, etc, that would otherwise require coordination between units. - (eg, selecting a password for a new relation) - """ - - -class LeaderSettingsChangedEvent(HookEvent): - """Represents the `leader-settings-changed` hook from Juju. - - Deprecated. This represents when a lead unit would call `leader-set` to inform - the other units of an application that they have new information to handle. - This has been deprecated in favor of using a Peer relation, and having the - leader set a value in the Application data bag for that peer relation. - (see :class:`RelationChangedEvent`). - """ - - -class CollectMetricsEvent(HookEvent): - """Represents the `collect-metrics` hook from Juju. - - Note that events firing during a CollectMetricsEvent are currently - sandboxed in how they can interact with Juju. To report metrics - use :meth:`.add_metrics`. - """ - - def add_metrics(self, metrics: typing.Mapping, labels: typing.Mapping = None) -> None: - """Record metrics that have been gathered by the charm for this unit. - - Args: - metrics: A collection of {key: float} pairs that contains the - metrics that have been gathered - labels: {key:value} strings that can be applied to the - metrics that are being gathered - """ - self.framework.model._backend.add_metrics(metrics, labels) - - -class RelationEvent(HookEvent): - """A base class representing the various relation lifecycle events. - - Charmers should not be creating RelationEvents directly. The events will be - generated by the framework from Juju related events. Users can observe them - from the various `CharmBase.on[relation_name].relation_*` events. - - Attributes: - relation: The Relation involved in this event - app: The remote application that has triggered this event - unit: The remote unit that has triggered this event. This may be None - if the relation event was triggered as an Application level event - """ - - def __init__(self, handle, relation, app=None, unit=None): - super().__init__(handle) - - if unit is not None and unit.app != app: - raise RuntimeError( - 'cannot create RelationEvent with application {} and unit {}'.format(app, unit)) - - self.relation = relation - self.app = app - self.unit = unit - - def snapshot(self) -> dict: - """Used by the framework to serialize the event to disk. - - Not meant to be called by Charm code. - """ - snapshot = { - 'relation_name': self.relation.name, - 'relation_id': self.relation.id, - } - if self.app: - snapshot['app_name'] = self.app.name - if self.unit: - snapshot['unit_name'] = self.unit.name - return snapshot - - def restore(self, snapshot: dict) -> None: - """Used by the framework to deserialize the event from disk. - - Not meant to be called by Charm code. - """ - self.relation = self.framework.model.get_relation( - snapshot['relation_name'], snapshot['relation_id']) - - app_name = snapshot.get('app_name') - if app_name: - self.app = self.framework.model.get_app(app_name) - else: - self.app = None - - unit_name = snapshot.get('unit_name') - if unit_name: - self.unit = self.framework.model.get_unit(unit_name) - else: - self.unit = None - - -class RelationCreatedEvent(RelationEvent): - """Represents the `relation-created` hook from Juju. - - This is triggered when a new relation to another app is added in Juju. This - can occur before units for those applications have started. All existing - relations should be established before start. - """ - - -class RelationJoinedEvent(RelationEvent): - """Represents the `relation-joined` hook from Juju. - - This is triggered whenever a new unit of a related application joins the relation. - (eg, a unit was added to an existing related app, or a new relation was established - with an application that already had units.) - """ - - -class RelationChangedEvent(RelationEvent): - """Represents the `relation-changed` hook from Juju. - - This is triggered whenever there is a change to the data bucket for a related - application or unit. Look at `event.relation.data[event.unit/app]` to see the - new information. - """ - - -class RelationDepartedEvent(RelationEvent): - """Represents the `relation-departed` hook from Juju. - - This is the inverse of the RelationJoinedEvent, representing when a unit - is leaving the relation (the unit is being removed, the app is being removed, - the relation is being removed). It is fired once for each unit that is - going away. - """ - - -class RelationBrokenEvent(RelationEvent): - """Represents the `relation-broken` hook from Juju. - - If a relation is being removed (`juju remove-relation` or `juju remove-application`), - once all the units have been removed, RelationBrokenEvent will fire to signal - that the relationship has been fully terminated. - """ - - -class StorageEvent(HookEvent): - """Base class representing Storage related events.""" - - -class StorageAttachedEvent(StorageEvent): - """Represents the `storage-attached` hook from Juju. - - Called when new storage is available for the charm to use. - """ - - -class StorageDetachingEvent(StorageEvent): - """Represents the `storage-detaching` hook from Juju. - - Called when storage a charm has been using is going away. - """ - - -class CharmEvents(ObjectEvents): - """The events that are generated by Juju in response to the lifecycle of an application.""" - - install = EventSource(InstallEvent) - start = EventSource(StartEvent) - stop = EventSource(StopEvent) - remove = EventSource(RemoveEvent) - update_status = EventSource(UpdateStatusEvent) - config_changed = EventSource(ConfigChangedEvent) - upgrade_charm = EventSource(UpgradeCharmEvent) - pre_series_upgrade = EventSource(PreSeriesUpgradeEvent) - post_series_upgrade = EventSource(PostSeriesUpgradeEvent) - leader_elected = EventSource(LeaderElectedEvent) - leader_settings_changed = EventSource(LeaderSettingsChangedEvent) - collect_metrics = EventSource(CollectMetricsEvent) - - -class CharmBase(Object): - """Base class that represents the Charm overall. - - Usually this initialization is done by ops.main.main() rather than Charm authors - directly instantiating a Charm. - - Args: - framework: The framework responsible for managing the Model and events for this - Charm. - key: Arbitrary key to distinguish this instance of CharmBase from another. - Generally is None when initialized by the framework. For charms instantiated by - main.main(), this is currenly None. - Attributes: - on: Defines all events that the Charm will fire. - """ - - on = CharmEvents() - - def __init__(self, framework: Framework, key: typing.Optional[str]): - """Initialize the Charm with its framework and application name. - - """ - super().__init__(framework, key) - - for relation_name in self.framework.meta.relations: - relation_name = relation_name.replace('-', '_') - self.on.define_event(relation_name + '_relation_created', RelationCreatedEvent) - self.on.define_event(relation_name + '_relation_joined', RelationJoinedEvent) - self.on.define_event(relation_name + '_relation_changed', RelationChangedEvent) - self.on.define_event(relation_name + '_relation_departed', RelationDepartedEvent) - self.on.define_event(relation_name + '_relation_broken', RelationBrokenEvent) - - for storage_name in self.framework.meta.storages: - storage_name = storage_name.replace('-', '_') - self.on.define_event(storage_name + '_storage_attached', StorageAttachedEvent) - self.on.define_event(storage_name + '_storage_detaching', StorageDetachingEvent) - - for action_name in self.framework.meta.actions: - action_name = action_name.replace('-', '_') - self.on.define_event(action_name + '_action', ActionEvent) - - @property - def app(self) -> model.Application: - """Application that this unit is part of.""" - return self.framework.model.app - - @property - def unit(self) -> model.Unit: - """Unit that this execution is responsible for.""" - return self.framework.model.unit - - @property - def meta(self) -> 'CharmMeta': - """CharmMeta of this charm. - """ - return self.framework.meta - - @property - def charm_dir(self) -> pathlib.Path: - """Root directory of the Charm as it is running. - """ - return self.framework.charm_dir - - -class CharmMeta: - """Object containing the metadata for the charm. - - This is read from metadata.yaml and/or actions.yaml. Generally charms will - define this information, rather than reading it at runtime. This class is - mostly for the framework to understand what the charm has defined. - - The maintainers, tags, terms, series, and extra_bindings attributes are all - lists of strings. The requires, provides, peers, relations, storage, - resources, and payloads attributes are all mappings of names to instances - of the respective RelationMeta, StorageMeta, ResourceMeta, or PayloadMeta. - - The relations attribute is a convenience accessor which includes all of the - requires, provides, and peers RelationMeta items. If needed, the role of - the relation definition can be obtained from its role attribute. - - Attributes: - name: The name of this charm - summary: Short description of what this charm does - description: Long description for this charm - maintainers: A list of strings of the email addresses of the maintainers - of this charm. - tags: Charm store tag metadata for categories associated with this charm. - terms: Charm store terms that should be agreed to before this charm can - be deployed. (Used for things like licensing issues.) - series: The list of supported OS series that this charm can support. - The first entry in the list is the default series that will be - used by deploy if no other series is requested by the user. - subordinate: True/False whether this charm is intended to be used as a - subordinate charm. - min_juju_version: If supplied, indicates this charm needs features that - are not available in older versions of Juju. - requires: A dict of {name: :class:`RelationMeta` } for each 'requires' relation. - provides: A dict of {name: :class:`RelationMeta` } for each 'provides' relation. - peers: A dict of {name: :class:`RelationMeta` } for each 'peer' relation. - relations: A dict containing all :class:`RelationMeta` attributes (merged from other - sections) - storages: A dict of {name: :class:`StorageMeta`} for each defined storage. - resources: A dict of {name: :class:`ResourceMeta`} for each defined resource. - payloads: A dict of {name: :class:`PayloadMeta`} for each defined payload. - extra_bindings: A dict of additional named bindings that a charm can use - for network configuration. - actions: A dict of {name: :class:`ActionMeta`} for actions that the charm has defined. - Args: - raw: a mapping containing the contents of metadata.yaml - actions_raw: a mapping containing the contents of actions.yaml - """ - - def __init__(self, raw: dict = {}, actions_raw: dict = {}): - self.name = raw.get('name', '') - self.summary = raw.get('summary', '') - self.description = raw.get('description', '') - self.maintainers = [] - if 'maintainer' in raw: - self.maintainers.append(raw['maintainer']) - if 'maintainers' in raw: - self.maintainers.extend(raw['maintainers']) - self.tags = raw.get('tags', []) - self.terms = raw.get('terms', []) - self.series = raw.get('series', []) - self.subordinate = raw.get('subordinate', False) - self.min_juju_version = raw.get('min-juju-version') - self.requires = {name: RelationMeta('requires', name, rel) - for name, rel in raw.get('requires', {}).items()} - self.provides = {name: RelationMeta('provides', name, rel) - for name, rel in raw.get('provides', {}).items()} - # TODO: (jam 2020-05-11) The *role* should be 'peer' even though it comes from the - # 'peers' section. - self.peers = {name: RelationMeta('peers', name, rel) - for name, rel in raw.get('peers', {}).items()} - self.relations = {} - self.relations.update(self.requires) - self.relations.update(self.provides) - self.relations.update(self.peers) - self.storages = {name: StorageMeta(name, storage) - for name, storage in raw.get('storage', {}).items()} - self.resources = {name: ResourceMeta(name, res) - for name, res in raw.get('resources', {}).items()} - self.payloads = {name: PayloadMeta(name, payload) - for name, payload in raw.get('payloads', {}).items()} - self.extra_bindings = raw.get('extra-bindings', {}) - self.actions = {name: ActionMeta(name, action) for name, action in actions_raw.items()} - - @classmethod - def from_yaml( - cls, metadata: typing.Union[str, typing.TextIO], - actions: typing.Optional[typing.Union[str, typing.TextIO]] = None): - """Instantiate a CharmMeta from a YAML description of metadata.yaml. - - Args: - metadata: A YAML description of charm metadata (name, relations, etc.) - This can be a simple string, or a file-like object. (passed to `yaml.safe_load`). - actions: YAML description of Actions for this charm (eg actions.yaml) - """ - meta = yaml.safe_load(metadata) - raw_actions = {} - if actions is not None: - raw_actions = yaml.safe_load(actions) - return cls(meta, raw_actions) - - -class RelationMeta: - """Object containing metadata about a relation definition. - - Should not be constructed directly by Charm code. Is gotten from one of - :attr:`CharmMeta.peers`, :attr:`CharmMeta.requires`, :attr:`CharmMeta.provides`, - :attr:`CharmMeta.relations`. - - Attributes: - role: This is one of requires/provides/peers - relation_name: Name of this relation from metadata.yaml - interface_name: Optional definition of the interface protocol. - scope: "global" or "container" scope based on how the relation should be used. - """ - - def __init__(self, role, relation_name, raw): - self.role = role - self.relation_name = relation_name - self.interface_name = raw['interface'] - self.scope = raw.get('scope') - - -class StorageMeta: - """Object containing metadata about a storage definition.""" - - def __init__(self, name, raw): - self.storage_name = name - self.type = raw['type'] - self.description = raw.get('description', '') - self.shared = raw.get('shared', False) - self.read_only = raw.get('read-only', False) - self.minimum_size = raw.get('minimum-size') - self.location = raw.get('location') - self.multiple_range = None - if 'multiple' in raw: - range = raw['multiple']['range'] - if '-' not in range: - self.multiple_range = (int(range), int(range)) - else: - range = range.split('-') - self.multiple_range = (int(range[0]), int(range[1]) if range[1] else None) - - -class ResourceMeta: - """Object containing metadata about a resource definition.""" - - def __init__(self, name, raw): - self.resource_name = name - self.type = raw['type'] - self.filename = raw.get('filename', None) - self.description = raw.get('description', '') - - -class PayloadMeta: - """Object containing metadata about a payload definition.""" - - def __init__(self, name, raw): - self.payload_name = name - self.type = raw['type'] - - -class ActionMeta: - """Object containing metadata about an action's definition.""" - - def __init__(self, name, raw=None): - raw = raw or {} - self.name = name - self.title = raw.get('title', '') - self.description = raw.get('description', '') - self.parameters = raw.get('params', {}) # {: } - self.required = raw.get('required', []) # [, ...] diff --git a/magma/squid_cnf/charms/squid/lib/ops/main.py b/magma/squid_cnf/charms/squid/lib/ops/main.py deleted file mode 100755 index 0f5391d7..00000000 --- a/magma/squid_cnf/charms/squid/lib/ops/main.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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 -from pathlib import Path - -import yaml - -import ops.charm -import ops.framework -import ops.model -import logging - -from ops.log import setup_root_logging - -CHARM_STATE_FILE = '.unit-state.db' - - -logger = logging.getLogger() - - -def _get_charm_dir(): - charm_dir = os.environ.get("JUJU_CHARM_DIR") - if charm_dir is None: - # Assume $JUJU_CHARM_DIR/lib/op/main.py structure. - charm_dir = Path('{}/../../..'.format(__file__)).resolve() - else: - charm_dir = Path(charm_dir).resolve() - return charm_dir - - -def _load_metadata(charm_dir): - metadata = yaml.safe_load((charm_dir / 'metadata.yaml').read_text()) - - actions_meta = charm_dir / 'actions.yaml' - if actions_meta.exists(): - actions_metadata = yaml.safe_load(actions_meta.read_text()) - else: - actions_metadata = {} - return metadata, actions_metadata - - -def _create_event_link(charm, bound_event): - """Create a symlink for a particular event. - - charm -- A charm object. - bound_event -- An event for which to create a symlink. - """ - if issubclass(bound_event.event_type, ops.charm.HookEvent): - event_dir = charm.framework.charm_dir / 'hooks' - event_path = event_dir / bound_event.event_kind.replace('_', '-') - elif issubclass(bound_event.event_type, ops.charm.ActionEvent): - if not bound_event.event_kind.endswith("_action"): - raise RuntimeError( - 'action event name {} needs _action suffix'.format(bound_event.event_kind)) - event_dir = charm.framework.charm_dir / 'actions' - # The event_kind is suffixed with "_action" while the executable is not. - event_path = event_dir / bound_event.event_kind[:-len('_action')].replace('_', '-') - else: - raise RuntimeError( - 'cannot create a symlink: unsupported event type {}'.format(bound_event.event_type)) - - event_dir.mkdir(exist_ok=True) - if not event_path.exists(): - # CPython has different implementations for populating sys.argv[0] for Linux and Windows. - # For Windows it is always an absolute path (any symlinks are resolved) - # while for Linux it can be a relative path. - target_path = os.path.relpath(os.path.realpath(sys.argv[0]), str(event_dir)) - - # Ignore the non-symlink files or directories - # assuming the charm author knows what they are doing. - logger.debug( - 'Creating a new relative symlink at %s pointing to %s', - event_path, target_path) - event_path.symlink_to(target_path) - - -def _setup_event_links(charm_dir, charm): - """Set up links for supported events that originate from Juju. - - Whether a charm can handle an event or not can be determined by - introspecting which events are defined on it. - - Hooks or actions are created as symlinks to the charm code file - which is determined by inspecting symlinks provided by the charm - author at hooks/install or hooks/start. - - charm_dir -- A root directory of the charm. - charm -- An instance of the Charm class. - - """ - for bound_event in charm.on.events().values(): - # Only events that originate from Juju need symlinks. - if issubclass(bound_event.event_type, (ops.charm.HookEvent, ops.charm.ActionEvent)): - _create_event_link(charm, bound_event) - - -def _emit_charm_event(charm, event_name): - """Emits a charm event based on a Juju event name. - - charm -- A charm instance to emit an event from. - event_name -- A Juju event name to emit on a charm. - """ - event_to_emit = None - try: - event_to_emit = getattr(charm.on, event_name) - except AttributeError: - logger.debug("event %s not defined for %s", event_name, charm) - - # If the event is not supported by the charm implementation, do - # not error out or try to emit it. This is to support rollbacks. - if event_to_emit is not None: - args, kwargs = _get_event_args(charm, event_to_emit) - logger.debug('Emitting Juju event %s', event_name) - event_to_emit.emit(*args, **kwargs) - - -def _get_event_args(charm, bound_event): - event_type = bound_event.event_type - model = charm.framework.model - - if issubclass(event_type, ops.charm.RelationEvent): - relation_name = os.environ['JUJU_RELATION'] - relation_id = int(os.environ['JUJU_RELATION_ID'].split(':')[-1]) - relation = model.get_relation(relation_name, relation_id) - else: - relation = None - - remote_app_name = os.environ.get('JUJU_REMOTE_APP', '') - remote_unit_name = os.environ.get('JUJU_REMOTE_UNIT', '') - if remote_app_name or remote_unit_name: - if not remote_app_name: - if '/' not in remote_unit_name: - raise RuntimeError('invalid remote unit name: {}'.format(remote_unit_name)) - remote_app_name = remote_unit_name.split('/')[0] - args = [relation, model.get_app(remote_app_name)] - if remote_unit_name: - args.append(model.get_unit(remote_unit_name)) - return args, {} - elif relation: - return [relation], {} - return [], {} - - -def main(charm_class): - """Setup the charm and dispatch the observed event. - - The event name is based on the way this executable was called (argv[0]). - """ - charm_dir = _get_charm_dir() - - model_backend = ops.model.ModelBackend() - debug = ('JUJU_DEBUG' in os.environ) - setup_root_logging(model_backend, debug=debug) - - # Process the Juju event relevant to the current hook execution - # JUJU_HOOK_NAME, JUJU_FUNCTION_NAME, and JUJU_ACTION_NAME are not used - # in order to support simulation of events from debugging sessions. - # - # TODO: For Windows, when symlinks are used, this is not a valid - # method of getting an event name (see LP: #1854505). - juju_exec_path = Path(sys.argv[0]) - has_dispatch = juju_exec_path.name == 'dispatch' - if has_dispatch: - # The executable was 'dispatch', which means the actual hook we want to - # run needs to be looked up in the JUJU_DISPATCH_PATH env var, where it - # should be a path relative to the charm directory (the directory that - # holds `dispatch`). If that path actually exists, we want to run that - # before continuing. - dispatch_path = juju_exec_path.parent / Path(os.environ['JUJU_DISPATCH_PATH']) - if dispatch_path.exists() and dispatch_path.resolve() != juju_exec_path.resolve(): - argv = sys.argv.copy() - argv[0] = str(dispatch_path) - try: - subprocess.run(argv, check=True) - except subprocess.CalledProcessError as e: - logger.warning("hook %s exited with status %d", dispatch_path, e.returncode) - sys.exit(e.returncode) - juju_exec_path = dispatch_path - juju_event_name = juju_exec_path.name.replace('-', '_') - if juju_exec_path.parent.name == 'actions': - juju_event_name = '{}_action'.format(juju_event_name) - - metadata, actions_metadata = _load_metadata(charm_dir) - meta = ops.charm.CharmMeta(metadata, actions_metadata) - unit_name = os.environ['JUJU_UNIT_NAME'] - model = ops.model.Model(unit_name, meta, model_backend) - - # TODO: If Juju unit agent crashes after exit(0) from the charm code - # the framework will commit the snapshot but Juju will not commit its - # operation. - charm_state_path = charm_dir / CHARM_STATE_FILE - framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) - try: - charm = charm_class(framework, None) - - if not has_dispatch: - # When a charm is force-upgraded and a unit is in an error state Juju - # does not run upgrade-charm and instead runs the failed hook followed - # by config-changed. Given the nature of force-upgrading the hook setup - # code is not triggered on config-changed. - # - # 'start' event is included as Juju does not fire the install event for - # K8s charms (see LP: #1854635). - if (juju_event_name in ('install', 'start', 'upgrade_charm') - or juju_event_name.endswith('_storage_attached')): - _setup_event_links(charm_dir, charm) - - # TODO: Remove the collect_metrics check below as soon as the relevant - # Juju changes are made. - # - # Skip reemission of deferred events for collect-metrics events because - # they do not have the full access to all hook tools. - if juju_event_name != 'collect_metrics': - framework.reemit() - - _emit_charm_event(charm, juju_event_name) - - framework.commit() - finally: - framework.close() diff --git a/magma/squid_cnf/charms/squid/metadata.yaml b/magma/squid_cnf/charms/squid/metadata.yaml index aa3bbfa1..aabf09bc 100644 --- a/magma/squid_cnf/charms/squid/metadata.yaml +++ b/magma/squid_cnf/charms/squid/metadata.yaml @@ -14,10 +14,11 @@ deployment: type: stateful service: loadbalancer storage: - docker: - type: filesystem - location: /srv/docker/squid spool: type: filesystem location: /var/spool/squid - +resources: + image: + type: oci-image + description: OSM docker image for LCM + upstream-source: "domfleischmann/squid-python" \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/mod/.empty b/magma/squid_cnf/charms/squid/mod/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/.flake8 b/magma/squid_cnf/charms/squid/mod/operator/.flake8 deleted file mode 100644 index 61d90815..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.flake8 +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -max-line-length = 99 diff --git a/magma/squid_cnf/charms/squid/mod/operator/.gitignore b/magma/squid_cnf/charms/squid/mod/operator/.gitignore deleted file mode 100644 index 5596c502..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -__pycache__ -/sandbox -.idea -docs/_build diff --git a/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml b/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml deleted file mode 100644 index ee5cf263..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.readthedocs.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: 2 # required -formats: [] # i.e. no extra formats (for now) -python: - version: "3.5" - install: - - requirements: docs/requirements.txt - - requirements: requirements.txt diff --git a/magma/squid_cnf/charms/squid/mod/operator/.travis.yml b/magma/squid_cnf/charms/squid/mod/operator/.travis.yml deleted file mode 100644 index f222ba8b..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -dist: bionic - -language: python - -arch: - - amd64 - - arm64 - -python: - - "3.5" - - "3.6" - - "3.7" - - "3.8" - -matrix: - include: - - os: osx - language: generic - -install: - - pip3 install pyyaml autopep8 flake8 - -script: - - ./run_tests diff --git a/magma/squid_cnf/charms/squid/mod/operator/README.md b/magma/squid_cnf/charms/squid/mod/operator/README.md deleted file mode 100644 index 347bfc8e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/README.md +++ /dev/null @@ -1,137 +0,0 @@ -# The Operator Framework - -The Operator Framework provides a simple, lightweight, and powerful way of encapsulating operational experience in code. - -The framework will help you to: - -* model the integration of your services -* manage the lifecycle of your application -* create reusable and scalable components -* keep your code simple and readable - -## Getting Started - -The following overall structure for your charm directory is recommended: - -``` -. -├── config.yaml -├── metadata.yaml -├── mod/ -├── lib/ -│ └── ops -> ../mod/operator/ops -├── src/ -│ └── charm.py -└── hooks/ - ├── install -> ../src/charm.py - └── start -> ../src/charm.py # for k8s charms per below -``` - -The `mod/` directory should contain the operator framework dependency as a git -submodule: - -``` -git submodule add https://github.com/canonical/operator mod/operator -``` - -Then symlink from the git submodule for the operator framework into the `lib/` -directory of your charm so it can be imported at run time: - -``` -ln -s ../mod/operator/ops lib/ops -``` - -Other dependencies included as git submodules can be added in the `mod/` -directory and symlinked into `lib/` as well. - -You can sync subsequent changes from the framework and other submodule -dependencies by running: - -``` -git submodule update -``` - -Those cloning and checking out the source for your charm for the first time -will need to run: - -``` -git submodule update --init -``` - -Your `src/charm.py` is the entry point for your charm logic. It should be set -to executable and use Python 3.6 or greater. At a minimum, it needs to define -a subclass of `CharmBase` and pass that into the framework's `main` function: - -```python -import sys -sys.path.append('lib') # noqa: E402 - -from ops.charm import CharmBase -from ops.main import main - - -class MyCharm(CharmBase): - pass - - -if __name__ == "__main__": - main(MyCharm) -``` - -This charm does nothing, because the `MyCharm` class passed to the operator -framework's `main` function is empty. Functionality can be added to the charm -by instructing it to observe particular Juju events when the `MyCharm` object -is initialized. For example, - -```python -class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.framework.observe(self.on.start, self.on_start) - - def on_start(self, event): - # Handle the start event here. -``` - -Every standard event in Juju may be observed that way, and you can also easily -define your own events in your custom types. - -> The second argument to `observe` can be either the handler as a bound -> method, or the observer itself if the handler is a method of the observer -> that follows the conventional naming pattern. That is, in this case, we -> could have called just `self.framework.observe(self.on.start, self)`. - -The `hooks/` directory must contain a symlink to your `src/charm.py` entry -point so that Juju can call it. You only need to set up the `hooks/install` link -(`hooks/start` for K8s charms, until [lp#1854635](https://bugs.launchpad.net/juju/+bug/1854635) -is resolved), and the framework will create all others at runtime. - -Once your charm is ready, upload it to the charm store and deploy it as -normal with: - -``` -# Replace ${CHARM} with the name of the charm. -charm push . cs:~${USER}/${CHARM} -# Replace ${VERSION} with the version created by `charm push`. -charm release cs:~${USER}/${CHARM}-${VERSION} -charm grant cs:~${USER}/${CHARM}-${VERSION} everyone -# And now deploy your charm. -juju deploy cs:~${USER}/$CHARM -``` - -Alternatively, to deploy directly from local disk, run: - -``` -juju deploy . -``` - -# Operator Framework development - -If you want to work in the framework *itself* you will need the following depenencies installed in your system: - -- Python >= 3.5 -- PyYAML -- autopep8 -- flake8 - -Then you can try `./run_tests`, it should all go green. diff --git a/magma/squid_cnf/charms/squid/mod/operator/build_docs b/magma/squid_cnf/charms/squid/mod/operator/build_docs deleted file mode 100755 index af8b892f..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/build_docs +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -set -e - -flavour=html - -if [ "$1" ]; then - if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then - flavour=help - else - flavour="$1" - fi - shift -fi - -cd docs - -sphinx-build -M "$flavour" . _build "$@" diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py b/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py deleted file mode 100644 index bd78ed2a..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/conf.py +++ /dev/null @@ -1,89 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For a full list of options see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - - -# -- Path setup -------------------------------------------------------------- - -from pathlib import Path -import sys -sys.path.insert(0, str(Path(__file__).parent.parent)) - - -# -- Project information ----------------------------------------------------- - -project = 'The Operator Framework' -copyright = '2019-2020, Canonical Ltd.' -author = 'Canonical Ltd' - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.todo', - 'sphinx.ext.viewcode', -] - -# The document name of the “master” document, that is, the document -# that contains the root toctree directive. -master_doc = 'index' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -# html_theme = 'nature' # 'alabaster' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - - -# -- Options for sphinx.ext.todo --------------------------------------------- - -# If this is True, todo and todolist produce output, else they -# produce nothing. The default is False. -todo_include_todos = False - - -# -- Options for sphinx.ext.autodoc ------------------------------------------ - -# This value controls how to represents typehints. The setting takes the -# following values: -# 'signature' – Show typehints as its signature (default) -# 'description' – Show typehints as content of function or method -# 'none' – Do not show typehints -autodoc_typehints = 'description' - -# This value selects what content will be inserted into the main body of an -# autoclass directive. The possible values are: -# 'class' - Only the class’ docstring is inserted. This is the -# default. You can still document __init__ as a separate method -# using automethod or the members option to autoclass. -# 'both' - Both the class’ and the __init__ method’s docstring are -# concatenated and inserted. -# 'init' - Only the __init__ method’s docstring is inserted. -autoclass_content = 'both' - -autodoc_default_options = { - 'members': None, # None here means "yes" - 'undoc-members': None, - 'show-inheritance': None, -} diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst b/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst deleted file mode 100644 index 424d78d4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/index.rst +++ /dev/null @@ -1,58 +0,0 @@ - -Welcome to The Operator Framework's documentation! -================================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - -ops package -=========== - -.. automodule:: ops - -Submodules ----------- - -ops.charm module ----------------- - -.. automodule:: ops.charm - -ops.framework module --------------------- - -.. automodule:: ops.framework - -ops.jujuversion module ----------------------- - -.. automodule:: ops.jujuversion - -ops.log module --------------- - -.. automodule:: ops.log - -ops.main module ---------------- - -.. automodule:: ops.main - -ops.model module ----------------- - -.. automodule:: ops.model - -ops.testing module ------------------- - -.. automodule:: ops.testing - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt b/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt deleted file mode 100644 index 37b11036..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -sphinx<2 diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py b/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py deleted file mode 100755 index 4682c20e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/charm.py +++ /dev/null @@ -1,562 +0,0 @@ -# Copyright 2019-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 pathlib -import typing - -import yaml - -from ops.framework import Object, EventSource, EventBase, Framework, ObjectEvents -from ops import model - - -class HookEvent(EventBase): - """A base class for events that trigger because of a Juju hook firing.""" - - -class ActionEvent(EventBase): - """A base class for events that trigger when a user asks for an Action to be run. - - To read the parameters for the action, see the instance variable `params`. - To respond with the result of the action, call `set_results`. To add progress - messages that are visible as the action is progressing use `log`. - - :ivar params: The parameters passed to the action (read by action-get) - """ - - def defer(self): - """Action events are not deferable like other events. - - This is because an action runs synchronously and the user is waiting for the result. - """ - raise RuntimeError('cannot defer action events') - - def restore(self, snapshot: dict) -> None: - """Used by the operator framework to record the action. - - Not meant to be called directly by Charm code. - """ - env_action_name = os.environ.get('JUJU_ACTION_NAME') - event_action_name = self.handle.kind[:-len('_action')].replace('_', '-') - if event_action_name != env_action_name: - # This could only happen if the dev manually emits the action, or from a bug. - raise RuntimeError('action event kind does not match current action') - # Params are loaded at restore rather than __init__ because - # the model is not available in __init__. - self.params = self.framework.model._backend.action_get() - - def set_results(self, results: typing.Mapping) -> None: - """Report the result of the action. - - Args: - results: The result of the action as a Dict - """ - self.framework.model._backend.action_set(results) - - def log(self, message: str) -> None: - """Send a message that a user will see while the action is running. - - Args: - message: The message for the user. - """ - self.framework.model._backend.action_log(message) - - def fail(self, message: str = '') -> None: - """Report that this action has failed. - - Args: - message: Optional message to record why it has failed. - """ - self.framework.model._backend.action_fail(message) - - -class InstallEvent(HookEvent): - """Represents the `install` hook from Juju.""" - - -class StartEvent(HookEvent): - """Represents the `start` hook from Juju.""" - - -class StopEvent(HookEvent): - """Represents the `stop` hook from Juju.""" - - -class RemoveEvent(HookEvent): - """Represents the `remove` hook from Juju. """ - - -class ConfigChangedEvent(HookEvent): - """Represents the `config-changed` hook from Juju.""" - - -class UpdateStatusEvent(HookEvent): - """Represents the `update-status` hook from Juju.""" - - -class UpgradeCharmEvent(HookEvent): - """Represents the `upgrade-charm` hook from Juju. - - This will be triggered when a user has run `juju upgrade-charm`. It is run after Juju - has unpacked the upgraded charm code, and so this event will be handled with new code. - """ - - -class PreSeriesUpgradeEvent(HookEvent): - """Represents the `pre-series-upgrade` hook from Juju. - - This happens when a user has run `juju upgrade-series MACHINE prepare` and - will fire for each unit that is running on the machine, telling them that - the user is preparing to upgrade the Machine's series (eg trusty->bionic). - The charm should take actions to prepare for the upgrade (a database charm - would want to write out a version-independent dump of the database, so that - when a new version of the database is available in a new series, it can be - used.) - Once all units on a machine have run `pre-series-upgrade`, the user will - initiate the steps to actually upgrade the machine (eg `do-release-upgrade`). - When the upgrade has been completed, the :class:`PostSeriesUpgradeEvent` will fire. - """ - - -class PostSeriesUpgradeEvent(HookEvent): - """Represents the `post-series-upgrade` hook from Juju. - - This is run after the user has done a distribution upgrade (or rolled back - and kept the same series). It is called in response to - `juju upgrade-series MACHINE complete`. Charms are expected to do whatever - steps are necessary to reconfigure their applications for the new series. - """ - - -class LeaderElectedEvent(HookEvent): - """Represents the `leader-elected` hook from Juju. - - Juju will trigger this when a new lead unit is chosen for a given application. - This represents the leader of the charm information (not necessarily the primary - of a running application). The main utility is that charm authors can know - that only one unit will be a leader at any given time, so they can do - configuration, etc, that would otherwise require coordination between units. - (eg, selecting a password for a new relation) - """ - - -class LeaderSettingsChangedEvent(HookEvent): - """Represents the `leader-settings-changed` hook from Juju. - - Deprecated. This represents when a lead unit would call `leader-set` to inform - the other units of an application that they have new information to handle. - This has been deprecated in favor of using a Peer relation, and having the - leader set a value in the Application data bag for that peer relation. - (see :class:`RelationChangedEvent`). - """ - - -class CollectMetricsEvent(HookEvent): - """Represents the `collect-metrics` hook from Juju. - - Note that events firing during a CollectMetricsEvent are currently - sandboxed in how they can interact with Juju. To report metrics - use :meth:`.add_metrics`. - """ - - def add_metrics(self, metrics: typing.Mapping, labels: typing.Mapping = None) -> None: - """Record metrics that have been gathered by the charm for this unit. - - Args: - metrics: A collection of {key: float} pairs that contains the - metrics that have been gathered - labels: {key:value} strings that can be applied to the - metrics that are being gathered - """ - self.framework.model._backend.add_metrics(metrics, labels) - - -class RelationEvent(HookEvent): - """A base class representing the various relation lifecycle events. - - Charmers should not be creating RelationEvents directly. The events will be - generated by the framework from Juju related events. Users can observe them - from the various `CharmBase.on[relation_name].relation_*` events. - - Attributes: - relation: The Relation involved in this event - app: The remote application that has triggered this event - unit: The remote unit that has triggered this event. This may be None - if the relation event was triggered as an Application level event - """ - - def __init__(self, handle, relation, app=None, unit=None): - super().__init__(handle) - - if unit is not None and unit.app != app: - raise RuntimeError( - 'cannot create RelationEvent with application {} and unit {}'.format(app, unit)) - - self.relation = relation - self.app = app - self.unit = unit - - def snapshot(self) -> dict: - """Used by the framework to serialize the event to disk. - - Not meant to be called by Charm code. - """ - snapshot = { - 'relation_name': self.relation.name, - 'relation_id': self.relation.id, - } - if self.app: - snapshot['app_name'] = self.app.name - if self.unit: - snapshot['unit_name'] = self.unit.name - return snapshot - - def restore(self, snapshot: dict) -> None: - """Used by the framework to deserialize the event from disk. - - Not meant to be called by Charm code. - """ - self.relation = self.framework.model.get_relation( - snapshot['relation_name'], snapshot['relation_id']) - - app_name = snapshot.get('app_name') - if app_name: - self.app = self.framework.model.get_app(app_name) - else: - self.app = None - - unit_name = snapshot.get('unit_name') - if unit_name: - self.unit = self.framework.model.get_unit(unit_name) - else: - self.unit = None - - -class RelationCreatedEvent(RelationEvent): - """Represents the `relation-created` hook from Juju. - - This is triggered when a new relation to another app is added in Juju. This - can occur before units for those applications have started. All existing - relations should be established before start. - """ - - -class RelationJoinedEvent(RelationEvent): - """Represents the `relation-joined` hook from Juju. - - This is triggered whenever a new unit of a related application joins the relation. - (eg, a unit was added to an existing related app, or a new relation was established - with an application that already had units.) - """ - - -class RelationChangedEvent(RelationEvent): - """Represents the `relation-changed` hook from Juju. - - This is triggered whenever there is a change to the data bucket for a related - application or unit. Look at `event.relation.data[event.unit/app]` to see the - new information. - """ - - -class RelationDepartedEvent(RelationEvent): - """Represents the `relation-departed` hook from Juju. - - This is the inverse of the RelationJoinedEvent, representing when a unit - is leaving the relation (the unit is being removed, the app is being removed, - the relation is being removed). It is fired once for each unit that is - going away. - """ - - -class RelationBrokenEvent(RelationEvent): - """Represents the `relation-broken` hook from Juju. - - If a relation is being removed (`juju remove-relation` or `juju remove-application`), - once all the units have been removed, RelationBrokenEvent will fire to signal - that the relationship has been fully terminated. - """ - - -class StorageEvent(HookEvent): - """Base class representing Storage related events.""" - - -class StorageAttachedEvent(StorageEvent): - """Represents the `storage-attached` hook from Juju. - - Called when new storage is available for the charm to use. - """ - - -class StorageDetachingEvent(StorageEvent): - """Represents the `storage-detaching` hook from Juju. - - Called when storage a charm has been using is going away. - """ - - -class CharmEvents(ObjectEvents): - """The events that are generated by Juju in response to the lifecycle of an application.""" - - install = EventSource(InstallEvent) - start = EventSource(StartEvent) - stop = EventSource(StopEvent) - remove = EventSource(RemoveEvent) - update_status = EventSource(UpdateStatusEvent) - config_changed = EventSource(ConfigChangedEvent) - upgrade_charm = EventSource(UpgradeCharmEvent) - pre_series_upgrade = EventSource(PreSeriesUpgradeEvent) - post_series_upgrade = EventSource(PostSeriesUpgradeEvent) - leader_elected = EventSource(LeaderElectedEvent) - leader_settings_changed = EventSource(LeaderSettingsChangedEvent) - collect_metrics = EventSource(CollectMetricsEvent) - - -class CharmBase(Object): - """Base class that represents the Charm overall. - - Usually this initialization is done by ops.main.main() rather than Charm authors - directly instantiating a Charm. - - Args: - framework: The framework responsible for managing the Model and events for this - Charm. - key: Arbitrary key to distinguish this instance of CharmBase from another. - Generally is None when initialized by the framework. For charms instantiated by - main.main(), this is currenly None. - Attributes: - on: Defines all events that the Charm will fire. - """ - - on = CharmEvents() - - def __init__(self, framework: Framework, key: typing.Optional[str]): - """Initialize the Charm with its framework and application name. - - """ - super().__init__(framework, key) - - for relation_name in self.framework.meta.relations: - relation_name = relation_name.replace('-', '_') - self.on.define_event(relation_name + '_relation_created', RelationCreatedEvent) - self.on.define_event(relation_name + '_relation_joined', RelationJoinedEvent) - self.on.define_event(relation_name + '_relation_changed', RelationChangedEvent) - self.on.define_event(relation_name + '_relation_departed', RelationDepartedEvent) - self.on.define_event(relation_name + '_relation_broken', RelationBrokenEvent) - - for storage_name in self.framework.meta.storages: - storage_name = storage_name.replace('-', '_') - self.on.define_event(storage_name + '_storage_attached', StorageAttachedEvent) - self.on.define_event(storage_name + '_storage_detaching', StorageDetachingEvent) - - for action_name in self.framework.meta.actions: - action_name = action_name.replace('-', '_') - self.on.define_event(action_name + '_action', ActionEvent) - - @property - def app(self) -> model.Application: - """Application that this unit is part of.""" - return self.framework.model.app - - @property - def unit(self) -> model.Unit: - """Unit that this execution is responsible for.""" - return self.framework.model.unit - - @property - def meta(self) -> 'CharmMeta': - """CharmMeta of this charm. - """ - return self.framework.meta - - @property - def charm_dir(self) -> pathlib.Path: - """Root directory of the Charm as it is running. - """ - return self.framework.charm_dir - - -class CharmMeta: - """Object containing the metadata for the charm. - - This is read from metadata.yaml and/or actions.yaml. Generally charms will - define this information, rather than reading it at runtime. This class is - mostly for the framework to understand what the charm has defined. - - The maintainers, tags, terms, series, and extra_bindings attributes are all - lists of strings. The requires, provides, peers, relations, storage, - resources, and payloads attributes are all mappings of names to instances - of the respective RelationMeta, StorageMeta, ResourceMeta, or PayloadMeta. - - The relations attribute is a convenience accessor which includes all of the - requires, provides, and peers RelationMeta items. If needed, the role of - the relation definition can be obtained from its role attribute. - - Attributes: - name: The name of this charm - summary: Short description of what this charm does - description: Long description for this charm - maintainers: A list of strings of the email addresses of the maintainers - of this charm. - tags: Charm store tag metadata for categories associated with this charm. - terms: Charm store terms that should be agreed to before this charm can - be deployed. (Used for things like licensing issues.) - series: The list of supported OS series that this charm can support. - The first entry in the list is the default series that will be - used by deploy if no other series is requested by the user. - subordinate: True/False whether this charm is intended to be used as a - subordinate charm. - min_juju_version: If supplied, indicates this charm needs features that - are not available in older versions of Juju. - requires: A dict of {name: :class:`RelationMeta` } for each 'requires' relation. - provides: A dict of {name: :class:`RelationMeta` } for each 'provides' relation. - peers: A dict of {name: :class:`RelationMeta` } for each 'peer' relation. - relations: A dict containing all :class:`RelationMeta` attributes (merged from other - sections) - storages: A dict of {name: :class:`StorageMeta`} for each defined storage. - resources: A dict of {name: :class:`ResourceMeta`} for each defined resource. - payloads: A dict of {name: :class:`PayloadMeta`} for each defined payload. - extra_bindings: A dict of additional named bindings that a charm can use - for network configuration. - actions: A dict of {name: :class:`ActionMeta`} for actions that the charm has defined. - Args: - raw: a mapping containing the contents of metadata.yaml - actions_raw: a mapping containing the contents of actions.yaml - """ - - def __init__(self, raw: dict = {}, actions_raw: dict = {}): - self.name = raw.get('name', '') - self.summary = raw.get('summary', '') - self.description = raw.get('description', '') - self.maintainers = [] - if 'maintainer' in raw: - self.maintainers.append(raw['maintainer']) - if 'maintainers' in raw: - self.maintainers.extend(raw['maintainers']) - self.tags = raw.get('tags', []) - self.terms = raw.get('terms', []) - self.series = raw.get('series', []) - self.subordinate = raw.get('subordinate', False) - self.min_juju_version = raw.get('min-juju-version') - self.requires = {name: RelationMeta('requires', name, rel) - for name, rel in raw.get('requires', {}).items()} - self.provides = {name: RelationMeta('provides', name, rel) - for name, rel in raw.get('provides', {}).items()} - # TODO: (jam 2020-05-11) The *role* should be 'peer' even though it comes from the - # 'peers' section. - self.peers = {name: RelationMeta('peers', name, rel) - for name, rel in raw.get('peers', {}).items()} - self.relations = {} - self.relations.update(self.requires) - self.relations.update(self.provides) - self.relations.update(self.peers) - self.storages = {name: StorageMeta(name, storage) - for name, storage in raw.get('storage', {}).items()} - self.resources = {name: ResourceMeta(name, res) - for name, res in raw.get('resources', {}).items()} - self.payloads = {name: PayloadMeta(name, payload) - for name, payload in raw.get('payloads', {}).items()} - self.extra_bindings = raw.get('extra-bindings', {}) - self.actions = {name: ActionMeta(name, action) for name, action in actions_raw.items()} - - @classmethod - def from_yaml( - cls, metadata: typing.Union[str, typing.TextIO], - actions: typing.Optional[typing.Union[str, typing.TextIO]] = None): - """Instantiate a CharmMeta from a YAML description of metadata.yaml. - - Args: - metadata: A YAML description of charm metadata (name, relations, etc.) - This can be a simple string, or a file-like object. (passed to `yaml.safe_load`). - actions: YAML description of Actions for this charm (eg actions.yaml) - """ - meta = yaml.safe_load(metadata) - raw_actions = {} - if actions is not None: - raw_actions = yaml.safe_load(actions) - return cls(meta, raw_actions) - - -class RelationMeta: - """Object containing metadata about a relation definition. - - Should not be constructed directly by Charm code. Is gotten from one of - :attr:`CharmMeta.peers`, :attr:`CharmMeta.requires`, :attr:`CharmMeta.provides`, - :attr:`CharmMeta.relations`. - - Attributes: - role: This is one of requires/provides/peers - relation_name: Name of this relation from metadata.yaml - interface_name: Optional definition of the interface protocol. - scope: "global" or "container" scope based on how the relation should be used. - """ - - def __init__(self, role, relation_name, raw): - self.role = role - self.relation_name = relation_name - self.interface_name = raw['interface'] - self.scope = raw.get('scope') - - -class StorageMeta: - """Object containing metadata about a storage definition.""" - - def __init__(self, name, raw): - self.storage_name = name - self.type = raw['type'] - self.description = raw.get('description', '') - self.shared = raw.get('shared', False) - self.read_only = raw.get('read-only', False) - self.minimum_size = raw.get('minimum-size') - self.location = raw.get('location') - self.multiple_range = None - if 'multiple' in raw: - range = raw['multiple']['range'] - if '-' not in range: - self.multiple_range = (int(range), int(range)) - else: - range = range.split('-') - self.multiple_range = (int(range[0]), int(range[1]) if range[1] else None) - - -class ResourceMeta: - """Object containing metadata about a resource definition.""" - - def __init__(self, name, raw): - self.resource_name = name - self.type = raw['type'] - self.filename = raw.get('filename', None) - self.description = raw.get('description', '') - - -class PayloadMeta: - """Object containing metadata about a payload definition.""" - - def __init__(self, name, raw): - self.payload_name = name - self.type = raw['type'] - - -class ActionMeta: - """Object containing metadata about an action's definition.""" - - def __init__(self, name, raw=None): - raw = raw or {} - self.name = name - self.title = raw.get('title', '') - self.description = raw.get('description', '') - self.parameters = raw.get('params', {}) # {: } - self.required = raw.get('required', []) # [, ...] diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py b/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py deleted file mode 100755 index 51d46ba1..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/framework.py +++ /dev/null @@ -1,1134 +0,0 @@ -# Copyright 2019-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 collections -import collections.abc -import inspect -import keyword -import marshal -import os -import pdb -import pickle -import re -import sqlite3 -import sys -import types -import weakref -from datetime import timedelta - -from ops import charm - - -class Handle: - """Handle defines a name for an object in the form of a hierarchical path. - - The provided parent is the object (or that object's handle) that this handle - sits under, or None if the object identified by this handle stands by itself - as the root of its own hierarchy. - - The handle kind is a string that defines a namespace so objects with the - same parent and kind will have unique keys. - - The handle key is a string uniquely identifying the object. No other objects - under the same parent and kind may have the same key. - """ - - def __init__(self, parent, kind, key): - if parent and not isinstance(parent, Handle): - parent = parent.handle - self._parent = parent - self._kind = kind - self._key = key - if parent: - if key: - self._path = "{}/{}[{}]".format(parent, kind, key) - else: - self._path = "{}/{}".format(parent, kind) - else: - if key: - self._path = "{}[{}]".format(kind, key) - else: - self._path = "{}".format(kind) - - def nest(self, kind, key): - return Handle(self, kind, key) - - def __hash__(self): - return hash((self.parent, self.kind, self.key)) - - def __eq__(self, other): - return (self.parent, self.kind, self.key) == (other.parent, other.kind, other.key) - - def __str__(self): - return self.path - - @property - def parent(self): - return self._parent - - @property - def kind(self): - return self._kind - - @property - def key(self): - return self._key - - @property - def path(self): - return self._path - - @classmethod - def from_path(cls, path): - handle = None - for pair in path.split("/"): - pair = pair.split("[") - good = False - if len(pair) == 1: - kind, key = pair[0], None - good = True - elif len(pair) == 2: - kind, key = pair - if key and key[-1] == ']': - key = key[:-1] - good = True - if not good: - raise RuntimeError("attempted to restore invalid handle path {}".format(path)) - handle = Handle(handle, kind, key) - return handle - - -class EventBase: - - def __init__(self, handle): - self.handle = handle - self.deferred = False - - def defer(self): - self.deferred = True - - def snapshot(self): - """Return the snapshot data that should be persisted. - - Subclasses must override to save any custom state. - """ - return None - - def restore(self, snapshot): - """Restore the value state from the given snapshot. - - Subclasses must override to restore their custom state. - """ - self.deferred = False - - -class EventSource: - """EventSource wraps an event type with a descriptor to facilitate observing and emitting. - - It is generally used as: - - class SomethingHappened(EventBase): - pass - - class SomeObject(Object): - something_happened = EventSource(SomethingHappened) - - With that, instances of that type will offer the someobj.something_happened - attribute which is a BoundEvent and may be used to emit and observe the event. - """ - - def __init__(self, event_type): - if not isinstance(event_type, type) or not issubclass(event_type, EventBase): - raise RuntimeError( - 'Event requires a subclass of EventBase as an argument, got {}'.format(event_type)) - self.event_type = event_type - self.event_kind = None - self.emitter_type = None - - def _set_name(self, emitter_type, event_kind): - if self.event_kind is not None: - raise RuntimeError( - 'EventSource({}) reused as {}.{} and {}.{}'.format( - self.event_type.__name__, - self.emitter_type.__name__, - self.event_kind, - emitter_type.__name__, - event_kind, - )) - self.event_kind = event_kind - self.emitter_type = emitter_type - - def __get__(self, emitter, emitter_type=None): - if emitter is None: - return self - # Framework might not be available if accessed as CharmClass.on.event - # rather than charm_instance.on.event, but in that case it couldn't be - # emitted anyway, so there's no point to registering it. - framework = getattr(emitter, 'framework', None) - if framework is not None: - framework.register_type(self.event_type, emitter, self.event_kind) - return BoundEvent(emitter, self.event_type, self.event_kind) - - -class BoundEvent: - - def __repr__(self): - return ''.format( - self.event_type.__name__, - type(self.emitter).__name__, - self.event_kind, - hex(id(self)), - ) - - def __init__(self, emitter, event_type, event_kind): - self.emitter = emitter - self.event_type = event_type - self.event_kind = event_kind - - def emit(self, *args, **kwargs): - """Emit event to all registered observers. - - The current storage state is committed before and after each observer is notified. - """ - framework = self.emitter.framework - key = framework._next_event_key() - event = self.event_type(Handle(self.emitter, self.event_kind, key), *args, **kwargs) - framework._emit(event) - - -class HandleKind: - """Helper descriptor to define the Object.handle_kind field. - - The handle_kind for an object defaults to its type name, but it may - be explicitly overridden if desired. - """ - - def __get__(self, obj, obj_type): - kind = obj_type.__dict__.get("handle_kind") - if kind: - return kind - return obj_type.__name__ - - -class _Metaclass(type): - """Helper class to ensure proper instantiation of Object-derived classes. - - This class currently has a single purpose: events derived from EventSource - that are class attributes of Object-derived classes need to be told what - their name is in that class. For example, in - - class SomeObject(Object): - something_happened = EventSource(SomethingHappened) - - the instance of EventSource needs to know it's called 'something_happened'. - - Starting from python 3.6 we could use __set_name__ on EventSource for this, - but until then this (meta)class does the equivalent work. - - TODO: when we drop support for 3.5 drop this class, and rename _set_name in - EventSource to __set_name__; everything should continue to work. - - """ - - def __new__(typ, *a, **kw): - k = super().__new__(typ, *a, **kw) - # k is now the Object-derived class; loop over its class attributes - for n, v in vars(k).items(): - # we could do duck typing here if we want to support - # non-EventSource-derived shenanigans. We don't. - if isinstance(v, EventSource): - # this is what 3.6+ does automatically for us: - v._set_name(k, n) - return k - - -class Object(metaclass=_Metaclass): - - handle_kind = HandleKind() - - def __init__(self, parent, key): - kind = self.handle_kind - if isinstance(parent, Framework): - self.framework = parent - # Avoid Framework instances having a circular reference to themselves. - if self.framework is self: - self.framework = weakref.proxy(self.framework) - self.handle = Handle(None, kind, key) - else: - self.framework = parent.framework - self.handle = Handle(parent, kind, key) - self.framework._track(self) - - # TODO Detect conflicting handles here. - - @property - def model(self): - return self.framework.model - - -class ObjectEvents(Object): - """Convenience type to allow defining .on attributes at class level.""" - - handle_kind = "on" - - def __init__(self, parent=None, key=None): - if parent is not None: - super().__init__(parent, key) - else: - self._cache = weakref.WeakKeyDictionary() - - def __get__(self, emitter, emitter_type): - if emitter is None: - return self - instance = self._cache.get(emitter) - if instance is None: - # Same type, different instance, more data. Doing this unusual construct - # means people can subclass just this one class to have their own 'on'. - instance = self._cache[emitter] = type(self)(emitter) - return instance - - @classmethod - def define_event(cls, event_kind, event_type): - """Define an event on this type at runtime. - - cls: a type to define an event on. - - event_kind: an attribute name that will be used to access the - event. Must be a valid python identifier, not be a keyword - or an existing attribute. - - event_type: a type of the event to define. - - """ - prefix = 'unable to define an event with event_kind that ' - if not event_kind.isidentifier(): - raise RuntimeError(prefix + 'is not a valid python identifier: ' + event_kind) - elif keyword.iskeyword(event_kind): - raise RuntimeError(prefix + 'is a python keyword: ' + event_kind) - try: - getattr(cls, event_kind) - raise RuntimeError( - prefix + 'overlaps with an existing type {} attribute: {}'.format(cls, event_kind)) - except AttributeError: - pass - - event_descriptor = EventSource(event_type) - event_descriptor._set_name(cls, event_kind) - setattr(cls, event_kind, event_descriptor) - - def events(self): - """Return a mapping of event_kinds to bound_events for all available events. - """ - events_map = {} - # We have to iterate over the class rather than instance to allow for properties which - # might call this method (e.g., event views), leading to infinite recursion. - for attr_name, attr_value in inspect.getmembers(type(self)): - if isinstance(attr_value, EventSource): - # We actually care about the bound_event, however, since it - # provides the most info for users of this method. - event_kind = attr_name - bound_event = getattr(self, event_kind) - events_map[event_kind] = bound_event - return events_map - - def __getitem__(self, key): - return PrefixedEvents(self, key) - - -class PrefixedEvents: - - def __init__(self, emitter, key): - self._emitter = emitter - self._prefix = key.replace("-", "_") + '_' - - def __getattr__(self, name): - return getattr(self._emitter, self._prefix + name) - - -class PreCommitEvent(EventBase): - pass - - -class CommitEvent(EventBase): - pass - - -class FrameworkEvents(ObjectEvents): - pre_commit = EventSource(PreCommitEvent) - commit = EventSource(CommitEvent) - - -class NoSnapshotError(Exception): - - def __init__(self, handle_path): - self.handle_path = handle_path - - def __str__(self): - return 'no snapshot data found for {} object'.format(self.handle_path) - - -class NoTypeError(Exception): - - def __init__(self, handle_path): - self.handle_path = handle_path - - def __str__(self): - return "cannot restore {} since no class was registered for it".format(self.handle_path) - - -class SQLiteStorage: - - DB_LOCK_TIMEOUT = timedelta(hours=1) - - def __init__(self, filename): - # The isolation_level argument is set to None such that the implicit - # transaction management behavior of the sqlite3 module is disabled. - self._db = sqlite3.connect(str(filename), - isolation_level=None, - timeout=self.DB_LOCK_TIMEOUT.total_seconds()) - self._setup() - - def _setup(self): - # Make sure that the database is locked until the connection is closed, - # not until the transaction ends. - self._db.execute("PRAGMA locking_mode=EXCLUSIVE") - c = self._db.execute("BEGIN") - c.execute("SELECT count(name) FROM sqlite_master WHERE type='table' AND name='snapshot'") - if c.fetchone()[0] == 0: - # Keep in mind what might happen if the process dies somewhere below. - # The system must not be rendered permanently broken by that. - self._db.execute("CREATE TABLE snapshot (handle TEXT PRIMARY KEY, data BLOB)") - self._db.execute(''' - CREATE TABLE notice ( - sequence INTEGER PRIMARY KEY AUTOINCREMENT, - event_path TEXT, - observer_path TEXT, - method_name TEXT) - ''') - self._db.commit() - - def close(self): - self._db.close() - - def commit(self): - self._db.commit() - - # There's commit but no rollback. For abort to be supported, we'll need logic that - # can rollback decisions made by third-party code in terms of the internal state - # of objects that have been snapshotted, and hooks to let them know about it and - # take the needed actions to undo their logic until the last snapshot. - # This is doable but will increase significantly the chances for mistakes. - - def save_snapshot(self, handle_path, snapshot_data): - self._db.execute("REPLACE INTO snapshot VALUES (?, ?)", (handle_path, snapshot_data)) - - def load_snapshot(self, handle_path): - c = self._db.cursor() - c.execute("SELECT data FROM snapshot WHERE handle=?", (handle_path,)) - row = c.fetchone() - if row: - return row[0] - return None - - def drop_snapshot(self, handle_path): - self._db.execute("DELETE FROM snapshot WHERE handle=?", (handle_path,)) - - def save_notice(self, event_path, observer_path, method_name): - self._db.execute('INSERT INTO notice VALUES (NULL, ?, ?, ?)', - (event_path, observer_path, method_name)) - - def drop_notice(self, event_path, observer_path, method_name): - self._db.execute(''' - DELETE FROM notice - WHERE event_path=? - AND observer_path=? - AND method_name=? - ''', (event_path, observer_path, method_name)) - - def notices(self, event_path): - if event_path: - c = self._db.execute(''' - SELECT event_path, observer_path, method_name - FROM notice - WHERE event_path=? - ORDER BY sequence - ''', (event_path,)) - else: - c = self._db.execute(''' - SELECT event_path, observer_path, method_name - FROM notice - ORDER BY sequence - ''') - while True: - rows = c.fetchmany() - if not rows: - break - for row in rows: - yield tuple(row) - - -# the message to show to the user when a pdb breakpoint goes active -_BREAKPOINT_WELCOME_MESSAGE = """ -Starting pdb to debug charm operator. -Run `h` for help, `c` to continue, or `exit`/CTRL-d to abort. -Future breakpoints may interrupt execution again. -More details at https://discourse.jujucharms.com/t/debugging-charm-hooks - -""" - - -class Framework(Object): - - on = FrameworkEvents() - - # Override properties from Object so that we can set them in __init__. - model = None - meta = None - charm_dir = None - - def __init__(self, data_path, charm_dir, meta, model): - - super().__init__(self, None) - - self._data_path = data_path - self.charm_dir = charm_dir - self.meta = meta - self.model = model - self._observers = [] # [(observer_path, method_name, parent_path, event_key)] - self._observer = weakref.WeakValueDictionary() # {observer_path: observer} - self._objects = weakref.WeakValueDictionary() - self._type_registry = {} # {(parent_path, kind): cls} - self._type_known = set() # {cls} - - self._storage = SQLiteStorage(data_path) - - # We can't use the higher-level StoredState because it relies on events. - self.register_type(StoredStateData, None, StoredStateData.handle_kind) - stored_handle = Handle(None, StoredStateData.handle_kind, '_stored') - try: - self._stored = self.load_snapshot(stored_handle) - except NoSnapshotError: - self._stored = StoredStateData(self, '_stored') - self._stored['event_count'] = 0 - - # Hook into builtin breakpoint, so if Python >= 3.7, devs will be able to just do - # breakpoint(); if Python < 3.7, this doesn't affect anything - sys.breakpointhook = self.breakpoint - - # Flag to indicate that we already presented the welcome message in a debugger breakpoint - self._breakpoint_welcomed = False - - # Parse once the env var, which may be used multiple times later - debug_at = os.environ.get('JUJU_DEBUG_AT') - self._juju_debug_at = debug_at.split(',') if debug_at else () - - def close(self): - self._storage.close() - - def _track(self, obj): - """Track object and ensure it is the only object created using its handle path.""" - if obj is self: - # Framework objects don't track themselves - return - if obj.handle.path in self.framework._objects: - raise RuntimeError( - 'two objects claiming to be {} have been created'.format(obj.handle.path)) - self._objects[obj.handle.path] = obj - - def _forget(self, obj): - """Stop tracking the given object. See also _track.""" - self._objects.pop(obj.handle.path, None) - - def commit(self): - # Give a chance for objects to persist data they want to before a commit is made. - self.on.pre_commit.emit() - # Make sure snapshots are saved by instances of StoredStateData. Any possible state - # modifications in on_commit handlers of instances of other classes will not be persisted. - self.on.commit.emit() - # Save our event count after all events have been emitted. - self.save_snapshot(self._stored) - self._storage.commit() - - def register_type(self, cls, parent, kind=None): - if parent and not isinstance(parent, Handle): - parent = parent.handle - if parent: - parent_path = parent.path - else: - parent_path = None - if not kind: - kind = cls.handle_kind - self._type_registry[(parent_path, kind)] = cls - self._type_known.add(cls) - - def save_snapshot(self, value): - """Save a persistent snapshot of the provided value. - - The provided value must implement the following interface: - - value.handle = Handle(...) - value.snapshot() => {...} # Simple builtin types only. - value.restore(snapshot) # Restore custom state from prior snapshot. - """ - if type(value) not in self._type_known: - raise RuntimeError( - 'cannot save {} values before registering that type'.format(type(value).__name__)) - data = value.snapshot() - - # Use marshal as a validator, enforcing the use of simple types, as we later the - # information is really pickled, which is too error prone for future evolution of the - # stored data (e.g. if the developer stores a custom object and later changes its - # class name; when unpickling the original class will not be there and event - # data loading will fail). - try: - marshal.dumps(data) - except ValueError: - msg = "unable to save the data for {}, it must contain only simple types: {!r}" - raise ValueError(msg.format(value.__class__.__name__, data)) - - # Use pickle for serialization, so the value remains portable. - raw_data = pickle.dumps(data) - self._storage.save_snapshot(value.handle.path, raw_data) - - def load_snapshot(self, handle): - parent_path = None - if handle.parent: - parent_path = handle.parent.path - cls = self._type_registry.get((parent_path, handle.kind)) - if not cls: - raise NoTypeError(handle.path) - raw_data = self._storage.load_snapshot(handle.path) - if not raw_data: - raise NoSnapshotError(handle.path) - data = pickle.loads(raw_data) - obj = cls.__new__(cls) - obj.framework = self - obj.handle = handle - obj.restore(data) - self._track(obj) - return obj - - def drop_snapshot(self, handle): - self._storage.drop_snapshot(handle.path) - - def observe(self, bound_event, observer): - """Register observer to be called when bound_event is emitted. - - The bound_event is generally provided as an attribute of the object that emits - the event, and is created in this style: - - class SomeObject: - something_happened = Event(SomethingHappened) - - That event may be observed as: - - framework.observe(someobj.something_happened, self.on_something_happened) - - If the method to be called follows the name convention "on_", it - may be omitted from the observe call. That means the above is equivalent to: - - framework.observe(someobj.something_happened, self) - - """ - if not isinstance(bound_event, BoundEvent): - raise RuntimeError( - 'Framework.observe requires a BoundEvent as second parameter, got {}'.format( - bound_event)) - - event_type = bound_event.event_type - event_kind = bound_event.event_kind - emitter = bound_event.emitter - - self.register_type(event_type, emitter, event_kind) - - if hasattr(emitter, "handle"): - emitter_path = emitter.handle.path - else: - raise RuntimeError( - 'event emitter {} must have a "handle" attribute'.format(type(emitter).__name__)) - - method_name = None - if isinstance(observer, types.MethodType): - method_name = observer.__name__ - observer = observer.__self__ - else: - method_name = "on_" + event_kind - if not hasattr(observer, method_name): - raise RuntimeError( - 'Observer method not provided explicitly' - ' and {} type has no "{}" method'.format(type(observer).__name__, - method_name)) - - # Validate that the method has an acceptable call signature. - sig = inspect.signature(getattr(observer, method_name)) - # Self isn't included in the params list, so the first arg will be the event. - extra_params = list(sig.parameters.values())[1:] - if not sig.parameters: - raise TypeError( - '{}.{} must accept event parameter'.format(type(observer).__name__, method_name)) - elif any(param.default is inspect.Parameter.empty for param in extra_params): - # Allow for additional optional params, since there's no reason to exclude them, but - # required params will break. - raise TypeError( - '{}.{} has extra required parameter'.format(type(observer).__name__, method_name)) - - # TODO Prevent the exact same parameters from being registered more than once. - - self._observer[observer.handle.path] = observer - self._observers.append((observer.handle.path, method_name, emitter_path, event_kind)) - - def _next_event_key(self): - """Return the next event key that should be used, incrementing the internal counter.""" - # Increment the count first; this means the keys will start at 1, and 0 - # means no events have been emitted. - self._stored['event_count'] += 1 - return str(self._stored['event_count']) - - def _emit(self, event): - """See BoundEvent.emit for the public way to call this.""" - - # Save the event for all known observers before the first notification - # takes place, so that either everyone interested sees it, or nobody does. - self.save_snapshot(event) - event_path = event.handle.path - event_kind = event.handle.kind - parent_path = event.handle.parent.path - # TODO Track observers by (parent_path, event_kind) rather than as a list of - # all observers. Avoiding linear search through all observers for every event - for observer_path, method_name, _parent_path, _event_kind in self._observers: - if _parent_path != parent_path: - continue - if _event_kind and _event_kind != event_kind: - continue - # Again, only commit this after all notices are saved. - self._storage.save_notice(event_path, observer_path, method_name) - self._reemit(event_path) - - def reemit(self): - """Reemit previously deferred events to the observers that deferred them. - - Only the specific observers that have previously deferred the event will be - notified again. Observers that asked to be notified about events after it's - been first emitted won't be notified, as that would mean potentially observing - events out of order. - """ - self._reemit() - - def _reemit(self, single_event_path=None): - last_event_path = None - deferred = True - for event_path, observer_path, method_name in self._storage.notices(single_event_path): - event_handle = Handle.from_path(event_path) - - if last_event_path != event_path: - if not deferred: - self._storage.drop_snapshot(last_event_path) - last_event_path = event_path - deferred = False - - try: - event = self.load_snapshot(event_handle) - except NoTypeError: - self._storage.drop_notice(event_path, observer_path, method_name) - continue - - event.deferred = False - observer = self._observer.get(observer_path) - if observer: - custom_handler = getattr(observer, method_name, None) - if custom_handler: - event_is_from_juju = isinstance(event, charm.HookEvent) - event_is_action = isinstance(event, charm.ActionEvent) - if (event_is_from_juju or event_is_action) and 'hook' in self._juju_debug_at: - # Present the welcome message and run under PDB. - self._show_debug_code_message() - pdb.runcall(custom_handler, event) - else: - # Regular call to the registered method. - custom_handler(event) - - if event.deferred: - deferred = True - else: - self._storage.drop_notice(event_path, observer_path, method_name) - # We intentionally consider this event to be dead and reload it from - # scratch in the next path. - self.framework._forget(event) - - if not deferred: - self._storage.drop_snapshot(last_event_path) - - def _show_debug_code_message(self): - """Present the welcome message (only once!) when using debugger functionality.""" - if not self._breakpoint_welcomed: - self._breakpoint_welcomed = True - print(_BREAKPOINT_WELCOME_MESSAGE, file=sys.stderr, end='') - - def breakpoint(self, name=None): - """Add breakpoint, optionally named, at the place where this method is called. - - For the breakpoint to be activated the JUJU_DEBUG_AT environment variable - must be set to "all" or to the specific name parameter provided, if any. In every - other situation calling this method does nothing. - - The framework also provides a standard breakpoint named "hook", that will - stop execution when a hook event is about to be handled. - - For those reasons, the "all" and "hook" breakpoint names are reserved. - """ - # If given, validate the name comply with all the rules - if name is not None: - if not isinstance(name, str): - raise TypeError('breakpoint names must be strings') - if name in ('hook', 'all'): - raise ValueError('breakpoint names "all" and "hook" are reserved') - if not re.match(r'^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$', name): - raise ValueError('breakpoint names must look like "foo" or "foo-bar"') - - indicated_breakpoints = self._juju_debug_at - if 'all' in indicated_breakpoints or name in indicated_breakpoints: - self._show_debug_code_message() - - # If we call set_trace() directly it will open the debugger *here*, so indicating - # it to use our caller's frame - code_frame = inspect.currentframe().f_back - pdb.Pdb().set_trace(code_frame) - - -class StoredStateData(Object): - - def __init__(self, parent, attr_name): - super().__init__(parent, attr_name) - self._cache = {} - self.dirty = False - - def __getitem__(self, key): - return self._cache.get(key) - - def __setitem__(self, key, value): - self._cache[key] = value - self.dirty = True - - def __contains__(self, key): - return key in self._cache - - def snapshot(self): - return self._cache - - def restore(self, snapshot): - self._cache = snapshot - self.dirty = False - - def on_commit(self, event): - if self.dirty: - self.framework.save_snapshot(self) - self.dirty = False - - -class BoundStoredState: - - def __init__(self, parent, attr_name): - parent.framework.register_type(StoredStateData, parent) - - handle = Handle(parent, StoredStateData.handle_kind, attr_name) - try: - data = parent.framework.load_snapshot(handle) - except NoSnapshotError: - data = StoredStateData(parent, attr_name) - - # __dict__ is used to avoid infinite recursion. - self.__dict__["_data"] = data - self.__dict__["_attr_name"] = attr_name - - parent.framework.observe(parent.framework.on.commit, self._data) - - def __getattr__(self, key): - # "on" is the only reserved key that can't be used in the data map. - if key == "on": - return self._data.on - if key not in self._data: - raise AttributeError("attribute '{}' is not stored".format(key)) - return _wrap_stored(self._data, self._data[key]) - - def __setattr__(self, key, value): - if key == "on": - raise AttributeError("attribute 'on' is reserved and cannot be set") - - value = _unwrap_stored(self._data, value) - - if not isinstance(value, (type(None), int, float, str, bytes, list, dict, set)): - raise AttributeError( - 'attribute {!r} cannot be a {}: must be int/float/dict/list/etc'.format( - key, type(value).__name__)) - - self._data[key] = _unwrap_stored(self._data, value) - - def set_default(self, **kwargs): - """"Set the value of any given key if it has not already been set""" - for k, v in kwargs.items(): - if k not in self._data: - self._data[k] = v - - -class StoredState: - """A class used to store data the charm needs persisted across invocations. - - Example:: - - class MyClass(Object): - _stored = StoredState() - - Instances of `MyClass` can transparently save state between invocations by - setting attributes on `_stored`. Initial state should be set with - `set_default` on the bound object, that is:: - - class MyClass(Object): - _stored = StoredState() - - def __init__(self, parent, key): - super().__init__(parent, key) - self._stored.set_default(seen=set()) - self.framework.observe(self.on.seen, self._on_seen) - - def _on_seen(self, event): - self._stored.seen.add(event.uuid) - - """ - - def __init__(self): - self.parent_type = None - self.attr_name = None - - def __get__(self, parent, parent_type=None): - if self.parent_type is not None and self.parent_type not in parent_type.mro(): - # the StoredState instance is being shared between two unrelated classes - # -> unclear what is exepcted of us -> bail out - raise RuntimeError( - 'StoredState shared by {} and {}'.format( - self.parent_type.__name__, parent_type.__name__)) - - if parent is None: - # accessing via the class directly (e.g. MyClass.stored) - return self - - bound = None - if self.attr_name is not None: - bound = parent.__dict__.get(self.attr_name) - if bound is not None: - # we already have the thing from a previous pass, huzzah - return bound - - # need to find ourselves amongst the parent's bases - for cls in parent_type.mro(): - for attr_name, attr_value in cls.__dict__.items(): - if attr_value is not self: - continue - # we've found ourselves! is it the first time? - if bound is not None: - # the StoredState instance is being stored in two different - # attributes -> unclear what is expected of us -> bail out - raise RuntimeError("StoredState shared by {0}.{1} and {0}.{2}".format( - cls.__name__, self.attr_name, attr_name)) - # we've found ourselves for the first time; save where, and bind the object - self.attr_name = attr_name - self.parent_type = cls - bound = BoundStoredState(parent, attr_name) - - if bound is not None: - # cache the bound object to avoid the expensive lookup the next time - # (don't use setattr, to keep things symmetric with the fast-path lookup above) - parent.__dict__[self.attr_name] = bound - return bound - - raise AttributeError( - 'cannot find {} attribute in type {}'.format( - self.__class__.__name__, parent_type.__name__)) - - -def _wrap_stored(parent_data, value): - t = type(value) - if t is dict: - return StoredDict(parent_data, value) - if t is list: - return StoredList(parent_data, value) - if t is set: - return StoredSet(parent_data, value) - return value - - -def _unwrap_stored(parent_data, value): - t = type(value) - if t is StoredDict or t is StoredList or t is StoredSet: - return value._under - return value - - -class StoredDict(collections.abc.MutableMapping): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def __getitem__(self, key): - return _wrap_stored(self._stored_data, self._under[key]) - - def __setitem__(self, key, value): - self._under[key] = _unwrap_stored(self._stored_data, value) - self._stored_data.dirty = True - - def __delitem__(self, key): - del self._under[key] - self._stored_data.dirty = True - - def __iter__(self): - return self._under.__iter__() - - def __len__(self): - return len(self._under) - - def __eq__(self, other): - if isinstance(other, StoredDict): - return self._under == other._under - elif isinstance(other, collections.abc.Mapping): - return self._under == other - else: - return NotImplemented - - -class StoredList(collections.abc.MutableSequence): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def __getitem__(self, index): - return _wrap_stored(self._stored_data, self._under[index]) - - def __setitem__(self, index, value): - self._under[index] = _unwrap_stored(self._stored_data, value) - self._stored_data.dirty = True - - def __delitem__(self, index): - del self._under[index] - self._stored_data.dirty = True - - def __len__(self): - return len(self._under) - - def insert(self, index, value): - self._under.insert(index, value) - self._stored_data.dirty = True - - def append(self, value): - self._under.append(value) - self._stored_data.dirty = True - - def __eq__(self, other): - if isinstance(other, StoredList): - return self._under == other._under - elif isinstance(other, collections.abc.Sequence): - return self._under == other - else: - return NotImplemented - - def __lt__(self, other): - if isinstance(other, StoredList): - return self._under < other._under - elif isinstance(other, collections.abc.Sequence): - return self._under < other - else: - return NotImplemented - - def __le__(self, other): - if isinstance(other, StoredList): - return self._under <= other._under - elif isinstance(other, collections.abc.Sequence): - return self._under <= other - else: - return NotImplemented - - def __gt__(self, other): - if isinstance(other, StoredList): - return self._under > other._under - elif isinstance(other, collections.abc.Sequence): - return self._under > other - else: - return NotImplemented - - def __ge__(self, other): - if isinstance(other, StoredList): - return self._under >= other._under - elif isinstance(other, collections.abc.Sequence): - return self._under >= other - else: - return NotImplemented - - -class StoredSet(collections.abc.MutableSet): - - def __init__(self, stored_data, under): - self._stored_data = stored_data - self._under = under - - def add(self, key): - self._under.add(key) - self._stored_data.dirty = True - - def discard(self, key): - self._under.discard(key) - self._stored_data.dirty = True - - def __contains__(self, key): - return key in self._under - - def __iter__(self): - return self._under.__iter__() - - def __len__(self): - return len(self._under) - - @classmethod - def _from_iterable(cls, it): - """Construct an instance of the class from any iterable input. - - Per https://docs.python.org/3/library/collections.abc.html - if the Set mixin is being used in a class with a different constructor signature, - you will need to override _from_iterable() with a classmethod that can construct - new instances from an iterable argument. - """ - return set(it) - - def __le__(self, other): - if isinstance(other, StoredSet): - return self._under <= other._under - elif isinstance(other, collections.abc.Set): - return self._under <= other - else: - return NotImplemented - - def __ge__(self, other): - if isinstance(other, StoredSet): - return self._under >= other._under - elif isinstance(other, collections.abc.Set): - return self._under >= other - else: - return NotImplemented - - def __eq__(self, other): - if isinstance(other, StoredSet): - return self._under == other._under - elif isinstance(other, collections.abc.Set): - return self._under == other - else: - return NotImplemented diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py b/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py deleted file mode 100755 index 45178862..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/jujuversion.py +++ /dev/null @@ -1,85 +0,0 @@ -# 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 re -from functools import total_ordering - - -@total_ordering -class JujuVersion: - - PATTERN = r'''^ - (?P\d{1,9})\.(?P\d{1,9}) # and numbers are always there - ((?:\.|-(?P[a-z]+))(?P\d{1,9}))? # sometimes with . or - - (\.(?P\d{1,9}))?$ # and sometimes with a number. - ''' - - def __init__(self, version): - m = re.match(self.PATTERN, version, re.VERBOSE) - if not m: - raise RuntimeError('"{}" is not a valid Juju version string'.format(version)) - - d = m.groupdict() - self.major = int(m.group('major')) - self.minor = int(m.group('minor')) - self.tag = d['tag'] or '' - self.patch = int(d['patch'] or 0) - self.build = int(d['build'] or 0) - - def __repr__(self): - if self.tag: - s = '{}.{}-{}{}'.format(self.major, self.minor, self.tag, self.patch) - else: - s = '{}.{}.{}'.format(self.major, self.minor, self.patch) - if self.build > 0: - s += '.{}'.format(self.build) - return s - - def __eq__(self, other): - if self is other: - return True - if isinstance(other, str): - other = type(self)(other) - elif not isinstance(other, JujuVersion): - raise RuntimeError('cannot compare Juju version "{}" with "{}"'.format(self, other)) - return ( - self.major == other.major - and self.minor == other.minor - and self.tag == other.tag - and self.build == other.build - and self.patch == other.patch) - - def __lt__(self, other): - if self is other: - return False - if isinstance(other, str): - other = type(self)(other) - elif not isinstance(other, JujuVersion): - raise RuntimeError('cannot compare Juju version "{}" with "{}"'.format(self, other)) - - if self.major != other.major: - return self.major < other.major - elif self.minor != other.minor: - return self.minor < other.minor - elif self.tag != other.tag: - if not self.tag: - return False - elif not other.tag: - return True - return self.tag < other.tag - elif self.patch != other.patch: - return self.patch < other.patch - elif self.build != other.build: - return self.build < other.build - return False diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/log.py b/magma/squid_cnf/charms/squid/mod/operator/ops/log.py deleted file mode 100644 index a3f76a37..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/log.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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 logging - - -class JujuLogHandler(logging.Handler): - """A handler for sending logs to Juju via juju-log.""" - - def __init__(self, model_backend, level=logging.DEBUG): - super().__init__(level) - self.model_backend = model_backend - - def emit(self, record): - self.model_backend.juju_log(record.levelname, self.format(record)) - - -def setup_root_logging(model_backend, debug=False): - """Setup python logging to forward messages to juju-log. - - By default, logging is set to DEBUG level, and messages will be filtered by Juju. - Charmers can also set their own default log level with:: - - logging.getLogger().setLevel(logging.INFO) - - model_backend -- a ModelBackend to use for juju-log - debug -- if True, write logs to stderr as well as to juju-log. - """ - logger = logging.getLogger() - logger.setLevel(logging.DEBUG) - logger.addHandler(JujuLogHandler(model_backend)) - if debug: - handler = logging.StreamHandler() - formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') - handler.setFormatter(formatter) - logger.addHandler(handler) diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/main.py b/magma/squid_cnf/charms/squid/mod/operator/ops/main.py deleted file mode 100755 index 0f5391d7..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/main.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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 -from pathlib import Path - -import yaml - -import ops.charm -import ops.framework -import ops.model -import logging - -from ops.log import setup_root_logging - -CHARM_STATE_FILE = '.unit-state.db' - - -logger = logging.getLogger() - - -def _get_charm_dir(): - charm_dir = os.environ.get("JUJU_CHARM_DIR") - if charm_dir is None: - # Assume $JUJU_CHARM_DIR/lib/op/main.py structure. - charm_dir = Path('{}/../../..'.format(__file__)).resolve() - else: - charm_dir = Path(charm_dir).resolve() - return charm_dir - - -def _load_metadata(charm_dir): - metadata = yaml.safe_load((charm_dir / 'metadata.yaml').read_text()) - - actions_meta = charm_dir / 'actions.yaml' - if actions_meta.exists(): - actions_metadata = yaml.safe_load(actions_meta.read_text()) - else: - actions_metadata = {} - return metadata, actions_metadata - - -def _create_event_link(charm, bound_event): - """Create a symlink for a particular event. - - charm -- A charm object. - bound_event -- An event for which to create a symlink. - """ - if issubclass(bound_event.event_type, ops.charm.HookEvent): - event_dir = charm.framework.charm_dir / 'hooks' - event_path = event_dir / bound_event.event_kind.replace('_', '-') - elif issubclass(bound_event.event_type, ops.charm.ActionEvent): - if not bound_event.event_kind.endswith("_action"): - raise RuntimeError( - 'action event name {} needs _action suffix'.format(bound_event.event_kind)) - event_dir = charm.framework.charm_dir / 'actions' - # The event_kind is suffixed with "_action" while the executable is not. - event_path = event_dir / bound_event.event_kind[:-len('_action')].replace('_', '-') - else: - raise RuntimeError( - 'cannot create a symlink: unsupported event type {}'.format(bound_event.event_type)) - - event_dir.mkdir(exist_ok=True) - if not event_path.exists(): - # CPython has different implementations for populating sys.argv[0] for Linux and Windows. - # For Windows it is always an absolute path (any symlinks are resolved) - # while for Linux it can be a relative path. - target_path = os.path.relpath(os.path.realpath(sys.argv[0]), str(event_dir)) - - # Ignore the non-symlink files or directories - # assuming the charm author knows what they are doing. - logger.debug( - 'Creating a new relative symlink at %s pointing to %s', - event_path, target_path) - event_path.symlink_to(target_path) - - -def _setup_event_links(charm_dir, charm): - """Set up links for supported events that originate from Juju. - - Whether a charm can handle an event or not can be determined by - introspecting which events are defined on it. - - Hooks or actions are created as symlinks to the charm code file - which is determined by inspecting symlinks provided by the charm - author at hooks/install or hooks/start. - - charm_dir -- A root directory of the charm. - charm -- An instance of the Charm class. - - """ - for bound_event in charm.on.events().values(): - # Only events that originate from Juju need symlinks. - if issubclass(bound_event.event_type, (ops.charm.HookEvent, ops.charm.ActionEvent)): - _create_event_link(charm, bound_event) - - -def _emit_charm_event(charm, event_name): - """Emits a charm event based on a Juju event name. - - charm -- A charm instance to emit an event from. - event_name -- A Juju event name to emit on a charm. - """ - event_to_emit = None - try: - event_to_emit = getattr(charm.on, event_name) - except AttributeError: - logger.debug("event %s not defined for %s", event_name, charm) - - # If the event is not supported by the charm implementation, do - # not error out or try to emit it. This is to support rollbacks. - if event_to_emit is not None: - args, kwargs = _get_event_args(charm, event_to_emit) - logger.debug('Emitting Juju event %s', event_name) - event_to_emit.emit(*args, **kwargs) - - -def _get_event_args(charm, bound_event): - event_type = bound_event.event_type - model = charm.framework.model - - if issubclass(event_type, ops.charm.RelationEvent): - relation_name = os.environ['JUJU_RELATION'] - relation_id = int(os.environ['JUJU_RELATION_ID'].split(':')[-1]) - relation = model.get_relation(relation_name, relation_id) - else: - relation = None - - remote_app_name = os.environ.get('JUJU_REMOTE_APP', '') - remote_unit_name = os.environ.get('JUJU_REMOTE_UNIT', '') - if remote_app_name or remote_unit_name: - if not remote_app_name: - if '/' not in remote_unit_name: - raise RuntimeError('invalid remote unit name: {}'.format(remote_unit_name)) - remote_app_name = remote_unit_name.split('/')[0] - args = [relation, model.get_app(remote_app_name)] - if remote_unit_name: - args.append(model.get_unit(remote_unit_name)) - return args, {} - elif relation: - return [relation], {} - return [], {} - - -def main(charm_class): - """Setup the charm and dispatch the observed event. - - The event name is based on the way this executable was called (argv[0]). - """ - charm_dir = _get_charm_dir() - - model_backend = ops.model.ModelBackend() - debug = ('JUJU_DEBUG' in os.environ) - setup_root_logging(model_backend, debug=debug) - - # Process the Juju event relevant to the current hook execution - # JUJU_HOOK_NAME, JUJU_FUNCTION_NAME, and JUJU_ACTION_NAME are not used - # in order to support simulation of events from debugging sessions. - # - # TODO: For Windows, when symlinks are used, this is not a valid - # method of getting an event name (see LP: #1854505). - juju_exec_path = Path(sys.argv[0]) - has_dispatch = juju_exec_path.name == 'dispatch' - if has_dispatch: - # The executable was 'dispatch', which means the actual hook we want to - # run needs to be looked up in the JUJU_DISPATCH_PATH env var, where it - # should be a path relative to the charm directory (the directory that - # holds `dispatch`). If that path actually exists, we want to run that - # before continuing. - dispatch_path = juju_exec_path.parent / Path(os.environ['JUJU_DISPATCH_PATH']) - if dispatch_path.exists() and dispatch_path.resolve() != juju_exec_path.resolve(): - argv = sys.argv.copy() - argv[0] = str(dispatch_path) - try: - subprocess.run(argv, check=True) - except subprocess.CalledProcessError as e: - logger.warning("hook %s exited with status %d", dispatch_path, e.returncode) - sys.exit(e.returncode) - juju_exec_path = dispatch_path - juju_event_name = juju_exec_path.name.replace('-', '_') - if juju_exec_path.parent.name == 'actions': - juju_event_name = '{}_action'.format(juju_event_name) - - metadata, actions_metadata = _load_metadata(charm_dir) - meta = ops.charm.CharmMeta(metadata, actions_metadata) - unit_name = os.environ['JUJU_UNIT_NAME'] - model = ops.model.Model(unit_name, meta, model_backend) - - # TODO: If Juju unit agent crashes after exit(0) from the charm code - # the framework will commit the snapshot but Juju will not commit its - # operation. - charm_state_path = charm_dir / CHARM_STATE_FILE - framework = ops.framework.Framework(charm_state_path, charm_dir, meta, model) - try: - charm = charm_class(framework, None) - - if not has_dispatch: - # When a charm is force-upgraded and a unit is in an error state Juju - # does not run upgrade-charm and instead runs the failed hook followed - # by config-changed. Given the nature of force-upgrading the hook setup - # code is not triggered on config-changed. - # - # 'start' event is included as Juju does not fire the install event for - # K8s charms (see LP: #1854635). - if (juju_event_name in ('install', 'start', 'upgrade_charm') - or juju_event_name.endswith('_storage_attached')): - _setup_event_links(charm_dir, charm) - - # TODO: Remove the collect_metrics check below as soon as the relevant - # Juju changes are made. - # - # Skip reemission of deferred events for collect-metrics events because - # they do not have the full access to all hook tools. - if juju_event_name != 'collect_metrics': - framework.reemit() - - _emit_charm_event(charm, juju_event_name) - - framework.commit() - finally: - framework.close() diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/model.py b/magma/squid_cnf/charms/squid/mod/operator/ops/model.py deleted file mode 100644 index 3d19ba8b..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/model.py +++ /dev/null @@ -1,915 +0,0 @@ -# Copyright 2019 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 json -import weakref -import os -import shutil -import tempfile -import time -import datetime -import re -import ipaddress -import decimal - -from abc import ABC, abstractmethod -from collections.abc import Mapping, MutableMapping -from pathlib import Path -from subprocess import run, PIPE, CalledProcessError - - -class Model: - - def __init__(self, unit_name, meta, backend): - self._cache = _ModelCache(backend) - self._backend = backend - self.unit = self.get_unit(unit_name) - self.app = self.unit.app - self.relations = RelationMapping(meta.relations, self.unit, self._backend, self._cache) - self.config = ConfigData(self._backend) - self.resources = Resources(list(meta.resources), self._backend) - self.pod = Pod(self._backend) - self.storages = StorageMapping(list(meta.storages), self._backend) - self._bindings = BindingMapping(self._backend) - - def get_unit(self, unit_name): - return self._cache.get(Unit, unit_name) - - def get_app(self, app_name): - return self._cache.get(Application, app_name) - - def get_relation(self, relation_name, relation_id=None): - """Get a specific Relation instance. - - If relation_id is given, this will return that Relation instance. - - If relation_id is not given, this will return the Relation instance if the - relation is established only once or None if it is not established. If this - same relation is established multiple times the error TooManyRelatedAppsError is raised. - """ - return self.relations._get_unique(relation_name, relation_id) - - def get_binding(self, binding_key): - """Get a network space binding. - - binding_key -- The relation name or instance to obtain bindings for. - - If binding_key is a relation name, the method returns the default binding for that - relation. If a relation instance is provided, the method first looks up a more specific - binding for that specific relation ID, and if none is found falls back to the default - binding for the relation name. - """ - return self._bindings.get(binding_key) - - -class _ModelCache: - - def __init__(self, backend): - self._backend = backend - self._weakrefs = weakref.WeakValueDictionary() - - def get(self, entity_type, *args): - key = (entity_type,) + args - entity = self._weakrefs.get(key) - if entity is None: - entity = entity_type(*args, backend=self._backend, cache=self) - self._weakrefs[key] = entity - return entity - - -class Application: - - def __init__(self, name, backend, cache): - self.name = name - self._backend = backend - self._cache = cache - self._is_our_app = self.name == self._backend.app_name - self._status = None - - @property - def status(self): - if not self._is_our_app: - return UnknownStatus() - - if not self._backend.is_leader(): - raise RuntimeError('cannot get application status as a non-leader unit') - - if self._status: - return self._status - - s = self._backend.status_get(is_app=True) - self._status = StatusBase.from_name(s['status'], s['message']) - return self._status - - @status.setter - def status(self, value): - if not isinstance(value, StatusBase): - raise InvalidStatusError( - 'invalid value provided for application {} status: {}'.format(self, value) - ) - - if not self._is_our_app: - raise RuntimeError('cannot to set status for a remote application {}'.format(self)) - - if not self._backend.is_leader(): - raise RuntimeError('cannot set application status as a non-leader unit') - - self._backend.status_set(value.name, value.message, is_app=True) - self._status = value - - def __repr__(self): - return '<{}.{} {}>'.format(type(self).__module__, type(self).__name__, self.name) - - -class Unit: - - def __init__(self, name, backend, cache): - self.name = name - - app_name = name.split('/')[0] - self.app = cache.get(Application, app_name) - - self._backend = backend - self._cache = cache - self._is_our_unit = self.name == self._backend.unit_name - self._status = None - - @property - def status(self): - if not self._is_our_unit: - return UnknownStatus() - - if self._status: - return self._status - - s = self._backend.status_get(is_app=False) - self._status = StatusBase.from_name(s['status'], s['message']) - return self._status - - @status.setter - def status(self, value): - if not isinstance(value, StatusBase): - raise InvalidStatusError( - 'invalid value provided for unit {} status: {}'.format(self, value) - ) - - if not self._is_our_unit: - raise RuntimeError('cannot set status for a remote unit {}'.format(self)) - - self._backend.status_set(value.name, value.message, is_app=False) - self._status = value - - def __repr__(self): - return '<{}.{} {}>'.format(type(self).__module__, type(self).__name__, self.name) - - def is_leader(self): - if self._is_our_unit: - # This value is not cached as it is not guaranteed to persist for the whole duration - # of a hook execution. - return self._backend.is_leader() - else: - raise RuntimeError( - 'cannot determine leadership status for remote applications: {}'.format(self) - ) - - def set_workload_version(self, version): - """Record the version of the software running as the workload. - - This shouldn't be confused with the revision of the charm. This is informative only; - shown in the output of 'juju status'. - """ - if not isinstance(version, str): - raise TypeError("workload version must be a str, not {}: {!r}".format( - type(version).__name__, version)) - self._backend.application_version_set(version) - - -class LazyMapping(Mapping, ABC): - - _lazy_data = None - - @abstractmethod - def _load(self): - raise NotImplementedError() - - @property - def _data(self): - data = self._lazy_data - if data is None: - data = self._lazy_data = self._load() - return data - - def _invalidate(self): - self._lazy_data = None - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - return self._data[key] - - -class RelationMapping(Mapping): - """Map of relation names to lists of Relation instances.""" - - def __init__(self, relations_meta, our_unit, backend, cache): - self._peers = set() - for name, relation_meta in relations_meta.items(): - if relation_meta.role == 'peers': - self._peers.add(name) - self._our_unit = our_unit - self._backend = backend - self._cache = cache - self._data = {relation_name: None for relation_name in relations_meta} - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, relation_name): - is_peer = relation_name in self._peers - relation_list = self._data[relation_name] - if relation_list is None: - relation_list = self._data[relation_name] = [] - for rid in self._backend.relation_ids(relation_name): - relation = Relation(relation_name, rid, is_peer, - self._our_unit, self._backend, self._cache) - relation_list.append(relation) - return relation_list - - def _invalidate(self, relation_name): - self._data[relation_name] = None - - def _get_unique(self, relation_name, relation_id=None): - if relation_id is not None: - if not isinstance(relation_id, int): - raise ModelError('relation id {} must be int or None not {}'.format( - relation_id, - type(relation_id).__name__)) - for relation in self[relation_name]: - if relation.id == relation_id: - return relation - else: - # The relation may be dead, but it is not forgotten. - is_peer = relation_name in self._peers - return Relation(relation_name, relation_id, is_peer, - self._our_unit, self._backend, self._cache) - num_related = len(self[relation_name]) - if num_related == 0: - return None - elif num_related == 1: - return self[relation_name][0] - else: - # TODO: We need something in the framework to catch and gracefully handle - # errors, ideally integrating the error catching with Juju's mechanisms. - raise TooManyRelatedAppsError(relation_name, num_related, 1) - - -class BindingMapping: - - def __init__(self, backend): - self._backend = backend - self._data = {} - - def get(self, binding_key): - if isinstance(binding_key, Relation): - binding_name = binding_key.name - relation_id = binding_key.id - elif isinstance(binding_key, str): - binding_name = binding_key - relation_id = None - else: - raise ModelError('binding key must be str or relation instance, not {}' - ''.format(type(binding_key).__name__)) - binding = self._data.get(binding_key) - if binding is None: - binding = Binding(binding_name, relation_id, self._backend) - self._data[binding_key] = binding - return binding - - -class Binding: - """Binding to a network space.""" - - def __init__(self, name, relation_id, backend): - self.name = name - self._relation_id = relation_id - self._backend = backend - self._network = None - - @property - def network(self): - if self._network is None: - try: - self._network = Network(self._backend.network_get(self.name, self._relation_id)) - except RelationNotFoundError: - if self._relation_id is None: - raise - # If a relation is dead, we can still get network info associated with an - # endpoint itself - self._network = Network(self._backend.network_get(self.name)) - return self._network - - -class Network: - """Network space details.""" - - def __init__(self, network_info): - self.interfaces = [] - # Treat multiple addresses on an interface as multiple logical - # interfaces with the same name. - for interface_info in network_info['bind-addresses']: - interface_name = interface_info['interface-name'] - for address_info in interface_info['addresses']: - self.interfaces.append(NetworkInterface(interface_name, address_info)) - self.ingress_addresses = [] - for address in network_info['ingress-addresses']: - self.ingress_addresses.append(ipaddress.ip_address(address)) - self.egress_subnets = [] - for subnet in network_info['egress-subnets']: - self.egress_subnets.append(ipaddress.ip_network(subnet)) - - @property - def bind_address(self): - return self.interfaces[0].address - - @property - def ingress_address(self): - return self.ingress_addresses[0] - - -class NetworkInterface: - - def __init__(self, name, address_info): - self.name = name - # TODO: expose a hardware address here, see LP: #1864070. - self.address = ipaddress.ip_address(address_info['value']) - cidr = address_info['cidr'] - if not cidr: - # The cidr field may be empty, see LP: #1864102. - # In this case, make it a /32 or /128 IP network. - self.subnet = ipaddress.ip_network(address_info['value']) - else: - self.subnet = ipaddress.ip_network(cidr) - # TODO: expose a hostname/canonical name for the address here, see LP: #1864086. - - -class Relation: - def __init__(self, relation_name, relation_id, is_peer, our_unit, backend, cache): - self.name = relation_name - self.id = relation_id - self.app = None - self.units = set() - - # For peer relations, both the remote and the local app are the same. - if is_peer: - self.app = our_unit.app - try: - for unit_name in backend.relation_list(self.id): - unit = cache.get(Unit, unit_name) - self.units.add(unit) - if self.app is None: - self.app = unit.app - except RelationNotFoundError: - # If the relation is dead, just treat it as if it has no remote units. - pass - self.data = RelationData(self, our_unit, backend) - - def __repr__(self): - return '<{}.{} {}:{}>'.format(type(self).__module__, - type(self).__name__, - self.name, - self.id) - - -class RelationData(Mapping): - def __init__(self, relation, our_unit, backend): - self.relation = weakref.proxy(relation) - self._data = { - our_unit: RelationDataContent(self.relation, our_unit, backend), - our_unit.app: RelationDataContent(self.relation, our_unit.app, backend), - } - self._data.update({ - unit: RelationDataContent(self.relation, unit, backend) - for unit in self.relation.units}) - # The relation might be dead so avoid a None key here. - if self.relation.app is not None: - self._data.update({ - self.relation.app: RelationDataContent(self.relation, self.relation.app, backend), - }) - - def __contains__(self, key): - return key in self._data - - def __len__(self): - return len(self._data) - - def __iter__(self): - return iter(self._data) - - def __getitem__(self, key): - return self._data[key] - - -# We mix in MutableMapping here to get some convenience implementations, but whether it's actually -# mutable or not is controlled by the flag. -class RelationDataContent(LazyMapping, MutableMapping): - - def __init__(self, relation, entity, backend): - self.relation = relation - self._entity = entity - self._backend = backend - self._is_app = isinstance(entity, Application) - - def _load(self): - try: - return self._backend.relation_get(self.relation.id, self._entity.name, self._is_app) - except RelationNotFoundError: - # Dead relations tell no tales (and have no data). - return {} - - def _is_mutable(self): - if self._is_app: - is_our_app = self._backend.app_name == self._entity.name - if not is_our_app: - return False - # Whether the application data bag is mutable or not depends on - # whether this unit is a leader or not, but this is not guaranteed - # to be always true during the same hook execution. - return self._backend.is_leader() - else: - is_our_unit = self._backend.unit_name == self._entity.name - if is_our_unit: - return True - return False - - def __setitem__(self, key, value): - if not self._is_mutable(): - raise RelationDataError('cannot set relation data for {}'.format(self._entity.name)) - if not isinstance(value, str): - raise RelationDataError('relation data values must be strings') - - self._backend.relation_set(self.relation.id, key, value, self._is_app) - - # Don't load data unnecessarily if we're only updating. - if self._lazy_data is not None: - if value == '': - # Match the behavior of Juju, which is that setting the value to an - # empty string will remove the key entirely from the relation data. - del self._data[key] - else: - self._data[key] = value - - def __delitem__(self, key): - # Match the behavior of Juju, which is that setting the value to an empty - # string will remove the key entirely from the relation data. - self.__setitem__(key, '') - - -class ConfigData(LazyMapping): - - def __init__(self, backend): - self._backend = backend - - def _load(self): - return self._backend.config_get() - - -class StatusBase: - """Status values specific to applications and units.""" - - _statuses = {} - - def __init__(self, message): - self.message = message - - def __new__(cls, *args, **kwargs): - if cls is StatusBase: - raise TypeError("cannot instantiate a base class") - cls._statuses[cls.name] = cls - return super().__new__(cls) - - @classmethod - def from_name(cls, name, message): - return cls._statuses[name](message) - - -class ActiveStatus(StatusBase): - """The unit is ready. - - The unit believes it is correctly offering all the services it has been asked to offer. - """ - name = 'active' - - def __init__(self, message=None): - super().__init__(message or '') - - -class BlockedStatus(StatusBase): - """The unit requires manual intervention. - - An operator has to manually intervene to unblock the unit and let it proceed. - """ - name = 'blocked' - - -class MaintenanceStatus(StatusBase): - """The unit is performing maintenance tasks. - - The unit is not yet providing services, but is actively doing work in preparation - for providing those services. This is a "spinning" state, not an error state. It - reflects activity on the unit itself, not on peers or related units. - - """ - name = 'maintenance' - - -class UnknownStatus(StatusBase): - """The unit status is unknown. - - A unit-agent has finished calling install, config-changed and start, but the - charm has not called status-set yet. - - """ - name = 'unknown' - - def __init__(self): - # Unknown status cannot be set and does not have a message associated with it. - super().__init__('') - - -class WaitingStatus(StatusBase): - """A unit is unable to progress. - - The unit is unable to progress to an active state because an application to which - it is related is not running. - - """ - name = 'waiting' - - -class Resources: - """Object representing resources for the charm. - """ - - def __init__(self, names, backend): - self._backend = backend - self._paths = {name: None for name in names} - - def fetch(self, name): - """Fetch the resource from the controller or store. - - If successfully fetched, this returns a Path object to where the resource is stored - on disk, otherwise it raises a ModelError. - """ - if name not in self._paths: - raise RuntimeError('invalid resource name: {}'.format(name)) - if self._paths[name] is None: - self._paths[name] = Path(self._backend.resource_get(name)) - return self._paths[name] - - -class Pod: - def __init__(self, backend): - self._backend = backend - - def set_spec(self, spec, k8s_resources=None): - if not self._backend.is_leader(): - raise ModelError('cannot set a pod spec as this unit is not a leader') - self._backend.pod_spec_set(spec, k8s_resources) - - -class StorageMapping(Mapping): - """Map of storage names to lists of Storage instances.""" - - def __init__(self, storage_names, backend): - self._backend = backend - self._storage_map = {storage_name: None for storage_name in storage_names} - - def __contains__(self, key): - return key in self._storage_map - - def __len__(self): - return len(self._storage_map) - - def __iter__(self): - return iter(self._storage_map) - - def __getitem__(self, storage_name): - storage_list = self._storage_map[storage_name] - if storage_list is None: - storage_list = self._storage_map[storage_name] = [] - for storage_id in self._backend.storage_list(storage_name): - storage_list.append(Storage(storage_name, storage_id, self._backend)) - return storage_list - - def request(self, storage_name, count=1): - """Requests new storage instances of a given name. - - Uses storage-add tool to request additional storage. Juju will notify the unit - via -storage-attached events when it becomes available. - """ - if storage_name not in self._storage_map: - raise ModelError(('cannot add storage {!r}:' - ' it is not present in the charm metadata').format(storage_name)) - self._backend.storage_add(storage_name, count) - - -class Storage: - - def __init__(self, storage_name, storage_id, backend): - self.name = storage_name - self.id = storage_id - self._backend = backend - self._location = None - - @property - def location(self): - if self._location is None: - raw = self._backend.storage_get('{}/{}'.format(self.name, self.id), "location") - self._location = Path(raw) - return self._location - - -class ModelError(Exception): - pass - - -class TooManyRelatedAppsError(ModelError): - def __init__(self, relation_name, num_related, max_supported): - super().__init__('Too many remote applications on {} ({} > {})'.format( - relation_name, num_related, max_supported)) - self.relation_name = relation_name - self.num_related = num_related - self.max_supported = max_supported - - -class RelationDataError(ModelError): - pass - - -class RelationNotFoundError(ModelError): - pass - - -class InvalidStatusError(ModelError): - pass - - -class ModelBackend: - - LEASE_RENEWAL_PERIOD = datetime.timedelta(seconds=30) - - def __init__(self): - self.unit_name = os.environ['JUJU_UNIT_NAME'] - self.app_name = self.unit_name.split('/')[0] - - self._is_leader = None - self._leader_check_time = None - - def _run(self, *args, return_output=False, use_json=False): - kwargs = dict(stdout=PIPE, stderr=PIPE) - if use_json: - args += ('--format=json',) - try: - result = run(args, check=True, **kwargs) - except CalledProcessError as e: - raise ModelError(e.stderr) - if return_output: - if result.stdout is None: - return '' - else: - text = result.stdout.decode('utf8') - if use_json: - return json.loads(text) - else: - return text - - def relation_ids(self, relation_name): - relation_ids = self._run('relation-ids', relation_name, return_output=True, use_json=True) - return [int(relation_id.split(':')[-1]) for relation_id in relation_ids] - - def relation_list(self, relation_id): - try: - return self._run('relation-list', '-r', str(relation_id), - return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def relation_get(self, relation_id, member_name, is_app): - if not isinstance(is_app, bool): - raise TypeError('is_app parameter to relation_get must be a boolean') - - try: - return self._run('relation-get', '-r', str(relation_id), - '-', member_name, '--app={}'.format(is_app), - return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def relation_set(self, relation_id, key, value, is_app): - if not isinstance(is_app, bool): - raise TypeError('is_app parameter to relation_set must be a boolean') - - try: - return self._run('relation-set', '-r', str(relation_id), - '{}={}'.format(key, value), '--app={}'.format(is_app)) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def config_get(self): - return self._run('config-get', return_output=True, use_json=True) - - def is_leader(self): - """Obtain the current leadership status for the unit the charm code is executing on. - - The value is cached for the duration of a lease which is 30s in Juju. - """ - now = time.monotonic() - if self._leader_check_time is None: - check = True - else: - time_since_check = datetime.timedelta(seconds=now - self._leader_check_time) - check = (time_since_check > self.LEASE_RENEWAL_PERIOD or self._is_leader is None) - if check: - # Current time MUST be saved before running is-leader to ensure the cache - # is only used inside the window that is-leader itself asserts. - self._leader_check_time = now - self._is_leader = self._run('is-leader', return_output=True, use_json=True) - - return self._is_leader - - def resource_get(self, resource_name): - return self._run('resource-get', resource_name, return_output=True).strip() - - def pod_spec_set(self, spec, k8s_resources): - tmpdir = Path(tempfile.mkdtemp('-pod-spec-set')) - try: - spec_path = tmpdir / 'spec.json' - spec_path.write_text(json.dumps(spec)) - args = ['--file', str(spec_path)] - if k8s_resources: - k8s_res_path = tmpdir / 'k8s-resources.json' - k8s_res_path.write_text(json.dumps(k8s_resources)) - args.extend(['--k8s-resources', str(k8s_res_path)]) - self._run('pod-spec-set', *args) - finally: - shutil.rmtree(str(tmpdir)) - - def status_get(self, *, is_app=False): - """Get a status of a unit or an application. - - app -- A boolean indicating whether the status should be retrieved for a unit - or an application. - """ - return self._run('status-get', '--include-data', '--application={}'.format(is_app)) - - def status_set(self, status, message='', *, is_app=False): - """Set a status of a unit or an application. - - app -- A boolean indicating whether the status should be set for a unit or an - application. - """ - if not isinstance(is_app, bool): - raise TypeError('is_app parameter must be boolean') - return self._run('status-set', '--application={}'.format(is_app), status, message) - - def storage_list(self, name): - return [int(s.split('/')[1]) for s in self._run('storage-list', name, - return_output=True, use_json=True)] - - def storage_get(self, storage_name_id, attribute): - return self._run('storage-get', '-s', storage_name_id, attribute, - return_output=True, use_json=True) - - def storage_add(self, name, count=1): - if not isinstance(count, int) or isinstance(count, bool): - raise TypeError('storage count must be integer, got: {} ({})'.format(count, - type(count))) - self._run('storage-add', '{}={}'.format(name, count)) - - def action_get(self): - return self._run('action-get', return_output=True, use_json=True) - - def action_set(self, results): - self._run('action-set', *["{}={}".format(k, v) for k, v in results.items()]) - - def action_log(self, message): - self._run('action-log', message) - - def action_fail(self, message=''): - self._run('action-fail', message) - - def application_version_set(self, version): - self._run('application-version-set', '--', version) - - def juju_log(self, level, message): - self._run('juju-log', '--log-level', level, message) - - def network_get(self, binding_name, relation_id=None): - """Return network info provided by network-get for a given binding. - - binding_name -- A name of a binding (relation name or extra-binding name). - relation_id -- An optional relation id to get network info for. - """ - cmd = ['network-get', binding_name] - if relation_id is not None: - cmd.extend(['-r', str(relation_id)]) - try: - return self._run(*cmd, return_output=True, use_json=True) - except ModelError as e: - if 'relation not found' in str(e): - raise RelationNotFoundError() from e - raise - - def add_metrics(self, metrics, labels=None): - cmd = ['add-metric'] - - if labels: - label_args = [] - for k, v in labels.items(): - _ModelBackendValidator.validate_metric_label(k) - _ModelBackendValidator.validate_label_value(k, v) - label_args.append('{}={}'.format(k, v)) - cmd.extend(['--labels', ','.join(label_args)]) - - metric_args = [] - for k, v in metrics.items(): - _ModelBackendValidator.validate_metric_key(k) - metric_value = _ModelBackendValidator.format_metric_value(v) - metric_args.append('{}={}'.format(k, metric_value)) - cmd.extend(metric_args) - self._run(*cmd) - - -class _ModelBackendValidator: - """Provides facilities for validating inputs and formatting them for model backends.""" - - METRIC_KEY_REGEX = re.compile(r'^[a-zA-Z](?:[a-zA-Z0-9-_]*[a-zA-Z0-9])?$') - - @classmethod - def validate_metric_key(cls, key): - if cls.METRIC_KEY_REGEX.match(key) is None: - raise ModelError( - 'invalid metric key {!r}: must match {}'.format( - key, cls.METRIC_KEY_REGEX.pattern)) - - @classmethod - def validate_metric_label(cls, label_name): - if cls.METRIC_KEY_REGEX.match(label_name) is None: - raise ModelError( - 'invalid metric label name {!r}: must match {}'.format( - label_name, cls.METRIC_KEY_REGEX.pattern)) - - @classmethod - def format_metric_value(cls, value): - try: - decimal_value = decimal.Decimal.from_float(value) - except TypeError as e: - e2 = ModelError('invalid metric value {!r} provided:' - ' must be a positive finite float'.format(value)) - raise e2 from e - if decimal_value.is_nan() or decimal_value.is_infinite() or decimal_value < 0: - raise ModelError('invalid metric value {!r} provided:' - ' must be a positive finite float'.format(value)) - return str(decimal_value) - - @classmethod - def validate_label_value(cls, label, value): - # Label values cannot be empty, contain commas or equal signs as those are - # used by add-metric as separators. - if not value: - raise ModelError( - 'metric label {} has an empty value, which is not allowed'.format(label)) - v = str(value) - if re.search('[,=]', v) is not None: - raise ModelError( - 'metric label values must not contain "," or "=": {}={!r}'.format(label, value)) diff --git a/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py b/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py deleted file mode 100644 index 72d840c4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/ops/testing.py +++ /dev/null @@ -1,477 +0,0 @@ -# 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 inspect -import pathlib -from textwrap import dedent -import typing - -from ops import charm, framework, model - - -# OptionalYAML is something like metadata.yaml or actions.yaml. You can -# pass in a file-like object or the string directly. -OptionalYAML = typing.Optional[typing.Union[str, typing.TextIO]] - - -# noinspection PyProtectedMember -class Harness: - """This class represents a way to build up the model that will drive a test suite. - - The model that is created is from the viewpoint of the charm that you are testing. - - Example:: - - harness = Harness(MyCharm) - # Do initial setup here - relation_id = harness.add_relation('db', 'postgresql') - # Now instantiate the charm to see events as the model changes - harness.begin() - harness.add_relation_unit(relation_id, 'postgresql/0') - harness.update_relation_data(relation_id, 'postgresql/0', {'key': 'val'}) - # Check that charm has properly handled the relation_joined event for postgresql/0 - self.assertEqual(harness.charm. ...) - - Args: - charm_cls: The Charm class that you'll be testing. - meta: charm.CharmBase is a A string or file-like object containing the contents of - metadata.yaml. If not supplied, we will look for a 'metadata.yaml' file in the - parent directory of the Charm, and if not found fall back to a trivial - 'name: test-charm' metadata. - actions: A string or file-like object containing the contents of - actions.yaml. If not supplied, we will look for a 'actions.yaml' file in the - parent directory of the Charm. - """ - - def __init__( - self, - charm_cls: typing.Type[charm.CharmBase], - *, - meta: OptionalYAML = None, - actions: OptionalYAML = None): - # TODO: jam 2020-03-05 We probably want to take config as a parameter as well, since - # it would define the default values of config that the charm would see. - self._charm_cls = charm_cls - self._charm = None - self._charm_dir = 'no-disk-path' # this may be updated by _create_meta - self._meta = self._create_meta(meta, actions) - self._unit_name = self._meta.name + '/0' - self._framework = None - self._hooks_enabled = True - self._relation_id_counter = 0 - self._backend = _TestingModelBackend(self._unit_name, self._meta) - self._model = model.Model(self._unit_name, self._meta, self._backend) - self._framework = framework.Framework(":memory:", self._charm_dir, self._meta, self._model) - - @property - def charm(self) -> charm.CharmBase: - """Return the instance of the charm class that was passed to __init__. - - Note that the Charm is not instantiated until you have called - :meth:`.begin()`. - """ - return self._charm - - @property - def model(self) -> model.Model: - """Return the :class:`~ops.model.Model` that is being driven by this Harness.""" - return self._model - - @property - def framework(self) -> framework.Framework: - """Return the Framework that is being driven by this Harness.""" - return self._framework - - def begin(self) -> None: - """Instantiate the Charm and start handling events. - - Before calling begin(), there is no Charm instance, so changes to the Model won't emit - events. You must call begin before :attr:`.charm` is valid. - """ - if self._charm is not None: - raise RuntimeError('cannot call the begin method on the harness more than once') - - # The Framework adds attributes to class objects for events, etc. As such, we can't re-use - # the original class against multiple Frameworks. So create a locally defined class - # and register it. - # TODO: jam 2020-03-16 We are looking to changes this to Instance attributes instead of - # Class attributes which should clean up this ugliness. The API can stay the same - class TestEvents(self._charm_cls.on.__class__): - pass - - TestEvents.__name__ = self._charm_cls.on.__class__.__name__ - - class TestCharm(self._charm_cls): - on = TestEvents() - - # Note: jam 2020-03-01 This is so that errors in testing say MyCharm has no attribute foo, - # rather than TestCharm has no attribute foo. - TestCharm.__name__ = self._charm_cls.__name__ - self._charm = TestCharm(self._framework, self._framework.meta.name) - - def _create_meta(self, charm_metadata, action_metadata): - """Create a CharmMeta object. - - Handle the cases where a user doesn't supply explicit metadata snippets. - """ - filename = inspect.getfile(self._charm_cls) - charm_dir = pathlib.Path(filename).parents[1] - - if charm_metadata is None: - metadata_path = charm_dir / 'metadata.yaml' - if metadata_path.is_file(): - charm_metadata = metadata_path.read_text() - self._charm_dir = charm_dir - else: - # The simplest of metadata that the framework can support - charm_metadata = 'name: test-charm' - elif isinstance(charm_metadata, str): - charm_metadata = dedent(charm_metadata) - - if action_metadata is None: - actions_path = charm_dir / 'actions.yaml' - if actions_path.is_file(): - action_metadata = actions_path.read_text() - self._charm_dir = charm_dir - elif isinstance(action_metadata, str): - action_metadata = dedent(action_metadata) - - return charm.CharmMeta.from_yaml(charm_metadata, action_metadata) - - def disable_hooks(self) -> None: - """Stop emitting hook events when the model changes. - - This can be used by developers to stop changes to the model from emitting events that - the charm will react to. Call :meth:`.enable_hooks` - to re-enable them. - """ - self._hooks_enabled = False - - def enable_hooks(self) -> None: - """Re-enable hook events from charm.on when the model is changed. - - By default hook events are enabled once you call :meth:`.begin`, - but if you have used :meth:`.disable_hooks`, this can be used to - enable them again. - """ - self._hooks_enabled = True - - def _next_relation_id(self): - rel_id = self._relation_id_counter - self._relation_id_counter += 1 - return rel_id - - def add_relation(self, relation_name: str, remote_app: str) -> int: - """Declare that there is a new relation between this app and `remote_app`. - - Args: - relation_name: The relation on Charm that is being related to - remote_app: The name of the application that is being related to - - Return: - The relation_id created by this add_relation. - """ - rel_id = self._next_relation_id() - self._backend._relation_ids_map.setdefault(relation_name, []).append(rel_id) - self._backend._relation_names[rel_id] = relation_name - self._backend._relation_list_map[rel_id] = [] - self._backend._relation_data[rel_id] = { - remote_app: {}, - self._backend.unit_name: {}, - self._backend.app_name: {}, - } - # Reload the relation_ids list - if self._model is not None: - self._model.relations._invalidate(relation_name) - if self._charm is None or not self._hooks_enabled: - return rel_id - relation = self._model.get_relation(relation_name, rel_id) - app = self._model.get_app(remote_app) - self._charm.on[relation_name].relation_created.emit( - relation, app) - return rel_id - - def add_relation_unit(self, relation_id: int, remote_unit_name: str) -> None: - """Add a new unit to a relation. - - Example:: - - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - - This will trigger a `relation_joined` event and a `relation_changed` event. - - Args: - relation_id: The integer relation identifier (as returned by add_relation). - remote_unit_name: A string representing the remote unit that is being added. - Return: - None - """ - self._backend._relation_list_map[relation_id].append(remote_unit_name) - self._backend._relation_data[relation_id][remote_unit_name] = {} - relation_name = self._backend._relation_names[relation_id] - # Make sure that the Model reloads the relation_list for this relation_id, as well as - # reloading the relation data for this unit. - if self._model is not None: - self._model.relations._invalidate(relation_name) - remote_unit = self._model.get_unit(remote_unit_name) - relation = self._model.get_relation(relation_name, relation_id) - relation.data[remote_unit]._invalidate() - if self._charm is None or not self._hooks_enabled: - return - self._charm.on[relation_name].relation_joined.emit( - relation, remote_unit.app, remote_unit) - - def get_relation_data(self, relation_id: int, app_or_unit: str) -> typing.Mapping: - """Get the relation data bucket for a single app or unit in a given relation. - - This ignores all of the safety checks of who can and can't see data in relations (eg, - non-leaders can't read their own application's relation data because there are no events - that keep that data up-to-date for the unit). - - Args: - relation_id: The relation whose content we want to look at. - app_or_unit: The name of the application or unit whose data we want to read - Return: - a dict containing the relation data for `app_or_unit` or None. - Raises: - KeyError: if relation_id doesn't exist - """ - return self._backend._relation_data[relation_id].get(app_or_unit, None) - - def get_workload_version(self) -> str: - """Read the workload version that was set by the unit.""" - return self._backend._workload_version - - def update_relation_data( - self, - relation_id: int, - app_or_unit: str, - key_values: typing.Mapping, - ) -> None: - """Update the relation data for a given unit or application in a given relation. - - This also triggers the `relation_changed` event for this relation_id. - - Args: - relation_id: The integer relation_id representing this relation. - app_or_unit: The unit or application name that is being updated. - This can be the local or remote application. - key_values: Each key/value will be updated in the relation data. - """ - relation_name = self._backend._relation_names[relation_id] - relation = self._model.get_relation(relation_name, relation_id) - if '/' in app_or_unit: - entity = self._model.get_unit(app_or_unit) - else: - entity = self._model.get_app(app_or_unit) - rel_data = relation.data.get(entity, None) - if rel_data is not None: - # rel_data may have cached now-stale data, so _invalidate() it. - # Note, this won't cause the data to be loaded if it wasn't already. - rel_data._invalidate() - - new_values = self._backend._relation_data[relation_id][app_or_unit].copy() - for k, v in key_values.items(): - if v == '': - new_values.pop(k, None) - else: - new_values[k] = v - self._backend._relation_data[relation_id][app_or_unit] = new_values - - if app_or_unit == self._model.unit.name: - # No events for our own unit - return - if app_or_unit == self._model.app.name: - # updating our own app only generates an event if it is a peer relation and we - # aren't the leader - is_peer = self._meta.relations[relation_name].role == 'peers' - if not is_peer: - return - if self._model.unit.is_leader(): - return - self._emit_relation_changed(relation_id, app_or_unit) - - def _emit_relation_changed(self, relation_id, app_or_unit): - if self._charm is None or not self._hooks_enabled: - return - rel_name = self._backend._relation_names[relation_id] - relation = self.model.get_relation(rel_name, relation_id) - if '/' in app_or_unit: - app_name = app_or_unit.split('/')[0] - unit_name = app_or_unit - app = self.model.get_app(app_name) - unit = self.model.get_unit(unit_name) - args = (relation, app, unit) - else: - app_name = app_or_unit - app = self.model.get_app(app_name) - args = (relation, app) - self._charm.on[rel_name].relation_changed.emit(*args) - - def update_config( - self, - key_values: typing.Mapping[str, str] = None, - unset: typing.Iterable[str] = (), - ) -> None: - """Update the config as seen by the charm. - - This will trigger a `config_changed` event. - - Args: - key_values: A Mapping of key:value pairs to update in config. - unset: An iterable of keys to remove from Config. (Note that this does - not currently reset the config values to the default defined in config.yaml.) - """ - config = self._backend._config - if key_values is not None: - for key, value in key_values.items(): - config[key] = value - for key in unset: - config.pop(key, None) - # NOTE: jam 2020-03-01 Note that this sort of works "by accident". Config - # is a LazyMapping, but its _load returns a dict and this method mutates - # the dict that Config is caching. Arguably we should be doing some sort - # of charm.framework.model.config._invalidate() - if self._charm is None or not self._hooks_enabled: - return - self._charm.on.config_changed.emit() - - def set_leader(self, is_leader: bool = True) -> None: - """Set whether this unit is the leader or not. - - If this charm becomes a leader then `leader_elected` will be triggered. - - Args: - is_leader: True/False as to whether this unit is the leader. - """ - was_leader = self._backend._is_leader - self._backend._is_leader = is_leader - # Note: jam 2020-03-01 currently is_leader is cached at the ModelBackend level, not in - # the Model objects, so this automatically gets noticed. - if is_leader and not was_leader and self._charm is not None and self._hooks_enabled: - self._charm.on.leader_elected.emit() - - -class _TestingModelBackend: - """This conforms to the interface for ModelBackend but provides canned data. - - DO NOT use this class directly, it is used by `Harness`_ to drive the model. - `Harness`_ is responsible for maintaining the internal consistency of the values here, - as the only public methods of this type are for implementing ModelBackend. - """ - - def __init__(self, unit_name, meta): - self.unit_name = unit_name - self.app_name = self.unit_name.split('/')[0] - self._calls = [] - self._meta = meta - self._is_leader = None - self._relation_ids_map = {} # relation name to [relation_ids,...] - self._relation_names = {} # reverse map from relation_id to relation_name - self._relation_list_map = {} # relation_id: [unit_name,...] - self._relation_data = {} # {relation_id: {name: data}} - self._config = {} - self._is_leader = False - self._resources_map = {} - self._pod_spec = None - self._app_status = None - self._unit_status = None - self._workload_version = None - - def relation_ids(self, relation_name): - try: - return self._relation_ids_map[relation_name] - except KeyError as e: - if relation_name not in self._meta.relations: - raise model.ModelError('{} is not a known relation'.format(relation_name)) from e - return [] - - def relation_list(self, relation_id): - try: - return self._relation_list_map[relation_id] - except KeyError as e: - raise model.RelationNotFoundError from e - - def relation_get(self, relation_id, member_name, is_app): - if is_app and '/' in member_name: - member_name = member_name.split('/')[0] - if relation_id not in self._relation_data: - raise model.RelationNotFoundError() - return self._relation_data[relation_id][member_name].copy() - - def relation_set(self, relation_id, key, value, is_app): - relation = self._relation_data[relation_id] - if is_app: - bucket_key = self.app_name - else: - bucket_key = self.unit_name - if bucket_key not in relation: - relation[bucket_key] = {} - bucket = relation[bucket_key] - if value == '': - bucket.pop(key, None) - else: - bucket[key] = value - - def config_get(self): - return self._config - - def is_leader(self): - return self._is_leader - - def application_version_set(self, version): - self._workload_version = version - - def resource_get(self, resource_name): - return self._resources_map[resource_name] - - def pod_spec_set(self, spec, k8s_resources): - self._pod_spec = (spec, k8s_resources) - - def status_get(self, *, is_app=False): - if is_app: - return self._app_status - else: - return self._unit_status - - def status_set(self, status, message='', *, is_app=False): - if is_app: - self._app_status = (status, message) - else: - self._unit_status = (status, message) - - def storage_list(self, name): - raise NotImplementedError(self.storage_list) - - def storage_get(self, storage_name_id, attribute): - raise NotImplementedError(self.storage_get) - - def storage_add(self, name, count=1): - raise NotImplementedError(self.storage_add) - - def action_get(self): - raise NotImplementedError(self.action_get) - - def action_set(self, results): - raise NotImplementedError(self.action_set) - - def action_log(self, message): - raise NotImplementedError(self.action_log) - - def action_fail(self, message=''): - raise NotImplementedError(self.action_fail) - - def network_get(self, endpoint_name, relation_id=None): - raise NotImplementedError(self.network_get) diff --git a/magma/squid_cnf/charms/squid/mod/operator/requirements.txt b/magma/squid_cnf/charms/squid/mod/operator/requirements.txt deleted file mode 100644 index 5500f007..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -PyYAML diff --git a/magma/squid_cnf/charms/squid/mod/operator/run_tests b/magma/squid_cnf/charms/squid/mod/operator/run_tests deleted file mode 100755 index 56411030..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/run_tests +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -python3 -m unittest "$@" diff --git a/magma/squid_cnf/charms/squid/mod/operator/setup.py b/magma/squid_cnf/charms/squid/mod/operator/setup.py deleted file mode 100644 index cc017478..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/setup.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2019 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. - -from setuptools import setup - -with open("README.md", "r") as fh: - long_description = fh.read() - -setup( - name="ops", - version="0.0.1", - description="The Python library behind great charms", - long_description=long_description, - long_description_content_type="text/markdown", - license="Apache-2.0", - url="https://github.com/canonical/operator", - packages=["ops"], - classifiers=[ - "Development Status :: 4 - Beta", - - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - - "License :: OSI Approved :: Apache Software License", - ], -) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/__init__.py b/magma/squid_cnf/charms/squid/mod/operator/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids b/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids deleted file mode 100755 index a7e0ead2..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-ids +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -case $1 in - db) echo '["db:1"]' ;; - mon) echo '["mon:2"]' ;; - ha) echo '[]' ;; - db0) echo '[]' ;; - db1) echo '["db1:4"]' ;; - db2) echo '["db2:5", "db2:6"]' ;; - *) echo '[]' ;; -esac diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list b/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list deleted file mode 100755 index 88490159..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/bin/relation-list +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -fail_not_found() { - 1>&2 echo "ERROR invalid value \"$1\" for option -r: relation not found" - exit 2 -} - -case $2 in - 1) echo '["remote/0"]' ;; - 2) echo '["remote/0"]' ;; - 3) fail_not_found $2 ;; - 4) echo '["remoteapp1/0"]' ;; - 5) echo '["remoteapp1/0"]' ;; - 6) echo '["remoteapp2/0"]' ;; - *) fail_not_found $2 ;; -esac diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml deleted file mode 100644 index ffc01860..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/config.yaml +++ /dev/null @@ -1 +0,0 @@ -"options": {} diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops deleted file mode 120000 index 1356790e..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/lib/ops +++ /dev/null @@ -1 +0,0 @@ -../../../../ops \ No newline at end of file diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml deleted file mode 100644 index 3b3aed87..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/metadata.yaml +++ /dev/null @@ -1,26 +0,0 @@ -name: main -summary: A charm used for testing the basic operation of the entrypoint code. -maintainer: Dmitrii Shcherbakov -description: A charm used for testing the basic operation of the entrypoint code. -tags: - - misc -series: - - bionic - - cosmic - - disco -min-juju-version: 2.7.1 -provides: - db: - interface: db -requires: - mon: - interface: monitoring -peers: - ha: - interface: cluster -subordinate: false -storage: - disks: - type: block - multiple: - range: 0- diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py b/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py deleted file mode 100755 index 0e066c97..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/charms/test_main/src/charm.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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 base64 -import pickle -import sys -import logging - -sys.path.append('lib') - -from ops.charm import CharmBase # noqa: E402 (module-level import after non-import code) -from ops.main import main # noqa: E402 (ditto) - -logger = logging.getLogger() - - -class Charm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - - # This environment variable controls the test charm behavior. - charm_config = os.environ.get('CHARM_CONFIG') - if charm_config is not None: - self._charm_config = pickle.loads(base64.b64decode(charm_config)) - else: - self._charm_config = {} - - # TODO: refactor to use StoredState - # (this implies refactoring most of test_main.py) - self._state_file = self._charm_config.get('STATE_FILE') - try: - with open(str(self._state_file), 'rb') as f: - self._state = pickle.load(f) - except (FileNotFoundError, EOFError): - self._state = { - 'on_install': [], - 'on_start': [], - 'on_config_changed': [], - 'on_update_status': [], - 'on_leader_settings_changed': [], - 'on_db_relation_joined': [], - 'on_mon_relation_changed': [], - 'on_mon_relation_departed': [], - 'on_ha_relation_broken': [], - 'on_foo_bar_action': [], - 'on_start_action': [], - 'on_collect_metrics': [], - - 'on_log_critical_action': [], - 'on_log_error_action': [], - 'on_log_warning_action': [], - 'on_log_info_action': [], - 'on_log_debug_action': [], - - # Observed event types per invocation. A list is used to preserve the - # order in which charm handlers have observed the events. - 'observed_event_types': [], - } - - self.framework.observe(self.on.install, self) - self.framework.observe(self.on.start, self) - self.framework.observe(self.on.config_changed, self) - self.framework.observe(self.on.update_status, self) - self.framework.observe(self.on.leader_settings_changed, self) - # Test relation events with endpoints from different - # sections (provides, requires, peers) as well. - self.framework.observe(self.on.db_relation_joined, self) - self.framework.observe(self.on.mon_relation_changed, self) - self.framework.observe(self.on.mon_relation_departed, self) - self.framework.observe(self.on.ha_relation_broken, self) - - if self._charm_config.get('USE_ACTIONS'): - self.framework.observe(self.on.start_action, self) - self.framework.observe(self.on.foo_bar_action, self) - - self.framework.observe(self.on.collect_metrics, self) - - if self._charm_config.get('USE_LOG_ACTIONS'): - self.framework.observe(self.on.log_critical_action, self) - self.framework.observe(self.on.log_error_action, self) - self.framework.observe(self.on.log_warning_action, self) - self.framework.observe(self.on.log_info_action, self) - self.framework.observe(self.on.log_debug_action, self) - - def _write_state(self): - """Write state variables so that the parent process can read them. - - Each invocation will override the previous state which is intentional. - """ - if self._state_file is not None: - with self._state_file.open('wb') as f: - pickle.dump(self._state, f) - - def on_install(self, event): - self._state['on_install'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_start(self, event): - self._state['on_start'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_config_changed(self, event): - self._state['on_config_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - event.defer() - self._write_state() - - def on_update_status(self, event): - self._state['on_update_status'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_leader_settings_changed(self, event): - self._state['on_leader_settings_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_db_relation_joined(self, event): - assert event.app is not None, 'application name cannot be None for a relation-joined event' - self._state['on_db_relation_joined'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['db_relation_joined_data'] = event.snapshot() - self._write_state() - - def on_mon_relation_changed(self, event): - assert event.app is not None, ( - 'application name cannot be None for a relation-changed event') - if os.environ.get('JUJU_REMOTE_UNIT'): - assert event.unit is not None, ( - 'a unit name cannot be None for a relation-changed event' - ' associated with a remote unit') - self._state['on_mon_relation_changed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['mon_relation_changed_data'] = event.snapshot() - self._write_state() - - def on_mon_relation_departed(self, event): - assert event.app is not None, ( - 'application name cannot be None for a relation-departed event') - self._state['on_mon_relation_departed'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['mon_relation_departed_data'] = event.snapshot() - self._write_state() - - def on_ha_relation_broken(self, event): - assert event.app is None, ( - 'relation-broken events cannot have a reference to a remote application') - assert event.unit is None, ( - 'relation broken events cannot have a reference to a remote unit') - self._state['on_ha_relation_broken'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._state['ha_relation_broken_data'] = event.snapshot() - self._write_state() - - def on_start_action(self, event): - assert event.handle.kind == 'start_action', ( - 'event action name cannot be different from the one being handled') - self._state['on_start_action'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_foo_bar_action(self, event): - assert event.handle.kind == 'foo_bar_action', ( - 'event action name cannot be different from the one being handled') - self._state['on_foo_bar_action'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - self._write_state() - - def on_collect_metrics(self, event): - self._state['on_collect_metrics'].append(type(event)) - self._state['observed_event_types'].append(type(event)) - event.add_metrics({'foo': 42}, {'bar': 4.2}) - self._write_state() - - def on_log_critical_action(self, event): - logger.critical('super critical') - - def on_log_error_action(self, event): - logger.error('grave error') - - def on_log_warning_action(self, event): - logger.warning('wise warning') - - def on_log_info_action(self, event): - logger.info('useful info') - - def on_log_debug_action(self, event): - logger.debug('insightful debug') - - -if __name__ == '__main__': - main(Charm) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py deleted file mode 100755 index c8d84475..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_charm.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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 unittest -import tempfile -import shutil - -from pathlib import Path - -from ops.charm import ( - CharmBase, - CharmMeta, - CharmEvents, -) -from ops.framework import Framework, EventSource, EventBase -from ops.model import Model, ModelBackend - -from .test_helpers import fake_script, fake_script_calls - - -class TestCharm(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['PATH'] = "{}:{}".format(Path(__file__).parent / 'bin', os.environ['PATH']) - os.environ['JUJU_UNIT_NAME'] = 'local/0' - - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - self.meta = CharmMeta() - - class CustomEvent(EventBase): - pass - - class TestCharmEvents(CharmEvents): - custom = EventSource(CustomEvent) - - # Relations events are defined dynamically and modify the class attributes. - # We use a subclass temporarily to prevent these side effects from leaking. - CharmBase.on = TestCharmEvents() - - def cleanup(): - CharmBase.on = CharmEvents() - self.addCleanup(cleanup) - - def create_framework(self): - model = Model('local/0', self.meta, ModelBackend()) - framework = Framework(self.tmpdir / "framework.data", self.tmpdir, self.meta, model) - self.addCleanup(framework.close) - return framework - - def test_basic(self): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - - self.started = False - framework.observe(self.on.start, self) - - def on_start(self, event): - self.started = True - - events = list(MyCharm.on.events()) - self.assertIn('install', events) - self.assertIn('custom', events) - - framework = self.create_framework() - charm = MyCharm(framework, None) - charm.on.start.emit() - - self.assertEqual(charm.started, True) - - def test_helper_properties(self): - framework = self.create_framework() - - class MyCharm(CharmBase): - pass - - charm = MyCharm(framework, None) - self.assertEqual(charm.app, framework.model.app) - self.assertEqual(charm.unit, framework.model.unit) - self.assertEqual(charm.meta, framework.meta) - self.assertEqual(charm.charm_dir, framework.charm_dir) - - def test_relation_events(self): - - class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.seen = [] - for rel in ('req1', 'req-2', 'pro1', 'pro-2', 'peer1', 'peer-2'): - # Hook up relation events to generic handler. - self.framework.observe(self.on[rel].relation_joined, self.on_any_relation) - self.framework.observe(self.on[rel].relation_changed, self.on_any_relation) - self.framework.observe(self.on[rel].relation_departed, self.on_any_relation) - self.framework.observe(self.on[rel].relation_broken, self.on_any_relation) - - def on_any_relation(self, event): - assert event.relation.name == 'req1' - assert event.relation.app.name == 'remote' - self.seen.append(type(event).__name__) - - # language=YAML - self.meta = CharmMeta.from_yaml(metadata=''' -name: my-charm -requires: - req1: - interface: req1 - req-2: - interface: req2 -provides: - pro1: - interface: pro1 - pro-2: - interface: pro2 -peers: - peer1: - interface: peer1 - peer-2: - interface: peer2 -''') - - charm = MyCharm(self.create_framework(), None) - - rel = charm.framework.model.get_relation('req1', 1) - unit = charm.framework.model.get_unit('remote/0') - charm.on['req1'].relation_joined.emit(rel, unit) - charm.on['req1'].relation_changed.emit(rel, unit) - charm.on['req-2'].relation_changed.emit(rel, unit) - charm.on['pro1'].relation_departed.emit(rel, unit) - charm.on['pro-2'].relation_departed.emit(rel, unit) - charm.on['peer1'].relation_broken.emit(rel) - charm.on['peer-2'].relation_broken.emit(rel) - - self.assertEqual(charm.seen, [ - 'RelationJoinedEvent', - 'RelationChangedEvent', - 'RelationChangedEvent', - 'RelationDepartedEvent', - 'RelationDepartedEvent', - 'RelationBrokenEvent', - 'RelationBrokenEvent', - ]) - - def test_storage_events(self): - - class MyCharm(CharmBase): - def __init__(self, *args): - super().__init__(*args) - self.seen = [] - self.framework.observe(self.on['stor1'].storage_attached, self) - self.framework.observe(self.on['stor2'].storage_detaching, self) - self.framework.observe(self.on['stor3'].storage_attached, self) - self.framework.observe(self.on['stor-4'].storage_attached, self) - - def on_stor1_storage_attached(self, event): - self.seen.append(type(event).__name__) - - def on_stor2_storage_detaching(self, event): - self.seen.append(type(event).__name__) - - def on_stor3_storage_attached(self, event): - self.seen.append(type(event).__name__) - - def on_stor_4_storage_attached(self, event): - self.seen.append(type(event).__name__) - - # language=YAML - self.meta = CharmMeta.from_yaml(''' -name: my-charm -storage: - stor-4: - multiple: - range: 2-4 - type: filesystem - stor1: - type: filesystem - stor2: - multiple: - range: "2" - type: filesystem - stor3: - multiple: - range: 2- - type: filesystem -''') - - self.assertIsNone(self.meta.storages['stor1'].multiple_range) - self.assertEqual(self.meta.storages['stor2'].multiple_range, (2, 2)) - self.assertEqual(self.meta.storages['stor3'].multiple_range, (2, None)) - self.assertEqual(self.meta.storages['stor-4'].multiple_range, (2, 4)) - - charm = MyCharm(self.create_framework(), None) - - charm.on['stor1'].storage_attached.emit() - charm.on['stor2'].storage_detaching.emit() - charm.on['stor3'].storage_attached.emit() - charm.on['stor-4'].storage_attached.emit() - - self.assertEqual(charm.seen, [ - 'StorageAttachedEvent', - 'StorageDetachingEvent', - 'StorageAttachedEvent', - 'StorageAttachedEvent', - ]) - - @classmethod - def _get_action_test_meta(cls): - # language=YAML - return CharmMeta.from_yaml(metadata=''' -name: my-charm -''', actions=''' -foo-bar: - description: "Foos the bar." - params: - foo-name: - description: "A foo name to bar" - type: string - silent: - default: false - description: "" - type: boolean - required: foo-bar - title: foo-bar -start: - description: "Start the unit." -''') - - def _test_action_events(self, cmd_type): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - framework.observe(self.on.foo_bar_action, self) - framework.observe(self.on.start_action, self) - - def on_foo_bar_action(self, event): - self.seen_action_params = event.params - event.log('test-log') - event.set_results({'res': 'val with spaces'}) - event.fail('test-fail') - - def on_start_action(self, event): - pass - - fake_script(self, cmd_type + '-get', """echo '{"foo-name": "name", "silent": true}'""") - fake_script(self, cmd_type + '-set', "") - fake_script(self, cmd_type + '-log', "") - fake_script(self, cmd_type + '-fail', "") - self.meta = self._get_action_test_meta() - - os.environ['JUJU_{}_NAME'.format(cmd_type.upper())] = 'foo-bar' - framework = self.create_framework() - charm = MyCharm(framework, None) - - events = list(MyCharm.on.events()) - self.assertIn('foo_bar_action', events) - self.assertIn('start_action', events) - - charm.on.foo_bar_action.emit() - self.assertEqual(charm.seen_action_params, {"foo-name": "name", "silent": True}) - self.assertEqual(fake_script_calls(self), [ - [cmd_type + '-get', '--format=json'], - [cmd_type + '-log', "test-log"], - [cmd_type + '-set', "res=val with spaces"], - [cmd_type + '-fail', "test-fail"], - ]) - - # Make sure that action events that do not match the current context are - # not possible to emit by hand. - with self.assertRaises(RuntimeError): - charm.on.start_action.emit() - - def test_action_events(self): - self._test_action_events('action') - - def _test_action_event_defer_fails(self, cmd_type): - - class MyCharm(CharmBase): - - def __init__(self, *args): - super().__init__(*args) - framework.observe(self.on.start_action, self) - - def on_start_action(self, event): - event.defer() - - fake_script(self, cmd_type + '-get', """echo '{"foo-name": "name", "silent": true}'""") - self.meta = self._get_action_test_meta() - - os.environ['JUJU_{}_NAME'.format(cmd_type.upper())] = 'start' - framework = self.create_framework() - charm = MyCharm(framework, None) - - with self.assertRaises(RuntimeError): - charm.on.start_action.emit() - - def test_action_event_defer_fails(self): - self._test_action_event_defer_fails('action') - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py deleted file mode 100644 index 2ec4c4ed..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_framework.py +++ /dev/null @@ -1,1727 +0,0 @@ -# Copyright 2019-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 datetime -import gc -import inspect -import io -import os -import shutil -import sys -import tempfile -import unittest -from unittest.mock import patch -from pathlib import Path - -from ops import charm, model -from ops.framework import ( - _BREAKPOINT_WELCOME_MESSAGE, - BoundStoredState, - CommitEvent, - EventBase, - ObjectEvents, - EventSource, - Framework, - Handle, - NoSnapshotError, - Object, - PreCommitEvent, - SQLiteStorage, - StoredList, - StoredState, - StoredStateData, -) -from test.test_helpers import fake_script - - -class TestFramework(unittest.TestCase): - - def setUp(self): - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - default_timeout = SQLiteStorage.DB_LOCK_TIMEOUT - - def timeout_cleanup(): - SQLiteStorage.DB_LOCK_TIMEOUT = default_timeout - SQLiteStorage.DB_LOCK_TIMEOUT = datetime.timedelta(0) - self.addCleanup(timeout_cleanup) - - def create_framework(self): - framework = Framework(self.tmpdir / "framework.data", self.tmpdir, None, None) - self.addCleanup(framework.close) - return framework - - def test_handle_path(self): - cases = [ - (Handle(None, "root", None), "root"), - (Handle(None, "root", "1"), "root[1]"), - (Handle(Handle(None, "root", None), "child", None), "root/child"), - (Handle(Handle(None, "root", "1"), "child", "2"), "root[1]/child[2]"), - ] - for handle, path in cases: - self.assertEqual(str(handle), path) - self.assertEqual(Handle.from_path(path), handle) - - def test_handle_attrs_readonly(self): - handle = Handle(None, 'kind', 'key') - with self.assertRaises(AttributeError): - handle.parent = 'foo' - with self.assertRaises(AttributeError): - handle.kind = 'foo' - with self.assertRaises(AttributeError): - handle.key = 'foo' - with self.assertRaises(AttributeError): - handle.path = 'foo' - - def test_restore_unknown(self): - framework = self.create_framework() - - class Foo(Object): - pass - - handle = Handle(None, "a_foo", "some_key") - - framework.register_type(Foo, None, handle.kind) - - try: - framework.load_snapshot(handle) - except NoSnapshotError as e: - self.assertEqual(e.handle_path, str(handle)) - self.assertEqual(str(e), "no snapshot data found for a_foo[some_key] object") - else: - self.fail("exception NoSnapshotError not raised") - - def test_snapshot_roundtrip(self): - class Foo: - def __init__(self, handle, n): - self.handle = handle - self.my_n = n - - def snapshot(self): - return {"My N!": self.my_n} - - def restore(self, snapshot): - self.my_n = snapshot["My N!"] + 1 - - handle = Handle(None, "a_foo", "some_key") - event = Foo(handle, 1) - - framework1 = self.create_framework() - framework1.register_type(Foo, None, handle.kind) - framework1.save_snapshot(event) - framework1.commit() - framework1.close() - - framework2 = self.create_framework() - framework2.register_type(Foo, None, handle.kind) - event2 = framework2.load_snapshot(handle) - self.assertEqual(event2.my_n, 2) - - framework2.save_snapshot(event2) - del event2 - gc.collect() - event3 = framework2.load_snapshot(handle) - self.assertEqual(event3.my_n, 3) - - framework2.drop_snapshot(event.handle) - framework2.commit() - framework2.close() - - framework3 = self.create_framework() - framework3.register_type(Foo, None, handle.kind) - - self.assertRaises(NoSnapshotError, framework3.load_snapshot, handle) - - def test_simple_event_observer(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - baz = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_any(self, event): - self.seen.append("on_any:" + event.handle.kind) - - def on_foo(self, event): - self.seen.append("on_foo:" + event.handle.kind) - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs.on_any) - framework.observe(pub.bar, obs.on_any) - framework.observe(pub.foo, obs) # Method name defaults to on_. - - try: - framework.observe(pub.baz, obs) - except RuntimeError as e: - self.assertEqual( - str(e), - 'Observer method not provided explicitly' - ' and MyObserver type has no "on_baz" method') - else: - self.fail("RuntimeError not raised") - - pub.foo.emit() - pub.bar.emit() - - self.assertEqual(obs.seen, ["on_any:foo", "on_foo:foo", "on_any:bar"]) - - def test_bad_sig_observer(self): - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - baz = EventSource(MyEvent) - qux = EventSource(MyEvent) - - class MyObserver(Object): - def on_foo(self): - assert False, 'should not be reached' - - def on_bar(self, event, extra): - assert False, 'should not be reached' - - def on_baz(self, event, extra=None, *, k): - assert False, 'should not be reached' - - def on_qux(self, event, extra=None): - assert False, 'should not be reached' - - framework = self.create_framework() - pub = MyNotifier(framework, "pub") - obs = MyObserver(framework, "obs") - - with self.assertRaises(TypeError): - framework.observe(pub.foo, obs) - with self.assertRaises(TypeError): - framework.observe(pub.bar, obs) - with self.assertRaises(TypeError): - framework.observe(pub.baz, obs) - framework.observe(pub.qux, obs) - - def test_on_pre_commit_emitted(self): - framework = self.create_framework() - - class PreCommitObserver(Object): - - _stored = StoredState() - - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - self._stored.myinitdata = 40 - - def on_pre_commit(self, event): - self._stored.myinitdata = 41 - self._stored.mydata = 42 - self.seen.append(type(event)) - - def on_commit(self, event): - # Modifications made here will not be persisted. - self._stored.myinitdata = 42 - self._stored.mydata = 43 - self._stored.myotherdata = 43 - self.seen.append(type(event)) - - obs = PreCommitObserver(framework, None) - - framework.observe(framework.on.pre_commit, obs.on_pre_commit) - - framework.commit() - - self.assertEqual(obs._stored.myinitdata, 41) - self.assertEqual(obs._stored.mydata, 42) - self.assertTrue(obs.seen, [PreCommitEvent, CommitEvent]) - framework.close() - - other_framework = self.create_framework() - - new_obs = PreCommitObserver(other_framework, None) - - self.assertEqual(obs._stored.myinitdata, 41) - self.assertEqual(new_obs._stored.mydata, 42) - - with self.assertRaises(AttributeError): - new_obs._stored.myotherdata - - def test_defer_and_reemit(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier1(Object): - a = EventSource(MyEvent) - b = EventSource(MyEvent) - - class MyNotifier2(Object): - c = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - self.done = {} - - def on_any(self, event): - self.seen.append(event.handle.kind) - if not self.done.get(event.handle.kind): - event.defer() - - pub1 = MyNotifier1(framework, "1") - pub2 = MyNotifier2(framework, "1") - obs1 = MyObserver(framework, "1") - obs2 = MyObserver(framework, "2") - - framework.observe(pub1.a, obs1.on_any) - framework.observe(pub1.b, obs1.on_any) - framework.observe(pub1.a, obs2.on_any) - framework.observe(pub1.b, obs2.on_any) - framework.observe(pub2.c, obs2.on_any) - - pub1.a.emit() - pub1.b.emit() - pub2.c.emit() - - # Events remain stored because they were deferred. - ev_a_handle = Handle(pub1, "a", "1") - framework.load_snapshot(ev_a_handle) - ev_b_handle = Handle(pub1, "b", "2") - framework.load_snapshot(ev_b_handle) - ev_c_handle = Handle(pub2, "c", "3") - framework.load_snapshot(ev_c_handle) - # make sure the objects are gone before we reemit them - gc.collect() - - framework.reemit() - obs1.done["a"] = True - obs2.done["b"] = True - framework.reemit() - framework.reemit() - obs1.done["b"] = True - obs2.done["a"] = True - framework.reemit() - obs2.done["c"] = True - framework.reemit() - framework.reemit() - framework.reemit() - - self.assertEqual(" ".join(obs1.seen), "a b a b a b b b") - self.assertEqual(" ".join(obs2.seen), "a b c a b c a b c a c a c c") - - # Now the event objects must all be gone from storage. - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_a_handle) - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_b_handle) - self.assertRaises(NoSnapshotError, framework.load_snapshot, ev_c_handle) - - def test_custom_event_data(self): - framework = self.create_framework() - - class MyEvent(EventBase): - def __init__(self, handle, n): - super().__init__(handle) - self.my_n = n - - def snapshot(self): - return {"My N!": self.my_n} - - def restore(self, snapshot): - super().restore(snapshot) - self.my_n = snapshot["My N!"] + 1 - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}={}".format(event.handle.kind, event.my_n)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs) - - pub.foo.emit(1) - - framework.reemit() - - # Two things being checked here: - # - # 1. There's a restore roundtrip before the event is first observed. - # That means the data is safe before it's ever seen, and the - # roundtrip logic is tested under normal circumstances. - # - # 2. The renotification restores from the pristine event, not - # from the one modified during the first restore (otherwise - # we'd get a foo=3). - # - self.assertEqual(obs.seen, ["on_foo:foo=2", "on_foo:foo=2"]) - - def test_weak_observer(self): - framework = self.create_framework() - - observed_events = [] - - class MyEvent(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyEvent) - - class MyNotifier(Object): - on = MyEvents() - - class MyObserver(Object): - def on_foo(self, event): - observed_events.append("foo") - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "2") - - framework.observe(pub.on.foo, obs) - pub.on.foo.emit() - self.assertEqual(observed_events, ["foo"]) - # Now delete the observer, and note that when we emit the event, it - # doesn't update the local slice again - del obs - gc.collect() - pub.on.foo.emit() - self.assertEqual(observed_events, ["foo"]) - - def test_forget_and_multiple_objects(self): - framework = self.create_framework() - - class MyObject(Object): - pass - - o1 = MyObject(framework, "path") - # Creating a second object at the same path should fail with RuntimeError - with self.assertRaises(RuntimeError): - o2 = MyObject(framework, "path") - # Unless we _forget the object first - framework._forget(o1) - o2 = MyObject(framework, "path") - self.assertEqual(o1.handle.path, o2.handle.path) - # Deleting the tracked object should also work - del o2 - gc.collect() - o3 = MyObject(framework, "path") - self.assertEqual(o1.handle.path, o3.handle.path) - framework.close() - # Or using a second framework - framework_copy = self.create_framework() - o_copy = MyObject(framework_copy, "path") - self.assertEqual(o1.handle.path, o_copy.handle.path) - - def test_forget_and_multiple_objects_with_load_snapshot(self): - framework = self.create_framework() - - class MyObject(Object): - def __init__(self, parent, name): - super().__init__(parent, name) - self.value = name - - def snapshot(self): - return self.value - - def restore(self, value): - self.value = value - - framework.register_type(MyObject, None, MyObject.handle_kind) - o1 = MyObject(framework, "path") - framework.save_snapshot(o1) - framework.commit() - o_handle = o1.handle - del o1 - gc.collect() - o2 = framework.load_snapshot(o_handle) - # Trying to load_snapshot a second object at the same path should fail with RuntimeError - with self.assertRaises(RuntimeError): - framework.load_snapshot(o_handle) - # Unless we _forget the object first - framework._forget(o2) - o3 = framework.load_snapshot(o_handle) - self.assertEqual(o2.value, o3.value) - # A loaded object also prevents direct creation of an object - with self.assertRaises(RuntimeError): - MyObject(framework, "path") - framework.close() - # But we can create an object, or load a snapshot in a copy of the framework - framework_copy1 = self.create_framework() - o_copy1 = MyObject(framework_copy1, "path") - self.assertEqual(o_copy1.value, "path") - framework_copy1.close() - framework_copy2 = self.create_framework() - framework_copy2.register_type(MyObject, None, MyObject.handle_kind) - o_copy2 = framework_copy2.load_snapshot(o_handle) - self.assertEqual(o_copy2.value, "path") - - def test_events_base(self): - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyEvent) - bar = EventSource(MyEvent) - - class MyNotifier(Object): - on = MyEvents() - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}".format(event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}".format(event.handle.kind)) - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - # Confirm that temporary persistence of BoundEvents doesn't cause errors, - # and that events can be observed. - for bound_event in [pub.on.foo, pub.on.bar]: - framework.observe(bound_event, obs) - - # Confirm that events can be emitted and seen. - pub.on.foo.emit() - - self.assertEqual(obs.seen, ["on_foo:foo"]) - - def test_conflicting_event_attributes(self): - class MyEvent(EventBase): - pass - - event = EventSource(MyEvent) - - class MyEvents(ObjectEvents): - foo = event - - with self.assertRaises(RuntimeError) as cm: - class OtherEvents(ObjectEvents): - foo = event - self.assertEqual( - str(cm.exception), - "EventSource(MyEvent) reused as MyEvents.foo and OtherEvents.foo") - - with self.assertRaises(RuntimeError) as cm: - class MyNotifier(Object): - on = MyEvents() - bar = event - self.assertEqual( - str(cm.exception), - "EventSource(MyEvent) reused as MyEvents.foo and MyNotifier.bar") - - def test_reemit_ignores_unknown_event_type(self): - # The event type may have been gone for good, and nobody cares, - # so this shouldn't be an error scenario. - - framework = self.create_framework() - - class MyEvent(EventBase): - pass - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append(event.handle) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - framework.observe(pub.foo, obs) - pub.foo.emit() - - event_handle = obs.seen[0] - self.assertEqual(event_handle.kind, "foo") - - framework.commit() - framework.close() - - framework_copy = self.create_framework() - - # No errors on missing event types here. - framework_copy.reemit() - - # Register the type and check that the event is gone from storage. - framework_copy.register_type(MyEvent, event_handle.parent, event_handle.kind) - self.assertRaises(NoSnapshotError, framework_copy.load_snapshot, event_handle) - - def test_auto_register_event_types(self): - framework = self.create_framework() - - class MyFoo(EventBase): - pass - - class MyBar(EventBase): - pass - - class MyEvents(ObjectEvents): - foo = EventSource(MyFoo) - - class MyNotifier(Object): - on = MyEvents() - bar = EventSource(MyBar) - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - pub.on.foo.emit() - pub.bar.emit() - - framework.observe(pub.on.foo, obs) - framework.observe(pub.bar, obs) - - pub.on.foo.emit() - pub.bar.emit() - - self.assertEqual(obs.seen, ["on_foo:MyFoo:foo", "on_bar:MyBar:bar"]) - - def test_dynamic_event_types(self): - framework = self.create_framework() - - class MyEventsA(ObjectEvents): - handle_kind = 'on_a' - - class MyEventsB(ObjectEvents): - handle_kind = 'on_b' - - class MyNotifier(Object): - on_a = MyEventsA() - on_b = MyEventsB() - - class MyObserver(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append("on_foo:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - def on_bar(self, event): - self.seen.append("on_bar:{}:{}".format(type(event).__name__, event.handle.kind)) - event.defer() - - pub = MyNotifier(framework, "1") - obs = MyObserver(framework, "1") - - class MyFoo(EventBase): - pass - - class MyBar(EventBase): - pass - - class DeadBeefEvent(EventBase): - pass - - class NoneEvent(EventBase): - pass - - pub.on_a.define_event("foo", MyFoo) - pub.on_b.define_event("bar", MyBar) - - framework.observe(pub.on_a.foo, obs) - framework.observe(pub.on_b.bar, obs) - - pub.on_a.foo.emit() - pub.on_b.bar.emit() - - self.assertEqual(obs.seen, ["on_foo:MyFoo:foo", "on_bar:MyBar:bar"]) - - # Definitions remained local to the specific type. - self.assertRaises(AttributeError, lambda: pub.on_a.bar) - self.assertRaises(AttributeError, lambda: pub.on_b.foo) - - # Try to use an event name which is not a valid python identifier. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("dead-beef", DeadBeefEvent) - - # Try to use a python keyword for an event name. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("None", NoneEvent) - - # Try to override an existing attribute. - with self.assertRaises(RuntimeError): - pub.on_a.define_event("foo", MyFoo) - - def test_event_key_roundtrip(self): - class MyEvent(EventBase): - def __init__(self, handle, value): - super().__init__(handle) - self.value = value - - def snapshot(self): - return self.value - - def restore(self, value): - self.value = value - - class MyNotifier(Object): - foo = EventSource(MyEvent) - - class MyObserver(Object): - has_deferred = False - - def __init__(self, parent, key): - super().__init__(parent, key) - self.seen = [] - - def on_foo(self, event): - self.seen.append((event.handle.key, event.value)) - # Only defer the first event and once. - if not MyObserver.has_deferred: - event.defer() - MyObserver.has_deferred = True - - framework1 = self.create_framework() - pub1 = MyNotifier(framework1, "pub") - obs1 = MyObserver(framework1, "obs") - framework1.observe(pub1.foo, obs1) - pub1.foo.emit('first') - self.assertEqual(obs1.seen, [('1', 'first')]) - - framework1.commit() - framework1.close() - del framework1 - - framework2 = self.create_framework() - pub2 = MyNotifier(framework2, "pub") - obs2 = MyObserver(framework2, "obs") - framework2.observe(pub2.foo, obs2) - pub2.foo.emit('second') - framework2.reemit() - - # First observer didn't get updated, since framework it was bound to is gone. - self.assertEqual(obs1.seen, [('1', 'first')]) - # Second observer saw the new event plus the reemit of the first event. - # (The event key goes up by 2 due to the pre-commit and commit events.) - self.assertEqual(obs2.seen, [('4', 'second'), ('1', 'first')]) - - def test_helper_properties(self): - framework = self.create_framework() - framework.model = 'test-model' - framework.meta = 'test-meta' - - my_obj = Object(framework, 'my_obj') - self.assertEqual(my_obj.model, framework.model) - - def test_ban_concurrent_frameworks(self): - f = self.create_framework() - with self.assertRaises(Exception) as cm: - self.create_framework() - self.assertIn('database is locked', str(cm.exception)) - f.close() - - def test_snapshot_saving_restricted_to_simple_types(self): - # this can not be saved, as it has not simple types! - to_be_saved = {"bar": TestFramework} - - class FooEvent(EventBase): - def snapshot(self): - return to_be_saved - - handle = Handle(None, "a_foo", "some_key") - event = FooEvent(handle) - - framework = self.create_framework() - framework.register_type(FooEvent, None, handle.kind) - with self.assertRaises(ValueError) as cm: - framework.save_snapshot(event) - expected = ( - "unable to save the data for FooEvent, it must contain only simple types: " - "{'bar': }") - self.assertEqual(str(cm.exception), expected) - - -class TestStoredState(unittest.TestCase): - - def setUp(self): - self.tmpdir = Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(self.tmpdir)) - - def create_framework(self, cls=Framework): - framework = cls(self.tmpdir / "framework.data", self.tmpdir, None, None) - self.addCleanup(framework.close) - return framework - - def test_basic_state_storage(self): - class SomeObject(Object): - _stored = StoredState() - - self._stored_state_tests(SomeObject) - - def test_straight_subclass(self): - class SomeObject(Object): - _stored = StoredState() - - class Sub(SomeObject): - pass - - self._stored_state_tests(Sub) - - def test_straight_sub_subclass(self): - class SomeObject(Object): - _stored = StoredState() - - class Sub(SomeObject): - pass - - class SubSub(SomeObject): - pass - - self._stored_state_tests(SubSub) - - def test_two_subclasses(self): - class SomeObject(Object): - _stored = StoredState() - - class SubA(SomeObject): - pass - - class SubB(SomeObject): - pass - - self._stored_state_tests(SubA) - self._stored_state_tests(SubB) - - def test_the_crazy_thing(self): - class NoState(Object): - pass - - class StatedObject(NoState): - _stored = StoredState() - - class Sibling(NoState): - pass - - class FinalChild(StatedObject, Sibling): - pass - - self._stored_state_tests(FinalChild) - - def _stored_state_tests(self, cls): - framework = self.create_framework() - obj = cls(framework, "1") - - try: - obj._stored.foo - except AttributeError as e: - self.assertEqual(str(e), "attribute 'foo' is not stored") - else: - self.fail("AttributeError not raised") - - try: - obj._stored.on = "nonono" - except AttributeError as e: - self.assertEqual(str(e), "attribute 'on' is reserved and cannot be set") - else: - self.fail("AttributeError not raised") - - obj._stored.foo = 41 - obj._stored.foo = 42 - obj._stored.bar = "s" - obj._stored.baz = 4.2 - obj._stored.bing = True - - self.assertEqual(obj._stored.foo, 42) - - framework.commit() - - # This won't be committed, and should not be seen. - obj._stored.foo = 43 - - framework.close() - - # Since this has the same absolute object handle, it will get its state back. - framework_copy = self.create_framework() - obj_copy = cls(framework_copy, "1") - self.assertEqual(obj_copy._stored.foo, 42) - self.assertEqual(obj_copy._stored.bar, "s") - self.assertEqual(obj_copy._stored.baz, 4.2) - self.assertEqual(obj_copy._stored.bing, True) - - framework_copy.close() - - def test_two_subclasses_no_conflicts(self): - class Base(Object): - _stored = StoredState() - - class SubA(Base): - pass - - class SubB(Base): - pass - - framework = self.create_framework() - a = SubA(framework, None) - b = SubB(framework, None) - z = Base(framework, None) - - a._stored.foo = 42 - b._stored.foo = "hello" - z._stored.foo = {1} - - framework.commit() - framework.close() - - framework2 = self.create_framework() - a2 = SubA(framework2, None) - b2 = SubB(framework2, None) - z2 = Base(framework2, None) - - self.assertEqual(a2._stored.foo, 42) - self.assertEqual(b2._stored.foo, "hello") - self.assertEqual(z2._stored.foo, {1}) - - def test_two_names_one_state(self): - class Mine(Object): - _stored = StoredState() - _stored2 = _stored - - framework = self.create_framework() - obj = Mine(framework, None) - - with self.assertRaises(RuntimeError): - obj._stored.foo = 42 - - with self.assertRaises(RuntimeError): - obj._stored2.foo = 42 - - framework.close() - - # make sure we're not changing the object on failure - self.assertNotIn("_stored", obj.__dict__) - self.assertNotIn("_stored2", obj.__dict__) - - def test_same_name_two_classes(self): - class Base(Object): - pass - - class A(Base): - _stored = StoredState() - - class B(Base): - _stored = A._stored - - framework = self.create_framework() - a = A(framework, None) - b = B(framework, None) - - # NOTE it's the second one that actually triggers the - # exception, but that's an implementation detail - a._stored.foo = 42 - - with self.assertRaises(RuntimeError): - b._stored.foo = "xyzzy" - - framework.close() - - # make sure we're not changing the object on failure - self.assertNotIn("_stored", b.__dict__) - - def test_mutable_types_invalid(self): - framework = self.create_framework() - - class SomeObject(Object): - _stored = StoredState() - - obj = SomeObject(framework, '1') - try: - class CustomObject: - pass - obj._stored.foo = CustomObject() - except AttributeError as e: - self.assertEqual( - str(e), - "attribute 'foo' cannot be a CustomObject: must be int/float/dict/list/etc") - else: - self.fail('AttributeError not raised') - - framework.commit() - - def test_mutable_types(self): - # Test and validation functions in a list of 2-tuples. - # Assignment and keywords like del are not supported in lambdas - # so functions are used instead. - test_operations = [( - lambda: {}, # Operand A. - None, # Operand B. - {}, # Expected result. - lambda a, b: None, # Operation to perform. - lambda res, expected_res: self.assertEqual(res, expected_res) # Validation to perform. - ), ( - lambda: {}, - {'a': {}}, - {'a': {}}, - lambda a, b: a.update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {}}, - {'b': 'c'}, - {'a': {'b': 'c'}}, - lambda a, b: a['a'].update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {'b': 'c'}}, - {'d': 'e'}, - {'a': {'b': 'c', 'd': 'e'}}, - lambda a, b: a['a'].update(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'a': {'b': 'c', 'd': 'e'}}, - 'd', - {'a': {'b': 'c'}}, - lambda a, b: a['a'].pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'s': set()}, - 'a', - {'s': {'a'}}, - lambda a, b: a['s'].add(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: {'s': {'a'}}, - 'a', - {'s': set()}, - lambda a, b: a['s'].discard(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [], - None, - [], - lambda a, b: None, - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [], - 'a', - ['a'], - lambda a, b: a.append(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a'], - ['c'], - ['a', ['c']], - lambda a, b: a.append(b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList), - ) - ), ( - lambda: ['a', ['c']], - 'b', - ['b', 'a', ['c']], - lambda a, b: a.insert(0, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['b', 'a', ['c']], - ['d'], - ['b', ['d'], 'a', ['c']], - lambda a, b: a.insert(1, b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList) - ), - ), ( - lambda: ['b', 'a', ['c']], - ['d'], - ['b', ['d'], ['c']], - # a[1] = b - lambda a, b: a.__setitem__(1, b), - lambda res, expected_res: ( - self.assertEqual(res, expected_res), - self.assertIsInstance(res[1], StoredList) - ), - ), ( - lambda: ['b', ['d'], 'a', ['c']], - 0, - [['d'], 'a', ['c']], - lambda a, b: a.pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: [['d'], 'a', ['c']], - ['d'], - ['a', ['c']], - lambda a, b: a.remove(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c']], - 'd', - ['a', ['c', 'd']], - lambda a, b: a[1].append(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c', 'd']], - 1, - ['a', ['c']], - lambda a, b: a[1].pop(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c']], - 'd', - ['a', ['c', 'd']], - lambda a, b: a[1].insert(1, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: ['a', ['c', 'd']], - 'd', - ['a', ['c']], - lambda a, b: a[1].remove(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - None, - set(), - lambda a, b: None, - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - 'a', - set(['a']), - lambda a, b: a.add(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(['a']), - 'a', - set(), - lambda a, b: a.discard(b), - lambda res, expected_res: self.assertEqual(res, expected_res) - ), ( - lambda: set(), - {'a'}, - set(), - # Nested sets are not allowed as sets themselves are not hashable. - lambda a, b: self.assertRaises(TypeError, a.add, b), - lambda res, expected_res: self.assertEqual(res, expected_res) - )] - - class SomeObject(Object): - _stored = StoredState() - - class WrappedFramework(Framework): - def __init__(self, data_path, charm_dir, meta, model): - super().__init__(data_path, charm_dir, meta, model) - self.snapshots = [] - - def save_snapshot(self, value): - if value.handle.path == 'SomeObject[1]/StoredStateData[_stored]': - self.snapshots.append((type(value), value.snapshot())) - return super().save_snapshot(value) - - # Validate correctness of modification operations. - for get_a, b, expected_res, op, validate_op in test_operations: - framework = self.create_framework(cls=WrappedFramework) - obj = SomeObject(framework, '1') - - obj._stored.a = get_a() - self.assertTrue(isinstance(obj._stored, BoundStoredState)) - - op(obj._stored.a, b) - validate_op(obj._stored.a, expected_res) - - obj._stored.a = get_a() - framework.commit() - # We should see an update for initializing a - self.assertEqual(framework.snapshots, [ - (StoredStateData, {'a': get_a()}), - ]) - del obj - gc.collect() - obj_copy1 = SomeObject(framework, '1') - self.assertEqual(obj_copy1._stored.a, get_a()) - - op(obj_copy1._stored.a, b) - validate_op(obj_copy1._stored.a, expected_res) - framework.commit() - framework.close() - - framework_copy = self.create_framework(cls=WrappedFramework) - - obj_copy2 = SomeObject(framework_copy, '1') - - validate_op(obj_copy2._stored.a, expected_res) - - # Commit saves the pre-commit and commit events, and the framework - # event counter, but shouldn't update the stored state of my object - framework.snapshots.clear() - framework_copy.commit() - self.assertEqual(framework_copy.snapshots, []) - framework_copy.close() - - def test_comparison_operations(self): - test_operations = [( - {"1"}, # Operand A. - {"1", "2"}, # Operand B. - lambda a, b: a < b, # Operation to test. - True, # Result of op(A, B). - False, # Result of op(B, A). - ), ( - {"1"}, - {"1", "2"}, - lambda a, b: a > b, - False, - True - ), ( - # Empty set comparison. - set(), - set(), - lambda a, b: a == b, - True, - True - ), ( - {"a", "c"}, - {"c", "a"}, - lambda a, b: a == b, - True, - True - ), ( - dict(), - dict(), - lambda a, b: a == b, - True, - True - ), ( - {"1": "2"}, - {"1": "2"}, - lambda a, b: a == b, - True, - True - ), ( - {"1": "2"}, - {"1": "3"}, - lambda a, b: a == b, - False, - False - ), ( - [], - [], - lambda a, b: a == b, - True, - True - ), ( - [1, 2], - [1, 2], - lambda a, b: a == b, - True, - True - ), ( - [1, 2, 5, 6], - [1, 2, 5, 8, 10], - lambda a, b: a <= b, - True, - False - ), ( - [1, 2, 5, 6], - [1, 2, 5, 8, 10], - lambda a, b: a < b, - True, - False - ), ( - [1, 2, 5, 8], - [1, 2, 5, 6, 10], - lambda a, b: a > b, - True, - False - ), ( - [1, 2, 5, 8], - [1, 2, 5, 6, 10], - lambda a, b: a >= b, - True, - False - )] - - class SomeObject(Object): - _stored = StoredState() - - framework = self.create_framework() - - for i, (a, b, op, op_ab, op_ba) in enumerate(test_operations): - obj = SomeObject(framework, str(i)) - obj._stored.a = a - self.assertEqual(op(obj._stored.a, b), op_ab) - self.assertEqual(op(b, obj._stored.a), op_ba) - - def test_set_operations(self): - test_operations = [( - {"1"}, # A set to test an operation against (other_set). - lambda a, b: a | b, # An operation to test. - {"1", "a", "b"}, # The expected result of operation(obj._stored.set, other_set). - {"1", "a", "b"} # The expected result of operation(other_set, obj._stored.set). - ), ( - {"a", "c"}, - lambda a, b: a - b, - {"b"}, - {"c"} - ), ( - {"a", "c"}, - lambda a, b: a & b, - {"a"}, - {"a"} - ), ( - {"a", "c", "d"}, - lambda a, b: a ^ b, - {"b", "c", "d"}, - {"b", "c", "d"} - ), ( - set(), - lambda a, b: set(a), - {"a", "b"}, - set() - )] - - class SomeObject(Object): - _stored = StoredState() - - framework = self.create_framework() - - # Validate that operations between StoredSet and built-in sets - # only result in built-in sets being returned. - # Make sure that commutativity is preserved and that the - # original sets are not changed or used as a result. - for i, (variable_operand, operation, ab_res, ba_res) in enumerate(test_operations): - obj = SomeObject(framework, str(i)) - obj._stored.set = {"a", "b"} - - for a, b, expected in [ - (obj._stored.set, variable_operand, ab_res), - (variable_operand, obj._stored.set, ba_res)]: - old_a = set(a) - old_b = set(b) - - result = operation(a, b) - self.assertEqual(result, expected) - - # Common sanity checks - self.assertIsNot(obj._stored.set._under, result) - self.assertIsNot(result, a) - self.assertIsNot(result, b) - self.assertEqual(a, old_a) - self.assertEqual(b, old_b) - - def test_set_default(self): - framework = self.create_framework() - - class StatefulObject(Object): - _stored = StoredState() - parent = StatefulObject(framework, 'key') - parent._stored.set_default(foo=1) - self.assertEqual(parent._stored.foo, 1) - parent._stored.set_default(foo=2) - # foo was already set, so it doesn't get replaced - self.assertEqual(parent._stored.foo, 1) - parent._stored.set_default(foo=3, bar=4) - self.assertEqual(parent._stored.foo, 1) - self.assertEqual(parent._stored.bar, 4) - # reloading the state still leaves things at the default values - framework.commit() - del parent - parent = StatefulObject(framework, 'key') - parent._stored.set_default(foo=5, bar=6) - self.assertEqual(parent._stored.foo, 1) - self.assertEqual(parent._stored.bar, 4) - # TODO: jam 2020-01-30 is there a clean way to tell that - # parent._stored._data.dirty is False? - - -def create_model(testcase): - """Create a Model object.""" - unit_name = 'myapp/0' - patcher = patch.dict(os.environ, {'JUJU_UNIT_NAME': unit_name}) - patcher.start() - testcase.addCleanup(patcher.stop) - - backend = model.ModelBackend() - meta = charm.CharmMeta() - test_model = model.Model('myapp/0', meta, backend) - return test_model - - -def create_framework(testcase, model=None): - """Create a Framework object.""" - framework = Framework(":memory:", charm_dir='non-existant', meta=None, model=model) - testcase.addCleanup(framework.close) - return framework - - -class GenericObserver(Object): - """Generic observer for the tests.""" - - def __init__(self, parent, key): - super().__init__(parent, key) - self.called = False - - def callback_method(self, event): - """Set the instance .called to True.""" - self.called = True - - -@patch('sys.stderr', new_callable=io.StringIO) -class BreakpointTests(unittest.TestCase): - - def test_ignored(self, fake_stderr): - # It doesn't do anything really unless proper environment is there. - with patch.dict(os.environ): - os.environ.pop('JUJU_DEBUG_AT', None) - framework = create_framework(self) - - with patch('pdb.Pdb.set_trace') as mock: - framework.breakpoint() - self.assertEqual(mock.call_count, 0) - self.assertEqual(fake_stderr.getvalue(), "") - - def test_pdb_properly_called(self, fake_stderr): - # The debugger needs to leave the user in the frame where the breakpoint is executed, - # which for the test is the frame we're calling it here in the test :). - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - - with patch('pdb.Pdb.set_trace') as mock: - this_frame = inspect.currentframe() - framework.breakpoint() - - self.assertEqual(mock.call_count, 1) - self.assertEqual(mock.call_args, ((this_frame,), {})) - - def test_welcome_message(self, fake_stderr): - # Check that an initial message is shown to the user when code is interrupted. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace'): - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_welcome_message_not_multiple(self, fake_stderr): - # Check that an initial message is NOT shown twice if the breakpoint is exercised - # twice in the same run. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace'): - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - framework.breakpoint() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_builtin_breakpoint_hooked(self, fake_stderr): - # Verify that the proper hook is set. - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'all'}): - create_framework(self) # creating the framework setups the hook - with patch('pdb.Pdb.set_trace') as mock: - # Calling through sys, not breakpoint() directly, so we can run the - # tests with Py < 3.7. - sys.breakpointhook() - self.assertEqual(mock.call_count, 1) - - def test_breakpoint_names(self, fake_stderr): - framework = create_framework(self) - - # Name rules: - # - must start and end with lowercase alphanumeric characters - # - only contain lowercase alphanumeric characters, or the hyphen "-" - good_names = [ - 'foobar', - 'foo-bar-baz', - 'foo-------bar', - 'foo123', - '778', - '77-xx', - 'a-b', - 'ab', - 'x', - ] - for name in good_names: - with self.subTest(name=name): - framework.breakpoint(name) - - bad_names = [ - '', - '.', - '-', - '...foo', - 'foo.bar', - 'bar--' - 'FOO', - 'FooBar', - 'foo bar', - 'foo_bar', - '/foobar', - 'break-here-☚', - ] - msg = 'breakpoint names must look like "foo" or "foo-bar"' - for name in bad_names: - with self.subTest(name=name): - with self.assertRaises(ValueError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), msg) - - reserved_names = [ - 'all', - 'hook', - ] - msg = 'breakpoint names "all" and "hook" are reserved' - for name in reserved_names: - with self.subTest(name=name): - with self.assertRaises(ValueError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), msg) - - not_really_names = [ - 123, - 1.1, - False, - ] - for name in not_really_names: - with self.subTest(name=name): - with self.assertRaises(TypeError) as cm: - framework.breakpoint(name) - self.assertEqual(str(cm.exception), 'breakpoint names must be strings') - - def check_trace_set(self, envvar_value, breakpoint_name, call_count): - """Helper to check the diverse combinations of situations.""" - with patch.dict(os.environ, {'JUJU_DEBUG_AT': envvar_value}): - framework = create_framework(self) - with patch('pdb.Pdb.set_trace') as mock: - framework.breakpoint(breakpoint_name) - self.assertEqual(mock.call_count, call_count) - - def test_unnamed_indicated_all(self, fake_stderr): - # If 'all' is indicated, unnamed breakpoints will always activate. - self.check_trace_set('all', None, 1) - - def test_unnamed_indicated_hook(self, fake_stderr): - # Special value 'hook' was indicated, nothing to do with any call. - self.check_trace_set('hook', None, 0) - - def test_named_indicated_specifically(self, fake_stderr): - # Some breakpoint was indicated, and the framework call used exactly that name. - self.check_trace_set('mybreak', 'mybreak', 1) - - def test_named_indicated_somethingelse(self, fake_stderr): - # Some breakpoint was indicated, but the framework call was not with that name. - self.check_trace_set('some-breakpoint', None, 0) - - def test_named_indicated_ingroup(self, fake_stderr): - # A multiple breakpoint was indicated, and the framework call used a name among those. - self.check_trace_set('some,mybreak,foobar', 'mybreak', 1) - - def test_named_indicated_all(self, fake_stderr): - # The framework indicated 'all', which includes any named breakpoint set. - self.check_trace_set('all', 'mybreak', 1) - - def test_named_indicated_hook(self, fake_stderr): - # The framework indicated the special value 'hook', nothing to do with any named call. - self.check_trace_set('hook', 'mybreak', 0) - - -class DebugHookTests(unittest.TestCase): - - def test_envvar_parsing_missing(self): - with patch.dict(os.environ): - os.environ.pop('JUJU_DEBUG_AT', None) - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ()) - - def test_envvar_parsing_empty(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': ''}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ()) - - def test_envvar_parsing_simple(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'hook'}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ['hook']) - - def test_envvar_parsing_multiple(self): - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'foo,bar,all'}): - framework = create_framework(self) - self.assertEqual(framework._juju_debug_at, ['foo', 'bar', 'all']) - - def test_basic_interruption_enabled(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO) as fake_stderr: - with patch('pdb.runcall') as mock: - publisher.install.emit() - - # Check that the pdb module was used correctly and that the callback method was NOT - # called (as we intercepted the normal pdb behaviour! this is to check that the - # framework didn't call the callback directly) - self.assertEqual(mock.call_count, 1) - expected_callback, expected_event = mock.call_args[0] - self.assertEqual(expected_callback, observer.callback_method) - self.assertIsInstance(expected_event, EventBase) - self.assertFalse(observer.called) - - # Verify proper message was given to the user. - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - - def test_actions_are_interrupted(self): - test_model = create_model(self) - framework = create_framework(self, model=test_model) - framework._juju_debug_at = ['hook'] - - class CustomEvents(ObjectEvents): - foobar_action = EventSource(charm.ActionEvent) - - publisher = CustomEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.foobar_action, observer.callback_method) - fake_script(self, 'action-get', "echo {}") - - with patch('sys.stderr', new_callable=io.StringIO): - with patch('pdb.runcall') as mock: - with patch.dict(os.environ, {'JUJU_ACTION_NAME': 'foobar'}): - publisher.foobar_action.emit() - - self.assertEqual(mock.call_count, 1) - self.assertFalse(observer.called) - - def test_internal_events_not_interrupted(self): - class MyNotifier(Object): - """Generic notifier for the tests.""" - bar = EventSource(EventBase) - - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = MyNotifier(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.bar, observer.callback_method) - - with patch('pdb.runcall') as mock: - publisher.bar.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_envvar_mixed(self): - framework = create_framework(self) - framework._juju_debug_at = ['foo', 'hook', 'all', 'whatever'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO): - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 1) - self.assertFalse(observer.called) - - def test_no_registered_method(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertFalse(observer.called) - - def test_envvar_nohook(self): - framework = create_framework(self) - framework._juju_debug_at = ['something-else'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch.dict(os.environ, {'JUJU_DEBUG_AT': 'something-else'}): - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_envvar_missing(self): - framework = create_framework(self) - framework._juju_debug_at = () - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('pdb.runcall') as mock: - publisher.install.emit() - - self.assertEqual(mock.call_count, 0) - self.assertTrue(observer.called) - - def test_welcome_message_not_multiple(self): - framework = create_framework(self) - framework._juju_debug_at = ['hook'] - - publisher = charm.CharmEvents(framework, "1") - observer = GenericObserver(framework, "1") - framework.observe(publisher.install, observer.callback_method) - - with patch('sys.stderr', new_callable=io.StringIO) as fake_stderr: - with patch('pdb.runcall') as mock: - publisher.install.emit() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - publisher.install.emit() - self.assertEqual(fake_stderr.getvalue(), _BREAKPOINT_WELCOME_MESSAGE) - self.assertEqual(mock.call_count, 2) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py deleted file mode 100644 index 131681d0..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_helpers.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2019 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 pathlib -import subprocess -import shutil -import tempfile -import unittest - - -def fake_script(test_case, name, content): - if not hasattr(test_case, 'fake_script_path'): - fake_script_path = tempfile.mkdtemp('-fake_script') - os.environ['PATH'] = '{}:{}'.format(fake_script_path, os.environ["PATH"]) - - def cleanup(): - shutil.rmtree(fake_script_path) - os.environ['PATH'] = os.environ['PATH'].replace(fake_script_path + ':', '') - - test_case.addCleanup(cleanup) - test_case.fake_script_path = pathlib.Path(fake_script_path) - - with (test_case.fake_script_path / name).open('wt') as f: - # Before executing the provided script, dump the provided arguments in calls.txt. - f.write('''#!/bin/bash -{ echo -n $(basename $0); printf ";%s" "$@"; echo; } >> $(dirname $0)/calls.txt -''' + content) - os.chmod(str(test_case.fake_script_path / name), 0o755) - - -def fake_script_calls(test_case, clear=False): - try: - with (test_case.fake_script_path / 'calls.txt').open('r+t') as f: - calls = [line.split(';') for line in f.read().splitlines()] - if clear: - f.truncate(0) - return calls - except FileNotFoundError: - return [] - - -class FakeScriptTest(unittest.TestCase): - - def test_fake_script_works(self): - fake_script(self, 'foo', 'echo foo runs') - fake_script(self, 'bar', 'echo bar runs') - output = subprocess.getoutput('foo a "b c "; bar "d e" f') - self.assertEqual(output, 'foo runs\nbar runs') - self.assertEqual(fake_script_calls(self), [ - ['foo', 'a', 'b c '], - ['bar', 'd e', 'f'], - ]) - - def test_fake_script_clear(self): - fake_script(self, 'foo', 'echo foo runs') - - output = subprocess.getoutput('foo a "b c"') - self.assertEqual(output, 'foo runs') - - self.assertEqual(fake_script_calls(self, clear=True), [['foo', 'a', 'b c']]) - - fake_script(self, 'bar', 'echo bar runs') - - output = subprocess.getoutput('bar "d e" f') - self.assertEqual(output, 'bar runs') - - self.assertEqual(fake_script_calls(self, clear=True), [['bar', 'd e', 'f']]) - - self.assertEqual(fake_script_calls(self, clear=True), []) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py deleted file mode 100644 index 9d269547..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_infra.py +++ /dev/null @@ -1,130 +0,0 @@ -# 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 io -import itertools -import os -import re -import subprocess -import sys -import tempfile -import unittest -from unittest.mock import patch - -import autopep8 -from flake8.api.legacy import get_style_guide - - -def get_python_filepaths(): - """Helper to retrieve paths of Python files.""" - python_paths = ['setup.py'] - for root in ['ops', 'test']: - for dirpath, dirnames, filenames in os.walk(root): - for filename in filenames: - if filename.endswith(".py"): - python_paths.append(os.path.join(dirpath, filename)) - return python_paths - - -class InfrastructureTests(unittest.TestCase): - - def test_pep8(self): - # verify all files are nicely styled - python_filepaths = get_python_filepaths() - style_guide = get_style_guide() - fake_stdout = io.StringIO() - with patch('sys.stdout', fake_stdout): - report = style_guide.check_files(python_filepaths) - - # if flake8 didnt' report anything, we're done - if report.total_errors == 0: - return - - # grab on which files we have issues - flake8_issues = fake_stdout.getvalue().split('\n') - broken_filepaths = {item.split(':')[0] for item in flake8_issues if item} - - # give hints to the developer on how files' style could be improved - options = autopep8.parse_args(['']) - options.aggressive = 1 - options.diff = True - options.max_line_length = 99 - - issues = [] - for filepath in broken_filepaths: - diff = autopep8.fix_file(filepath, options=options) - if diff: - issues.append(diff) - - report = ["Please fix files as suggested by autopep8:"] + issues - report += ["\n-- Original flake8 reports:"] + flake8_issues - self.fail("\n".join(report)) - - def test_quote_backslashes(self): - # ensure we're not using unneeded backslash to escape strings - issues = [] - for filepath in get_python_filepaths(): - with open(filepath, "rt", encoding="utf8") as fh: - for idx, line in enumerate(fh, 1): - if (r'\"' in line or r"\'" in line) and "NOQA" not in line: - issues.append((filepath, idx, line.rstrip())) - if issues: - msgs = ["{}:{:d}:{}".format(*issue) for issue in issues] - self.fail("Spurious backslashes found, please fix these quotings:\n" + "\n".join(msgs)) - - def test_ensure_copyright(self): - # all non-empty Python files must have a proper copyright somewhere in the first 5 lines - issues = [] - regex = re.compile(r"# Copyright \d\d\d\d(-\d\d\d\d)? Canonical Ltd.\n") - for filepath in get_python_filepaths(): - if os.stat(filepath).st_size == 0: - continue - - with open(filepath, "rt", encoding="utf8") as fh: - for line in itertools.islice(fh, 5): - if regex.match(line): - break - else: - issues.append(filepath) - if issues: - self.fail("Please add copyright headers to the following files:\n" + "\n".join(issues)) - - -class ImportersTestCase(unittest.TestCase): - - template = "from ops import {module_name}" - - def test_imports(self): - mod_names = [ - 'charm', - 'framework', - 'main', - 'model', - 'testing', - ] - - for name in mod_names: - with self.subTest(name=name): - self.check(name) - - def check(self, name): - """Helper function to run the test.""" - _, testfile = tempfile.mkstemp() - self.addCleanup(os.unlink, testfile) - - with open(testfile, 'wt', encoding='utf8') as fh: - fh.write(self.template.format(module_name=name)) - - proc = subprocess.run([sys.executable, testfile], env={'PYTHONPATH': os.getcwd()}) - self.assertEqual(proc.returncode, 0) diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py deleted file mode 100755 index d19fd600..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_jujuversion.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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 unittest - -from ops.jujuversion import JujuVersion - - -class TestJujuVersion(unittest.TestCase): - - def test_parsing(self): - test_cases = [ - ("0.0.0", 0, 0, '', 0, 0), - ("0.0.2", 0, 0, '', 2, 0), - ("0.1.0", 0, 1, '', 0, 0), - ("0.2.3", 0, 2, '', 3, 0), - ("10.234.3456", 10, 234, '', 3456, 0), - ("10.234.3456.1", 10, 234, '', 3456, 1), - ("1.21-alpha12", 1, 21, 'alpha', 12, 0), - ("1.21-alpha1.34", 1, 21, 'alpha', 1, 34), - ("2.7", 2, 7, '', 0, 0) - ] - - for vs, major, minor, tag, patch, build in test_cases: - v = JujuVersion(vs) - self.assertEqual(v.major, major) - self.assertEqual(v.minor, minor) - self.assertEqual(v.tag, tag) - self.assertEqual(v.patch, patch) - self.assertEqual(v.build, build) - - def test_parsing_errors(self): - invalid_versions = [ - "xyz", - "foo.bar", - "foo.bar.baz", - "dead.beef.ca.fe", - "1234567890.2.1", # The major version is too long. - "0.2..1", # Two periods next to each other. - "1.21.alpha1", # Tag comes after period. - "1.21-alpha", # No patch number but a tag is present. - "1.21-alpha1beta", # Non-numeric string after the patch number. - "1.21-alpha-dev", # Tag duplication. - "1.21-alpha_dev3", # Underscore in a tag. - "1.21-alpha123dev3", # Non-numeric string after the patch number. - ] - for v in invalid_versions: - with self.assertRaises(RuntimeError): - JujuVersion(v) - - def test_equality(self): - test_cases = [ - ("1.0.0", "1.0.0", True), - ("01.0.0", "1.0.0", True), - ("10.0.0", "9.0.0", False), - ("1.0.0", "1.0.1", False), - ("1.0.1", "1.0.0", False), - ("1.0.0", "1.1.0", False), - ("1.1.0", "1.0.0", False), - ("1.0.0", "2.0.0", False), - ("1.2-alpha1", "1.2.0", False), - ("1.2-alpha2", "1.2-alpha1", False), - ("1.2-alpha2.1", "1.2-alpha2", False), - ("1.2-alpha2.2", "1.2-alpha2.1", False), - ("1.2-beta1", "1.2-alpha1", False), - ("1.2-beta1", "1.2-alpha2.1", False), - ("1.2-beta1", "1.2.0", False), - ("1.2.1", "1.2.0", False), - ("2.0.0", "1.0.0", False), - ("2.0.0.0", "2.0.0", True), - ("2.0.0.0", "2.0.0.0", True), - ("2.0.0.1", "2.0.0.0", False), - ("2.0.1.10", "2.0.0.0", False), - ] - - for a, b, expected in test_cases: - self.assertEqual(JujuVersion(a) == JujuVersion(b), expected) - self.assertEqual(JujuVersion(a) == b, expected) - - def test_comparison(self): - test_cases = [ - ("1.0.0", "1.0.0", False, True), - ("01.0.0", "1.0.0", False, True), - ("10.0.0", "9.0.0", False, False), - ("1.0.0", "1.0.1", True, True), - ("1.0.1", "1.0.0", False, False), - ("1.0.0", "1.1.0", True, True), - ("1.1.0", "1.0.0", False, False), - ("1.0.0", "2.0.0", True, True), - ("1.2-alpha1", "1.2.0", True, True), - ("1.2-alpha2", "1.2-alpha1", False, False), - ("1.2-alpha2.1", "1.2-alpha2", False, False), - ("1.2-alpha2.2", "1.2-alpha2.1", False, False), - ("1.2-beta1", "1.2-alpha1", False, False), - ("1.2-beta1", "1.2-alpha2.1", False, False), - ("1.2-beta1", "1.2.0", True, True), - ("1.2.1", "1.2.0", False, False), - ("2.0.0", "1.0.0", False, False), - ("2.0.0.0", "2.0.0", False, True), - ("2.0.0.0", "2.0.0.0", False, True), - ("2.0.0.1", "2.0.0.0", False, False), - ("2.0.1.10", "2.0.0.0", False, False), - ] - - for a, b, expected_strict, expected_weak in test_cases: - self.assertEqual(JujuVersion(a) < JujuVersion(b), expected_strict) - self.assertEqual(JujuVersion(a) <= JujuVersion(b), expected_weak) - self.assertEqual(JujuVersion(b) > JujuVersion(a), expected_strict) - self.assertEqual(JujuVersion(b) >= JujuVersion(a), expected_weak) - # Implicit conversion. - self.assertEqual(JujuVersion(a) < b, expected_strict) - self.assertEqual(JujuVersion(a) <= b, expected_weak) - self.assertEqual(b > JujuVersion(a), expected_strict) - self.assertEqual(b >= JujuVersion(a), expected_weak) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py deleted file mode 100644 index b7f74d5c..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_log.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/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 io -import unittest -from unittest.mock import patch -import importlib - -import logging -import ops.log - - -class FakeModelBackend: - - def __init__(self): - self._calls = [] - - def calls(self, clear=False): - calls = self._calls - if clear: - self._calls = [] - return calls - - def juju_log(self, message, level): - self._calls.append((message, level)) - - -def reset_logging(): - logging.shutdown() - importlib.reload(logging) - - -class TestLogging(unittest.TestCase): - - def setUp(self): - self.backend = FakeModelBackend() - - reset_logging() - self.addCleanup(reset_logging) - - def test_default_logging(self): - ops.log.setup_root_logging(self.backend) - - logger = logging.getLogger() - self.assertEqual(logger.level, logging.DEBUG) - self.assertIsInstance(logger.handlers[0], ops.log.JujuLogHandler) - - test_cases = [( - lambda: logger.critical('critical'), [('CRITICAL', 'critical')] - ), ( - lambda: logger.error('error'), [('ERROR', 'error')] - ), ( - lambda: logger.warning('warning'), [('WARNING', 'warning')] - ), ( - lambda: logger.info('info'), [('INFO', 'info')] - ), ( - lambda: logger.debug('debug'), [('DEBUG', 'debug')] - )] - - for do, res in test_cases: - do() - calls = self.backend.calls(clear=True) - self.assertEqual(calls, res) - - def test_handler_filtering(self): - logger = logging.getLogger() - logger.setLevel(logging.INFO) - logger.addHandler(ops.log.JujuLogHandler(self.backend, logging.WARNING)) - logger.info('foo') - self.assertEqual(self.backend.calls(), []) - logger.warning('bar') - self.assertEqual(self.backend.calls(), [('WARNING', 'bar')]) - - def test_no_stderr_without_debug(self): - buffer = io.StringIO() - with patch('sys.stderr', buffer): - ops.log.setup_root_logging(self.backend, debug=False) - logger = logging.getLogger() - logger.debug('debug message') - logger.info('info message') - logger.warning('warning message') - logger.critical('critical message') - self.assertEqual( - self.backend.calls(), - [('DEBUG', 'debug message'), - ('INFO', 'info message'), - ('WARNING', 'warning message'), - ('CRITICAL', 'critical message'), - ]) - self.assertEqual(buffer.getvalue(), "") - - def test_debug_logging(self): - buffer = io.StringIO() - with patch('sys.stderr', buffer): - ops.log.setup_root_logging(self.backend, debug=True) - logger = logging.getLogger() - logger.debug('debug message') - logger.info('info message') - logger.warning('warning message') - logger.critical('critical message') - self.assertEqual( - self.backend.calls(), - [('DEBUG', 'debug message'), - ('INFO', 'info message'), - ('WARNING', 'warning message'), - ('CRITICAL', 'critical message'), - ]) - self.assertRegex( - buffer.getvalue(), - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d DEBUG debug message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d INFO info message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d WARNING warning message\n" - r"\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d,\d\d\d CRITICAL critical message\n" - ) - - def test_reduced_logging(self): - ops.log.setup_root_logging(self.backend) - logger = logging.getLogger() - logger.setLevel(logging.WARNING) - logger.debug('debug') - logger.info('info') - logger.warning('warning') - self.assertEqual(self.backend.calls(), [('WARNING', 'warning')]) - - -if __name__ == '__main__': - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py deleted file mode 100755 index 0703b88a..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_main.py +++ /dev/null @@ -1,675 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2019 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 abc -import base64 -import logging -import os -import pickle -import shutil -import subprocess -import sys -import tempfile -import unittest -import importlib.util -from pathlib import Path - -from ops.charm import ( - CharmBase, - CharmEvents, - HookEvent, - InstallEvent, - StartEvent, - ConfigChangedEvent, - UpgradeCharmEvent, - UpdateStatusEvent, - LeaderSettingsChangedEvent, - RelationJoinedEvent, - RelationChangedEvent, - RelationDepartedEvent, - RelationBrokenEvent, - RelationEvent, - StorageAttachedEvent, - ActionEvent, - CollectMetricsEvent, -) - -from .test_helpers import fake_script, fake_script_calls - -# This relies on the expected repository structure to find a path to -# source of the charm under test. -TEST_CHARM_DIR = Path(__file__ + '/../charms/test_main').resolve() - -logger = logging.getLogger(__name__) - - -class SymlinkTargetError(Exception): - pass - - -class EventSpec: - def __init__(self, event_type, event_name, env_var=None, - relation_id=None, remote_app=None, remote_unit=None, - charm_config=None): - self.event_type = event_type - self.event_name = event_name - self.env_var = env_var - self.relation_id = relation_id - self.remote_app = remote_app - self.remote_unit = remote_unit - self.charm_config = charm_config - - -class TestMain(abc.ABC): - - @abc.abstractmethod - def _setup_entry_point(self, directory, entry_point): - """Set up the given entry point in the given directory. - - If not using dispatch, that would be a symlink / - pointing at src/charm.py; if using dispatch that would be the dispatch - symlink. It could also not be a symlink... - """ - return NotImplemented - - @abc.abstractmethod - def _call_event(self, rel_path, env): - """Set up the environment and call (i.e. run) the given event.""" - return NotImplemented - - @abc.abstractmethod - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events. - - Depending on the combination of dispatch and non-dispatch, this should - be checking for the creation or the _lack_ of creation, as appropriate. - """ - return NotImplemented - - def setUp(self): - self._setup_charm_dir() - - _, tmp_file = tempfile.mkstemp() - self._state_file = Path(tmp_file) - self.addCleanup(self._state_file.unlink) - - # Relations events are defined dynamically and modify the class attributes. - # We use a subclass temporarily to prevent these side effects from leaking. - class TestCharmEvents(CharmEvents): - pass - CharmBase.on = TestCharmEvents() - - def cleanup(): - shutil.rmtree(str(self.JUJU_CHARM_DIR)) - CharmBase.on = CharmEvents() - self.addCleanup(cleanup) - - fake_script(self, 'juju-log', "exit 0") - - # set to something other than None for tests that care - self.stdout = None - self.stderr = None - - def _setup_charm_dir(self): - self.JUJU_CHARM_DIR = Path(tempfile.mkdtemp()) / 'test_main' - self.hooks_dir = self.JUJU_CHARM_DIR / 'hooks' - charm_path = str(self.JUJU_CHARM_DIR / 'src/charm.py') - self.charm_exec_path = os.path.relpath(charm_path, - str(self.hooks_dir)) - shutil.copytree(str(TEST_CHARM_DIR), str(self.JUJU_CHARM_DIR)) - - charm_spec = importlib.util.spec_from_file_location("charm", charm_path) - self.charm_module = importlib.util.module_from_spec(charm_spec) - charm_spec.loader.exec_module(self.charm_module) - - self._prepare_initial_hooks() - - def _prepare_initial_hooks(self): - initial_hooks = ('install', 'start', 'upgrade-charm', 'disks-storage-attached') - self.hooks_dir.mkdir() - for hook in initial_hooks: - self._setup_entry_point(self.hooks_dir, hook) - - def _prepare_actions(self): - actions_meta = ''' -foo-bar: - description: Foos the bar. - title: foo-bar - params: - foo-name: - type: string - description: A foo name to bar. - silent: - type: boolean - description: - default: false - required: - - foo-name -start: - description: Start the unit.''' - actions_dir_name = 'actions' - actions_meta_file = 'actions.yaml' - - with (self.JUJU_CHARM_DIR / actions_meta_file).open('w+t') as f: - f.write(actions_meta) - actions_dir = self.JUJU_CHARM_DIR / actions_dir_name - actions_dir.mkdir() - for action_name in ('start', 'foo-bar'): - self._setup_entry_point(actions_dir, action_name) - - def _read_and_clear_state(self): - state = None - if self._state_file.stat().st_size: - with self._state_file.open('r+b') as state_file: - state = pickle.load(state_file) - state_file.truncate(0) - return state - - def _simulate_event(self, event_spec): - env = { - 'PATH': "{}:{}".format(Path(__file__).parent / 'bin', os.environ['PATH']), - 'JUJU_CHARM_DIR': str(self.JUJU_CHARM_DIR), - 'JUJU_UNIT_NAME': 'test_main/0', - 'CHARM_CONFIG': event_spec.charm_config, - } - if issubclass(event_spec.event_type, RelationEvent): - rel_name = event_spec.event_name.split('_')[0] - env.update({ - 'JUJU_RELATION': rel_name, - 'JUJU_RELATION_ID': str(event_spec.relation_id), - }) - remote_app = event_spec.remote_app - # For juju < 2.7 app name is extracted from JUJU_REMOTE_UNIT. - if remote_app is not None: - env['JUJU_REMOTE_APP'] = remote_app - - remote_unit = event_spec.remote_unit - if remote_unit is None: - remote_unit = '' - - env['JUJU_REMOTE_UNIT'] = remote_unit - else: - env.update({ - 'JUJU_REMOTE_UNIT': '', - 'JUJU_REMOTE_APP': '', - }) - if issubclass(event_spec.event_type, ActionEvent): - event_filename = event_spec.event_name[:-len('_action')].replace('_', '-') - env.update({ - event_spec.env_var: event_filename, - }) - if event_spec.env_var == 'JUJU_ACTION_NAME': - event_dir = 'actions' - else: - raise RuntimeError('invalid envar name specified for a action event') - else: - event_filename = event_spec.event_name.replace('_', '-') - event_dir = 'hooks' - - self._call_event(Path(event_dir, event_filename), env) - return self._read_and_clear_state() - - def test_event_reemitted(self): - # base64 encoding is used to avoid null bytes. - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - # First run "install" to make sure all hooks are set up. - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - state = self._simulate_event(EventSpec(ConfigChangedEvent, 'config-changed', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent]) - - # Re-emit should pick the deferred config-changed. - state = self._simulate_event(EventSpec(UpdateStatusEvent, 'update-status', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent, UpdateStatusEvent]) - - def test_no_reemission_on_collect_metrics(self): - # base64 encoding is used to avoid null bytes. - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - fake_script(self, 'add-metric', 'exit 0') - - # First run "install" to make sure all hooks are set up. - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - state = self._simulate_event(EventSpec(ConfigChangedEvent, 'config-changed', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [ConfigChangedEvent]) - - # Re-emit should not pick the deferred config-changed because - # collect-metrics runs in a restricted context. - state = self._simulate_event(EventSpec(CollectMetricsEvent, 'collect-metrics', - charm_config=charm_config)) - self.assertEqual(state['observed_event_types'], [CollectMetricsEvent]) - - def test_multiple_events_handled(self): - self._prepare_actions() - - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - actions_charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'USE_ACTIONS': True, - })) - - fake_script(self, 'action-get', "echo '{}'") - - # Sample events with a different amount of dashes used - # and with endpoints from different sections of metadata.yaml - events_under_test = [( - EventSpec(InstallEvent, 'install', - charm_config=charm_config), - {}, - ), ( - EventSpec(StartEvent, 'start', - charm_config=charm_config), - {}, - ), ( - EventSpec(UpdateStatusEvent, 'update_status', - charm_config=charm_config), - {}, - ), ( - EventSpec(LeaderSettingsChangedEvent, 'leader_settings_changed', - charm_config=charm_config), - {}, - ), ( - EventSpec(RelationJoinedEvent, 'db_relation_joined', - relation_id=1, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'db', - 'relation_id': 1, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_app='remote', remote_unit=None, - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': None}, - ), ( - EventSpec(RelationDepartedEvent, 'mon_relation_departed', - relation_id=2, - remote_app='remote', remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationBrokenEvent, 'ha_relation_broken', - relation_id=3, - charm_config=charm_config), - {'relation_name': 'ha', - 'relation_id': 3}, - ), ( - # Events without a remote app specified (for Juju < 2.7). - EventSpec(RelationJoinedEvent, 'db_relation_joined', - relation_id=1, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'db', - 'relation_id': 1, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationChangedEvent, 'mon_relation_changed', - relation_id=2, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(RelationDepartedEvent, 'mon_relation_departed', - relation_id=2, - remote_unit='remote/0', - charm_config=charm_config), - {'relation_name': 'mon', - 'relation_id': 2, - 'app_name': 'remote', - 'unit_name': 'remote/0'}, - ), ( - EventSpec(ActionEvent, 'start_action', - env_var='JUJU_ACTION_NAME', - charm_config=actions_charm_config), - {}, - ), ( - EventSpec(ActionEvent, 'foo_bar_action', - env_var='JUJU_ACTION_NAME', - charm_config=actions_charm_config), - {}, - )] - - logger.debug('Expected events %s', events_under_test) - - # First run "install" to make sure all hooks are set up. - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - - # Simulate hook executions for every event. - for event_spec, expected_event_data in events_under_test: - state = self._simulate_event(event_spec) - - state_key = 'on_' + event_spec.event_name - handled_events = state.get(state_key, []) - - # Make sure that a handler for that event was called once. - self.assertEqual(len(handled_events), 1) - # Make sure the event handled by the Charm has the right type. - handled_event_type = handled_events[0] - self.assertEqual(handled_event_type, event_spec.event_type) - - self.assertEqual(state['observed_event_types'], [event_spec.event_type]) - - if event_spec.event_name in expected_event_data: - self.assertEqual(state[event_spec.event_name + '_data'], - expected_event_data[event_spec.event_name]) - - def test_event_not_implemented(self): - """Make sure events without implementation do not cause non-zero exit. - """ - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - # Simulate a scenario where there is a symlink for an event that - # a charm does not know how to handle. - hook_path = self.JUJU_CHARM_DIR / 'hooks/not-implemented-event' - # This will be cleared up in tearDown. - hook_path.symlink_to('install') - - try: - self._simulate_event(EventSpec(HookEvent, 'not-implemented-event', - charm_config=charm_config)) - except subprocess.CalledProcessError: - self.fail('Event simulation for an unsupported event' - ' results in a non-zero exit code returned') - - def test_collect_metrics(self): - indicator_file = self.JUJU_CHARM_DIR / 'indicator' - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'INDICATOR_FILE': indicator_file - })) - fake_script(self, 'add-metric', 'exit 0') - fake_script(self, 'juju-log', 'exit 0') - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - # Clear the calls during 'install' - fake_script_calls(self, clear=True) - self._simulate_event(EventSpec(CollectMetricsEvent, 'collect_metrics', - charm_config=charm_config)) - self.assertEqual( - fake_script_calls(self), - [['juju-log', '--log-level', 'DEBUG', 'Emitting Juju event collect_metrics'], - ['add-metric', '--labels', 'bar=4.2', 'foo=42']]) - - def test_logger(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - 'USE_LOG_ACTIONS': True, - })) - fake_script(self, 'action-get', "echo '{}'") - actions_yaml = self.JUJU_CHARM_DIR / 'actions.yaml' - actions_yaml.write_text( - ''' -log_critical: {} -log_error: {} -log_warning: {} -log_info: {} -log_debug: {} - ''') - - test_cases = [( - EventSpec(ActionEvent, 'log_critical_action', env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'CRITICAL', 'super critical'], - ), ( - EventSpec(ActionEvent, 'log_error_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'ERROR', 'grave error'], - ), ( - EventSpec(ActionEvent, 'log_warning_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'WARNING', 'wise warning'], - ), ( - EventSpec(ActionEvent, 'log_info_action', - env_var='JUJU_ACTION_NAME', - charm_config=charm_config), - ['juju-log', '--log-level', 'INFO', 'useful info'], - )] - - # Set up action symlinks. - self._simulate_event(EventSpec(InstallEvent, 'install', - charm_config=charm_config)) - - for event_spec, calls in test_cases: - self._simulate_event(event_spec) - self.assertIn(calls, fake_script_calls(self, clear=True)) - - -class TestMainWithNoDispatch(TestMain, unittest.TestCase): - def _setup_entry_point(self, directory, entry_point): - path = directory / entry_point - path.symlink_to(self.charm_exec_path) - - def _call_event(self, rel_path, env): - event_file = self.JUJU_CHARM_DIR / rel_path - # Note that sys.executable is used to make sure we are using the same - # interpreter for the child process to support virtual environments. - subprocess.run( - [sys.executable, str(event_file)], - check=True, env=env, cwd=str(self.JUJU_CHARM_DIR)) - - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events. - """ - all_event_hooks = ['hooks/' + e.replace("_", "-") - for e in self.charm_module.Charm.on.events().keys()] - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - initial_events = { - EventSpec(InstallEvent, 'install', charm_config=charm_config), - EventSpec(StorageAttachedEvent, 'disks-storage-attached', charm_config=charm_config), - EventSpec(StartEvent, 'start', charm_config=charm_config), - EventSpec(UpgradeCharmEvent, 'upgrade-charm', charm_config=charm_config), - } - - def _assess_event_links(event_spec): - self.assertTrue(self.hooks_dir / event_spec.event_name in self.hooks_dir.iterdir()) - for event_hook in all_event_hooks: - self.assertTrue((self.JUJU_CHARM_DIR / event_hook).exists(), - 'Missing hook: ' + event_hook) - self.assertEqual(os.readlink(str(self.JUJU_CHARM_DIR / event_hook)), - self.charm_exec_path) - - for initial_event in initial_events: - self._setup_charm_dir() - - self._simulate_event(initial_event) - _assess_event_links(initial_event) - # Make sure it is idempotent. - self._simulate_event(initial_event) - _assess_event_links(initial_event) - - def test_setup_action_links(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - actions_yaml = self.JUJU_CHARM_DIR / 'actions.yaml' - actions_yaml.write_text('test: {}') - self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - action_hook = self.JUJU_CHARM_DIR / 'actions' / 'test' - self.assertTrue(action_hook.exists()) - - -class TestMainWithDispatch(TestMain, unittest.TestCase): - def _setup_entry_point(self, directory, entry_point): - path = self.JUJU_CHARM_DIR / 'dispatch' - if not path.exists(): - path.symlink_to('src/charm.py') - - def _call_event(self, rel_path, env): - env["JUJU_DISPATCH_PATH"] = str(rel_path) - dispatch = self.JUJU_CHARM_DIR / 'dispatch' - subprocess.run( - [sys.executable, str(dispatch)], - stdout=self.stdout, - stderr=self.stderr, - check=True, env=env, cwd=str(self.JUJU_CHARM_DIR)) - - def test_setup_event_links(self): - """Test auto-creation of symlinks caused by initial events does _not_ happen when using dispatch. - """ - all_event_hooks = ['hooks/' + e.replace("_", "-") - for e in self.charm_module.Charm.on.events().keys()] - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - initial_events = { - EventSpec(InstallEvent, 'install', charm_config=charm_config), - EventSpec(StorageAttachedEvent, 'disks-storage-attached', charm_config=charm_config), - EventSpec(StartEvent, 'start', charm_config=charm_config), - EventSpec(UpgradeCharmEvent, 'upgrade-charm', charm_config=charm_config), - } - - def _assess_event_links(event_spec): - self.assertNotIn(self.hooks_dir / event_spec.event_name, self.hooks_dir.iterdir()) - for event_hook in all_event_hooks: - self.assertFalse((self.JUJU_CHARM_DIR / event_hook).exists(), - 'Spurious hook: ' + event_hook) - - for initial_event in initial_events: - self._setup_charm_dir() - - self._simulate_event(initial_event) - _assess_event_links(initial_event) - - def test_hook_and_dispatch(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - self.fake_script_path = self.hooks_dir - fake_script(self, 'install', 'exit 0') - state = self._simulate_event(EventSpec(InstallEvent, 'install', charm_config=charm_config)) - - # the script was called, *and*, the .on. was called - self.assertEqual(fake_script_calls(self), [['install', '']]) - self.assertEqual(state['observed_event_types'], [InstallEvent]) - - def test_hook_and_dispatch_with_failing_hook(self): - self.stdout = self.stderr = tempfile.TemporaryFile() - self.addCleanup(self.stdout.close) - - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - - old_path = self.fake_script_path - self.fake_script_path = self.hooks_dir - fake_script(self, 'install', 'exit 42') - event = EventSpec(InstallEvent, 'install', charm_config=charm_config) - with self.assertRaises(subprocess.CalledProcessError): - self._simulate_event(event) - self.fake_script_path = old_path - - self.stdout.seek(0) - self.assertEqual(self.stdout.read(), b'') - calls = fake_script_calls(self) - self.assertEqual(len(calls), 1, 'unexpect call result: {}'.format(calls)) - self.assertEqual(len(calls[0]), 4, 'unexpect call result: {}'.format(calls[0])) - self.assertEqual( - calls[0][:3], - ['juju-log', '--log-level', 'WARNING'] - ) - self.assertRegex(calls[0][3], r'hook /\S+/install exited with status 42') - - def test_hook_and_dispatch_but_hook_is_dispatch(self): - charm_config = base64.b64encode(pickle.dumps({ - 'STATE_FILE': self._state_file, - })) - event = EventSpec(InstallEvent, 'install', charm_config=charm_config) - hook_path = self.hooks_dir / 'install' - for ((rel, ind), path) in { - # relative and indirect - (True, True): Path('../dispatch'), - # relative and direct - (True, False): Path(self.charm_exec_path), - # absolute and direct - (False, False): (self.hooks_dir / self.charm_exec_path).resolve(), - # absolute and indirect - (False, True): self.JUJU_CHARM_DIR / 'dispatch', - }.items(): - with self.subTest(path=path, rel=rel, ind=ind): - # sanity check - self.assertEqual(path.is_absolute(), not rel) - self.assertEqual(path.name == 'dispatch', ind) - try: - hook_path.symlink_to(path) - - state = self._simulate_event(event) - - # the .on. was only called once - self.assertEqual(state['observed_event_types'], [InstallEvent]) - self.assertEqual(state['on_install'], [InstallEvent]) - finally: - hook_path.unlink() - - -# TODO: this does not work -# class TestMainWithDispatchAsScript(TestMainWithDispatch): -# """Here dispatch is a script that execs the charm.py instead of a symlink. -# """ -# def _setup_entry_point(self, directory, entry_point): -# path = self.JUJU_CHARM_DIR / 'dispatch' -# if not path.exists(): -# path.write_text('#!/bin/sh\nexec "{}" "{}"\n'.format( -# sys.executable, -# self.JUJU_CHARM_DIR / 'src/charm.py')) -# path.chmod(0o755) - -# def _call_event(self, rel_path, env): -# env["JUJU_DISPATCH_PATH"] = str(rel_path) -# dispatch = self.JUJU_CHARM_DIR / 'dispatch' -# subprocess.check_call([str(dispatch)], -# env=env, cwd=str(self.JUJU_CHARM_DIR)) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py deleted file mode 100755 index 660176a4..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_model.py +++ /dev/null @@ -1,1288 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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 pathlib -import unittest -import json -import ipaddress -from collections import OrderedDict - -import ops.model -import ops.charm -from ops.charm import RelationMeta - -from test.test_helpers import fake_script, fake_script_calls - - -class TestModel(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.model = ops.model.Model('myapp/0', meta, self.backend) - fake_script(self, 'relation-ids', """([ "$1" = db0 ] && echo '["db0:4"]') || echo '[]'""") - - def test_model(self): - self.assertIs(self.model.app, self.model.unit.app) - - def test_relations_keys(self): - fake_script(self, 'relation-ids', - """[ "$1" = db2 ] && echo '["db2:5", "db2:6"]' || echo '[]'""") - fake_script(self, 'relation-list', - """ -case "$2" in - 5) - echo '["remoteapp1/0", "remoteapp1/1"]' - ;; - 6) - echo '["remoteapp2/0"]' - ;; - *) - exit 2 - ;; -esac -""") - - for relation in self.model.relations['db2']: - self.assertIn(self.model.unit, relation.data) - unit_from_rel = next(filter(lambda u: u.name == 'myapp/0', relation.data.keys())) - self.assertIs(self.model.unit, unit_from_rel) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-list', '-r', '6', '--format=json'] - ]) - - def test_get_relation(self): - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - - fake_script(self, 'relation-ids', ''' - case "$1" in - db1) - echo '["db1:4"]' - ;; - db2) - echo '["db2:5", "db2:6"]' - ;; - *) - echo '[]' - ;; - esac - ''') - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0"]' - else - echo {} >&2 - exit 2 - fi - '''.format(err_msg)) - fake_script(self, 'relation-get', - """echo {} >&2 ; exit 2""".format(err_msg)) - - with self.assertRaises(ops.model.ModelError): - self.model.get_relation('db1', 'db1:4') - db1_4 = self.model.get_relation('db1', 4) - self.assertIsInstance(db1_4, ops.model.Relation) - dead_rel = self.model.get_relation('db1', 7) - self.assertIsInstance(dead_rel, ops.model.Relation) - self.assertEqual(set(dead_rel.data.keys()), {self.model.unit, self.model.unit.app}) - self.assertEqual(dead_rel.data[self.model.unit], {}) - self.assertIsNone(self.model.get_relation('db0')) - self.assertIs(self.model.get_relation('db1'), db1_4) - with self.assertRaises(ops.model.TooManyRelatedAppsError): - self.model.get_relation('db2') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-list', '-r', '7', '--format=json'], - ['relation-get', '-r', '7', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-ids', 'db0', '--format=json'], - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-list', '-r', '6', '--format=json'] - ]) - - def test_peer_relation_app(self): - meta = ops.charm.CharmMeta() - meta.relations = {'dbpeer': RelationMeta('peers', 'dbpeer', - {'interface': 'dbpeer', 'scope': 'global'})} - self.model = ops.model.Model('myapp/0', meta, self.backend) - - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - fake_script(self, 'relation-ids', - '''([ "$1" = dbpeer ] && echo '["dbpeer:0"]') || echo "[]"''') - fake_script(self, 'relation-list', - '''([ "$2" = 0 ] && echo "[]") || (echo {} >&2 ; exit 2)'''.format(err_msg)) - - db1_4 = self.model.get_relation('dbpeer') - self.assertIs(db1_4.app, self.model.app) - - def test_remote_units_is_our(self): - fake_script(self, 'relation-ids', - """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""") - - for u in self.model.get_relation('db1').units: - self.assertFalse(u._is_our_unit) - self.assertFalse(u.app._is_our_app) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'] - ]) - - def test_our_unit_is_our(self): - self.assertTrue(self.model.unit._is_our_unit) - self.assertTrue(self.model.unit.app._is_our_app) - - def test_unit_relation_data(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', """ -if [ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]; then - echo '{"host": "remoteapp1-0"}' -else - exit 2 -fi -""") - - random_unit = self.model._cache.get(ops.model.Unit, 'randomunit/0') - with self.assertRaises(KeyError): - self.model.get_relation('db1').data[random_unit] - remoteapp1_0 = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - self.assertEqual(self.model.get_relation('db1').data[remoteapp1_0], - {'host': 'remoteapp1-0'}) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json'] - ]) - - def test_remote_app_relation_data(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = remoteapp1 ]; then - echo '{"secret": "cafedeadbeef"}' - else - exit 2 - fi - ''') - - # Try to get relation data for an invalid remote application. - random_app = self.model._cache.get(ops.model.Application, 'randomapp') - with self.assertRaises(KeyError): - self.model.get_relation('db1').data[random_app] - - remoteapp1 = self.model.get_relation('db1').app - self.assertEqual(self.model.get_relation('db1').data[remoteapp1], - {'secret': 'cafedeadbeef'}) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1', '--app=True', '--format=json'], - ]) - - def test_relation_data_modify_remote(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', """ -if [ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]; then - echo '{"host": "remoteapp1-0"}' -else - exit 2 -fi -""") - - rel_db1 = self.model.get_relation('db1') - remoteapp1_0 = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[remoteapp1_0]) - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[remoteapp1_0]['foo'] = 'bar' - self.assertNotIn('foo', rel_db1.data[remoteapp1_0]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json'] - ]) - - def test_relation_data_modify_our(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-set', '''[ "$2" = 4 ] && exit 0 || exit 2''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "bar"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[self.model.unit]) - rel_db1.data[self.model.unit]['host'] = 'bar' - self.assertEqual(rel_db1.data[self.model.unit]['host'], 'bar') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '4', 'host=bar', '--app=False'] - ]) - - def test_app_relation_data_modify_local_as_leader(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = myapp ]; then - echo '{"password": "deadbeefcafe"}' - else - exit 2 - fi - ''') - fake_script(self, 'relation-set', """[ "$2" = 4 ] && exit 0 || exit 2""") - fake_script(self, 'is-leader', 'echo true') - - local_app = self.model.unit.app - - rel_db1 = self.model.get_relation('db1') - self.assertEqual(rel_db1.data[local_app], {'password': 'deadbeefcafe'}) - - rel_db1.data[local_app]['password'] = 'foo' - - self.assertEqual(rel_db1.data[local_app]['password'], 'foo') - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp', '--app=True', '--format=json'], - ['is-leader', '--format=json'], - ['relation-set', '-r', '4', 'password=foo', '--app=True'], - ]) - - def test_app_relation_data_modify_local_as_minion(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = myapp ]; then - echo '{"password": "deadbeefcafe"}' - else - exit 2 - fi - ''') - fake_script(self, 'is-leader', 'echo false') - - local_app = self.model.unit.app - - rel_db1 = self.model.get_relation('db1') - self.assertEqual(rel_db1.data[local_app], {'password': 'deadbeefcafe'}) - - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[local_app]['password'] = 'foobar' - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp', '--app=True', '--format=json'], - ['is-leader', '--format=json'], - ]) - - def test_relation_data_del_key(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-set', '''[ "$2" = 4 ] && exit 0 || exit 2''') - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "bar"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - # Force memory cache to be loaded. - self.assertIn('host', rel_db1.data[self.model.unit]) - del rel_db1.data[self.model.unit]['host'] - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{}' - else - exit 2 - fi - ''') - self.assertNotIn('host', rel_db1.data[self.model.unit]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['relation-get', '-r', '4', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '4', 'host=', '--app=False'] - ]) - - def test_relation_set_fail(self): - fake_script(self, 'relation-ids', """[ "$1" = db2 ] && echo '["db2:5"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 5 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', ''' - if [ "$2" = 5 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "myapp-0"}' - else - exit 2 - fi - ''') - fake_script(self, 'relation-set', 'exit 2') - - rel_db2 = self.model.relations['db2'][0] - # Force memory cache to be loaded. - self.assertIn('host', rel_db2.data[self.model.unit]) - with self.assertRaises(ops.model.ModelError): - rel_db2.data[self.model.unit]['host'] = 'bar' - self.assertEqual(rel_db2.data[self.model.unit]['host'], 'myapp-0') - with self.assertRaises(ops.model.ModelError): - del rel_db2.data[self.model.unit]['host'] - self.assertIn('host', rel_db2.data[self.model.unit]) - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db2', '--format=json'], - ['relation-list', '-r', '5', '--format=json'], - ['relation-get', '-r', '5', '-', 'myapp/0', '--app=False', '--format=json'], - ['relation-set', '-r', '5', 'host=bar', '--app=False'], - ['relation-set', '-r', '5', 'host=', '--app=False'] - ]) - - def test_relation_get_set_is_app_arg(self): - self.backend = ops.model.ModelBackend() - - # No is_app provided. - with self.assertRaises(TypeError): - self.backend.relation_set(1, 'fookey', 'barval') - - with self.assertRaises(TypeError): - self.backend.relation_get(1, 'fooentity') - - # Invalid types for is_app. - for is_app_v in [None, 1, 2.0, 'a', b'beef']: - with self.assertRaises(TypeError): - self.backend.relation_set(1, 'fookey', 'barval', is_app=is_app_v) - - with self.assertRaises(TypeError): - self.backend.relation_get(1, 'fooentity', is_app=is_app_v) - - def test_relation_data_type_check(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - fake_script(self, 'relation-get', ''' - if [ "$2" = 4 ] && [ "$4" = "myapp/0" ]; then - echo '{"host": "myapp-0"}' - else - exit 2 - fi - ''') - - rel_db1 = self.model.get_relation('db1') - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = 1 - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = {'foo': 'bar'} - with self.assertRaises(ops.model.RelationDataError): - rel_db1.data[self.model.unit]['foo'] = None - - self.assertEqual(fake_script_calls(self), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'] - ]) - - def test_config(self): - fake_script(self, 'config-get', """echo '{"foo":"foo","bar":1,"qux":true}'""") - self.assertEqual(self.model.config, { - 'foo': 'foo', - 'bar': 1, - 'qux': True, - }) - with self.assertRaises(TypeError): - # Confirm that we cannot modify config values. - self.model.config['foo'] = 'bar' - - self.assertEqual(fake_script_calls(self), [['config-get', '--format=json']]) - - def test_is_leader(self): - def check_remote_units(): - fake_script(self, 'relation-ids', - """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - - fake_script(self, 'relation-list', - """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""") - - # Cannot determine leadership for remote units. - for u in self.model.get_relation('db1').units: - with self.assertRaises(RuntimeError): - u.is_leader() - - fake_script(self, 'is-leader', 'echo true') - self.assertTrue(self.model.unit.is_leader()) - - check_remote_units() - - # Create a new model and backend to drop a cached is-leader output. - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'is-leader', 'echo false') - self.assertFalse(self.model.unit.is_leader()) - - check_remote_units() - - self.assertEqual(fake_script_calls(self), [ - ['is-leader', '--format=json'], - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ['is-leader', '--format=json'], - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ]) - - def test_is_leader_refresh(self): - fake_script(self, 'is-leader', 'echo false') - self.assertFalse(self.model.unit.is_leader()) - - # Change the leadership status and force a recheck. - fake_script(self, 'is-leader', 'echo true') - self.backend._leader_check_time = None - self.assertTrue(self.model.unit.is_leader()) - - # Force a recheck without changing the leadership status. - fake_script(self, 'is-leader', 'echo true') - self.backend._leader_check_time = None - self.assertTrue(self.model.unit.is_leader()) - - def test_workload_version(self): - fake_script(self, 'application-version-set', 'exit 0') - self.model.unit.set_workload_version('1.2.3') - self.assertEqual(fake_script_calls(self), [['application-version-set', '--', '1.2.3']]) - - def test_workload_version_invalid(self): - fake_script(self, 'application-version-set', 'exit 0') - with self.assertRaises(TypeError) as cm: - self.model.unit.set_workload_version(5) - self.assertEqual(str(cm.exception), "workload version must be a str, not int: 5") - self.assertEqual(fake_script_calls(self), []) - - def test_resources(self): - meta = ops.charm.CharmMeta() - meta.resources = {'foo': None, 'bar': None} - model = ops.model.Model('myapp/0', meta, self.backend) - - with self.assertRaises(RuntimeError): - model.resources.fetch('qux') - - fake_script(self, 'resource-get', 'exit 1') - with self.assertRaises(ops.model.ModelError): - model.resources.fetch('foo') - - fake_script(self, 'resource-get', - 'echo /var/lib/juju/agents/unit-test-0/resources/$1/$1.tgz') - self.assertEqual(model.resources.fetch('foo').name, 'foo.tgz') - self.assertEqual(model.resources.fetch('bar').name, 'bar.tgz') - - def test_pod_spec(self): - fake_script(self, 'pod-spec-set', """ - cat $2 > $(dirname $0)/spec.json - [[ -n $4 ]] && cat $4 > $(dirname $0)/k8s_res.json || true - """) - fake_script(self, 'is-leader', 'echo true') - spec_path = self.fake_script_path / 'spec.json' - k8s_res_path = self.fake_script_path / 'k8s_res.json' - - def check_calls(calls): - # There may 1 or 2 calls because of is-leader. - self.assertLessEqual(len(fake_calls), 2) - pod_spec_call = next(filter(lambda c: c[0] == 'pod-spec-set', calls)) - self.assertEqual(pod_spec_call[:2], ['pod-spec-set', '--file']) - - # 8 bytes are used as of python 3.4.0, see Python bug #12015. - # Other characters are from POSIX 3.282 (Portable Filename - # Character Set) a subset of which Python's mkdtemp uses. - self.assertRegex(pod_spec_call[2], '.*/tmp[A-Za-z0-9._-]{8}-pod-spec-set') - - self.model.pod.set_spec({'foo': 'bar'}) - self.assertEqual(spec_path.read_text(), '{"foo": "bar"}') - self.assertFalse(k8s_res_path.exists()) - - fake_calls = fake_script_calls(self, clear=True) - check_calls(fake_calls) - - self.model.pod.set_spec({'bar': 'foo'}, {'qux': 'baz'}) - self.assertEqual(spec_path.read_text(), '{"bar": "foo"}') - self.assertEqual(k8s_res_path.read_text(), '{"qux": "baz"}') - - fake_calls = fake_script_calls(self, clear=True) - check_calls(fake_calls) - - # Create a new model to drop is-leader caching result. - self.backend = ops.model.ModelBackend() - meta = ops.charm.CharmMeta() - self.model = ops.model.Model('myapp/0', meta, self.backend) - fake_script(self, 'is-leader', 'echo false') - with self.assertRaises(ops.model.ModelError): - self.model.pod.set_spec({'foo': 'bar'}) - - def test_base_status_instance_raises(self): - with self.assertRaises(TypeError): - ops.model.StatusBase('test') - - def test_active_message_default(self): - self.assertEqual(ops.model.ActiveStatus().message, '') - - def test_local_set_valid_unit_status(self): - test_cases = [( - ops.model.ActiveStatus('Green'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'active', 'Green']]), - ), ( - ops.model.MaintenanceStatus('Yellow'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual( - fake_script_calls(self, True), - [['status-set', '--application=False', 'maintenance', 'Yellow']]), - ), ( - ops.model.BlockedStatus('Red'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'blocked', 'Red']]), - ), ( - ops.model.WaitingStatus('White'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertEqual(fake_script_calls(self, True), - [['status-set', '--application=False', 'waiting', 'White']]), - )] - - for target_status, setup_tools, check_tool_calls in test_cases: - setup_tools() - - self.model.unit.status = target_status - - self.assertEqual(self.model.unit.status, target_status) - - check_tool_calls() - - def test_local_set_valid_app_status(self): - fake_script(self, 'is-leader', 'echo true') - test_cases = [( - ops.model.ActiveStatus('Green'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'active', 'Green'], - fake_script_calls(self, True)), - ), ( - ops.model.MaintenanceStatus('Yellow'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'maintenance', 'Yellow'], - fake_script_calls(self, True)), - ), ( - ops.model.BlockedStatus('Red'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'blocked', 'Red'], - fake_script_calls(self, True)), - ), ( - ops.model.WaitingStatus('White'), - lambda: fake_script(self, 'status-set', 'exit 0'), - lambda: self.assertIn(['status-set', '--application=True', 'waiting', 'White'], - fake_script_calls(self, True)), - )] - - for target_status, setup_tools, check_tool_calls in test_cases: - setup_tools() - - self.model.app.status = target_status - - self.assertEqual(self.model.app.status, target_status) - - check_tool_calls() - - def test_set_app_status_non_leader_raises(self): - fake_script(self, 'is-leader', 'echo false') - - with self.assertRaises(RuntimeError): - self.model.app.status - - with self.assertRaises(RuntimeError): - self.model.app.status = ops.model.ActiveStatus() - - def test_local_set_invalid_status(self): - fake_script(self, 'status-set', 'exit 1') - fake_script(self, 'is-leader', 'echo true') - - with self.assertRaises(ops.model.ModelError): - self.model.unit.status = ops.model.UnknownStatus() - - self.assertEqual(fake_script_calls(self, True), [ - ['status-set', '--application=False', 'unknown', ''], - ]) - - with self.assertRaises(ops.model.ModelError): - self.model.app.status = ops.model.UnknownStatus() - - # A leadership check is needed for application status. - self.assertEqual(fake_script_calls(self, True), [ - ['is-leader', '--format=json'], - ['status-set', '--application=True', 'unknown', ''], - ]) - - def test_status_set_is_app_not_bool_raises(self): - self.backend = ops.model.ModelBackend() - - for is_app_v in [None, 1, 2.0, 'a', b'beef', object]: - with self.assertRaises(TypeError): - self.backend.status_set(ops.model.ActiveStatus, is_app=is_app_v) - - def test_remote_unit_status(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - - remote_unit = next(filter(lambda u: u.name == 'remoteapp1/0', - self.model.get_relation('db1').units)) - - test_statuses = ( - ops.model.UnknownStatus(), - ops.model.ActiveStatus('Green'), - ops.model.MaintenanceStatus('Yellow'), - ops.model.BlockedStatus('Red'), - ops.model.WaitingStatus('White'), - ) - - for target_status in test_statuses: - with self.assertRaises(RuntimeError): - remote_unit.status = target_status - - def test_remote_app_status(self): - fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") - fake_script(self, 'relation-list', ''' - if [ "$2" = 4 ]; then - echo '["remoteapp1/0", "remoteapp1/1"]' - else - exit 2 - fi - ''') - - remoteapp1 = self.model.get_relation('db1').app - - # Remote application status is always unknown. - self.assertIsInstance(remoteapp1.status, ops.model.UnknownStatus) - - test_statuses = ( - ops.model.UnknownStatus(), - ops.model.ActiveStatus(), - ops.model.MaintenanceStatus('Upgrading software'), - ops.model.BlockedStatus('Awaiting manual resolution'), - ops.model.WaitingStatus('Awaiting related app updates'), - ) - for target_status in test_statuses: - with self.assertRaises(RuntimeError): - remoteapp1.status = target_status - - self.assertEqual(fake_script_calls(self, clear=True), [ - ['relation-ids', 'db1', '--format=json'], - ['relation-list', '-r', '4', '--format=json'], - ]) - - def test_storage(self): - meta = ops.charm.CharmMeta() - meta.storages = {'disks': None, 'data': None} - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'storage-list', ''' - if [ "$1" = disks ]; then - echo '["disks/0", "disks/1"]' - else - echo '[]' - fi - ''') - fake_script(self, 'storage-get', ''' - if [ "$2" = disks/0 ]; then - echo '"/var/srv/disks/0"' - elif [ "$2" = disks/1 ]; then - echo '"/var/srv/disks/1"' - else - exit 2 - fi - ''') - fake_script(self, 'storage-add', '') - - self.assertEqual(len(self.model.storages), 2) - self.assertEqual(self.model.storages.keys(), meta.storages.keys()) - self.assertIn('disks', self.model.storages) - test_cases = { - 0: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/0')}, - 1: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/1')}, - } - for storage in self.model.storages['disks']: - self.assertEqual(storage.name, 'disks') - self.assertIn(storage.id, test_cases) - self.assertEqual(storage.name, test_cases[storage.id]['name']) - self.assertEqual(storage.location, test_cases[storage.id]['location']) - - self.assertEqual(fake_script_calls(self, clear=True), [ - ['storage-list', 'disks', '--format=json'], - ['storage-get', '-s', 'disks/0', 'location', '--format=json'], - ['storage-get', '-s', 'disks/1', 'location', '--format=json'], - ]) - - self.assertSequenceEqual(self.model.storages['data'], []) - self.model.storages.request('data', count=3) - self.assertEqual(fake_script_calls(self), [ - ['storage-list', 'data', '--format=json'], - ['storage-add', 'data=3'], - ]) - - # Try to add storage not present in charm metadata. - with self.assertRaises(ops.model.ModelError): - self.model.storages.request('deadbeef') - - # Invalid count parameter types. - for count_v in [None, False, 2.0, 'a', b'beef', object]: - with self.assertRaises(TypeError): - self.model.storages.request('data', count_v) - - -class TestModelBindings(unittest.TestCase): - - def setUp(self): - def restore_env(env): - os.environ.clear() - os.environ.update(env) - self.addCleanup(restore_env, os.environ.copy()) - - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - - meta = ops.charm.CharmMeta() - meta.relations = { - 'db0': RelationMeta('provides', 'db0', {'interface': 'db0', 'scope': 'global'}), - 'db1': RelationMeta('requires', 'db1', {'interface': 'db1', 'scope': 'global'}), - 'db2': RelationMeta('peers', 'db2', {'interface': 'db2', 'scope': 'global'}), - } - self.backend = ops.model.ModelBackend() - self.model = ops.model.Model('myapp/0', meta, self.backend) - - fake_script(self, 'relation-ids', - """([ "$1" = db0 ] && echo '["db0:4"]') || echo '[]'""") - fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") - self.network_get_out = '''{ - "bind-addresses": [ - { - "mac-address": "de:ad:be:ef:ca:fe", - "interface-name": "lo", - "addresses": [ - { - "hostname": "", - "value": "192.0.2.2", - "cidr": "192.0.2.0/24" - }, - { - "hostname": "deadbeef.example", - "value": "dead:beef::1", - "cidr": "dead:beef::/64" - } - ] - }, - { - "mac-address": "", - "interface-name": "tun", - "addresses": [ - { - "hostname": "", - "value": "192.0.3.3", - "cidr": "" - }, - { - "hostname": "", - "value": "2001:db8::3", - "cidr": "" - }, - { - "hostname": "deadbeef.local", - "value": "fe80::1:1", - "cidr": "fe80::/64" - } - ] - } - ], - "egress-subnets": [ - "192.0.2.2/32", - "192.0.3.0/24", - "dead:beef::/64", - "2001:db8::3/128" - ], - "ingress-addresses": [ - "192.0.2.2", - "192.0.3.3", - "dead:beef::1", - "2001:db8::3" - ] -}''' - - def _check_binding_data(self, binding_name, binding): - self.assertEqual(binding.name, binding_name) - self.assertEqual(binding.network.bind_address, ipaddress.ip_address('192.0.2.2')) - self.assertEqual(binding.network.ingress_address, ipaddress.ip_address('192.0.2.2')) - # /32 and /128 CIDRs are valid one-address networks for IPv{4,6}Network types respectively. - self.assertEqual(binding.network.egress_subnets, [ipaddress.ip_network('192.0.2.2/32'), - ipaddress.ip_network('192.0.3.0/24'), - ipaddress.ip_network('dead:beef::/64'), - ipaddress.ip_network('2001:db8::3/128')]) - - for (i, (name, address, subnet)) in enumerate([ - ('lo', '192.0.2.2', '192.0.2.0/24'), - ('lo', 'dead:beef::1', 'dead:beef::/64'), - ('tun', '192.0.3.3', '192.0.3.3/32'), - ('tun', '2001:db8::3', '2001:db8::3/128'), - ('tun', 'fe80::1:1', 'fe80::/64')]): - self.assertEqual(binding.network.interfaces[i].name, name) - self.assertEqual(binding.network.interfaces[i].address, ipaddress.ip_address(address)) - self.assertEqual(binding.network.interfaces[i].subnet, ipaddress.ip_network(subnet)) - - def test_invalid_keys(self): - # Basic validation for passing invalid keys. - for name in (object, 0): - with self.assertRaises(ops.model.ModelError): - self.model.get_binding(name) - - def test_dead_relations(self): - fake_script( - self, - 'network-get', - ''' - if [ "$1" = db0 ] && [ "$2" = --format=json ]; then - echo '{}' - else - echo ERROR invalid value "$2" for option -r: relation not found >&2 - exit 2 - fi - '''.format(self.network_get_out)) - # Validate the behavior for dead relations. - binding = ops.model.Binding('db0', 42, self.model._backend) - self.assertEqual(binding.network.bind_address, ipaddress.ip_address('192.0.2.2')) - self.assertEqual(fake_script_calls(self, clear=True), [ - ['network-get', 'db0', '-r', '42', '--format=json'], - ['network-get', 'db0', '--format=json'], - ]) - - def test_binding_by_relation_name(self): - fake_script(self, 'network-get', - '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) - binding_name = 'db0' - expected_calls = [['network-get', 'db0', '--format=json']] - - binding = self.model.get_binding(binding_name) - self._check_binding_data(binding_name, binding) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - def test_binding_by_relation(self): - fake_script(self, 'network-get', - '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) - binding_name = 'db0' - expected_calls = [ - ['relation-ids', 'db0', '--format=json'], - # The two invocations below are due to the get_relation call. - ['relation-list', '-r', '4', '--format=json'], - ['network-get', 'db0', '-r', '4', '--format=json'], - ] - binding = self.model.get_binding(self.model.get_relation(binding_name)) - self._check_binding_data(binding_name, binding) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - -class TestModelBackend(unittest.TestCase): - - def setUp(self): - os.environ['JUJU_UNIT_NAME'] = 'myapp/0' - self.addCleanup(os.environ.pop, 'JUJU_UNIT_NAME') - - self._backend = None - - @property - def backend(self): - if self._backend is None: - self._backend = ops.model.ModelBackend() - return self._backend - - def test_relation_tool_errors(self): - err_msg = 'ERROR invalid value "$2" for option -r: relation not found' - - test_cases = [( - lambda: fake_script(self, 'relation-list', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_list(3), - ops.model.ModelError, - [['relation-list', '-r', '3', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-list', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_list(3), - ops.model.RelationNotFoundError, - [['relation-list', '-r', '3', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-set', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_set(3, 'foo', 'bar', is_app=False), - ops.model.ModelError, - [['relation-set', '-r', '3', 'foo=bar', '--app=False']], - ), ( - lambda: fake_script(self, 'relation-set', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_set(3, 'foo', 'bar', is_app=False), - ops.model.RelationNotFoundError, - [['relation-set', '-r', '3', 'foo=bar', '--app=False']], - ), ( - lambda: fake_script(self, 'relation-get', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.relation_get(3, 'remote/0', is_app=False), - ops.model.ModelError, - [['relation-get', '-r', '3', '-', 'remote/0', '--app=False', '--format=json']], - ), ( - lambda: fake_script(self, 'relation-get', 'echo {} >&2 ; exit 2'.format(err_msg)), - lambda: self.backend.relation_get(3, 'remote/0', is_app=False), - ops.model.RelationNotFoundError, - [['relation-get', '-r', '3', '-', 'remote/0', '--app=False', '--format=json']], - )] - - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_status_is_app_forced_kwargs(self): - fake_script(self, 'status-get', 'exit 1') - fake_script(self, 'status-set', 'exit 1') - - test_cases = ( - lambda: self.backend.status_get(False), - lambda: self.backend.status_get(True), - lambda: self.backend.status_set('active', '', False), - lambda: self.backend.status_set('active', '', True), - ) - - for case in test_cases: - with self.assertRaises(TypeError): - case() - - def test_storage_tool_errors(self): - test_cases = [( - lambda: fake_script(self, 'storage-list', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_list('foobar'), - ops.model.ModelError, - [['storage-list', 'foobar', '--format=json']], - ), ( - lambda: fake_script(self, 'storage-get', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_get('foobar', 'someattr'), - ops.model.ModelError, - [['storage-get', '-s', 'foobar', 'someattr', '--format=json']], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=2), - ops.model.ModelError, - [['storage-add', 'foobar=2']], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=object), - TypeError, - [], - ), ( - lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), - lambda: self.backend.storage_add('foobar', count=True), - TypeError, - [], - )] - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_network_get(self): - network_get_out = '''{ - "bind-addresses": [ - { - "mac-address": "", - "interface-name": "", - "addresses": [ - { - "hostname": "", - "value": "192.0.2.2", - "cidr": "" - } - ] - } - ], - "egress-subnets": [ - "192.0.2.2/32" - ], - "ingress-addresses": [ - "192.0.2.2" - ] -}''' - fake_script(self, 'network-get', - '''[ "$1" = deadbeef ] && echo '{}' || exit 1'''.format(network_get_out)) - network_info = self.backend.network_get('deadbeef') - self.assertEqual(network_info, json.loads(network_get_out)) - self.assertEqual(fake_script_calls(self, clear=True), - [['network-get', 'deadbeef', '--format=json']]) - - network_info = self.backend.network_get('deadbeef', 1) - self.assertEqual(network_info, json.loads(network_get_out)) - self.assertEqual(fake_script_calls(self, clear=True), - [['network-get', 'deadbeef', '-r', '1', '--format=json']]) - - def test_network_get_errors(self): - err_no_endpoint = 'ERROR no network config found for binding "$2"' - err_no_rel = 'ERROR invalid value "$3" for option -r: relation not found' - - test_cases = [( - lambda: fake_script(self, 'network-get', - 'echo {} >&2 ; exit 1'.format(err_no_endpoint)), - lambda: self.backend.network_get("deadbeef"), - ops.model.ModelError, - [['network-get', 'deadbeef', '--format=json']], - ), ( - lambda: fake_script(self, 'network-get', 'echo {} >&2 ; exit 2'.format(err_no_rel)), - lambda: self.backend.network_get("deadbeef", 3), - ops.model.RelationNotFoundError, - [['network-get', 'deadbeef', '-r', '3', '--format=json']], - )] - for do_fake, run, exception, calls in test_cases: - do_fake() - with self.assertRaises(exception): - run() - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_get_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-get', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_get() - calls = [['action-get', '--format=json']] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_set_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-set', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_set(OrderedDict([('foo', 'bar'), ('dead', 'beef cafe')])) - calls = [["action-set", "foo=bar", "dead=beef cafe"]] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_log_error(self): - fake_script(self, 'action-get', '') - fake_script(self, 'action-log', 'echo fooerror >&2 ; exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.action_log('log-message') - calls = [["action-log", "log-message"]] - self.assertEqual(fake_script_calls(self, clear=True), calls) - - def test_action_get(self): - fake_script(self, 'action-get', """echo '{"foo-name": "bar", "silent": false}'""") - params = self.backend.action_get() - self.assertEqual(params['foo-name'], 'bar') - self.assertEqual(params['silent'], False) - self.assertEqual(fake_script_calls(self), [['action-get', '--format=json']]) - - def test_action_set(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-set', 'exit 0') - self.backend.action_set(OrderedDict([('x', 'dead beef'), ('y', 1)])) - self.assertEqual(fake_script_calls(self), [['action-set', 'x=dead beef', 'y=1']]) - - def test_action_fail(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-fail', 'exit 0') - self.backend.action_fail('error 42') - self.assertEqual(fake_script_calls(self), [['action-fail', 'error 42']]) - - def test_action_log(self): - fake_script(self, 'action-get', 'exit 1') - fake_script(self, 'action-log', 'exit 0') - self.backend.action_log('progress: 42%') - self.assertEqual(fake_script_calls(self), [['action-log', 'progress: 42%']]) - - def test_application_version_set(self): - fake_script(self, 'application-version-set', 'exit 0') - self.backend.application_version_set('1.2b3') - self.assertEqual(fake_script_calls(self), [['application-version-set', '--', '1.2b3']]) - - def test_application_version_set_invalid(self): - fake_script(self, 'application-version-set', 'exit 0') - with self.assertRaises(TypeError): - self.backend.application_version_set(2) - with self.assertRaises(TypeError): - self.backend.application_version_set() - self.assertEqual(fake_script_calls(self), []) - - def test_juju_log(self): - fake_script(self, 'juju-log', 'exit 0') - self.backend.juju_log('WARNING', 'foo') - self.assertEqual(fake_script_calls(self, clear=True), - [['juju-log', '--log-level', 'WARNING', 'foo']]) - - with self.assertRaises(TypeError): - self.backend.juju_log('DEBUG') - self.assertEqual(fake_script_calls(self, clear=True), []) - - fake_script(self, 'juju-log', 'exit 1') - with self.assertRaises(ops.model.ModelError): - self.backend.juju_log('BAR', 'foo') - self.assertEqual(fake_script_calls(self, clear=True), - [['juju-log', '--log-level', 'BAR', 'foo']]) - - def test_valid_metrics(self): - fake_script(self, 'add-metric', 'exit 0') - test_cases = [( - OrderedDict([('foo', 42), ('b-ar', 4.5), ('ba_-z', 4.5), ('a', 1)]), - OrderedDict([('de', 'ad'), ('be', 'ef_ -')]), - [['add-metric', '--labels', 'de=ad,be=ef_ -', - 'foo=42', 'b-ar=4.5', 'ba_-z=4.5', 'a=1']] - ), ( - OrderedDict([('foo1', 0), ('b2r', 4.5)]), - OrderedDict([('d3', 'aд'), ('b33f', '3_ -')]), - [['add-metric', '--labels', 'd3=aд,b33f=3_ -', 'foo1=0', 'b2r=4.5']], - )] - for metrics, labels, expected_calls in test_cases: - self.backend.add_metrics(metrics, labels) - self.assertEqual(fake_script_calls(self, clear=True), expected_calls) - - def test_invalid_metric_names(self): - invalid_inputs = [ - ({'': 4.2}, {}), - ({'1': 4.2}, {}), - ({'1': -4.2}, {}), - ({'123': 4.2}, {}), - ({'1foo': 4.2}, {}), - ({'-foo': 4.2}, {}), - ({'_foo': 4.2}, {}), - ({'foo-': 4.2}, {}), - ({'foo_': 4.2}, {}), - ({'a-': 4.2}, {}), - ({'a_': 4.2}, {}), - ({'BAЯ': 4.2}, {}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_values(self): - invalid_inputs = [ - ({'a': float('+inf')}, {}), - ({'a': float('-inf')}, {}), - ({'a': float('nan')}, {}), - ({'foo': 'bar'}, {}), - ({'foo': '1O'}, {}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_labels(self): - invalid_inputs = [ - ({'foo': 4.2}, {'': 'baz'}), - ({'foo': 4.2}, {',bar': 'baz'}), - ({'foo': 4.2}, {'b=a=r': 'baz'}), - ({'foo': 4.2}, {'BAЯ': 'baz'}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - def test_invalid_metric_label_values(self): - invalid_inputs = [ - ({'foo': 4.2}, {'bar': ''}), - ({'foo': 4.2}, {'bar': 'b,az'}), - ({'foo': 4.2}, {'bar': 'b=az'}), - ] - for metrics, labels in invalid_inputs: - with self.assertRaises(ops.model.ModelError): - self.backend.add_metrics(metrics, labels) - - -class TestLazyMapping(unittest.TestCase): - - def test_invalidate(self): - loaded = [] - - class MyLazyMap(ops.model.LazyMapping): - def _load(self): - loaded.append(1) - return {'foo': 'bar'} - - map = MyLazyMap() - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1]) - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1]) - map._invalidate() - self.assertEqual(map['foo'], 'bar') - self.assertEqual(loaded, [1, 1]) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py b/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py deleted file mode 100644 index 1645e5a2..00000000 --- a/magma/squid_cnf/charms/squid/mod/operator/test/test_testing.py +++ /dev/null @@ -1,756 +0,0 @@ -#!/usr/bin/python3 -# Copyright 2019 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 importlib -import pathlib -import shutil -import sys -import tempfile -import textwrap -import unittest - -from ops.charm import ( - CharmBase, - RelationEvent, -) -from ops.framework import ( - Object, -) -from ops.model import ( - ModelError, - RelationNotFoundError, -) -from ops.testing import Harness - - -class TestHarness(unittest.TestCase): - - def test_add_relation(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - self.assertIsInstance(rel_id, int) - backend = harness._backend - self.assertEqual(backend.relation_ids('db'), [rel_id]) - self.assertEqual(backend.relation_list(rel_id), []) - # Make sure the initial data bags for our app and unit are empty. - self.assertEqual(backend.relation_get(rel_id, 'test-app', is_app=True), {}) - self.assertEqual(backend.relation_get(rel_id, 'test-app/0', is_app=False), {}) - - def test_add_relation_and_unit(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - self.assertIsInstance(rel_id, int) - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'foo': 'bar'}) - backend = harness._backend - self.assertEqual(backend.relation_ids('db'), [rel_id]) - self.assertEqual(backend.relation_list(rel_id), ['postgresql/0']) - self.assertEqual( - backend.relation_get(rel_id, 'postgresql/0', is_app=False), - {'foo': 'bar'}) - - def test_add_relation_with_remote_app_data(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - remote_app = 'postgresql' - rel_id = harness.add_relation('db', remote_app) - harness.update_relation_data(rel_id, 'postgresql', {'app': 'data'}) - self.assertIsInstance(rel_id, int) - backend = harness._backend - self.assertEqual([rel_id], backend.relation_ids('db')) - self.assertEqual({'app': 'data'}, backend.relation_get(rel_id, remote_app, is_app=True)) - - def test_add_relation_with_our_initial_data(self): - - class InitialDataTester(CharmBase): - """Record the relation-changed events.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.observed_events = [] - self.framework.observe(self.on.db_relation_changed, self._on_db_relation_changed) - - def _on_db_relation_changed(self, event): - self.observed_events.append(event) - - # language=YAML - harness = Harness(InitialDataTester, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'test-app', {'k': 'v1'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.1'}) - backend = harness._backend - self.assertEqual({'k': 'v1'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - - harness.begin() - self.assertEqual({'k': 'v1'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - # Make sure no relation-changed events are emitted for our own data bags. - self.assertEqual([], harness.charm.observed_events) - - # A remote unit can still update our app relation data bag since our unit is not a leader. - harness.update_relation_data(rel_id, 'test-app', {'k': 'v2'}) - # And we get an event - self.assertEqual([], harness.charm.observed_events) - # We can also update our own relation data, even if it is a bit 'cheaty' - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - # But no event happens - - # Updating our data app relation data bag and our unit data bag does not generate events. - harness.set_leader(True) - harness.update_relation_data(rel_id, 'test-app', {'k': 'v3'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - self.assertEqual([], harness.charm.observed_events) - - def test_add_peer_relation_with_initial_data_leader(self): - - class InitialDataTester(CharmBase): - """Record the relation-changed events.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.observed_events = [] - self.framework.observe(self.on.cluster_relation_changed, - self._on_cluster_relation_changed) - - def _on_cluster_relation_changed(self, event): - self.observed_events.append(event) - - # language=YAML - harness = Harness(InitialDataTester, meta=''' - name: test-app - peers: - cluster: - interface: cluster - ''') - # TODO: dmitriis 2020-04-07 test a minion unit and initial peer relation app data - # events when the harness begins to emit events for initial data. - harness.set_leader(is_leader=True) - rel_id = harness.add_relation('cluster', 'test-app') - harness.update_relation_data(rel_id, 'test-app', {'k': 'v'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.1'}) - backend = harness._backend - self.assertEqual({'k': 'v'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - - harness.begin() - self.assertEqual({'k': 'v'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertEqual({'ingress-address': '192.0.2.1'}, - backend.relation_get(rel_id, 'test-app/0', is_app=False)) - # Make sure no relation-changed events are emitted for our own data bags. - self.assertEqual([], harness.charm.observed_events) - - # Updating our app relation data bag and our unit data bag does not trigger events - harness.update_relation_data(rel_id, 'test-app', {'k': 'v2'}) - harness.update_relation_data(rel_id, 'test-app/0', {'ingress-address': '192.0.2.2'}) - self.assertEqual([], harness.charm.observed_events) - - # If our unit becomes a minion, updating app relation data indirectly becomes possible - # and our charm gets notifications. - harness.set_leader(False) - harness.update_relation_data(rel_id, 'test-app', {'k': 'v3'}) - self.assertEqual({'k': 'v3'}, backend.relation_get(rel_id, 'test-app', is_app=True)) - self.assertTrue(len(harness.charm.observed_events), 1) - self.assertIsInstance(harness.charm.observed_events[0], RelationEvent) - - def test_relation_events(self): - harness = Harness(RelationEventCharm, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.charm.observe_relation_events('db') - self.assertEqual(harness.charm.get_changes(), []) - rel_id = harness.add_relation('db', 'postgresql') - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-created', - 'data': { - 'app': 'postgresql', - 'unit': None, - 'relation_id': rel_id, - }}]) - harness.add_relation_unit(rel_id, 'postgresql/0') - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-joined', - 'data': { - 'app': 'postgresql', - 'unit': 'postgresql/0', - 'relation_id': rel_id, - }}]) - harness.update_relation_data(rel_id, 'postgresql', {'foo': 'bar'}) - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-changed', - 'data': { - 'app': 'postgresql', - 'unit': None, - 'relation_id': rel_id, - }}]) - harness.update_relation_data(rel_id, 'postgresql/0', {'baz': 'bing'}) - self.assertEqual( - harness.charm.get_changes(), - [{'name': 'relation-changed', - 'data': { - 'app': 'postgresql', - 'unit': 'postgresql/0', - 'relation_id': rel_id, - }}]) - - def test_get_relation_data(self): - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'postgresql', {'remote': 'data'}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app'), {}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app/0'), {}) - self.assertEqual(harness.get_relation_data(rel_id, 'test-app/1'), None) - self.assertEqual(harness.get_relation_data(rel_id, 'postgresql'), {'remote': 'data'}) - with self.assertRaises(KeyError): - # unknown relation id - harness.get_relation_data(99, 'postgresql') - - def test_create_harness_twice(self): - metadata = ''' - name: my-charm - requires: - db: - interface: pgsql - ''' - harness1 = Harness(CharmBase, meta=metadata) - harness2 = Harness(CharmBase, meta=metadata) - harness1.begin() - harness2.begin() - helper1 = DBRelationChangedHelper(harness1.charm, "helper1") - helper2 = DBRelationChangedHelper(harness2.charm, "helper2") - rel_id = harness2.add_relation('db', 'postgresql') - harness2.update_relation_data(rel_id, 'postgresql', {'key': 'value'}) - # Helper2 should see the event triggered by harness2, but helper1 should see no events. - self.assertEqual(helper1.changes, []) - self.assertEqual(helper2.changes, [(rel_id, 'postgresql')]) - - def test_begin_twice(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: test-app - requires: - db: - interface: pgsql - ''') - harness.begin() - with self.assertRaises(RuntimeError): - harness.begin() - - def test_update_relation_exposes_new_data(self): - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - viewer = RelationChangedViewer(harness.charm, 'db') - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': 'data'}) - self.assertEqual(viewer.changes, [{'initial': 'data'}]) - harness.update_relation_data(rel_id, 'postgresql/0', {'new': 'value'}) - self.assertEqual(viewer.changes, [{'initial': 'data'}, - {'initial': 'data', 'new': 'value'}]) - - def test_update_relation_no_local_unit_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.model.unit]['key'] = 'value' - # there should be no event for updating our own data - harness.update_relation_data(rel_id, 'my-charm/0', {'new': 'other'}) - # but the data will be updated. - self.assertEqual({'key': 'value', 'new': 'other'}, rel.data[harness.charm.model.unit]) - - rel.data[harness.charm.model.unit]['new'] = 'value' - # Our unit data bag got updated. - self.assertEqual(rel.data[harness.charm.model.unit]['new'], 'value') - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - def test_update_peer_relation_no_local_unit_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: postgresql - peers: - db: - interface: pgsql - ''') - harness.begin() - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.model.unit]['key'] = 'value' - rel = harness.charm.model.get_relation('db') - harness.update_relation_data(rel_id, 'postgresql/0', {'key': 'v1'}) - self.assertEqual({'key': 'v1'}, rel.data[harness.charm.model.unit]) - # Make sure there was no event - self.assertEqual([], helper.changes) - - rel.data[harness.charm.model.unit]['key'] = 'v2' - # Our unit data bag got updated. - self.assertEqual({'key': 'v2'}, dict(rel.data[harness.charm.model.unit])) - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - # Same for when our unit is a leader. - harness.set_leader(is_leader=True) - harness.update_relation_data(rel_id, 'postgresql/0', {'key': 'v3'}) - self.assertEqual({'key': 'v3'}, dict(rel.data[harness.charm.model.unit])) - self.assertEqual([], helper.changes) - - rel.data[harness.charm.model.unit]['key'] = 'v4' - self.assertEqual(rel.data[harness.charm.model.unit]['key'], 'v4') - self.assertEqual([], helper.changes) - - def test_update_peer_relation_app_data(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: postgresql - peers: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(is_leader=True) - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - rel = harness.charm.model.get_relation('db') - rel.data[harness.charm.app]['key'] = 'value' - harness.update_relation_data(rel_id, 'postgresql', {'key': 'v1'}) - self.assertEqual({'key': 'v1'}, rel.data[harness.charm.app]) - self.assertEqual([], helper.changes) - - rel.data[harness.charm.app]['key'] = 'v2' - # Our unit data bag got updated. - self.assertEqual(rel.data[harness.charm.model.app]['key'], 'v2') - # But there were no changed events registered by our unit. - self.assertEqual([], helper.changes) - - # If our unit is not a leader unit we get an update about peer app relation data changes. - harness.set_leader(is_leader=False) - harness.update_relation_data(rel_id, 'postgresql', {'k2': 'v2'}) - self.assertEqual(rel.data[harness.charm.model.app]['k2'], 'v2') - self.assertEqual(helper.changes, [(0, 'postgresql')]) - - def test_update_relation_no_local_app_change_event(self): - # language=YAML - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - helper = DBRelationChangedHelper(harness.charm, "helper") - rel_id = harness.add_relation('db', 'postgresql') - # TODO: remove this as soon as https://github.com/canonical/operator/issues/175 is fixed. - harness.add_relation_unit(rel_id, 'postgresql/0') - self.assertEqual(helper.changes, []) - - harness.update_relation_data(rel_id, 'my-charm', {'new': 'value'}) - rel = harness.charm.model.get_relation('db') - self.assertEqual(rel.data[harness.charm.app]['new'], 'value') - - # Our app data bag got updated. - self.assertEqual(rel.data[harness.charm.model.app]['new'], 'value') - # But there were no changed events registered by our unit. - self.assertEqual(helper.changes, []) - - def test_update_relation_remove_data(self): - harness = Harness(CharmBase, meta=''' - name: my-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - viewer = RelationChangedViewer(harness.charm, 'db') - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': 'data'}) - harness.update_relation_data(rel_id, 'postgresql/0', {'initial': ''}) - self.assertEqual(viewer.changes, [{'initial': 'data'}, {}]) - - def test_update_config(self): - harness = Harness(RecordingCharm) - harness.begin() - harness.update_config(key_values={'a': 'foo', 'b': 2}) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}]) - harness.update_config(key_values={'b': 3}) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}, - {'name': 'config', 'data': {'a': 'foo', 'b': 3}}]) - # you can set config values to the empty string, you can use unset to actually remove items - harness.update_config(key_values={'a': ''}, unset=set('b')) - self.assertEqual( - harness.charm.changes, - [{'name': 'config', 'data': {'a': 'foo', 'b': 2}}, - {'name': 'config', 'data': {'a': 'foo', 'b': 3}}, - {'name': 'config', 'data': {'a': ''}}, - ]) - - def test_set_leader(self): - harness = Harness(RecordingCharm) - # No event happens here - harness.set_leader(False) - harness.begin() - self.assertFalse(harness.charm.model.unit.is_leader()) - harness.set_leader(True) - self.assertEqual(harness.charm.get_changes(reset=True), [{'name': 'leader-elected'}]) - self.assertTrue(harness.charm.model.unit.is_leader()) - harness.set_leader(False) - self.assertFalse(harness.charm.model.unit.is_leader()) - # No hook event when you lose leadership. - # TODO: verify if Juju always triggers `leader-settings-changed` if you - # lose leadership. - self.assertEqual(harness.charm.get_changes(reset=True), []) - harness.disable_hooks() - harness.set_leader(True) - # No hook event if you have disabled them - self.assertEqual(harness.charm.get_changes(reset=True), []) - - def test_relation_set_app_not_leader(self): - harness = Harness(RecordingCharm, meta=''' - name: test-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - rel_id = harness.add_relation('db', 'postgresql') - harness.add_relation_unit(rel_id, 'postgresql/0') - rel = harness.charm.model.get_relation('db') - with self.assertRaises(ModelError): - rel.data[harness.charm.app]['foo'] = 'bar' - # The data has not actually been changed - self.assertEqual(harness.get_relation_data(rel_id, 'test-charm'), {}) - harness.set_leader(True) - rel.data[harness.charm.app]['foo'] = 'bar' - self.assertEqual(harness.get_relation_data(rel_id, 'test-charm'), {'foo': 'bar'}) - - def test_hooks_enabled_and_disabled(self): - harness = Harness(RecordingCharm, meta=''' - name: test-charm - ''') - # Before begin() there are no events. - harness.update_config({'value': 'first'}) - # By default, after begin the charm is set up to receive events. - harness.begin() - harness.update_config({'value': 'second'}) - self.assertEqual( - harness.charm.get_changes(reset=True), - [{'name': 'config', 'data': {'value': 'second'}}]) - # Once disabled, we won't see config-changed when we make an update - harness.disable_hooks() - harness.update_config({'third': '3'}) - self.assertEqual(harness.charm.get_changes(reset=True), []) - harness.enable_hooks() - harness.update_config({'value': 'fourth'}) - self.assertEqual( - harness.charm.get_changes(reset=True), - [{'name': 'config', 'data': {'value': 'fourth', 'third': '3'}}]) - - def test_metadata_from_directory(self): - tmp = pathlib.Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(tmp)) - metadata_filename = tmp / 'metadata.yaml' - with metadata_filename.open('wt') as metadata: - metadata.write(textwrap.dedent(''' - name: my-charm - requires: - db: - interface: pgsql - ''')) - harness = self._get_dummy_charm_harness(tmp) - harness.begin() - self.assertEqual(list(harness.model.relations), ['db']) - # The charm_dir also gets set - self.assertEqual(harness.framework.charm_dir, tmp) - - def test_actions_from_directory(self): - tmp = pathlib.Path(tempfile.mkdtemp()) - self.addCleanup(shutil.rmtree, str(tmp)) - actions_filename = tmp / 'actions.yaml' - with actions_filename.open('wt') as actions: - actions.write(textwrap.dedent(''' - test: - description: a dummy action - ''')) - harness = self._get_dummy_charm_harness(tmp) - harness.begin() - self.assertEqual(list(harness.framework.meta.actions), ['test']) - # The charm_dir also gets set - self.assertEqual(harness.framework.charm_dir, tmp) - - def _get_dummy_charm_harness(self, tmp): - self._write_dummy_charm(tmp) - charm_mod = importlib.import_module('charm') - harness = Harness(charm_mod.MyTestingCharm) - return harness - - def _write_dummy_charm(self, tmp): - srcdir = tmp / 'src' - srcdir.mkdir(0o755) - charm_filename = srcdir / 'charm.py' - with charm_filename.open('wt') as charmpy: - # language=Python - charmpy.write(textwrap.dedent(''' - from ops.charm import CharmBase - class MyTestingCharm(CharmBase): - pass - ''')) - orig = sys.path[:] - sys.path.append(str(srcdir)) - - def cleanup(): - sys.path = orig - sys.modules.pop('charm') - - self.addCleanup(cleanup) - - def test_actions_passed_in(self): - harness = Harness( - CharmBase, - meta=''' - name: test-app - ''', - actions=''' - test-action: - description: a dummy test action - ''') - self.assertEqual(list(harness.framework.meta.actions), ['test-action']) - - def test_relation_set_deletes(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - requires: - db: - interface: pgsql - ''') - harness.begin() - harness.set_leader(False) - rel_id = harness.add_relation('db', 'postgresql') - harness.update_relation_data(rel_id, 'test-charm/0', {'foo': 'bar'}) - harness.add_relation_unit(rel_id, 'postgresql/0') - rel = harness.charm.model.get_relation('db', rel_id) - del rel.data[harness.charm.model.unit]['foo'] - self.assertEqual({}, harness.get_relation_data(rel_id, 'test-charm/0')) - - def test_set_workload_version(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - harness.begin() - self.assertIsNone(harness.get_workload_version()) - harness.charm.model.unit.set_workload_version('1.2.3') - self.assertEqual(harness.get_workload_version(), '1.2.3') - - -class DBRelationChangedHelper(Object): - def __init__(self, parent, key): - super().__init__(parent, key) - self.changes = [] - parent.framework.observe(parent.on.db_relation_changed, self.on_relation_changed) - - def on_relation_changed(self, event): - if event.unit is not None: - self.changes.append((event.relation.id, event.unit.name)) - else: - self.changes.append((event.relation.id, event.app.name)) - - -class RelationChangedViewer(Object): - """Track relation_changed events and saves the data seen in the relation bucket.""" - - def __init__(self, charm, relation_name): - super().__init__(charm, relation_name) - self.changes = [] - charm.framework.observe(charm.on[relation_name].relation_changed, self.on_relation_changed) - - def on_relation_changed(self, event): - if event.unit is not None: - data = event.relation.data[event.unit] - else: - data = event.relation.data[event.app] - self.changes.append(dict(data)) - - -class RecordingCharm(CharmBase): - """Record the events that we see, and any associated data.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - self.changes = [] - self.framework.observe(self.on.config_changed, self.on_config_changed) - self.framework.observe(self.on.leader_elected, self.on_leader_elected) - - def get_changes(self, reset=True): - changes = self.changes - if reset: - self.changes = [] - return changes - - def on_config_changed(self, _): - self.changes.append(dict(name='config', data=dict(self.framework.model.config))) - - def on_leader_elected(self, _): - self.changes.append(dict(name='leader-elected')) - - -class RelationEventCharm(RecordingCharm): - """Record events related to relation lifecycles.""" - - def __init__(self, framework, charm_name): - super().__init__(framework, charm_name) - - def observe_relation_events(self, relation_name): - self.framework.observe(self.on[relation_name].relation_created, self._on_relation_created) - self.framework.observe(self.on[relation_name].relation_joined, self._on_relation_joined) - self.framework.observe(self.on[relation_name].relation_changed, self._on_relation_changed) - self.framework.observe(self.on[relation_name].relation_departed, - self._on_relation_departed) - self.framework.observe(self.on[relation_name].relation_broken, self._on_relation_broken) - - def _on_relation_created(self, event): - self._observe_relation_event('relation-created', event) - - def _on_relation_joined(self, event): - self._observe_relation_event('relation-joined', event) - - def _on_relation_changed(self, event): - self._observe_relation_event('relation-changed', event) - - def _on_relation_departed(self, event): - self._observe_relation_event('relation-departed', event) - - def _on_relation_broken(self, event): - self._observe_relation_event('relation-broken', event) - - def _observe_relation_event(self, event_name, event): - unit_name = None - if event.unit is not None: - unit_name = event.unit.name - app_name = None - if event.app is not None: - app_name = event.app.name - self.changes.append( - dict(name=event_name, - data=dict(app=app_name, unit=unit_name, relation_id=event.relation.id))) - - -class TestTestingModelBackend(unittest.TestCase): - - def test_status_set_get_unit(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - backend = harness._backend - backend.status_set('blocked', 'message', is_app=False) - self.assertEqual(backend.status_get(is_app=False), ('blocked', 'message')) - self.assertEqual(backend.status_get(is_app=True), None) - - def test_status_set_get_app(self): - harness = Harness(CharmBase, meta=''' - name: app - ''') - backend = harness._backend - backend.status_set('blocked', 'message', is_app=True) - self.assertEqual(backend.status_get(is_app=True), ('blocked', 'message')) - self.assertEqual(backend.status_get(is_app=False), None) - - def test_relation_ids_unknown_relation(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - provides: - db: - interface: mydb - ''') - backend = harness._backend - # With no relations added, we just get an empty list for the interface - self.assertEqual(backend.relation_ids('db'), []) - # But an unknown interface raises a ModelError - with self.assertRaises(ModelError): - backend.relation_ids('unknown') - - def test_relation_get_unknown_relation_id(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - ''') - backend = harness._backend - with self.assertRaises(RelationNotFoundError): - backend.relation_get(1234, 'unit/0', False) - - def test_relation_list_unknown_relation_id(self): - harness = Harness(CharmBase, meta=''' - name: test-charm - ''') - backend = harness._backend - with self.assertRaises(RelationNotFoundError): - backend.relation_list(1234) - - -if __name__ == "__main__": - unittest.main() diff --git a/magma/squid_cnf/charms/squid/requirements.txt b/magma/squid_cnf/charms/squid/requirements.txt new file mode 100644 index 00000000..4da6f5fe --- /dev/null +++ b/magma/squid_cnf/charms/squid/requirements.txt @@ -0,0 +1,3 @@ +ops +jinja2 +git+https://github.com/juju-solutions/resource-oci-image/@c5778285d332edf3d9a538f9d0c06154b7ec1b0b#egg=oci-image diff --git a/magma/squid_cnf/charms/squid/squid.charm b/magma/squid_cnf/charms/squid/squid.charm new file mode 100644 index 0000000000000000000000000000000000000000..00ca09ed1e2947b3e934e45bf8fd81abefdbbc5a GIT binary patch literal 601730 zcmb5Ub9iiDvn?Fkwr$(CZQC|>Y&+SpZQIF?ZSN#Iwv(IRd(X@JoqNyM{Zx1Vv7R|+ zuT@oJ)TmOB1_nU^004jhXp8kz{Qdy|^w-Dt3;Nrf9bGL==!`84oos;t6#j8(WvHLx zN4fh(*!LyAfB*n6-`|GDE|&Io&UBuJwl>xAvQR*bFk(;6k+a4w-&hs@=8T`h;s;nBvT!$t`^gHlZ43)oTwxWic zx(-XR_5OL_*6;tu2?=*XRA9|gP=E=9c%Oa-rkoj)YNq9$rchq5!=mG_ zO^I)W7!8aT>@RHFMC-GxYzT+Rf%5O@)ITBO)AP}0un2L>;{s#uja_3ZaZU9vswr4`mws6yW)VKZkdGx_>Iv zkaJ?t;zE1Srp}|x&p9%!4X?J}f@_!<(>^j{TTtAlv2{HOOJ#c9p#Rf_{_^>z(K6ze z@Ayaq1pt8jexypGf+Dh_bhaibDjRkS0tmi4wHW2_3cYq4Be~?=^Ff;{Cnw|qfmvg;;blv%-t1fZGnqF2Lb&+hSg%u-A&KBIQ z_UU-ab_cO)UL%SPw=mxTrJe|42@{)t@O=FN>2r6ItA!b$a7SDV#WS&D2zsT`3BjOr zB8gM!23lk3$J%|8lwQQ5LA5=D*tIN6)zi|?VaEJ414}>a8(u>d0)%}STRo08y$3^{ z{OViVtoTW$@wP`Q!gyO6)IT31mWJ|)*tA~cLdaKZC{9?wdpA379bB!Jx-Vt2Bk*H^ zmmGWW$1ZHeuImojgmom>us+Xv>cW=HqARVA1%wWL*v73Rgo9T9-K>VvXz?1 zw&!Faa{=AJl1Ow~WXVgNlek#ji$ zzB0X!3^LwT1pAvyWY_yp?UIkeO%G9AHUP>yf=>pWqhPl=+>a|?JRfm4FdKHZaj;8I zxY#Tlnw7U*?qTbT=0q}~pCf2j!qDhy6|hdZlWnQ*Vb3JO_>unqbncYz{FtG@lh5<* z)au{%SME2qw==Ue|64wvq^B7FHACI9uLSVp$9n-11T=^g6|_<{3e%m`E)iw<@VID( z0j?U96rjM8l!TLIL@_6+8q`Rr7}|d(MY;7|bNTP2sQVp7u-}{5nz|U87`hn#Z5vg^ zeyc$SnC@fhp=nufcw?KY^QMNu9s$SX^~Dw*Z8^yEgX8shH?Tm@TkqS2yAz9m`=qJG z;&Yr4*8pNt)G3KNr`S9eG4Mt zlQrxRx7yWi7v&tpp*sBC*2r$bQ)G=ta}NvP8HXhbf=mLDpAAUq=}39GQq?I{Q<_1= zAv75L&Mq4598PGnKGo-D#TGOrFditIstH1ER)s7eQBKHffD!BNKaQvBsAD@s=4Qck zZzblE6sTH$94#fJEhn>XK2lS#m}}<`=tj=uV+>o0MCmD>CprugH4U*13IjdJpNFIUB~cz+x=tRmQIv&7y`Wxa^wseE%9nCc0X-}h)ByhM!@rcq zNfHrUW4{l~lTwDSWHkX@QIA3dhCGHLM z-WBU1yqy=zWpXfc67mE_&WcB#XhPFqLx|ip$93G?I*uW0$!H0;{A?-*wPf7zbOKRY zwjbi;_mTSy^zTQ@GkZ6){&ouEZ=^*2KAMZEt%HrBiz)qo(T{IObWPNi4`M(Gt(~kr zDIm*&EcAiA9Elp{W{$a=m!NW)tx~Xwikkj#hn~uYa_EM5_ont&D;K*$!+5dKa5%Q6~O_e8E6_*YTH2j zWz#V;$vbt+qjwUK<~#)1-rnrfT!5t8;9Cv4Hs#8j#RS)QS->4Z(j!zrR6%(Eew1GrceXf759s*hXfRWNt%%X;IRY z7#VA#Qzq!kjyK7Jpr)Kv6(EjwSLco|zWhvXf~fKRzSbD%7;X90xz@P4BoSNle5#67 zGm_I1Z|3igWh!vv#G*wjVHMj3SoFjun9C=D@f96=uK9Xzk3m?Nd!;+rO)B4on{4gk ze2&)50m5f&Re_}hy<;_-{&6-lxlbW6=)}n`elO+ncd|V8?vHi@qe1oA{A|43?6%`L z1C>JOba^?y6|GaX_o#UN=SjIoAU4+{8Tsk2PnX+N++05o@zh|tzTePy_Qa9b{F5m( zmWgeF^r64{PrQ&$ALbafQ z=ZWy@tqsR4VKa?&B4)%wvm?+AN5HX{#1-Yu12qIBF_4usMwEb6Im!7QyP2vx)Q%wM zL2HNn5&9t0Kpm$eR0{(!!YtkiZRSXXtBC%r2WHx$g2&jO zffI#Lf&nH}S9nK2q0feoHWsB`BcdD^8wC$Cj0y4UbEO3^Lw#Y6dnVu4PJ($B2kMc}D;<#P!07GogL zi^T?Igmw4gX8nl`8uLqE4}9v)D4aw3-Q{+2I#iEIX^O_D83J$Cp(q;0xVWsZv8XUW z7GXrN9n~#{7~O;`nyo58n~Qie-s#u*=ft@hbT&Ei<{HQ9M@V9h=QAV%E2@C3A1S?F zJhr0hVcJvf^w@E>cEhSu_iT(!sTFPH3`(UptZH-DENpaLLGVS3QWgz=VSx()aOhmF z8SCgLQyR+5$spDH~Z zRn0Ol>oHV^c{p{Oakvfrjg-?P{${#zS8iHS5l`)YzdV#N^pSh$IUYRTXTm*X62gy~ z>S{*P8Yp1#X!Iy}T>)F~l~MMNtB}|_W|c>fN^SIcIS_If`s?`td(GVtj?<9U_oJb- z9H%Qk%et6UW$4hNIJ$E2NF?!K6*iNKerYb`P*sbX&eo@2@-s&7B_TgYDmA5Y(%fBm zz<(r+BV#0m&=uF7b#yp;!)3~DVhI#tpL2SKS+8U^ZR89&Z8)q5@P;k9?=<_wsllH$ z$;G?-+`9Ze*-6`YoO#?}>0(V$gDIBPx@oJ`;)nFG@;1lILgHKBS`L>D`A zGN{@V0xEwcev_v?J5qcb-jx|g+07I*G&%mTB_VD%$5f*I zKNH_yr7-n$*B;$BO9A?>-4MS)$<5Txjo#kaQs2_n(A@Mp`&Fy-$7V4gbl;&8KLAJ| z9#bj7+b#*Oi*>F)DygD68AxX6~vlRcZ)LJjML_TnaiXTQ!-CsmNFTIypio-|`cSF|9vi{|*DaTg9!A zVH17zPl9nDghOJaqmYI((YDPD7}s?+OB-6g`YtMqQrLr8+i?-48o*!w{2D3 z3KisSap;5;y8L`r%G$L*<%wIPR7pnp?Dj*nMo4>nmCO&Q8n1&s{_Wb{p3Pj5x9cNX zL2Btdv?x%FBoM;FRgNuDpL_@V)Yn@34;fNqSlz5LDa zkE$&5m5Is0AiqlM(Q|#JYmxCu#P18B^Mdg%5|Ke%QO44!b3d{_S#TIWJ&E!cKbts98 zZmCYckQSOn_EnACn!kE-VK<87tT_X2qI*|lF7bboKOOMRmcrxnD=gr~vHgms-00+# zxx7Tl#xKYA=9)^~lxXCa_0F=p++3BNak*Y#Fuy+>;C-R|cvUtCy4vc$=!A$@WY_en zTi6w<n4oO|F1exuu+1UmG%m$!Qt^yYu09x)r$JZM=_qDg= zmz-0@XT}Xg6Rd$8{e)-D+r;N)Up)=2m;X`#Y^lW2 zQ|UAC|IzS87(5MzEO+%(+8>+mjk(}0(^tqfHw(($e#y~Wk|Tyqws>||00w+e~z@Hlu6}8 zD>$M#n3CYB?IbE&nW+UG*#cF5mpBG(T`po*kh7v3dze@IE8R|n&QSmZ$gFMM6kUe4r`bX%0jg(@+Qa+Jox~*~cvylV zsY}%enUxrPi>@i5g!PA-t8P(VvqCEq`YUxxvz%qKmWcra4-&Hg0afx`r$w_&{`dq$ z@%qSEhgaB(9U?S~6A!IYhigg|QNGp%z=RPP<$H9Cb)YvYu&m?_MxdBcdwwO`HKBm> zQG%+G>O@MJ6Jn*S$eI-GwxJr*gc>5#yd5XUh6(31M8&jt`P$@&nPnnL+EA1>rm21= zqc<(RcOuc`N?M!!s{Fs_Xiw|%{J*NmzsgnG|3MhJ*gNRkn7WzT{1r%(vNRKPv=nkO z(nmo55uQ14gkt&Mp(*-JdMW+~>&l9%2#N@*2&SmpDj%>ReAejaJ2`{92VLN8>YBrt zc!8Q3OlV8ixV(a*cpsFlrc#d!yq>*DI3XR!T1#S##5T=X?cAUL&aN5@L7lrQicxW$ zaNmDA7g9;SbR}}#y=j%OmE@NnD#8_Ss9s!$TwIy#-~RltfBXAKKdm48`=(yHY4UPi&eeyD#iTT46TIK zRW8fV$~rV*>9{>&tP}-J5I%|=<%7qoi10u%tnsJO8b283F z&oqFSEpg0px{b3@Z~fYtk|~3-SnT5vpkw#tP>216(R(-ZwB=mteK~TqikKlYIig!o z=1ht;g@q6^oG`9j6k}Q?J`Nrw@1HSQK{?)T-gd1}GZKs2mIF2E7;dp^%Z6$I0kY^& z*w&@;b6)Kd{Y`BB|gIHDaBakLVW*Yw?&4wu0cI zoaKnKWnHw~-t|y^1*n6i7>r(OsQUbbkcNo<^0bvm5HvJX5BtWQu~!aQiPh?QQ>uBv zZ!(uc#;Lf%Y);Tk*6egfH!W=F#~>s$TD~aLE8C4cTqKsxq)V)|&8?E?Va7}$xw$r# zHD4^J0gO>_q&kA#Li&%Nrvk03m#$oELsM0V^(v4{5jQ#+c{;m4QP;^BZk{FEV6a+P zuFeLtFtJoPd>JsVBh*m!6Wc2Rifzru-O_GD?knvA-94G2XdbNwK=&1+M%siRBGI6L ze5{@M7taKei!Ri*A9!3aTmEw#ymth-^Gzt1P9Yw- z2UFeJBVDJ%w00a2SFa!0vDCXSrM69dYVsRF;56>@j2wha%MI+FTdXdHEMBt}=yASE zU1Y0ke{YWuv$9=qI7bh)5=<*Di{zSjA z*F)AZKZj_{B4wk0`^+nG3GDoe%PsT3iSszL1Jl*QrEpsI{YTtF27yY?z6Rign z!`TKrtZeac!U@@^7$UKbsgBGKWW{NxTb6zdssPI|);&-Hr$j3z&VMn$5Q3lr6*Dq1 z(MUP8>NC9omY+;wAabcY>_=zj-s(7tx^wyQl#D}y*v_oE;~w3=$}NH`oSNWPO}Npo zMz(T4oKzV^_j|wd)8N;WK3l+#^^s>drIqou)4iMFYYwqN?9DB&qm@HpW3SI&SeS)W ziPMQD8J`Am*m(=+aI%UT|97lp!6qnb& zsyUsnW2&4VR-LgB=2+lal({q(Up}K_i)ArOjJj`wCLKZ5bkV6wcA`d)Oo)zc`|0W} zsxWKhbWkEbiXQC!f9Ab^g8n;vjN+#afPJU;Z+QcN@_&%#CFPV=1Z8AIm8i#PcK;JI zw8o-NqQ5C!*Y|2<|AWPpM1|#*L{b(e?Ft!Cz;=C$dmv5PgwYxab{(LDt)aFE2m~a; z1DznR?~`IP&9usKRrNG)U#4&9wd3^Ud@n>aBln|Ln(5c!Xbsdplwd}W*s%?WF9?Y& zem`wK`AX#&u$Gs(Gs^NGH@LX1=3MVrE<@WlI9uJP8QLB}JUr+5%i5y=V!&y*7`qSR zHm?Dl8T4OPVcOuQgLCQ^G*Ih@0{GUPLUL@-u%uEq2{}X-_ddAp-V$Bivg>Fv0Z#TA*dN?YYjl=2j@)RWD;rC)s&GjL#mnw!sEh(-MufhW#`FU~7HkW{`|% z_&rmKuwoQ4UTA)b^z&gr^sL)O(sOkExr_r`F<=+tiFQ-fRii{$>l0g#+0e{W#!~bm zOicrKp^yt#WDnxmm&mRuKKxcUF?N&rfRN+!+2Ql7RsBmH1Fi04z(G--z1r!(N!nc6 zwz}{EAj`CC;1DOdjba{9zH7Dm-zsS^hS2 zOC43xwWjb=9JKC&XtkNYEKpG$=F}f*o2>nKK8V~WQrzK}SnNO2r|hvPCNaxjEJ(#_14o*)%`;u$n#n6|YYLQzbK^TV0uCBgcPWlNtu z>hO0?oefx|7!+Ay?gJTY9aV|MijL87PGH0($l7;GbUQd4OFSs6?RrX{OE4A+6`BNk zB+eZ4n^U{`;#Z>wlicMqX*DB&bs3Tfw2S(^6olocik*6IWh212Y!$S-2`^#M?TA^^rb^7zD_dce3SwdHBeaUUyPoA*;N-CV?BL4(5c z$2G-vEIg`pRXCki;`70gq?mXndochsIJoUET4**B`L$Lk{>65UJhFMzsWMk#Xj{x` zBd}$*>srHiwRHO+<TN`r$!|2-M9mE2_QE0N`D%=+s&@3GftTRXQgw3nxk{I-b0wC=l)Z3!W>= z=`difvb{mdJk4;?uPz`?aAcAE%vlGs1YcS-C1*wN_PC}%P2|Ced0;sWR?GMdJSRqB zKh+t6htlffdGcN!<@HK-(N zU1>avgt8JOTOob@(ouDFbV7A=RBAz|GGDUJ(tcrHH}_xRDUlOCVsS9cN~@&Za*CQ# ztEHH_5#GnJ2R-=%bUHaq&KrxLE;YZJHke`v+&*<<1^!xk9BMK zEw6)a{vJ79k+H!?V$0iR|R&9vvp`XOsIQ5ql7APE=f5s~%f~ z)IFU3Am7#Q#gB-kEvihjSY&yEkl`8SNo=*Ho&jo7Fw8$OsMEOm%xn|EFIKhsO&`}A zfjf}mXD8YIF#r`qloeTeIuDuHR*Kzy*8VLhSm>x6g1P93ZF8ADrRgc(G@eq`hSsGJ zh7sPZqDLr;6`?ml|2(g10PzNk5^IWjK+C}eap+e##tvcSMJ+BJtwE@PcjgGtM8v=8 zj2H=_nO|?@VaSKr#s(IYl^nO{)Wjn=ZU=f~v?vqbl0=}&5Jfk8mwo)KLDfXk3E1WO zobGL0sN0Dk{YR;pI@^^(Nus#ACMrW-O`X95N}Zv;CgsqUSjFpy8}Q1h6_Qnvb2N^4 zbBo|Bn51~iY|KQZ>xxyk5|o4$ryvR8omd=2+Clwcj1xLlk&@}|Dzf{5ndT~fe<4y*NeDw8rOX{O+l9y<Hyw{ZgLUP>w+xWzXb)Lcd=nrHq0fp7oHQ~yCN|GTaK zuO#)Yg&*nHH|52I2LK@ce<9_6G1RothDr&f&?nqEd!W*rM6|};UBpBNpbXf+$N^}3 z5P5zbXSzS>?YQ@Hh!d}46Te=+s92|w;{+n$alQ!n-rFqaIN&3DlM7wVSY;U!$ZjDr zUuG6vaf{}=FjN=uTt2YufH^d=!zybl6dPa7evI0kh!TsG@qa1!4=$m|acB*QZ#C&3 zBBut)QicBl$>nUevFWXUZAs<7rip^3Kl*oJsZ=iG_PZE#c5!W#hobBPumO6$l z))iamS;0CA)*5Ofl%tp(-_&jG@C zE;Xo$;Fc|Yq+De64&9LH5igyPpGXZ(u4tIYutx;@;_aoCVh`f|wY}#Bl_OorE0J88 zC>;$>Zsfj?2Pq3Zw*;!#RLj}xmdDLH_Irju@#?%+hkg2B*_D6d209pXvtRbn`!m4! zz~rUjlw)zh!vVeris3X|(s4@dhInVnG_QOMyAmf5oam$j8a>$<8a@4^k>Tkhjtbp#cjz$ zPt1IU13q7egRRA`>zWqBueUb3+hd*g6lgtwR9l|XUN%3{XZ;7J$BlJh%j{YjDKLF& z?j+Qoyx38U9NL)cqq3W5Urp_~6-^QczmDc1)&D=sd){33W2PFLcYQb(H-IwmQsXKzKD26wg;$Z`6<*tiEp(7V_NmEc@d{-mH zO1s|G`~CSq^l%7{06z^tvSjJX1Zf)~RCsv}t36~*C z#SYWjAx^tC!>WsvQs7aSXMy%iX?dBK2-Q^m@qbV}WqkmIg5 zlDOA@aJ=D)+WYtWQCt8`rlouVM2iRB| zJ%PQJ4?|6(L8|K3oj^O`sI&tryFeGSHG?LYRlvy zy#YK?5xc&}l3g9i!%sIbHlKEb<)U?bz1qhWK>!CHJd)nJxh>+;&pEDm2X+k;j*JhI z;=CKp3-`;M-pkEEN2Fo{Ek_QE3n9K;@*ewwm%0U)L|i0MW3R8%U4I;~?L5 z=l~k4GyhJ{Px-w>D=6V(uti}5maGcKkD>Ohkh^?WZyFJaXp$WX{w-5OM+<`--7iYA zJyP0w@6lq{G6x$+D=2Bihzo=|qwG=*!x^uBhDjA4_FPaCk^@?(STcF6P1YBcNsSq| zHwILt(+a-T@}b+5;sCiIqebcjOTQvQgdFj3C&>A1lx@CUYPRxFBs2&zg{CR zQpxCgT4sfWC*fMl*$b+oO2{k2X}0xfVPN)-+@vO6!$ZxH$K-%}aLNyeH9R^m zLJXT1DTR9UXMu6!(O)3_22lRt%C{%(b2o3aPt;Z9Z)WA|=1(vKh8)%{&} zQQl_%1QMc0pj%;l{}v@yg-enR@lC#}$jto#;t0>mk$W6NmsJ zi_j~f@7Go5p?x_4b4Q^|#r`sBb7i!#j*NW(&{YD3FbAUjVJ5GQO$cdK^Xd=y?}#2h zzuW-yJ#zF{6Yd`>|9=OofA7FKIe&NHCha!35Vr29!E~Dg;`uK3fi5CbEwTb=%1Kc5 z=~1KXAT*2!<{)pMc#CpIEIYgPR$0tF^qAZIJ$`P+y$R^^`M#!QUV1bcn#rtfPZ>J7 zm+rnxY^^R>wj7FOeps$=xHun=*m;!%<%V(=lA~Xa%b%{~0%7}H!P)JI21Iv^&j;mz zq5rrzHN1_h8716w2h>L+7%lX7I)Gn)t9QSd!@;lb53P;%?IHB4v?TNQKx};KF5Y7S z&$KxqU?OsJ|71+11H;^7e%*a!6W*F~0nq|!C&PK$SqyOUKi@Pc#UAN-7X@9daq>_E z4Elha_=G2PVM}-L>g9)ZgV~x)=Q9GrTZ#y!TOD^DePO*|DS+^{1?>3@texn%r%4^P zt5a0q`I?t~`dlqEyswqDgn)xaZWj2&T$E>C%{`qSDGo%GcRP2qKJXKm+6^jp7BM6X z=n!whRge&%OkTquP~Oa(XYu)9O2GzBm@La1XWL<$eE~_jR z0H}L2A(79VsH)czQl*9o7*MfZr({N)Q&g|yV@_Yuci`upP6=~opyfCWYzm90WDa37^Re* zvD*+Ybx5}E$$KOL_c{@MDt3qj9!zKuTB+;Szqs!mMTSzoi{101^~qmMC{02m8iaXV zo0LtF*=hDd2-{MN*g|zh6iN%)mD)MKS5fmUS*=nO3~Z2?5g4RE2(vp%Z4xE3Dq5k! zHoB@3KK%-nd#-bCgO`UNz86^(Uf+Q8Y!wMK5h(#Um zdrqKOCxQySUQ0Z=dT}4vj5OZ{m5}%%HK|yAe_Fhr?$sD9B*K)2>J)XNm{$$s6m;JMsGog1`x56gyn}@TN z9iDazc9@SW_1ed`51n~7XXDmdtnG*%y;COkgZ9w#9E}> zjD3>errP8t>JjrUsI^GV^+qlg2xo;H zLOnn)%h4M-&vNNld=?(l$;Oo(dm8k{@+j1@{&ilR*uiV=6Hp3}Xn*zy4mr-Fm%d6q zy0V?ALvwIIY&x2e(A>1W#x@9*1#C@;Yb5U@kc`8?NiI_2NhKk*0x)+q=|}p2^#rSN z>|w!ht1O`itD*3*lsftrc3X|r`y1w)s!zK}zVcSj3`d)O~u3=_l5Ltl^WGs0G>3jk*M;yKivtzh@~LqMvuEtJ|k!hM5(#kRZn;}S7MH) zsnx>y_3;UWSgYUpnOhxtd z@c{gT*t7(P3fQfEfdk4jj7bjIenhgkT&E35330lFC$43$T3r=#bZ;$-_7$w%R5I_t zBB_arQ`OmkIgSz^T)-S;;Zo`7eqG4?P&az*)I`Wp40IN@Ni3)b!>1RW^6;jZ)L6ZT)#OE*8~R%q&UavqZArYV2|}xkET@TDWSv2 zo0sP3A|sKdXDo!NG>z{Jod94SP)iOzJqIoK+IMoH0C#LxNku#CaB^qt&+@ncNpZd> zJ)iCXK}=g5a5=ze1XOqWUazGI7|$cIH71LE%Rg8QG=~CQm&})JG87VEX8`8GF@UWN zg|}>?#tEaLJticmO}`HWmxpJ%F*sd^kcT^vjlQ20)uUc_M@*t@{FpWlr9SZoyly`T z$pV3$I~HK`pbPf>w40k4^4-n$^lqZ{~p~g{ikObkG^y)8`WRyA?dspzz?ALdcIAFP@ zqGP6TDP4SK9ua-FhbMR*jp8^~dYqYR07 zlU24RC_jIx7b59MK*gQDW!V5*b~^xW9uJUh!8y^)BriTx3*vzrWG%!lnWM`!s{~|J z5z}?N1K+~Fbk_8J%iCMiCB0w!8D@HDD{l~!brP)c0m}dw=qDjDHWaasXe+KFd?VA^ z`UYr+V(Q}x7Nz~gCWLRD`)f)l_0&7SpVC}_M1R20*##&CwbUAjP@TZp%a)H2;8@*N zG=!uo5p%D=`9}ut6C@RuB`FfRj3YD`cZ^OU^Op2&R}k{SXj-4wIT|*(bNrNpho&}YE(<~@xH3_Eu8Q-{*IsD;#t+nZ zW8RS)$azwZt5Mi0P->yP$CzM&xSfD$9V=Ylg9y>>)*}{vBgTZIB;1)~=K(agS$t;j zEh&(#FW@VkKBgu3bc0zZm_VYyAF256bwrTk z)!2@WLFcY=TC!`J+5)+=a}>B%`ahr1FOk*_7AW-*0Y3v0MAYObW6^_w9mCElY0G9v z>?^W&jN)n_n(gRPSzq}dh2Y|$jJdc>XSLM??MOdm2#&FzqEzaLT3bfi(@Yq6#4N=Q z<=-)R=tYU2>=uFXniaL_fDG#MeD*=a%bs!i6lD#DbL^XwvY9xK5n@r_=a7^^8D)k` z5-=!~EyR3Fg2jlB(&;?|RUKXXP(-gnG!p0#TA+Gh`q8VQ=j-IFFra!eqPSD!Lw`59 zQo}>8#VSHLD1h5B_ZOOL;I)HT65Fr=jVa;~76yK?*AvNan9=RY6KE!A5i&_YRjW}x zI@w~KM6~sQpL-$yIS=VNOo~OY)LukiI`9MDtk?^O(BgcE*&_VR!BJ82<+vp2DP_WX z+%)mN-6d1BJTI*CKhBRGM)>h4=#D|Y$=hM$9o&X7Pl2rcM2jh0pM5%Q+R~^BOrnA4 z;k-Pc><)m1i%++~VV4e6&<7*ERDV6EOF*Lr<*A&I00}imSe(U=9Y-*I;tW&%oR*GV zXdW*(p&AN7tAfcxmYKvn4Oi}PBPl2SuxPPF`a|u$*ZzHWsc~uQG{OxcpMX)bJhO?gLg&G-EOCFLh8TBEZ@?=r7k%&Sv`_9aWrwozlTJQv7IBk^` z*?D`w{6eZ9j0uYrw?+9Sd7EBx4QdF2%@=twS#Z?k%p_k@rQO{1nGgIav0WDRTBWCcxID#l*J~|#@(IkmN(J8(3K8N2U`>-?R*n89KI|k5?$~*jfw*1) zDRcG>*WEB&ztn8{UG^|g`;_A_2#<)hc1)q<&+{hH5SNVEUA@g%#el!|x%+MSuOg78 z?vNf5WT=)NVDUrq0zarxY}MipD;r?j91$4+w9Bs_+;NOCFgT$Y2BD4PA`4U}8R_7w zHyod<4Dwsr*{q6xsKQ(3>wZG^&FxY9xk+}OOe30PM3H}1}1G(NTSA8VVjSO6f?$>8E34Pao@fu%qL1l@-Khm*5!|DjB~?BQ-)Na_n&6G>+M%r^M9%#L*=!iQ~qDcS`?b zdwY84zmVyfDQaZ~I7pPS7m!keu|-7t=pSUIlZ7s1Z}cC4X_>L#CBmrd{I&H#Qu6fmHD z1T{l3Sh?4svehd2#ELOm3VB3lVfZfza3xP@NNiQ~ICA;kUu+zx^EsMFw z`%>IiIoIto^JPY(jW?oRgyVw28$olkGqSBB8Z)~%mw_wN;OG`*3FeK?%Qy^npl zO~1CzZcTmX=A(@PFnctCFFdv-moou&=1o+&K~NrZS$o!bXD$cWxsW)8chaG$-^Dz( zE^r)(cOOrj*pbh@M$8Pu4%Bar(fK4U1kiZ=QtG&7^5~g3jjJ z5%6k&`7F)WA-e?2abq_JXVF095#nRISZ!Ds=ofd;?Ay9CVjhi*&zK*4{D=UWzQ^t+ z6cV4Xb;Luwq8&&D?g`vIaeMdiWAKuj0EaXEF^MIM{T2bxuGZqjowIlF=UPg@i?iT0=h!(4)bpv5O803_7B!-McR1T1(Y1N$WAz-rR{x5lt>^@#Stfmm7Ze)0^y?X3Hz)seZ^)s?uT)!U$Hm`d7$q1bN;gKs!?1e{GBw1ePNbUJV z9=~M~xn1#{leuubqO>XE3j~bZDfi zAT2@yy4voDQ2)?S@?FMv$S*uRH(alswe$&1<}mVr7E2xa?!h*5JjGR3!Zr|i0>xPZQ+1iViPgwJX70A+0aVjlCzEwaXBA--11M@C};Z3H? z%x65{-1FVuv&fQKnytBpG8kFPm}_sMB~&C>nTw>%5w~8j&B(<8CKFbVouYzQj9O^F z`Mo~RQ63r&2%MnnkuCAdz(+wuxOK)etmvF?tlLu|71rY9aT}yvh zd%0&{G{Lt`+Q0LGPDk->jj~`Vl(z)dFd~G_7hEou!1bb4S>gl)1wz6d^a*B9i7N8@ zJWbym@!5iDuX2kJ1UbLr>a{`6i;k{F<|*vCM3*{ zegbMM9!wU8E<4bPrA-Xxr(t#aw$E#tzJe?S5AM}L_t8MNHO@>CVOY}bsCv&`7%133Zi>r2oRl~_h+72kF6KB zXghfgdf=!utP97)f=%04g!#QG%lm|k1v*z`)8N;I(O(_ z|Dnn;C9&WBeJJZ6&948ia{b>2Ip`^V|K}736iV`V>387|`#r)z_|31MHqqP-_ zJ(|)}TS_6`xywM1)sk}f0~(VXkFq`yQ?f3ZqrZ;u6yp4I0C{8GbiP z_Z(=v@lf#|#536ESjAOcnK{+?*=V(@f{%aaW!gQmW4@Y7r83ojb{bo|_UL%cd_Sb( zUTb|M>gL9L&3vtN-&I|8;=%gmciB;85AV8Gs@d_i%;o*uVh9gMwN?gxN@dscgqqh{ z8L%98i|xTm4d8XdF|KJ{PVJT@t;5Mt7Sx$uGDn0HP-Ob)7UBa54X7VqH#;yDF*~uLSg}z9+lkIz#)!;>pBH$O+# zv~_2XujO9WFE_Z4?(6PN-jsbSr8iVM?2gXVnsZ8XdgG;ENE=)l?mf5ubo9*~>l(V` z+;JcHnVgrd^j!K@QhVz4aSlZW`FC89mImv@S=XOQ9ntHT@_#-jVe1jX`4{oi$!>Kc z>z`e59W?2OLew0g%j22%qR2PT(ZQm`Wh( z#_Cq)oo;kdlBoc=lr_}aCr+9i&Xv~XSlQXsx1uT)U`7_ETsO8)EtApuvh1{jQT4+! z%!JdX4U%wdk{$&nu_qMD*5n(+6M?PXD!Y2ezIs*}+ieIMo$O(BI9>5zj=aI}O8Iio zi!$`8)3v7ZixCeQ7(mBi9uM>I&$9IUgNeYHq=jkiR_oK2doIUIaH)GHni?opwDwls z>VJTmo7`IxUvb%5@xTW9Z$Nj$MwVUpJgEdw2{29*;9~~hGekYRmpr48A@=a7T_e>C z*UO6Al{JRdja{^x#`Iie}W+C6^Fa$A-4JO{&;fwb%T24uz!AZwDjKd5`;U6h&p)< z$6l&&xZE+YSh0jccL0J8GRjB4m+O`-cq$A#2uJU4EM15H2C8tBYN+n$({{Bg2#cI#}d>fG%`SNBy{SF67I`gz}mIU!m< z0P@`rGQ*=hw6tqHSO{InFB?n7m->^-Dy1Bk9y0(LIZ!P5$Q~rm2m%7)IhMPO^j3T` zB{Byy(nsMi0U^}=8N-dV z)pa136A+i|XxQ2IEa;l<6&jUdX&2dxj)hXN91BhyoL^rN4#u%&palqZSu_+F%FL)>Mu>PQ?$wZmMak2;l4yy4dfCG zVd?V9QklD;V0(Ch2Ug<4jtUPI!;3p_= z1EG0Df%shx+AC+u=dh`njL zN*w}5=B;178PL^l3t7eP&w11oB|-h)>r}-;s7Jd541?T({025y8NihC2d4zfRd7AT zG{DUGdNm78oCd0nP-l>n9`X;0_7^8asR@|0+}@NMoMGu9Tr$fwlVar=M_0=1;e*?L zXH8~R!Uqw&YZPWL0YcI8_=y>2%=ZZZ9#%9igBNjVXO%q||Nlk`hc7vT1Xwkjh^Oo)` zX^0h5mE#RToaoL%pdwUG$>6gu*hNeOd(5lFA!{?T95l|de8Z&@#cc7xqVWnYa9WC~ zz!W*u)Z4@%f@bgCx6z0%c3?tGt*pi$e{}sVLvoZ)m?uUQned9G#SsW)4tk7b$gYkF z;hM%=;T(}#K6Ex1kBeiURiK@5S`uy*d90*_IAqzqEa(hU#5cL4h6|p`Vu`z@k9hek zHfHvi!ys@O5`T@A3tQo^5~NU87SxpngFSH}Zvr7@hoPsiX^iAPDY6k>W{(dVdlF$E z!dG2eok0$0GdYLvB>Cchl(50o-4azigA;&v${dSfZ5Q$>T04;jD2|*%x4p4OBi~^l zlZEi$krC-Zd_wf*$O-?(dqYqoZRd3L09Ca`$*J%c&196V%5wBenH1ba7!Yr;1lum- zEv+>~;Kw>b@YM??(Rtc^{5FvRMuNb!2wI@7%ew z=r(^ciOruet=Mc}mLHz^)(+5`mR&&+afWaX3eiGB44Hqz8PsFBXq`jUCb&_!39&7C za9?0Y%T=Nsfgnlw(FfH!&?YNC@qTGr;?;dZt0s|42k!;@4Rsb;5IPrere(K*8_^g3 zh*k-RF8K#RyUiW&MJO?GS9Y&yqv<1MX|6O$cWJ_ti5V5BA80VPtM{AY*@ift>J(h0 zsj5OolIpONq1K~{bzT9Rqe2m*)p9{Dz|2hTj931yXeRzdb6JY1f%A-qupScg8-|K6 zb~o}WN94WGvB&zoAMhjSpfBLp>HqWf!$7sCrYV$MI(;O!)RKpM2#1q*oDe(DL-xlyM@{5-^3QcO?0Og9f#c^0 zhX71fv){UXL<|^#%{%dtstVR*s~gTiY*;hOMg5E5=g$XW-}sN{x{)YF0_7k1Jbi(F zPr%W0^JH=|mwaA=XD(m1cT?yXse}K?6=MJ8CHz#=bFzgHxWL!?{`Y%(|J1)em^Sd8 zShTrp@zN0HIdP4HXDMpF?+dE-V=b7^1p|qj!=b&ONwLm&xG0T{VQvGl8xRX;AeC;c zTvdSP7|IEeplEgL>KU24AnQo=FwCvXdfa(%W9WBDL51~Zqu@d@9T_rQ?T&|`q>@s} zW<0&$^X`g{*Pq&v1~aPjF!SSd{{(d!0!-g&zJGOwl5M15lIA}J;3H+vfwv(-g6n#GH6z__KZh~3P zRbDxLX306Hg(t?JorNFwT>?$KqxAw6mPL}tH20Y)riacEFhhhs1Q_h&4|H8O=UNg;%rbw~Pm-u%V)v?mW~ zGfx4?-S`*hq_u@jQrwixJv8RRz7ev<9yYh;>{dAg@=xZ$%d;<-I-KCrDF+bS{i;4l zN&>iE=`*nBLBN$}6%0r+Oe~+=ZdkjzcyMdtRF%@q62S<7`>T4Ot7Ie33LlzHxh|Wu z!4`ohXa)l7I5HWuFjN18cM?-}Yg4-OIX)_~xI(MPoEaF@6tY|VT6lat%K-$5AE%Eo~B zl1OO#y*^L4zn!-u=b+$^@Iu*GzU=4wNN!i4;&Ibg;K&3-@CxnctOw4}?EH%TP@;^Q z3}Puw!(vjd8-UNea&%Z*bU!AF-rGXX8^m)10To2J8+PP zX)(DXa&f`lD{h>b`?*~gW3~jrAqxJYd#r@m?}8xB+ZM?{^tfqG0zlt+yP@;0c^dSPD^C9Q*t4Hy1;BMT4y>XWu;s&G3)Meo?J^s`g9J)gaCvu_nV z1GwK*odvuCWiW&0EmPG)Qe)^yr*ldxJnT2HZi{O8#!7(c&Y40&^Tsp&*?X23>i<`4KQNuai0NoSHf52 z54e*8x9>gvXXrm4$#)_C44HegeO1mX6zY7Uzm)$KjrFAGlGu6!lR*45{+XuW?9aahrUH7tnw?Ar5~H!N6lm6jlh zJMpgSF*7_XaPDqJxHIZu-dRDLP7^otV@jXA0QcOVfARsT&Az8RKZTwpZo@+)ox+?P zn7PIT|NZWOfR(s?rBoDJ^gD-9tWprI=0P;ryxoufqCIZ6tk}VV`8xd zy7-;UdS`*c?bHqWm_9d7J86ACu=EOl923Ga*{C9=_Co8fWH!RiRB-Zz@!aR~Zp8{z zZ1{@lHkpVR&Iffe_@ZVSa?2Qlsj9Pi6Ln^f} zpu|QUF-DtA7s?CxOU1Y1`m#ozEXYX0U!M=S|2t;%9?Rwb>)+A*k3#TY9nt?Eh|$`A zB1R|wmspIkYX;BtpP}f-KcF7_KgVVL-_>V~R;I4bMkY2^_7?vPV|uam{@G>S@Ad~T zAPsE675m^HMAXPP0NL@7*}W*C;gBx2>1aPmP1OH>SoK~N#Pj^pq zYTnh|ZbXaw)V(rXa{O!W_kBBt>B?AYGyMU^KksVqn+71s1z1#S~H`re2K#-Uy@B2E8DI6l<6-4(X}= zn1q=S5FPI<6y0*5(++kzY>}vuh6$5F=9Q@_&9Yvk#TlF^1gjAlLiOwLesbMB_cZHJ zqus;i}AdfC63p=n%ecwXP zbb}|r>?jmxPq3(k=4ZrW#bFHi`AR3%#KlJhfsEXd)@~(+lzI?zv8-r0!{AD^B7QX?W?a{_s@vy){==6n3gaXV65eWO|=y0qu`aVZwFaA*p!4kIqbzj-d6Am#;9AD?=BLOg)}GXi zXw1i8IYKVEN@oDuc!LF4GE=&=N_6pT(!Gc@yEI-Bq}J>s8p}n~o<$D|e1-NCk=>pZ zelOWAfmCux7ZCywH*}@EB4|Tl9T*m%TQ<@n6PNMTcievMnrb60q@U@%16a;ts>UEp0I`1T_Z>zY1D6WS#T365Gl9 z=|c%?EMkTf6`yxp$Z$kw0t6k;j5I{;@UG0!%J0toUV5Ichu`!96l>=E#XaJ@c+8Xq zvYwLy>s^;Qb6aKeoU2wztvAQPDY3aHY0zAyGGr^|Fuy-@e!r;mC}*_s6Tlp!wGssA z&gaRs%kRRL?ktZq!*`_)Am0i+H_=M&*2@fn^7QZKvm}(Bf zm$ZH}2}P{>!=dD>rK#($88=w{&Y}RKx9fp-Xp3arh{@QJQ6#k;%~vXyJ&b!OpdEkl zgfegH0F{IV7NX4qwbC#);5#;<)uXvenpv51bBSR)pXZN7cb`4=UD-|^??t|&GqAKRsErvo$k2W1mN))8!!qFz3|eKnU|G&VZhg|%9=Dm zZ;38{eZ=k~gIR-=){g5vu8c-^_MJmr`L;8L3j0{QN|2Tx#MZ>|v)PNtviV$j;Z4lN zYq=Luz|n%&lHGwt0#9NnW(tN=3SzQ+iP$(9zQ8M{;_dd%!Tw$-H*~+P6t~;6U;CDD zcRLuBm4Z96d6qDLrp!W`vvCg@P|m5<>; zt@cU*S+zvYzgt#lXooC>`IeIS+OKt{PaQ|C2a?a#6PMzFi3ZLr03C5PG*nCqDY1V< zBL5R=lMJSLr?xv?4j-ei>8^_=%6uPOM;WdN44fp5lDe=OPzb$-BLeikoa&Q=Z}{PQ z!?#?y(qF`;iSMx>b;@hRz*F=BP${~KD&Bx)p@Y;jm^3^c=?VLHy?xNvx0Q#wuS@Z^ z!Min!_I<(pjiodrm8nRussJiL5Vnh5bTD%Z*>r>)g-7{wpG56FDGLX7O_h}-USvSk zMIh3-9fQ}iALO0t`heU1%&asSZpIQ_G!1aZ?EF-)l&!e*Nz~|P1RkjLDaTMl@m>Xb z@(X~)<12nvm|~BJgx^9MrH8qmF0?FwW>+|}1exXV%q}zS-5g@fDRa{+^GuYaVFP<~ zOTca>lufgGPDSW`<3o#wQ8VYxnTOtY_@s*Sbd9<}({t%{L!q}FFOynaxmCK{{`s!! z7Q*NCJwxi@j?-bZg6~5(AXV?1l+`CwK;uqw4V>U-Jj9~F-}H~!f|Yb(-ZEL}_Z*2R zJAXGiA=MG0guS+ABbGD>6?(L{0P$s#=LVeH$Xm@Irc+yPc?=eQ$_EekO#U-nso|a!qz14b*K}OHXb$&9LB_Q-B~b zDTF}HSsmjVUaZyO!zh_X!(2f^69oMqhq*p$UBG+{VU{lh%^;-K)Czm>5WSDoJ!w*d zi@*jmpifJm{k=1v^b6EseaqlDhfz_^P9bcj^;z{Z8DJz~drhw~z0ejGlMz~=oIjP1 zSN$~8Ta2h!l<)+h0@MC{=hqp}v1g^!c$%6e0Gd{~Aa^L}T2%*w3{Na8{#} zdCfJzoY#}ha)-j^1q0-9K!^Zy7{OdRYSt!&Ml{{<>H zel{*U5=jRhUodjCp0{l}zb1W<+oyHs@a(2pyPC-($mU1F6o7+wEm1U3EkP{>uI~f- zeOE}Yzze9k?MdvhyG^1irlzW~87m>)mBH z&0QS~>tFuu^qrID2KDb{n^_PayItqgpKbK+-A$(w>IQ8J#jEPdtDiR}UIE)JHeaQe zPlPa*yQjQEw3-3FBYt%;fMfr4^lTLm+HUnmT2+I9g8quRadVmuoJ)r{n6-*?c#QQ? zh6nI6ke`6u%U7G!^Vh2L>g-3m{h{w3UwnsUjAygVmltn}@0WOQ)sT@_Kd*IJpwr!| z9d6v$x}H5dqlh`44WG})B0Jnx#qrfHhnQ7KEHTaip8!8#-1N`ymuAklm-_j>+4;Tz zFMxZ`W`c#ooWJM8?P&HxnS*|h-`Cf^K`iIz#cDfapU>OnXnPfPa;Nq4QQ3z7@=6EO zr3)ymv))&9%DlY(m0$(LM;}Vb)=IUAM{i|Um4n>4Ceyb1yU;E8=bBmhrb7bD zYi4Tyj6&1q#f9zUPo3=NOa4qhqtCzUMzC`@Up|DM{T1;;(f*#WOj!N6|1jVgN`5{d z*ns8z?_B}`|D1h&pje$Om&_F$0xt^lZ=toF0}>*3iz|w5`sVGT+s45@+Gh9}7rk2V zRU9gCAayr)?X?vj`I#d|Z3x@r>f>%(U4Vh>Ciy_+JFSmG+Uu9WVfQyHUaobr9=hJ* z%MG5S))1WQ-_4^?^WcE_2gX-Hdb&!>$BG^IQz2H{N2tVUPP4_kZIt$tFI&As0Q>Vb zD8pn|kl>4^dOCB=q#^yi&DxDeOQ&^S1B~AObyvUXUqXY=4E~S$pPPNmgm*yRIOE;a zs;|UI;#oF7LfTmtA6zIN@eIbw@Zc3zrfF~9d~lhs|y8_(AeDiVDra!9%9Uq%d$90eE% zq1GlrpBE_<7YIRucF-xxf01AsE{g+oGpa7k9Ty4sQRMXw`PQoudNHhHo-XoKIU%&y zIMugT*3IB0TPf~wwFti9O;xmi<@Z@zzd{O8ZTD1Ff2Ty6ShZRD$+#8(kl14TtAeyp zjc{(W{JM?jR2Md|fh_#Q>Is`#>p&iHh7wu(R`00<+*i;unldF6m0 zy4)w?bIp)}6MZS z`LCgdAI`(a(@l^fJLxXH-2-keYO#-PJFPD7<{l@y=F~lC3r}UCdPM9ny6N~cF(U&8 zBmPKGaY_)d6yFQ|p{4Xr+y@ntii~aB*6ZqeOu!__;Ml2HVZ<`IZ{X(%vMcIF>h1Et zKZABVX&$nL9Q3JG?Gt%iQ%l06iSFGqZR(IAuH*8}`t7H>E&yc4dw+gMb(ZLcg^`PdW!H_{P%@dWmm1vOYB0JOl3f165}S&fhTzbf-jz) zgKUjF27X~X@XtWNkda;nBj!O`6y?f=x4^IUcZXyew9vXjC6iQLK`z>9LK1<>jry=k z?GsMIwddZ3r1VW7IY0IZYrN;!R0yCefnjQfT#nto;<49ku+&6r3%L@SgO$aVPvCe^ zOc%f3Zg|8o&HsWVhxrb)KaMuTRt*5Hxzx2iZQ!O{;LTcHI#Vg|%p-VE{U>1O7*XRAO^BseIy-Gu`x#0ss`B6ngvk_OZbN9iw0#zdqkxdZtsh}Li(OxcmX0;n9xz@~y&qTpVIyHEY{mf7 zYF+qE55yIDnayJIOP(>Oek|hKj(e?Ya~HK8r3NaD>^zMB((P4`angF9rLT3h^`X2M z_;rRq;V)hsxOw0`;!(X9gKZ-2E3NkN8?!EU7xmAgl~rf1ssDJWi{V}ir@MwaJWieQ zka~nU4i<)M)~;3GVV%(aim0}kvwg!HPGEPJ&JWSzA(O+bBYsY1Dc@usq^BhDLj1-X z5pDc+l7vBnHJ7HvQNH8eZ4@8F!MeGg9nDKhfnN(lTSW>e^wA+?I1Jr+m1SxY;t#n^ zwaIuaQ@#)ADTa4#q;X)>V3NW0BJLA7s(GSz+7y4xyFdsrU!Lre`TV z=te|2^B>gT#I?nWM4ZTVc?ASS+UGfE3kU(sG{Fmre;fep)}W@eI&Ozy?u9G>%$F98 zGiC8xJj!+TbhpOQUC_x%?@*lUZIoXA0{XoGNE*9M>u1GR$dYPJM zP?}4JT}fgw|LSeXLK}ORcA7MNo2m}=CHDDd%?@lC%%{{V*ilm3LL@|bqG{wwLN-+b zpk!Yi!Tj3p0vX33>A!Z>8YB&)3BySiY<^pbXq{e59>R>TMH2(;nC)X%Qi5DT{Ok zm|`exE3_W+yI<~tzJF>S zoV^naA4iP26=+^g4oH4gTUc82y<)x;Cp~lDU_;4uvBzxhxqBUSe?@FhcyB54Ta@cC z{~e#`Y+QFO2ZaBVLyWX~wW}|t+Sc7a%bpz#1t%P+GY;-q-fe#M>|TG;)fZOoVS5 z7!2qHP9gY!=!j9qaxw2M~}R5deZEA000|Xs(U&9B51$j00r%QtC{TycvuU2`nLYn<&{=sS`M=kLkB* zdB{z}n`FF2!_+$i_uT#^NV1!x6XeP^oo<8b(@ug{DZwsCrd>6Mbm?t z0O?^A@*bg>kmqVM1QpU90zUu|Dqzy+X3_(g3^jNYz2d77AGik>n=^i5XFNoLK4^fW z(>+`ac-DNMWq`OWg=19&jn|dLkxm>ZiAJcC2y0ttF^R#N`_5e?N*Gg4Q zx0FrKBYiq{zP*~)57KU9ioOYTflFcTSeWUo?j?i~v6%kMxTX|+QdScR7M)ST8+rJr zo_uT7Q!MiltdqNARQeX$nLR{cyT4gL5ai~KYHyTe;+wQJ$#?$R5Ku&6fzLUd+(~RB zv5h|k2Yjn|%hv#K5Z=DQE7?pi!qbd4kXRcv5q52Jsy%BajXrq|{F}HiBJ#Jz<(oGd zF9(Ucp1cTQq`jWo(sm+93_(;vD`d%+;ZlVJel3h(r&At=BT_!k@5!}E?#_6hlW$?t z7CB;o&n)ki=72W(5O;-poPRca^0}g7 zW$Jw#K)f2P+sAj23*fK`1o$b-hC7g{fyJ`R!A|L7yPvBbPC9bWZol+3U{R%b&$zj3 zU_iY-y-5x?Ge?LU^7^>;lusTupNMOHkdGOoneWsZ_}dtTxWmRo!3u}i>?4Zs3v$xl zHegRBzor|6)wY#Vfck~YC+XrR>n(zeG)e>xGa1WepVBN{eNp<_5C)6ai~P+L?3jq$mUSR^y=%G{d$x8dX^PGBf`ehKc2o7 zCN>As4y?;C&SyIJH3*B?7$|VuM{)=bE`?}89uEkC`?mlUCKM#YC3<>_%URvMU?dC- zdcVnhW2boO0!2a|zb-k>Im!lXly(&|+U`%jcbebDu%Z-(m5~7VGcULw++GlJI$z?P zV_S$h{a>ygv%o!)oFL%r7V6=&x(D=dNb$8~_syD$-#{@?zU!}YqP@DFCE_J@6S9sa zVwGj1s2iU>xJ% zsl!3MV&oa8uA923Yk9OYCY*W-5~h>JT_x4Cg@A*RutP}x>~KS2wbNvvX=FPf0BRr6 zjFFV!b=+G2d{xZ2HIGIB*dTuss5gZeNI0*Fw8kW)w2vM=8%2F4JvXzc}Q1_k8`_e}wjVlI_4Xc;6d4i2YpJo6^WEhC^ zngbBLhpY$&A!xERNcTS^+S5t9{AmdT{-(LxMeKXFx;3or9_NjaU zS5tD?#kXI|vi^IWtQ|RM1_u$OJb7qZ*S;ns4j3C8BXW!mqbLvXEMn8GX zIc$5XF}0VQJf$pd98g5QKTo2^)t5})IFy3JaI44pxC_diA0kM!8<-ui0*wq8monAG zX!1xqT2yX~mgmNp#crR8PkDqghsyw>M*aLAa~6vg{*A3pl1>=QXYdTwYRi$kSOH|U zGBrw13C>3WTrsL|{(j4~mqM>gnF@!ObzXNl8{L$h3oN(^;U~+z%-7_52zXH+OHD2; z??ZofAN7?{!1sC*izI*JNJksfW##MxvVi3$^_}~+wfZxM?6?!K8)3EH-p!P{y6syu z7aWy3H8+7t?V5+I-CGJf*6$QMYuf^-A29Mn(X2oOtZZ#5apFEEB^0!>w^^-iA?cdO z2y^76c)1i37umw!++3kat)gw_CA0}*em5b`;0_z}^ENI;*ty&t z6S!-uwt`2~pXRCn23HVnz0-Dbaec$F3G(bqpoUKRO$E$GL^xeuV&sbP1CJeYhzYpl?J-9>aU_C)V$o zZzuINnm(|#gbsx>XU@G;ZIltrtTZ_BZ1SG5>!uhMo4N;U(_FvAG0^apTgD!%!&Yt$ za@Hi9iXz^kxH2j%EByilQ~O}YnM1$|@o)vHbaH$$^nA||%xxy6F?)VW9pRxBCF-UY zm>ak+o?G%1c0t{y7M#c58$@A!rUm3{yZA~%lQJmW&WWxajF(gI$-_MM2l~{O^1FJj z*L~EjC^(_{MQ-)J2%LX+d(Lmb>={OD8TKJRXc!?mG_BSMD#jwOI%?YCxArK!*BoT2 zm-g}WOPF%VZeMp(cH*{F%Upy<$I-ynY#P^SzDE&!dV5iX_DhBj%ppwlDHZ0PwYdk+vNnvKWg?8ryPJHLeY&cyW+x18(Rlik<%qp6} z`y+iU<@n7I0T-I7pb|q*^wg{llYc%8{An)R!=^x$Gf+2FF54i6p9r7}UxjE&o*X8D zi)3B|QiNewsA6l~DP|rO%SI9y8#~f+g^g+0d5R}HpV{95FC}vjA|Sn@@DbcxLawGJ zRj`UApD8I<$yqeSJeBk|Joc*Hv`f4@u43wwJJiVvKCS%>)-9N8G=FXu^!Ex`&d?<;nO(fWX*Yqu!8*2g_eY7vhWFs%zI$|+k*S9db-H9NF=HU!h;V3RTaw3vGzT`^qjrKPMH+wL;r>B6%_p&xXrZHA zv-|Vwjm&M>ROuvP0rCa8Mz*@1={Y)>-xjj!mj@gJZ3Y!xR!Zu?;I$d-A9AhAt|!yx z$y-^PL?{e$N}UuNUYs*oY^nQ~KAoGvb3+|E>d3q}{mj236S>RR*!&YVH9_aCQ$oIjetJKS2vj$n75&X z*|}NzDDt`m;si0Fw~3(v7DVnkBo;U7`16Bc<{h+iV!3#;xXKJcneA&* zN`bNwi9z_&)0vL?;V>)O^i*C|J*p*-_bu0vPMqWoT-41S<1*}OJ;LPx>_OB+dzM*6 zLiVn}2L&CtxQ^GAo;C+}wOZL#_b3ywE>z9;LVbuN1>AM;Jf1qAXdS;rir}@v+DeEM zg;>O{_Eb81IT|u>%Y{HaTfthcJ%hldG8vy<6*b1U_&0~2t~tIv zTe~F}v}*=R3?{TqRv(u@$3Tjc=CH%}$58KZIvVmXzN55hh{jq%9YduR9J#SctI~%h zr7%OOg1dY_&p=(e+r1dXnzoGOITU>X8*1ZIALm*+d^XZI5ZJ`34~;Xgt0gLuRnhgQ zL%ywh_Z`G_2CC&X473xhH|^aCk&sKCr8!A8Ej0A~Gk>T+sWo(eMuyux=Qql~C4oBP z^UahTJj#IVi$#V?)d!zMjtHooc~8ub)C5>>I69%YOphyG<{hKh6g<9)eg^8g-@=fp z`a2j}LtJDP*Z~p(9W!$cA20IFsvn0O9x$E*V6MRL!LZRSuA*={u8phiC@nxf5SjcK z2aY3iCRXIU;kmdIz_kZI6VUrtY&fb@q4qgBG|c5kFW53Tdel+lCrxj^_=`DGx!;4M zC4dvZ!uNrDK!9cI>4H5%{)o0cA+)^^>tnYG@QfMhzfh93VnJ2`<62X2^ zzPy45XiKf9$q=dfy{`!97mvc4DwAoz}IE)O8UYKqcq8b7H7BZ`V#Fz+2F z*_<7nk3DkQzG+hzjEI-jhGQ05w(yk9JZP06=wKEK{E+RqepKJ5|4HP(4K< z%#ai%$==xvRuydHHo8YMdeIGygC;DIQyY&4M-$5gD>~hTPcCZ4#oYOthZXX&8JkCP zS0W5OiRqa+QkT1#%$RcWAmRk3v23EBrqz*dZ*az*1^b?4nN77*=s|~Kj#BP#Zn@QJ zvR|*aT4dGhP8!<%#Adc;8BiXLcr{6jQf29}+?47XXB@u>0A=U-x=V{vr{OMgl;A zhkowVzi+&w1smenJ{ZkWct}6yM0Wtu5J@98M|74rLy(L1APdg4Kg7e z@e4X#^xVcW6jo)Il&TFMFyz&To8l!fmnvqOj?aX?B48UWkk+MyEGkT&OSD_7oWeJ; zXl$(UBJF(F`OOx|Gz;QSOBo8*-ju2M&yK;Wk?Q4`%gT?Qg|!kj6C<6MPu0laU8U>% z9qX>Y?-@iy(YM|NsuUn=P0YsW8VM_4q1Au6xSm4tS_}3B00wt%vzCr!ca_AwDP1!i zk=x~)mub1m(1(FdMzI38)w-Lz{G4U3ABAGmv~A6SwT@5`HMet;ELb(BmIueE{p)`i z2<@6|O$4b=huOeq}sR`A1lB%wAod#eI3-|SK zt5oa=5=vzl`_t$(Lekhsj6=lzT2tmG?M&XhfSIyC@ zfI0V#V1`v$M{p1OC)zV2ipA2Rfmp6Qq}}&e^k`(27vFsL-`3=PCiz8qr5~Fl(m0xN z(h5XM8wRO0!5+)n6w6>5Bd8qE-;ws_=EF6 zBy$*8q!Ew>8O92ob`PN=PW=bD1>Dc`C3K!YD5p9}Cm?iavxD51Fp1_n01Sgi8t0|Z zsxT7))r^KiDCllV|FpK^KJ0}MgC|YWxZ{4eQ5n;sbPpF+i_z@5!chFtokdZTGs*8k zSziLesQJ3VV?#{x;VXsR%6q zFEIc2ILu}(cb(QKg3WoS?734wdl&umar&=3J2`?Mc!&}%O8dRAB`m1!t{Px){8#?# zr17UlVaj^9hM?B8YMTn|JT_n99 z!66`YqC58yRROW^<;DTKW(FOQcg^B7 zlez`mVPvCBoT~Fqc`^ro@QenI=S&KnnoVTHXFB=LqX@fAEl#c!9&Fk}7*@lT@)+?( zjA5Lm=7i;^6g&J~(!PM?NMBftCS?d;prk*8B;G-}it1Sxc4srD2FymbACr7)nbb!EmxuBn3t9i6cA(R4LgQDwa5g&wdAvlaesaZh%+( z7C#8fA#wMi#BNe`9R$xcdFwDAXn{K1UoCa%;hSW#LHO|1H|NiXzu(+MI>rlPekp42 z<-)y*KnI(?19$D{1X`@WOJSMYd9})=DP5sD;89s%Qpd!+E2!$;3(U$8smH z<(N~Hq@_28u5u=$0pjSeP*AgzVb3qh++IQ%)Q+uQsf9K;q|K7*#fesoOXcws0?$T! zh1{};V*d?p-c($?F%oh*_;L!|&X-W9+9f4_nL&ZcQn$#nw@xbLqhC32TT_`Rys+IK zC1S>k#zV)tGJV;9J&o{z!cOQmd}vnY3*Puft{Hw17{k@}kcD47g3OsE`6T+uY@zK# z;YA(dE)!Ho#|k`go4;`2jC=gT?yge^NJd(z;SrXzKX zmFe17eES03slNyT#wJxQJ3DQ(W$slR7_kNfSS$`Z7x1wYpeLSRzT(>m@YT=jv(ioV z3a;nM^r@ud50Foa@)nV|+Y*?BYiQ_xV ztK~@V2}R?lzWtUC9MTodHLtlVo}|@WJeAa~1K4Tq9_S5pt-!kmNh78y=$GNS)Je6h zapI`uPbsJxCDTF@SuwcNsewJnvh5CT(g1i3H*mw?l#%o}$6?CL|6<2Sbs}LwOCO{O zyQXY%$78t~%T&e1Se$pM^+39 zEemJG$^G*kNZx-67Hzm;SCWkDdTBj zJzga6td_uw^oikcsL=KsF z)d8<3VylaA4N@#m437t9(@`kd=ubrUOrUE}Cil@gTva5|{Bj!boC!skcMhz}k*@V@ z={zcoV0x$ZWuH4mkLE^{0LT-OsIRLpg)W~v0g~(3H8RfB<<;ob(OvetM+gU}XIU3S z-0$~Qq;;e5mUKml`@jXW%Hp_zs}~qOuMBJ8$s<80`f3}(rHcuO!VK`7u`u$K1$#aF zgkUwjtnPSudP#^vi=GTuS{n;RIEgzzpYfk_EAq7z+($p{9G7+Ii zkyR)~$$upI_ATivK_k%0{sBj=ab1 zZ6!2pA1>k8-9J+ZGY}fy{d>hcqX(0^Ti$~^CNzEs&x@KGn_o~rsZXOtq7;X4)~8kF zbb9e`v+N368!{?6|NUeRb7mpQ*9Q8xG#@oo^dvZM_Y`!-9~?%5>1)y%Xm&BlmA97b zV5;nVGeA^C55MweK3xbB){=Rg)jk`2W6hZ<=Uk)5#XDD;$$Ys=I_2`VRO3+y6 zt=;ODpdK<>y#{6`@csT90B1m$zcMw#h_h!5}^ zAl^Q^{Dk5DSQb2;+4|p@kwjahAF)^AC!0anUbXRDa$U0-idVK4?a)0h8nPO4{F?W~ z58{aP-Z)oHfDY-D0+Y7T+-TPHuVL0i_o!I(37aO#fW9WDIyBw%lw;H8aZ>XhnEL_D zcsww22t&zCCt>JODA&6mB2q2}@4rHzwSV!_n(Xel`LvyrtD)aI@|i~zc{{Y% zdQ@oHV@|W=MMH4r1x8>jn5&@PB#70V8RN^}k%==VsYbX{wF&(*buf;ut^Gahiz@7;Kzu z$epmD)A{7~^I$P2z zQ`Hs^2JECS)RU0Wl{m_?N-l~ zeXQ1Qd!tHR6xsQ?-QM$aUTwm$!D_Qqh_mn8>SEtxe1ZXReojc9pF79m%$bpyrk+o> zF8V^G_)^yCu>=Y<|0g+6Je_P6fM2qK+{r-hsAdGv;bnkeqGykSc9Tc|e}>4wC%0u5 z5QcXK^}&(CW^N}9*jsrva4d-}>(Y|QgL3l%)iS#T7P50W^k3C$sq_gmfeqtgMFanR zQ&NN^KVEbGnt%(I#g%V}FDn_AQ4p36h^*ANhidsyY-F{eVp}pt%*@fVx!ukwcn}HV6 z4!9l@1}`_+NqM(AImhIJuB$FUJ|RKVZ707r%EK#$ZT1RerqEBZ#&}jsqO0iXn~VMBrBf45ZW*Db!=#E%?FOsOwnkiNwMU+}3kv)Y zVE#6ze>&b-otDarjq$vwWL-AqjW4|&&IP`gBdn8wHL!01R#2dp9lTms3Q*CnEb8HS z31q8~Zg*`Y3q3`$Op;vfOPwE98dOCT(s)Uok+dvS4~M3c%7V8sHw`QZ5O4a{XU=X85?JEV8FIfNr6x3}0} zakI~{yF+(;2QPtzU@bSsVbE@SjBHO7)u%|z9>mg8#S5uI+OU#cg|k=H;X@LQRaW-v zx1EVvM`A>-^Mb)XcU9MiELs9Nye`|IFK~LXHP?3=)52LJaIG>61C4P`#Sx4DLh*TN zfw{A%2UL_eI?i5z8HP7i*I88yFa+C(o{A()LB$)8F0n#MwPKEpRvJsO-Vr#D;}Xkp zk}#p0ydh-K?xIH@WL7@kct{M9U)(}f^wb&gr*-ZGAiIJq3bXNraGIq2tz=n|80M#X zixt_)3cdhgys|nKEil(5Y#4(C46Bk9_5E#eA4dnHr>tD0#g7WcpmR!Nrl>6jU{##? zB2>b)lxKpDt9A+>pNG0;1edCq`(rM%7h3&^;QE+cIp%)XSGB0@)2I#3fQ;hx8pys@ znis{T(ao_^>~60rJXM`it|D;yM%Cqv9S!|M5$h_shE^xs86@GV-j{)aN(Y!;$gn$( zf5QjQR27zRp>zW?C@VM44n*UNB&P4F*N2!kXiF!?rH{%Np&GCglSGb8`jNd!;b9(- z2ZGR;`OhQZCNXb{B_(c3i!zi3iS3eGfub!m;+P>c8D^8v?($IzNe8GnIBwQ_#E~PX zG_p_O9;KE}#Vlt}aO{v!C%^fDnB%KSlgiG24vd!>FUNrxYu9vQEph*>R2-3o4&cy& zU_u#WjHWlc#YK-qyND*67-q_%$B%Qk@N?SN!x_U^fQ#7G#VlkaY@5s$flfS8&m6uP zKcn#5@ym?p>yn8J@M*EA1Cbk%>(|tciHl_9>B;yl4o`dhYIMrn-O}^%i@L{L1>cDu zUlkpe;e1=w?4v4sT{oH^)&}#Do^Q);rD95Y?YinHI9j>m)vLX_)P8YKvFVs~fH?>T zu#EOH6)dn|4ZXIgGu*TSCtd-THPjPN#<-=cMhmr%Tueqwqsyz}fd6lVj6k@xqGuR#aY@Wt^6OG#f|M`t_ieNe7URkztGn(rwjserPv6X>){RJWJ! zJH9Y)jwc^@#H59h&@*1oND9M9U=GU}`7CTg0dv~0{<&U@7#QJ#OFTGgo4S4oRf>Jv zH1zf@&{bj6BH-h7b$Mk=7OzWSDf;?Q075PUIz1JDM=Q<5D60y<_&gv#2#!`EHa2Oj zh0JwA&9B|7>tl|hE!~&N*>Io=^vuBYK*{aEA-u#9dH~H|CdyU8FZ0-=7IAx;0LkYE z{RT(`*y#PU4~Wd)&)($Uzdrjm|MBe2*$*$?y?7JtVX6+N-joh791i1(>KwDVt!JU@ zP-K2}4Q39T z!*s#(-?NT{A&}oai7vimXs?T{0Cv7+yk|LD&U7a!sA>9lA=a zmh$wftQi^fKF~R#3fFiMbq=EQT(j~+4sy73#=l07Fp#=2dxDmkyt*`|TO z)l|XZkpk3C3|wm4^v}g)G3974D zwJPy+xMS@NM4d%#RMDA`Jk6e|%pjEo9=Vjj3cr(=;k`iUpK;c+58(vAtya?~_}f3h z1dl(K;oFctkdrYWs&e$eTKz89>Y}Qf-Mrc1{2I{U=^ZpY$EfUa?C*({vl_c!reTo6Gi7rs|gK8Hse4 zkSOAsSIa~lVM#M&JsO2U?-J3@w%mlqTx{roSYpsxRK%m;#uHloETB)q78S(979x#$ z@;X+95-8fTB)l*Ff1%+0Clm1g6X`eV0>hsv1eZPe93ve>AIj;rM$?WD@9c>peE#%y ze_=m8bw2&D-`Y=KI-kC+ZtSOjaXx(qW^?O)cN_fJ+zPNR+#ec&=#lg3tQMbuYGyvA zbLgMw@w&Agns&VXj|~+xEW$;4RbHAe?i#&ndh-R9`JqwP<(AP|QU~6k$Psjuar6z1 zI9eu!<~WZR%meLGccSxnOuAp_#{LCeu|w+!6m`aqf!IkK_W81C^PHQZ+u(L4;CG8RKqGX}Pq zoG;SjfVLEi=Rqb`uP0;gOULfLLh8fBS&c8~UsaIs$WaNU%V-5%_0j;R596;+lvqmG z=%D2X-KNND$;PrHbA32keta?$$rDx+b?Fh`Qn#&EB|bQYFLwm#DVGc*!w1}&^-!4Q zF`YOzo8KbLn0Me%$@o5PCfG4YV0?IRjgS#dV34Fn$ci>*WO9>MXviF!yhIBh^H0c; zk8m0yhe;O=TtH#Mz0KSRv1tzDC5n-(sR5=D}D81YnrraICDb=;r=Vz2L zqK>qqU-`aF$pIABA251D_K+1C-HaXTi6V+j*l6H2*!`rv@q3h4cT zs>c0*Sv*aY121h520cn3VgWJ37`ZZEam2d=MbIr#S90J0#u@9V08>KLeT*Ogwp+Od?clz)V^xz@v+qI+#c%_tb_r7b0s6OiDMQ+T?wz?_T4+TuWt_eo)K57JaOu(54+SUuhPNqhm2lVT0puSJ^&1tg39lj4oj?PcVv)5@Fo>zlIO7Wd=Rr(nuV>G*?1 zs{M7R8gA;Ol3_kTIzv#Xbet*&=fqw4Y|u#mXz)Hp*{c>#9R@xLo^% z(*F53-d%-e7g>amYlB=;4C04o%^N*LBq*{!vdSQCV^HgknRAiqfJP9S!hZ@JY86S( zpl%b7hQXg`k}SveIi1IY{P1T|>>I5|+?8_3qs7W+ zB68Ac2XdoM=AfAA;-@jb5Ntemq6;*EOzf~nsWYmdhk4Xt-k~5TnPn@0xRYy3EPOII z(@)Pcn4;>c9766i|1VHW0|XQR000O8xQ>2NBzO6OH#7hM#l-*s8UO$Qc4cmMFKTIS zYGE=jWo~w9a&K;JWo~pXaCz;0{c{_~k?8OIE7nly5l|qUB-q+z_ zIYk95fd#Q9u#4;mN!aE4+poW7re}5*r1YG6b+3+cU7Y;(cy4Txp7O506i=kD8=-#`2F?DX|_ zvv+52U%dXq!DjEyp1wUh-0<1=uU?(LKD!;FX?O>i-<>{x`oqh!+4C1K&raXIyQS6Z zr>{=my?OfV^p zHY=|3sw`;RIGWWvAYEEyWn0hmn`CNH7(RY9IyyQ6A`%1id@)>X>T&WQtuE@($x#A7 zurI&OnzkyE6elTBA8I5f$J)?p@L2;-dGMQk0vo{^xT#sE1^lNf z+lw{m3rycFeeGU7K+j&!e1Bp z6>ubeGBJe7SM+x>ohFYuq&>PVOP#WG(scg3IkU8K8okvDrYl1-T|XCU*k zqDCP;RC7E|+;ca;m+%3N#=T5PxZtx5tPoPM&vW=s-jK||wjmqyyn=#GLqG!MMGbrg zIy5dv&1pX0S6L0)D6o`_5;?(Q0zed6jxa#DyygxT+0eEadkW^rwdW;afKGie?7kl< z$|F|q?VCxy1l03Yo>jC+%yUiNk)9<6Aak-x^UVwfHWLXAoVMAd=NsTb!eE@B(l7XK z>kH_CUnKYG%~5yE_;~ELFf~?BV&D%poy-V_>%3XdTJzB?L)kD?OPr;~sZjxv6vVC% zjIkTsuan{Z`gbtd%Vb}+IBT#6Ab0$uEn&Iv`sP6r0{=D|z+i^(IdGv+3hjibf`iQr zKWia1tJ4BleFl8Lxb#SGx%o|20WKhn6KET}P)y*kEsl=*947{#F}Z0&qz{B!YdiX7zFK7!y!S?= zJA{pY0|c4X**{t^eluL@Zp4GXSA((s>+gm4xA_aP>p-fR5!>RjD6dhyDRAP^*C2RK z270Axz2fMIr%Y}6!}9z`&?JPzD&U$k}pA@CV1mS_GDN3g}UV|9GZ3W)eB?z;M zCHO0Xwn*7nC_PF7UaKbKJ$;o|brXX|P_FaMCfQ^uX-9Qi?JAUVppyXyEgBx5UOu3_ z=4B;n+8=?*XaLyHt_0zV{F%eT&(lr*6QP!nc9tOlPmU}P&ASU}?g=`aWf8*Y-yt^? zJUY)V@}j`MfWm1)P=N5?8EX&*F`pm*eE)bppLBWyF8r9jNH84e<^C^0FVQ9cDZ_$E z;I-XkZi_cR;aGp}!{Sqi8}{yX=|O_-e+h{Y6J?)51A!Bn+fO|2cWf`(ekT1_!F-1 zKiO~Qb2N(Pb0za+YZ6%~>li-qAXVA6yn=xaWt&A=Y`5Abz4&YtGRAWlU*?k=>9_k> zL{aL}t_T){@vW!lH3?J#xC_W^%>v%_iFs*&0JTR-b#V>%>&RL$J2@EbqG8nRE5Hw- zhgYIzz~+lcz)Jah1uJD7%7(ue@H7Fop%(Plgu4*$9a6=%yI$vuH9ko_IKYLgc4NOl zE_|66?G4fE`*+D-@k{|-=*X(q8L%$>d+q^Ace{<*Dm5`KvurnOKoj1eSs)|yDe?wP ziLAQfJtaZK4(AaqU*7q5A{{tzd_^pdkrU zd+wOTF^0%ALRC1 zI+!A(vwHUCf{&j7+H*XBLM<;Z(4b&df;?wFdu+<`G66PaaTD0l%W^>;ApZL69})M5 z?)^93!oY*8ZT?fX^aozA%XY&Sx@kdU%L;g7;T!WyPMg;a|3a8=5@sDOmN7pH>*1fgmy-Baf*Cp_aE#J z0Mp2Jv(wM#Up#tbx3q1R7QXo7Ia)EtkZT;;>tpsRGZr6t0U2}B%NC$D6do|-GisHk zHJ<-2U_h`=c;%Y)FN%oq`qDtGN)oI&#N5XPfbtnH=!1X*@l=iuusi}ZfcEgQEHZ9H zgFqeYJmaxs%R4d0S0Qtp`Te35h$oYE>OT%@3 zfm*tY^%rS^L1r+gXLDwZOUB?s4vN-n1LOKfTXLORf6w2;FDHT_b5I5j^w47LrG5tN{ zA#*TJpbKddvApGz&prY*z%WMcv8RigJ66eVvPDaJ5=$*u=;gJ~KImyiQ0XO*Z+Vr1 zVs%0C5cE};>Nopl4WG-lSsRrQnJ$OFeXW|?em?nETm*W=;so2XNe{2A;dYJl0&DLwGr$7>vx5R}@KjRRHU)fP;@#Wu+!H{t8fsNfQY)WK zn;VH~MUBy%X*9he*!YZV&T60K!Nd-htG@2plP(`skL3w`Qalq5?~T3wiy zGe%+>gid*Aa+ridH+r~!7*C0=m`G5@VFam(!i>W-=p`Nc%+QBBo4FH#I@_$AIofsJ zPP^e+VRPr6n}#7^u4&YTI*kVRL_ShoL?VaW2QeSzG!`D#{X})q4Lozrqn^TPG|npc z$oJY!BSBp51LYo@s$ePwQ9GulUg(x<6nccFVfdD78ugbmc+S^lH z{_eT8WvA9Ob}x!}N>V^kfRvn|xzq8dpeFiYMBfUK^0klvoZf$R|LRou zUh>&zFYKukh_QT;efF7pEeb6V33lp5gFDdzkAdq1cF%@vp6ptMw6JfkV}2nZvHW01 zxy<(0WwrEzaCQb%upQ6Hl8543QvZP}9nhXegSc30wSZWb8=W#sg<#qtXrNBg?%~ z_wFSe-}f(xiPUrQ-ILdm!)g%r2TrinM^4PyPuwH_gQ&=cuMQu8`=5Hpt{9ii&dhF8Vz3sV~sYhyGLlGbPrcx%w-Bu7x|o)qnduj^UspM9_}=jp zANX7VIJLUb(|?|#$mc*X6{=)Te=yDv-NNTUaEf=xi!~-1;Q%I4@}jW_+TxfYpnhgk zlZH_`30vcM*J+JSgsuQ3XvWjm_-&*oH9O)@_z0U*!Z{BZnw=JL`?9~;Ay`o>vbWVC zNO5a1-Yl>WJB_qW*oENPgPqsPQtP~P=33{Kv)DSXti9HGqfE9gnryUnY3b~?C_H1k zbs57q-@Nz!;y3Z;lo}x{892yN3D&FaVF)_$Y0=?d4%@cE7)ZO87Ws2?GZ)@4xNKrjZ0Iq zjI}ZiYa*%^a>y0t zpc9@@)TWW0(AvYllcOR7g3sTZem^L!fcC86Q_~qGiHwu8{m%UQvMev#9sSW=zAA0T z06&;16vfc|;D|Xt#{wI58it89aZu&bOk3KSIC@kwH9z@LLx*g`ZE*e&8KM zr8nQ7f}KvOV+`||I_hXHQ%bnSkx=***vz(a+uRQY z!s%%wgIG7<6N}{XTKyr%fbv%ct!InoW@-~813_6_m6sHx%3V?uAPq6B80)BOxer=(xtXhYF(}cOcmF^L&GOZ5VTMo#uRCuD8=7 z%a*tLIDQ*9!dvHB5;x=o7@Lv}y)By>b`o3(L~p9&pePN^5Z*GmUkxPjG1Nrg)2x0- zena`Eq?Dl)&{}EkqzNK3P6onF+yy|Ub1+J(Mb)sgDVQ_w=qPAa^rt6A1?2$N7{-K3 zpaOBL?L`J|{37yr&;jI&YaI9l_AbyuhL7xe(W+mU47iLwk`!j;_0z(q7piFSc7&9H zHZ|W&%%hLk>=YDLAwv9w2WVuzyM;(@h2DusK_@;IA}{ znw#=V5vo%e5*47hFyg#&1r5@3&>YeQ7Ma4TDzJxVCNDwl>lsI^aSasbkoD#Z3rui0 zx*tD{vFB>f$8Ca~^o-L(B!TfX`95FFV4<2I*?D_GHMP)k(XbeEo$SC#9WJ57Hh!_9 zNIdjeup4=qU1gh+V$3_~8BxEo@=E}Imtj8ILa@vw1Qb6c?LtD%Eyv6W zDCwnudNq=}7JW8G|@XPc#3 zHdsW6GOU_*w{iI;l$$g`hZp`bzVnS+=B}P0z4fK6hvfM3#5FD@x{UzG#@|p$x~a*1gjnTYOi>dK-tMol5C<0+nLmHcg8};SkR`! zWbU;Vss{aoa#g04j<+In`i$p6wqOZqf)%tZyGxN~hnJRKm}UUJj}@ z+WeMf#{mn9%D1eanxL8w_3HbnZx0k2jl6M@&R_IQTCfyNm#FhIm1g{G$p847yPV!C z?;N)p>ymM?qg>OCYGyy}BZm=1T!+qakWnZOa?lvt!eHcBb*cs| zMXys=9mQ3uG{AVh1HnHjM#1``WK90-@X$I-(SJh2_0@Mn1n;RLi2K!V;tp*6psM&% z76m4lhg)=`kEOSC^6Qe@Vjkd(b|$FkgM$`HeAs=v(KxBnYl-l^g(sg$P27~VXBEe9 zQ>=`YkR@~MVXmT4wZ$S)V4S=eBzMaJY0hV%Kb90%*LqruY*zSghKbm7c2c1bORGKC zI}o2(#$6QlZ^=`ec*x96OCMpDzBMozRUC8R0*qBWVAzdKQnZa12tl&=Or{*ta+_^S zOn1|!ongT(#`-Qj9WXPz!iKsj&STgQH;5g3B1tipvr>!B9A@3^^xmL3bw$#mRTrj) zhAFMVDhhYvFviX>))>B_&;s7_Y`Pgk%%s53b?(yaE#_`1rFmhpK3$--&JuI{Iv1-{ zM`WWvGiUGUwp_NG%*&D~tI&{^k_BW~7^9Fs5v7<@{7iV7@w`!ciiC8UrgGQ1!W&%R zAiK?H;^ho`Lv+(btq*PQvo#jHnYz+|#GIiv?Vn^BQE|&Tmfr#Y)zir63U{=VBOkiW z^!9Dk{o2tAfZHSPSlPh4BS7bqS?s+YOxt3b48AtY`y1Z@8}~-4FMF-!exF0%=I~E3 zbZDBjuaP^Sxq1k}KI2LOHs!1U!co>q5RI5%r~71`ZNPjrE1x#q%Br`1_P@y-k@OE| zF8kRd7-ExFXwf)f^_&Axczno($t{mZX65Ntc>Utz~3AA@lH z3<*$GEN|;`SQaY68X^F=k&z(&;O`0` zwxU=!Q?uyGM;_c+9!EC}u}`OQrykq51GAh42YfTaM+}dheR?=iQ%xGP5jDxm`nFRu zCCqvb%@*snxD+kYbw3yfeMu8EwwZxD)#=a++5*Fn1yjZ#@RacKe z*R@D-LnxMGLkoJlb-Q7)OlU6oIqoZSCdQmMy*Z4FRArW;W6A-*N|{t$Srw3gcDVD5 z16+&^K%Fe<6RC?1wu{q8zqM6z@I6xzLBi-RFi>p0HRn{522$V9CO2@-E}%nGn3j3I_CBqPQS zQ#@If8%is!LZT`(6``DgNZ@$)XJ#UFnZ1@&l9fY8Qq7g_Fb4}INp96x1As;s{JlOJ z2Re#wdM76ZENb`+ zM`lBQxPFeq$P~iePGYS*dFD)=&@bmT8{R~WLW(rgfZe1;6Kvl6?Fs6%cuyqVxHJ!-(QlDWt#$5bJ#D5VTAhibjq6Baao-Ow3=1JjCgY?#X=D1hjb z2}wSmJQ|FnAAg6H?bsmr3!@xw2aLG5+~67E^hvixH{j9@&DIFfuj5vyyDy~g)fN<_ zb-L-&8~R&kl9&l?Fn%2tts%3!ivSA^d9W4$pchO4&kF`o|KlZB}2!=A7JyiQbJ z2lyX6fc^}6a{2g~J>;c|lK+7USG8E$H1Vuv%aqG7*@$`_LawY`8Q`y|L8}(T0_PtI_?MR&2gH75cNyc$26;{_> zp1mRTIDK+~NH*$@f$32+d7<4t=0~|hwVuMe3_WoEQJ#dD%<5A(Z2#7$Y-R&z=uo^; z6ih_!!xlJLpnt(_D`qR5EZgm_9xi%-`Q-g}-((N1F@dDT8TN?lcNu}&AO0HMuyE*i zLG9U{uu}L?lI*5?+z{Oh?T)qBlrBK5g9Td1dA-hbG>cvPIz=jw3Sq4TcMR$o|GqWu z;w&~&CR$a^jOA$cl?LSMiq3|&k@@b~v1=`+=zo3-2A(W~z$~>PRoX`45FIo(=v+vUhAn3CC^A?~a< zM^@TB^+i$2U{>f*9Yf!U7krGdtE#R0hX+nEuqA|5JyBagSkiP&(O@<&xjLY{!cyd| z)1HOAa#Voh=}d~5bZbhQau$f!7=w5~yr0Z%jt!BB#PMzE7IEVb2U7MX8%9 z+0~c$G|bTbu!~ZhwPrj$wwdsT&cv>~KFrk8Y>g>ajS|FxyJHy+9eY*5ikho3$%DxN zXORo<-%P4{x5=9!JRK*GNADkh@GlGV2zMunnCW;=Os2ILe&fU8%}r-HGnUlWNw=;8 zSUKz?lFZ$`MPG7laXfenYk2ra=Q2mWZct^$xuP!hEGrjt%l8JLFRV%z8P@c$6=+@I zc7|{+J!fyDWr)A(8S386a9TDO=2lOtjIvJ{eD#_95?i-S_ z2-0}sJ3PgKyP;$`@&PG?(S3GhOJeu?(9wIfPByZEwOPi6JR*C^kr6ZZFXgokD_Am|QKymh@-en6a z_o~j*I1^tk?Ub9uC-DEF>U|WNAqF{nL1bJIg~vBs=^e9fY_FZ;IaP7nLZzwd3U%7q z!ZKPaJ`AfwwL3i0S%x*m`-OAIH60GZ>~HW-bP7L~NUqI$OO+24o*p3b5uAoLOq9=f z;fX3L7{@XlkdjLDxN9_d@T6#@iQ`QZJwQdEbug7IwffRKQ3{2#%An9O#>VokGHll;7 zlv((0_ttBv8<|bkzAx$}C>`IR-)bgIFf=mbU}Pb%29qIc76f@?N-5zfF&MN@ zvf<;$-kbqOqUY9;yMe}d2*{oK_rcFQcRbJ{Fei5tf?FzkoNgglA+jXCSYOrv%uSh5 zEGRw{Lx(SDZ=m|(s35P}&8Mw95Jk4bJ1;+P)fpilTYd+v!q4xxI_vmFzhF+*$5^S8{?osOWruGbLK)HI*pMY83_&^gh?z&IM$+0IXs} zC*~+4b?lgXm*!Z=wd_|VJnw3n3z!#lKT#I>)Fl6DJf=nsm*i@6$u zejL&rKIOnaI^Y$Wb;PFvKp)7NA8^`m$#mU81$fmdxQc5x-lXnZ@+ zK=|5S9%)&n)xHDG-p^RUaykcwko$``(t{DP%DO?@I#Ctcc4gq20qRg85)R2XL4g=A zuN*;ktseg|+ic3@=bu@F`sJ6;Bway&FkzFOG?D4?pUQQSfL?Gs!u*C-Aeg709W&WY zus*`EdBPT;BqN6a?H2`=7~;I+yY`~Lk+;T|KHQe}LPYYRB(UVQw|X++E#h5M?zj%5 zxvfCoLWYh?)L*f zHE~T>y=%F^xG?Ydf9`JjpSzp>o7~-WhkKPcU5mnx+;u@-vWf580JW&IuKXaUjjn;7CVens93F4c2O-MAktROB1|>ioe+FM_z6`1t1l;JqjWS?R?4T-t0)ERH z6`dB8CW+KBz@N6uZv;?y&VTAy&VTMRCjLC~{|p#3{*7i^U2MVpCYm)SvUz5e7*v4? zwXk;B@96<6X1-xYCI(7k@*46Mxu)83jnqX7GZFEG$YJvF7S)V{HhDYO|1a zb#ttrxIy0@644iSQ4yc2ndNca)LsRq8uBxJAHY3x7-v1^WaJTP6)+66 zm~qRQ6rogL@vYal@TqqJEceE7D%gi`4@cB!GR&yWOyc}iH}1LLnOa$4cN7>dr=wJN zM%61&khK8$&@*=)y{U4Pb)g~U(YEOXASuOM3@Ev8$do4Ka+&@b)kQr__I}h4z{kkQ z|8s2%I$%!|UL4{RswJX?oK|?#g}D;a0_DT7qKsTbNTxnH-t=LvN$#PehKV@|Zmucf zWmB8NU5NTgkR278mX`%qe6FX*e5ndvosqAPM+d+8`B=U>K1uxVei`Y*?z}cPl-mNK zF5b!>;MaIJB;W0Qpz1iNZ1#qZa2}OHA1}WLbX%n2Lkri`(A>^96Y37JtC5NgK3vLP zZXt7)V<+Bi6tW}hC3j}ZYdV58Z9u#5i7ZI){zA!c7 zZs!O-kI!yW@?`qw^6X#@7{Y!W`sfc9-3xNx-#Ppyw!}?{r+3YPS5xlbi15mH@`P?M zpGJA!@+PQM+VJIWCXQu|uAg!f3Am!l_MoLAA*`o5!>nj)kx9XYv|xW9CH!K+RSRsF zXA7Q3`YkB?be`67R};m{nE7BQs|!hTay(w$HNhA)y5b=~Clrcaj&XC#2Ib3#UsIk^ zIm9ce>i<#Vw0j0i6kup~6t(=tM+scRh<6vcPtA1&YUPG2448q}A@Qw9W|)3+c;QwM zm33iwbP$X4Z{kA!Kag8`o|(2d+os$odDTs=KE76~*YK6=-i(lvYWH)8kli9Uj1K#8 zYt^Pyh+^bwC3unC-O@dwIY2RVl-DcYngaf$qRBZyC#k=Y3+S`~ZZbE>ob!R%Qf$zZ zIf=5-eHO-?DQ5FVM4c>GOiC5_w<4yJf{?V!9u(?&(hjOJa$2fl(8S|J)Hf46PW-b; zMmxqWbehUG$|rM+7Q)vqHjT)AFn>L(YLDFhIYLabhvHEss=d69UP|TB`_h!&$#N1mH{o8^K4OK;7wb2ak}n$ zod527LQnbv9uA1q)$2c!v|wBqy)kEAs94}I@gPjuf#@Pkq~neg*t-ABZFi25qo_(? zg*IU0?mH68TTY(jXzZ@0YVK+$;Um(*73f3l5X;{1iS_~u#wt~bkJ}wAwIP@zcBxi@ zH$+xJmA%G0jsE#QEZaqeIqq22>;5laJb_1`*74K(zdZRoD5r;o8kz}@+`T!5c78X~ zWWs>yNcoE=u8m(=kLc$FcZU@*q|MzWMM)}RZN}D($14#Y^zUT@`Bw1_Q@AP5xFDE_ zF8(7L`J*DFu$2mePQ3>K2e@z;TWgkGOM4qpkyDwWMgMKl))7XhI3)e(SNyWVovJps zB03*lx7>&O?CYrv^wt~~Y9G@1ao;-fvT0%$KuR%STY44?en}-J&J?D^0N8`F$_gRN z6k(7RPq+0>#`B+Kzw>TP)!bq}H$2iElp|@6fRNlk^rvpq9bOF+$J7Ce;`pAf`xpX< zVU8-<%|x<3r-RXGM0{{#tuY16H2YrzRTj^{{GdY@F#1dGqm4-9{-Uy`m@HR3GOR7w$?%u&u-l>Sq9c|EU*E^H{cjLxa91v#1YpqQ%w(4x9sS)zZ?+d3$U6?7be+?ZAWGM5%T-;rZQHhO+qP}nwr$(CZQJNN zy)XYS;=DsftjsmX9I3(?xCPyfo!z{OhNrZREWaqa&jb3BM`xajjzWPwiAlVMT~L{S z{HNXxD?*I_8^5KAdOpQkw1f;@3VI6UYFT07Y*g7pp_T$7g?=CCg>@GE){=RSI!r~b zv6JrNllE91nyhoV#pPRz(# zrnN|~k_c#-2<7waknv5j3@8?XRpq}M>KDvvmV}$j6s^WT%2tT6Cq)!p z6silzACIWKQ$$q`$W#R(bq6w``=1?y9v|Pk)S*BN(yYxBI!4M2Q~yw7T7m9Le5ib& z9uExu79X5lRB)APbL~zhWgBisWS#^N++_~h(i#< zDc{ISgn=F z?U6-xxR_F-!FoQJb)jr9v!JZrItvHO!e-#!=1UMga4C99nKS@_q2v@z5+flSrNlfbUkWsBXWYrs}?hA zUyJAsjnJ8AFZhn9xP2+i4J)|;;QI^ zT-5c)t!E?A!LQ67#&|dUiiLuEwWRI>;sv!502+`+Uf9Y~5hu%zQUQNi3KsOt>*>MW z2g+aI3|X{?_YRm}*Q}6{5j)JEC zp5yN6rJ*HMK9y_B5>I%*W znnX4nQ`d7v0lHR;M>Muli$g~9Bdm|y9!hJ?(00Zh%x_%V?YXV2>>SHSmRti-^{1+j zRaL6h?dq(&C5pk}kz`CnU0!luY`zrvjU+Zr7(0HP+9+mdvrVMbI@f6CkX89C>RuUF zU5c(vY%V`DF=g2(TzV#Gr^ZOMwscVB?`asZX7Ur;)VMg-OwqhvR#wwUuMq1n0aR3O z2S`OyGPu-UHLU`qdlpR|qJgbb+lQKsm|9)3GH7N0GjgxCZ1BG|E;9x)kH5_2@E%>p zRPs4*iPp5#{Nzd&do~Oos8~@&=|$eS&s6nsW7L_y*mPOHY4PaxP;FkFh_+EusVrsZ z(5Q)+v`(#3BQQ;fJhnA~{FTO)o!yy4&8p3IdaxThY`t~X-CnOOx7ESy&#m%CAK1#w zN#2VKW#~ZmLqV@Ww+Jad=&v5DcP)cOeyzh|AwOsH9wq3f5wAU;>B&=Z|fx-3$f~@d~St%YqIsQ^bOCSBVM5>!^nM-8ZyH48Qy%XARVRddBi# z^B@PzRaMIzzuEO>gaXAr-#J;P=1=R-P(rZh^W!U9G@W!|&C0b(2hM0!2EGX-$ZQ{? zs0Qtps;x~NXV7VXyk)3$3BS;ML1rRY8*lW*PDn3+7dwfJn>B9fH{)f;U z)*afn!_+=I;T#3`Gv7CWOpq;OGn5`jTMsJ;hO%_w`rFogJxeYKo$h87z#e{fKKpg6 zs9J$7a~@?{+uYxiHjM**%dum8+LbToBeta%a1up&i1)4Gf-6;XWoaW|(>80Uu?zx0 z91?J-K#Op~|J$Te5R6T(@l`dnU&q`o35dfOB_DjU!J;`XNVJ*Pcy{8dR?yK~b*(g4 z^hH<=B*vUAAp*ai26x?CHrkf)S~%Jl7#XJe9ZbC4QJH&{bGxJ6(;jz7X;qJyEj83X zL)>55sK>-I1o9dKPt{MeFQn;a1ajWvv8?b@BH}ca*e)Q?A{mGrp=$vvjBVg2UbzA6DCl$^7Bk zRZ9p8#_u8&eK3ClPr@lgv~X}y8N6n9av{jIy{g~HrH7$Dq)XGrhAsDiWIuRKYKx1K z+n{8w!@KBpd<>dDrQu9MgV|rqU8|haCnN4%Pm(RHDh$i8VkAoP+baJv#o!SFZCNn~-j#-!0iu{QX=&#|)h7 z`O)2TYWUBXGcl<@YWk-!d40v0Tb9IUM^5hqUBHjObT=zUfc!Y#bc|^Q8Fw%>C3h@6d_7ES$*c02 ze#r$g`c?ME8?}tam+0;%q<=&w4v>gDb%jEdKd6Uy3tZ-KX7c#+l%Y~HH`Kd`ECyiX zW>gc{2l3-H@>&L`e7~TT7aQ$Y&I^Zk|cZ(92(K@Mirpi$$8CWO;7Lm|UXtNq~Yx?b?DYie3 z;X0O%hCGHF7Kg1(51v`BS6H!!BMW=d(1p1p32|EL_Jx0R&~73Yf6eR~|zi4$zHUI%52M|c4=BTLr&Q(_EY&m7@c{BXcGhOh zy&iN;7BUkb5aqb|LQkF8nF|1XFn<~D1pvJ%8VDUn{o(r?RbU8lwTnRef_$=b{s$O2cB!{={0H~$W_-Ij;coz6?cfOwAWq8icQj&3{r;YeEX6c` z1g{~_1A46YiCkj}d2+eQV-{#=iPtO-#6#DnsuoZEKbuL-J)?2o8P&V&YY-W%-$8A2K)NrwmfO-sZt zgO1a@%8EKaiI$VrixOQ750Gbz)NB;|1+}LLEfG2+SW(+l!n!qb!CDr+ZX6roU%wEP zf5BiSu8$7$U4E#6;IUnG8xDJg%JVj zOg{%S(bSl-C!cqMm_?oD@8C*GYc0WEr)g)Ev0*Qn^fmMB%ajEj{gwpn>U>P?%P7JE z%8q8uBpYz>>S9A__?3K-baUbG#mjHGYt#A@u~b-Ih)Jn=sPu=0%TX6^enJ&zeP@d% zk;pKDAog7fLe0z!yi@kQ9FTOvRJ5~q3X157d-7ul!89qT2{H=4O~jY0O_FO}r$1i; zRW7JuG)H0HA^R=_DF6m#xxye7&B904_XQU9nQ2gXQkqLr3XTGxL=Gmftl)H)J=94*Z{S#fLG4jpR9>R(g? ziz891>Eg~Yd_DNWP2{orjQY&k-z*#h=#S;Y0Jb@cAN+TFnP(h*rC%jw)Y{-marIs) z@x^?9L9WgAH9`N{Ym)`XM4CL%cu0;efTyhdyTcv%65zr*w|JfHMP8L8Q8Mx?!!ry5 z(8+=QthpEm;0es^1EOo1L=srcJ44ef@``MUM1Pr7Mzv&um;DI$pUkzFKP&P&9R-vV z(CsESpBBBrpM&4_57XLem@tJD21ei{aPn}_=LYgs zNnUE+z#C=N%s#bkee%z2NU=mQ%0dJ@1_#;5X~8JH9RELphMI{IEAL)HF&aE?YC5p5&>Y_`!~=QYcYuLW!MtkMQPY{!!-vkj5Psrf4%A zrU)H{>XQr%gu=d5CAMj7FPQNgJRaSZ(476Mb}+Z2U+A(()qbCPF&~2?gn>7b`r-bv z{w$)(OP0*g+J~-2`$!0Qlfq0W7BQWK+7_$-7h!cB_J>NAAVABQj<-q#uN$O!G;x&i}wT>ED0b}Xbvl_JTg#Q zKM9^#*Z0AFjy<(UQH%L~Mg+zprdf_vi5JFHIKXo1q%$pK`k`&kh z!ZfiX;10a*=`#3)#LNpBOR|weV)bKEDCIutbyEBHI50OU!@#KH&LyPj}hfH zjG&GdFYiI=R2CIx5zi<&Xd@uq#Ag_u5GynqF@eKSW28ebVAF5-en9X!yxdgckL0S6 z_=nfcjd=Y-3;Tq1^BiuGeG}%at6;5vbIb)0>~Kf#%&bzLPYx%hScLG!iel6K=()+s z)2KJ8j^)1&>?c4b4u>cuCnfT?1AKB6H^_#+M$LsUXr89@DXpbMpR2AfG`BmsfS`W* z&zadJsF7<;B^5$UAC!%4><(0D&^`}=|L}!7dB75FVE0S^5@@)(<8$HN9T0>ZM`a7{ zDY-qGB(?d3nz*;-yUg)7ij-cXT+J{oWueIT9)qSf3JU2&OrkOW=Q%d1N?&_ttA@@i zBmgtN=C?}udTP@Yg{*3fm#5qqPbw1nj+lvrsmR2vcoUWKwB&T5S`CVMGR+MDG$P3- z$5a$p`u61Zzho#ZJ1&z`T7AxJoh=<(&-y{&$2Z?aT%;8ehxef+-ECof7may54gOKR z$q1Xx@ql%Rz-jiW^aiH_cCnNrYH(+&-3c@m|2Nv%6;Z;KOraQsGWR#2!;E^f3J7!(D$xu(Seknb2%V1dp8DP`Tk}w_+G=ElIJ6#j#yQ|hMP6Y?L9oNQb99FS z8gc&i8DD?-lXw7S*APN!fL|oANE8wgl1O!w^7E@knY#_eeH&=x;v{R$b7zZ{e1Q8c z`h+IN}?`+>*wP1+nSCd6l z&rf%TLDiI#P(~2LjSfx3faxt)1`>k`j5mK=k(L zIe&w~lb@2XeHV6s9+6%_>(XSK8WX5ZvW$r+3I+z@u&g2}Msa@$#aE5T+DR~(p_22= zz1gePAKn%>hf zR*$vgmqQiPwh2cMXN6J(O;p0wGtj-drSKEY#?3jRzd;a4A%e4jhy4Hn(hhuoh zH7Jsth3P({vur^z3Eo|W`ASc=LqDprPKi%KAIUvCHnI*v02Pn(O%eDpB^tuDVS5I1 z8|f)`s9?=Bc?jU=?r`Ul$exa~-thC_?k3Q7V%*AXhrQaa_s}*1OpbQ86HI<@9yn;e zxIcFGmXwuofG)j99o`pmL)9wFmA-(+agx798bYCd&=FCm4?Ih=Wf2=K{7@i{T?XK4 z_92dX0nKj)HS}JO7Zdg0hiFkVm&IF#`u!eV7LgL@+r242iIbZ`9E7ufo)(-bW&0(^ z#k|Fcd;bZ<*zBF;q9PsB6<|9TF|eyBuv_{f@)^{76j{!&tC#5}_71LRU~>txJpAGD zw*0t11jC!u^c)b0(lJqPs(p{F#T=}(_JsDiZh*LrZPbvtjog5)N}a5m7HK+%oQN*y zYg(Makw}iQy@>VCY4EZ>lN=iHt=H6M7FQfi4dDpZL6lBnp9o$>1e99&d9RDN{!mAE zI)ZBi%LvT9;qxQN+JDUy8R#$SFOmCgzW%1<82?aA8p>r6v$euWJ?ndiMnE#)KX*Xy zPQ9Kp1h>s1<+pA%;)CZMd#6*vlH*E#6UckhKz+^Fh&Q?L^7-u``>`Uk*%6|kJXtG7 za8K-%BAcabdbu$Zxv5O;Eergm83HIqW#U;wuRtXWp7|K;Dpnp^s_)HP$yKst-=r;) zH-8GZ?e~2)ju#z1FHOcO5dN~O_~`b&E5{MO?0O;e?#j#SEa9x39YBuDrf*l3sZ@ilYl&&&N(=+KuuB>&YA)DIyrmh5-SEVHc zNcs0~fD9!(Acsk!esAukc^DQy(eD%6?rwZ#Q~^?W6{aW9WJmlFPFqh96gMldPUSqc z(V|0xd+&U(&pgNny5qaT7JQ5o_`R22J>VB*(ggsVCG;(bN0`A37HBC&rwg!rwq=qw z2LFnzc9PbLE}iHf&dAw(`k{sU`^^>6sC%ih(C?)2I>$K~oW}wjA^veagCWBXPjLc* zR6XT%L8c$i+qk20bO&hO7-NPj9xle%vDdQbC9-3E4e%fx?$>96qW1%# zD$4c@U(4hx8u8*@)@xy1sl!X*fH7aBa|So)lcnJt>7zUf1M>qSYVfHzM(oS?g}`Ga zpu$8W)ET0 z#B_U#XnltVk=NwBE4paMCCDYvO$dS6Qde@wc->HJfaEO{jrS$w^o)PH^rcAyB4S4Z zZLCZ`$%<~ddGMSpjfMW^YdzOKzaGQ6XK{MN|65i~bn#8!1mRiT*lJtH5*y7E_f-!q zYi6zAu%S(W@bn~cQM}dyGw$Q51x^GIJ+Dh7J3+EzG#Lny|CZ-CD>n1a!hHpakI9w6 zcu^_~7PN`E$3^W|zmDr$Uj4$IkCmbA$=ss1{u(QOrc4|vkw3vYI;xr972=w|$>GPb znIyb4nGbsDNd&=M?;PK!;`F>XJ+>8Zr@(z}W_yLri+aSC!zM4vuz_keo%FrDN@?T< zvjV|RVeg8D4m!jT@K;WWUZn`_7144?u{T5c20#sh$BQZ(xBejZGA`i|~e9m?)`y>vtp{c-VdxPi>1BB60C3^C7 zikVQ;P%zU8*!`VK>%$8J$>RA)YTnjQ zm+5+GD*=+0_JRUxQWT|qG&LF*?QZ{R3BCPx-h8_QS!Ex7czO%`ILTZ#XzVv0BU_4c z8cYCJCdLNTWA6H1zL!KMvc7QMC%sR%>ESflbIvjTsYVUo!*S&<_+GAJJzSp$J|wWJ z|4`I4)0ITkg506-cd@d&6~C>eh|3(I37fd$4R^c00Ji3$W!Q$$D)ZZHpk~R~q;rzT zh%p_a1oh+|iRsMp3I!gfro9GfdT(~;Cq+b<}bRoCw_XlaW z&?hkAHY7+&)YdW&kof^+lSo6xc67FDyKkuGDPaqrZuPG#!HKyVYf=jL;XsV7Z+WW& zUEbmL`GjY1F{8Jz&p@5SxmL)>fkdV#FyDA>Bq*64Z$De~mHw9^tyx`h)G7yLNG`R@ z{h-8s0bKWvj8J{034hr(a$ozLC<1d@!4|rQdm!sHXzj6Wfx3f)g?`(2$t4kbS-_X@ z7f>CFN+q_y3rQ86`jzfaOzx^gVqf|!=$^S+eE@g(VC`zph2?R6ayj1iUaQ_pV_oks z@@Ncd-Fux&&C4QEG!ZN3Ja?^61TgdaJw5(!00#RjJPvjzgKdgVn;XdZ2~yE;Qt3_0 ze2zAifZW92;kHoh)f)Av-C4LFjPc6S zybXvw{R+Nrg)3eSeTJB!y?}8qw&V+kK#Gw`C{J{)xArXGc;l{P5xXa8=ve2?)9%6S z_yE+N>t3qa=cH{>i^+LApc{ecV!B9s z(TD-~Lz?2L5|WR*gFBmOI^l2MasP~qC&5@{-xEcDimD6%Esb|+nL_h`CD%ra&&~#x z0I%czJvme0&MA(fz>CFs(0$PcN2$Tyb7zvk*++q~ews74C0QP6SiJcGUUix-PjxTN zz6+mU#2YFg2osg^f2Qj_JBP|P4rkZ$SNSMkVrY}5)aXtVErcwXV0=Pp+lSD5$EOLz zd>vv*;(pq-W$tRW!V>RKi*h9KajM+}*6h2VlF0AL0Vkz6+Zh$X`7ynt;*uiOK@juP zbiyfhw)@yDDdCFlv$$b^Bgp}k%!$u(h$Q*@@$~~dFDBZCv@aiy1{NKj3ok$8KsOAd zafznur`qseKjZx6H`I+h4Jv*OAxMb|p^K#op1l_m*ouL)P*IgDe*oh{tuS=w_Ww*H zrW5UAhv@WAZK>WA$yPhuLj`etd#eAk5{Z9eCQnFDiHxES1n-GA!d>RCi6Ix1YHd(F z=o;`+-$FXaKYM+MC?ljRxO-@_M~+3qG>ch`B234>aUO_7_6G;L| z@PmQ+@=sc8p;^4_L2cNpeE?Kon(~3ffu9bn5zQrdK_fpvD1@0C3&p130-PhJ`jGN+ z4#UhK*d*f1{1ifZ=n@BugC1oIm$*(u75zGjY3Q9k>EZ;;W`18SUl(gsc^2KLn2Xze z>Iesbn5t0#hR)*!nm9$?fU&Aq(fe9N-d8+ zP&t#9HDNLc8>okOWoAzTdiz(!_n(Cqh39 z8Ya4qcJ6xJujP&pM?fotXSTN1ir2cL^z2ErYE;*}Lb0N+gNc=Sno$&d*8WsLJwEvR z1%#dRs1+A=ZZe7Zp55>zhp!?va(+Dt+!-8<7ata?fJ)A`8?*^_-1B)OKjiNH(M7>>TtHX>H=$I(>oHBIl=?WPmoCa*@?A zLs>o9c}#82Tt)Yb;ZCG_f8}Q2F~}_eC|ilKSQpl60#ysk)40>d5NKdsOYuMRg(hIzi%ADC>*Q2t20`!kd5C zuOcJsiW4|f2sn^RMZ-B6FElD?XqeSJWY3VYyahCswkA${1Nk?ogCR$Y3O;JV0>Y=}Fp9@&3gVjgkrfYB2iQ+VgpdT#_y(um&3|q&9;lPdWBr#5&mft`vGj zCF8MJrtL@O#Zsn#l6S+H1%dH-i)j{=@g7WO@)gh5lV<*MDqv9MxqVU&AA&HX& zw(Le{r;bP@tyZpvXnWjYDjX7Oj%!^N=5b0URc+rupn^byfBOlZWVS zf>vbQ3dP6nJBN$N&VUMdS%Qx<)R26JddB`aN|p;_Ka~-eBA4G|A?yN<#RZmyLPfR7 z3_SWiCGbXSQQXc*99|<9ilP$R&pP8s5hz(=;qo@)TQ~6Vb!R&iVye8zyL{EZgqmse$zT2RZfKvz%bgwb{Sq1B*wk$Bf!b2wt#1$p&pHc(fz&w5!}baxzQG=;C1?a8B5 z!((@FosTFHVNY7zlc30+ckHo!UjJfImC_*bk5aT?yNvl0lOwbmrqXQ#Axy;r)M%ai z(&r(aCWkZI`84bFV$I;2OWff#j!nSWpt&(xEs;CJgbIFvc+AEFm}P}zj6>9JIvgIK zPT%h%3nBe{bos9D&sUsVNg2!Vt(XB%gDkls%e;8mAiG1+h`)C;DzrEy(d)`0GZDFw z%v`ANnQlk^ZI%u7`X7nyPMLpDlmkU0)Y4MEsRXq)q6sYcZN;E0f~#XAC5?kdttno- z_s=u7(;bC4)8g9a8MWVVmWhf`3gPJjzNfvG*j|n+iMpBbfN*S#pwdhg@RFB89r%*Y zmFJQK;6*8(XxdchzurmTa)MMBj~`$}eOyG-Nm;7!De9bSlc@dN`_J)bL6Z+J%JD_R z%#IjsC)^JW{*#Yr5IRc}JV8h9Wn;c4J~7=5YuKPS9ACDAGdKt?=i6|{#OMNdi0y<* zBF@a8v?M^fStz2p3lD^g7v_y$iRY7doYrgfE~*CwYliyMehwtf(C>xuM!}_tu`d?i zQm-!&wCuKvPI(kVCKl$ygo4m}7OZ*=|7TV6z4{e|z?;XdzGg@7T6# z-MVMo&pekBjy>eY73RgCeseP~HA^)6{uK#jQ1HKT`JAEIZLyx)GX$#pmApjP3+hvd z53B~`Q#2itY?D}EDAAxVmAaC@tbFhtDokrK4>LHnM;gPhUGIY^rQroPpmL}95XV%f zrpQm2&K*6^JWIP|vdXOhQC=;teURUb+b61P@4tGS(xyF&$Dsw@4(IMjxQZ;uisE2z ze8zQ=RaDs}YC+iHB=|O%jX@N!QD1W-CJmFo19sKG1*9gwjg`<|rzTYfVyo7AC%1#> z11uNyXZR21`!1xNm?r;A^0B8CskFiZ09erh0HFTQm^CyqGB7eX`ESBvTG<`3K6d$m zUX2jCUXibf1aN`O0Bzl%iZ9%tW<75TDXcdOZ%Gp?qEr~`Air(dnTksm7Z-2fVm=#4 z3>|dq9W%LpUQkTA5Ul*oZgF+{r1NIVnmbzqA8@uQQSCO~DnbDuQJ-~kw~HN(q%>Ls zw?O}1!fddTB6Yhi*K*x=3*3n~WuJ0UNjn4v-tRm{MU~ug9JWAL18wq$GBB2)%h+Ym zO}*E|TA*QMQo8gSg7m3__ZxE8Nn>=As$Q+Od=g^K(s>!bgDV7trtrYly~sg{ym5Ad z!fx_vh)KXuAGm=&C{9#;RQyW|8QKL*&xjvvv^=oMrr#b z>ozh|ycy!85%*WgR1U z!s`7A*=$C;C*xP`4&0S|RakR5Mj$y8Wf87<+7=LWz(&Qp-omqb;ACa8fly;ru026ohnv<2@6UY*g{Imb%ST3!7LMdMFy zCcWNgFdY{Wan`FJi5}Q<^?fpw?c;rFoRr@-U3ls;q)SzThoVoJ9;z-(3AKy%i#srz`ezV4s5eLZBCaAV486G(ckhxHg~9~U%oKwU<5$tfll z=ydPPaCE(dhk@D-gc~IoMg+5K>NWk)zEhwa6T(r8fIt4NR)xa@@1MD7sK4pu_$DMI z#eX*v>zS;SrjXzSMWqwud7rb3VQrx4qGHhY~Q^>A#> z8hP`Jr-5*X7DK_Uaghq>YmZ^uVf&@~i{ua=$PA%4ef>EFC@}Ut#^0>oTVnSGn|L7R zLH{0VFTowCZ&U@K>h7_((TmLG5!4#Nl1$;>Dd-JZ3;w2d{kgGaeHn1PZ?uzvC=rTf zLiZQP4FLghd;dJ``umPDcjCo&AtLLo@^IebNq*NU1`^ct3h!0G+DBkDFNJD+0|t_8 zD3-uO2Y&dAl`**Q?sbykQq+41J0QOlb430;ob^~Ed+^Q`qTHF1uak7+clry>9D}Umuu{5MNrp*reIdTP%x_y!5>_`1qxHFb9b@&CGfMyhlW( z>t}v+=ner%mm!ki`q;7&?lW|Ya8a;?b=;n@8Lv`T44>PY<}bvOBoRY^e*H9;d%9W> zRGbL%P+i%87Z%RF&2=!s_Ow(lbg%1i1Dt(!>SBa`G#aQl*GRA`BgoK&KPcIiQCSr| z42F8am=ugig%yoXR~teeZPTS)uL^%l0h=5iCTM~`iiLVZ8;uUwT7crS7!j4E?&>0t(llp&CZ$i zsK~9f9~32xZ51Wi6W*Bw6Q$4K9|-<|!CaVefM?`faRboD*|}rbtmr=Jb^>B(tZ)wr zfc2QLZB~wQZmY*cdUp&42n45b27Myj&svB4y(O_k`)8uCACb+xnLyMrVCw<<2S?%s_KcWPef|CJcEv(JKPZCZ-9hom4fU}B~ ziFU%XlpuxdA;W;EZoj0O+JDY5N?PKY8-6oERHcA=*zh+ZH?9a|Pb8y)31Mbs2Ix$J zhyR`|4;|IS<0?g-gXF|EuP=BKK?b!h&fgk9$6VSS6PDE3v+}|y%p%uDi~@R3sy;m; zK6Es~)>uRz6pHCQ`LH?X*M=q%08FZZ1OlRsiT${B5bzm-#>}H(_@gyP|4d%Xe_{F4 zN1Wb`+?^qATKCW+Vcr}29;R2Gy}Dt39;1bgcitN8)nyDho%lKL*h8*U3F|%^UnwE%DQVD z@MGH_ES`8RTaU&pt}!oGFn)Q;e4SY~;*D0&Ej(7Dfjo5TH(j6sM~6txPZFa%YN-4# zEMtGF9&uz z7z`p~e9KCj{y8gH#v`5lxKLKh&YUy~Cd@Ie-@O2?@$vxAkzk&7S2_+;`CHM`RLJ;Ny}oN zXH04_P1kRd8js=-wdJGjTxCrWa6@_l80T+H8Bg_JL>!4H{gRsCd1=PA3lhss5ac4=Q>^gvP&jS0Aev3R$&t} z3-f4^Ml%BMBUt+iTI}8V+VLk34w36Yo>m96L3>&ZF+=Px6b2PTl*4J%7J=hF%P0k% zH{J<=={moho5CM)`E8MWmO~rQIDru1_!>smuJ)hZ z=}l+ii9%=_ICC~pM%0MZ0M9d}M7AjLqmk&d#0EMpQO(cms?Nb_IyH2Azt2x`MGMDW zRE;#(BH*>ag8q;YaDN<5CHWfJ?0kE>J8{zjjH}}kQ}8HtxC5${k*z=+AITrgg7rCw zU9WM0xicE9;yE0dO8jHjLzD5wyFNc3e++??LdrmtqJ{?B?s|Qn_63OvQTZ<|jR4DB zQFs5saAwz!kx>{F`^TaE)kFRMrFkynXo*ANc@-FTOW;iwgK?Chp>v6P3ba z%h@QHO)R<;$pZo({v3fn%e>*fp~bVM67!AqgOfQhOwUnvujE*eHT9^7c|UKE(tn|V z-W`LERd=_4d?mj@a+Z@7$^FQnKdw*wr6nj*aOg$h7~5`H^Mqp|sk>4tcuk*!qJhpW zd~c)@JT?_u2jxFv$Q5&AQyCOsDIgR{q!CU}wxu+#n9B?TbS0wnK??!16sbRQOA}>u z2Q$)nr@{pe(v79|{A=+~n>ClW4Isp^El1BJwsdH~cFDQA{Ji*2p%oPduEY1Hs%$Je zlC;@zb^Fh>q;8tLQ-(Y{D6!}=|+$4)@J~o z1EE6)G=bLp^B&8ZHducy8)>H+82+s=M)BQ6zD=+eGvD#r#%}xyeX@MuC$71|4b zXHyS6j6=;>zow!V0hF91zR89$>8XD9n9}Ta-5)4D9T)PV}tO;bD`a7 z@U%V8ZY5@Y0#2AncO2yMdq+GG1fr2Y!*+yr8{MfydrmryIj9$?E5XGjH$#_lgcsQ{ zuGU{N+XLtLZ$E1Bj|qPo54S1?Xsmm;;7cUQy3!tRrX>Y zdLlpn7hR(tSV#{c1}J5`UxylPsLO?r{-y8&Yv&H$;ZYk5V3Z4h4%a+PZaY6MSec(S zax%2K>Q8Zopy==QvNwZU%!@|+@kTfJ1CZNLac^c0@$F%!1<(BbVrHBxT5j+Fz_`X% zNEz7=I`lbVe4=k|DM)@9pSSS=A7%PCO-VS}bw4TtR-R0*!I$NQ3_A(7OPX;boYS*e zQeZfHry808ELu#d7M$Gm@d$2b-&+C<$S@l6ZxEqIjO%sXLvfiy#3x>H-s=~&_4$BW z+%rkTEj^EKB>G=pksrAKyHLj2amj@T0st@t0RTYzpO>z&iK&5$wex?qH5(-@yDWNS z-!nCJVV?}dR>>@7kxgKkoXC`U==0VviSa<8Qxt1ctQL*r-`*h>0~k1bpERciK2zfd zTLHxkhX$?0&Eu#num(pGsYBulYARC*I;sk21?g*ihA&7@-m?(E5^&#}4+a>bLFSGk ztG9``BtSwY!ehKv;;T5kTCX-h8&NyyBKN~tW+o>avfIlnLTPuPHf8Cp zfi~i6yKuz76!}Epcgcf#M*eTg0$B za2sF6YB9A-3yHk4PKzW#5z*mGD9{5C+b}V$wpzdX2;SGM>93E}`A@Oq?w0U&ygZ7{ z9Q@ac+@3OhU%b&{yuC;4M2t#Q3=kLJ#s`5z1H zua4=m9CFPTm?M?As1+&$zkx;h{M)FCsx$Ae$t==0`5SE=?YWGVs1&sq$N+TKamQr_ zcr+nND<&mL*esz^3@y2Ta`oz)ML+eezL^ru)~|f~jp{;nDze!>tuWzA*r;YQ}s%%a5s?416mW9#A z>V0jV^lEvw*nuXiYC5mDN1s~Nu8S@Tb$e6iA!0QxrpYO8rCj5 zLst&{`v8;HzoGhzzjht+wyi0|N|L4Otgj+71ooY<)xrwxOp_Gp@ic(%p8HgbR7pE; zd74sqfz8vuqo<>0Pz(%L z(nqdOv_0I-RCpxXJ!N%_^xZqMWnTiSKKuA?z{Od*?}YOARgt;n4MZ9ryyXbSfG(Mp z#*WgH5}4~5ncDzX6-Zrg184X_7$ zpOA1v?XUUVI(e{tLb=EHGjm*NP*4-Z6LDa4j4BAE^&FVLtENT+7aITRD`uKnCl+W? zGY?>P)n`73_}+}UqZW}X-xpAFm>@=!Sbk#=c4xtJZ%2W!9ITcg2uFO7WNnkYlfOBn z7EiyPZQi2H)KUSlhgYx}BjfBKM{Dea52h}Jr*ATW|C-)0am!=7c;A7jqX|$as*HPT?v&@pJ7R)P6UqYxbI{`wr*Z1hOYYJc*@4K+of zf+}%^Qey$VMibxQvDQp`>`Z|Td47Fmr2Ly3)q;kroy!|&+!t8twq#B0cZtRoa(<%Z z^2oC+6Wq)iSKP#(7DVeQFVfA~+q0#OlkmJ4*BwW`NDlF*av|VhH(lDCm> z)ILbP`vPwL`-~_9J5PZ)p)V-e$~}bspesy;?ns{u$IRAiU)E!8Rs=gK%xjVb9cZ$< z68e9Dq#5^|q;qTkzJA0nY}Uni+0?f0nqo}2h(drJvT74>$;+Tj*&nVbt{TFgfTD!0 z;js^Z%jo+kdn}LSFY?LIq9f$F*=}!$8K|QFN7g$w3!{Tuw#&9{+qT!cY}>YN+qP}n zwr$()eQwqL(5LeoQpuClm}43ZA~b-W;!^iMV<SV2H@Z`{AGuBehlhLrdK2YwCfC0S~Vr&oKov}_UZl`+Z9c%wcG?Zbo zV()mbcP%k*#Y*oTvxjEPf?~fu5q(HVD9u{e60{{yGnS&8JbcaZ3n=#ImTvz0dUS0l z?K!i0PT-dIr+@R?`O) zBpF79^fT0Icffc=i6!W^c+G!%!{;wu$R28LK%u_%9Jq!Kn{&M($Vnr5XJ|~NUNc`? zl6;n3(rBhr0wt5E96r+rpvSk+M-)+}lK6Ke&B%eBTNGdwG}@vN+zd`gH#O0h^at>N z-*Jf}*FP_~003UD|8Fka+Qi+&@xOCvhxf+uh%NE&1tr|Ome3|+VtPeo=R+*Rg={k0 zj`v7ot4YhHl~@Uhgt=6LR`P>5W83Hk`Z`L-?I;U`(j##PzpRo2Y2KU#E9O?LC}6_? z+zZ?~b1u=^VSIJvdw;K?ch+O_cA%1d>=q=(4&5 zuCl&tQBUV#%u<`Th9m~jFZ(ftIS_iH@u{pj5?@@jph8_uvT{InmaiwKtgU-(%RuRS z@RUJ0n;{W8J$%7PF%SkY>B(>u8YL8RdVu8Q{e`Xf%(_Fi3Iq(6!`(Fx#e?klmaxJW zQVo-ybZ|HQmmSRq*5z-Y&j*f05)#5L9hM<@KZT-8&`Zr(R7JRKfwcc5ENGpFVI3Ur$>{=MK~k zuCA8ogLoTS?^)yF&xJkTla7f&~^X^Da!~Ak|HJ*APKa(3sCE%e^~N!c+^v62881W6_$93 z%{!>Z38{j^ZbZp71B+ z03L+c-TC`==wjpiX5k~;XLQdGFUQBtlMf4^$V=tHS;C%Ryv^HlERk~@ubiRcY4Qb% zwAVPVQKUQu6Cq<7Io{E-tbI4{@5j#X4_iX%?}e*t>M`tE>pS2R$n;+|izzMjO4aq* zioZ$6t;j2vfaqlG>>eII`{#_lgZuFj6W{yC`M%%i+T#>E_#b2M?iFD+oGsR3b#6XO32%B zS5r|NaTQxmzvGeZ5573MOE|afeV#WD7xsqqKZ6{{p%Ub>mX+BO>Xr*nKg+pwCU)l6 z-=zqhCRvvma4(z;%%QQPIM*2}4GotvzlN$ua2+SrGwB1z)9Q(g!r6=_E;Fb!=Ch)= zF&9Yc4+dBu*B{S9E4o;@-Zn{)CthZh-;=&rda*P79R&;}i>cLx5Nh=X%%O*{ zsD-YD3>A9Vw1ck&udt{3NZ1>6voZYLjpHPPm6tMnaWirBGB(c>6^rycS=qf`hwq*9 zorak*$;=?%^n2076#{YmUc3H>X^Hu~xY^jaUT#cQ`Q0(mz+EZWs!%sXD|76(jRid{ z^QiZNP{aalV+f-o!5OAc`-T1xEHD;B*t|ej2P$>=U9x12lremk>FL+E&$}hmnVch$gH=s)!gg zteju{s(bHU@;g*EmDf}78)QxT&|J?AW>n$VsC%2&uP|vX`h(MFcxTLW5RKOsI^d`L zN$CP6oJLbQHGjMmldjTh<(FnN0722o!M_!gVt3<<5;~PpAyw_GNai*o23iTh$;0{n zt&zU=ca^rj&UKXs`|>GqzeE$gj7E5Yu*@Tyyd8(xty{uc*{i_0%Qb3skdn#iG zW%jL0f9|~Qh!SjflP!!yLCOf19t;%$3|MYrW4IjbU|N$ z|FtbbyRqxPwOcGm9}Xl)Tw%}t^wWbwLb^# zFkLt4;5a=i3#YegxVtWd+W(yFsCZ>Ix*H?7iC);YRO5aX6T zHCmrhlgm9|8&@=hxU`YSHf8NFm)q-k# zoYBnUM6t6x>|%aBtGaKkQtIO+Rn{j{!$TLiL%F$Jqs5JDXC9FV-OqI#mYU%sgIEVf zlWq{C))Ft@CkCxfDz*-mdQMg07NQFvrEvH5Wk!;Y!G~&(0$Y%~+{&WZfZ4)8q=}I) z7PGXijtGR%x?p8H<@W^@y(x)j)!*zO2AZL^uDS-voA9*pR~5Nxuvg+VNb(LegmJW6G8hZGQQa8H5AnCUWcc9o0);RpehE>yE( zQ+>EcKr$acHYM?52@gP<9`R4i$sYNLCB->YF#Z7t{R(ANA5`%s0YM@H(TONkUvwSR zPcvqob0(mYg_0VFLGZF8^;J{dNRZM1OB0O6-V`oOzaTF8O@?s1L0^-@KGRuKzwnR~ zqo!^rIihD@tdnMDM^uHpwZ>v`Ydprd!?HK3QHDeKM7(^(hMi1-#fxmFa*)92&ey_b}XL;0S^p=rRX1?(6h_tJ+_O|Zr)4Fdo$>x(8irV@l zI&s90LT_7^t7EYt97HaVJ&fNMZnqmxHz(}iBu?$jeQ{y3U^dt0cm3b>WLgRe>QskP6J$!gb}%_Q{UJ${FZP^l2g4G^KV)@! zP~2@SGpVprjOnA98R#Qz+{ikSo2V>oY^B^1Ig#AaA_@dBiRmbgx`KK&!mPPiAcT3ulI-`Fuv}LFeu@am26M&U z-M>5#XK$z!6pDne;KrIF{xgz+>q&6k; zc>~v53@JgFn_%ZpWrej0o}jPH*dT=r>jk+$hZQWp^(bJ2lqYQk(@23Z%RX~N4;O-Z zA?R+JVUx(O)WTALnpAr=ZUZya><^qQ*im88K?l8`+nC9qrHvl9?!YCq zw=edX2%6VHHlCZU@+NJEa5NVr@CgVZs)i3YU-t~fX7(Z(qx#55j!h)^JEA!=Pk9MfhfC-9v979;j^-ARK>aBtB@2j$feag_(pg-6+u~ z?*QKgokeOHMk1fNyU5e`6nzX5xx!&DYZbtzDN+&rS2Uer!G1(N06=x4s%E7uL5yl| zkTrjydl`*kI`=`_T!BhYikEwV{?Log^f8S~Ghft_!eQ z5}}X?E_j>1Sl$Vy%tKLQqKzpPlBe{HiZ5@a6g~m<;Ly~s``)5Wq`LwNe@hTgP zQ7FE=EXyY`I;T3Rnah8IKfA7}q7n6cfG|_r+G_#3l%`cf(ceHS?>n0QcI#M2CPF&~ zZ_7qxSEIEG=lZ6*(Ya^i)|raE4LT=vZK2KqNW!4&H|Sq`6K*(LH0zr%?Yb9p8c;E3 zf?Y$mQqIau!Vttsz9m`v=tM&^iMC9q85f}J0u&LX(rzb`m@+Jt2cWF5sofb3qBK>D zM^xGPnBv({=8sl`y3#Pms_m3qI^8c7QpExKAaroacJE~h<3{_V#So)4|H%C<|K;H- zktNH?v5lt?=S(^dtWgdm9q^acm;`XCm1`8l8!G7NaWjZ0Kvfikr^LOcKly&<$I1 ztOi;)66g6ZF`C197&tk^5T0$)1??mbhhY*1b9tGeUKv_H?wFCs(Bo}WkRUkDxE^^j z`)(hgGqUVnh7|iTS@bT1H+VUAXh4nx%N)4Cb@`F|ccDnWCk9@iTPp!U5 z!GQ{RB#^S0gd|nJR$DFOydd*<0G}*^00GNwK!By!Vmu$LVNnlA@|rcpos9Y*J(P0) zn=;u&UN$lOWx^gYBIcO3Wi>&Z6DGRbx!SOG3c0f)1uVX;iG@^j0AKe8VW{-9$^K}W zByqk1G?CH<9Cm_W=geA^)-%Jx3c6ZA{u~YexEe4UD76+L>iPX}@+>cSYZ?;pu0=n# z==qmOEO}|rke5_!S;xE0-7R3X`UPZIwZR)oJ58av-#J(&DHXC9y3?|QWy1Pe)$lZt zT?%V!NF;7em3PFOrt^BDm>nF`wUgGRUw&ZrHKpE^mZI~DnD&SeRI&I6p;}TY{S8GN zO>0+3&m~t;m3D&^u7O9LQ0VLrE=tfN8=d7bi!C1S;X-r;!hdGP6sqaE#t;Vpx z&c4EZvfT|ht6QM7NYG;4&;H}!aR0x`d*I6}X(;7mldpi9ZC=pY#b#{STANnGav#b- zvwF_yr%6-iVKQ&5Bb~J0Grp0_CeeY9X}DE>d)i6&;BYH|Y=2P~X#T52o*8C&B=_9= z_@qTg2u8fkA=+xr5R4)h(^JWt?p;zy0^oq#hLF>j+xW}m85-jB0?r-R;hG&`X{ql2 z+UZC;GzwO9+l<=feKpe#50jw!A&3A90*y|8i$g+)Mi1$d9U2q5jI`vpltivEk&0;6 zoVYr{nEJixBv*jOn2HCY^*Sj)s24f3VCZeAKGoDVviNMPRyNUj@#a!e7<6FdpN2g3 zhQKgd5OaAUk%??g4<6t{jBGZ>AFumq_|27g?Q~Q+Z6BCnwisQ1rhd6(ASsN(Nl(i~VesL$2i6+#k{iL>n z^*06Bq20&_S~(HQ2KhF_`*3`0;|crT{BA2?&e7#{Q?ATNdcQu>AAh>7ZG-8|_iTPk z253#a+F9#1h28YeC6@JPh1-!jzSZL_jJps{Hu~`GPqm9W1l9#yz}S?V?J z=N)AI_${I1!bLlAe&iXs$)7%#8hK3}>7qPZ5Z>XE#+}PvgrxWEQ+<8Y7dTX6r6q$o z9_zKY4#y{pbR_MuY4vFu^wZF%I%IxN&)DD~ zB36_C7_y`+c22CMZDbHxEq8pVoJb!HhXeJ>5#g~v;9h8@Sx>%@+}|Fc(yGRi;<*F* zrX-}*L4yqSZy|uL7|TuMkt9F&a26^S4h`-4#AJ%S$`4l|fhQPqC5^gmS3CVt>?jyO zTX(`pCT5OSwB?|Rhu6Oe?AwxrutLE&i7->EG~_V0WGg%P{WHDOiW7`D7%3@M4j!;W zDYJ#CVqu%^^iq_h9_MD)h|`pQg2_JyWS^=3YsMOpIV&=9N;%IhpD-sGxQyM|8k<=% zL#=hDqOcJ&pw!*H)rQLJzrohG| zj-$*nu{Qt$Q1Cbcn81QE({XQtxdCH~Z`Ee4-OIz{?y-Yc7ujFvPdi9nQYsmE7i?f@ z47qvHy5Ikw%%H60Av$Vwu@E<0u(jDdb#l2p!Sg#VR^;1TJr$bLl!rwPc~A;NTO{GW zf6t=p9$=J>a-HYkvA@bk(7zQC89|Z_?8hN5v679rtcX320o6NWcKdfk7!kR(i~ zH*qvIe|v@5*8L|e7uULI-dFrFN>WAK_GWWLTcA=0eE`0scFLP2PsZw<<5-L(JG$lE?C94kMJB6b6g4Pq%M`kiE+MUiF>A ztn;Kqaz9^%$e)A`lHJ0wNY!N7ZCiN+WIKbKOf3QIAxLO_`hSy+#$(J-F-=%uTB>m5 z#jda`rEE$quBpOmcnUkUyGV&1>f5k5cI`1mOjp>|5{!Pl~XP6!Z zqW1GGu1>bG=XpThN43T}%${ZN=j2?c5?n{0k>n?h;;xksP)`PnUjUr3g>Y{{eDPqh zmkqpF=`THQ)lC!ieTOno%+igsq>EBwy(VV#DU5p{y=B!##w*sfL=!qG=CC8B+j z)XpNqyHTV`{$YVj^tp4k;(?{M1W&xfEfUloKppDG6`d|MeqsvCk%`mq@{I?NSyq4h zqGxAr`OU*WAXC3mWs#jITd&!*c*y@cV7TJhF3{hUjr5_3V%9B2RcvFjX${wkp|1w~ zZ{QhhM0tux?J%{}X!+(*W7t510*;azE*l2}|EqV2RI7u7*V8Fdr?EC#C*pl4+_Jcb zyEy2Zm1nHiHZ~lz*Ge>gW|@z3U*IF-r897=H&AxI0a+e1YpH)B#gx`SYaF@?*FAw8 z|F{?~N6)e4gBZw`8tvt==3gdH>-^H!2WKXsJW&b7dSGIqzm*KIBC{PJXOuf%yml)~ zzGiVM=v+ARX3YlwB3nFt7$NJK_5{#3s#_0Qc7FEPm#CQTMecpYyqe>D0xYS^;6|#Ql^-pM4z*^UpZTQ;S@{9H>bV4HkwXsv2NX&`GX-!w6 zsz`^|G=oc7maI2qW8fC{E%1g1;JEF~w8zI7{^D_-~S%%5O2>NdZlqpkUwi-B!Aha{t zjjao{2-5H}x!9I(p{w9~0xCRfO&FK8Aw)u9w5pqF)0?~Eia5RGbYi|q#i+w;C(U4^ z#wPx=y~}KG%%`FDhFIhl20u*w5q3fKYiW;`;+gPw1y%mo!*g!q6i3X`%Jy|OS0G*F z@GsTo0*=;R79t~=UV6RAW={-9XG&sNm7V5p#=7K4;3g}u_d-??1h5$Gb4J)9e8AGK z(l+;>8lH*!Ojfg*Uo-(xIc-?JJT~8Q6K}1Zw->QbB-I>&C<&}v0}I$ga`0SxGqWC( zPVFz+ntfP+VLt=VO;ukj+luAac59eoL&nU5d{sieg+!c~8&hp7;%Y*Z9(OXJh3t;- zeF$%`)|>rD2(Px?3b5#!??}C7xL>W0fy5VaPo!qqR%Mr24&w&?7uIdm&Lik0Zt*X)5xuLX4SG%ku>1naNd*`mHy*ZjT>LAn*J;Z*ZeZP(0;+!yQF zXW7rF)6Y_=UvMnipMENQp)Jg$nHF#yDh2nnK-Z@o)vaf-8uiu`u(!PfMc^A>2>%%d z9nhD5zuTNOVwq-QV1WH^y`@QObO1D+B)F1T z9F2)nH_~`kg84TYu9T(`m*0C9M3WH z3+_doJX?70rmT0;+_t@|QO?b3gD+Do+B)o=3))TJg0USk9ijtqA$@n$T4-e=p1`<%g= z)g%_m5TAbXP!=UomRQ+i@5qdWdtKJbOzNa+um&9ENu)nfg^Y8vc6$1gL(o^w9f3H^ zP2~A&k_T4j#~ejU?3uIac_jhj+S7q?R<4s-h$HKID~?_LeSP9l3?? z|3$HoA8l3lf&l<9q5=S5{x1~D#NEim-r2&=_J0_b9d(=kN!I@6>Irf{7}~{l7O&T1 zGR(u7H^7OqH{*s9LZfJMZCM*D9!cT+eeEP9i)grJ+J3PV3D{iRy4%e;jb%4R)zPUJ z{3BFjKD~ZC^zw9UT(%r)?3T~U)FNYRS$xK?i|eVNUiWV%YolUUE$SFb?E7_ac@GHz z&)U*~B_}5r9f>i(2dr^~u4`8H{Jt#k--IG1Z$b{uTQGknW=9Z7`^T)SVop-dK!BT6 zFdvbICdK7}<~v^&OgiO67&7zJ5Maq^g3S=>4kjD!Z{ZIpO$yiVojS=~cCyQ*{)Fhrtcedp0N_x%&X;T@tuY!~ z^p+1>+OF=@5$MQfq_%Nlf<2H$+GM3q?Es%B+4~SM+nv<3wMRmxAwgk>nMR6b*VJ%Q z${LW;flivNgks3-PJtwP_fEU9yn9v+N!ac-Nd>c3PYV(A32nw0gY6QR5U-|HOL__; zWdlWP85Lu;CZU^`-JsxCpgOC}O>ddb98Hg+Y4NQsFki=tl3x5+tmj>6dVef%q{tTA zYFEAHdz2`<*z)s>`6|0_d{c~?{Lw#Q^CX8lzraL0d6`&LP81*ow*_*8||%s^bS3=^;}0Y)V}W;24{mF%&P>4p)iU zPi#Fbv&CdQP`#pRI6L1RX21av)XI(4ZnIBIKXrbkg8wEyZ+dz(p)mZDre4|6+DmTt zIcHI1v3QP)HFzmyu#T7Z&2$rTW}GQfEMgH}I~ zwp`83W~f)hatpaZPI~N)!CqT%QDqMm(_&ty7(AYzr@Fw!~N2VRH_bdcqj$vAbd38Kwrubl*Zkm zZ4EEyHM{2&B4OEoOZJ~z?yPL*{|c!#&Zh|w zvooA{=$W*Mms+qt_9j>ZQGAbs9(%j9pa33hT$ z4^*}xF=$MlM^y}K1ptDVN0mtw)bQ=Ha9n?b9seHGOKqtSan;Hb$O9T zIoiK(!>Z2a`fh9u$Q*I|f`-Mqur1!FAbFtI3R9l`Bl*7Zu!L9w5UmupReUkerN3k8 z%^L_>(?eUJD=^0-BrL{KkXr@U%wO8Am#o%q2Yy(dS1 z#AGJ_BB~%_&Plreq7ul?FrNkQ!f@L(BU=Ul^(# zch#*5_hUm*==1_GI5*apgEjkJ-+>NKq;s{5rvd|4fI4W-J+z{5Y3n1X+c$oTTm5tQ zPu*mRYlpkh*>)UzOxw3`Avm?+*Lb!!VHV(#vd}PyTs_-9Z%!V4)>rUyCh0ezNX!-L zO`EL9gzR3K;;DfUp1RUwgQ=>YXi!=|@qh#R{YQs7CKlKOt zVh+5blzo#@u8xza(a2VTZWi7SyH?+~3t$Klp<1f^_g8<^Lj5RpHM{qJvr$Whw(ta? z004bR|1TTmY~u9)!M`=?|G!CMpo7}5E@J-K03+BFwADn;3Y=zFi!md0mQ5)_S%NA8 z@z`(gVJWeuU4fl{{m|#hZR}{GZhQnDy%>S?C@Z?z)8`?nfFx<+I4xD>Gti;1z?P~K z5I@g`fhBNpvK5B_=*IS-w6~)c{juP*W(ex};n(6TQ&3 zoGe#RZG<7n0Tw&HW0y5QR5UrYJxK`(3$OXatJS*0lojN4uRECaNS+MR?h4g2N#GR2 z+H$%cs?_muZX|5(BBiuFaD#7XXKF;B4MTe?=vUm7X)J@t{7}#>2`O?**!Z<$+>E&ilmE5@ zAil+3dA9R?>s7w7n>3@c&P{fnQy|23&QE8^VU&Zgmuw-H#!dW*fY&UwW86=tam;qs z+9VQnUa3fgDw_WoKx6bagRd~|lsBFpHZt(#@rx1)6Fz#``jqMMgG1f>^D--BN}v(2 z7ryrSep%V56b#r4%>!2dEv;5t_joFW+}1z(2`o7}iAFReK^654^QYX~a5RwsGTJ*$ zI9(O2`Kv&?!+sQp5=wf4W47Ex4R*|hTLZ3NeZ5XWtOQbxmQ67Fd#TO)Vgcx|4ZjK} zI*w=>;36h%>+$d4>Dr$Z1l0MoY@&wFfWiFGeJ@%wwwM=Ja7D%e3k^e5(_c@+@5fw2sb1b~{#r5Bb z3@Z{dHU>o{9c#f5ZGBC5$<>s6&6}b(x2g8$M|;wk-BAaXH@dcr7{=Qb93d?r@#Xjs zyO05|8vugMw1lLrT}ZhdX(OeZ+cTk1>EuNE%4 zmrI=IAI?rw66-mOYuKi46qg<~7E94?S1ses#u7j}#ZAZ^e-9=VV+Hg-=P++uowNrD z8}7D=?~@h8cH_&b`<#qJx}fl92H`S(PJKRe z27;~%NM7`KaGGRr$^>4ZkQ~W((YZbq4Hz^I&WBl0&HF*b>lIrQHYLEC5(fqqBHihH zN)RcIM+|``tPCsx;+AoyTM+~M9S>6#?TxIw9AfPa;^olvipey- z!@1supYD*$&oq&{={f?n2}23lvc&+|USv23!Cgz-1DTS*@;qHn{LaGR^gT;!9R`@7 z=Nf#<G3?)^~PXH29|s`WGn zO$cTAyHU3q(I&vEBATr>9mzM3D-k6d5Uo6NwoOfN1&fNT)lyujD=TLsRsE{|tGo;) zo9RWoT&bx>bj?QHdJLCxlk{0qk!einT%>;%LlytDQLr^G+8wdzs7h2tH>s&U*t0Ec zw*aiFYTr>)0=R8_<=UNKlYA;(aA9-Ia`v#Y_j`HzTH_xvyYmg_&++sAx*ZEz;mgVM z<>A+Uc=^)v<@9pMGGaI{Z#8*^r5Okb8i!uyRGE0II&n7$C8@8?5xJG{v26ji03;IXcbu$+>Oi!y zARvnYYNRw#!Wja(p&EwpMEW)3gotyi0!0Y?C>RLOq+w1!xNhN|g z)TaXiMZ$;v;o;_ryvuA)m9I%ftbL|QGr;}cgeP zAlU~FycxSjD+RkCj?tEe7}?`akA}S$Z=E557PJJ3CO>SCcXPn`uRnt>(wO|rFoy-H z*BZtAd%4Y@z!e?0(oQAr^Vi5a7404T324E4A_F5-4(X2u^1L zJ@%Xt{p6E9qqQlQtW=g*F&|W#$sR_A!5pesDF>re^09iy2r+T~1P2Jb60jF~AE#QL zl$C}wVM;3l*r>-ehWP6jDSg>x19e-AusTI*e-+nWw-KC8s6tQ3#><91MLNKuYX1a~~`~rsyeAjLtmw_|DvW{7u0k(6#;~njIpTJcwg<;$!_EDb$U}zaTR|rd76}tt#yV{h3_6kcKah@o3QGIIQ za~jK(RzMPY1v9^0<`GVnl?Rpr?58`?0_b{rNe)+sxok5yWuz2Q2UO%_BRB-0&MH2~ zRy5^7A# zzmjo5eMI|a`KH(Q0`^2T)d_(LYf7w*P-fs95jogWnn|ibI0>6hqSGT?63KXyxi?M8 zOA|Qx>Iz~2fr?5xCCI~6OgMm?$nI`n&jsj)B*m1aqAb5|N|yW@Q|1O~zPu4JhE4PAHJBWtEQ-B`42(Je7*D-MJzn0VP)# zs+PjtK$`%$DK`^Boj`;wf7>293y0!<4vO-VR%IsWV{vdH;C2%hAgn-s!Y1d4F=aG^T zE$uiJp&b%K!KZfhpE)~oByVIu(Ed;^dOPEX2&_7HSdC+be*b`WCHKJ3m_cdVXCW1o zKClB|7t~zBOf_i$%+9xLE`m`~bMnfRd9BxbOCAp_E|XMG(v+m}CNXB0Gf~!e2*W zx>U3$3FYF%Ldv=w9%^F+Pt{xTAr>(crMqJ0iTv|^6v}VSK$W1Gy79O2oGdoMq$(O5 zlY(Vt4TnvR(e>!okMJI}A7)>P(FOO|qa8jrb-XOWhrA8KQX@|+r(b1Y1ISHoY+y%= z@zC0FO~yHkb91yE1ouips=1MwoEMWO`ojUWvh7U#K<;_=dD?NL5ozJ7!OVCOmNor< zrS-`zy=0k&QzK9oZ9sF9b^0y-864|l!;_#{APOUJ2m>L^{K}0e=xMGlcv*b`R8E;3 zOTp>E$UOU5xgQXD9c99AIk|BUT6#8ReZ3GlSAQ5{gyRGXaGo%-28+S@(;bW2JjDBl z8_c(2GEG>$73hR{FEfRjY$m?c!pI=$F@%70%P({t3C5D;orH#^pO}PFL7}RhwILSO zg=Fg^Hi~BDa+w8k{QVdQum8>0;?Jz4<>wqWcSXfkf@{T+tojIn(+Lapy*C9sh-IAb zlmz1Q-$ISxkZI} zB(c;zpu<;03JH1q=LK=B8D)H_&bOTq`&%qvw5X^epppqie50k^?Q?*P7Wbkaj)&hr z@OK+IQ?kE`9E5;14V2>%!8aU8MTUSH0VIiTQ1VGFxP)=CTb%W|uO{PKs7+{fRcZp+P>5F9B1?(6v+9LVi+63@D$(Z#27yHbQ(F{EM;O3xd`i45OnJEEca~d! z2CBNX$vvD9hX+V&Da75}wdSquv{5q(CO}6cY;7Q0OecH`E1BL}skz?mIuTR8v@Y=+ zO3e>oG&A39pK9GfCQB2yQiGlrv`R5tf^lTZXpoU#!Lg?kLGju3ppT!83IKZhK~$)hgI%w z3tUoO6!0`;y6Tca@U0|SwUBnbkRiT7JMgdR`Jx9=M_-RHWE1ns!<`oE|u{~{E zAC8#p-4Vhybeb5$!#IWWFKVM+v_GWZ4uz|*7#pR>BNhUD47e)Mu(jf@>}{a%yGN%O zE}I6&CAxD(mY|=6`%dAh%J~o@@lY=pGE9DAcZj>3?QnVdFaMW7trh|(T9b|oO=J!d z$UrkOC3oQ5TyW|jurg;6g{mzNG`KsM12b1djl6`rS5ZKrYLjMR(`{}ahF#>a*tAF5 z**H34!oSB2T|oVz+yyy}MBX!wi+D#-4;m1mGDmYTpdaegncl>M6*U(Y>Vya5LEM5t zqwX9mZ-~hOD^kWD$8h1?v1VeM?EjUNrbX3j@*lup-maP9IBlY1CmSDr9p|E7!roSz z_u{!WEL&sh8JN#KLVC8pbpd@UCQ1TJn!NUw2I`;FW|%lX=>XK z2GgEZ4J1r|#w(_9vt_j{UCfhgopT^|QE!FL2Nd2!>k1$cxPg(!y4>aPRU)zN2&6;< zV>+a3F%}auTJ1i3-zLcxE`2VyPXj#UB4;)9pL0$O&>h34&WWCe3V#&qI<8wT?Ke5v z;b-BPU~D23$T5t3;2@jS98Tlejs)wcZG`kD$pWAkPgbX6JxXx;o zfZG&0f4Zgf*bcOG&7@Zvc1Y7v`H}dTEkzsHwaJf87A|9*;-GfTX9q_e_gaa40Zbrg z&)_O{hU`s3wlB(?oMR(&_VpKKDxSTm-C%#gc{4 z>7*ECO$Z=6ias6xJ_wBW?vT(&eK)@`CBk!^a%-iyRY?AvllsMCF<-I!1Mut(?7jQJ z`A*Hq_AxGx*vn-Bu5#b|2Nr5{9wV#RqX~`pA7{i7;T~YYk)ULa*O2B?Rc`S7b=A6U z_v?*r4a9~7!xw>;RedQ7U;RK^i*ki92Apl9PKl#;cPV@$q@}U`2p(&m$u~sk4LM>i zoerVMrhD;@gJg0|PcnKh<^v~!F$^yS#?1@zb0Xy1=v3_uBiwUoX4H27x}(9{>e4zc z?Gw$6KLViG8>0xWMbhOWu;2a(94g#uHp$&vkk!FV^;Kgh%Mmfp5o@cq=Cx zW~O352(%wJ8#g_CwTV^VT4Y7^sm9s*JRh7H7yUZWInhz^Yqh8xdi||sY*x}s4qY5+(NYPCri4AbP+fR_f*l4`eh12 zouK+(Q|>Xbblmt15Vl+(8I&sio4x{UI3k~oX$%`4kLPw&80Llg6kn)(b-^FKvS+kK z#ScK9m9%p{!PNZ?;WxfPt0n|oYF6Ja3lZ82emy+6!lamDbCO}8ar06H0u0$Rmf{Mg zIKVyg1SmL=2nJ{Q6wZlaTHx?ujXJ(=jHEdk(8nMGykjyAez;-4O!g@$sh;Kq{IDCb z?@PyccIa!u+@<}mM*KsrdoA)gNpI^6ZqJVY=y9i+j;2GM4bQwkG91SnTc{#tFU z*vMNs!e_4bh@`y^;9t?C%n%Mx%JX!Fy?ZSLDIacW`Q;0juZuoOw(Ps$g zRGAn@Q-Jj>(;kG|*{Nh7vif!^<()Z$6&EHgM?K$gHO=^dIVV-9xNxs6{Wx3Ca#0D6 zI(PI?Ieezh_kNIZ%VBSmA1A!6LH$?E`q0b1m7fB)F27E20%F` zX;yQ)dN#)D8ZBPS2?shEl8x+DXs>n^9{8}v-GGBBLP(^$93|yz@_}(UsOq22qI-Y2 zHs-%O%YP5pWPMAz(yL-cmlPbMwIH?`mlA<`_+G^O?}Y3@Nr*8XqTMe^+j}W5WY-qV zPVN3o&bRV8*8lK0COd(v&LDG&$tpKA{*G^#4lJR@79yy#-vzb4%t5ekGHK7>VMy1b z8q;+>(nDV%KRvp5Sz$zlaUn;68-UOaJ07%P)p;5uMPU8L``5FZz39lKJR$HCtKn=g z0h(BrmYnN<(s#a&1x-IMUXSL{d`)|AsDF-&A^Pq%E3JeREz({w*D8OPZ#RP?+{@Z~ zks3CWsU5eS7jc{L@BoI7l-WP$B|^t29kkLgz}8Rz4~hML93X2sj3)*@=&qz!Me8Yp zrp9jDxVH<%D{wweo_9Y9!1D7svTSVBPMDq(H{xH;8mo1iK0X;tCRERm`Ti-M3pbD* z>7nhfjVmM)CxvVl0WHtq%aQVh9>}oS2g<6?L}oh1B>_f~d4`~}v~;}0_u2w=4Q}s= zD81Yfc$H2>fKy7VBr}_lnBi^ggLmB4!p)_q*YNR!W(tWuJWu_r0X@EyX{&m-mvV%z z4Qwi^F;w@aft0q*HhccWN}vNs zcB<0yv%p9f#HuVj7T(!#5Dr2gnH&yIygax z9&adwV(H?LU7dN*#xbJ8`_(yWAn+DoT}q6S+`E5=Q_1gE_g=@r?^nlhbAdzSi$72A zqYx<9hlTidR3k^_+q-id9AMjswHSq%;iqj_e0#>{rMvh`d)`Y#Jf&eDjB&#J#$fV2 zF%4qHCQuMUF+aY;{UmvoX5<{~W~kqXR)_XKKpz4sddedwUx2Qo_`yLyzZgCT7Y&w_ z$b`eE#WW;ZmZ%WAZDRHdsKlgk#-65+S?I$sKNfJ{Shk+*O!1aqWlT_sfuI3q00_N_cz|m* zRbaCG8ev1{mt1Ya)(Ch2%axw2#43WvX#(?E(oS=$cAkW4+VKz`cgVVd_M}7G(~eA& zLiFWE-<$bAY`s%-XwkB@8{4*4Y}>Z6V%zqLZQHhO+qP{xx!LD!@Bg+o+jyQ&eT=H= z_4UqjU%JmQN?vUQMw*kzq5BPv61JkN`7OvC7;k*A61j&+#+Ok7FX?o`?TWf&_sO%8 zz(nsVP(f4zLvzVsGQ!R8n%>p=q_zA(kc7;N? zv4sV@K^&F^i7DeFB|IHmVIx~ujkF4h>T2w{GBxmh22rS-sZ`DY(F6*km54Q^nwmjWDQ{rFy6aa)!JZS^ zR+7vpZ^e-98iLwXLBa64q53jwFnU`P5*s zuZ=Lqy+Lt}qVWd;NN@hRhnO8<_gJe}e` z)(;Ws`JWWjWA2aT_BvM`imIcXEZ3nB+hrSpYEq;}pYNVdq|l{BsGELVbIdRCKl(B^ zN+uGIFd9<}p(bg0e!ew89MG>OlN@6V?N!bwAGhc=RwJX_?szk0gwg3ndz!iRvprUu zG%YzGX8V#xD&PW@8v0u6f8a%aWEGpE;kkOZt1QlIzAur391?`MJuCYa2K!puwXb$^Bfs34XQ}ndp3VCctf;ud)vLB3eyr+mtS`a^tBKI+Z{xBD$7~0plwhte zE&3U;m@AT1r;n=7$)V1%O)QaW!d5T%hVSiBbXR(!3b7L9Rtop$8@^5IC^qu3#hkU4 zN4j>Zb18p&jk)+@{G5u3F|sepC6;D0Zxix!dQo~E)k*Z+?*Iagmvi3~i`N9+eAWd) zX+&ViL>%WY&ZX+>y5^ta;P=88KS$OW(1jd}A1Hp>!sX=d?Pa&|a0A8{VL#78Us@o9 z7nhfVz-PrA&!<2fvAB)9N&pBuIw4Sl;JvtnF?S)lkQ`baE#80aQvl9%#Y7Ykq%F(v z*Y9(itKgjbE1jo1Mu%^u*qf0>A32QRbtJ8{>H#PziVptK{SLF@Z+?QEvQYJ9%Bcg@ z(F=Q6g12CQ4Hjn8l#hZ-&o}W<0V#@Z?AHGR$At|!z!NIoL5iPnmz+6XYo1}DdSi|t z@sKIKC8xH5;TObkb2FFN#H*K&+vIH_l&|V;g&(;@h+Zgm+U)>mIj19{Vo6IZS0_9M zpBCL3le+-aYT9nCKuZ(u#_8b1mxRVIn0j2B0Ug{ zHyH(6;CF^gEyrD=TpBN`s5Yjkh=enBhug)h-VXtMIdv{g6%*mxWJ>ZF+0Zw-uLYZY zQ*3%EX=+Pn+2~~s;^xwz1ymYlB2EQ?PJ}72i{GI&{X=L8oY6bfACl{?8hgDr6S`0C zc4#Tm-! z@cEWNkjGeOQm?qru}a08C&{f9Ep@42L$Nd z;5}lu13@Z*VA3@nz^t8La-a?s>Hg32pv`Qu7F_h~0WIgSkrnaVZb5JWpypETwKqj~ z-_>s7m!(s_{w%Kb0FT3M&i$d}j%_iieh^?8>du=umW^BV+FS$p#}C`qp>icwCqA5q z(RU%Q{qaiu%sL_O++RESp{^2CbAcB$$9JRH^in6O zwh!)Z9(NPH^sLmzAo~5B^Eb&6sGeD?mRu{9>kdJrv&03%U++LsCM?b+3R0Lk;4`c? zh2N}YZ}Y0$WkDQ$|Vy^1-rF3r^+g%0}DN6z$*KiXlEtePRkfSPry8;BOl z>dD?_2K&|Dg1*@_7uhdRzRg&i-YDDk78fz@slG29*6W+7919DFWbiCcxzD9< z2kWnb#0*g%oF`yQ^Nu3EX-tfVng*H0Kict{z?foC=u4Wd-(E+BB%UE9=`QosnU=y% zqS1gRXMX*X%hk(`mFnV%a!7AU| zI$gUrS^$_3mg*eXd3vttUHZl0;4-NuG1zPuX%L5L^tjgQI>C@WM+1#c#Q?$L@NF*# z%+xhkuz6}4<832^H&mC29qq=U&8lm|wfLIkUft^vM3N;>ieHXHZEQ60mb1mMVG1Mf z*Q4+2D;L9nGL?0Mml3~q0Z}-^M8&+3s8QUJBBI%8OgTmgIp1~v+f4IYvQ7g3nrUu+ zU8Gq5Gy2svH!`+yGB+{*Kim*Y!i>#^D8}H;KPbYsMsn7xq7byxqMA80f%MWKKT>;K zU=bS>38`@7<@_u0WNV4WQXgWG1QZgbWD3aBwkyIAcE5!~&9`QB#8GG`h(@4)Tn!Bk zhw*{S__o|zo8wj{E6dj=|E77zYT~Q~NKWme0t;1a*a`?8DKk;8iGyyxuSvTE3S23q@VP8jI+HOU)YC$WU zo;;pit<%~QE9Xzo&U-RxT^#>34Qw-PzcQdYIJ(U1GoEE`ihT?luwSyir%it@J8$Y= zzQIGhA;wDS87+)5`K1{-WAQN228$Z73L20Z;W5)pjnX66p_)o!Q`a3uvv|%=V=0|A z78%Mi3>Q^Ov6av(c#=Fo&r!?N`h^R0l00b6(-y_5YUKHfc`cHqRsAZ7)JxT|)H&68 z)dAHF>*pF#>wizD<}nI>o!Ef#g17~ukwQR8;2BSMjT7XmDIm3tD=Zb9B;;3Obwa1p3l95a;8!dyXt2%v=E);0M&eQ6}n@8~%(T z5`v;a&gpNd$XrNXD8ZkASTL4Idv}`Bv%s87;eSRVQ)7m;pb|HiBzlK9#1cM&B8H-? z$X((l(BM0#Rpg$144Q74s%#!@%Nb)HcM?C)%6!rWb2v}=Mr7Z%ugOE?m zjrQSzDRiQX_CRO!i}m2&-~i*n9xpsRp*LPT_uyJTB0L#)=OLnts3D%V0GgC}-K50C z=AI%&Ly<$f@^rE!__S`hnADROriT?K*uIau6Y3mn z+NnhT3Zi#J*mqDZivAUp6!J1E^0M@5cWsFD>K}cv{%i4QRFb3kxWp#tVEy#OyOqIQ zU+Y-#4)a=Y(lQCE)e|RvwmFh8{a8TNCoMc`JtN}!oOJX23Ue`${AWcb$;T`Dxd-!f zv2=KSD5O=1DVuzBaQY#LN#w4@!9pXlcbj&7H9&?`!~C*bfbiTzFsxF4Gv3ifK1}lP?Jg`nb&T?=B(wwZ0kYgsuL4 z7iA|cN=iU37Mq3Ng2C>2q))ut;$1#~^YttM2Zc6~oOZwR6cx*uz-z)3wxq`0e?}yXX z|4661X&&_iAOHaDuXO$|hg4VB+{WBVSNGRC6O|}uyFm{#bn}fO?1GH|d}WSNJMa#_ zItw#Y57>bjDb1x}G#*we;_o9Hfe>I~7VyVyeQezUZU;oew57eUmCA79fiFVrmJ98Y zf0=w&XhVaH*M_AF*}3Y^P18|pz{IPsH3{vU5igo*a{*(wOGVaE@ZbAyvtObQFl@Vw z8ILMR`AT>h4Mv#TLW^qb?!ztdla{s&_q_uR4agvJX7Tag^N>; z>G!v?2mZTr>HyOm1y=fzF0gJF*$UOmw7M%=PvpD)Q6CuXj6WZ6gbl6J6Z!^i2u_i< zkE4VNj4H=4rFGzDoI-LC=bBncoWf1QD%wj-HD#yo;P`*H<`s`+ z%!X+E&WW0xIY=^+NNATX92i&#cc#!aD~I91z`h;~v82@$y-=J6uL-y3>c^E@%(V%h zgd`rBZZ!TS;#y^OwVIlW8k;V$uFsouea%CDyLZCl*4~9rAD5bWdiO-SDzUaVT{$ZU z^Ap3_wXkA%Ouj^Tc|}6`G$?l&wnuGEOi4b<6qZg`{_#a2d-i$pLGb-H*oJYIhcZq> zf)^3*^-vj=#i};{7 z)!>MdqjQrvm#;U9N=qBMT#R!<%NWc25k5cu98EP+EAMQNTM>VX6U!$x+;NSz`pwN0 z_P!xmc_)i)7FKS(`$6he#=5`y)dVm4F%3@CQlO~OHlWs2PK=1F>G$+|b?}}k8R+w| zh5L}SEkKnQ|ktTApTtzeECl$TVy~SM&ZW)u?!Ck7BfN zVl;#)RYY{4n#$xtgQrdkv;PMIwWPZgxM;Ld4;+DV& z^y9C_Y?d9OMq(X9=}*P4A%9abV6rCurLdBF0r}qYefW968q0p0v#qAE%-?XnF;Hoq zqzTx@w)mWfm^D8#)tW8?gv&B#>`es;;5^x+Y|U$y&tcg#x-35P?gF3jvy(alQ?k1M1DT@)=R1{KEDl94D z^_J>@PnI(LL+HM_I0sy%D(@1H&hMxYaJuO&WK#z;$gu((WfkZUv~U2Cn6?3Az3>AI z{32EH+3W-G%VsyZ&{-yp$)~>anQ!hkmq(L8;CBQQm5lqFL4Mv75r9KrK@&Y^66fV& z4fUYm(sUfs&I1ci(MW&VjAi6%EOjwIt5En>e8Za0D?a}K4OfC9AF!zh)e8`3hwWvu z$K!`d+SlZ}3aot70CNnTX^ZanW<7M9ES2C;5KEFYUIL4;bR9vkPY)x7$pZ(vSAbSXr6tTD6yCv^rdGf@CAE;{9I$zUv{4X(w|GAcA4` zT`Jt^boyPD`il;IvoHf$5HQIBbQ;9bKOrx}^Jtzi_zfe|10Em^1+z+c*Lk!P?{Q#( z&Ah?SnB*Bat}veR>G`PvhW=hP!j6@F(ea*RqHRb(I4X8Dy%V>HvPX-MpL6}E1W5AS zrXItPBq|nk4B8f&CNtdF6h9CO{fd`+zbjdc=vMdFaOHDD2ud8G^H+ zb$qa4#|6}F7csX$sc$$&*p(d9HX3SSdH}7H30w-<2*H^_Im|eMK*|LuBe#(Yq1CpO z5+Vz?*p7i*A|s(Jlj!e3s?&=K9$!VR=y+ukccbm=tkmWa)idPb8W{od(L#{p-4OXW z+2k4vL~BISwiJMPI)7!6Wjo3R1W~VwFXW2&K~U>>{S9Ry*t{v$0phx?LEO+GYq8%b z!s1ClPIYmA2oJHG{?&NG4p3)Qo6QnI`(gwV%dOcb&hj(;Ju zYnsh0j1GrA#&FKg1U!QDWoHC%)rxLY!y1pmudinl_b8V$lBu@dyGkdU;bGVo6M;06 z`+QT6e^uq*kPXutSC&nv@xPzOpiMUX(gkjNrjII|qlIL24TNPY99rP-TLB--08P#S z0}LppyoQh4$0|iI@gD@;3CDr}1~(h=cQ(23Ptd=SLFz?{cTJVOwItzHkAY2OX(S3ji_A#HY)CjIx08Y}N<)R9;v$^z! zEXd#iWT@)|xyvd%zSxbM8OeRYNQ{z-h5Ms-_9XD;s$q6yhH}6m9K=p80I309cVh0O-|AXyI!ko1 z1hRc2o=%Ow(u-(Sj)J@JLYz_YSX6N#Y$Ws6Xs{NCfDJ6E1C0iPWJ|Fm62YN+NtmLF zF}XplhDOF@*JSt&(ze%k2Ouv5a%jWuCrsq zS~G!_s*k$RY6{l1Ck7pf!FDRtRANO}tq_sSU|_Llf>1po$3as;70#R~A*Co%9e|Jv zdeFbtR%%J<4ed2|9fU6rz|u&HZNtJ;oD2GvWNSwQwGx*6jAFDv;CthGxJ_ON+o`%( z#Re4eL@@kEmKn-jeWiqcL}*>ourH_;di4e@4oO1+P$jv5Rj`Svun1Y;Tl134ePcx> zy7PE#8{U}YQPlUnnSKI*5o`1o9n6pNh=Zgq@~RJ29kQR_{cn;+DkA}+J-c22{w$9s zj5#Jt9G@R?Syuk@lh^I^(MB{SP-Ik=%u7O0`5g7(@x^Ei!L}ruJaM9;yek#an?>$v zVm(R-15+4>Q7TSH@y-URq6Q?7`53}`ZEV*N$$RdS8OF|mHsHe@)yS>kviHSQ|@>PSjZ9WIRHFYXWkl3`Tmh(MnK zu=vorupRp7LcgjhvwEy)p5&|2nLvruKHNuSf=wA>N+%SU%@f1qb(Hk%e8H;~dRyD) ztr5^;nR-J6lZpiH#|0ZCK{$KCAGivKU&kj4R|F z^{k0Kk&>G=AMeEXExyMuxjF<6d@CF$GNuuPQDw=f(gdzBuYBwr&9&!t1`W6O$3#$R zxhHZu%!iQ_vd_;_G<7D6xO=275Wf;;U#Yb&A)7xO z8LndrWC)PJ58dC?Q@|oH>2cI!yku<+;75>jzlBiah!BjZv5`|+etCW7Bt}J?B+V;t zC4i_&(Vk+0Gf@Plu88W%hCE!ySgmASg;*gA>Z&Y_DuL#SM){ji1^;nCGS?9qkA;y0 zycWUjK9c97r(!Q&;+TYd3`_nO)OZXamv{(@N&2)Bg#U4ufVr1^65JR2Pra9Q3uCKm z^zFoWheBJ76r4$3li4&Qd3~*|GTZhz>xp@YEc)c#e8H=|9|5OP*11cP-5{x>2G}wK zg_5N#T0p9SRdf`-^A2pJmIK<1Z&<`pMA2E2_@dTGpjmF_ShVA*;T!-VQr21Q6jaP z9Ah{w3GTpYXhcchKYKu(K59S{TjoEs@Cn7-IlY{1Ue<{V=k*85&RJDfdEdspqC*wC z70lXFaW?Ic_NocQm-S^-#&x82X7Fv7kWz)cS^4)GS~!BbFq`bEFqN>O{R!;j1}kPv z4K}OWRfzw{#A8}Ff|hBek?e#Uo|RsGR|tYB)3q@=)$PeH@81CWi-PrQ!4?TXal#7s zf9f8AF9x*wU=6Wisw=sv#3!|v6}7=;K+4Qbj@eE7!Z;482tOFLAelQAObyh53FEHr zd*EdWsBs%yZs#&p^8`}r|6XK%#!%nh!(i__w@C!F(4m@}F=PXB+U`j*29vXMEd-#G zU@T=IO4=1Es;KE!EIIaemw;-}Hd!OT_{ot+p?&gPLzfzGt8GU5=P;myUC7T!8%WE@ z7>j#M0;p2?XRSxI_IER$iZ!FHjteG%H~51y1BpcJxv5@ZQh0b8$C_bIFc!8)XG_+- zX4NjRF(sO^rXYXw=Z_Dhh0t^>+h}_$jf7o%0%*Wsmq-@ zh*3{)Oe0+4Ck$_=l$uMpT|{VR^{JzzLqv@SfJh*D_mi+yZyP?0ut9AE6ce&%@i}om zIn^soz;!iI`f;yc5XsIOlh@=YaqP8jC|MtW;8|DfFMiNi&lSN zuFIcbzSm-0gK1Pq*JMj!XkG-i?NSBk zAK}fK?-!pV&m>}EwVSHEL8%or*2B>;5IBVSO@MK-=fMiqqBx?rwFBTS!ZsKWr zQDANRSkjY~> zCT7RCv~S13znpQt+Ox=c12vhR7Nka~`&E#)-^zWAF=y&m^pm$AR+}gvn$35uWvD5_ z9F?0XrM1JDD)(o(|F+qQ#1;UacCF z>@n8E;dws_gm>^l7?%0?uMtyBjTLp*6h2|%z;ULLUI8SwbYM6CI_&hZ`Hlf*TSuMHDq=O6^ek8f9S%AG2mZh@cZAk*Yon6zNOwo3kMJsSOud_e+eQn>=jJ zf4K)k^mLG$d1-yHKn#-XO-62$)%2C7SD6C0HYheArCd%EF#HPol+uL%T(njDRuxo6CEsH|f3i(t=mix$KzpcPgmQ$DbyL$*CL7)EI_i#boH7HVEso zv7}C6zi9YJ>2tkq9h)?Vy4kZdaLmizl?IHk&h-Hw#T*vG+(`HxVzSn+%hH?%4voV78a2W*w4$W{`IPR=}Z6(XC_Z`9Z>zviDUd+R?g$4b{Dal*85`zWj5C0lD_u*T48GBWDP_=}tX&My zW)w~17LjTrKi}BdFeTYJGpdE&hL*{iuQL&|B!x{gfq5fVW47W{DK+Ge;v8Le8g%wI zO%{7NqjuUmOQ^O1KXm4YBe~5TcXIj?1f&NyW=Y4b29E@$EyQm*)#vNJhg!?j^(vre z4LtgUO31g|-1Dcx8W3Rs182jss}$C#)M`^s2wN(v@9IVe%lKAv@h(^g(7LktdqGl8 z1#5{@WsXPEP8Mo@azb1(ORWXJ!kQIg|BBab`m@y9pKI$z+Mf%O-yt-?l zTe4`UShTuv++4-6mq4fco#qHu=4?TuDZZOugc2piVlQ zMvvS|NE?VSnec-}744FzpUS&p69>BLcYMbadxGpW^$-lC^@8gtL{&viF!jR-c^b$Y zXOzn;>`dgb6m&Yi!Q6i-i!)P$V%2X$RU5eL-Oa-m7kzi16la&FZHe)?=k2df{Q=GB z+a4B30XH!E!kePM@4kvUD*K5y31uC3ukK8jZP0LJz`3Xh-jjB9sM@GbPa_ZqSyyR> z=DS2$S0LY7l*%RKBrI+Bk6(aY$WA#rav^)VJ87o=wPGA$ZqMPD=BC>DY1eS&YDOfd zy^E5Du3R_605HSSf#sTnJG+x2)ND`@#ND^#=YP$>E#N^rHN$168oTA871CtdCXd9D z$_W7vqW~Xi9$iA;<<6g?_VsU)7quj|df1_=FYiO1g66y`YGXsQPJ3?pJVSNiM>lq{ zrmo9IKtAY&IBl4iW|kX?FET5EzLD2 zYXZg=uVZs8F)JkCkIW_Jb%Y@8E}`VnTG%Emt*J*C(pX);uV0CcHGq!(6`QdhvDWKk zCA>rf>ukK@!6X5{ zWBgH7G*9opvD~?YZ}FFZ%_1IJ0}x>>w~82iqFa3)Z;s@aM7M|doRKSPbxfYvI+q=; z@G$&KBg(Ig-Sd2)A|@$V3KHBD>QdI`Q!dFPY%gaUp2Gv92y}AnpnO?ICxG2LbxxDO zInO)%?&jFYsz~4qF7874j-U2X#b>2`3*;O;YKcD@nMdiW;v8*8gF3yh``LAZbEoRA z4ua{m!jE7M-R+jK7~n5rdHmvpU23DEVmcppEtR-%kIoRfCvcPV&>z2)QD!4$glm^D z1BWKWd4u*BBpe3M>+d+pV2keDnQ2%yjGVnp2}neGJ_{2`MISLR15z8a=|v_m*N1nY zK#<2<1`aYX@cVYZ_7iVjjTArS4Qf{9^$g>oa4Zh^m`dh&%1zyk%lTUJ^?%Uq1k^cbKHZEO_eu^x9Lh!}4Q@bM5I@iE0Rpgm zftD{2>yu=R%14p;mX;DDU^&FDZlyW}Uv~@2q;Q^cC=b>7o+J5|?u(~{Z)ulCrB0Q- zwH_^MvEos+Bwm-32mp2GX{WQ!UzOf8`8?7-k@D8@D#KnE;(2-9k7zVAfJrf*p*DvO zyAYv#fjMWr-f#zJx-Y#dI8)Xyaa2Q>S#N3coo}NMJK0{cH`(nD8&Z^;U{EL)asl4q zqVJAFT(#spSY6qD^AIHt!Ux$lMfI_Rkh5E6aZWTnF$9ZP=F6tKRY<>82ajuZ5Rl=4 zJ&{{ns3VqtEo>!}Il21rl*Km3U+X<4N-e-*?Q(c2fb7ntSjx#U5IXl_Ti&hb<`{$7 zY@pq^d>`-pqG;1n;|J z$J`#KDat;$Pu;f#2%w@HZ!vy)h~IF5BdkDrBt~FtVjwRm`_>;HoPJ*86gJmgwpeFG zdT$mYXQIbkh@oyv&XLrMJa@3I*HsFA>)N&Fj{@Dgeoo=PCVFpc`9Hw_Jt}@<%YM*~a5 zig=!&j9nnkXNRrOXe>JGxKT8Kljx28;kXO)2sW#Wr(hFpeKT7Ld%R)iaLkA^OQ)F> zejQ6LPtosH-j*aKy&KMuZMm>1s35}oiG+n#r=uhvD!GJ92 z1!;nW4%N-sdf6wOn5*guS5H>990Y#gM^KzSG@Rg&Am)N~&l$geye_x8oy0^DD<^e| ztOyB65ecd7`zf;+oyGP6t zJs&R77R1a}7JR{O>~zlZq~LmO2Ch_5N|BO`597Zbp06})8&&eqa!aiIJOyUNCwlCW z>Q$Q*AZm1GHHI(HD%52;g#-bv2RGt}n5pq)-ij*9Pjb<>(|9C+E+09i(v{^GZW7~g z5Qr$SzR1LA$@r~hmm-Uvh-c(`CKZ&2Uv4ag@NctgV(!@Us8M6-@?<kB7`LqT1qL3vdd@NY|gkO+~Q0&|lWq+fQ0h*e(r5&T55FgheF zL0pyp_&2utI&uqRU753nXx`4-2R9l$b|gKD8NHr@vb8x}_to!#RS|a)H@fUMeh&f7 zlfw_rfx()#zOXYQA|e&Sd*!&pV+H$bVU-*fylE@aL*S<1>Fvw~_R|2CixFk;!Rz^e zI9^jD;-sg$AfW`G&#VaN3n_<(XDWEWLF(DzN?2~cv4%-+vb(5ZrTQpQDmji43wj_R z_QA1TP|6sRfpuM?rku*&50EJ)#3S}O%(2d2_)ld_WHT)J#a=ZPPG66vB{UT4GD?zE z5}%!b#g(i%qA0w>H2mA!lrtL$uiK2Q!S`XNGn;bbd>R+5vl6h0B9V?XVj=L?vph*> zh$o`L+7#Y6>OYMWe$aSXHP-|36X*Vb!`AACZQMJbFdV-Emk>>E3&!W0vsZbSnl89H zD~Wgo*NvqC6Fja}`>-)nhs#yC5p8f?gNzs?^z@Lg0)4EatvB`y3)HHmpaN--gln`2 z!<&w6N>j=ss4!Om5PiR>6!&iakkJd)e<>EknWuO$8P$@Mcu^Kk(cVdqvO%-taIM#W z>6$>dJ`G`a9c_+aS z@MzRI@0?i$b7;itzmt(Vx92R0imfhA`xn0epnF^xLHbhu?tzn_rT77Bt&=CL|ALX+ zmd-ihGIxtQqy*SH{YmvZ6sZfygP4?C{Gsn9(=-YHS%E+b=~Nm~hMpQW$BzBNRgdqw zs6GhFOgU}!kf->F29mnWga7o$&tdD<}D8j?1;RU!PoJBAg+SC_CCPegH(U% zN-&VN47QPv0BajDEF&MlAFnFfCM*7Hx}Pn{`Mfy`{YpL#kWXU$F1PisNOzw`P}=z- z7vWuSd(`wdv$gr?27n7x7LV9xnuag;7{0N0>g$_icpq5@tIs_xwfq5oVcr9&>*8FZk6w`0xbUwAot=8xNYS(js0{ zQ4RE8eh-(+11-31B04pVm?ZC{OQ_K)HhH&-dmIdHxq@8NziqAT;bqR^CpBf_AlKbR z^4e{mTmMI~^c8dAo~I=1i+$@xm!joUixPRlcBpkF#WMpCrqX|vdhS6NTE3*OB4~bL z%OU!tC=sAy1pA-U;0)3|+6V6($RE}eZ&s@fLPG-Q$AnFg5?-$j1~G$bPGJx)TDWwa z_o$+rdbx<|0kI+(0pX5>JmqeL@Gltn4DEEMajE|+`2e?ui$%Zy0DVyZud&ib-^tv? z*vZ|__&;pUB2}rFUp8m=hZ>AmJX&z zX>h#s+ZKFR$j(5-|Uj^Y^+RQJ2qq0eUTb$GTes* z*pv>JrHh$~N=!-BhM>=W^^GzCx+)8+p7N|GafVEhAnCuu7ph#-E}frfeLJv4a?qUU zye6PmAFWtY%D*0#E^fdsa*c|>zyv-g4p>hz(e}{ypH*>7eN0C zq^@&$BxWV`Ku{8eLW_yggxeFr@o@yg`<2y;U^)pN$KB((PG_N}y_r(a|4BhA6sFap z$|OAcq%(V>qS6hjDuDNuYBRs#W&fRkZj;6lq4Sr?A}4J=+R88A6A+&=s2<9-+V##B zbDLrpAT}&~4I}Lpv$RV-pEaUR8W;fnj2$fpF569*xyd$0=ZZNw8Sv2ds#`b8IYF6z z=3rj#!)pvvA$rX?Rr}_~!q~j)uT8v+L^)Kr(G2qTy`&@koa4A)y&ahYd1C$d8P0VP zeIKW*hXiA6zeI7fS73CSpISe(LQ&yE^lTZpas~odRjmQU!orzD+7^;hU{`gXE=U8g zVO?ts_Ig zVxwZAt2B&i8QdHqZKQgwmkM)UmoSXvn=aYm#a*&CC|%XnS%NmATS0|-J2*a5x8N(x zBCZI;!xHf6FC9O?(j8iJ?$kOib_+^{G5KU6_d(T zdfMRJldmFoTK|tyzPA zO@>|%r}U1&0H^MWsYps>7PUGVs3`%ia9+_FyNV{p0Fm~c!{n<0?H}582ikQ;ja$2_ z+nLJ@q8yosx%$CkrbegOX=bqqF^ii-&!TKE*OwPRHOMkXR&_;_!9zUH6)sJ9R2|%s zg-6Nyn+`Ejz8yAJQw+SE9ZpWu*rG7C5mUka&TV9Rk>X{Q(P?u&l?#Jo;-ijFpFd%j zl}E#443uj{t(LdFiktXMs%a;0k!;arV(#Xa)fPyJ#3kXXY3&0@C7PQhs_2la(i9HK z0S`ZoKL2C=+UItZlmAVRc7*`|K>MHfoUWm*wVnQdpjk<(eKrTI2wfLc5J&Rvc@RTr zplDzY=5s={9boGd`7{t3SVO{Q3WQ=|OZh+BgcOpAS8kfX3WI5E17i16@~)TP13VSZ ze>zHNuxq=14yo60EtA}WBu)VE{4M(0AODg79TcZ{@HXY&T*h!WYavHN5-UB(&L zkl>A&S6B@nu{qW8Ve(GTU=uGO*`s-4=ioar_X2-AZ2V_@G|QSaY0y|H*f(*w{m7|9 zB47@n`2Oy}bF`D`RcvT7N0&n;Ob0qaSi6*rZi>`jxHW=Z1BAfLmu_?yrl`rwSl&j8 zVl#4o{JlRF>vg~G@p=MVXBvBI5UiPJ*0=a4U@!=2P*zhWAE+>|@p&)cSoIseKCN$6 zHnTKgJr(#IrwgA>{69c3Wdo380d0}srKJ5nWL!X5tLl@&RppomCK{dQ5`wbzUsIff zJf=-e+9mw->2Ff~|BQ_}v=jg}O>j|N;sm6F>udSu7Tg2KM&=@m{e9!nD~H;K8R1`q zr()B3OG1;`cO9SxHr|t7*gF#JnU)r&J^H8d_)lho;Wl_UZGLNkCeM>2J@-MA5x%wb z9-9chSK@#wY=x`Fp7b(k{X%^N*#!^zwFj*?5L$;_K>Ki~+@G&qqMXW<_YN*dyh5NV zDQYp(LW*vgahy{VniaLe&`zXQq{>P$khz>wG4R6kal8%Nj`sswegzlIE|+7>)wx~$ zL+$v$D;{3OGc&nY;(oB%X2aa7u1pXYwXMhKeoDr{ltpbY#aS#~)dfvNjm}r($`qGE z8cBbL2-zOGpm7u$U9%%oE~Km|?LeiuY5r>EDC6jp`Z4nFor$UhGBU_ZdL_b0G^MqQd{w3P2$cHSL4tN`$ys(Z ztZTL{YSoN8rC8#ZB+wor8k8>`D)q-%2YHDi{4>1-zL2{n)sISre7U8x)f63T-@~tE7@&_k%53_alc(Iu$E2w*!Oa9?%X7U#{gTRn)A?ISt zX0=WZKSR$X+qQWNmXgLPW^Pumaem7>MXGN5gWa+!8Xzd9hB$i)sZ zxMSxpFbn*f!&2i3dj+OA>Rcma;2c$e-xKUe&=`zc8fgb6}fZKnB81?4tM4~Q$A z1;>fUYUI_&Tu+`m;WRNF zPkxxj28<;6W&2>^k#C5=KWnid&5c^iR1WA|6xZLFo6}3g$sk_{DX&QVKyjq3z9jCj zqS>JE(>M<19BpA|nJc2Jfad9{IT}BFk7%0%L@4%vJN`Y~C1_)gpC=o{GvFEG^zr?f z7m$$rRJUQ;IjMgZ0~=5`=^L6}9Uok7e};+Y6{423O6-?0^2O9kigJlyG-D^RLTSYm zGJO+rFOIxWPR2xZC3>_NrPGPGzD6i~MvxCGgsXaYG$|wtcOOjf7Xot1S^}XW`t1`^ zxCkpUo%Gy!iUaOH*lUCZa$uFvyqPztkww1Z6AjYeeI-L5^3X`2HHt3S0f3@(xFeWC zL=eV+JurfUM=tg$FmPXTjRRRwMN8}*snjLJW^ch*LJ1lxgN0PdaskNzvy(wTXtIxV zggj+p;QS@$Q}4Mn1{4supcTR4_zz4S5mKY<)S6>z1ugehT{55p~zHnyeA_=?EXk zd9TK+95(oQB3~4VOM{w-AfIwgteVJQqqV`ayCbEf z%dkeRLekDwo-oU}r1Tb&b4gMiD$izdhe}8h2j8<&w`x|Xst}Ga_7P|gYvz*FgSfR- zdO}xohHPM|ux%cT#&UMhR%$~bTbVGrm^w{qjHH`zZjiWtkEo}XEYoCl&$5|>*g3JU zmwX^j-Y=HDTGUz0fGIJ2R#G`^XkD|a=(gBUQ2@eyL>=3lN@tXENFVB!G*14;J$7|b zNxZ9+UPK8c8zd}IXQU3mufYR1^m_cxSn+w=IMIzPJSI{v;ZR(zTsJY_T5xc4c{F@F zxE;~`$Nh2l_I98EJsAK_??y0+LzYP4(~2d7NB#CVUG8CcX&heRfVM+YBkK zqjSN7T<%({k}RX%FXYdlZla(fbL_K6>bNSeUW^vD-fy_7s{m>}0Tn8aM!BfHa6&W#fk~u;t2Hec>&WI!484`U?O5YrO^_R zwY^Yt`wLpW1{z<(1aBi;5jeQvRJb5m1Orh9Q~>7)OQ~+<(~}*-RL!EVn3 z56$lp??Ie)XU6gHlKCSNEf^uh$F#J?_=hc^Lw6bg7Ct3lV`?v*nKmoEU_@aKop2L# zbdCJJoc^S}g$pnpvcNr=7qvoq=*8Em%Y(L%gq-o|1DC$-G`Zxu0W8vAL$tq&OyL0B zM8H;IQbDGR{dKQ|cJEEM1g1^8JIOYQmKXMsC0*GvZSvhkx>OzcD{%msWT>~eVPy4h zGbbs|P?iEeMI^54GFo<~fPrb~UtC8Z{I)jRL*4fWWGA<<A0uoB!>eLN!V%C-KVn@`k;O2mh>_ug51w7 z2+A)0G)s4JsDrqP*GHSD%+fYgoVK&{Tt+oZ`*=>ZpXuyfa+$-F*ACJ4Q5K+QOj$|R zrOOsccALTm9$phgUx#TGr)!{bq1aD>aXwKe9g)qAWA|S43q?LnEeItiW>mbAj@Dlz!b_9S%?)`0R4-o!mhPw63k|( z6wPLVGiYW_QxR=+jp4{$A;HyXZi4m54#}uU?E(Gorhp9{M|DIqhcX<_oqGS>*Tg>+ zJp8#y${Q#`Y4!cPFONPG-u5c0(xtj8qwN+&O;DBLBo$E)I?U2V2y{^;;m_C!C@2?j ze2A<=0C=6p%1Ve{GlTS;nTLu~I7@Ip11;iY3LX2a57~#P{Yi18$L4a`Fwbp+>9CeXg-Ho0fE{;`>8-7f#hBThUbgB6%@aBhHi!( zJPGu+W~4%(t9ReR*;=AfqUth%BN%Ieh{6l@@bt?-B|kSQpaXma$V{Jep?bYiH$|iJ z1n`kTR-h_eB-NPK6^=9lGN0eV{>>uTZUB4CKyhTO0PN9>{^T7&2Z+}&mpHm^wP>*n zU&}0acX&s!7pi@*yI)+op3}itLo|dg6L70~{b*!@KL#N#vpryght>396{v@5*hTen zjMO^&xtgLLH5&Jg#;@WZR?z+ft|~KPe2V+{e|EG`y|wjPVujhVzJ@h`9hJpnpoFV2 zh-*#Wuauy$S8Q*zG{%gEBsCCsRIy~Gb1AZms+t8au1pT~DrUS0`%=&cn<;#i6KNbf z@Bxr`SzQ!O7UMqB@WxyfG-Z;?MGm7ff~9vAf_Tk{7i66Roxi?F%h+~1pVQdqq#e`V zgL%ob8_|yeMcEFznmc5a8Z}N6vm>ga0q&1$2>aouH2*2Gr|U1jsNk;&2(Ie;qRisJ zZZdj`8||y2h!-~rNMj#AdZ+Ty3ngXT*oPY7U%9?;Kt>2I9uybwF;=I20J)U^=l1R0 zOXKdI(ENC+j!tw%+{2o@!lky^))j{13vDX!=ZZ(H%ARCagwCZCOSngVFbuAfwWyb7P;$eG_yph{O z8qd*TW%sFAM__yL=7dv?>Y!nyZTe{86*4dfI$K5dLpNrZyP%7SWiMm8-effAGs~G^ zC6RopEld*gK8p<=c4+QVZ@+r;^^^Y#@|9IM2g@ zCr$Q(k@+sEnv6Bzs@NpJ6=CYK^b#e2wAwQwZ!C(&F%4uCAgRRDfDn9k8r+G)%Zg-? zB`hZzVAI;4Vucz+lEMBQ z2)3}VJC`3|A2)$&AM4Ek&UHB3g8`oG!U#b4gRSam1FiGgNQZK2i@*`vYA^<=V3jz- zn!2)#wLLl7H!4(m>#$MugTsIIh}2{FuItbC^K5Lx9;#va!DD0q!mtfgaq0+tC?4-H zPc{2+PyXdaM3#}#h{=X+jaj(B4Oxj*QL`L>jr#eHgN?)5K$p%u^o)Q*B}-x(BF%c@ z4hYR5{D%%75$RziO14)KEQ7boNCU1I|1#M`X-*CsJydOI+Bce@O>t))CqTM6J3iN} z8`hGZoJ`IQzjdpxSX0>`+3oUKi2~f3MjsB!)2@L-+kDLQB73chvexv8w;sOhb3}zGEsH+Ir1|E$Sb2x>nB#MOi5T*rP1{W|*iyOr!0fB*TQG#Hl@h}1J zp*Q858^r5YPmX%%OJMX235~`JebYFJlwiN>$vYJKP|srM@PP!U6?hmXwL$YmKIkokN7y+Pk?s*&V`0zKQZyGeMJC3`Kt3iBV z&J*5cTtDO^4GuyW#MEGGx4L|?K-hLEYCb}1?fE8TAw7n%i@z9Yu%*m0Tgk1_h7DEU z67LvP+OovMas0jqZ1rVYlYs?3)1&4;UtE7h$No; zNfeWUtsjPN%hu|$9SQNk*5WfAGo>|bg#*S)hlN$=cu%ssCcE*#J01xSGP`Xmq*mIb zW1L_sju#d>vQc2OLhGUW3sgi#90O?rd6Ivgh0pmsh~l^eSuMnQ4d!z@bJ%K;IKCCf z-D4WBlQG8fP(x~o0ta=RqW>7zevFc445AKijf*H>Ct^YX@fl`N&Vynl`;cG=Ws&}2$QT49DYpV;G4~v}HGMJ#vGMcdBs?~a-cj6|>5I(5TIpD7 zVs3d#^+>I8!kL>ST!;Ns-jB_{Jvac9D>O@^_12e0Vb2o#hLfS+e{3*3#F6YAF8yZ` zduEVnJL*i&A;X7@M(&sv}@B+^fqe% zRl?mw73YJsFT%)o!L*O7cjUonolJ5f@!^Fi#4yq{*Cw3q(Zr&bIh4raEQ1tV5AI$P z{jKZUqj;ukP4E9)O0N>2lPP@ELlL`NQCRd3jRqd4Q{{TRJ%JC4$!0)imE4#1@JR^U zolF*932Ry$O~M}BO`6Y&a<+-Cd$$a4K!0$~v}hl1-RCx`%Nr+phv;gm^5nXP@rY5C zB1+ZUy4aEr2oI2sE!p*!8*AM#_@+?NdR-=K;;0;}Q^AQ%M2q|`*=*~ZFc4(gtnOdJ z6LOAn%E;$;``H_;*Kfw#mIKXqAmrb4{i5rh^?UlS zTtC3*H(kHz`i}L}1}~26Grnd1IisJ`CJ4rAQ50DcY=dwQyfLQF&rYj0@lZcv|qx@1ox z2p7=@d?E*N-R~uU7IRdX<_AyeU|{ExKuU;-K7T+kW2@Q6J5&k{^mRSJS-A3*%pzZ< z>!xHf&~e}YMd+M{Ui`N)SS!`3_!m5RaHif{rx!rS^N{b~$WU|u2%5t$H84=^a$qw+ zr$$-Ejqa$pH2Y|WMJHf{Dyt!Smd-RN5kKi5B!n?w9}i=kI?$OWAQxDy4YFifoBJES zHw47GP0(&Jlr3ufENugh4No`U=HOvsTD6bEZk%;Z|%zGVrl+)bZ>wrxFfq zLMzN>Ie3fMgN3GPa69M=QaHIiy?wf;U0;(^Y4Dn?GO*PPZ`V+>Wl|C?wxZp0Ib#kU z1sfK41fXoW%R0a^RMiK4+uR0C`I@>_)bG~QQ^zRMAOC3#yqjn{>|9;Y-oJhUcci^8 zjQS@4-a2VbY~#Nxnou%Ul2VMJAW@aFQzh4U-akSl9hfm zbuS;(%-LZ<(Q%EDI%NWfy4V}9kjo^?OA8~)Z(PrEg#jTUMG)NpX!J=82DA?%wjnf*1H9W+>_K;`YPQVO(V*>*(TjG$M@p%I!B_=HQDvj%l>1W4|_nXQqSJp$0z9Kc7g5}sc zL@nE)H0>zePL7M`d#ug2=+_*A{RVedh`9Kmt+EuN2}BgM%wMZO3J<0`$Dh*r9I zKYWv{BL?+V3g75*5l91a)b<5Yk?I6m5}qM*s>Q=2AiX^-(lJ0^q$6LXSs=c^`d3*I zd50v1_Q7)oOENnQ?->g6C&$Ofen0N@qoLCx_+RNO_OM^R3P$7pI&XBHH@oY6rR#jP zyUsgZ=iTl)-|9Nw?ymENuJgt2I{&Hb{O9gEKj=C?m^$ZLdXZV5s*}!E2u_HGcy%Nm z0xLhK73o%g7&Fab@H^F%hHhQCa>eWAi!^!-Te1oq#b_laB6#!&NM1cwr=2JzjTzSN z3N8l2@MNVVI)BIzrR5W9IntPQWRCkZHM@ViE%82*?0R6ni=rF)^eyyIW7K1sbG$8^ zE<*LbN>)uqGZrU{X1#WsSC>_qi+v7(aja!Wa8VPS(LK$g*QM8wS;s1k_=E; znqO+Cvsj*JcHMjQIVxzWXv1=Y)EM>1NiHsNz}wtnC({Vf{sPzLB`T^>`;tO(4JW-Z zqFg4G4nF$9&FZ^SPtPYO*7JSA2;CYd(J-y@0B9v_5F8{X=D{7|a$~lwbC0 z=B@$mv&XJ-ZiaHFX1*;@D5RsPPs&)x5%GybUSBnAy}*rQAONg)II&=y~xg83qYhf-^)%TnW%4wu^=+s32r8C zi;-Av1L_o2A2gg)m+4mOA@){TL@c~!gxrp1Y*Hk|_r|H5*qE7D_ZlnyeV3qqB)r5~ z9Aqe(fudMCm#1ALv2D|DK-1ZyLi{rH7-WDfVcE^k|k^(-fHd@O9!UxL-WX@WPwW^c_22ON)I!fm)e4~V@e%RApk+y#%Uk_sHo zx!W8Af&}>|&?H0GOtU0k15-Wy^wY7r1j?t26q=hRc{~lm5QrS=C0EhSE}p8v#y#AX zJsjMRCt?s31z2b3g8OpQV~ zh3aqGugP;RB4M1uc?E)=F-zgpn9d2t73CsPt7s`sPBRS}2wtp5XB#?nvUFSF_|tW+ zhVwa1?0i1*e5G;+-A1DN%|OV^m1$}(Xwj73V6PlHttB!RRUP%>t$3nHTBR6ww6!EM zN?s$$ol+MWXneps2+{^PXR0s2iyv?Wq8-$C)(nS?EE@QwnTvx18G=<&fC5>Q&-`mqCeh_AEAsV> zj|AL1QV~EgYiHfvsbA!?i<|95lI!~RtoR;US)aK?pt?>L^~E(s8Ljo%$}%RU(9jv0 z*etRJP#1J00LgOllGwW+;flc3ME$Kyfp=kg0c6_H4BL2evdH6aqU&_iZ1hUNF{Yu5 znCvuZPtXL}ctnQ;?hGs-4=XWjf+xs??)fZs36qN;Ynw-f5ZmpF||Nf}+5K%WQ9 z2T_daVJCRIh!Z&!jOU#cA$Q;*h_&VzHlQbH5%7{2hO%%oZEoKm0B>Vw_Ah;F*>^7Z zoxQwdg9Yg#?df%+?)Sp`Q!h9>ojxGVIhj}3^sHFlh@{Dc8Z!Z#d^w+RCq$Em2v7h{KcsPEk0;@YcFOkN)7@E3|9Lan zEyh1YyPF4qpc5zMA@^2*BMHVgtD}V$wR@{cE{Yk5!gazK7xvWdaP0Pjea#%k-G0z* z=9~4qSDLk2vqSgl+)hU9D3gYt+X8c#AR+SIZjw18lRlcr(7h?xV-WIZ+RZwuMk4&ed&fW5#J zlUU%0w5Q}(ZHn+8-WI#bMBn3RJFO3$zMWI&InW+~k_^Jwqequl_|4AW%k5UOR|O(&P%f{lcXm2 zXan_>P0DpO<}6l!5GPTtHbuo3X2@k}vwo59k=8g*>Exwe z1>U|6V82j2B{Fb~q}5(df|=Zq&Y&&dcm=~=BE($()=JU3*y)^}lHCKQnsLOnBNBH~ zxRmL}|VC!tG4@lO%P^*LA|ZkYGSN9i}r0xAafP8QJ6j=~*UmO4is{;1G3 zmSrUszV4&h6L!y<=&ZdI~Ioi-aTS4*c36mDH37hgvFdxnP z4AzGURvF9MlP5y843fSQ>CPxGx2^cltyip875TW?ElF-AES<6JflE=Mwm#%GZf-zI z3^mmd9{cScwGnkiOt0qiF0Q_ur905cXYdcb08ZCK58`8WGTMVcz1dRu!Ov$jgbBbp zcd;{jzLTBI>*dAtF2tdukUbVd1JjC{dg9!IL8#}E8n>GZ(dSF;lp$6? zAV{hp_VSv=!%A`7lG-%nmB$1kg#4U9{M1x(;gAyZpjnr47gKxvu8B5R)2=3hz;ak_ z9Pqk(*+FIT0p-r9=c*ZqqDR z={|&={s{`zv_R`7i(tFrtL{ifRDacimEx3ucRA8u@h-0EBCt*}E?n z#(1)XdBU3+pjDthWy1zNbM2B|z(Vh^NSBBMfZ{84msg2??{&D! zI|qAH7_?Kczy_h-oZC()kLXl6iyJ?2o1YqwAV_*V^X9`)x}P(Pw{4ewncY^B3Qq2b z^UHe1I}^UC_c;}rG*n~I37(?V%w<}1`lF+Vz_{sw zge~JM%0!eJJJQ{J4%??h!;+g`D8jVxfV3OB%mzsv>Hy5Nj4xUgACk~pIlh{2Rb1WF$rOYPbUw$PO?{ay(Hf%KBgK0ztkC*>mXygz z1_3KFQRX3{$v4`OwfWZ0{sp)r16_+xRLyovIT728!eZmzqBrt>B$ z%Xc}cu(dE$J9BndW(UKJcC*nTUYPzHKM2D4{tTzh#>ZLbPHX3b81s=fJ#L3X>Q`m7 zuCU@S?c~~KjeGSNO8nbC0|Grz!)_4dG2RmVUT1GKz*D)_h!UOXzbuy{Abl~WKidLg ziUK(D*kyRq`;)>i~7EK988M6U8x*)WpL09ecO9OFBTKRBdp!`Kv=um z-5xru%-70N4p_A@Sndn*uo}TKw|mU_YOV9VIh$N7-~*d1tGt}yyMfzyqKVr<67ZoH zDl?&Pk|-AoF%qG7rCCmOo!)|Zj-YK5k z@yZ)3TATI{_OQE&cg`l0qZ2l{^j`he*WA0_SmTU!ZZ>rs;~#e9>EOapPgtwK1j*|s zySt?NyY)|FQ`Z`(-miBgL?8vy;|8#B;)t{wK~lH!H9M(qLKLW0MR7}@f<;u)yT90M z>bQ$BJQ@n2NX(`9HWfCNc(7d&oZh5r(vHI3Az0?+n{tx8HE(1_D+PHB@YPUDbW%~U z@$(#?A7LDa`}_sJ29A8jG3e51wlB1UMA0dd+K^_)C6V{+`)e&3IzG6TcNe5XJlYqh z^?ADjZMt}=XQ_ucOmE#D@h|n>B^_2UwTt3f=9seWIHhSt+|s^}u^V${kQBMctI(4< zrZ+1Dbz&1G^bFi-+DWL@pKSqvObwtZL)(>50*}VMQ4(l&jI@KG$aiSP7-Xj3YwOao zjx}N?+_0;Xf*j){%FI5n9YjmU}5^QOih1c1vp~oB4v? zsMu7|nl{#kLn~<{E}n28Z=yBE$(bB?kv)SkWicuW9$vl3m<-2~$?8CP?L9#+a(&f& zolI=5EL@}BBw03#mKEiGXk9@;wOePS(~7Y~fus%()7C39WRvop^Zi|PUa5VsX|`_= zfgVI)1Dt}Fd6D02ilz!iEp3Xxy+jhsBMxFSS8cL{QpaHaB1-!ql)AVfcA&*7VqJv| zf--l|*+lNdVyxgfr3FAaRjrF6*477L=n`WSVe}B`w#+0kiropT>f0>;5E;-bcX$d1 zln=Cj>EDWlj=c*y0}mzPFB6O$P3c@9L!-sVi|XNs8jH}d3H3^`;lk+5qux4rKiV$i z?k48tY1bqBdRZRk=-`a;ZoIc8@!e75yWYA9Yc$ptW&IvrB3ELI!W6aW1(jQAImA8Y z72qHHj_fN)cJg4(UbLGHv$#|3F-RJE1X`>($r8qAa}~A%(rXjw9V*nD-WZ;Vj_=W- zS+H5+B{Z8k<244wbD5u%!0E?mDmrf{zr$50cJ<%h%^dk)_l79yw=z{h5ywG0s_fU) z!KigoychVErKfjQ$Je6a4HBsP?6h53l1iG&^wNu(-cq@_;lkke-K=60LTc2O4fLVH zs?A_BhPh+1*;m(@lwppu(%F)`c9PbXX$CNFaG4-wcspsVvS_o2BXvDd*K*BnPr@q( z@cZu#?&$y1Z6UK{N&cTqVkjqgWcEAJ3-)t2%{bZMep9+31D|(U+S3PJvO1LAiu`ad z+VU*rgUY;RxJzY><8MM~@;VqhvjJ#G5#1>0FxhThe77Gtl<{4izcYn4-Ix6!iIOwL z;5@psK9Mt`JEWF0g5Q-9(p~5~_~5^urVn6~EK~in$oWvxbtdpm(sk?pKR~+3_3lf) zh9m#eNLYBYA>*Bi%Ie~$s_4n`%}F#`0g9hDo2{70n`KRj+Y9v{Z~yj%zMa5*p7Lp`9=Wz`0KkjU;BqCx<_$A*j^|(-{YdeXFoRu zaT3=T^;)hm@*6gwlZ@d|U9>WkUdHp1yOb2rDf>kvjh!=hk~FIG1~VO?%Ki}@Q%fN@ zOlNNs$%HF(mN+4?Iw#eIzA&QqMCIK7G3lRhR-81wx*1XslVMtE)?sE+_G?9=%O3st z&mO0^SL(JHHZ;9A%I2fM-4WvRYNm->a#9pxzTQ!rnNVPoa>}gt`U5Q}eEs53evaDZ zX8{8V&P`e$mm6YO0hw$Oiy2{I?&;CMru>1&v+07JMmsGFjH66F^okF4W(kh#rzhgN z(J`M>P79}pj-jgr4MXZqIe)34+W;51eV56e^HV9K%u7xyC)c{^)U7E`;cz6LZE9l* zj#g(hg@;|9BFcK7n=B#i`%>y*iC4^QerB1*U6-JDysN4wVX^nBDs7dN&%Tsa9XEzJ zNNBlE&%GkLqa{U8C$>!78ebR1WwX7X!wU$>rWG}YPd!b6lR*o~ukTg34q^A@Z^rk^ z&lqfXiP-VM*_?fmKtN69v$ZU~Y$1lX))u)#=GYW5zfCQpS)*0G=Ptq>V;k>TQY`LS z(tlvt-pHK&dpy z0{v^CY1%&ANS*GUef;xYbNJ=!uit&~-CMx%7e4=^MHNgG{6Ci8fCD@br@B0(OELVE zzRF_^6saRjWy)ptx2{0%aF9a!t_$$CMnLJAAMe>$(DU)APi1@I0 zrytOd_ESGaJwx)JnTlm)%HgYij8_EYF@DvL3s7ZEk9?tBKd@D7k8V#AbH^p}LyAPG znb`cTrocSakI=Kk&+wZ(#LI{L5Wne%bRE!J3X1EV=%6V55M4d;6u-)2IKcQJe9@0| z*BjIGCc4(OuH_LY23S!+bN?f z&C*K$)Wwa=D}0ehlvI%tOvOrwjO(6mn=e7x8ypK-Y-*IeyiTOCUHz zU5fNiTWr`0f0qK2*M`f?Pp25KF56Q4C56|U%r1ib&|@S0UPeaW#}7U}_-{~40|XQR z000O8xQ>2NNhq$VBLe^cvIPJD7ytkOc4cmMFKTISYGE=jV{dMAbYX6Eb1rasJ(SI= z<~9t5_qhr&vuO)wUk18s7ljT}W+>eh2FF(NX>ja}e^Sof_fft>A(0eEmS5?W{9ayu zdXZR@mHmUvvAz84E6e*2lC2M^o8;Q`5Ig%k@{7!O@812h1PPHR&ZCDSA@SI0Jpw_37WKt! z-)A_UT8D(gMHwpL99pnjoD#+oW*oIinEO;&ZPk*1x#m!k4T(AQPIkvpQ$@3Qup19- z-+}5HhmNUjxj#5|`0`vWxV}QB5E5HJu$X<>1I!jy8?)V(y6m${3a72JFUdfkEc#hb zMKP1@#dyULv=BlYK($qT3GLp)&(z6d zorGlz5xCv{H#*j#ec7m*qm)fOw@uqy^iAh(gxwlkSk3`DdsNw5xGV*Ec*@Z5X7sLD zae08TX#?5gl}JGWWg$)vZb|H*F_Hn%3QyE?xC3nNG>q%!q}`3Qe4Bk#$sjIN8V$@G zXhF7TsPa$60jis;eS(sr)P|~SZG%JamR<6^-H)IVP;Trc+|v9bYo8(cLhmlexR+;h zrT0#gqvAG97YtA5sK9mAR(|4Bs5!x-dMlJLD*Y->Y0;*(o zA3!hDt9?u2F+;*gR;eu-qJ*Y$hQ=A@-G6H0TXR-N!#T@IhU4bchwyx`!NX#7+;NRr?6EBX`!CwUZRW)64Q72v^nGR|y(Niv8X z>@9+TqR5uaF~!!hN!!}R+;6{n^pm7yCkreNhZAOFiQQdQT~%GLF77k&;_QXURZ-U4 zrRdtti$CC#$#gos5IU=iwR#X$c94x|Z?aa%T6c}qqN{bbkwWcdleML)waBx&R;^e| z0naw7*~ucAeAIH&RpS0e*05fRR_^vy)=E*fT2>oCyaQmHM(spa1JJhVbSn#?RoCP) zK{6)gZm*iwpi+(f-5&N*+aLE?Q^OAQgh1u0s$|Y&nF)pbYbSYBw+&3S1FwP7tZij8 z;n7{z+;)4~oSAW{^K38uyd%@z(h~zENnvMu;FlT9*7^9ruYdV|e4xqdtxR!~>E{dxtzSc_^68wf_T zE@h1bQPsLEWCJp1l}aY%2D!4F2>5(_cXjdlGJXB=-K*<2@86{t*ViB3{P^+u@(R%X zou=StiU`uYQmCBMMgO@fh7XG}Z-)=%ChMwJ4+gfCT4$Ag{`*8$S~7*t#QR#@$wm`P ze-QgadjlK&p446MWnN}g#EsfqC|C5YJ))habH2;W{_|LOft zJpoP29Y`h9z&L^55w!V=$A9{JNQ>KDNR9>n^X0qC4;R<(KlCwd%XHIZJBeW7JIOi% z8}mL_jq2L6hC^c@zk2`S{m1J!?=Jh0^TtDl?~g&w^r6lJ5n1>bSATi;>Nx$`*663e zuZ$3}z#+Q@1p<8*_fiz9{#Ukg0@T9lSn?lWSYSI~47$z6&&yFh>O6sx<~l=6#b&}mK8)qdtP2F&poi6DBTE=;2$xp;S3b0E8nN^!c8Wj0 zN@WZs$3`l-X}?IPEX~J8jsZNPOYr#EisNe5sP<`k11EDr)#g8c-&7LyQD8U8HGQmu;HPFnC%(P`1?zaeI${&HjmY7)(-p z2zCtr^hS6AjPaM=C@`)CG=+SC8Q+Gux3a~P=g{BELx2_B6Fd;-=Roo@l51H!Q0N&$ zkERSzgQfm1n&G@w_-SO@K}6&?{0VS!T}StiN!AtH30IziLy~s+8mMS)NrC7#KJp z8qCZ~4YNV7bLowaow*P*vWCf9f^ZGr7aT?#K0Vm4)p z&@@`wvi)?pv3HRD&@;#kf#(50+%ANeW&;87Fmn;5zeA`n#V`m1^^~&K*;#N-sJy|+ zETy6lQbOEpf_KRy5HFSO4VVaE{uaJK9=n5R85gjT@To7Q$Ns<)C15GegDl>lpV$qd zL}AVxQbq?S*hf}Eob(=C&!$rMq_?rBn0{d5l@jZ6n}}r<;c!1n8=lOfd`dt5Zw7dV7ffJD!{BOuD zxQSw0-pLw`bcSgd!?C%En*|v(cqsxTA2RenY}*}Im?kY&Nac#$0-{;DTE!|rsWu#3 zGZIri0TkE9U36SvGo*$UAm%)C8^14C|9!;@B8#9blmJhNeGcae;ez9CnzATlZ6x-? z4?l3m@LO5`mVKXCWiz?MC}-WmalXSD2J^6M)Raw%liFiTI&|S?(d(?zGE#^UYr&T6 zwUGcBvB+~F0yJC4izl%X8nto+%jzi7z;1paN?|G?!K^`%bisCCE8rSg( zR5x@S*O2hZb(Y_T4_{+}gSauY+D~EU&$hnuC`ZRCE>GCpO{NhL?+JA6l`R+{!s(pq zaO0#!Gf$E>R&x3Z(k`ftB-pMx3@I$Xyd{S?W^t5~NAH@^{D0wgu9MyEQPrs>qi zFgpdgW+`=gTdVuprfH*AIkKbqjYKzxwAP`;tSPFepvBcf*l==AMwKN&6)38az%irj zY%cCqR~1ap0em`wMyDbRFt~480hUGy4aNryo;E?d1ZxCY;q-+o0V_7ew$eRYVTmQV zlI?0CR<=HroUMdx^MvF@peWV|DkiFiKo3i-=z+$nCt~GmBr8ssR&gZ+5TZ7$dgYE) zV9}58{_nppYz8@Enoli)cvufC^NB^DJ}+F3`*c*aiZX==7kzzWg=WGxyjC(ogJ&!j zG1Fas!%<0zE_W_g1Ok0uptpF1^%yM>->T`OPKmrco<0cI7q);53L4d&q60W;WMI;K z^uXEU8pKj&#IVMs(PJUNEchNCHWyI>--5`355v8}V6Q4~C8=m5w;e>9Q3L|Vkxz-N zDpq8?!YV6Hzg@8Hk)R|1`bANcc)~%72RLtQtMDckqG&3Lbh3kuSC|-gJ%OP;VrLS& zx-EB-u1yF~Sif(2w=yIjpfbxb9Z#HUMVFYcTxvfHvoX9&le7`ALQBX#m#gT0%_|s2 z_-I)Er0(ewhpdajTCE7~=xA>_01!n-)dyxas6PGD%Gn`O`Uaf@QpESP=AI205P+m> zx2)UVw7n987letR>FKkjFjY1}feu};QMHllx~#E8VlQYhJiP!G>#AVrWjNFVyNdEI9FE2zi&ITJ;Vgo^SNFl#^9Zdf?6u<)1=9V~<9e>P_eA5;x(R1q>`&fr%SrGzFdyVgtgT z!C`I>VtueQ&v72+pWCdpbEVrZXHv*_R<)JQa0$ab-piQw2aW>l&ID!X28D%YN4*@8 zD7-TUKT{x0BkG=*)fNcC-KeTk_h=9Xyu#D&7=!@a!qw{K%M}JCtLOaZ8~$^~e_rq( znnGd3>I_CkkXvPRy&z(+eWRbbY8vois-~;skgqmgvql(wjF&3$hqsbd_t^oM1lu)5 z4MJ1{;yXFYR|xV{aG9!Va4LY@@q`Jj!H^$Rhd3-0njxtjrL6m0PZE3SPb#%sV$jCv zr>C1$1WT>H-ajAeclWgeZCGmyUuRBb}_~UtUkiJ6Sdy4Lf|1yQ|Yr2DTT*-}I_Nz@n z$~bbjcE*=$XJ>=!wXk;j$RfWej#oFmj>COZ-l1(Wtuf~Gct|7Ndz(Sw-xhjcu`L>) zZwmn}(N!#0qb2Q?_ampY74Ow%!z$X8uHhcL))`rc>zk$Pp7ZGu|Mo9wPspt#&q z3DfSeH_j{FW`mmw$N=LjK}*O+nZBvg_QO3co2V$Wl`U0jNd(j0E~g8&JtVq#Ceg3c zB5N}@%K;9g=<^RFKVWhzA6oB|7XrI77NRL3&yPj>n)(pD0q>;@#-PuP4;zNFt9jtW z!h&q*K{1PzSz)W8&LM>!w4|nS2W(A^d^>iiiE0ni?ETTSBQ;EwiejYPKBcs*$>~!Q5TBa|6rn_ z@X}WI#z74lTxh9lVSh47_@Oue=!y&%d705AhQJGJ*N?Q|oTT(LwfLdlSWvHF924o! zFp3%b7?q%@M<>QgO-M1$z_V1uNXPq!qRHp90F$9}zbZTs#OYp0M*I7!6G2XO-^dO7 z%3&O4@*D4rQ7o|dY}e`b3~fgSAr8btq}t=YaiBy;6^A#{KXj)w=2SBnon*Uqv={7Y z#~DA7HV!rLF|D&dkE`8LReOSZ4LSED{qoD4f(;Nnu4y04trJJrw8|+Q_>RE~63KCg zV39`qpPCyLjOm;fJ}0LH|MvQre0*wpjIfbu7O)>CK&nR9NNMVN)#h>gY0RE@%<{0W zPUq3xjvo$~Yr5a~s2I-bxOa15C!upc$Bwv|*>A8w!c#b@q6%IMdzQrlPjKzJN3jC| zz4{G&+1`v+LbT#)p6VJ3$lHT!9K#nYY+yj$s_ppMj$Iwl&+oqV6ntafn1e&_uN~u; z=`2GMNzdmePTMHB7|?tYk{B?R8fzg+N8Xb43&wo!BDTN;&5DD=jxBqX*NcBS7vEv@ z&hi^M*VMk}?96O1fjH`M&E}%bZY73vS>8g1MRXchAf6Z8c{Uvd1FG%``$o)6dvCDg z`Oq~7oWhT538tRbZ)3A*hNx3>GFUO%mmM}H`(uBH)kQ0?EP#urd{6>+_W)al|N{WIT72B*V=+$5VOOwK>RuHeo7gs_2bG+0$QlhbIp5IUXSUyT5-HK zyfpdgubZBaB|V2kc+{Vbd31R)*pFfvCBP`xpZu`7(}3Ux{sjFMeFrsUo8%@H)BX36 zhJBgS$K`E0Cx72Vb1dac9Rg&b9Gl|Dc?H3)v2PGeUONd&6I-y&_~SGRC~CxyR7_xe zg*%EojR>JsbS88sF&2>SBpB96?4bSjD;H2Y@d8ow^9@4hV7ayAwi34SY}iuh^h%af zg!i)_cZ^)lsBBXL1%jr78VDMMSwdWI8$vT`s%IsExtmg-Gdn!56cCqT5@ ziC@#!)~=OPMZZmcyUDy2URUX8*ACC$^?o(|IyR_R`+EDyj*}sM+E=R#wD4HJY+*E5 zbt$kRok8dh2yIZkvs}d!E_UTw?w3~>*U?FHIg>PYD02Ddf~`TXw)ag>{CyM{@07i! z3menP@UCthfZd$DeHXCYvK3pueQ*77Qu;a7-LxoM7JEAn$UPBR$J49BCTKnW3e1Ki z8J%^i<$T-ipW}L*x?VNx2vsXb9xh;P_s7>1`5HT=y5Mwd50JtCJ_Tln=@9 z+`&^;Jk!p{Yd)VI9u_Hf8NjjJMwf*Jy&-bktx-V-;wAWkXO|RDz^++@Dzs534q^6E z!lify0FJV9@U}^6yv^!sN##UfWdDPTyb#J2Y8i3!8oc=3V)Mg6C3{44}a_3b)N^$r?%Y3t4Jn#R_m(~DbgcO z+2G~i4w9{^KBQmzk>AK&2%FT*Eczva^^CulP%*i2O)jq@&%=8lKw$`(QDL43`0Rtx z@>RBL*%I`EmsCtm%Gz2%zvjzUU>lwR50ZD{z`&zc76}ZleADkV1z6?-vM4{@eX|h) zhTr*uCq4iq98AGAZ>49_YfHTcz+D0I0+WvR=w?0y_6t?00oZ5{60d>yN^R?a-QPJ& ze|8@WL$jX1~%WkQSnCcD~&5Jcq$q3=*ejYV(aT`F!> zxg5NT!*NZ%?Ui7gy$Cic4(-{k97=n+I0d;FjK@j7r=oI=1mN5X#p6AnFpfMM+&N_AsZ_hN<+)6^tc z`qHLqf*UO@3JmsfW1}{8 zWS=4{z?%h4Wstb%-QW_=4J6XQA+0QR74!d`76fu33poWxqHWL|QOmf3yhUr8dJ18?8ibvj z{X}iD9F?qBqcNB&+$0yWq#HJbk?A?z=XrSYYeYiv?Ie(y!6>?|CTB~@qyARPBg2_` z-1WXl7+X}GmMCUN)8$AWGwg|djNmmttjrkDzM{WlWPr~18&lwI%nh_dmO2d-6y9i{ zU%_ZfD3Id_^|{k@ylu;IW!zPaD0>UyFK}}_fzS|nAVY$2q>y6$9TxgHkY?;iSbb)A zL93d+k9nS;Waj?(j^S zYHA8!mJSj31AtVHjJbnH*4sAy1uJKpdrY3wP5sz9n}a9~Ghnt9Jle^ctmAJb9u zvj^Dyc|+;i1^-rJT#L40B|X2KWYh~5yZXaQVCxtVoxL1n=Lh~8Z#$ORyPQ^vS+ z+IX3O&7mUL*}d@K1V0lOa!BIb^y|J>)6q_Cf)JCY3Oy$kC4^O8&y|Yf!7=v9d1tTz zLVa5LdxY^UUw}_T;uqhXhHyO@eL3nTXsdf>Zy}k36KRp*h5A%5Pl1$m=wB*jSGkh ziw;h-te7Ix~OHn}} zm^|Xqh(S+nECe z9)yF0Edj?CF8(4Y`sc;450h3U6@EcN6KKR2oD8GDt3l&u5kpVO)S>^7CnSmV)hBsR zhX*Le*eJ}^lM`mC;qkug^S&8VRK5j_(C1ab2O*r!w6d?5hAKcV7|MX9(HRDDgUJzB z&9=!C8&pwZi6JcGewIT_ls`e_V;1o7)AHNcTd}L{y)ly9>+Db>Lm8{o`)h~2!IY#1 zF#ZB2H1TdE0Pp)q;)LDekrXXML8AjO(G>BLsQ2VsK^TSkz&0zt*<>k zj`U+H;Soqd2ZkdVIWTPINX|oy;rhekh4!s`E(u97pf|uq{q@tzuFz2O*yi=if!}Od zAr)_J2OeZz(eB+peY#|$9G(W7ZONQYg?6SSy09!VDMpT2b18Ki`)PbcYO0$i%jgVe zizKJyOb_*_6w@!Hic@Hye%11_bI_z0KZ#7@82B`YO_|G^hs7br;+zH7aL_yfaUt~3 zi8l|mm#_*WCslUBhgUHjG2CbO>I^6T=oIZbW!lSq@Kx`q(1=MUNAKjR@QIaU=dH6A zae`6ddX|0chuNmvI6_q`ia-|(tnPSmi(2ILk4`f0F&&Fh)w&mz%iac;dETje`H%n? z<{WrXe0u@6pzHbbdo(Rbp*_G_K)c|Rpj}G!#6PpLY%RdB*3Z`E6Cvutz}@{lCde8K z9-x17@`&#P;2}_iu`mUWVe3PZU0o{DEzCsB%97=If$7kRGrK_5DM?*XgCvn~x7>r7 zb&zz9WWuTl{cmlbt?2$QA~mz4i3c}4U4!u7FaFVfa&tv5@%3i8EP~U$H&s5PTRSZO zFWyfBXz#dZZNO0yW{$+e)*;@*I`)_Tc$U5n{?JlX0RS*{yUM9GC~4^6YBK4}RX@3G zOGetrHaQ#+rrE?+f6F&ENSn&c#v%uprO_z`<_mUO+t2!JpdEq-;lfm)+DDVpsox4A z#t)C@7qDyR_+IrXDMJ!OzWeKRT#+G;LKZ9G)AGeboIh96G*8CgaCI7@#J~mK@OwHt z6{dSv7}FaLB^})?PL$)qWqLvH=-<#Nf07{J?wh2WMv7IXhGbvBGu)LV*XGeOucF=} zCJnQk_)CE zDW_(4%h}}V!<(=@Z+`%s_eA#I&DO1iDYw*6G&7BflrG)WV}_XukgWBI5Iw1}{#^+K zUf;QaPGT640vU}WtoxSkq&>%$aZ?7(5amP8-mM~3cU(NcPv28J;d)GfT%xEvR4OBv zvlo{%P%<1M^PIBKY*djlpg2_1iod!7S-s0Xf`VRVT=cm|Ii7g@vp|FB2RxUg$j~xV zfWGYTI0ZJLAS8B$a6DO;GyCdvV27pK*D%UDh*HJ4pagUfkS*)uzmoo$d&km_gBTzs zoOcgm_W)U3t9bR;7o40{{+j`sgTA=Ok>fC@yo<$6{lPfHOx+k=|I!XDqV@Dot>TQ1 zuySz1EzvG7$Z9cNiQJ;RsF3#5wm1grtPCPw%0rF$&KrDNhA`;z*zG02%c;_`OQS&( ze1y&PZs)^MJR=aZxDh0Vy1`78ijO+Y5P&d&=FabTaJiUGBV^{`e0rB;it!%3eaq-o z4;DTcb|kfawj-|TE0Tb9u;B0t)Bu(x-aH(r7ms07Seo{+FAV|oXAR?kDUi0g%r?Ow zKQP-`e82sx&UN>b{JXK}%J6$@E=l!c+k zR2;t`T|o-{Fq*qB#*hs4`UiL~jJI{d}kn%GwH3^r2enta?!#~WR47U!nJ zM4`Mz^67MfH=P(R|42Bl9cUgP+ri6C2$0Ouu%-_`!9(!`f%GO<`7u1UWAr2_U5|SLTSq3S(2M|ihFN!h+VYR?C4RFTWdZ9^uZJVOggl6OIUhvs&!6W%BVUy zKGaH|_QraF{M`O=gk8mkeXu8kVnfjP?%0hy8Pi+houDPhvB zm2zK||APw+y7{Ps%@l})ViV3YWxyRmNRF2%VPD)TWN&Oa=~=$q&bSu8mRAm*`GfkU zfdh80+DAKUUWls4)QR7U1O{XyC;E4CB5Z=3USQm<3i=j#Kh#F8`m>W{IjFV$FAWcm z?`SAA`D0ROx+25l{_f^}(d#vPmp9krfsh05GbPu}Tc*tVeLW&Je6%MMXoCKR*c+s$ zzXY)i_5x$+NFmjE#ik2=Xm@JOCt@PqZmj^Cz_v$`pSDbFx7{3Yrvm4-)GOqijEiG- z-Z8lb*&hGK@HE9_s_YTaUQsNl>5iM$bg7o-8R(m{1^7h^A&k&AVH>Z%@$OqYuG6*{ zeMLQrwK+i-@VSPYPKdF7JO@dnW$m^fUmWn3X66+rX<*hU?}lFT+7fXx=u8j4gS}U4VunjG?YEY zGKp}(4S^-Q&jEymZOPIRmPeesSE`zPW=;T85@Bm2G~+(H=%PnWC&EF=HC;5_i&fd@ zdJi`vMi)ro|d?K&kDe|R=XWPJ!y_v!gAjHGSX;R-!f%Hp;Y zKPx{329~CU$1BDvkm$Gltm}x(=AP)?KyzF)=dfRWSDs~T0sEpp>kTbede*T)%^~bo zpVKE1uMPlr&O!)M+JR*Lfjz3?ce9uzZ^)r{@k!cZlA*im-{$Dl_ ztRYo1D#z4U)%Sn6i4T?Zo#*sy-Gz_D-u*0H7C6aw?ozkXBz(EZ+MF2u;I|-VZ4MWJ zmGOh-ab4^v=yhRIDH1o92NMFC&z?!5WxC)`wr0Jn8Jo)YhaDQCy8D8?8n7@|M(x+# zOOe%a>X(3e>50jb)BsEEVZ*#!|fQZ*rwRP`g`-GDs1@`MP(CdM9o#O8Dy(IjZj)-hu zWxYJyJa2x6rzpGP+z!g@PM1JN4Si1Or_^N*+PY#N zKR~}6XEi~CY28o$_AAK3nyE1)o@3*yLY9hbvpMo?tU2yR>r@ygp%w03J$oK~fg>u> zUVR|SHd1NSCBVu8gU`|_Ic6Uwy2ZT2yR)_8{!~JX&6qB{YMd?FFwsa>5!?!(69SQS zOjP#0m&~2Y)&UT_?bIr zs5q)_1K@M4xC$JrfRN$)wtxADI>1^BlmV>K_5{>tZxUGN4XtO|1kutqA1hhzLoOz##~eugAmv>0I6GYccV#Hy6hjM|AX5tae~0 zQkSsR&cA}JC(e+@`>X$+@$T^L?Fm12)`y#?*H;n;O(c<}Gae2f%#`nE|I6$HJZM5> zF-!v}3jQEI;(3_N(>vWZvcW@fvZTACXZ`!>sByN}?PHYh`+c(Z=i%yob=T{26`j8K z^T(F&Yt{F6J6G7;C7vZ{?`Xd;*5^BO_vhvn|1)u%M^1%k{9r4QK$AgQ9RO3AmIMiG zpl6z-#ZA?I2kN|f5{p^D%^7-HlW~3;8h)7WF8A@#^$uVQu7v5u1`@xH5sX`PAd{Q{ zoI}@VW=@J8OxConPDe|(NmC8#)`J*oAUrLvwLt>N39pFFM)=HKnEMO-sAh9(a)q^e z)gJH?KCunKk5wWlDF}Xt0855KTEZ1j^74U7N}u`c7NA-u&^s9M7h>;#O!S-3XvJ-s zOcZ*%iG?772NDbd;TTi8LJPY>pymPwli1y_rAEI+It>hw&8(XwYUji+pN1ZAnsf@M zgezArisP-RwWb7c6~_dZktkkNqzmicc?#M`H=O5T0D_Nd z>l8w;bv22cAJ#X#IDQzkACUuEd=G<50bmQ=)Hs+GR}F?F ztwjeZI1>+*XIPF~pIuPsur}mm3y4%Is-9@e7P(F`100cvFs=z@n*XCl)v1&fmx}dd zTq-wAH+5aOABn7h=&9qa!rSG}MAY49%Q9t6LkErg?$30kp+2jmRjqU=>eoZDaJFQI zSLyNBOYj9}uZ{6wM5wn18cCud*{Qi0reR=NXjN&-7q3_-cSmsHMpPkct9m#fLZV?D zKq@n{G){X3xU-i4L?mw2U>IJ387F5&)CSPc7}T5|!ide*EE`d~@L-q_HKXzg#&yY! zQA#mLC&<)V9J%m3=t+Zixp1^#6f6OF8M%GDpUE7+y-1WTOk(e9SZa~7*#H3jP&P|r zDp=z&YGYOUez-!MsydISMP1F3rwN^?3JemZd_LJeS^(_rHFc+yBn zVi86s)V{fqn8Caw_7#w_ z@Qnzy78dh(0G^F<&@%ByM7w{TPHEymr7nR*c(I|r0;b00)%yp*5j`=TX zaF2szz5De@q9PIKwT-oJ>A(i=AdZ7o-wguA}sWR2^p?+O<1t60YnfAb;yImocPn#2P;+K!EGSftx^4Kiu9unSM@S zL69-_1{kGgD~14I$FUqPH9FfCcZx&ouU_j0tqR;Vhw&&u*AObC!r?j_8c@c+9P{y@F4>hX zMx2PJ;+l%LoTOl0KU?IWw<;?v)|-E<9o4M)L2c%Npv`M>`G3=2?JPb3@Bz%-*ox*c zb~+*~*8~l!fZVL6{zi$mC=_*wwfMQjkQ|h}mRGgpPZ3@sKz_}Se1}2TzqX0WsDX_bmzy&+hZ*L z7ZkLz9(Lb3a`sBvp?nrk9O(R*C+=PuI$lOa_$U@Xn2kxUTj2J>8)e7r0svSzk!Ax1 z_f5r>n`wc^+fqN=9(oxYzrgH|5*PSHl)W&P?~zMO@gUz^%EBugM0i4U1e+|*a^H=q zvgEug zpP8T>vhU)ihZOh+}8IIk|;kMIK8rz_OX8?0BcpuOrrH zOHaziMUt!zuvi%|Ml zLA~Vz249-}Oo1-8vkfmFr!i+e_hnsgVAo7N4i-S!OdSK*!4DDqY$0q)cFqN#1tIug z`W^gAK7N`W*Y3OuV;b*uxi`cr&vNc70fveofMOcXhMg*2=iP&%@*2;wM7fPl@Wg)+ zr04V4m}N_)5gdct%Hz#;knoDtu#)j|b}Ud#u#>0Fu-Xm^{Jzy-HrSATV~pcrO~{ z93gPb5>n-+&6!_u_|K425r-zc-WGK?ByMhl9frI4+qx1JFl_j^IK&!cUiQZn&4cE7 z2g?_+7`^Mz6_$dHy%_~DfA-?n0lE;T=>fq9*@13)FgarMgzH{HV-0N;BcBBy@rIuH z@x~T`-`@nhJkE-$LoiGVtu<;#G-)Vk%e|#VQ@o{&h z*woL(Joo7Cw>fv^xT!je$sX~LBHc0^;HV92BU)?>-TaBofCL&*JBW=z_|)RQap9y` z-)Oi({lz>t^s8hSCY)|lIAR|f&^93o-d(U!B6p_?;wKLx6^~tJPm@#Wnqu|oPK^X(dBZ*bbUS_K2PW2ce~yWj)(4Z z0!@zjn@f}2ygKe?X1Gd4I>D(hA)q`f{bZ4|v{!~OLP}oTIew1nt%#t`;>zFZY#y~( zjX`I#y~%vr>eZzA z`{rMiX%8lQ)?U$#>HXiRuK)rGwc>r?7QG&OTTz9~ z%=JP);vNs=Qbkd(0Tfe_G_e%M(V9B58?R78hM;^r{h`gAQ>a~eO){>`f@o|YidWx_ zH5k3H^7*>Uf(NKdK_`?@Z)7Y$yWg zN0Gnes~JmGD)m8c9IOG68H7#e5;b($5D^XMxSJqgPJ1r==Dm3&0sB>2Kc21geG+|% zrTd8(mN?nV1j`S!=7tG{CEz}Tc@l9Ug^E_OzCTOaIzryRwI;j20wMC+aT?xnj=rks z#xU?~231K{CSadc(GP|YqDokBKjDBHMw?YQ*^wfHIn%ht5;#Ty!S>jl+lN{<(O&_M zrpdvWgIlNy%s}@m;1GG41532O&dw4E@?d+-`D?oa0necK$G(W^(d&jW^&6a5gm6sn zcZ}R*l1ldD9gS4}J1Iju%0z-HSI%{F=te$fA%G4Jn3W&kH$>8BNg4&MqCnG)dRHun zo0!uvP!&FH?*ocODYb*rB0sZ|0FCx}nVmAItOts*7cPim{d$hV2X4<2@E&~c86Gct z?|wi2rf{jM2go>os_yk__%+uMi*iq~Ll!y54F`uPNQ?lF$B;GRr5$BkdM$#5il<3b zO#CveoD<%OMYe$qcpReRX;yM?9m>sX$pd_evje-2O^$n z`4D#xpd)Na!mPjZ5NSA4@Og$qkhz4INnMC$v8)+s0R{D+DGKrUTGNcV>|swUh-Xh2 zHTV~22knlG%W9B)y0 z*xn{|NEh8aB7|}=?-&Y+pY?nB9vu?jo0{BC`p4%AbB6CNaN-6S1RiGsTWi5$sk14m z&jJ(?^Ax|KVC!T9h|C=cf;iydwh-^Kt;xW??22U`%1Z6t#PPkn)XgEMnQ%K!@WSYX z^{zQ_Rg-d}2J8q7ri$dQ&OcX6iq39Vf)4|M=YtRf29E@oVPsNr&~627UX(7{xM9wE zJDC*ALROs-B9d92ZFpzmsZjk3IrWJKb!UC{vwCZfbZ!Sl{klUnsf=|V=S0X%pmFHh zlMbcnT_`eQrLxpQ_}&Sb>c>#pH+7rEklf3m42FUJ4p<%$OlzUYt4$w%Fm@p?eZMv# z7GU=FE5^J#ozZadq#{#vf*Gsx~Vsat36_XpuHI$zLgL8Pqvd~z0c)H5bY z3()3;qSSa?X4lnY_hsyWIQOebUruuv=-5)NU&v`N#u*jbof^Tz^xx0rIZ+uV4+!Gi zC63SC;KI*3d3xAHj~uUhUZwuN@q2)?48QtY8c91ioLq~+od7I*@ISi}+Q@qaXmayuZay@knlAN@2zTDNJv% z3oVtn_QlO;pR?VXVjRhrnOaqV#|UVc;0y|oUbIfSkT234ej06JU3inCrg%?b!4@C6 zC=?1sBkl!t4=Kk-mqGh1<@0 zrulJqN$D|ZWFlF(hSj_x{umFIL++W$WDXPVe-s#m`L>Ny{MHTf@Gu)gZ2TQ$UUCM% zExaRn>Pa2ofqmu?M5wb=b_0m7*?-vnUPgDDq|R>)!cU`U#eE?hH-@tsN004D0rWK! zH>k#|KSbTd?3{!mZp84Q>EP((0Nyo^!MUEF*-j?JaaB)`@84->j{4Ho#TrieJ=#bk z6kBs9m+-Om`Q|cu{{K_F}{vvZP+tEam}* zUkL+qZYelRHbKM9M)w~flqtM9%bt`z`o4^uGW&6qx^naN>U0e)@)E*grWK}%!9TZd z#ISKPJ*`TK=onR{mSaR9`7}WwA>C#!z}7yTG?KHW&u%-cc2NiduecjE`V+1y@z!Ns z=W^e^;jwx^G>AOSk1u<<1xGM6aMWfknG8WxRM59$E<7sUw&mbIOtOhH+q2L1)8S99 zoD*;208zX7wnaFQ=q$@%$Kkg<#!Gq(i&Q);C2uR5JI;xijyb+@NNPUfpqV5LIAfQA7&r{Sh$9;_-e% zmm;AKXeLu>B8gUQi5D@8A+o>MS)gQN@1631qhBiXAsNm>>c{oAq)k7rb{UArB3zQvGOdA zRG#xr3AOH0`4CE-=F#Xozmg5sk!CPbj|yc*t6sh!7t4l~ZTi7C*Sc`S8KMby#)opy zDjVDM*i}uGSBs(}&rtUtLLr{+9gAWE3Z6yO<}Bq^(hQRS9Te9qMH{Loj`7cMagXJd z$G+@=zB<Du__0nOC4gq02)N4rvL^MX8eL%VPUsg4(o z{8qo@ezf&`8IjR|@!phsQv;gQz7Pp*Hl80x+>{{~sgBA~;N4b2!v)fMXsf?%yTW&U zOG8X`tw9w8?b!_|2X@b#9rDQ&EDV({#Nz{2SC}$214?rFCDIQ3br`>z&-wyN_n5+M z!oPsHSb_sjf$vSKw|`Vz&B|>NWw?ak&#LnsE(_JK`O}9tbf~O9so!H@Q@EoiDm2l@ zfJY5&O1bnhdaKK7u`X?&Inl&|#muusRXJ=+`J(Fc{OyI$McwO?45gi#y|>rZb~ zGfQk-P~^kfsn^3Hw{tYV^GWR2$A5Q=dUlM)Lk#p;#oLu~!S?q2V`vR>P@=v>q}a^Z zj-BO{(+Bg)3q}sr29~u`7?_c4K~y6B0OT!ttgzFItq5sE8521hr&USkhSb#RZGyo| z&a{USCrWV#fBh8hvvOs#OX0Iih1~uQ>Ql;kl}|DJjhdfw34Tq|)Jyr74>?u3=B~u; z5AXYP^Um~Av+=gSy@;y4Jm^f8*b=f=G3=^z9q;nWE>5y!Dn7PzKg~8EREJ`tewP+i zM7UgP^k?GIpR{N)Ij{gD9goq$Q*^9rp_BI06Oi@_nj7`1eey*c>Z1S4*qgbzY zESor6Ds^U#T7U#hbx=;dxx95w@!I8U2AA)~84k)Rv69!GL&i*)ce85YPF(}Y%6Btn z?y(d@R|7M-@Dv7Rla@0F`zo>M;c>GlC*`hls8ifFj(Fz#wRwdo&At}IMO5e+$g;w- zGlBpV57LG5aeTj9h=>NsWNlZiw%>|wwFEmo&ESA!2khXs;KZg@0qKdJVj^XmBSSB) z(Qj`8nYo4VXzGRQ5z4iE=)*{2}s& z-ZhSN0y2H*R7z}12djf%B1%q5CakBNoic@$TrOYTSduxg4}>!qxj^xH+{!E%%j66l zoyJQXJg-kOnf}H|!Em*xv`L*u%Gbd{Z}-3ztwXo5Q~&By7wxH?jtaDI)?wR&b@BdQ zdUl+%hs?g4>3hOpY_3%7B!BFXKg`>ykv<3l8=snJY3?jTOu|u$DeO&Pey`7N zB((>6qmOLR-KEM?Pi8P(+AR@r+yP#paRA}X?;CXQ`*w@Z{>jef4Ck)Ut6Ue+Fu>01 z@zKr!y8%Va9M|?0+KrT*!U0y)KcZB$NZWE$6gmg!7Z&R3lX7Gs(FdX=dyf!)XV4{& zs=>hld>{Pu%0XC^x1p`~#6Us8OuHP4TR!d78E+#7ZvYzVXuRC?t1?A4VjvsNx9{9l zu$6Sh(d7DHLcDq~@0VOIy{;#QoSH|579(6&XJ>?15@TB_QJ7=~S=z#}h>5;H|Ji>7 z2MH@;ga!amApGzCn~|}Bv*|wuL$SJo?O_|D&uc9K3XaMSr{F8x8S2RUoEF_C-CQSZ zgL$M77Da>b=GIsN|6hBr(9hd!%mgG#>i(AJK^vOCgX#NIY`amzJ;@Uc-b;qb*Fr_*8dv0)UENgr_M%nrdMMQ zsVphe_Z%)|y$W6_Sf4RzjId2R04If+ji!?9p_>@h!hU00{ueu;`%Qz*t2=|?l|a&7 zpP9aHui_$kKf>^%^{@i5&Oj`HMWO4U!YsBTwFJ{lfC;YeQlM`ZUgka=)tHjs(1g`v z;-Y6mdrVw8Oq}gOLTOxoI@N)Ka&D}a+=zMIz70A3lFe!byAX*b=U9pk>*-c!!N*NXPgXi=TGBkzsl@7{anpr!r2iaBm^-=MMQJ zG^XK}hheUKv1?*rv1&u=MTcsQ+x{0G9y);{c@3&f{S^#3^QUiA6c3AB*?zJ7#Cf~g zQtA%GP3+!LIZTJP&GZ9bw?9sMPFGH3yFb@tT7?EBZKnEi2rLR27DP_*f!WP)Adf>! zK&0mK)!6Pjdc=FVq1D0yHKtb?H+Su@tHI$W9kw+;CQ$k-s~)>2RgN{rSR0mclpv}$ z)&%_5yHO8mWf_oL2%F7LT`LykS>a4jgAukJOtmQye5F~v$$Ji!*j~Insey(WQZP{) zqj0E$Da#8@a}G@d9xSImHhUf+Kw41HH5$>=t}7*Q!;Wnl+lh@H5IVy;m)Rdix*s$U zIGtf8BIHrhP^T41FIZqK2$Bs$Orf3<4;VwDlvbCai3OtE3RuTdUIgOzsIw+t{)ZQ` zb*W%K`U+G-?q1{3IPa%aY#t2EmLJC_5T|NSg;iUTNIcq!^>V7}F@z8MQf7eH&BxWY zH@6<2(;pBh;R?%*JuKzfR3{@ikmrdS2%lg2Xr~cj+Xb%_14}mC?}TxRw3!|Z7oJNC zoEDIYL3z%W{ADA}2$jCL;3`k(=fDymCle6G0b*b9zK1oa6>jb<4$Va`4uIdfgR=?f zsJ8PO?K&~roQuf~abf2pj(MC_$@y-(3}(2W>&2^0MKWxs1iEpRx*jXLsrtC1%(>;5 zOy=RM(To?peK-4b+zZY8d|0{znU8hi4g-Ie0CNc(W3}3fih-}y^KWI?_n+9HHIg*( zPzWLPK}_B+bSp`mVJ(#=T4DPOBXEAi;=Xa8tq+g3PWrlln>#{Zz%RYcr%1c>2tNB@ z1`73i5|Lra{D~SmlqxIsAer&zXh_LU=R4Wt1lfOE8P13Dv#@9Im6D)%6|uOnQlB~z z*BHP)by>rEZzpG3lU&7VL=E5+n%IPQ7TWS9l$Pc`RdDwtf+NHyqDP zQgr@eS%ZcKYa~I@2Y~_)F^J|J9W}RlGeZ6rB6D6U7;c~qOf=_tnN|*J1fB4>o|S<2 zu#wPoH7+`IE7;<Xbw6i_Ns6BQPt9xDuw2d)rj70BXGs%K2U>pv;FfGa%Et$K~v zUH)U=v^wIyEwN|$Ef>coLZRK}mhOaU$DQrOw=TZptg6bx+b9ddiqr z%XZG;wA%)IM|aijYQ9ieto}#}1}c_~3N$xRLQkp*p$CG`-cUcYs`#=na#;VP)}g;K zGRXPA@nxK$Gr#l&Z~q2RCrAi*#$8!GSIT^3akP6!d1P3OlzY3~dn4Z%Haiv!iC!5TCc9U^2qCPn}~qm(@Ct3TobMxz-8r6o+T?Ro&^xdd$m7GiRGu}2aW9F zXYX#Yny>RL_?bjWtZ3{bqbqSH!yiK~!yFV&7QD5W^N$K~qdcrTUjr?V$m0ws!~@aQ zZU+b&OS0Kl*N2l#Vkq9PH$J@ej?%ODjthF4pmfHbI1xPAGGu!ARC{>6{D@^1Wl|QN zifzB#fO;chk817oXX({{|M@Uu6&uQ^#>9k)Sc(_dj8wU~iHdAJn@@f00y?zbJrJF( z-MDRYf)b*a`CUo-I!t_%9iWx>3arso_^^5Lww2!#11Xfg{uOa&$rY{`#;RurTKs3E8YH_4m|F!Z&Z*iIn^ z0)k0~-p@k?A0c%)KJaHVZhCrV4Q}{`J>xvwI~EhYxl0D#;o_ONNbE0YJRaWv@O{>% zrISb6?W(l{{k#&PmiGObMNsvBX=!!#OweBd!v+^q4yKHoOf$7m%g>cNm9N?~A#rpgVo43uo zmSr|rcA97>Rdy;P(Wu)I02iV~-WpVH~C8(==q9Pvi3 z6h(z3zXGK6=!H3ER$vL4L$@E-g1KMSfUKv4leoAA0Wo`*!`~+Sx>(Z~zQM_1yT=`T zXfJeeQ`$`0(GaXQ#3CaYVPwO2#*-6hQ9O;c5&L5lYfJw_L<&9K(J=Gv_5lGIN#9%; zg5Pj38Gv&TA{VOH2T{0Egccjw**n#`&`Lh66F;oy2iio7-sO@p%-GRKWW^ zB@kgTL`anN*S#oPv@6Zht#yXB`6{HfU;Y;~=EeHAVte*^#~xc#RxDQf7{h^i88jK& zg8S^nr78irg4;LfOa4cBW=iw0{Zwxf7fLZB-+H+O&XfZ8U}W@>i-aF%)u;f z_v0Dy$89%_XS2;iiRM6=#3Nr4Gy<`21%xiVTP>`j0IuVK`yKT=F_`*KnTZI^t=plS zUg6uFvo@IJV8U~4@9ib5!=Wx&DJ9k4%Qg2vjt`OuLr?!4u zEd)Q27j_`gK%{&2Aa>O_#mMZGIcf0-G56`?UsDLIB9&jpfcF;t9nivm+{}!eto%B; z_%3Y=C<^!G`Q2O|j+KYcqB8E`6$I&V=0<80$}yZIV{^}$5!;@@{0!5|8^TA9U@1;= z#gV=Ez!%2Syp(MmuQ(_yR4w2+d0F1$Rwe79$&li5g4fF42R-J$MqTAZWroWYoA#ZC z9;S(O<^zslD*tsJJUoBe0)c-mV`rtn1(}l5nb2{!ZQ7(a>_V*`+pF+BI)>dX`aX|$ z_6hq%5|1I}M zcKG+qwpNm{-DH62zEnlH)|ZHf;(`P9IP3A#?hx|C1{1137cQg0D#$AOd?r3-ciwn2 zP$$XV@htL!ZDnhfS3EpCfeYE%@tMbUbasC363OHJocSFD;czz^BWaIsjKtJ{g5ArP z8@n<_*0Rb&E_y+2SmNd8!N$*ruMyQt;7RQ_-J^y5+b(K`YZ^?}mkk{_X%_t+(Tt5j z4q+xf6P@(DcLg#REFYkyNMF@In)3Iw!Hxoj#Khvl10Tfm66$;<)ej+$uvRZtzOyV3 zHv29{0~$dpVm(q4nvXJEa`hQd6(P(6!=M1+$?O=7&v;GI15tqZo-s;B!laSjqSYpJ zkAKRXF~6==sS#;afra{D+N&^<;mKf6yTq#B*j zpy)5!aWv<);a}JV>%ZNoB<4gC6(F&vsOF2seXTSn>2`>V{^0RrQ|hEI9m;9Rdk$1K`GPjL9* zuv2yXdP{y_IQ(D*4$ty38for3uAIbo%DE>7?t!`08Zz_6@C*2#Wh^77bA*o%0FdGO z-($=U&Nlz**!W)&FY{Q&61T?ho~k-EsZ}+tT$sE*5Rz|U_-JL(%(wt~0-x4lHfbP{ zHkU5bz6xQj-}&}>+^<`iuP{ali+3TZ)1XBT8z|S0xuu(4%!Y>>NGUbIw1ki};#(@jd%Sk8hQPxSu1uF>cXEWobWHhmUyHEW1oAgE9` z22UoLO=$Qa%p}+S`gwUqxKdU6qqM1%$$CA3!=BffS=g%AEv_7qV&&petb>0UCFA6 zs$Qs2Hk!;?#}Bc_mHt&*`4U+HOc*Xb6Kt|um-k&?Q~41t^Q%&`Oh&()fd#1s`DjM) z<2DsBTZsftv8%`k(p^K(Ww|M8Ka(UItc`pwM?ZD3lVc!H{j8T^Gwvk2;e&YnF+#M zNMCtD0D~pdJ|-QuQKpehT}<6Gq2g@pyC-DlgD4R7Y&5clSfmYv>SkbW^AU+^i-}SyV?OKka+6u z4~=F}Vnuh$S}N@ko7gY^hp%&J5(Mb7XxX-H+qPX@w$)|Zwr$(CZQHgzJu!=k`4;mR za&aSH=DX)?!X=N=ylWM*>BL*>->3C{#fzg4(^wDq5-HJ$6u)2aAdSt^_f=C;iQK z$6&tz-+Vn~aj%%7k#+;i&y-cFNVd$V;#j51{sTiP#f45AY56>N=Q>9*4@Q1d5#U3Odrqceb9y~O`6d@uh>DYK~c zJIejDQ7PE;yg+f-RIp>ZkrNUOT`=RsWT)gD1F%%{0tZh2on{#tbcA$Q8%1lG=obd9 zXic!cNLU$vHEME~_^BHZ&D1-@*~NMaxVQUcoTWXxZE0_XzKBBvVrSl$-!|d&d9?7z zooVGQF5d!bw=RZ?Q5YW_QztxECE=sIRU%oD#UODDiJ6&#h!)wM3D(4&iQhXcp5;-D-KntSAf zBhfGt?QFWEK-TDvX~>6|@*h4U`I&hx7MOAE7$GIk6+XGpbmyV zp@s`>m4h-3Zz0-}ScPcOW|l&9TykIrl!^r4hka(P>5WPh@QVem|Dt>8*w7Ga=h#uuH*`a%h^o*wp^sFl^u z3UzjplofEGL|*1NeeYh;(^jA!OyIPa8nKqmoXj9cm`!7oEWeRjv)6Ki^WUs1bf(Wt zHeemO6zOt(5&d(PZ9(m7q(ADTBkmz$pOIqNP(fsu8d;V7`i~!|h&G&CiAsopA$b;I*0-wQN5HTqT>x0<)?)Pf+boe54f>qJ zw#L2VshVnsuJA=@3?l~^bn3I8ylss7&@^Oyhw`hJINap%!uF)ssicli#;4GVEYLzN zrRq4H9+y(A=EHv*y7I~pnl!#@xe_~j^KeVhPFbkkP0e*?(MM)=B^Uy$RI5d%p<3i9 zz1>s3zHfbV59x}oO`U@zFT!rTU;KVp5PF8L|H6*M8w!G)b%=B^#0QlA`Gj)rYU>8p z8b+^s(~uWgW>$mONK@2WWwr<2TvUJj8m@iv##6p>0&1SA1%L@6)@hCfI27p{A%tQy z4{SjqmI@9MYd!=BIv{pkT4Uu`f1D!{oH?p9?3d=K2G<0Lg6h{LH{v1;Ct0qRTgVQK8JwCS%6<=I8sXtoI}EjW z_;KSmsD<*P+RaVCe6FTn1MR0GHIr|qI7HzG5@ccngIowV66#aK03D+^OXqQwHUHB`t9+8jiU#$lu?133-MK1LuR}5A|6kr z{=!Nlhv*jFiOaG+Q~Z44!gCH+ zT77&b6Tf3vP+g?Q?GUfW?cv+Su?t(x(|AiF3g;Q#YEz&mg6(LnHaL4XW4auNELL(0 z>I5q^hkM|~Sjo}A9SjFD<}-v}C+xzLL$=~3fE?A`B7gu;7!oZSQd0|$WCw4wmkr;> z3e5ZpE6moN4t<4YJJEC;n|qS?r;VDns4zIjH(onXNh}t%DjYTk^NY&ysA2uInqU(9 znlI||a4E-J_Ct|F2*V?VPkAsQ66v5KLgn_uzzK5XhkUJ!X+wG3iS@t+F0tzU#6gN) zzB?1E@#H&j=a0So^(GFWNgfBWNc{>@AWq;#%slKLUd4>m%7Q^7n^^6@;e>1wJpj&S zz^TYDamLC16bq^Z{Dj}@7#;#%DseTqjme_S{)Vx6S3KZ*C05HSJa2 zyxjHy>fmp%f>+SP-co&*tpH&5T#WjGjoBqu%~vfJ7xHQuEv#$plh)61H~Q8VRQm+e z6037xDBnubbT%Rpa7lBE~cR zymxNO3y3H+$6hJqU8i^4t0e!HHNECoXp;M%AW{ckRf%dN-$9sx1XN??Y4i4l zc&!Ei4K60I1rNqyKPiYM_GUC>9oN=fv!AOZUd62XWW_QMD8iD^V3hKh04&L$wTb)n zn7ic^XyKSb%QbRgSc%KTA|nt(3$^D_w4A|{lO15W6;}|wG!mN?Y;q)b65}1Z5~D`( zQV__+GZo`8(xV3>At~Lis9T=`6IF@c1ct-lt3c1Q{Y-Kvc$zr2pb~8)N7nM&cj(CV zcRuvYI~s{o5&q8-p|*IU1%9+_M?XAXq1oi}6?KdukXcI}iApv6;1#1M0w~lX(T@@p zB-{RaT;f-$mbOe>977J=v!8s2M_=7M;PRwwtPk$b^ZTNF$=xL+bp*f<_L8C+hR?9? zFd*PGz@~~Po5*HgA$`ZLA?LUW|A@J^%guh_k@Lg7j#8P!6$0vN^iG-2H9=k@>Gy#| zUf^J%^97R^R?KgKZz=5eju7WVli^Ex;8%Cxr_U84WBSu6!IrR@+s`;5KGEJO(qH?r&Dy!K;{=QHPNu_bUpI#)W*g2fOP=Z!QszM7n zc4(dPWQCC#a{ie7baOfyp6+zwEGL1Dpc4xM_99m0IS3|9uGU{!#Vsw2_sZ2MQc%wA zg${wkpvVT;J!nJ0a**D^gW>?dvVVnZBcO2*$@PF{1Ys;8W*f`rFO(8suD>W|KldBm z-JQ?qrOs&vtj3;!<~d!6P^i#(4mCu;hTMLnt2cZ>?j#Sea{UJBc!(aaPsrojBTR~&a(zJ$ zFdL{Le&vi%*O1IqCrM$J_Fy@pYX0ZZ@5SuFT8dh3?<9Kn{Y|JVX8@j`JS!ZB_-m$a z^P(^5^zN(^Oe=1tD-u4Jt9CS!3wR785Wj=h`#~$vctvsk6PQ{qXYa94sn~3P*8eQ` zQA&R9SqIUI8Y5m=#$}8pYt!&ot{6l>TZb+ z>@-di$7bau(#IJ_Muf_L0!$e!!a%_o9%Vz|9JSNvHgvUr*r%AzI!c5#R0i}>9mA47 zsxym)Nqf8j^mUg;a%kiLxUq!d7ssdpwjXUnrrnP)@S3{Tl{AO9>V~QmVq8aM=a%Zq zn>wCHr~WZ6Qt^Pa0bxbmNm~{IP=6aSjVMW%DhDaGVhnQq_8u5q%3KbEIKrLyWat8n z{oT%NiSjDIRRXltVLTr4%bFBo!yQ{H&+ zBJ7%|+@Psw-SholZ0IyeDZAlG?j;YykW1fBtEV7b2gt}-W+)XbVK*KiJbU#ty1{V-b9KZR!k*U~xwkABjf2(hK^d20R_^cz3Vw8G zo^y2t6t!B8wP_LtQp)a2FX8**mG+C^+c7&%mhR zkUQo$Ftqi4^8UZI(@)&w$wA z!6%vlWIIdI#|jvu_2@VSGFQVVMRh&nlMB&UL~`OoyXO#y+ld5bc$su)V8k>W5wOb* z>JCVs%BuX@i1xTP=iA|=0l>=#sz?)n6S^1!y5=34_Mt%bnz?8kh3dVT-d+5DNym%2_ zpounlVqZ2vB}TauUdRSMUfp7QJU85Cgn*rew4cGk|9l;5R%AkoW%{1wULi?lS>Q^S z7{Vzuk7%rv4K#Nr{Hgo;8kMRsY8U{#6`D59=W0Q^^Q7>nd!QOs zsb)7jiFs;XbCGoS*xNMY<8s1QD9jFh9#sqwN@LTJUB!my>-|f~B4pWMgw9RjNncH% z{6~Vqr%{GnfI`ma1ORFvO?cafhncbxHbzMPatHkz1`PLE=L>05hXa1$br*@!!P zVP1|eLKZWagf5r%6fRosCj>t-W9zEq9e$1r8ub~vMyA50ItC8zTgb^~1A0xXe&qTL zeR1x=EFUQt8VqiZp!BGDSLs>V^|28(5BfT~F2+CUA!!{fqCkwX5LSJQ!r^&VPzj9J z1O;{BU8P9a?ZylSdaw}qe7ge3dE^vD%2f;w{0^yxi7XMOmBtRNax(nXv!yV%j6Q11 z#=~r1Q<3!TS0(wAbC-YqlI7f;ATWS43pMM|Ko1QEN)IbSWfEIRvGn3~Y zy!c$`!a~RN^70bjFvNgy!K^O`~ z(usOH^}||c%Q)MRC*F{($&TNPU~~`BNF$52Od-HsA+C>@p8{Hwpb0~r7^UU! zP0pYrHRi^bjc2jt5D>-sx}s-8>PfH}5G9_Ubn^?3fA!=_Y;ZR&;9uX~*RXM`gx34M z&WBwWQ;QR}tl7X|GGOzrc!Uu{nJ#-)3iwXNJp+qh?dYkS1Fod$9EQW~NS>CCoMq5b zktZRh8KaT6Zo=a3|J z5uAG?Rp{tZVNApxKg*oGo8WX8S;*YSGzS^3(!}`homPZK*)pYKe+IeMT zx_l{wf7;Yr5aeCTp|`j?C3&?t(Yy2gHt#%FiA5`f<~a zf(e2r?>%8_j!qw8#maC6Y!eBQ4I81;*c*u#t6L4hDnsCOO4^_8jR78>eR%pzFc)|kB??P_Hs+FlNt)B6EIE9=~ZSz{JN+}v{qNGYAl6h-&U}_NmcN68f+}d%d)PDi9jAI8@ zeF=#Q>H=%Ts5cw`6O?l^1r0vrMh9-}`V;4g$l^=FAoFF05K^1m?+Z>CqFh02G*mW! zXnBUPWKl1^YFtS)nxE_J?ynXLGB9q{EbSkyjhyo@Ou`w|eIrSJEGPVDt4eVwk@R;H zAk{sN(;S|-T`Kcd zTidva;xNr+`%@l!8HRA;+fjAsf^OI@^Cee zWgtWT+XVKp=_saS(E|rv*}hnYHwBDWTxm5>EWHnrC^vqKB>YbNuri-IgkCVi2dCKB z&LhpP9Zf-~)mVhv+|BkSbEn*YTVeJq(16NQ`sNG!OBBuINc41jZO^%XY zGFd@od?C|W`icI+>GFv19w-%Q**W~Z0w!H2vTRtBAAGRmJVGwbAx&Yx@y#IL$t;h2 zo;m(!e^Li2$~zxaJ}s}^T?Ti!w(`6_t`$aTS+0SOi}{G@E__~#g^VSGb~Kd4bKH%% zMNHQwsVab<&$LbH#IZ9N`b>vttB*QFPibAGZn`Ssth#GNl_t#^E1PjWJB zul*jrOwtEGPHT8e-du89Q{O$R@n3^1$MKH5{JU=4>GBnxOU7%)GPAF|CoUex4?(VW z^eIXDxF{eFXY zzFBUg2fu2Bz49G#xTtk@lw;JnMvtp}SJ_VG8HWn%$LONP^r0UY_EFOP@qWGwl>PEg z1X3-WSJw%Ec%!%ST)9fHp%D5r#7cx&hkuE@lyP1 z?haz+M#v77Ash*PK`V~T+CFUWW+}aONay#MPJmUtp5qocoCd-0u!*uTwLNpX53WlQUO9zZ0Ic4jd+8 zXk=K!#T*STd$mqqzSW~?#Mj$;1={m@w#9wGYx2_T&DqAPZ-v~$Q=Kn}~xy%ZIYj5LH1#( z{}P}iEwY$RIXk0WjDuENJ-2P$_`uq0y?WP^8MZ^j?iK_{u|d=1?OwCvM9F6};L({R zl#jWmd_Nfa=D0f-L!;y1Huf6VGxPK9W6Gm}#EE@YXB-c>VO6wj__1Of=hAbOY?)Sj zyY_mFnsMzwY7BWl;v2X6S_JyS0lbzz6~WVxmU9k9(_Jw=LDE{JJ?33rhwYgi$+8nG zaG#zivz-h=_&Gsa0kfK@&e{6Djp(85o(H=;_h_ z@0N&>ox78{?O$4Ej(>mcMmj38vDmB_EvLlkQ>L306`Fg-kR&KevLF!Q!ohw}2&u<& z$5wDrT}HDb>zJN(yyG{P9vjIX0eXH4oG(Fdh+pCD4i|a?LI=%>*6i71w;U~}_m4b2 zdcK{#xkPS0o}ag0wHW!nb5`;o*UIK6Mi4M2VFqX_ZEy_$oj&Tp&Pk$kvFcvI4R6## zVAgKIYjNVK25kD{$Sj!i{ER~4j&dqSqO^2vWPhOlhN%`QET~h_QmPI^@LRF4i}exY zC&X(qD&`4j?hB(R#U0NlHdL&qdskR%=?mv&izFg4)3D z3L%u}>y=k+t|sY>Dl6|_3Iw3zua zOswhJ;M8#tf=p9(nC|Bt&5;jhUN5V7zEaaNqF}^1Vltc&e8fzfb-y^ru4FOe{&3c^ zXO`6)h|h<-F)GJkpKJGq$R?I8w*Rry0bxfX-D(=8)3_0;D;rFGvzP;&wGaL2ivxQ* zAQzu~pP8jeht7j-;S9)2VY&- z?E~2h{(u{(iFiqXCsTXzGF0NyY#m}*XI31Bi*tZ9YwT5myE*d_k`1DUEFN%Z

hMr<<>42W(!eL^O5IvktdWJNeb=bkmt9(c-ccNw)OMr6B`V)wt^NK|3>H09&LNq z)I1<@E*3{F3lw8ll(^daHMb^BX-dE?LU&F z<^^TXgB$=rNCNyg46lrDgRRcmMu)zI64v?c9C+XpWE1 z0{QKEDBo?k(M>J-rLp;B2kAB2Kb@sW7$PBCElOycAWg54lFYBvRNAjtYVs&aim#8+ zT)bRYN_oIKicS!Gm$50!p+2UlT@AT>SIT+N7>i93Be1Q@-!S)%DlUQdwzq-39XvEDhwu}eDU!QND8Ia>PG?W&~$Cn@uevy2tK zK{$R9ykR(g5x((p(K`op$$QFsMBpBSs~^1bdFk6sptdc;RysF0MUKn3>OcOJ$~A`P zTsQ&obd%N{PvINp>z`^ZUO;@2WCL6+yi&e`(2lJyyu#3qZ9KF_s!6Qs!}GWD&(>GA z^A6H65M}#r(dO!}X%Jtx7?Z6ZT|2zHBIz8-(U%vJjPD-FF_ahno6$WpQ^z@$ZMeGL zctvxB=PhVBTYtKnvi3N04%_^c)@b&AKTV!B+G6atcDm;70%*xQzN1fHhfes4vg8}y z4fCv5@*zL?ZMH7j)+_Ov8}cb_jdyc;?o+~h!ZWD5-nU{Z)wo(b@||&%r7_-JdPk`- z!0*z)@)@$Ez(-y`d8LZ+iIZ3>6}*5uRPr8xW18mJcq|}ROXL0*)KPfrFT)${LA1+! zWz|;5XpCNcrpkT7w3_BLH&YWpYelz$zw{1#+opO`z;nr=5wU+G+8pjqliPI1`U6mD zcDmOjzoI$+&-?hSc1|@XTW03h)RbcHodh8C1)UMAS+yh&J6)2aLKgD1E*-3%gEu~aBP@Zv78LB{fn1{2A5ppZW}NRF@r4zFd{L#7L2I3^X?RHeNvov7 zqnqS&(%Kst=FgN)^GEUAv=?j_$BqW$M~~pmW&MtWy25*lJ)Hc@MHEsCl^$Z<7{g*9}r#o64Y+r~31xspM+1=z)R~W7E z(Ck73R}$$92@bbU5T1^fqYpAiD!f+U*i6(;13C`VN!K(?H&a}M@uq3ZN<~QRS_7fz z4rChlsVX?a*SpJy^Y)xvgSP&pG!LlMjLZ8w4+(&OL^8MUtMK7Y&N@9 z9d!;R)96~xrHE+&Az;nnwEdf^H_PSWedX*{E_*1liD2-*25rlKrk(yxOEnwOeWQ{z zTyxgN2XB1M;G}CZJPK(_UrfDn9c5!Cv-p~=(tTBq3aR;!>U=$WL;Onx7Aopd+yY8Q&9g+ zvSUsxoOrukH+Q>7NB|c=;INWrIbx_ZSjF{as?bf7q&nbdJTmXH&o+FZidvvDkL(P^%a_ZtxlLtf}+-77=T#4rzJG zXtCu9=t)oC`Xw+&)zcV#-u6R4=iI~2G>;{r*SHUQ4~426cca=(UKA_zpaf)rOW^H< zP_&G(U=#A-Em1N81`(P=szI=LePNWT4&!c&9}^hrVP-Lf1fr=O{p`4?~K( z+f7cCan6vL~o5>k$`srC3ECj@ook}2K$-mp& zNU|ZKb{IA_JS)Chs54LD-u%0+k!9cyqCcRPz>Uf_7Qmo*5G)Sv(*j8oAL?!vr;iu5GWc0XPjVEf zm2G9b;kP1nU=dK4_^_8m8M`nf3bZBVq*ioaHTM^yNLtqAD7Auu5Gq>AgzJH-rMB%; zk%;a-IrzTnfVCLmxx{G^wx(K7IplZcH-|X_-y9vIH+r4~*JuT_4CqRlI}qy%=z~6^ z3e^m>i7aIFTeLz;ODwY%A}#%^!fxC6 z4*V1;_8VrtC1@S0b5y@gMjs2&Qs75j%iK5*6vYwgr7kp<47-|t4RSqbc0yK_(y*I? z^XQ9Kmia2+g$_HYcIHrJo#D2wJViOsi&&BS{8Oa&nCsd@W}p3a$YHY=H7_uWElq~M zDE$mN)4p8=kS|Iqi!ke(#e|VsSKb^l)rNnWig42@yS+Q?!LmDNY}y^k5xq(h3Y9U5 z!4EQ36QMYgOr`*DaDE{0d0 zkgfsNBG*Mh7vOnFz;OnOxnM~})sY)P)L6_FdoP8kX^}t`J)mK?3VH-dAIm`_bPIix zmV&}K4o;cqVS|V?5^>78l2%_?AgNxM)e6W1R2bz4-h{pOkwkfb=`7pAErBa?MUv5n zZ0W%t9gHww6v(VuP`o41GCJT~^o}{>_O3s*sNSBiz5^eKV1L_bmK0S$;`02nJy;1} z3nZCJ!3qUZxbl+Ii;^W=JtQFt8g5q<`iMzt?o$*fk?7Q|2-V7$?cR>vYxk3k0Le}y zXjN@+Oz2jY@0QcgIDxXk#Nlrzn1dF*YJ=E%@JzoU@RO3`2V{{wn%#p2(?1dVzl_Eyf?E~^ z@PYrCtj(*A48fRCTbR&4VgLs;;zmHtX00p!qO5-lW3Qy!GtrcZw2LR-|42b*!63IBrl`O z=$6wj!wmpBhHpqUr6-nfGlA=lIfgm*!*b-ehi#;iz)7+HEm&U3&|QcluuZr5V+lhZ z1R*#mT`4oV-|w*)?gULDV0^P@z5Y^paeu~r?SPF;iQm^wO6~JnXw19%8*Z0dwm40^1=!todZzpw}qW7 zPFPHiN((BwG~K|6!p+bYqn(TxV>_t>dz~Tx2_c02kg_%HgyNG?u2Q1E4p{!qvDo1u zevGaTCZ$T{i8#^VzcOw;c3Sj$gbg2X$I>AzXsUb*Bgow@7o&H6#MY>V6gIp6w}*RS z+!jj)yyp=%<@!ji;VVs6I>;llp;v0KsIiV0hY(eQ#k z$Vp1+D}7`4oe!S(?cAsxIlQ(Zh>tKe)l`RT?m0%|!ZfwaCeF2SivlfPYbfBbATwAN z!FliB9+zXHixjeV5&&3*Wd~~NBHGoh5h#kp)$s~2!44FV>GX4pe)Id0P;R2{<>h5V z?QbI8F;m0|0K=T4zEKWhPegQ{bw0mnOmyI8kCm1&mB$DjKJLvcui$>gABIc3- zT~W&s*qA_^7vQ83nYO=eoozu_6c^0A`7_%c!GCR(z~WZ($78ZABXlDK1ODMp!$G^| z@YD}zuWTW8549`cWQx56 zT9o(3H6dVX;Sb33+>E$maY0K6gqxaAOLnwflg-eZBu;%bDsK;j#ULaBXpj{@k5#7h zR(Vc(n6AG|%!l}Qd*RO&i<29J`_8W)zi0!2yC(P(To+~;iYmnwqJt2uzQ15fqTVTbqpq-Zra(jW z3|5S;^RQoY0MVJ2K}Kli>jdev;Nrp47L$1q=>JN9Kq<*$pNwoOfF=2K02)jOp$1^$ zx2Z60mV{KvA)=@qkS6R)bwIs3HRO$8# zxUbZQ4sas(6h&MFe)s+bSi7oCTc1*{~NUELZh2$ecqvI8)By2I=9Q#rhtUfD!b~BlFJ!Hu#|oEl@y`V*)C; zqpC2~pDu9`B-pXp^=>h~Lb(Phitw?RwrPQ=ign(ChSkY>-}lP^-=8 zbc-eZo5kQBinz-nwgusa75zH{;Y@eph@{VJtasiKewvfDV|H70u+@lcW>Sf$i-@-| zZh>r}=UxE351i-L|5C*tnwz&s25n_!o`&JHCM!_p5Q(+m)`ps*8x&Z{^0`XIcnM-X zt?>0=Oz#$yYq30|$Vcu{9SssXd4RML4$mhFWD!lx!O{65L)R(BAV4_kXLtM)5useT zAO{f~hAnsjA_u|S;k6@LN(*+QRXDc-hIf-~=n!!o#q3sq8eb-lV6{zdS|uhsux^GT zp^OwGP6RINJp$K`&#$6ds-sOzD>$!jxTs&@vzUSQJNT~v=n!Wlpj)#4l)nl~CXuUp zWz~cPgpj733bM`u;-2o))t<$j@<&)@TYxSn%Bw9cL75exk_m~W~?Yqa1!v<68pf*WDN}@L}#DuVZPxb*Zoduj*Dm22laxJQxLSHz| zB^PY+!##SUzK$T*LK1Sgi_RqiIpF<0fXx?uO<5$M?RO23NJxw%y`K~Ax%n`ktfN#e zBWr1&_(vkO2owop$u<`TUZcVQ8zy5@FXH`h+cX24xZ>JCWj;}5WWZP*@YtIhAz!A= zsEw-^-26F976!+m3Mrx>;oCLWRcJQgf_-{V#3S6;aCRsc6ft2ware+Vzeh z1?XH)L_g#oIyXZM?F9@cHqcgpd{dG%fl}TDGl+ZxUxiuJ zK&#;zdF^AJbg;�Ry%IsS&7mcb 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�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

vx_4EZ{)OI9(5ke{t=LW` zSrkoKY$YoySpTnmmObz#Hgdz(R>7pt-cYMz-~A}*L#XK2KB7si(wRBk3Q`$5+PPn5 z8|Z8gAYEdr)4n-FPV5iBfB)m>ZZU?$-_6W{@&ES9bal;b%$;;~e-lqv|8w=k@;|*Y zeqwSfu$lnDd0Hs+wk>T<;BBoy;?O~T1n?%ITKAPmDuwkn;U7=a5L!f%H|y0*Yx@&8 z_3#V~2V5RTVo`~vipqfDf||;VaRbfejP5YP#fr*ka^+1cW8QEDIE_h4Bnv%)S~t@3 z9;+4PO&iN3;#{F>BV|$u&ARc{JJvg0()b!zRfNFYc?s99F-;P$IAT|Y+C(jyI}8fn zGAxAf+441u=M1A>!QGnYao<@-l7g{}WMyRTpZ9{^Q}z$mT1oXC$`qC2n##|8Z9cq2 zynBoB2Z&C`Y>MgTwg|-4xUd9T$9Vt6UPR2qpDqtaZx}|SQPy_C$K!chvsEsX=AZ$qy{c{ zwvjdZos349Q2EHcD0}xyRNR82d_nqML%I~VE~iA&(Q7M&ASyzi73BzksS7nD`aI~A3wv{24iwysO=%DX*6T4p<{(m8^;8IxMWBDNzv z2B4G&F^)7Nk>$=dJGtTP4(!{9aZC5Ztc{bRyfUQ{?(E8#S$~gVSszAc&KpffLSOL5 z*rMYx+(#y(tS=}n75H83=B9{`+2)$dUGzEYzNSypXN!QRG>!)%M$a^gGJ`IqP4$&7 zi^dqqT&bE887S0K`l4c#sZzz8tCIjI?!6{0+t`PnTFKq}T$_SwGM7&rY7)B(Yc$Ip zwPY&;Y-C+=15HRQi($aklUYEVA|awQ#l$+Gpw5ewwV_Tsr{ME2iRArpSL^Zuegw9V zs5A39>Gq%x3HzJBb@YhwJz=r%$AHL}`2WW2+wpIpgU8hU`l8H)&j6Ry{DLY{$#!=#CddGYMGv611B`m*0AjBw^xd?u!gPU~No%L3s;eA!H#!#3~_rvwyD ziv;;2tR*Z*2jD2E#?p46X?#(y; zoM$(e=aTl)mF|M5CsN?Nd_8`)8m*~jW}UZesFBY1*r(qQNJ?3PO-X}Z-6YS-_S&dq z^>~A-51^v62oPsYQk|VGF2V>R+j<1`?nX}v^yqdBz#9-5*6QH?BAL@-4aNPsOLSx1 zeM}DYY77zoKs^lgZ+x!X&R#tR%xj0JUW+!p^+&)srH`zM?hli7>RSvmr_8DVVT)Z$ z-R*n1x&D(XuI9sNzT{8KEi3`-^`ENE$@p!MW5fXr3~KpH=hfD0$V?RgSSwiBjdv+?K?K)a`!=!GYvn@4A zorgfk3BNlYD9>Lla_o9#Xm4;QBR$wxli%6$Q?sRbgMQug0Wl4B8z|ME)dttJfuD;i zl-LwJnSDO#=u*eLuTqNNkVOuxd|&+Z{-C~Zp!QAkJ#3t>2+ORQ6mjQQMg7}^x}6Q= zGYiH2`g}}|v-y6{LBrq?4o5;H9!NAViw1OvT+;{|8>Vtu#r)g>1V@V2c(Rkyy9I4n z?vgt^RIj@338oS0la4<21kT!fSQ-KKWxOy%%tksCoib}fJ(yjoD#bO&3=md|hrT&P z*_z}oT0ow3Y!oIo<1F2}#9$%7VZug=_9;hkGS(?p>D8{2iqNL0UFQ5+^OR#k{fyE3 z3WC{>58LjiAGVI=H0J8ysP}Fe45jRXBhB_>&u!%4QqE0@R!;7u(BilRh$e?n%Wtc8 z(Cu_iU(?_Sl6H^|l_yz@_Gub!c7xcfdX?_T1; z9F0~JOH(`#A!ToJpqtw;fgE97!V?-D%~$o(Qf29tbRQ?IB;$k{v5rSH+km36*0-i( zhN}F>pf>lW`WylII^(m>Y=1nnL5m-r1?d=!cc#X&0=z%l(XBeX>y41o12&oz)t_=u ztid~HH}vGD3nHdish^%LDcw$3aE!Nwr(whY&&;0@C11mZK!XqLSv zgVqr5n3Jb7FTT|fBbQPQQe^wsePWF(m)H-I)?fS2_^(BwvtAYQuGibg#HSOEb4mVi zumsiZ7BT(#Ln$NcvJw|f#)d~zAw+Jfr5nzQU%qXIlQwlC((MqS`gPks6yW6 zGdLPdtGCrOd$zgOus|%zD046|jR(g~Mw{ev(iCvzLmR|D)bDeu*O0rS(3Lduahbo$ z3Qe@NpLPq$HVwo*_<-}{shelcht-@MGfF>A0d+o6@fyMMETS1LW5X}nMr(9{CJ^!e?{lWk45YgRcnG!aAea|3kn z-5)qr&g?CN)l#{ZK#b})4MKLy9fIM&XKZ7*JaAuYIMlB=+jzE?J_Nwfizb7*$jZG#Ls z21q5()yC$w;A1r3w_Z;Tq?d;4kaOLu%yUDju`{2foZMb#7idKuSfl5s6zzhyV&-LM zWYFkQ48n@Ba`K<@U=%WDN0UrbPCUZ+s}v%bxit+uAHnl5r^?wV++J56Y+LI=vmOci z4gtlNcXtrFdb-i#=HO}SMN!l!w5g6PF_GgmIW=ei2N?VG&Dx(v6K`LX0?VZe<@kp# zp6rqfm}2t!IbEFCdHMvQTS)-(J z!A(Ojj_k4bP2mg0T9O^k9!y-gx)4^T2q>Y(fna)CO-tha%c5;Mfv)P8Dvf_#i#4CT zSS!F%x!2RdJ|%bx+-w-|z?Px*PLU8}F_aKF zvAcc055C@m4-8S=dw-q2YSt6ua6^~_6*Z4$aO`>{dx2?7pScI^%3_y-@i5P>N&Y6E1ao zQU~9<{_X%pc}>r2qxaT!9#|E_mJZ5yfOOj$j`tt$;DkYNE&ETuRlJF9Zhd9~Q;xFs z8ONGIn+bg>;YQE`?`FshaOBF&A$sn5$xa6A`M;Gprj}^ldYYT(mO!%%9Z@@~SgPeW zGIS0yE2YdSdP^ki?317yzYGt_`!~6<=Y>iJHeS5Uu)sayNLs&ISHi%#hyUsgFu1aG z_J+|BBbD=;D+&^&sKDUX8CjqSp^g3}RALVq3JaT`wq=xWoHb+<7ERv;J!3w(GozGR z0NRdsvO*-YW|2jQmYSlSxpN4E^WySl^K|xP1;o?=!vEbs1gv;fzK#EeEcSXbtA((K zTiqwZD_xhpyQJ^^@*D%-X3l5k5l60*3WrGYjXmTn%h5TyM1YtCNP;w_qw&fm)4&z% zljk$c$A6Gq1n4t#f+i(N$L#;q^T|Xv6vXf9Rl^qm^)&C0C-3w52x0OV5F+`4Y%DCa zMmwHl8Fg)VnF9?yi-e-^#;mHNXgE8J%%7)MVu@iy=`~pq3_T?PKyc%`8`3fmUsot( z>K@($p@gU80^G>kDMbvRCUz4FRUC?ZMk;cV<0pTU4mjH~O*7-f~zr} z8LHFoUMTz&N`ldUCe8JoIEAOoS_B-1vK9RHSso#T zqKu*`dNm;!;6Th-SfjN7&A+YiOpGry0e$&QN=tbR{R*Dy@mEjPt=y=n5}6cWj*lgV zdB4xaMnPT79#;prm*AI%HJ%|&g>RmPW`U;m?ctp*vR)AXohQw09IxL5Ovs3Ks;^=J zmu0CUmB$Zs7iA~;MGzQ2Ih5Hj-UGI0IgmAq)r3$15y1Y4DR`*dUyQ18Bgq<_19D7& zpGPf;n54>Y2{oz^j< zafl;S$ZxoFKxw=#{5fPXkP1N(hS{ldn=kM*Z z8M>R`)boZ?6sR&O9iD|qDn&&lDBh)v4#90N-j*#PLjnWHZNyGOq7rjzDX?3x%qUEYJG6bjMH+!93dzQWFU@r;g1A^Q ze%u1`-SAWhs`_Cjn!>nx0`WiFJ$q+K`+WOWp}#tS6^;Eh*iOvwGLh!SAhE8l{ud+p zuriXs3f??%JuHu@G32-v9l7>7t0^OWR7Qqlrv&zg8umd&NT9dtyViR^#$hMQ)kjp< z7@86RY>phVY1ZwA`JB|?48x1@aQnD=X#??>8r9b#U`WWXiPi1HX65Ry$bx1T7w=e)7@v~)T(U=<*nTmg89R6Pw7%VEOZ3 zT89|vZc)=~Y2o0}%T@BGV0~H|H!N-_;)XljzI&KdAw+3@OZw-Q;hkttQ;M#)cw~#( znZp!4*-C(hGY*?t83BGL_|2SRH}fI3wixtiR%aYplF7ccg|hq7!eE8-uBba};Z~v; z=mG4O*JFosS&1!dORgxI&`96o&Pif5FI4N1BW`Djm5TckaIhwv*2D??r0n#td8duFLae`5zJ=bEaAeTfzl6-GboulT}J_a@rdMqR%kKF(-e3rk0BYc zl^*gi{aitpx2$1v`E28&QkF#cpD%R9n_&5ra!SV}Gj4>|?MQPBNY z8Q}nltvJfvwNWMqN8{409dnQGPtWK)WhN99Dy4fs+G6mwn`i7LjjeKOn39EBfGDRO z)Gu));0D@kW$CmroSI#u@73Yeq8dzBPr<}T2pDFh6tHGWl>(7;+?o91myBg*9M^GT zlCUb_DYYlOT`QPpb)Zx16cSI@G#Hu)XpjF|QmdPTaJQ&M(UD0ravn=>)O-rcVImx8 zt~0^)e=(zg_)$Sx1QE=z}bIpUw* ztxl1(*ojK=wtx66H8CsmqNb=*D(w>p85q;nhmDy0!q$Jc;v|SLkl42gp~S+-c7~Muq84GS0xexOoByUBB+#-!)3%7)ZTN+J1;JgqLVN=OC=x$< z_d4?)Jd|tT9amWdc*cA^*8)}svAH;B8O(InHyg77WRSwv5VMflj>KU4Y-)R*J2kS? z#Y`(ExmUW2Vl(et)P-?SE=rVcPcxy=bZ>1?#BKYz10HpD+VJeF0^<_+4*n6zKT3L* zNQe;9{U_plJT5Tfeu{QG;V7%J<2p6C#A3g52zvCvdzl4tZmzAzmZ19l*&A1A% zjS&QB@O8)N8EnITuF8dVd}N0}%jX~2!^|6 z5i0cFHuVjueyOa1l^zx?7FIDXEh4xHb`pQI%J4HA*6;dGeziGly56mRcyU&34($)x z$j*ABj0wz=c1H^KIOZOcvthbnp?yoS-ng~vnYGs=vpdN~iTO*1s~z7NGRDU$__c(w zOc{8hfft^_naTm7vS|e~2?J)iEE_H4^dnDe9j*(^>vq5gweTrW4&cu0y%tsBJp8#oHo4*m;e6+KSaL1Mw_jUu)i}UD^9sfBWQX zxORPl(Ph5&tHp2iXX zHdg*Vk;N}cxBqPtbFy_xTHuaZ{L2g#9~P}WxvHA;F1f)!Z>7^CEu~r^3Jv+QchwVQ zz>Zw=a!}LzXPW4S%518!J_e*)ce=9Z$rjm{|2ui-`&vLNs)vMpu$8EFncmcR{^2vl zrrekH=N}wWc>YRlYuvnByM(xV#!e&a^gW*=4hq@ett_M$XRF(AFBSEZmvry;&F*;K z{^oP45Me%>TwABBRFY4<%co-WRTbSzW z)Bm?*!`Q*Y#lqf>mYL&USYbS@GHJIcfRa;>yXlw+rbS^NZ-82CR4-r@fN;I@5&FqPi{6DsSg0zwko-y&>T(#7<)2x^k>BRbc^}bqwEmz z&yMcrm|QEwy9gW)T$9&aB#r=rU`V|km`M6SjZdXJ?}ZcGDM{~ zYd0QVbQg1!H>N9%`Lwkbf+`5<5utsfch(-)I*|Labb!o zD^;fxmHM1+SmHwYyVy;|SjO9QEcUpt0*FNujlqU^Rtz8|$fm!y8nzN%iSHOK%`J_XaV{hF1VLf;}ly7zLt>Ng1 z=PK?aqX23k1+0Y^^2CC@zl9sIe|N4XMxZwo%I>|N`)2{p==6>`p(~uvmEcGAbrYcf2!o!}XLF%pS}5rcYSZyk-iY|9uYADvYe976lhy`EXJ|aitVvwbW%M-*0=q zz|v^S;aaFbEt?)4%C18pz4mdK3eOxWWW=bRszzrq8)Zv&c!T&~bNbaR7G;+cX*tIZ*K(D-yxLVbS`{=nniaH2QjC*;GV_V!i-0n8G;DFG80xSZ zl+((vOd~CD^qM)12M#%&I?Yuc7uL9fIi9wkE;dsK;1lDHipG@p5Ucn8hZH5II}0T~ zUwl4aVieq!c_=OMutZlFisx9!l6gr1OE(${WF78GU1Mb9)GW*8(}`vwTgM-u`~kO# znBhp}6T3pC!{f;s&FZCz8r8q*=%>~-obVEu(j8`vIyr71h$fmeV0B}L^?*@=pwfy2 z5rk+|%~F*LYejP!{C45E?9Q^zzc2;vELDvFnc24 zg|}zf9}&wNy`guZo&k18T7`2CSML?e+3zkr@Gb;TwKzkGib%U|!n-$wIy zCh?EV^LrBbhsg8s4)IUng}dW^f&4%&vfecLAfJ7ID1Jefz~9K;qS@c zILqN5AHO8a?N2~|P?lQnhlnBKbd`$e?)(yf1JIWeVDzUeWbrbf0wR>mCHHOKT>~BdrQ-2F15JMEp(5Bl)^!Tz#V@Js$B(+~In?3w6=dmjDgP2LUt5d7ip zo2cccXpy2J8s#D53vEbEPe(@9UkZddyEPJWa^iRlfo_qybLW9MW{b&}Nsf02_{zm!M+dn|qY*E)g6q9bVWSk1C@ z&W7{&fJa5NjMP-LagIvpSc`(tik6-7qBQGYg?%2GqmyBc_b{$jIeS(Lw8IHITP>rx zF$^@ZJ^sjf(bF7LswHNsA-0CrVCwdaB<=oq7yAAW@Q%5^b&Q66EX=Uu1JZozGbOSCUQ3m55XCm zbdUqf{;V12TQfTq0m#j*tiX$!(-x4o@7P`@FMoU>-F>gm%_sob>4EWqr(1z; z5|C!Ub1ar&$bXS*%(>*NYqMj-vfOcJ$1A(l1)#bS%-p@N2`ab}HR-ZaCU!mDp$?nz zPQ+#J-$vDlkPo37R7KQrD#ixA7jrzpY{Lr}EAVa2j(<-G83Xh;lBH#173YvEkJh{+ zQ=ogncJ^XU&>vAaUvDI^Zq1n0Z73CB9i&m#8;NS~c2xHWGfZ~Dz>zcuZ%r&lC8RF^ zNrrAj)@};TFtZ5erX`x+NJ^IZ==3T?rw(?)+$)spu?`n~9#|XoH%Zr!7QaB*=11+Ir?veay*%;*@2z`0)U&o6 zzsMZ;@u!p=zl7PRK)1h;+4lag2D}uTi*rA8+4jM1RbeJxyV<@eoWyetma0kOgAZDv zHP=C@(+wqgTCswY;Wpz+lORnt3ADgVOu!6Vo++#adh2AhM`shx4^T_go5v}zF2|-8 z?Q$(JN|Tp!Oj5KP6VEI?{QgBeElqCz0fqMkaM&Z2-0IDykDOvEZI(tcmew|}SloLJ zLDpB0X+BmlIqvHVSev~ga#i(3azJ;zBQI6;xYkvTBeAvh-PShdUZac5DSwyfQZ|Oa zT(${agNifBoviS)Yv@=0;7y+zRj9f>bl#^LQU6naYkMrvyc=Cdw)xqlaffdMGNOg= zRV)iip1jbn4rMV<^nGHQ?I3F-qizPB-8CvpjEZB1brT?L$)fmA0;=+ zs!O5N&4QfbL~)}p{Qi`zAQ)Vaif6GxuZw#X#9zG<$&Z%vt0?Z3WK3F4k9<$!zHPQFSiUgoJb3Fc&Lo>%Snu z!P6aX2Y>P;!JQcNnZ1~4|Q|ft`YPN_Z1FSusUSAL3hwkxfr^sv6#zkL{ z0^wF!J7+k*`YMpN)(kl%OU`rKTF3f3viAW`^&qF9JH5( zk2v|b0W>*eMG5SaN9-gtzr@!_!@RRJ`&p5RC;P$sTj?sj1W^@~Qie@64}3H`5D!p8 zsnp-j51ylgc-rX8`o*)aIaDU-qJhiyAVF=gZdGn**4fPGjR*|5 zndfMljcDpxg&Yw_m=TgNp8hq_FSj*bl@NDgqyC9d#- zNBqFC!ARfW-4Cqku(46aa|IS}=%R zk-&ZcvAKrJkOz2S{!O4<@d~|aBGMIWpmpWJ!#Qs?E{0oSF^tkrF#uQYfub14d_EXj zP6_EO2Mu`0*K;4SkfyuozVZjgBB*z}?(qv_Ee18Cz_T<$niW|s-{5j`!*PaHk~tMj zaW14nN^?DEDC{ycX7=FW+s`H=Y)zP2rZ4N;$P9CoZv0T4mZ8_M)Io)Kjg{kve`U6A z0F;#7`--@ph`$dIPS{t7F&hzBpzec@uOgh{TZ@;C`N@9hyLIN`-l`{5w_ciVU( zNTY>@#cuDBJ0jnxF$P--7%)bv#0Eu~)Mp0_rfCaGC42$J^3Igc>2oS*_wHE4xP;a& zfKg&oCiuYz{9Y>*v}|J)u|qN`LKM0;S*ON4WspHloO1KK^QkkI-8xh9Z^#xLQ)Frx z%yftmCyC98AmlU5X;x0t;zL5b$(KZESVVx{4Yg4q8=a`kM~-7DPR#l)6GsG#4=`;b z%%){LoT-p=VK@Cxg{4(S_;p$16LASwq#+>{faeetd(tUnFpIeue;^|B2*AWh!5Bsg znJ>%Ch=BiKGyro%4Cw+nR_{o7=n)<-feTDj>_{N`zRw1r`4n~wOMygd4HX>)84ux- zIk;1^!V}hf8)zB~Xhs8mjV5qD=lbJ|Y$^l#3S-T(1kchmc8_S z7!afqWM4{EYr1I>g$h}7%X?KFArF>dC}q4H5i^>8Airr5!XO8P4}HkILn~YfY;XuQ zB>?s^PCL;&=4RCOsg@Bhw$LsXWstOpmzx=Ro zsjX*q&La678ARMYseF)(RC!t7iRb^pIklL_aZKUlGK%#4{UUa&u|T1Z#B5j;BYDm# zCVa)a)TH=hQYD;FuY}&syODDVv+`;@tbklU*F2mlb8mEoKweNT9*Tj8eP>}mNK*z` zAJEQ04_1}IUGRcU<^djM zUKj55OrEa+)x{M^Sx>Zpx(bz`x}>0#eo+UY*$h(S9W^$(3^t&OAVDS5gu=Y1AAF#R z?_Ta$6zft~nTKoPPMHq~#13Nnvh(&yf|7R&D^ef-)EIY^9@cZ}S#Zlpp?C3ZR&UYF z_utj9rxiPg4l++a4C8_sNiV8lC!KAM64&e}G#_7jAIaLu5iciruVqjiVW%k# z|2k8H@pQ*o#=S1^0%GbT6U$hDc&O)#6ls4j={S&?Vdl$0+aR!&l??}`A2<04^C(Z@ z3NY)!#oWKO9yYGd!XgbbT_IF&hQr~ohpTd;#kZX2`?$#O`-1)N**Ibqt}@Vumh)4%+M3&gB`{nhVihDBlII^ z#U*yp$!i4Cn{L?86FXg@wRE8+u*`*g7%5liPwr&-%hcW$&}i3k%sQpa zRa(RPGNv}A;|amJnO*eES4UnQI3=qB{QHW-Hv!%}z< zfK!HJY7WXhG;kcP5x8qJCwK7}!4v8pTF?lxG#ZeeK7bwWCRwhJFVeq2O?bzCC3b)n zJl8JbNE>@3lsBM#ITa|9*LM{V2wX~s3#cNDdcyx;Od>C?G zH9L(BdRR=@UzM9D??@(jY=p$Hb) zqz}j04X8@mwW}$|GMZkX3}d zkNkII)+#z;gx7-JZ)cAuuJ_=qc}ojIaXX`j~i1o3$>wU$)C0#y!WHfd|>XS zl^ryBNRbm=L#sF(y}R^u4c9hgiFws3n%Ya}Q05&bj#Ac)LR*cK5Gj{XQGXK)g52WA zXz!Uw54bUVEcC}Dm>|6~d3Lz+*&WR)CxIN_=W!5CiW|q4gP#hbU*rs4( z;8$8`I9Zn=stQVlXVvV7T90z9m_YtO;s!>` z@Z_YybZh}iQ8H{(i;TeFt#-V8(3Z}%LFVu!s0VNZ_%7d0cV7HCkH|h(!94**K3Ka5 zMJDE9tlCs#dPqMak)+f%T>%E5g0zA^TME{Ec#?@HV_~kot(lj!EXf(+5vrA3g8q^f zF+vCb2*C<@30u@SaSRf&t>iq)`@+J!=4xLjee~JPg`a-LiSba$Gc5qTK&6>cfJ65J z3e12j8bTq^evvmuI6{0Ryz$q7utzVBHdRo_(<~7pyAkZsLgk3R>3(R;-Sz^C-wKP! zBFiaWC$jc#ykv95s6HZiMfGk&oyKKI$_7|_Ddd1CWFIg}44|o2V?b$ml=H*V8s76o z@q>VnL7go9&BBQKQ$_tLHZWs=G-fFI2Eleq3&do zaAaR!nWWI3xBx1@-yQOY(T=Eaw12!XUyYB+EXV`15IE0MA-ti7_o=hg>)%{y7-+ZN zVQG3wCASywBC))izivt!1ILDZg=Q$9`Jh*jVJAZiIZa-|}fD5*Cwr93FvWUI53 zWO*mi&18!ey&D-~)8iT+f^G&{(+7|y#7ChK)#lJ#6*?Bw1z!%g zYuqn+gwvRup;rmiWC4> zkmj(@iT3&M@&JpxfFa;PBj)b>0nBCRLaW{-J^B-^6{-cyT{A#j!YTNxo?+bo=kp(Q zn9N{RB{rJ95}_0Eq@@Oqj0t)U8y>%i#r=YIEyLiz2!al>fek81i;`37K(HsponIL% zZmSq+vv;w<5%Dx`mpDWh94{{hdHc$H@rj0%#jDvxu{ElqqN6)#s5L!o8BIroC|81> zC8hXWIxH`E-zgD=OtK=vl|dPj#U#7PBo)6hd?LcLn31oLWE$bbEOS+Yyb+=X>Z}Nh zoahNG*x(I3o>&oon<%Fw*IWM1=pWB)SkvJAp=2~plr@no-A2aFZtXuu!hXtPj$}eC z!MA0orFgDggy6r9N>Pd0;MG4Esc&eu`jgKe5er%7G6!(5j zTW2PCxA$Mbe_bI5#$Ge8$e*&qaW>U6k=ghrw2I-TkkJGh+XO3 zu3F<*FZ8Kt3e)Cee(r0;x|&_BZe^hw3jpb?1!!*G)`H> z$&@k@!|in1M7ncRYUp64j$KbOO>sT?P|BtyOeWa^1 zI~IRN)ps@-J%zvZKHl#w zaX>eF10j5^6KCGD@tHB!=1Va8e7k~+-te^9Fw2s`w5=G`6Vc+k7{Kbbc+{4~=lw{F z-~QaPdCTEM&N#f`symQJkcp09i~oos>7V_G=iY~S-R2V69CiFP4SoZ2kvT|ox~`m3tDQaEvcpkDFa^GFYsbJfeUW`;oLxBF5!p z=e~{0RAYZ883Ty<@LPZQAWZYaiDqwbPj3Y9My`;})J-6^v{(m1@KOaFo?nD0oA$U8 z$cd6~fcXl9HdJW@J5(rZ5$$iVXO5y~;%W77rFhI02z#09Bm4a54#K7-TS7etEl-tT zp-ePJAYJ7Ql-l54hWeeF0->ZS(%K+;?eU6F6P%j zGP?;7sFp{^t*G1Fv%}G{$ez{ecZ?U19bnI(mF5=6q|`cnYLh+^ktE1f8voo^3L$>{ z?tGVMj(}T8ZF1JlNlny2;N$K6J3A}WIj~#M7zJV*!v5iiQ8#MuNzi!}t1@U@k`NJ9 z1_#6+OcP-j87)te;35M)NK8|j_K_>rRHvWtnU56>vzX`FdRrkr+@cj{>#I5L@CkN) z+P|n;X&^>P&&~CM`+thct{b4~tT}%p;H>F7j~Xn~IO(WAeYoh*{A62Y+N$;%nCZOM z-dE@D(41DZ+g>fF9M(47kUkce8JEQ%wc1Ep-PSgsj&?VvS2%n zxkdwU(wz{K;VW@Kh(bleSm^^2qO9A~C`8Pwm^{E{ofaRxDTC($5N~xF7qe8-h3jaxphF*9_hLyfPj)Zf-fs@JAwQ_XkH6UeEnYMxtrdcPmVZ-j1Gm8N z=o7a?xzA;vbG6ZtUHA3mWaC#GS0A|3&mGM+CGvnyP;N6Wr&tzb+7x8=oy|5WL2-52 zV|MFfh*NJ%(uwD*a)%NUV1fF26v{V{MK=2;Uk5H*4L;<2=ZM_N0zk%p!6qdesMR^bGG` zf<2|R+U(o$_`LKa!ROKOIDPChlizZG&z(n%H`+++<0*XP;CDel-F5j6m^4NyD=i-{3qeBr7 zA7tDL|N6pMJI|-E2vOWPYnE(FCAlGWm6^wvo_kE(mINZloH6&GNy;IacW*If*Y9`E zO`I4(qhoAelpO!(@+&r7S;DtsdZGZiwLtF+R>Op~v3fD)m4sX>BFoI^WNl2XVN zH%XvqdF1Ee`ieafr#7Y-x(*6xo>0&HW4R?)v zH%X7wHhXe0cvXYv#Vibn2VYNRnMD{2K_Ba z#5VvyXd${}MUV)U6(l5<>OG+E z6h1dmR`3R{Y{$Dq)7}>^5RhlsAvdlkz?oiS`SZ_lrn}v=vy9Be*dn*Tn@#>Ci}1#_ zh5JPj$p3*remKcHYAN4!{L(1t+$0PJYEKWSiO5LsOWYqIBIZ@88HCjf@Iv#iiWjIZ z^^xX*xr?7P=Yyr`n`7^)wstV`zOF8at^m$ z?t;o%Yi%H<(#TcmK?}&NDe30LRYL3{9-S9A5Xpo|4dokLmI@4k0Wrs6nV3@_xfr;{ zU`XvvJkI-P>ylg!_KTjPMt%%l#KKGiHhf5sG)hE@P=bhe()- zRR!9w$dWJY@NfD4mG%CQrdVa97zcH97T@^%_nGjIDuJ%MDi?IPYPDtU zv!+0uO^FW6jh`6k?mR7 ztSn}asx<4P2hvY26E04$fC=>b7<|2~cxSH$xlKAsOwdaq9dFkMVf4l^&yo$utaI8F4gAAi+{4x;8wr3k+)3FJay}G8d8BPnr?A~o%90y?fsRIN z0oNw*OI??WBxl?_NYc6vuV`LywmkiWQNdf>(EfgH`j|5u#W_7)BX8bxs33ipd0@PD ztS;pTi|v)5A*U%)zy6{{`^CQZu}5fi?764Cy~N`73&SNv(_RFRjW#W0Z0vm{flL^^ zj1=1%3ZbU`BBFbOrK{k6v#1UPFFQ-_dB4Hhd!+ChEka@sU}qU-TX9d`bBuX7R!TP7 z2{B?M>_so}s9Zn+Gc)P(AGN~7SX^2sP?(OPL1Kqiu)n26MAkBq4km5*>R?}qC%9vB zJtCK-JvG+zM(WivReU)j+K|RTPjHO?VWE5#MR8?P5$ZA*N%7fwfnWjPOHv@*PNqc% zw6(wIBeMD~8I7oCuGcpd59ji##~2*=y`%HBiRVircZ-@o5&3|FyVf0%1$*iz``AGA zkqhrR6y9wpm>rl?*En+~eL9E#*Z}iM59C`D*oDdezHCy=aC=xl)7%J_;^w!6C%d*T zjtOomi+h=zS7X^g67%|Nk%nZ8SSZWc#2WgNFqaB3QCAjhEwxc1qBN0Gj3YQvTm-`~ zv0YFMspV5LOs7>>zzPvrqP(}_fgSZ53o52P7J@dzxp8D7mC%3!iFZp?42p1Wj0}lr zYJj|JeEA~DZCtirJ6p2>>^8Gw@VZItkXz3_0MBlETE0avS=BwbV}~E`c@Mv-!f8Nm z`<0ge!?xa;A11q`zaiJJztYo>*EqYzJ}?i^WH-P5`SV@PD)anXPxDEJu}bjtPh&&- zG7?c=oJE5YxolOiM>a9`2$$HsrY9j(BrnSWhg9Pu^A!d+>X^rK{aw#ksW^+d-t!Cn zpR8pFxmRo3zfz;@f1T<7Z`RVr{=fVs|AP)onf}LGB8sFAP8jxS<%8l z#3Kk*gP^MjD$})VP~W!1+^MfhRu=A@89U^Uc7b;V*Jl3#m7C&dK@Mq(ELSnKHW&L` z-Qe!kjN@m+Vhgyu9K^R9BswC`X#dNgHz?5)geaoWA58Z2Efp6Y$>80={X+Aqb@RNX z?qq+J*ea49nBA{jOi8Pm(o!}4fnK=^FpPwPqD3XU4rB_M{MR7APN_YCl3lPq1T0dG zYBHk%NJ{oB|BP8md#ST{QQ}%Qcg!6TU8&?HtKb&hG3^%hQS9atf3P_FTNF?ztn?{? zeKG-QG5pnw_y`rADaa+4)6aEu;Rd%{&bPxgAYgRRIK@DXHQH*w|9yMfK0Jd8Y zg!6DHR)*+T;xD4~v&e^61z^Wfe|Wj++W9T~j3A1H_+8NtpSpZ5m*kl7DEA)K9m*~? zhaL)u;@QymA0Ld7txuBSkNbe+pASbK9`75xTn=)cJ6wL@PQ*M4o(NbGMRATMx$Cc= zE}n`tv4n*eiP0}1Jc+Scw`~F>Vf@36OFX!Cezk@&Gwoa^jp8aCR&U(YexqL%B{x`7 zRkU0#<^3{_88G*1ghU}7OX%4<7r^SmKUS7@b%R~E`UyF{x>sUpb(OSJ*Y`Sh)x#NvRyov6l{)CmuCGjJ z^d}7#^1n7{gn{ckSqSSlRi&kuPP<`r7UlQ+eKL_V_~tpi<{qM_wH}MI!l<%EAMP2d z$g)vKw#wULNvhbpRW~T&THDl6Dc80;rOKDbZOXj^CF4}-WQ`UcjjY_AS$_Y6kJJkS z6P`r`0O+Fo{|&%@uhRbK04!_G+GDHx=6NvV!1+ZMnv6G)X8hoiH5~uRu{rSE=CGc; z8BuIZXc$JyaM@sI0-16^(FnU=yb-?BLStQvChX2TvSt&&w8Wor(@igWxX#!xg46B`e_MO)qL zbQ_a$#M_;VbldeTBihP5D>L~P2rqqWhNDJ({#n{Ytye$f?|OYP{)a+-4_}=9xcK>5 zQdnt8o@zxn;+mNU3NCuipKTsDD6iM1On#fRckLd5!+Oi5P0GVl!M>kpAVZ$X4x{ht zZ(H81s(Bo1`g9WM`I;`fQdKWs$cbL5i<(YqSF^poX3bbt?sT~AHBqUqoixL{Sv8L| z!)t-d>r?al^n7$R>}uG~SJbrTE~??}vEBEtjK&(ijixUTjtU6*O-O;Udt4D$n*c%n zFS^cYU9ezDx68I|+qP}nwr$(CYS~sT+qP{RUFY2G{(9%#e1VJ^kt4=`s4&_-jjW)} zGp?*K>X~I;(CV2c{|`3g&(qU4+W_kH5*gLeVLKaE~6^T7N?v!v{kNH3Us zIQfOMwD`rxKTGdZlK${T^cRGd`HSf<&@;{73H^W%6#57B!n{NJd(`sNcUC{#i$$N* z-2ksZ{yqA~Y=%M1A6h?Xt(gb)w<-nt2m8m>0=k6(EH$QRIGU41j*K$_p7e!aP`RGV#yy{p+q-p41g*zESeP0Dwz(=+*X7sLyJ zD8F<`FQQ3%acXI$dZS6U#+C|}Zq3^mO9X$gHyV2NVqTe-feEeR)N6Tz8}mm@Cugk& zYS?rApxBglDmc0ooj=nqRe8#dKM7jx_~pClyYk9aUkWQB>hO!{M!j}jtYd2e`yf>W zQx-avUnh=lKM$(U)$UgFlBk@vZ&}}SI4N3%PlpyEa^TBDZiisdn))w-Y5&bxY+1KA z;2p7+d}8}2G+P?IIGgJW2@VM3JYYZ*5Yo1rhA}-B8m`X8n=zls2=QE9+(A{Fi+5Ld z@-La<_q*V@O%A{Spt?Q1f|>U^8hSg_SVTs4UHCQKFX0sCD^?1=QLZ~W7pv710Ur#X zWGXJ?YC6f^U&BibU1~|@SRnr)!0TREeAnGv<`#V>MCiQ_)lp}oHub*}MdaEoSz31R z=B>h?*78-nupcnCk+Bo6G8tUO(VTwq$j1xP_EMd=|-t|gaaD=aY+E>o~M^xhy&;ZX3MO>QwDUkZ3# z9LLr{JjO46x=WRM-=VDt+R11q)BMTL)4C-&^k&wLkAb_ zW|7hgUyw+jF$Wl*3ns00$!AP^x@v8imd*6A_x3>rFbzz#d_xod5E`B((V8Ac;sL1g zrrC}qUH)+LWk!}T!#J2<#0E4>$R9(6v+=yy$^N9DH)JO)&nVn1zZ&UH3ozq$Q__I~ zLmUvIqemm74Yi?0bCUv@szQvQLW$0HZ-?EMI@sd)OzYZT1Cxi{UCal}K13#Ct~3a^ z&ON#y9f0@c_XEq^e7H~|;a%$LQ1Woy18R?b`=OIY$N}vV0$16h$WukyIj9lh-#PT~ zy(p27V_DW3)gLq^-1!Dc$GL@&)85kZq3 z`g@K);0~42SXolMqXn!mSjKL159iM25L&#CV<_d|P#W%no1GM|ZuEj_jFBq{JEcDV zIs+vwq&-p^H6SIOey!36WQbk0<3B(=D8Z&9EZ+pwY*w~UGTZ$h<_Bb># z=#pU*&IGdLmh>Xa0ubK_I5!PBzvA~FI?qlo0$hLGG`QMZ#(j{P_3S)Rj*v1=xv}Eg zjQ~{wLtF^47npukc;+o&bp<5wA{=6n``!}-5<$eyR)Oc=qR12dc8kJg*Rv-*XMv!{n4br z)rQ`F4EzQ9f?%Klalf{>k^T zE_jk{J$(yej172C$gz77%27v)KAk^OKtFShMiwN-E|CoQ0vmbw^fMzg?SxlMmNbd4L51JOh4Y zw)Y9tVM~gk8$sgiY#&Byv%o8w+9e^93p(g;y)Z&PdwdL;RE6V-td%r8`i< z%w1saG+-U5V{|VSyvpwLWDBz1BKLFlwb;S%6}%Y~&n7pvL8g;KJo)ZV`!NLy4dZHK znTs5Q`1ZD=X2U;7gnVhtX*H2^fm?JAR1XwkVKc+Yz{ zcusp@+RYpThDid{g*r|4Jjnq)lpY<#Mz2Z?YB<33=YDIShL`>NT7WM!9&|5tJ(ylJ z*tZSm9_20lmBl-~MilG0>A~kLTo(XbUJPR_xMf|Ib7w6?@WdDlV{ou69$>oYX%iiuJCH^^VWtbUx<)B2Fg~ zr&E^LwWmaUn)!)MiW;WzWI33u9rGswdxb$aC%e9gP;c+t4(u%RA3*C>K!}-lZ6cs| z-~(mh1(yeNJR{t!HdWJR&c9X>oGXADO31MtiQWip{OkQjy9O**C2pa zozlHpuD%t>T!&S{-;R^f6x~Zr(pyZ4-;mOIs^Xp%G?I2TJ<*yIT1|{Opc=H#j#!P? zXESR$`xORMp)lkxCu)5tp*G^nLtn}^MxR`0UAA=hSO^Nfy2GSxhHP?Rbki2znWKrq+t~L#V_D^dV9=j$;2(y)_ol#tP=&b=2 zkE5;F9XBJY#)VFSfAH$V9=xR-u@ouk3p`}kH<1*(E+fsn8D`nm?DXne2V$-LPQK5!o|G1d;z7#5l@>xU5t8}vq}DlU znO24v&BQtE0P0dI3(@Ul#mbK$9q%I#XO?y6yE0bk+Bj9Teyleyk5zIGWNt>o1Ibfl zN{jN(av-hAfZ1BCeFILwi0N(^K{cowl`<a9xE6 zCzO&SD|hxS1I-B*AA}Pc(-T8{vNKSECZ^Yw#$|v5AF)gMvE&6gC5bZ*A!8<;H?C1# z4do`hrH)h6W_&(&IUABSk4y`>^4QCbsz9}kPIVxO@{tuD!3H9I;MgMi1)dI&; zGJjulOUY+EaJKM}|Eb7AJVjo98d8d+=EMXFU-e*YKkgY!E43S);^j}(ojCdg5 zkk41*nP+f?FB=dzI?;%cjQfljP=0vn(btjE!!ZZ_VGw`#;t&-0Rf2_L+IekB&Ha%AXkDkM{q z*BF!@^4>GZ?rz+~<{u%HiM za)jtNF3ouQoPtr0Wm06qQ7S~CN>;%?=tVgSLWyI_wgUI^#9F?lJhq6IhniYTD&)keEx5o@AM+m6wC$Rj5-U^GromV zgc3uA*UeKfb^>a3Xj#SfkKWGrH9IelTf!YNO4U`IrhNvYc7{o#OM`7P|5iPh0mhl@N2-T?S+b@VRbkOyTe@mMm071*a#&aiaay){_Q8dtikL*a{ z<&(Ac7B)kzZ1ave(Gv1957@iGMuD)}8PSK}nC{r()6xa+zi3G2ul7IkQrY=f7noL~E zCN5^c#lUc4M0d~W#9ouy z3Y=k20X{3=5cigX4KW9gl?z9R*n>&N^_jRWOw!52*T0ZpFNxp;wsmA2fciG2YAYW8vA*|1%sPlfIi-ubD9rgihWI}&(c_rdtU`8x%P zFD)O)nLRYO=izBP4Uz5lgWjx(y<6f0H)vZcv&>t}wm(<49-MB)P5s?48prop{aPj7}a)6)V!c8nb>x z!a8-^&(jZW^@{$jcK&oMC_fYcKe;8g3ikbs`)YaF?#k+vYNZ^7_NOubg8$FKD1U?g zvndz=fc?KD=l?z!b+NZLwR5KX&$&>Gy0-J87|P1U0fpQFhdWT<7DJ>ZlCl&gR4paS z#tef;nd?Son4yYj6^WG3q!d~5l4nrnOUtcqfcS614`k1a{+-Y)p61I&L#{#D%iG$n z)Xr_rZBA3yho=b%RsZGfu|LeurGCYA>A)%WTYI)hQg3>>$T;@f+Jd!dG(cJfkVXTf z0cO1vYaf;os6z-G0G>cK(8@W%p5PGH9tAECPY4H)M@Ad~o*)kZhnP5EJkbi^=sCt7 z<4|zG=sCz9l$z9lM<5-Lo(K<^Mx{`yc+T2}3AEc3F{bUW0-ksl!4QkXY6jpuC zF0#+B$rNptNlNQk6VT{PZoLUARH#y;%Bz%B>fuI9+%=bPi`mx4OY!50ecr=64p$qr z2g-QvE4!3<-))ARqC-qDa%av=5uziKFhbi9blL^9Y_(sv4zWNQf2q#}8}iVUTQM1CBQB-^VX*)x|sX3C8PwF=~dn87Fge7@|luCxP?%uQ9+;oADW#bLD%LA!=CDVN^gz5MGF=JCt~n z>sg(PoC)c?7C?72X5o7uFl;{LsIz@|GNqL53yds;K(aQlpKf?HRR*M1QE7y}QXaaK zsp=mSzHd-7>o;V_LLwRL)H)3QvC^}OSA(Avse8rn&!1}M+O}x7p+!i)FIcBZ*L1TW zupp=POpjr0QGtxhnNJGQ8kx0##G?9nOHK-HNj$t%Dlq1ey$ptK*D`HnZJB0wtI5`X zGns&_I>8?KG}njh3-QgV&#|Mskhnl4LEfH`Aqcr=-KftTj)H zDP`Tfu_|s)l48p?Rqv8)1u^5RR?(AAD1hhqn9qy`7A+#Md0epU_PeI6IXA)Tx#s%IdC{42Ya>W` zQDm|1B(mZ&%ng2uS&|25`x8Yq3=g%Y2MO9_evz!`$JMZVeEplQ(7rX4k1|1@t#!pxZt-FZjDx|NpF3 z@K}^!juZd@jQ=E{|K0LnYHR88{{jX7SGn?q{{NPTFZY+=VIU2kH$+e+knz$tWLiZQ zQE3uUp;npx7zj!h63-41`pAEZ2Z7ljqE+BbMpDtAv9jFg;x`w#Gani%D$-Pr4xMU^ zxC0WtPdfB2AHMAz`TO+_9gpLtRBG;HAIt*??WZH%@UvLn!503uLIp3_UgT7D(CQM#YuURBseBre{YB z#U;86WH23V8nD%d=#3CabvETasX*%J;dttfkbhl@cI9%^mh|`l;!M?7C6xWYbn&kq z@LO&vR)<2nTpPU1i+CDPNySWsOr}CcRIinGFjZsD?WV_fDZ|!`S?@?6zt#z~2@Sd9 z$4BVU#&&1XeMbw~@rQ5jKb1|xxz!G>E@gf89kzdzDW|S;a;WasCG|LTH#s$PbN`7Y zW>QaD=~Ygkl9@$YzvnBA8oIydJ3`-k-rpa&XVJ|jxucDQxKCylH5NGJXx6MId071M z*2j12yJ2JXHXpl0fiS3>{6N*$jY>}WUV7=Eyf6FAt; zFkv|FFF{Y{lR@C>-W^SmNN_E%Z7Z$Ou*#G-sfa1gbMLyyL)>dDPLB>WF zJkJhNw=XH-g=JB4iKb)bqhmK;)Nb<8gk|t(xrcb^=sIA)Xa?*ji)IcvMw@0rIc8iP zT}s%tKB^J+EHKG&Y3i$xY@oRU@0kQ!FF2-rb!Zb&6NIK~!>SF;YT25$4dBV%HMG)z zy)PFA+w`okILKC?O>k?9y$*5YYlFNA50o3%Y*7wiMOIcOK|L;DG`Ik^L8-x+vq>@G0P)tcV}{D8eqzMgwU*Umfz zS0Ajs7XB`t`zs4piwcv#9rEZNSJ1~p4ddjTu#7)gmb?miK-}EtNFt?34 ze0dFsdlJv|bj?%E{MMXK+a$gLz8?B2eGNSSI&W>1Z>S z6gTE8a$!sO?Q7Ea1#u?QNrm30F0Nl1X5H-o!)b~yOf$ic^{7HB)aWAxe&Gt{J*+Qj zio~+d%tTeQBUQhELKZ9+LGCGyuWXV(V3s+;DYZo|tfkfzy3tA0=@?y6dl+pon3&@;48aIaR1v0F3Be!4)j;*>iGM=xDOdBTzGz?`6)m*xJ4>~#yOlaw` z1l0CeXG^m4RC%rnEx*4?Zk>cf24I&DhqV#mS8&yItE_51_ z=m%II50XQrT9kkkPhBD3I|0;H)t-|6M9I3b$~8?MQ-_fI1hH zUV#EA+N7#CC0)6ETIuXVk`X~h#an_jLr(kOvV#v&rQSgXsrm2VcuFx zmOu7xbKgp)OILG=D!Y8AJX3`~>e;)2PxcvYDV7=c0~i{F#F2gu&LaDLM+;`x0da4t zSukMf7fD$EaE{?=0_%oHn z%AqDb8nwO$OoB&74ZUE3WPUx4ii#ZuN`o2AcZ1njNSCwVDn?UyJn8YK9OUflXHH*^S_%TTJPI&O{)% z`0N1Or*L#0VfNf846G8YKsM>`anT{mqmFw86Xcy^l#-Y~Qg}w$c$sAsSSD^a&@JBGRQW8I)Y1+F=Pt z_l`KHMQ1sj9x>|UITE<hSJ-mozzo*}Y%jVb@**iTxW6WGDn@chW2wjF{D%&1+6JPHKpmi+qHCMQzs*IM&`||O((noLMQun{D{M`9%Qj# z(7a>_yhzT;T4S&AXxzQ2@8`?)^E6;?tJOHfc&%l9odR$} zlju#sxn%(4*`2n8A7mP+A;^k3?DbFqP-&07*vYpz_^_>Kra5Wc$AQiKBpx4=*Ii)o z;ro5?>(M{`rOA^nc^uAb%=pEYryqCkxKkw#E(DmyL_z;|+`LsTm5N3OMh$XW^(y&J zIBTr?IzW(MnK&B0wB^-_E zUV2g(37MwrmtM3v93kXlC@My(8Vn52{`?41*8*zGIJ46Nr6cQ!>vfZ zXi2wJKTe#m>jjhmD{LrP%kBkysl&pW4Gw7dn)ZUmAUKfye!<6)o)@gV?eZ5|) zp03o7n-b`s2b*?7d<1v^O9ip)JK03g5-=MA(w1ePT>%l}05h~J>``Y4%iD~cn8`L# zcJsudo{+#NOM{57_ESQ<0IRx79MqwpA=fvgXYVgaFyel=c+T|?nYt(2bk8V%=zIpz zMCtm;L-d1IP8Bgvy-9&E$+13KdVL9Sy8T%HroRzv#Xp&XObKqkrLIfRH>yR5D@Tlq zHwbfk*iQK~%{xT0DAU(={~%V_qc0Snba^U{nU1wfC!S4KqD6Fspix@KrV2$!ay1>m zjYlm~(ZV&dYRC{0&K)e7%L1pLoarPVDeBYTvFJF>!Qr^=iIy&s5~MCFNJ^ZHiFITU zfJ(EV2bm)x8=VOUidc;f-iq^uG;p~Q_#j#FZnAKDX`Y^6D-Ea--4{?D*M}u(df=7G zYQB(j_=z6B{)-S2KT}@VD>Hb@4qkW383QMf6d_Miy8NC_<9yy?O75%PLe7Hx*vwyX zL<1w5DOkoDS86xrqdlgai9Im};>El}l6@SB=*Qkq=g9zU$~}FP zPIzKF$pB2uwnFVp#N(#cDEUnY;tfdFWP%VRlf|SN>ftbLHZ+ESv9#Q1RPA=6)|#04 zP9U3q$Yp#3X}(S>Z%bdGARu)$&masS3lv4rQp3j-P2i0TxPXjoiMdt1S9M}$MBtGB zM}Fmmj#+)N4X-YO*SD!&6A&Bt)*@H)gN-LprCUnKQwF(dU6NLn_jX)Als?1eBHm?E z0FkK)^|`Jaq{xyn1GR{H zx7c8t;D-x!^s9hW{zA@Z7M{5Q5Dult!omNDB&q#cRul*9HH39_G3<~IVK{N&#`^yA$Oj$J6 zC1A5>T1!vD)>(S^Y@ULpCze4*co=vz=71gW89ReE0WDf|Sl)i09r<~k@Ku#?Wlwe= zRw7x232S{poJ%Sfk->%B*Y@K-k?m}+xigf5PLkOzz$-F7MDl)^964xh~-FoelSO3ENr>BCy~aaRW;& z)eLaWUfXv~P3%KG-a=a1Ad{z-K6Zblog-r&20uhihQaVDHVWE4g^)dG!;d`GiVI6j zBe!2d!%2zpmX->Jcak;3%uzjNTcC%-EoDehwp@7Ji}-IrUL=J2RBQ+X0fOcuJ%Y-@ z>AtmWK%Ui5+$cDv)#Pheer?BkOWUAvCd&PO3SnQW#l}+Z z+W&$hkq;fSTZA$}Pn*V#ycy3AJCkFHfLo@x(P>7=o+wEvH{jQm`GZ9)ly$Cfd8b8F zP2(?p&uaFXZ87z4V;ZHnt(Vq9`-)_rPj|bu!Qy$-mf@aLg0Bc{M=8J7Rw+YddypD& zVpiGsVOL?pa$@%VYCSC}FZgIRo5j>_7_qLLDjSVaI_j3#K1p^1>7yT(6Shf`P4alH zuV-0}w3erdI>D!`K|@n<#bqS|@kA84qMvZta7e_poeX!q3I*o#j(v6-p(E)vi3px= z-m)2;;5`=%&ujVVIV{5RbpPu;{$a-;CI5zHB07O*mt}(WT5MeoPK?MZ>*a2~U?CR} zQ@42X3`uic!k8Y}Ud=C03~~JRD8cC0Jf&a`;GiO{fla<_;@O zrhnu5z;Gg=d(GflFDiU|K`mKuQ}!D1$eziCt$L1rOeHIy|97xCzGQIfK!t6Lu?yTi zRi}egMo+pWOsv#Vu}2p&FMio(!_^~7Yor36hP*tU>qa1gdr4gAB{AX!aMnLjgpu!& zh_3iNlZ7`qX||-SYgpL=XoezvsggE-b}#HE2lwKde5sebbWF)!svphhS17G9-Si5y z=$figpq3v+6A}J}0K(d*j;OoQh+3sHeHYmPjUDyv*66{_CIjX=^TGFtBJ^cBx>xuW z)J7U`!&L@LaRc2)EB&P0JT*F%xuwDkN)Y!^T!OGGQV7O1qWjtMX|32?&r5<~wy!5; zt*qPZYz6zxdPteI?p7PcRe;;VFkI&q7==@OB<^zbV^6PyZUf;(!O-F>x1GmvJOm%) zLfCb|gY8djY%mSRJ!Xi&w7yEo)N?-qJlkM4Vc^eqT}5F43LA;ySUj=0O{ALj6G zyeTA#6r)iquDK;~;F&cdBJfi3T_8EcI|^lJSFuC!^LGp>q|=n@<#WE3i>iRXrrq@c zxi*vf3A{ahF`}x?5bM}*YlOA-W^`cLFSa*H6QETIsYPk7R!)%!vMk_uy2whBn zS3?ZuwUMpxgOB)$tzMC=zI|U=5S@jtI;r0H|c);=6<3ZdmxuysahnJ@dkM{ydJBjcxvY? z@wRf;2^eBI>a1^aCojzE9TgSscV9&d5ELVp5Pn)kLs31Wuui4USRirfEdTWVA|&Ax zFu@~CB?@~(+M?Z%F8CDzo;3sHj$j8Yu(JT)mYv1LZp6FbwUkqgSbQ%ya7#fyb2`IWkzGp-%ScDpyHb_bL*~{2qTyem# zULrJCz_x!YR$y;yC(|!KsKBTbvRhobv2=IxoDB%7bK`#Xu+-*#At;}Fw-oeeCB5bP z{bNN5wE7eYd!#8OR5E~?he4+jX0xpw42SLDh{$57SR^f8EWi*X)*M9u8o*0Yp9Ltz$_JXlcaW7q=a(of z{Vy08@~{$+lWb&~@f1)qkK|YsXv;qxlf2Z>M++Tcnw4%csbHdx6YSQoHp@v{d#80D zcb+?|#-ecoVj>J}WZ`rHk+?bCIgMyTHd?}BUs2?>raJ764oJ}8%cDM=*QcblJq>I$ z#I;j~f(XJ+REQARSiW)4L)I@Snf}NTJ>xqyN%7CM`&GB~cQ0`Ej^pEq?K^I~?RGcm z>m2dqiO}`aOV8xW*w|R@Ho3&#exN)UIHncFXAiVoWhyVPROZ=?+Mur_aNCpfm!l;i z)3BL6gYxD$!3h0+Y%pp8S>*i`g7sR-@JIrjU>MZk7e=^o4ovJJohTzqFcq3Ma#Fx- z2+Gm{r2S&6DiMGMOd&ZF0kv8wb8M69aZyxACb_8G^Bb;0U zPJ@e#S=O~hdPBU9Mn;PHyRanIjJOd*VTElD>Z9g#6$a~Mvi}1VuAa$W-b#BbJFggKqcBtSIr~|w7h?Uu$^taE(5G-_aQmj z;l|Lk5Z4bN4y751Hbb%l*3Hom*YaFD90eQGm)>;?cQmZ+1zKCJ1>p%0=?ht|z{b;2 zE`m+BNRG>;yhbj*C6;QIWJ0x&FSbO zK3K>w#wKS8Ldhaba8Zh2y-xK9kNAnGON7eUB!wn5Ibt0fTm401H3EKN$$lY|{|uXlE0Bq%K}Tw zS{fqr?WN5`HLVnJlrk*=fwqB~)LxiG;KUZZ$PsPFkZgw?#Jsl%q_81amWffZl)x~T zz#tnx6Jl1ZNFh=$0RCEw+?S;`XPvc+7W-24DIoJXK=PJ?@{t6_M{r?VgjMQbhXY2t z@FXKhcQyn#TtXPMO15xX8Q_gLPx%n4q{Qd zcgb=NlA=hLJCLM(JHM0e@5Dv`pODM0Di#H%`WN&_>(<|7`R2;(&3I@gLcM3mQme`i z>{LEF4G_fggWDD^*YneGr5J3TK=)PUaqXrU=Q@rVlW~1e_kKm=*A}$qB8thG5b`5 zZOJU|SvmVO0tH;ioo@eb-sEJN2Yxj z*nY)Bs1HWVFTAjF_H7Pdsr)6saK){wkkktf`HmPz6G4;J!xz z+kH`i3#639P%#wG20#C<8}yI6&+CC<(VQl_?Vv}X08Kd3#93$lWj>e3*6*V-*v;rDLW9otW_81L6d zVTq!9FLT7V`diJeJ>I7$u*BeUD=l3w_q#*dE3I93Xx9of zRqWpwnmzYVuqxc$)qF3;N4x5I2+_qM;M?0RKi;OKM;KZEJNHh|~~b^4tSfl&M( zZ<9sC@PF@^s$K4kVZN{f*F(f(orQ&V_M9Avh+pV{@^hHyWj8+yqf8D>8ky&%cZ!8L z@gdkoFR9R>W87Tt5MD$aB;#dDth)p9C+_UoYlpu{OdrgWm^{q^O4dyf)vDi>Pak8I zcaVYW<3br*mx|S2Z7MqVjl6;Zj3Igi92Ml4u&H2Tb z0uNsTBGKgSZomWa4u@}a*|9+JE?I=awO18LtVkbLREITQPoHxKIXOBWK}_xpy-e1A zxm!iq0KkS@i;=U+I#NP>(dq)^kNDugs7KQiZO*&D@?p~-0*v^cAL;N(-J5^uL6xwZ z!`A*0w%v^)cNjR;asb5Pu*^8fH*#kMk0G5CdTW7kMSzFCSa>f}W1p8qSIvR0J#U9f zBoAigcgl>F0g|TsE1~K{3N8#zmL!UoIF=-@DF!AV?3;4DM4BYF-)gVoB z8BEqk-gY_ZAS4pv_3eT6kP~96{tQFQs7I?O4{LayFh+shm0#@Wg@_|Mt(cYcm|kz! z4zDjPfS8M54m(U|(P}w=GX;i8KN7L;~pGgpvpe^H-pMdXIEdNM*Y?kt-Oiab=;(Z4uEtgGlkt!K%Taz?+Mz zH+v&7IkgwqYm+*fff#Y2j;6}xMz0WiDm|?5mlYWQQv+-e|KXrWsim$;KtE_^*-?L z$;)>c*!;+<{Y7+p=~D~bAV1%t5wW}U2=K(@4?zDC+z;B(wXR;_3r zp7w<9a*J<=w9Y;0DqQeGjB+TEvsyvo_TIyZm(S^-}QrcR(n2>Dh)#Qeu_A6orE!^x_Y*W9oeyn?k= z%!})Ys0ie^0ii2{RqoUmKCvP!c$vTMW_M=qc9L`iL+L9>P&wklW@0k(LpIjY!aH+l zj!^j%&MeZ1H@A4gpIoc;mpAtWo``NHQqSQ8J-mHL(QFsm_W%k$LF5ZYQ6AI8)loET zVXds{1=r?4>Y_;Hg+|#)>TDhn7rwekWMXWMf#V=PG=<{ z)@r`13gf)2*QMe-FPhb!Y9U=4&6f1#b{!Sc^ko!%@nKe@!|Qy8_qq&^1R4S_0Cc9m zNQeLp^#E@s(Etf~Zp1@x_$E)Fp#k@=@7#cNphTRr2*TPk%!Rpu$?ePlQ+sM6)p;ZN zkk<%2VcZ};+jDsRe;ncoJfuAC|1RF`9kOF9C=N)_jB}xIfgg+%?Ge1|hFe-whTSM_ z@d6;RN1mzP9E?tt**ZmN!~nr75C9l!5V*-~83l1)YN*rFy&xC(5ik9z@PogETmGX_ z=D6&qayO-N>eztiL0{=5>>~%O#ZOHz&%wW(h#=B1o?V6gT$^4}o<(T6u3X+Av|fS)I;@8*Yi-3;e-8p6e7x$~_=( zc${h=(8aGQ8Q2pzc8>fxexR*zl(}|SPp|9u7MdOkuW|}KB(WV z(}u?v&P@+JFdnc9P26S23-}I9-1U-2Ajp;_9e%X531qk|CgSNU9=Gdzx0d+zEgpx< z>+zcS85a|afBH*EwE+Y@wL9_-E~Ajrf~-4jbSY2p9z%DS@IC8{sf4pXuwEA0PNJu(JatpWi%~w@0_*8$!2ckQ&*LUwm>zwV2qwUpJO~XP=x`Jilw<*u2?mB)!ng_8BVoiac5 zK(+aJFDW>3%ZJ$@3)&1E;u>2>egzbqVY4q2P?d=W0=5!Dv8z0OcYi9N*q=xP^VoBv z*JvOXw|Oh6NBGTz@XZuFJ7|!0P&UnKGY}x0*MqA9FdG?zT?|bkvTO4~1b-x_`s6ox zoo&y=ivt{I?CK`;&{FW1Sh4$rg9!K?VQ8UY`BMpKs|=d*_J|L}>l6J#44%gP0vfNM z#NQTfcCdk`E|Z4kq0NFP+j=o1f;A(P+bf~Mz?G>O!rGzaRBmj0J(&n)Cx*cg6#h4m zHPf$@>;eRg?3dlMM?t%wA^2WTsVTgWOXYTB@yh*8`-)xu>$SS820%cc;G| zS;#j`gFw=NBI8GKU+c?w$tOh0;$o2vU6EyyH@iE@Yzw~hgH9^-?}6OA9)UDeAWb)I z@W3?bFcB0nu)Dv53%>(L_?r^dRk=ee`9crwoln&iOf!p6JVATlVR1hAyht5PonK*sO=F@R_`>beTHq7{M6xq=9m^wAUU8*V+#FQfabE% ztYB2SKT*>2>odj{+Q8<%kke$VFdU>}t!*ReKyvR4j!?MC!HuFh4@!NMefz1Orun-i ze2H33v3lbtZEwG!ssLainog(&z_}k)0D_sB0Zg)uU!bOTNWMw^CcvUukKy0QIlpXD ziG)Eg7Km3bspIvy_ruwdw||H_=mi$w-&}8O2sSnOB*Is zez>%!`;+~4Oe*n0^fx6^zuLfgID*Ev_&_VdWa_$JqwK@QB{Iez(GfS|qL;!w5<}J* z=J&XHem;jQi&;!u6!53GvLT0y?w5P+3(;q?(Xpvm|T)N1mJCP5XvUfR5 zpB)ANcfj6!{!hb@B;{8hoNrE8?~YJDDq?hFtQZpc9Xq^r_CUpga$x zYP!; z2K)y0{s-`ctixKmq{l|C2EM zchKI+^#3rB_^MCaV~?WdXMXQFi7GXIkxteQu04Y*OIL1lFlq^x>yA1CWlMeoa$98& zTbWZTlB6$PF*QO?Fi>Gr1QoD)(P5pV0rxy@6fqbS{0hPk<0%saz}tGAjfZ#M_H37m zjMGK>GIKL`eV+8}e)h1pMTutj-@1$cUik2huko+7=EJSV??crECCEI0GLDucXeGA| zfCT4G!H<;mu|Zj>@zu)Tg0@=FMNwpn^975eXDdCY_S+ale!?;yRU=aAWoi zs+Pmcg$!nE2G+OmkgOGD+U;7k0%ywkJgdxh)~-90rbHFhyO*tb?wmHqG4*PC(@}F0 z{l`ky?PetP?{bjm5qna*kRvnOlAqliT9up`G*9mcFLw*##wk>I`11x*+;FCR8S%QM zM3gg*#t`qi`9v_48q-TaNpXKhfkV#dL8bZ1?p1`*K?LLa2&Z$iE9I-}qe+b53&LzFb z--}QL)y>;$yjE78FnJ(!!gL(6R@}0c)E&|n=-8%hm#m3stRcD^Tvh#i&;d^%mVWt` z;FK*yVofyS7B$cb5YcNPI0Hw3!sWnRLNXKG&3UHdaO(cbZ0bp*=F~jBw&OFfJnRG` zNAzfvqxNlB8wI>%uVY^KQsUR3Fn9{#II`A}%G`l-IbkvkTVjsE2}B4i@Wa$WSTUGP z7KsyaP3BxOizJ)~C?7mjz~q2s3jYnyia9p+F#pt1UvEkH+WATa^=B)KMM`fp&r2h0 z|EGQ8okw$YZeUaOCGj@y^P$#SVt_4`kOT)N)1HRMoqXAG&@#dOx!(P1HEub2SuqF+ zo=5MR-6u0Twb654R)bYHEe8sV9N8{Bf(&!tF0`!29ZgtU$BpuuZB#PcVqYX$NYfZk zg72<|-D+@OYtL)bHq>&RU{iMw?hBd^-Jx@TMig30oU+jpcsknwqFMiDM`+(8(S*uy zkb7`FK=$Cjar0qjp%5mYd!<$UG*7`3Qjqu2qy_Z*IE_be#p;-fyuw>CzyS#FPw&32 z{ySj!XVgfrS~`a?zx%kb+~7?|uLUclpCGGy65M2!P=5;wtA^S$*yfR5z|DJ!x6*fF zor(CE`V-WKdv@=?N3UfhQN3|qR1bTY6J-8!`y4;N`C)@tKw^oCCmF`D!MLz*h;@P| z+ytreAc6DyrAQ@{^|X}Y6K}agiy@~NA&a6Hj$CVI;U2GDxbcnDDWM&C^|SRDmNL!2 zQB>QgyuoXsqz*~q@0ohn_D&}A^{W=F6p+1l=>x*Zwl6Jl^}rME(F=jrtRh^fWz9+S z6ddqWvo5ZL4s%u33inL# zM2-U&Ix={@t-8Ct!;x1D6W#tu`(<0J?mm+rVZ_rGcvFR^QJ;Emji{@RkhoZ#$#-Ju594e}MVlM( z)tl~)jV)TB!G?-2hq;(Z+lF=BTO%V9dKJD(PF$Uze2>S$ABWQwCHE3mZ6xr}Qd|;@~@^{hjsvV94nSERW~c zUE=7BC)sFjAED0D(ihbk2t(_NdA0+T5+ULXDH7)c8&|ZK`pUhvTYgX7pA$G}$+u9IW$XtiAS0h< zxVt`UaOksvMsCM}4$Ty6bE_LW3!LYA1uur7$h+PhZZdGC}DB*`9bJ!?f^ zLho&7w;RcZE(97$aRVj;IRF&?j?ng-{YX}V`VAq(+yx~6LKRj2`;R{lnq#48560TzaV0jA=?sVOWsJF`YJHbP*0#F#-nWU_I%*Hp& zJ%bV*yN?r!Th{?UZ$uYrl11ZStCR+Z2R%AMpF%%1s_Y%uST^Mz_*n`q@OmBiph$*} z{U3Od7AWd#mH5Wpn9#>#9PHk1`JQS`8Ft8xJY3ZmrM>CL^Vfun4JwUr8ys8pVl-1& zpffa=F_L(5as4v(+f3eqs2>CqQ@4e0^g*iDt*2?;05pCxYlfHJj?UR5$;f|@Xc$6& zdwzlcQ=oAxSi43e008)q0RYhduLMy?6MIJ!CllNM*)OT#l=^@Dk{zDBoE#khDFhIS zJECw9b6OD~6sZJbwCV9?K`s>}ZIb?o77`Dpbv$aviKfPsMFl|7vez+>i5XH!$zlEt_G2I8D&frDw31HU@1kS_`m-!ilD)P@ziA z*)k?lphknCVn)SL&ulSq6Pc7{jdPLGqyI4xa5h$W1Z+ALhyG^su6Z9VHtHsM8rPw1 zKHHa)y(j^*Uy{NVtbPN93wm8UG6&e2cVrgWm2iX>s5Ra&Ewp~hUq_;$%D*SsP}2$V zE{&-j?5%~D*2!N-3`SNd9!QpG8z|d!LML!z>PGPqY(}TBjh3Y^*-*)UN4i0~3FfT^ zg)OrVhKDV)P3(@#zmE8=(hI#_4Kb+$R+Uzi2_ARPXYQJO&8??jWnntBiHBK!{7(tY zgVsNBd72MYJx%0$>7*R2vx>ruOTDJ$ z^<{I{vTUKlY2PJ#vzF?Xd)HxSHD@d*=$ozTGps6XR@X`eR<>!8gVW~ryuS!^y@?p2dNa6Hu!`{zs?T`Vqn7LPM2Av|sN zi7$hxLZdL(%auUTcUWS%8nUuIOYL$!D6iG3GHm^iZvr6xFj%$a#TeMlfQJ6zrfF?i zNM;TRJaxS{1T@!rW^OJnosYm)NWNQI$`q0LY->qL@^1@@DAyt#t zcH+0&7j&!8Tq&?tW4=EMVQh2iNarMBSJZ-Y(M?N=7RidEPof|(mLoy>xHBj2T2cZY zj_Wo#IID2WfPeM?m+s8A10ScHkXQa@%mMg|=!^x2CGHWXg>U{O*o1}-zda&=wpzS9 z>fXNCdo$l3Zx;Cd<6gYNb((-ex`)Ejs6S7o@7?wJG!DqQ(}H%Y(pEcF$SZ*;jioY+ zuOt9SCbOkvN_wfoo zKS(IY)nGC9iaro+>WyJTxtgpgF1ZKhq5<^qvu&5)oAY$D1=^nRbPBoCjbK5$aLzE{ zVHz7vd0NxfJ=egVyB9_#ps_!Xzl~eqwqLmF(TK%qVV%XuVSV59*K6wgl}ccCMJ27! z=(0L5d%u*+0W53C!Ow4R6MC4*Z(c`swanS2)rUMsQgL;~SjwS#& znXt$_=Pv7~`esAZFw1|Ds0rEux)<> zuT^!pCxLSpdtq+C_8q(j0LK~OA!FCo_l9|*cI3p-{orcrzfagciPt=J;B9Et?!9Jt z64}2}dN_lsT*XEjvkq+;ci9mV)g{V52@`Y1)da%%Tx|elkF+QaCtI@+lY3XJpfCG< zCk8?_BOJOTNFjp|$HtT)6z7A3BC>Ri5THX1`=xm}aY9$?XkFWf`rR_gd1oc0?|t$= zIr2aY=a4C!R)8B`Zv^0;1OZ+Bm>KkHDEkq*xEJAWGQYGHz#8!lFvtg2(Bp4z9ksmn z2xI!fIZGq&{6_M~2WALknu=paySSjwc41dzF@ZMe~ z%d%!xuM+*a%NT!~K-6=G>_?Ouv=|-p*{(OEvqIQQC1i~G%~L3!fU=1j#E8sRvA&uk zR2Q#vDOh#%_M3xs-Be6*z{si76!8z$@F|g#2^|E?aA$`B_Ss%Q;#>={(crLBu;1#> zv)O2RIc~5fkO_*@U~L*Wf>YF$xsao$^0x-i6gnvu;SkW>Oh@KNQV(8DREkGlx5Z1; z@VE7aqur@3rCk4ItU7vKBNqe6lg0!Jf&qL4PMv^1IrcC&BM57Uu#xB`rkj|G7syUf zJ5s^ONP#A(7YR|sNV2Y_+W?1I0`IgENv79~0XSrEffXI0Z9XrDXy%8H?%x(A^2HyU zptHKn8eVmby^%Hs0nbUTs#Ws4r1$Ta*t2ZYN?5%M90!=X2Dumj8F}ZOdZWPwBFUKx zfQm6LBcfz>?Pd-h&7lt#edk6MwsynAx$uF3P}{8Z{oLK@dcE-iuR#-j2FSZt50K5L z%c60&nfqq0`db77C+C9*L?{?Xw13m#05o7&A(nKOIoTe@|4lBmnlfQLFwIb@Xx0Zt zpbwZ<4w(iVK2Gn)zUm**J=TL1eYSyEKNGslZ^VD^mp?!;{ag-U3ni^p4G{Ww4J+m* z&?n654Cw)R5=jt0d*Ptl#gM+TKGBy#CO( z9hMt?DA2Z(E<0vd22*~3RKvU+#Z ze)i3)x&#iV;Unn%7aPa#QgTfa2;fdS8B?yBpJ&*_F8I=iX9=i;1#OtNAKn#+OXi%B ziau5oglPa1JrBT1dh8$Y7eP^+GB|}&Gm0VdhJa%fyunlzA%IW8?hF zdO+iVp;dxK0$%Q!)vf_PQyL&q&oWJKwsh;&le0`*rtUxLJW~kYUyJMu0!Hvx^-XIY zr2J*yFRohG0cv^WJwqX^uX*Z7|CSZ`Qf}!z7#AKP7Z_D`qakrbMS zZU>mYAN}d|Pg<5Bhd?h`h=g!c(G;gb7=!yI;*oQJxrPEdLcv!{AX&jb)iZ&uOoI2t z#%(Mw)qiTc0RN#?s#GLxC&Au@SNQo$;43}zLxZ}cm*UkO>T#q!AXd@z;~F~0_aT&# zqo6x}M;Y-J(d?g&C&cEevAe1*RLnBr;?$nSzX;_n*yhkJV^3RxMx2{O#x1;s2X^Uqg38e>zKl}UA*Iw)O9u4dewd?eYz$^JnCJ~PJ4?1Y8oYtm z`bHA-uhiz)_yLxnMwmAGB|BwhL}gv^YLV<7JizXEg{~IPY@#1BqebnOw0+dn_Ts^2 z`MtH~n~>T!3J}|~fwXO{+iP4xO5$tPRdsAMSSn7oSkhLg{GDS=LS_!zSI%(+Yflf% z@WknPX{{1=*PSlTByv`d-071<$*9ackboE@bN}LlhN{V~78>u+oo3a_a`R^s_^?Op zM^}|)sJ-#8(B()I%w$=Uqhqe93t*9>CWaG4_;+x_4_F~}^0K9Vr-Bxg)KT{Yts-eMmSV zu52NlAWRY;zD#vr-C?{Jd3^{Dgp$GkgDVAFVfBVBTN|KMA_LMLQE5Q5kT?0z6jPK&jp06aJraobb8O#b1zm;=6nC% ze|FAOWM)_ccY=9`M)Yq<{g*J9&NRJ9a!YTp35RGnN;4kH3yP&!Etmd9bNIZiHM%C*mf^ zhJ%7^SjZzavqCnrSCXlnsi|EkX$(^()}b}9*$_qK8(IsjYzw*BD#pyGd;Q`sG4p|h zMU1PeAJPc`7cfS*fDf9c|4eOxCTfyTRI#$zS`mf)SS@#Xhsx_;%V(!#8s9eA(Ml*j zI6qtBqTEl6ZLH`*lc=V^k_bsmu6`ADC%-1IzvwbfoH?rp-(r#nrAaJ2xjuZ0xGJwI z$mf$r-ZCzWs3A=#O{e=NmHj9)0+F4L zrb%MrypzakqjMspE*m_?%1r?kiJ~qfRUgcT>e7vu)M;{#SJ64q_0IgWV73f71D}Hjq*|Z5O|tL`bT!YDK*sD8Nb2!s#b5Sz-7so)UT1-0i(a` zx7n@8yj}M42CzwX=0hbb)l|1^vXmY3sbg9L-QTPzSBUrQilEjOo0#z%Me@U12vPsVopb6ikeW37DtNXXZ z7xG>TyyN-yxoXx}vM_3YK`1cX4f*41d`k;`^A;Ua`bMbU(o_1kY3-Zb`M#xmed_tV z=DaL{Raj^sL6WV1^q(4sn!Z;#luJ4}DZKLhJ6&$55`Wc_>SzIJ%}L<{88m%zcX zNbj<3INB3w&xm)g^V4jmLg9+Br=s*`GQHU{7mhbjxL0u8xEGRkemM{*LS^nQ5ct$_ ztX_}X@QH$vs(xg+mDBe!t{H)Q2YeVB>#T`j(*%Ylu#HS)^--_f&<;afp~l|9ac#^dfrSaAyV zRBE1;mTxtF<6KAAHs%;FZ3MEQY{zi#_Rg+R(YK z3rGYM3fzGYzn~zwpg@Q`w-5wOJf$Fn2^={DAu34rdvBeYshOD@iO$6XS>npl&eG1~ z^Q+HyPv;i=({l;&o5#)kEo$FAdIBTrUHOEpiCn&bQ&GsNUl zRFVbol9;4I60INmHhn97oc$lwKbEdC2_%#PIxh6ou>2O})FuVZG}N$y7VOlp0v2BC zn_wjg^~^9OxCRzn$*!R#h~zP$CAjjNsHv|1$RO&Hf)?YLyt+UlF|B?a}#L5l(P&H$2IgNp*>xG+*-`OQ?+ zF#_lE>YOkoJH8gtxB-g?_0A}gVuOne9^|->r(W3=^m;3s(2p}(9`0U)lWK9F zc5;lcyOyeWySe%kQ;I*yZ1#2&t-3qqTX1^RT(CE=+O#q)YTBCBD}|^*@XOcgSll;hHr z8~rRD@unKA5Go2yu_@EI{4hiIGQ=A_EY(v$iQiPco08+72v5tM@P&Rmy zm>u@R<|f+V(tW=9wYt8Ksz%a^9oPeCon9rkVX|q&Gf2bR>+O8?_4~E@DES36I5qjC z_N`58W>WI#GJP$m4j;0wm$K_2a~hu0U%?nyEjLk&f3Vj4Ha=oy7`qx zHrcWx@$cQ_QK8XB*(tSI>A=-Cirw@vX^o^0rRpYqsyhG4TahXntoP^<4;`v z;6(P)_>9vfWYx_PnoU$5&=ps=LX`&fn#sIl#BRL^T!}rkseqh+`64w(il|Sahhrny zWr=FTK~#r^6@}YVy$?!31%RvMb7Kn8=4mNbluN2w&-YTQ63P`o&9&ir&v=c+<%EY^ z9u>zirlwZ?kytzwWplKWDStjU&N)G0dUM4p{FQ;^WX;LXjWN`xvwbAmyrr5r74PAn zo?;af8BO3#f>)=b(e6nx#Q1{vh^T4>-E80|H0f+(xzfV6ajLOjgW#MQyYEC zUTs49*ARVLU?~O*)(N)`UM~>=6)50f*L>n|Ng!*!<-NQ6Dg_ywfdo8=k#l=cp!(A6 zM6Lzw%Y{~yX!7m4*8@@ZG*q?9$uH{CDN0DJ4HZ2ip4GnU4lM2#6Q6^1L0dwRLh%A+ z5{2RpsA&Wed)?PY8cvAN(=B`2pmZ1m#^`I9Oa?yjB~gNklr$KTq_U=wjt=%N#LgSx zd9iRc#ad$jGo$|4G{EO3E25Z;ZTJZYUIIR9;ehA*a-e z7$6&3c7n(Q^kFd-q6NYOY&Bl^mMN^S^E=TnPGC*7`-o!&ceP(sauR^H(^S|sg5HcV zx2jSrfBnMlBq~-9pKN&#iobB+z^isO(4-9oK`fNbm1bs0=Ksny1z?x zJ^RJl8xnQoUzhS(6)yri4waXB3b`pA5-q^;T+%HXl{-Q$LH*F2{T94Y*@YecS*Ru) z3Ul&!Cmn^fWcg}?n3c9gzA|hL)|^AN9e?P^5d7rT++@<58nS~i>CdQC+UjE4Pco^c zYz6hdy5ok_0Cx+}shn!jK)vz<=YBpWyRvLmMtxD;D8R#4$ z-`UVXLe;A_+R%spp&Bd&(>-ZysW%rux5P@&Zq>Ujxuu$!8$v1t3#tKgD%@PkDe;(k z`OrnLPNR|s12p8JSj{ry7lJ1CskA8wXrxPz!J;ypl@cpe6$hk@d^ucJK9-1k$S)$8 zgEw+p&iFDfgE=-DX!Kati=)seQVFM0N@&)~3}ng7PWU8bqlO>ARvKu-95*Qs8!w=q zBAk=F21 zP-4r>@h_0kulTvTv)Jnh+2En!p^>9FYtdzLD6IoTMlr3DVU80vyL8e^dv`tK&1Pc6 zsxV*vSA?dSnj3F-%>xAZ=Xa~1F~0?S3!R+GA5INZd5kEH&bfPflqwqKzuu+n&xbd- z;awx#fu7KP#UELj>X&NGaIx_x!hgJZ)UQdhd=9!>#rvz80c+l?83Ya=q7!r!w62B& zgzI;(5pPk6%K#B?U~Dipx>^yrAoH(?axabHHI#ON9;y_Zs32T7u<=$>TM_?-jc@0l zznp9Y{Dvh{V5yS8_-jKC*1C#eZj;y2&~noz>mRJ5^S8U%ep@Ag_hb0u00R2$p#&QI zE(+k{Be#m5oeEtRaVxYZb0|PPmtup7IANd@7*Y7FuLt}if=(VSAV*8oX!T`z(RhPN z?-o9h&FJYKDFB1nz`L=i8>NQRKLd+W=bmo?{6lFPy_jwueM>88^5p2GhBlmr$&;+L7!@FY8 z=I2}eUR2t%0O9Hz0do0Ntc2C58aHQycGRNUFH9RcMhPShQiwWW)lWrqD{mTrQ6(fm zgfXiKG_TAbq^f^hr1GxW(a0CFa>a4x#3Os~)j3NcqM-#IX1X&YA1;^Dn619S!c+x!Y+ z1&i8&hT^al1woR5=Szyu3^H)q1nD&~VH-Lmr4K-enBVG_{ zoVWyvceZ-4X&>9Nwi8TH0gP2=obv-}HC_!`x~muXYS_t~GLG%-X`;z&Hk(JxkbS}^qusGKQoMYU>Y-Y=7XC=bMfqW*K^61>I{dA&+%M&*y!OW2zY!>3)Xl|FBUuGu zNd@!q*{oayNYfjySK!%y{c#_qVjo37?(;iV0*Vt7ic>)*fK%N6kdy_Mh}2xzhy}KV z`A`s7GJ^%uY66q(-0O&%#=EeW2?sX6V8NMTGf-k48{j*N`oL0TL?z>0Ql8_kG)3st zGA*jMsvDSIAz1>Cgp9qgdLyLQ2`#Vnjl|olF=~f?WuL2=JfNe!Zj2+V;(!bG6iR>G7K&mFc;}f46!I4g``4yIYAdl z$a%ZA?Rbm z3yC+GluBQFaPQYbGm;t^nVX!c+-E^vVW)IF$?_(yE_B_R&gHCJ9wAx;bbx+zP5Y2b zOedkTetF<4zK%*zEFq;pER}UOtd9lds&3$D;DzFE6rDr>Sm6W<{F82XfC1|3v0zRl z5jY`L2dXCUgn(vg)Ea6;Ec!%E9o?#>9~CGeAIO=!o&O-7+Cyj=ZNOa3GIlN)T>xxp z|5817iNfph=&~~QyiI7oECrrfkO)j^zd3QZ#2^FDhWTz3!rln|No8yz%KmBw7`=hI6PdULD2$blx+lqCMbki6iHXkuFq?#T zOmF?4r8jciFjDT0GYMiRaoO6bGTVPw&MwEp6mquv*|_1u1lFj0k(drpya zsrPK(x#Otds`{&Wt^azD(WQ4Wcmr>+-B|hW6~UPl)G-Y5m>N^%aPX z7J725*JP~U`oS{DHrAZ<16AQS8q$Kg$1Kt(^c6yj%cE4!6yld9oMZFLZF7Ym$~6j( zZ!5BhBGVmOv5coWS@Th&7o)jLfY#m;f8K@0?I{GHbs@h@jvm-wEh~yHL6iS{zc;@esGfb8sHhr!03n!KmsdvYNkW1o2=R zA3AdzIGeD98vRwb_O|(ZZ-K3uclVU2Q>&awRwjwMUFVF2K@0>vIZ=Sp{`i7(^Khh( z%j&rNfRpa5o2g+!pGumBGi7_CsUzajOvc)mfTlQ6e_;ZZ%_m>?&plQyc7ml*nw6SP zw%)FLhGBs51G8c>G$()UsoGrJ&zc6>ktrqHBe_JA=3MUUF{8KMudk{r8=uYM74O@nm@?ZY0sW9Utc_d+^06 zrjrTz+`d7KOI35TeWfAlbbpUXEqiQR%rTBLF6V6Z=;x6sMx^(i{}iHH(r2N8)*6Jj zr71wrrPYAT|6;+xnrlP~g$bo5?(`A8tA%7g&d96GqhLQ$8qsAXL`*ivo%&YInin49 zGJCJxiS<3|?e@8HDo~brL&SjRO7# z#}c=T|59VDd_NP4N)!Egez3S(_MP|`cCt*}kOTIT4VdMme3*|Ww|+9IxNR}^yj0D2 zUKz=6SEdQ&Ec0nlOdq6NM^@=tZH|PC4_JQHsA~kD*ecZSLCadoAS{ za3KtKy0EIE1K7gC17Kga1DO6&+6Q9S%wjrdo=!!E&TQWzT%)5j%UQ{GbEbaavXs7u zSsQjgoG{LdvcA5IaEDt6VVDWzGrsY0+MmxhQQMqfQT(m=6^VDE$5?!}`|w=d#0yfv zAgT8Wr3?~l);=>|2kSi=K}e&F5j?P%ne8?&W8X`#AtC!DX2b(V6sl?h1k=>OYxBBw zTp{FE5VXlsc7lmv%X*ncPRDuj-Fo|EPsmY@9qj8{{Si=_H+&+_;DJ!u7bgkcs4;ZH zDg6uNW%-=Sfuog))NSy6JF4)iyYA&fq6M;K?e;Wya0)6#Y*jNAs5exPDR_%zj1|%8 z;B*r$`W)K?W3-8nFhV`1sv8xikUrlRN$zTY5Hahf_}|4cI(&2qzV>K)>;=aBOF=yi zHG^eUWUD@Hg$i!EPL|3$*PyDW{GMfmi8jALJRV9J*tC_rtlki4MKvkW!23V&F9~TT zc&AO;vJ>nqb?lgr!Q8^`=90 zCmS6Mm5pXY+u}nnlbU)6hClD$D5mF~Ir8&Zcep?8D6p5$yE5UQwd)$1_;s=juka;?d%V3ba~fTgJyq(qVu89_tA^{;on9uj^BLJtyAnB ztTK3AS&FkCkjUFIdZ=3?4qqCv;$=bVRRs@0PiyDdfUhfCLn7>%##?bBB|X3(%;QIF zSoaQekz+rr=qJ05TbttPQ)as5&z89wLsSLzao+YH3YUpWR{&#&_Q=4&iP`|dhqww= zJpC7ZY@z_`F%Fw?)1c@Gxa$bIM;+QJKG1jx!W0BzVr^_9yF+%h{qbvsJ@}zK_+uaa z{}iV5MNT|w`J)n#g=rP9wu)M!ur1_Q-3Up~AHrcAs34}|L*n`;86dp4Iy^waTls&3 z?5wnVt1=2eT`MEfr@7014Q~NikdbCa&($ohkBecK27GpWu}$eh9%v8OC!UBlyCwsimTgj6nO0WE5b z6G`KmY>aW1U59p)dmVO@qcFX<7msT*2n>ML9RPvvxkHt{s|NBTBW<6#q1b*v!T<%- zxSfE%&l_ap3xfoMeWNpauuA{pB<=gBw^@HIqe6;MPiZmt;NJmzM0a_j_ynzl|C_|IN&75R4d1$iD2_RBxJ zLTp#aQHs~$p+JROz7Z)r7XoQXnq5mrNaqq?vqb!0o~|a&z^==?+;zg{`NrCxn8! zWheFT-0AZL^4836B$vLoubW^8X*aO@cB|tcU#(uVzs%~AE%u=)SdSU9>5Y21TmUd4 z0&vI*j*K|{MEXnvqT`6rKxjbX-m!Ru4L9T7IhXvw8(%n&Pj2%HYI?YQXmHukNqh7V z65p89f7oKDsM#!Eem86Q>f#}tbrW)IDuGdY;O+46ta^MBaL<^I4A)@mJDO&`FsJy^ z0{Jy^Xzz4!&+y;aV0bAEfBha4g;}Uta#I^l>4RQ)8cOeOgT4^utmh|OwX^0B_Apjz zUi7DnSoF{+Z?$dS-DU8tQOH|OMk|1~gF<{c10dhtI)6>;sW(;=%tt9uv|3H-af|2T zSh!7;*M%bc$mzw!a4|#dj1*GdA-E!DcM%ua-^wmtK33F-@-GuZhq}pWZ{#`3=Kxb& zQVCw0#J4f+_XhPp_HS_5Kr!wto!>rgQ`6a4DMit@AsJlXRMPBU-**Yp;L6&U``}?# zgVX$r?SKdzSB-b&3G?imDJr`ytj&iQ%6}2_L1AUPt1)>{GMvqhNym!iJ!J2r)}bs$ zgk;Tn0uL~1c(ZQ6)yKO@sb;5K{mqnW`fpx(ST$ys#ML(O3rYAhL79`A+J{1Q+9wLLXve%suBU z-v)U@!!zCp-#hv-o)X?5QHrA-tz^U$PNN5Ov|nd+J)+t{*e180Or*QB8F0(KSFiVU zLV~ILd~9>>pD!-+phF-@t6rLnt#He?h38cju;O6#I}`@HDA&UUA*838vlBIf`y&2a z!rJ~PUfZRLio3sVx5fr5jOm2HyXhOAs$fv^PDVd*hFVBveQUq}#0A;DoN$1RwB>>2Nb zNkrrdgvsaMmFHvS0ssIA=|MNoi3q}Xfh&_~dF5jR!TS}Bup5-^tExKakR-`YIYwo{ z?&JEe*eBe&vqln9~E>>04=bL9mo=9vH=Tb~-0CE83 z>r}ta!jI~7X8L;LABd`iB+DvxZSq;q_gt@_iAFFW%F>r1B)!rCXP;k*A^;Yk2tR1W zhLp&hrC(^(3Xq4fo`>2V`8Orh4wBplO=Jpzt1;GDhZi99!~X zI*6Y+Ac`)gz@neEtLS!RhIIx}>$A~!kH`9j&8-9;{%XB9$2a7`m=FD8Aa8mv&Bq~` ztq#ejmo3SLr`7v7P{Xl%nEKQHRLGN(U26(~YZ^eG!ph zYHa%>kI5)HGU1aM%`t2hhZBnY=|mTgR3>rAPNG;_X)Py`heFpuHIL*PUqdZKYzB~~ z^7U58Yj+enp$lH`CMTZi6A!>E5?@^_S>4%<-+S*f5=5`!Z6PTjLfKA6!ueEf@|Aah z1{#B>5Z&M;66yY(gKAYh>%Megun>gI2f)w@;{!HU0LnG}hIMzR^3HQks=`t#D`62v zKPec)`UCyQ`A>ghFOv$qgREpZcVgfAnD;kdWcFq|!u|*tnvD}??tuK3X92k>WCOCj zo1JA^yK-D-+IlJv#@szF4vy`h#1Ca70P4n)@x1eaw?8LhAR|a;5AT>wg0TgeE75g_ z9aQK$Lje8RAWzSm8@6~AJQaKMGkBPZKac44>XLW0gTFu-0IH*5N#3_sAr+yH>kCD) zX83y>?{_Fkj+_5mL9?jmU2vHraTsVl7Knfz_3kHmROTyXd2P{bkC?T4ql*uo@Y5Uq z*Tt}kUx@FwH-?qLfuh}u2`3Iui5W6T6lad=fv^AQG5w2>)Gv4@soxj^}Mt^%YZQJU}5`%|<=>i*8H<+@XokstAdmu>NmB|ql z0H7BB|EhPIxc+Mn{CAF0jjEL0mMFrm4ljvDBQ=>U?x_ly>=1M6q7XiLV!i;DrbbJ0Cj22eOQ}a(ize)d%$STKJ#Hy}^-rY!hf;Qf0tudYE(o)e10m zBanI^^)fJhp&-2ycLJp;;p(0=@RmHw&+U(7p|PB3?w-MV=z8DpJSQVw}W zI9q=Mb7-Yz5dx+Ju3g2&>^9}d0~?|RU7UJXYp=;*aG*7&gA%CHxX*C`A0V`DmIcUG znnaYM_2Y&m$M?%&V;jm}4aq`L>h+UBNOaF^g4&_EJv!_zgD94Aul?KhuOvBag{^Dm zZk@C??i<@NSUT&LLD!DuOFO@V8+?{H9X0s_!_h^ar{oN{ zV|Jenf6Wa`|6mMq-l!PMK3|oFkvT5?tAwWM`wDKQ8%pkGDtpB4?i)$3>@6zDM87m( zeB4V98RE4m`s5xI5gMs|%Ac9maea=x&=WI`MAC%*aa|0c32KYN z5i8$%-J1SaJ+hdH0;=z)%67W2c>f{CRtiPnqL;gPayp$}grGxpAFG0&J}G+gkI(R* zRvQa%5l^>lRq-xB5NR|Vv%X6(3wK(a`xOJy4|iGj`jhc&X>H}B@vBtriMC=+Yl($O zO~rblNwDkklU>!v>vqP4SRYVoM45>ZCjPa;^!55rY8INZ`-KT^;nbDtR$+Jn^p(&h zOxJ&LJmHjN2Zeoa8ZQq@uC@N~cEp4$ac==zS{~>ie~$+I)-1yn%z5J@988bQ8<~=d zxKa|)3_&|YRyRmE+%K_RlpI3QC@4$d;}DZ5#HHDh#|a1SJ0v%TGC z3yYXDRqL&jHM0dO&qqhn%m_r$GRG^J5%wZ?Lb(QlRN|He7~N(I$;${viu>lfw*Kwu z3a`t<3)L(JGh3>GFawa(5fV*EVUdLdN;?X>O8d! zNi2_Ys9$?ka>Nr~+T|RJg659oavpe|j^>k=c_-VaZnR6KmT|WYadaE$G< zke0OadNz^yU}VM})Dt3un;C@a*v1s!b@iT>CXHz0CF{?g!3e1J>Fmi?q&y`K--VCa z6DE{LzY4pF*^R|suAquJ1=USrn(GOT8LdsU^tt)BK_eNXQ=elUZ>%@lC%Y1w$qxps zl$Y^5h18b?E3$+-!+qY5<~gvydiT^d!EddU`f zmj2ZJz+1lmj7JH!>y~ExL*OC90RYhauf;DTI~#jDr~gS6Qv3gh_X%wpN=+C|9}t&} zVu=T{q*WKqJotRR3|4Uub0<5jW&yyI<65h6WMWz}GW0UZLP>A@M3|Cr2RC|WA4oc&tIw_t!!>U83Ft(8R%Ub+y1WmbXFVPb=C{ni|rd% z&mHmc=ERsA@r@KZh$}_1^FbZC8|a^%nl3#mj_`4p-*y|~rW%+S`pjT#nMueieiBfH zBHPl~%TQghc3Vy79oe*3V4O6a*Zf;h&wq1Qr~FzhbZu=fowyAnJwvOtWP88%R8T#; zsePvtv2;B-?o+p}oICbaYZo?8L%F9x8QAbI!4Rx?PaoiU?cicsV!CAfJjZLMx8j(8 z^9wBbW!VLp#BOHT2hWj7Wfw!UtZrUpyemFw1)x-i19_#e&am+A-^9;zW+551vQioZx@)@CE z8Jmc*jEWMbZet)}B&7!ipz9mQJ|xmL@5YZtCj~dt$RcmH;x&m8YY`4OGhzo>9U92J zHSDw0p|uR|@GmopS=Q8}-9~5@$Kz*zH{kylU+2`O39w}Avbt>Bwr$(Czhal|F59+k z+qP|^%RGH^F7}>h<}!akW<;#W^{!RdjxR*jL3-J-aP#ey$g>MDwDv$awIb26(#?P& z$gLAJ%yqZ&;xRt>6_CLEXr;6)iI-XGDcnRPQdIl_C>Ba1KbFb-pk^#mXM$Ov2=sc` zxk@fUB<`}nkw5Shh~-`RP^u%`-03MS1CB1?WH1v650O;kRV*;!2o0*DkP{^$0A|fx z@uPa6hv}?gSAMYXDT)<2yi}2YlJ7|z87Z7-of1YHfa=fDgmqlL}JW?nr!608B* zgMp)opFH_tEg*dellJxaHL_)T`kZ<;E12}R=;%2wq$_WT5|a@LbJM`3v^L1OJtK8& zF^#k~@Hqiv#;P(V9pw=nl;{d()%jeY#8s1U)M(zZSTl{&T};mYm;T&Cx8~CCufTEz z8y-5W;pUp#mtxd>28hV`yUsj5wB<@_`pjXSw!9kr2uYpVLQ2(o>RHO}9K^(gA+e*# zxK3r!?LEaYbF0l45QU5PrYt24s{DvQCkri{XNM#0!Y$lNxU*Kv!=3uIkog&ly5s+- z`_eS@?v3Vx1Lc1jy>e7NmO$3A| z8At0Bqo?wr?bkcu6oB!=7IW$TXcZVgd!aQtL$@1|%Az%<9uec(tD_Qt7w9jMX4bc6 zqK~w(MP_tEXl81M>Ca)5FJ2hxHX9H7UJy=cRvnQI$riU3_pS6%|6$05U{bHJpFd;+ zXByBVlhLfqyQz=#(>Jf7O^F`#SH6qKdsE{1=0Hf(+hGi zDwiA!f8zW|X>@(im@uFfolkPV5Qx!s<`mOG{V(yRUM?F$tf9aOs9|qF3j6OmpGZ+6 z#l!iJ_)+js?r$Y^$c*AqNwT?-4Kl(N=_@?3tNyQgvXG)UlBK2KiFccIn&``w-o#eM zl?;c{GhvY9PLzWzT|2^@)69q<{)`&S;rVB~uQP%W>zE~VHnZ?eMcvt8i8}YzLJm?G1s3Wb# zayjRv{J56&(l4uimu^D;UZ#{j0f~fiO^tbMHab??g;P{6v&5zL{2v&fQ0t44{W)e& z*~*jus&VzHlcvD`%*_D$|EtCs7+Bd^{WdW8ujIU8?dim=5tq?bL&mlB^!Y@nQtDxc{-5O~%YN>cC zgESG{87eMvHLjB^82I+1A_2lw(eQ^I8=#={Y`swA)O{!HZNb8T7q5TD=5BF6RvsJa zyW82^FN(}wYN;Q3xlfycTi8!xk$6&aru9^QR0%E~>UE{*7;V?8KBeY{9@Or z*y6oB^7dx6L_cbo*U_e!dlD)|{&>xh^PY7kt>p5Yt#l)dw0>*1Bl$19@cwlkAH8k^2OgeeCg8-5RdC3Pvka2J~0_KcvdncpU4NThnt?7cNZh#fB?6_`aH8&QQ{rmA zyBL@x(EkKEcj5wkpIv?2c4Kf~nS?>=*KH-s*n+@IVSmn$6v~Ul18Jzk>Bkn^DAQ6b z0JzlizO;$;;(WawROF8|wU^)GMWv5Klwpr?7NSXDJzI|_0c_hQwc(?pEjXMqJ(J3G z`UGv|BVBe|>dGWehnTgc7Zshp1_zQaKV2bk1}_3W5C?%O@}J#9CSUt*ijAPgB3Sr%hNnIRcCJ?)#9Fy})kFBtmgtV;s#9IRZ245fPKte^=N&eS*|rCn-He60%5+ zEWVZ|9J$i6D7W0Or7ZBm%yUdEW)R@Lj<$x(lJEv=(PNn{~7A@YOk_WGyFNR@8g^_OIV@+m}mk zQ@-w0I->1F@h@@lR+Mi`MQn#SuY;FnR~1w1S^C{Wuv{f82r%u4?TOB!$g!u!fkZj3 z@m4sH*e}~k^u<_n82r@aCKJ->fTX(%7Y&L2hqCbE<)Q#{Ed9SQTNx1C8El-@c z&oXC6lEKC*qVB&z7ecVkS6<7B``FvP2HF;*926MjPRb?#gfLB3VuP2ER`I!~?j=RT zneg$9dY-c-&&`}`Vs?HZ+!0&ct6T#}KJ%0!F7lZ@RH7v{F>+fA(`e*fs*g+bOf?(! z>L5C$KVvbZWRuW|*yE>o9_S0)+`8Ss{NozD7jU4U+=q%PIL`xNTu%qZf(6CiwQ!5ZT87H%ZY_b`C9lYc z#e2qoS26+63Z;T8twUy8LS{=sCcS|0I$COLfTyRc8z{cC+v3py)N{!7d$ zYjm&EK9IGR4uR5|r%B&sFq|hvZxY!|qC?LMRS*P1{0)QK93>>d0uepD28>z{T^ln!?gX*=mgR|f1H{{k2J6cH z?b`Y#7@d7Q=49`(Ed=Wpq^DUa)CM7rt}R3Vgznq~9t7K83Qv+YzmEqo z_|FX24>@qtGld|>)Q&B`&K~$Bp^RQG3E_9MpZ9jTeK1fX_#i7(YN7&^P6s6P{3QjQ zbV>l9)azH}4GrqIt?fiyOM@RENT*3qBS;AO15J9NAgBd~1YyfFPtH~=)H=l@7gP~C zh^XqP9(evb*#EdWI*=^^i=cEC0-#de3q*Z)fzEth9X+{k&+>>k>WLqfx+GBQ#T#QG z5hqUjE&-dDL4ch98oluBAz~HH#Aq#)YYc`$KE0JLnBDfi=e~!~0D{i7A$%g!&1(ci(}@dl!wVL59|tKqEsF&EvB#+o zl*UDiKtN*!mypePM_4WA!eDrp)YNcN?@pEt?mfWf1@(`rB`YWCrRN2m(*)B>rJshq zYB?oCp!mmO@ji@R459pF;G@+-S+9#tE~4DmXpI0!Ngu;`1SQ4&`sl`}un znLDe7wV|Ng_)?{CFVhpbICJ7sqPB5hfdxAb&S>JuHVieZiaW}N=K^VnAIKB6KFKf# z;{nO=>_aX^BiZmz{+O@c4OdTVK)d154rT{1rqWtw2FQ^q<#AN3KhjAHj5M5kCL$bH z_0I2r6r(t6%X+K9ZnnGb8b~8H(Qrp?h7G&E4G2H*Fn6@DvK*b*?Xv~QqN^y{eIS%4 z%2eL!-#(0At~Aw#$Rulny+Ok*OZ~Rlz2U<;n%)SJ98U80tLIEfNPu*)htdL;SBxSE zc!p)LM%jN!-QS{byZ?5d%iKpGLu^weoz~$t+Rt7Xki2Q_i)MSu3Pw%^?tR4qYWx^l z2i0_*xdoToiflp~==KQh$R%_nWhwxdXtBf-H}r@fN?!Ajjcs+QyYBS-`1mhnOsz^r zW@iZ!8vqkCW1T6xRa`w={}OhlSKrceRQd*P)01h8>@|fVLHb6{z>@ao-y${U=H1=- zr4fqqZKj6x-|RZDV3Arc+rR1UpXZJj+9B(FhVBDj3`L1zuhrc6sB!Rqe2t(j9X?@E zv$gw~ec_?&II7WDJjV}q`VSxtW}oThFbRv}P#`SxIwdwglqb|NNE>avI&>Sll;o7Z zWmYMw?z-)bL%e^Hjab%YKELGD^}3B-#Tw8$P}9j0Ybs2Te0UjTH2g~j@g_vkg2J67 ztW$>azExW5OQxO3#C{V%_P(JBRtQ@lMG|aM`yK?Tv|2itolu zGu(e+EyWSxH5Fox+@LYG`34L0!|dO^Wi&s%wR4VtaHtm!9ETBIqV7_yhFO-&Kk|DMLCrFqQqe|5O$!2J!5@Ac)C9^D0YDC4 z3k~l(mr_R?ko88b5*Y_RT6snLfDMNTn=B`c@MmPTIn|0{7ap62u(~=G)q6>68EDDi zG=u1dF=(gT`Km0)ae#3Qgjwouo*#La|Dr14fb9U$SB+R4Mib`E^_va8flrgFhl(qw z{2N$Je>1a2@6Y2 znhX0g%Tr%S4aD4fx{d7L)mz*fcJ%C{;f*~5D6sIz!|cj@sQ<&SWU{&A(F9QAMkuvx zGeWS--6exdOeB?US#%!7g`Qt;Y`$bIE}ZKZ1+yBAGRXGrsu;>li9)t&GdtbJ5u#U zToVX2t_EXoX}xM0?~kP|@7gRW{Fc4=XB51^D=hqi{k>2Q^s3!~Q8HIjw@CM}Z=C8NR4_TXoy_A`OqdUjm+99KHkl(| z^$3yP094JTM0sdt@&ZgKU;LlJ`Tp(H#S8#S%$qp*LK)~VUi+G9Bf|GZ1J$j{Nm4Y4 z3Tk6quaC}YTgLc3|4tD`Jz#9l=r=A)_H@pQi;th}<&yQiZSWz&-Flgb$cidAOR|E6 zV&N(I>rhh6iMsA~HGL)CKbE{~iL3dZhMPtD2(??$rc)`f3tlUmaQC?CTy%T}Nk2QT z(YqMBSU&iO%^xOtlbYQ|a+JyeTq_mT73gGEx*y_t2K(DYMtm95J1Iu3T@(V|nZ;-= zSTG`kE*G_!6F$#cszvN?o5}32;U!VndNGW;x8y8z<7L3WgdXL$aniB<6%CeN{}A27 zSvxPJWX`1}qUCRQFc+Va_|k0hb$4tTX29hH^Z3*}Gn(wgN92teSI9N%xomr99Db^& z=m0knpIyf*n{;jBql?yuwMk8|pq*Vc^!H!>^a_B4FJ@u960PD8Jgx^_mNf&1Eq@%P zwJ6Vc%SihhjqJ89rttmftKCQNuqvyrr!wm+RYN%q^AnK00ZkYA&ED3#A5pdc50pnm zB*6BQ4foqy=$AHQX8pBo`gRLXGQIS+)jIo#Q_C$KQk^TebGZPN$0s{H#mc96=MT0< zn9$YJwrwi)H7F_%9~AEAAK}d&%O8~MPb4p_GaT$2g}mGQ$L4hY%7rkIcX{%-p;+1` zUs;;|CS?&D<)%4dnO{jU%Aq8mR1kVc99B06o;P7oZB}WeBRIw!XF8T}^9ICsFf|`a z&~uS$eGoMm*so}km1*WOY#C2j@0FQyjb>?u0)VE7SAi2>z{bTv>dCyg8jb)*%d;i_ zcG-d9()WaIbH+*4dfDnlv-)4Z|FRR~?w6B0g8>1#!T|wM|L=OahY`T`zl4PD6dn65 zQPfe35&g||8CQ;V(j+IUq)qgMV&PC6jAc-m`yJ* z!lR=Al!39nM_?=v6zAxU4u@Q`oTS_FVfv3dFH5hpw>kcbwHZinuKo7~ri-vIiL=13 zn%X_-Z=gZw(k#d5%dR0fyBi($eRKmD%Q0JY>lSfnhQHEzx9BemXLeCHC-iTjchnT6 zcl7t=J-S%Kn0mH$!%+2&HXK%)a%vTR)DE_6ZVK&#_z|+eWUJ~z zHV?>_WclIh{3Fs42zmsa z>b%ZQm%!Q@0UcxDS`tcTzJ`2wwIiH)jm*_`eY-rjuHMxvep=F}FiXOGX;eaz(Hm7r z0z189gGgu-md*(YjJtOAI?s zQYX0gACF#V#IS>&Ur2sa`)R>|&Y%C9Sl<72Gg!H%Ac84+VX}Ja+Orewn_$?#Cn$ zP#9R*@Sv9#x9)dY1zLt!rmbnF&p4B@$EqZ(b!BsNb@dr)Ew&(^M=7-ZBZWHINka^u zf?TN^?OHu`nH-$q_}lgX=FdNolxoE$xuuX3$nhA?0vj4^98mvwa6qxcx@As#5(97e z4Ila1=mO86yP)(^7Za*#6fQ`PX2RIgpPb5`7dI3Dx#hMsXGmavA7rRz=9-)Rk6!?) zaI*{Ch(yz}$%&-^1W|(suoDUxNcc-9G##e2qfyJaE^o-`PD{Ije)lATy#BR#%%cYq zRsd`3oNW#YlpEp`T(Er-Rgj?R@00gUN-g)FRl`EP(zSUCqlKEM7O%wJn>V4Ln{U|B z0X3~OWy>362&Ko@7X8D&=(SZ05s62soa%w&!O=h9w|I>P1?UjK6 z0*XQVzhuyVfJb{<*Z;BVOU9IOKpl1IIPEN4Zh(>^#6bxNa0h?)hg$=KG^Jgy8Tchs zK&{`Gc<*{^J%4poVG%s9PE#H+#wJzl{U}u7q!wW_5r*q5MGdI|&ox7on$`A-PZ9H1 zfA+>&Lpw=y;qmd~@pAQcv(RgBum(aPxA$FQ)<EkvXCb@TFtHg5XOsDuRo?9`We}) z-TL?WDB4$Y%@7J7a&M_+BH_Jh?2rn~#|1p_%_0>COKQ_VI_XCY!F?yMHCSxBWY)|T z*P0?tT(B&k#3uTrSG64X%FIAtGqRC(I5P;d74uen1EHu0YVLXXp+~;KX-;Zej)r~R z6VR#Ftd7o0P||}eiU^@J+%D~O4eNz>%3G|B+CMG;D^7^7b4%Ajq^H(vvU|%`*(%Py zZR1LoK0>CiM{?u2f(9o-i2$Icw)?yqFlG1pWT@W6mTqMS^^4R((JW$K7`5wGSNv2r z_c6P&h(((jQ&d`xM(b`3Q%a#ZVUWd&6cC^A>n{l+*NqCu9AXeAa11SuIhQ*^qX;d+ zEiTWL_@2)nF2ic2fE3&4Vc#ceYu-h~<-ZuGC-nN!#!QIQs}T8@zKycauaL7ID6*gH8D0(yOg~W3UcFz{J+i9;ApYnDHJmhq6LO5_GE@X9FhB{>{6Xf(R>P}uuLTp;fn<_Tow^zvGn}pq<=2vz` z4>2s6xFX0Ot)I*lX@cysMI^vMXNRl}5fpIyNji{Xv1(s0g|ak#8^=Y|>rlFJMZ@8H zBx(CAKc!fhXxNa3i{rnTQGAl^Nt?PFRy|GlO+H-G1S6yJqRV7p4-!lal_mJ9ReVD6 z+Pc;(%u8pdibkgn%i~>DRaNJYP@`U2&d3+2F|F_A{V>`IsS#f zT|44bf<99$n2rRuSTU(6*+Miqj)mtYB3@8)g5E7e;5jTVayD9p+=7|{J!Y1T@8M28CRk|sWp>H)y>AtJ`8t-JvN7D+hM(L>c@&5RLW zbyFxLWnzxTBbU?u6rOz|YQ!jb)Jg~R$zOdKVu-1xsjnN{VQ4VSj7kal2t;(&Mr!$w z+L)1!SA;Q~5jglNI0y5{pvh8MaefuD32WDlk97gaaLoZr?VMm_y zq8_tk8sg~T$NO@M4P29>YR$lb2X)sFCNCe#6X)d2ytL>gy}px@ zm=?uxh~@}?oP9geZ^w9q6+59A-HE*=vDv$FBP9N@N=9<07)_mfa?Uvo?3#2!B&=Qg z=;2=5g~73`;sbw!s%*x~mrbM(TZk65WXF{(KP|3;rEmm^dlt9b+uK*2b>pGCz`a8d z@3qwYJXE-&^zu?hpBx--vJspzA`YvBgi>~=vfvI@?WBgmp?L1lrDtV7v}R3LRt1Bw zoGhHIA8H-Dbj&Vq;6hwNT}zS?0byU%Z>=-_18Y8~V)!ic$M$c0y>ubNvV3C1DA+`* zb*Pt5IB#C$fg$R_EMy1W{a#k@5+YNrc*iE8>=(LB_KBSp<#9S)!U zo&$847VgP2k6;)4APVc6$Ffg7ZCiz{A;C-~U zB;Yd!pmrInea6U&Ub1U_H>5-($v4_=&2u$)ywaOd2c`|V_;@!A^wZmI?dKG`nca-u zOS;)!ik{fud3vLLiI;z%K@8M#{~{8+g|NSFH{Ocg2vpgWiakHTuwU|a%Xu1lItk1FaQxpyVl#Y)hn;xvFKAv>X(PBH3r*z@t;t+ zA!JzWrbyp*or$2nrnD>Vy6S`5UcVX+Adyld&pG{Utc>m|#3}6u4V2ia(L8W+hldBw z6FTpeG^0{!BBM8}3qPJJ!Qce!d?I0Xa`|8GxO+}Zc0KFykmUOG_5(cxTOJ^%tnFgMhqs~SVNqoPOGFT$@2@uiIPRYE_F z3>i3IxqEDH|Ak@Tcerp&W8cHZa<++L=T$A>63zMoUFHlNplXacgi^ z|19*7LzpO_m!7N7t7%(1%vWvT@CVz-Sw#S;GDml4NEBzDhUq;z@wr8C^j9rnw+`#d+m_N$FU+$;1vU=ah; zy6=5FM{V`PKY*EBDf;*|zf0haFm&&`_LEQgWm-rcdlwN1(l(?sPe7(2Q|a6eK+xJh z@C5RiEx#4yQ)P!jhXZ(H@7TK*q8Beq7RyO|sPbk6?=Q^dzb7yx zLt*Gv5(Z~54yJTSn>JD&w%ZdlK`dmG920BcEx06tEN+a*0CG2&-&+%cnb{98UxBSpu2(vVv0Bp;3PT?ln>Kh+Br&wj1DvB@1#QHT zdFvK9sHFLnlB~ub-a$cEln~63oMXb{kVOaBjsi=7#E+B44}VMgXNYasS?iNP8z%~C)? zY_&o98?Suv!CmOkRnuA2Ec)y3zJZW3CkI|jxtXL1i!1E)pa;owwS)&^DLqa3_%d8t zgv&fJAyA9pF>iv`N-)O~v1gdHf=%{Gezd#PNA9OHVh4TlUPpO)APsJ_r0g5|HEGV% z3VDlnJ8h857BKj6=LU&na9DJesy`w9_wC~ta} z=DI!gtX=iGBM{UK<;M?2VgAdtLhshT0(rY-}kDFu_xzt{50M+s+EjB;0Ahvr^uNQJiJg*1Yp}a*e-Fiko|_JuH-z} zKJx#l+t_ahSXXQPG1$hp9#elm4~hfCXCbt|2LwUm(ng#r`t^2&EZmWNE_a3V&tW=* zMha60I4z8JxCz9m$6%*q;1@RnJg969HB4G;Ts&@kj!HrQLcH|`gqsK*F4M#~Uh-iE zZ-$Rs$j%Ly-#)wCI#OI@c#p^~5#Nw0iOD~F&?Do{b_5>zkP>tqJf}s*-kClx4wo!e zv;O5uhwu2+Jl(*$-uVS$`s;!l$C1m2uQ*KIQ=Y2cC1wMlbIu472DdkqWI~6lTX5Xu zK`uixS$?Ix4sgB$&Ot$F{$Tw(Q~h$=n8v#ZQ|ZIhjG^+8wf)A_IGe9NFCq})Lz|yL zZ;X6Gn;;%Kw_2Ye_GoO61y5(B#9jct%UCADQ;vJJuuuD-`Qe7tYNj&nyRKl2ruI*Rh2ohsiDGj%P7rNDh=#CA`>eq z;(eSjsmL#4w6c&Ihs8#ijK6~e{QE`*=*_gJ)D}n@qaidVM&BN;MrO>sil{3p8Q}|7 zNuc{MR2cLE0`C%1q(1!$++n)i-p3Y93SWDFDk&8|315OpBNEmWc+TYoMo< zi=1(c33~;}H34SrDEfulv4Ti2=aRPYN<<-RZ|L) zC7NX(`EA7%OKKAOM?%#MWF$MdA_s=#$#mqgdJ2n8$*ooglMf(V(SdJZLMtsQ5ZoMT zHsa}nAH!l*SdpAbMec!$-{pb=#6oM4I=xzyGbY6YO{x~<9IWZ zjW$3{o3_=omf=wFA`pgyW_h{VS{*~JaCfamUTDgT{XO?m^Sy7e356honR;Hc3^Fpo z+T=||s@ZN}#W{gNkI>e&&M~9k*qYhogigK9UVJyYwJ3OF&2kBQ8R84>KkrYntlebO zzq>>DPs3;UUp4%H-`%Z@Y^^;1hZN?bvHefTN8Hu(%bIm_q_?63P$}l2*398TDI!%M zqR9!B@gYJ>Y7$PmbCjdx-ZnfJ%N->mj)NkoUa%bGdt4C=2<%gk{&T+k@}Xj}`8bdn z(8~G3zMc9!F?s39%xr}I{PsR%urC%F6F6E^2zz01Puvvb-2WZa9?ViB_PbA4yuMaq zLwo+h=IGY|oIHZRN}bO%o1v`}h)Kh&ZX$=e)at~w8j*+q%uDdpY3w_VGW@X$OhN~% z{kOy48$32pP)|0_8mwwo8&IU7;;gnPm9<FXH=W8=UxW z{V98^H@hgr9j<LE!YAhV)xalCsEPMb~UR#?#6}f=cprbGBt^C2}eRE3P$$#O(mD2bJ?hy3`PN)Iyy5j?#&*@dIyXnxmDr-Yx0~X9$swQwqSQHVJ=lSz z>#CAEPE9cfbyv|W=_zuwI)yTCBbYHHYHqu~%E@lQ8^7bV{e!2Ut<$@rbSWI>sBw2H z59^YY<&(1~ZjSW&LW(!|xr9a6tDkbSGn;AgON!NO^z_n;SyRh$E>TOWhq@TA4yZ;j zVd^K#67;l9g6IGptL5tjX&~w>5FgPKX;;5ZaF2&pjiwxQF~ObVR5Rn0Gs#!+tu2YG zSedn-t6;OH#`88ly-bWp+9rp1Qs#@dB z`M)8(@Qlz%U&hZ6;d=5F{G=2if~F52QFa%tV+u211NZguOphba)$Ur3X?>20PP(7* za!uhiZPd5e={2vb$*q>Xn~HTue{m2y78Jy^CY*R=2QXpOaQ}35Q@4!9i4?@f;qdsf zqCc=5M|OT&f(^rA5N4_+=&R3#mSY}mq^u=xC-&Fy_XId((d~nCrdJ!fPPpCL!mVXY zDuDg4CNh-mtulR{yJ$Wj@`9hNADG6C!ALw{ncYu+pBngnRkyY{y=3xmtg0X3l%9Ej zL*WO9*F63{+X=}~A7%XYm|>2&GcDb?OGT7i*-uo40{&t^g@SZJ#eIwv?RR1ghX-%N zo#nqlq-(2O`1_h5Ew3CJzJ-%#iCi2|)sN{lJ+)?B!PdIQoynSniX*R>Wkbl&MJH(r zT0HVovAy|mg_PWK(9gGNt>9S(P~(|ec6DgGR|H4qpulz#ZqrNC?BmGozsX}mhl}Q@ zNeplKYJKlfQJr^}7}rsJ@J*l4;Uu!ZXZ0wqqCwo44zE69tCvj{v*ri=)j%GDKYz_* zoy!uUd&Yn#e6A5-|Fqg+d+nOKtsjJw9beQL?;q2R4|nTjU38&>#K?e}Y+|Hcbd{-e zMp4n#hSvrM=HTz8Ogab!@A#HttOfTumP&1ey^L%wT+{z{(-Lu9AZ(N!Z(n(#L8e{( z{^aoFqI<1cxwzqqR*Er!%lkf(%}`1$?zWSw*05P|T*37~#&|4_>3mPf;oUR?aE^~4 z48cL5%xZ1Zd>K`W09}QFG*k0~>)%A;uH_5C>`i&=!-bvk55YKi#?dDg{dac z=-IpzU%7^P)FvN_-&vX8}}CG`T7Hw+YH32Li(R{{;|W!QzJ@{j@wxZ*-pD`%=D!X7)QYx>rqvN8ow!)xmbB%HkBI^3ih&%pS(N@cecnGLh z@uS!I+mOelxgSq~mkGV6AsOct5mrcYG^g#G4>kz#CRmv`I2`JJbL|sI^G zJ^72%zx!b`0JEdV->%okd-+=PdhzhG$Hn<`zslyx>*s7hA$;mutk%a<&!UF+(b%VncY6m+v66;o*V^?8!j$%g+||Yb0gPX@bQ2qgQuSB;1y!XHVzKCA zx6PC${sG+@BvP1!_QjGU{m{mBn1Z0Lm~r)(GWiwYwB>{B$Z+AoFp;L#ldj~nEPLp# zIJ^R>GQ-rYQPXOTxK%k~BrU0kiFE_-NWl||$V;}wf)G%d)qBtZjXpOA11KsANw{J~fTw7D6%mE#4!{*tBf$ulu@CBnW_ew$FsZW| zLWRh27PuD9iCO7p&rMF6K77x7`y%zM#*q{|(IhsrO@)kX%X?qwWv1>_6QoKpT{unf zr45Hu1U9vhk-Xy=Y&|0(O=!P)#ihwh=&z{x)Rm)13$uKNL|LAH)XoB@u_{hc^dDr6jQiv}MNRcT+z z4;b3=YgltUh#mK^HhqcTK)xB5tu-333&EW00EG+0c5{TSqqb- z4Jv&+p27=Q$`gO{Apz!CZ81mD#&ayKME4qeEJOD1JZT$hEGBX(E&An*k}J@8{aAfq zI6*?vlhT@`%+eW2o6s)>^YN}6fRAysWeVe}njaJ5CIo6WoOQwZwy+6VJ#4@NQ0z6V zHsoKfPTD4(F)QI<*tA>z?Qxc?hh#duoswA=#O$0CGXr>Vap3y8`+H7o7lJ>4w^LZF zi;EMa*KCs?NkdE0l^`cOVjs}1(Wo+1;4$Ak0;NtD7PQj(gAYdHyypj1B4cLL9sbbt z+)x8eYo>_PSw$1E>{^|k$eKgzVe`r~=~X^#Xl(9{Xir9kFNSFASatpuK-kzCA`k8c zpRBfb)_HN#$!xE#E>b(}-Xj?P`5EcY?H%lICb-JY-sGMEWP6ACK?Gh zAA=6hgeh?7RXR^aD*XofLpseBIAR(LYq1>}%Tc<{bU$u*F52jzy!U5cyTg+x>N&?; z>$7Lu!T2e}y#oCW@!IVYcUIYnxzW={W*07giJ`9X17j_0`{mYP4XYRG@4^ZfnNiCO zP3n+(7Yfs6tOk(A)90j9?TG1Fm(*VfxmShiVd0p4%o zuht#0un=f({oTf=DAH#XwRW47_AzbTo{x$B&bPtLTHGDh!Fxaw@_Qjw+D{y?y9Zl0>WsBpgi=wr6x?N#e*y zxf$`-H18Fs6Wgk={`{L_Lo|c8RAZ|wO@mZzK7;VN(oPa*Kka(Wk%qIAq}lHDfcuNL z0m&W?dNeJq3B@>j*{SG_M1P^Y!oQTtsn+x}?hL|OVV#6`q+mp_-F@oJJ$juP+2CiY zUZh!JH;vb2)Fki*y*2(J&yE@_zbX8(97Sca=e#|f)?R?47xcz0@x^z?+^P&Q0&;ui zVs7g;TTZiOeZuH_>&`j5Qq_DG^-lLsh9`7eJ4AZef3Yfvw}5SiLHS_*VuOKr*Wckq zo;Z3)rYD20;mnC_J+tLrk{c>e9?RvjX66g6S|QLPW^YL9aEx85!+#?NAM1AA6EN;j zK6)baJ)+tbcBJltX`RthJTd#R%|2nj24l;|PYmw@Px$0v1;2{?E9hO|mBl8PX$ zbTwUg3a-^}1VOyWvax@F3DS~!vNK!ZCJuc>CntXSH~A5+EJY#-7K_xgj@G>whT zq*h{?kxXPhfl8Nnt&i=O?s%SM^DlZ+sP{^%<8|EN{0+JKM|oaSopb6Msyf52deGzL zWT|7QkVuty%w~?0Ir#m`@0n(4Ri26QNw7;jEQlL-*{FMl<8LmFH`>S+)_O^)F^B2q{hzVDc#3R%f8!8{nIhPpQ4G}QSKfZE9u81CSPca*FJyeiVVGZK$8LBT42TV@4i7#ZUHxQuT7 zkb8kSR^-Cg6n4^$PMt--TnAL0oOW{yRZl~CmWotsA>%RX@49ZqwID2GkHOeYOjsUQ z#%k&cVdPK3XQV=R3m$}{A|<=5#Sf0J+m>&}Q}EhY#*Uu5GKcBm@|s+?nfNI2NTMud*hRpeC7EN8js)e0tOqKp6m^Re>+-E zzwIPyLzJZY{>b8avaU9kP=oT^H1H;eQif7VU7{*TqI<;5Q`fcV9=s;YL}zMYmabtjO?tTfYkL|$`- zH!uu&AzxMLqpaVjticYnM%zktO*hh(Lxg;wyZXRBU7SE2gJ5C30e|e0dFAh z38`pH>%$D2QyIyDp!%^`w7*3~9bqv&!uW*NSBQSM6bBp}xEvd5^#%k$b!QMGa*LFBXh0CQ!v_Do#`(H^HzOU0F*^Tu!12)v2h#79(}@5JGM5`Z zx6AR)k05Ne$?>c*_~@&{5trX4UIW?N5ciz`rQKuTyZl}mpXe2OU=aJ$2e!6YVn-`b zOEVXJRv>nd%;-DV{gWB#9(~^dKV)_vP2OTxkZ~_cRByj*k&4p?*g)0cc|gp8-KCkE zZ>O$x79-qqP_O#w+pur*_~PEnO78)?)N3vTR@ZkITtDBWtozivmgnLsDirt({&hLp?dWg3mKvd^kyz@!8Dme8;5KfvtZ}=Wzm?|&Wv_1<~Uof}PhB7#!`Vmr33C1vp{S1T>i)89DP)MNkP?{Y)uQnig ze-9|`4a7%r8EnOgn}n!#73G&0A`>D^Akld-+gbQqH}qG$&Z4J<&)Q{#CkCKR(GCEf=jm7LGZ^8p`agvky3-8TBB#Ir3Z$h)gTp0{8iK^ zNj&BKC+bflw4JH}0;PQx)z?C5?-Ce+f`Q7zMMpG!yjz8eJ1%N(ewxPgmjl zRd|~UA5!77Rro;_UTwE+DtxY5|KSfzBV(lSwCO1YKeq7tT)Qwf^G5iaIi&_l2=`;v z=+QBF&AbX>9D>oq1m2D?y42`F0$+eIy3*(a1P&vNLo>Rcz~>{3Lo&LDz&!}#P>gOP z@L33>x}zZiuSFP5Ke~ay%?P7Qj&=~Z4q+UE(Ha6TMi@;$T1Masgwf=qb^^~s7)?ED z1rY7v*k$nM*agSs2cx>N!^9xHnNu#KcG|tHAP?$x8?x|HeKML0=bgrZ2Yr z6pGfU#W8FYK^LF}t|vx2z8M>;{G1+0W3M?bAIrS#ZBSvL%&w!CLFIx*X$^2El{cd~aWse$hkUGm8!%sQxu5n~GyxO$$ zwai~NlFDmHWp|llcPpuEe4+eLExQ*!1nyS;N^A88nO95!PsVvs3r&RKk!eedGOs+0 zxL+M?a;IF;A|6MVs1Zh<`g&{(WMBUJHz+&Kl9&GqaKuo55#tQyAcnH(6hm1ZyW3NS zkClTer=ZiD=YV~5nGZR>0sHh0gMr?2?EJ*>>M>@Vmzi<493jSe4tRi39vg#+KBD`F zVvyQz6ob5Hh&M>%8{8TP4b&Pf#2PJNji#M{Y1v&|M9k4t{pZXpUPM1Z|E z9X<&Lc?f!t`4AYS;c}2a0zNJ~BHYKQUgC4md#f;#^0m_Y`hO_B|82^6y}vz0>kH6(?Dm_P zS9E|c(|KFF3%gBvT}v7)3`4APfGarA74|rGuLchF4)9T6@x*8rS|0pEi~m@I|KdrC zf8=Y1AJ)UveRFgtgIjhl&1%{CMa#~YT6TWfGWVO2AALDC*1S8X%JJ|lp-+ekOMs*q zW~Z+F6{K$(epc67{aNOfogk=ncf*V^hxkg<+#^jdkF4I^Am|)(4?D!C95B8+Um7_B zc#Td0Nxgd#b9 zzj#WK=Mn~l5QHw>!%Il$Xin?hS%>W>Cu=|V8(=ZA3)(-XmA^odAIA27`G&W53_mH3 zzC;Ft#M73Ye|PMB!?E)v$K1b+tN>nUrQNGjp3~3ji!LeuQ`7J>A_j)b-~S37?2V?m zZ;~c2jbs7w=o?=mrv?q56DK(z1Mrz%x!~FQ6yWv#&%u6bx|cL`)r{^cWj@8x?~9{% z4TLED=ow?l`x88=?vEe)GkO}K1v@+?j!sdv+dbnZ+Wrd%j?J-_xqlleJ&9%u&Rk_8 z=CwO^H(N7p)5>2_^aH<3X|4V|^U7DjotlO}6dg|-(}9tip7>DLygTJSOble-L$m$q z1eondrbFI zxhv%MS@G@jzP)`aZEtwX$lL4U+rJ*~f6poY=h)Ti7~OJ88HZgP9iy$M;_KaCso=96 zqt#!j=%K#x%lP_<3f%43`HxOm_wyaQ7FMN0hVkeZ;1iIU^g4DvRStc4Ze$2C!>2*` zc_v!sxctLtm1Ebk9H1?KrTm~{=if*A3BiCMW?r_HW|aA7pZgT+&(60-j(m?&X}G83rY-$v#Em}Yoc5vUBfUlnn_Aem=8IYESyWrrbDqpsF@B>)COr5${)Sy8x{wkOMkSmE@8#| z&w1QmcApN_kAm*AiSAGWEgd@z`=LSXGTPuN!bPzk$o-iaBsrO)5eq8n!?e$_#Bha~ zs05{(N$E+`%dtre4|yn4?j){Q!GU@1p=epuzno-d1+40p1tE^!&Bz zy%gSGpNz--C*HqhJUwvT0kRLN-VS)1G`Ro7`^cB{x&f|EXMc3S?{o?SuJFcKDB|k% z3azB5!jvedRo;l(74ou+Gvf1m15qIo?2S5O^u!Csi&oBw%(WLUw^J@@Y4yRtW^XuZ zkM?`*?tWL;<&Jv85&Nw9_NDXf%jer?&$qh*9{V)AFJO<5!!CQo9u3+ZU9By}s6<-C zyD8=kxV@1QyS+Q&1x~(*-Pda$3dZaKP!Fj+zDUUL8nQ>dgDA=swGa6E`lEJtFc5Y5 z0%?($yI(CHgrNZ7h@Fnu!`^5t9I$V8`D0$YE5fvA3Y9Q_jO)Cnn=QVLUOOeQ_r!=` z>~_SCCxxh?D`58ygrY+#o@(>W36f(!!jn>@rM0?%r;A&K5n|7MQM)e^m>spd{CEO5 z1l{PuK5qdFxVTEJ8Q3Zil=T5?^|;&{Q6a{!M44~1;5{AQmGEAmfvXve_XGyu9b&K_ z-cfijVQ`-c7ANYL;Jq6>5D0w)eh1f@kHO#Jx&f{?;}zz>2wb;;PtJ!pVh8{1fa_tn zM%iHzKNArzSSyHwR&k<~YT6^x`$>2Y#00#LBSD6BWk!B;re%w1o3NsA$-K%L)@4|))zxL>U!$+fuA+8Ycs4@=o&KehxO1v*Or!%5185v z(<;jvDA$wnYKyK{u5e)F7tjtZV2|ri!G;XGt}ZRZ)NE;ozfG3@3=`5w!2b}?+=n!+ z8TQRk*=lLeFu5}9{tOebM;Xv`fj!B&JqQ@qZ6%C4Gt{SG|Nr&xzW8~z_WYWkZC=d^ z9KM+q_}L-955vz4`TZAmY%HIj^V^|()Yx&be2!kEssH?&u^`cl$>V3IhuPsOKQk?3 zhsgZw^94rF&pg>NwQ{D+&LR2PbBAVL@-tU{8_8sj$DcID>uF_-_}Mg<2YD9J{|KWW zV=%YlaR&c@)t_Rp`YikZr5C?%u6

4F6y3`eSze6}vvmuCKG}-`MpFb~Unr%464A z?7E0uSF-Cm^&xhWm-y|~@{8Yh;jc0F;`dwr-50+F8n@=_WlaLpTh5- zXz!bR*K1XM{bKu^Rc+mK?F&j4l$>s_C@Zfht1Pdy&shr#r2|$}f-kP9oU10TDyb|f zN8)NAE?0;Nz8Gld3w*Me;uQQKEx97Utl*Q)B<_LEN;AMBf6Y`Hs_)S1qTuiPBNK2% z)|*oQ0G-u~rkx-ur3O*D)B+n^Qd0j6H7T8l5{;A+TLvFSPdSH!siym( zX^IgV>LTEKhQ4e(j&(KHd?pag3ufaWj}{`q)JDNWE+_Oh=TPmP|nN|GxP@HDn~)x%v_PFYJC#~Waf#sC?G|X9_ha%QuA7b6-MJEmaf=^&-rzq*V~3tb?>OQakj_dJzFk(ta2`>ox*Ng6%>uvvqjhEkrxZ`iYnV^;>g6 zh;$eS>wGJYjUZV7quW^Uj0qQxfQ`$gN&tO!fLglx+8bHi7-qDVgn_O@TxaH`}> z!(dw{NxsHca_yq;}wGd(>75 zfJ3SRf3^KO*930fA?*M!vOSiu5o*>;L2xzOlX)3XvqAbhYVcHk4gmeq=ODoL^n^kH zLQ*|UdE23kEzo9AIt{gc-gY)vZJTs90xuA5J0vrh%l2Z{YykF1zd&dFZI%;&z0yCB z^-DQ+;I?1-891Tsm27m1yQPm&ga0Poen6UpZH{E^1=$ZvPlEv4pVF^{%Rvd9%J!D+ z`@rpx^b2frjCA|3^aGgKws&mLK+O?pG6H|gdKrMDQV7)oIB(qq;om=55h-kJ?(?x))#KKDO2-{~FPeX$mu@E=C zw$Di~9b)0TIMiPd=^bL>b=ZLu1X?c^-iZTul0X~8!i%s!rwG(97WP6swS7sT5I|_{ zuZWKfiiNo_&u!mi;f&ZOPK=?}5XG@_hdA+l99f7H`@x;}h!dYjTcn7SKLY*tiZGec zp>ZQhPsTrhMHVSo)@=vt>2~MU5aN|G@!6c1w$R;xqOZy8BV+?I*_Cl*jP`4k ze{JRsg!cP{7H9BJ6p9u2XHVWQ3B{v?0{iizLXm|*D! zr1mpXi@}Gf^W$9XX0Bwx+AIq<+H6iS`8L8N1~6_Wj3v(WWNFhK zMUC#HobQ}MdPT}nlz3MzdZ4Zo%Xd>vqA-7TKcVHTP?LLd(Z^uaq*~F*V@+A)408v$Um_b(jytl4Qmxpr;z#xK) zIcT{ARO_(Ku~x&xw)ez(1>0N;8B=?(=X}97kA^?H-y0BYr_ot0=`l3TCqTY5f)Tic ztc7-I7silM0?d#aa7ik&kQ864!kTg$iYb%c!dO~CfGR1B0kV<+HPRcfdfFBc4II#a z6rsb9+SnHAZ${&`U<5lo^Ne(~&bjH_FSev}Ba+ep&0JStureUWD(gu~+>BuuDI}(C;G)=^W`@kY+nSGu4cyx($ZQwvhl;(h&B= zPk_aXdtT4bl_1;A|p5zw`pi2@@bBEyux% z5MWUH5W5g1+_p)#f!%E}G9){sOOb3dso5i4k2Qm&&0c8__GgFy`=u+erxy_5ZmAr# zzK{S9NLQgjE+RdBSUQOr%vMr!P%>dpFDAetDGiz5)1pW7rW>X ziGuD-Tq3X5{{bvj)M2~EycU*I={#h8ZTe5hXydmDYkG3nZ`KhH`U-){abHvR!l ztRE4h2+|tlbO*JNbT3N2lK{~84s^61>wk!it+u<(Ut{B^aRU7$XEn|y={j_{d-AuY zW16coqv?ODKVrpc^IP&4rwmMOQofe_MJ5*fl(9Xl(u7HxG#kWZEy%)LP>_xyu+Wx; z`!;Dgw9Z;&BRf}VBhY455wd*XGYi1XcQFr7H3gt-c^*b*PPWC0>76tW*kns2zZC3! z-l&kBE(IrJbc-O6AzcW7)$R$ph3rh0eLn%3Wn1aEfq)BaJmQSncyJ&k7IA(-{=Nj5 z?BC$HW{7%>!q#O7Y!?eZw~-h;1+%$f4yI${)3R_YYdwTDJ4Bm33u}t3Ig1VFK~ZW1 z)pC|(pGP(lL5QU}O9^0tQOH?g*akHAjb%bkP1Z^zv2QFFa%xE#DDra}40j-xa`1zk z#tB$vTvie;Rv{g?o)2cR4O%9)aTt!sZJJmc>}5_fYcnlBXOVdl1cd1^w~$knO^UsN z%|gzy)Wuo20)X{%>Qb=-GwwzRb+80@Exvk3$u#Nk*z9JaR4=AvHB%DDb3$_w+7kG|g1- zvEdykOm_u_gn~~pvDpmhkWlbx7UE~@1-~r#EbDzN--6}Ovp&uxvwnLH{@qOeo}YsY zM!`qsiFsVB<3;<3Rw$<6i`1Xyl0bes_+P;Z{Rx0(T?RI%#}x%NqOlXbVFG?&Kd%#y zUGg5pOfv7896VY{Uj_K{^2q5I5?a%cPg%-T#6ebPE5vj1ZqpC)n8gd%v9pDDKuF;k zmcQp=#3UhgqQqSer{cqTY$}dHLIMLfv3=s*dDK0@pC*pvW6T4n1SCuxWsq(JxfT<@ zOFstW-{i>$h_=UZ_|v$*-2v06D9awEJh$LJGOL_H%VAt6<#Ngm;F*(Wb7%lMI3J2O-`=+Z&+J)CnB=04`JWIn)mJopu_BX2aB+CeJb( z`Uan6wl82ZOe^8goiMkiXUbe)e5SA9(9IYUYdACsY&N}?Lt|ji=`9?Z06eF+a_GVg zfZ8~;1bREYgF~Y*j?>q0=oF0L^tBwi4cg6+b-5oQD~C?N7|pP8=vu6k?YS6iJwvwV zI=IY~Ew}-^e5Qp%Zm`m|#BQCHrtoS(15U0mhQU z5I$y?X3#B)19~vKEFE>W3$saXpK3w|I^;IHT;Bp^OF!sjoxRNZd*nOEE|LoOPOsu8%!MSI*rBS4vSDMabn z?HTlRZUBJ}>%0QY>pEcEXRj$jW)A6b7?jy-t+-F`kbZ|&=(Jo(vUn>@l-XSpZp}A< z@;^p1-3NmD$SK0Jr`Kc%PTa}1MEWJIZs}# zW`d@tNxbgQ2+3<@2IzWP9^;Z~8ZG48rf&-4P8n<=5HMe!)i1!16>|^GJSCD`tq^wz z{b2GEGuxNiGQoT$MZDD>P`P9hhkgmIO1UrDaFHxC$@3utZy|ALJ{YBpdy=jJ%uqfd z=f;U>n`i{G|B6ae2lQC#f~Zun$o4LNby)f}Oz4W!31E^^V6-c$3O<~KUiBpiu2`I7 zpNL+CJ+4^7Hon(mo26-Yk&W*QphLxS0?d@gpk+l3A)7;vlq(tuFkh-iU?l;{q@&Qo z3P)DYB=nFO5E?3)2v8$Eh#EALeYitf1g>1Mnw|ycQot_CwS*T72 zJrb0rz+9;4&im6O+~-}0TAw-L(@D62`z>m4HX++9HN(hMoJ-W%FI6JoBsF(SE1|y? z8^|f`1JYiwWknAmdszA_*0>4TLFqn}bCHBcM2Dm^AYxW*C3EJmbO6aNA#ILG^O3=& zq|H(3m#EHm0*pv+LA0#6i~z@_lQ66mmuFxKdvdPNBUJ1lWdU|&$6>U}3v$juUv>H- zf~dpKDpX`=1}5Rmj!xo9`VEt~E8>umB%SWyE$`s6P%*>$8jgM`+VM0ZSCBqJJDyfZ zjyB=8_HF)i^4}Mc4#48^~O@2OO-TRDS~zjEb1fp$5>h@=Ol(BhRzAn;(LSlx@oW zE0|VyIp~~i&b$&+3)Ak&+%R`djyvI^6ZKLkX3GoGK0sy5p&bv$vgOd83IQQo4(%IY z+_UB7X$17lmY1hDkY^`{9)SL3_i?BKlvp6gq1VB)7s%1<70`Quyx_LNFf7dDx79FO zFOnCeKY^#7p3b4mpwm_F@rZ>xjOseRSUJHk=J2^g753K4p;KtxUU?j_4}Bb( zfOY*Gx*aXy(qVz9 zj&Nu<)CNW?L^SRQF`_UcPG^eB$lWio{0a5;w_K|ObIXeKN&)mL*U6~bQiZVqLmU9RC! z4syAcLrbu34~J?XE>&O0p(8N+tFPzKX5@JThcLydzESQi`ru6*dLQQIVmZm{0?ii7 zv-nG_lM~m+VKkR~!sql^V6&xBRyUhOGuyqO?Xm;e!Ra&?IeR+BIgA$9PUi8$YO(HVh0;?_evP{SF1Mmv#ip{2Xr?W$(6blJq=i zy<*UYDW^%WeF}6dE|~H;u2Dq z^MAmBR_rv>4`-y9XJG8cFko8*v313@GtQVnB_JCc9&*>Da$8*wK2#$oL$BHJGc$a9 zcNVbt-VAwrmvSXG-vq|3O}BrKuq4~c11gexkOYr?Y73_xm_cI)_+{-x2Ax)lhi$o8 zIHqR(15@o}%a@K>yf~Aw(F^mdF{j%k=6pN@$@mA$=D&uY>$qN=h#9w8zn^^$u~>W) zIw9^8MUqbPpQ+#uCttfYM2Zc#Sx)VvDToLd1%^=bG8i_?2x>Wdy`4gQg_ z4U%k)KR}nOmgf;7GP&?(&_@_`B8ZxUDE!PYe*Sv#<OU2`U`nQd=ZR-C#YDqwn3qJ2v&90$Ed50B_+8&HLJ z9o_IQ#hS8r08<1}BMT3kJ_g`ADC|Pu9{`wOmb`(08SMHI1k-onU6u<#I}GmXRQyp2 z06Kuv$vIFn4S?GLdj-4~UT32^tOVmb=Mc{@Y!xCx(E@P|`r*RIR0LZnfo?0{|ER+6 zP1aD%QV1SNMo_LIcq0ixrAtMitrW`9*-Y%GB_uMj#Ao&Pxy-+whS~Wf&d}Or?4#11 z75KMg16b^j>D=%Kv00XwwqqW&3q#cjX!9<-OR=VG>wNrZoFLqfUcM86V%*Z>M`CUQ z0B>z?M&LF8cEMl{b19u)CRwTWC7~cSGS;1m**PpS3K2 zcUctxCEx|K;9b@Lz%@{~3f?sx^YH^tg75J8%&Y ze6AvBI!!TbLAHWFKUu>j6~V4#1Upp(_a-5zd|pMMtrRL-GUE(uknkJq=)%8Y{@Q~s zoNB^j-#YxDws@QcJap=M3^T`PW0Yy|1ww-Oi3QJ&8BQ5JWk6*&OuV9a-LAhc~ULsWiDqno_FVq zB)1cB>25@a5(`N~VPzT~gdYai)nkBJ`onwzo`#9k(ln6()!1}ZFeK<+X6w(&hw$SA zhp^Rc#jNfSt8?JmwSg@OTiM6eVQH9O1~X&kY`oKhQw7|(34pJm@Bso{0NfAMcfh-B z0|0Yj)TiKCLOuX^^u8C~CD?&$_jIrC-YeHF$eMiOf^XIaU&G= zz`ODgYpqT`2-~}5wsuUVR*3q0Iosbu!xttnw)ly+jC{s+Efm_|UAZhbp6zBR*9?H_ z9l)##*0r(#09OO)j(jF?6E}{q4F$G|`aGa(LV?CljshQ{8RfN!MAFmH>`9b#VG>ET z-TZf&V9Heb7=U>Jr&x>&@a*Wz4O5p)2?S1mc(YRf$9JUX6Y!tVV|v zTF?_)U*twYXTP=#M;y?QxOEGyZ}U2oeizXSWmleJ_@D4x^kz9zbzqXozo_v$MJ*ii ziua&yDP&n?c$RkpfLEdL9K1^mY*OGWMR)*R<~%X&rgGL7&qP5uXCmv%@1gK4yi1Xc zOtgw3JOXADjRT~6?frSG?zLW)r|QsPx!j?j<&E1Rp#yugL*75|(tgeg@>-J;e8l#rXjB zLN0@E-QN&e4N(l=OI}4N1`!wEy8p@V7R6>zzXsm*$g?#Azaa>#@QdOE01NRZAKqvD z18k;6u?6M(ArRK5dmRNr_2n)?#^$H15wgsx@6qSWv49Lz?kqSaiin!c@3M+c%&H;)duu2{&fSd`Zlg{R=Xql1) zL~DbBD2&q@HUbmldW|CEBma1|nt(Vi2}NQd+}O=jgBDA=MY15vSt-x~tp#T13aAr)m`2o_)FS7`sRX^52SZ>&kQq-^_DXYXApU%77;%*P_{rQ&(;|q zs)KTQJfVdWRu~kD%AMQs46Pi{3$EHO3c9rG>e4V9WN4&cM1h;?BqTe%L>yN!=%uP3 zR6@0Znn8_QEbE2Ml`bra=WQp*rG_{!T(&^P5B4Mr;%Zk|Ad9H60Q+tuHm(KT1=_zl z#@wQ2UT=tVgoXuiVB>-~zgVeOkG5ZBh||VV0;1wf(nO36CT+$-5xBu>93Y%3Em(k1 zr7|zJXv1+R&nDy0PSt0o??_@ch`$EHX6+&Y#dMYkID@aO$>6FALRUPF#E@U;ADkB~KlHYK~v@AY|3#GwOwAAS%KlSPIm%2kk(f(kdxU!_Gq`cG@aQkB( zZz)9rj*^G_OFiDr(O}RY@kWcQO2ffmv@{k8m->A@rG0L9>0s3&=b{D0VXvp(6)pDr z0l5^x{yITPKb~_$q8^X87s{|gM2AA& z2ozHY+82Z(3@vnp7eNQ7Hyrl+B2h{PK!DZ70)X|#Bqg*1C1Kt5jC~FJL-GCQ5!U!=P}J)R zhh0NzYD7lV2=+q?--ZG`{J}sU^eXHPg((dp;`o9~sNr7x#aT7N9UKVxy@P60*cIrD z6AUH@hU3(Y#-NcJfkP2z4xc*?4r&qJKx`mx{JnA21LTKk<1~*2+;NKgU6DA8_4+go z)Nm>eg4-2}09V$9u*>bmpRHi>{XTbGbGO$YXE`4@d;IuDqOPb{3#6jg1=NIFysnL5 zZ*RP_Tokk7r*4_?z7KUyBIJHlmx*9XH9UK7BdDUq!giG>s& zCqK!-8sSU~#{#^Qn_Yg^zX655#~<|t=n(K`Zk&`9aP>scc#L*wPt50!7W)FrNs0>l zZnKUb7wg~Fi3VM^A=M}v49y0e@xM}Zh8+E$1<{b3V=!bJvW#L1P#E>MU(#$4joAjh zF=R+Hic8l61dRB>seb<@gpp{p84RXuXmJ~o8FUA>8`2&&hX>$xV ztT#SymkMYZn65LLqQ*}?F&G6MWG;)5=tZUyXmSOp(eRyGT+fuaHHi`+Z|SX2 zT9%+epQ6DYqbbYOi#?wwg2Z$F`F?NzcSSBWzHQ1f*z{eZDXK5TKP@6CV7iEm>~>xJ z$bx2HZ*7LEETjH1op^u__P&cn<00erW?Tb}uN#;48kkMwr|OSg+zj|-WN^MG!Ys_q#{V!tFt#Oh zgxOdie!blFo#J-V^%EDbm%F}Q+Y?ZK5z!s&`1r**4YG5foMAAuq0-W=ge}CZ$+sF7 z-VUN?neIiw=e$lPxu~CUuOUr;PO~9hAKnv%n)QZsz#GppShfMQnHi(3#ArH~&oMm& z4^jUZiB3eCehG-sH#VyzPHr|BZZ%9niKU;Qz)qMJRAMno>}=kH4d(!lJe-u#lD9#H zmEt%m^g_F8pg$7wpG7+U8O&CT{_3rE*@bk*%M2D~$Gh}zr=W-Z@gh_( zM(ns>pTvbg`!G$_nmV1{ zz-C_<@_ctJ>;+o#yJs+hVMuR?JTOWGpU4pLh0q-s%g!NSICzFD9KdH106(T-@<$oO zAl)rr@VCYMeoE?PBZyCu2!(^t$Cjo#=eowVolWg+&aN{%8u5t;o#dGh zI2!!n4IM$UrJ^ACG2r75x;Mr@Dk9;r4fLTBYcXwak~<%v z-XCPs=3Aas0Xlowqbj=A*48(+*0!{?*E`$VyPQpJOY@q7%U$BN%pie4Bk9;+EX=m@iU`)CU6rFHvJH%zv2c)IMlObO1=F z1JOtVZEX(@uRP=Vb1};6&g^P*u5M~;U@h7^If=6^*bP&x6P&NX7X~h{lSyE!jv#g6 z;6`tt!^fiq#d7x~-SKz_(P&|xyC1htt}uOkM}5E7y>YD zio-)Dk1zo9!pmn>eZSA|=>SjlMj})yJr5whuq6z-lZS0Uq#+OI=)}DSsuK1NxKN$2 zu-O-3zRo>Nd8|lRIL03UFY*|iJu}=jdiXt>kF8p)fI5{c|CQp-d;Xc)LyUl zc()TQ%C?bYp&(;GoCIejsKJ9mFcfu#!8Wjd;nPu|4i^A**x|jUgWLjfB^IJ>6COeX z{dU826iCo_LL@~J{KZGAZJ*CiHk&X_VkBGvJ$hN(?`E>m!L^8vP@ECj5{aib;UU$! zS_`h$Kj4k}+^kzYB$}b)fn?bqx^U61gI;oDcaXiR+N8`(1S3zyra&YF9H<+?T86WM zE@WYO^<=-T84*ITEaO147)wuFARfB=p_=qrUf%1`c1i=gFIuIf~jRhjUzJS+5 zez;TZD3pWe{GP$eN*8u290bK6$`SlPh#E821A*HY;$f^QQY(iQ-p>Y~JG$1p8G8rs z0c9=nkp~ia$gD;Ol9z|>Ko8~@EkPJ}Iej4~CcVA*B~h5OEC3)iEdLlqg5kzNUz99- zIOAHGfs_@dm&_pLF-Y}zVv?}@c)b3o3&Ih3>=LXqWOl>)CU;xuGCC%Eiji|o%;%Ly zk}{1ON?fNGEs%TIITQg?5QWL3ks9mQHm*cIm|xLKP}l`AsWAW!tbRHX4h<$!0<01w zU!;{SkSEHS4<2(NW7NALHZXu8zMh`;$cro(nYg1D;-|+KB)Vf(g8haG4*y{alMo7S zAE74W6SG2DVA#m0(nIJ~B+BBp60k$jFiYMBz$_%Sp$^ODTPIFSsvP?XST=W^5Li6r z$&eMvkPDb5kfb)@QQiRLXUYnxdh}I~PoC}2%Rb1;pzoW5H0IJQ(5Z>xvXcxr@$1Pw zy_i!|D+-&5(_^3_ETIBV$Y?5$Q!*Tk^9LMta)#uL2K^+==X zZ7dW6dk@Au2(ZMps=%|zkt-OL8I*~Ob8RU0F#=S;0a<6K*Bu5giCYVC2SAon$P_li z1OC_zh75PiJW-<9_FuWy$h6q(B}S z))VU^o{0`y-&qbTD+EGJ@xarfN_3^`c_;f3WAJSpInPR;*UzIwn~TSJC*NlckR%U7 zY_G3R2yTYq!lCd87!mti11xsQGX|4%FqD(+1={5dZ&1#Q)_NnsSlI1VBAj?WC)v=!HD5nrKEYW}vNqmYM-xk$&LYQO>oy5UN1j1g$hhyjs zLk>jZFxqN)0)PdMe`udi^H!{qc}awE`d(g)&|Mh8NrAz!FC?A=t1r^24%sBbW|DNyAT zXlRxr0og-4xAa5EAP3*D3&kBMTMc0rCQK!s!0|~)m&1B`>J14VK%@dxGMNO-Q<^*L$y9lIkbnfBLd+ehz&{IstP_?TA$oz+6N%z{=1D9x zf~z+~=K~CT=N5AK(jG$S40?OVNv1rX@zgDy@n9EjEaT3Wa8D2RCg%=(#m2lwWx39E zO$|=;8K~?Hh6h|x$YA+8jy=PjA~~~AHs{&}mpm1dZp>YpgiMvPlCz|UT0eqO){qVe z6|i+;y%BgoBq@`dBSTIlF>uQ1>!z3ww%xdJS61+)7k@ck9bUjCo#?wPjPcW^L9Qb# zcIqgKDzEkq#VM=|6Pp+Vm9Wqke^kera-HUO35OCEI--JkYhuY&-emPwdbo$3H|l)?2HYXoTGSr1Ng{g zdwu!o-}$r4_TqtPEZ|+%hnp^+8$egs-M?(GYEki`1@_`TdvSZEy|{M^tk#?1+R;=W zKL_|TF1P_%?jY~-a0+2A5hZJg>Np(pK9>Gf(#ryRSt!U!I6d5C&y+pO8xE3Pb|mPB zRM|r}XEZ!O5DWz)xC6np1dPAg7mTrEYCP@T;v$>Rg0LT!Pn=bF^wD+#CpgF1|WG<(bMB@a*KhiByn2=)fofYRe2sS9!ilh z!XtP26b&ZekRKlp0!tK`a!{*IxcnIE%h~crgNgDeV0t%5-Hgc}#~Q5!q?6PLUx+XD}*MKB-$LeAok z4FrTZftq=tG7WC))x)72^U{YiJAEE-vIu1NFt24364!;i7qVF21!SDa@Zz~;4}^qR zlm{W0fjvQ2*h6+@;aG?*6|lO;m~G|IkB1m;7|b1Oq`iv%NK|sseDG5{5*)(N5~c#7SuB^n?vuzD&9+OEj&F}azDJQ7@&zG zIn%*&dsuz=fhSCEUr&t7CnvA&ey*hYloli_`$^*X>SV;(-L@@g z|D)U#S4R)mJlk9u%?7VBbu`a2Cx_y0yg?!#ThkpaEH_P!jg3y4j^H^NPjFQ03*;R{ z4_LV9s-Ez8cI8H*EM9ekuZ!L>QPQ{7)CQd~m0Q-w_ZiPl$(EZk$JMpLhqqaj+eP$T z12$G*GvbB89w&(|Y)*JReDIV+70e845&8U-K#$ec(?We$3_K{wiL$(W@(h{HVSeO? zcIP`=`M{pvej+P_au14alNBf8Ymn-eK!-Ox;EO1|?xQJ0e6Uoes1T9Q9HMb&eld&y z$}&W!hf@x{&ZfRVFzi(&8N{G;bLB`}A zlQ^KFlg9(~UFq^iRCmi@4TSw7)Uy+RZbo7ZWkmH z-Y|7P{*eOWSfN)p=g=j3b#o5=x6+&!pHEd2a_En#G9fRH#u0MpGlh^B z%_cP=hjL6ZAukrh5ek}D{KJR-m*&5h_4aAS0M+d2SG7hp;UlU4q*=7;DzB~V`nBAV z4y{t6a4r`gG03Q4jYfddsw2vds(D>5XeFGZ?I55YN$AHp37mBLloWn77{09pmo6rw zOYTLd7Nr*=x_um2uORjNIIux(y!K{RyjkI=MG<~Uka`)pUqPnqSg31wGa-xt_b;z6+csiXi-E+5~N;6o>U9rfLR{TwKG_8hK%aeqKFU<%u$f~ zeH>V*@Ds*+F|SIOy{jWV!KK$FI^4QMhg+v*jWd#a@AueMCzS2u<&R_)y1z{~QS+{0 zdUc5k%dP~SpFI187 zvN940@k%GhLe-+6CDJ|s?)(3{Rg5n~HzqDad>km@ssHR!qP%|09a-)`2Updt^vSK! zUKGyL>Io>VlH)E4_lsI~=OnT_hqEh?*?oI#=GSp!^v6ub$FjB8Xi<7$Q_4OLj44Rt zJ`SX$@WyAJ$%<#ns5M#?;m3i#6cs-X1QdSPu;MieKP`&zOM*1Y$eR_UX&(pfQG`6t ziq9)Tv?wAZ3DPJd-%<Zr{V~;guMfkXhE~C*|u%lwr$(SZrj#wbGL2Vwr$(CaXT(%=DTqw z&Oca@tE#f{&8+9$QqXIuh0`#BKXi?F6BM^A%^iz7~T5tWS4>boYGwfeEfkhh;3=C(j6gSTYXRUVM;-+zj8;OJ@lY}8sfpte@)Nr*tqFAr=u5XcSBop_I$!l2D5=AI%MkAOiJ`dlKBI+( zBF!4oal;%Z9kul)Qxq@U9W-?|ZqCVW1X?OZ!0E+My66mss8Ol(HnU2 zl!6=oIOMqU0CWg#mi&{nY(k>6G3r6p#0_`dV*EyvB`0|w>Dk;M;VI4j>3k07Yo{BN zks#8^o^?uEVHM(& z&LIT%L>b)K${lm7uUtW$rlni2Wo2TiYn4#CL|TEW1R;#ol&}_Y<16-~$^EslbuywI zo-lm&-m_MK@-GT3ty;#cMLT4nd8usOyM)*RJ8ab@?&%RQxeeEF1*;j{rIzM`K-xW~ z_zx$eCu26gogZVz_3Z6JHymSI&yr3X-#R+K-R6L|5q7}_w;ccLjLQQt>{TQ_kG*fF z59>zz%58<9#5Lv*HqU#@g*0N+y^-3x1p=gr@r-%eCH!W2fXFX7Nj0Ij(o%lwCOr9aiBaRTnWhl zb}&9kTDGUgdMwFM2^4wazO17WQY`y~ASGT7S=f|&r|7DIWN6AE{$=b)2{fzZ9p<<> z^8RgFATi}O6;2;H6WOj!|6JiKjUfpopEgG}N)9njW&%tOH209nE03X{(kF=F&!Wle zCkW0EdQ=cS4tUNW2Z%lkobNox>)63=3CZqkv~qClNTd6rLdqciakOwx+??IQY|iv8 zyv6MljGs=>j)1e$gm z=t=Cs>hSGBv^s9y42rGHzSh|3*v$lan%fDI_kQOE>9a%>u&~Zg+1+CbviH9CXWrjf zSxN6br>I{5PuOstpAF6@I7m+EOv%A)Y;@2_$$=SZc%o+e;bS7C&wfSVF75q*!fW)1 zr|$iCHEvjs7tZJGFR15W_XZRE2cl0N0WTY?X2}?)rs)Lw;MT(j=d;e?_6K7G4*7BH z>;%A93&}eO?<%vEk1cjUJkIZ>p%8>V5-q8HKv7>(fk1!k9J`m^OZ*qb18^$Avb>?a zkH+&q89aUPfns+PK79ahkl6CGYbWr}t)Fu8EEq8yx^;rjLGg+;C5MmquMQqL z3!;9MWC*bEkcSnXa`10|x);g`(TlT>bR#FLZMlm5}} z^5^t-dm;aHT@2!1&3z9BI~}dBFN>KQYX>ca<3@pGeO3E|_k_&bn`zrvDf1erH@R?Q z<3=sc)uJi<(t$eX%9Eel*U`*B#{XqS>rPj%w&rhR z@=N-y^q-OLyhr>9G@n!dnBeSpr%U$mC@VMoe+WEx8`^UJQaG}N5_Yhqo+o6+x{*Gs zdbkVU{&M_sp%&JHdg=u~mA|sEpHfV_kGzfsa}QFLAJQC37I;q+dR7qa5WkHv&h65m zN#pYXKT$IhBv@o>zB*AL#JWg*0yH4MmK$b>5&n8>R}C_w_$NO?IZDEQEUV+}2DjI) z+z1J&LA@0SLCzHgdw0|aN1016G!DoZZc;9Od{D z*K4&lE+1%N_QoHqVP<(;zmkRQ?7_f>zJK=a8LW}U%+6u6a2ry+Z7w~0@ImdlPT`*t zaT3|iHs5EBVz--l(f@o8H2W#un&#Z)EuPQ0S$J)dD(I1O8shfeDP4c~!s%HLIedRe z30t~*_TCw(QPb`8w)p|B^ueuRAJOL)`E4dAJO|0pcW>#`a2}4&o>t)g{4M6)vAe%; zfbCLs>e5)qz7c+XYDxDAa-HgyS;#&y{Vd<2vwG@@XgYa5`Oxv@E#)Lz81K3&EBt-jl|gt~o3hkRUwDsGRen|vFJE1r zm`~u#hb1@5=Pj-EVTbh&+maRD^w)x-=t$o3l`-x!7dR)3OR(yp_1D-t# zgsuy97!(5=a4TZ{FtIHxi{>yei9iC`86?_h8dpjwLh*~&`JHV{rTg)wm9V4qho{%$ zsaMcS{p!3+Dw`Kf7?m2o_zV)+g+kS9!_%&EheU1Bcf>?LdOpc}($w9H`1I*OTdyEm zt$popF89ja*<8>+2-kU6<$VMe@Xf^48_(+oO_B+fm+u7&AE8X{59d$RujNsK_mXDL z;mgKg_}}lwU#>oODCDpJRx3@l@d;VPuQQ(d~BhS?T9RS$Z-iE108CvcV_k zbQ=1)1eV_P$6oj6p!U`xk=A&n?(;SlX8JLs@lf$sJI=+(jF^86_|Md=``Ix5rj9 zH@TNl#LPe*%Ak}qF)Celq~G`b+0HSaIOLPkJHD|*k()oMHw3r}EG}E`b<>3G5{|t_ z^pPmc#s(<~Hqb?RQqkfxcprqDQ^N(ew74|p< zS-EC0MI6swnW-eK)9jHArn%NYg444z?}DH+zl`iJ$dTz6-AIOU#>`hc(S??XXG2?Or{4`{qp@MTA%@_yq7HGbt%!~!8J-ltcSyt{hCCr*oqHx-OQb%} zHX)r{h}&V&)3tb+-9V?%b7$a2XKp?n^*Qi)|BFysQ!D1wn;O}(*UXGx8yXs_RJ*=d zeLBze`&Md}`9$Bzwl}DQx`c%`bD0xs{PHI1UTKaq{X-PRd z!mb$Biws)p=zzcJv9`OezNv1>IqsSKNuMg|iB#9Nia}R@I4XXnBq+xLr&WL|WvNCX z0d{mg@57e@Si3GHGif+vWjCcVcO(d^``6P9#ImgB?*gEA(U%cW!(LP!#oqwv%ydFb z8P%yeQs9cLLITNX6GW)7z1`Kp!5k{nGU`l(s4&W+Nl-=0B#Qq`uhNNe;2^R~^<_1zY4vcGT3XF=CDfb^JRNR2@FY)}rZt~x|UwrrAX4l4m#S;5`w*m(}AD!`w=I=&Z z-p}guIOg917lc@-^m$MyK!v8~qJS$>A5xM^L^6S(C6#=S@=tG+YM1<=h-0TU*VBwl z`Ndp2qi^m~B*mj|p5;~_53si-fl#F0@~mxFhe*uoG&IRMKza6EHQmuwD;PXydiIg8NBn$p7fYBU*wn!kiS*Ke7VB!6!CMNpWA#s8~ah zu}-1Mt7jvfWe?JsY&w}sx8tM4sCwUndhPb&94N4)D>Vj_Bn zL)B*myo{Hwm-IQ7PX^u1{3B$ZQZkjcNTO;IXn>Xt1Y#ot1z%4E?;%BA?=*4^P+$S?y|x9U`eRBGBv(yv)F1eXX@~UxY%gJl!|O> z3-#i^H?}_>2}hyZ?*^g9GrOko8|pAes63j@Fhq?w3l*q@XRA|ztfv1~@=Wm% zRe{x;s6@G(4)xT10V(#`2)zPTZWAO_o9?khrAjfq@R@GLXvpTG*R_xEVO-O@9$ypo zSmwBAK>FPW-LWBB?*a}bKgDzjnv3yYjDk(q?4L~@4+=ncXtn)~Yeb<<+=JANd4cz6 zwF!g;s#y8Lf>l?IFb_a14w%Fk?YJ)}X;;CzmF_Y8E8r5oh=7_pp_y#j<`g$KQa`DL zn&7(shS=_doF^$8afb^iNaD>^Kg%LKx%P|bL6L2QP>ySVC!&kYvCmD32-7Cgk6buk zQAm$D!kV?W8sBGIeeL&m*$REC9Ce<5;*G~-tsi9~{ToxHx9=|-Pud<0M0g}3M0(60 z4Huxd;5rB0cT%KRNS34KOmfibVCb?u2?@MS)-NfWoCd2i;83JdlOc`(jd}7C8tsYA z;FP%R!a%`3H?5KG;h3A1WW%c#;7xve@{0=+fFum(I?=i2Ry||r`J30G51_}yQT9H! zL0HzMUkz0afLxn&;t4p4GgA;vhiZTvup2t+q|x{0Wp~Rjj`3qZFK3PfZR*e~kMcc> zI9PLrt@dgEJL4SDlNqLbF-?yc0-BZOv?63ojxuRjZor?gW=LFtb1gQGKVfVFO5BAQ zII3$Ebq}uA|AVz^c(CY5E_p?Y^vp#EX^eoMa9=7r8y}_gqwATH^@d_B7A$XQ9J)rH z3VI83AAj_4kdtka?QRXk6#w~hssEp8#nyLxi5lkDE}Z=T$0S1E($>;hU;j6$RB72b zZ8jr*`}P3k4Wr5PDJEySCL|UuJ6wjF8^xMmvW=BOf!^73X^{v5?`F|izK^_D^;C8M zNC0_rjxo2%9dH}mT^jxNTP>F4*&KEcGv1QBE$scb8h=1DU?OWtJ2 z?CzP2IjNIK8VO{`8cj?zQNyJ?0EMB2#nbR5W2S!@>>?5t>SzKL*=%Qh(8 z*<|ibLkO6l*>1?|6Yppg6CkzkS2!uu5ugD?F3?~V5~##2E)39Ie7faoModI>ZqXux z8Ib0#`qk6vPp6U?kpW_SY-bFui9ZE%AW%O&EYnPy)>IA56e{EUAY;sX9Mqy|5g$K) z4Qkg9@B|Yd@rk~WbZ?yi@j@FSAyi%6p*yLg-G{x$b10v{aMEL(E5U@5xFV3Lwa`dyV{ip? z7L$d4ko8!dz@3r}GT04_pcvI48+S#Tf1(%`z{E_fj7PABHEKB7ukl0?=dQ<-3k^v% zn={`ZUJ+$f^9ep?C^aFQd7xvGGr>=8b56t`y?csp(xKc#l=at$A+kdWhmbXOu|1x? zqo|Q!)R6Ra16Hhb6JNAfodvU}9?vVNGmJaO5-mlxDeCiw4UnP?|ABfJD&hgnjJg!D zz!lbp=0}IBAW+$szr$!PO6B#gT*@{4i$H_Kh5&Nz7gzGy{Z8T``lxlgPt{SbyRm|R zctn|+P|j?Y1_Nxm`2z%$E8ijOf`6I#eL-7jB&9K6z0W`W@$sqo^#;xc7o{FF|+5n(zkq>ks#`Q#__@zRLxc_JLqiLW`<+ab! zAm&G;>Ze11RoNN&@S>)L%~Hv05xEPrBd2-GsEb>k@+;NBz+sWJI5MOt3o&LSuqH=k zxf=O=EzM0u{;sxE)#60l!7@>Z#T-( zmF#+Ly>+v-!i$Zsn^j)Vj#{6@n^P2V#?NQdu|=>q|zV1p;_V36o7 z$w}2bA$_zIoD*|CRqwR~EV6&4dH?F`5OtN(DC#Md8?*Y1ay^LgmZ6@gEiBRm33flO z&|-dTsxTvSao@CSm%!k;4+}z&IFmO?31H#othqlRe2E~=Oee{1KBqO`U1Kef#Ipy- zE_jF=+Hs?E&=kRvOdK3QuJ*CsQx8HGs2cF*gm$2HFN&zI8S%U)v41^<=(R zhl+nKC`u#7g8b^AD(Hvw)p>zUO|pxZ`BRW)LqFdeq^@qO-gcg%RLzE9T& z8L@VHJ{F+DLshw<6B?Py|0?@C6LA>n{UPs9#q8t0-Os0lLYF`+_n2=Par7B=olX(; z2?mScD+iln4cl}l<>}&$F)p_ZFFIeGUUu=#ppxO9-V@)BqHum(xUOi8(vA=Vo^!)R zh=DVHXQZ?BU2E5L`=vy`B^x5T`rpf9)rDr=gS-yC^e%<@fn8P{Bd>kbh5QOXY);+s z^AcOw7M$l{=b!%&1jZ0K+gyYEp$`X)!tnev~iS^|e1Vu6f`wS84fE?Nne{hJ~w*q-!m$KUDmumu}XqIAu0Ll4<0l`}rPl zX#z@9aGg;XM}^|**!pL*u!{;&$Zc&^@SG+rp+S_T6tfO2YteG)f^V>W>hZ6#J*ZC; zP9?Y@56VS$^I-c^L+1AW5xSbMgAXLKaZ2nF64;V+45H%gjI&(#$Mcya@UUov=`yTx zd$X;MNAZFCc?s9zM%M_IuRTO0yBBR3KjEv8&!VN{<=j{4iGV^dJgdFq<;dVFSvTg(m@n`XmVo26JJZij1q!xtC zwVm7$Ynb~Ab5>_nTeD07VC%RaHfd&Qxb~ZL2aq8GX?hqwdi!M^)KoBOi51cubxNI0 zb`cNt`ju&H=59^P;D0(~K(gA&gI^a`;RvpFI|d&PzXR9f0z?I~$TGUC#ryjVm?4TC zIwX;WZFVq(28Nm1N^UGU#I5Aj;0yesjVvf!DS%!GpM&1Fz3S;Pdp>p+~||OS(7g?`y^Yk@UkqJ22fo z`RH%_7thBtt+wx$ri4f0Xs>#%GQz6gVY{5ZWXAHxA8701G|FifxG}n`Z50sROVgp% z7J3Dix^j&Gb?2ILjVhQ6eWdH~0>InWM!<(hrOF(Aok1*^n53dxTREkQDp&6sdb~fP z#U!8`GC&c9l#|DlyR*1&4PTTdB%u6Xi)FQi!#4S1hT z25zI&YSwb+x}V?M!U0WuC)@a_hXOjff)RbhWYQs&M_$K2YVdOskG!xW>GkgG(fO|& zDGYrRpSXKG^d{)qfmGoFZA<(DemVf=rDp`tqtRsQ>TaP^IVf%m6O>{ zNfz_Sh+Er~H6E%_;QuF4SvHI*w$?$D; z)3c@Ni%G#=4VL@1F}B%s-?sp>*qkqV@iovJ2Y0iz;`orOt$>bb1Tu||w7!RlOPHWR zYWoyb&eD`H`ma9FUsPDK`j?(e3=&>wuz|%RBrN(_zf@F1F$y$8g#{tIyZ=kN`f+q{ zLInf>p!;<*{x5}MV>=srL+9TTBRWpjYJdSI^yVFvsH3m|Qqv7HK(ARBJS1xvW60^> zGEH4{Rn%ks4&TriMkBS%ZjE}v7hiY(e!IYx>+rSJWgF$S7-&6BkX%UYw)m1l+fwyI z#NGuBz@Mv6#?-F>D;-sKR9lq|B=J)1f-$l3yYIKUR$4r*C2=YBjOmVEj95g2hx-1f zR$6{ak%Ppes9qKe+=8SfeZSLeAO`98>z#y4zGZS$9(BS{LUcc3ZCG4}r~*hqcUfg(Ww0E{63 z0GR$O9Z=ui!`RT+!c-X32+@bd8Ff~|_ z%UQ|YUv7GuxjwT$V1KNwYwh+vJZ$Y0)SSmWgguNO^qm;Lmck1#oQxXMJt(n1#PFa$ zNokFJ65~7PsQNj^lvfU)*Dh-WRrP9__vIm1XMZD^sNki9(R$JTpbW|F%c0YucP?ofA(Ng}WBJh&_f)!F z)$Ij-qVj%5Or#gIIDxU}csaDW%I2Kufgb#APnHqYgKNgJU;$E);@)da+E0OB)) zT|Ey8<1fP0901!~-))ND;9IP(KMKgybC^=N&cf=ap}?=Zk8zr!(aqw$>+_ zb~}@{MUX%}2HR1W`vk83aI%*4u@t&EHo;hqD@bWDD_b^C{GC(<{=6z45WH=7mSOk_dD`@|5(Lc_C=Fp-7y-6nW_VU$3Lgimk}HfQA)> z^Q^s9wYL-I_dn532QAA~wR76YFZf%y*N#VZhOL%QfqK1%;|OvFQW))_;%sI6FrJ|| zMTzQGp1pCMz;ApjlHXCI^uL^_vO2QwvzgD8e5#Vx{Td}U`HqbkGI(iWJ%-@rQbwYrz4D`VHOEB*r#H?8AyCVW=LpMOq2x3HK0o zt3RcFSCMuTUk?E>Qt^YF2NS@w(gcsig84{!EFqS*!-MmomUN+h_Dl2^fVG<4uzbmz`TzYA{F(`_5(-Af!U`2X{0 zQ>BSC1^vwtpubJU|MqD6-#Ozyk2X_9+1LdJgr=-U$%R-@hy6e*hjNjOE23Z(!e9+J z9gQj#LfSTwYF-;*Wb*o~Ei^*9TV{^hk#B_W;F`?mUk&lP-*za5h5q0!W76yX!-3*&Q**CkAjdJu2qf5Ny!|JFgPkZ6JkJx_XCdG>4!JBu0)kd^ zMC%Opj>3Gi@>Hj?b0VGCKI9_~vZs?#Ti!u`Kov3GW!;T#!!PJx@b!#_s#Is`U%nGY zQ6&vkc>%o}Q3P3KB^#4A%~PSDGY8*g&O8rzRla2QuNx5A*UAF>K*_*C<}y@1^~wF= z_?wCQOlt*i#>lkyNT68G9K3gU_dezNej*^FZ?Rx{=#Y?2UEc+5LZ0b2Uu23YAY;kN zTHyFyg9fD5khP>~A4%55>N&j>qPiw)rKso{)a$JgWE{Nt%!RWzKg95?rBvB#hBB(RabS@#RYtUCGV@s4E{awK&^Yc|x{$}9ZIJ*0Qp7OK({fTAVV*s4P^SK?YUt7pHtohF&`XXCx>9kzk#nyg- z`P^)25o6PQmrr?W)(7pnVToqzWS38UYR(7m`eBJ@3w^g+fp*ph@j7yeXfswt+&w(@ zo{_KHP)%Bh8{-H$Ov@$eTCR8N)sB&GOnL@`KD@tMG0XoX(HkneLb_?OOD5IIlaIHrZ1Y-bcAIo{}LapO6G&yig`Kn6Y~=DQ^QgN z)<+y`b%spl2Hm$vVhT&B{<&Ls&(26?p5LIzHM!PpD2H|zffP9U+nX?~=LNjxo6v_{ zgp0UsOL{;9T|`cCj?tZO*I9VGMR33o3k~98W^wJZcC^;%J8bEGvT>Jqjg}zA)^I55 zdoqgbOc~@w*2|7p3kHkmlnYNq^O-~m8Wg4mw{5HCp316n1VE^peP^x`4c+qRakVo$ z+koiBa&!iJC3wt9I0FTpr>!gtP@RR(#a`B%`tiz08~%ou8?rByf&_nF}G^17W^)q zZe8rbdQANwOO3w<{)S+$OXXlI6=XHHG&8&l<(SzgpaSC0Vb;0_qI~x>`cs5hd33RV zgRKNn%0>D5%3WFQ zKk^}$B(EOiJWzj9HO|~xd81XEyQk@gU1)wY7Xpwm#ETvJDw+= z;R899qXQN}BV7eNTBTx zQqaEI_bdyU%xD7LQjm0N3rlF)T3m4m!nnrNz%=GoL&yc~n)qvV`s{)L&VwkwS!w5^ z5%DtAssfvY)vH1qlC=5(nSgSjumK-RM7kC(z*t}``77_zT0)*j?m(f6GKda&?#MeM zlJ_be(~ux!Tf_~uL$IT(tLCUy90S^*Ex(P%5`ef4snFBYk3jKwUE%I|d}lV1oKN7t z&mTxb+rR8LF}Zw7WqFEuJ*oY8)ogRkm*k&*a3O1}cl{1K>2E>UDa(87D9o(p=(+nL zBkZ}tqSsrvEH$$aw3}}<94)C12FG1k6hH_D=z~{~Wwo!~9W^Ha*ETT86bH9n?*aqg zv}TL<%ZLI7S_NKyx;&L5_2WQdh{u?262p>KdUf|msQ!~0B5I9rq0XX0*!FDe!R1#9 zrd_M8rsZ5NM!D#5ur%Cyp{EtDYuu&LmwtzjfI3d6ePRAcMSSOgq3eUvvWn2t$_dO5 zVOvbs)dgKduBig=s67pR8prACYRAH!?H<-Xig4j?WWyz`1qeoDhCYTwd9dH*w5md# z=h(%V$J4d3FFG2HR@-lI??(YYR;?(o44SoE97G@$K+uDP2v`|kM!mqQ+-m<*#d)vA zAC?Qu%K3C`V;!T9$wgq8!ll7*Izd3_?(%l(&-;b2HVYY#3;&)eYE3$xe^wE~>eTCF zviHK)9%miFFPx2CfC)cSrt$+hvTC4!`E)Lpn~5 zL7kxp7rYmomz2m*IOtA2zUC@?sZgQ#5ICyi1cZ1b3VaA@50*kvL=VgvYG-hFGyT=MipMWyxDPzmH!B^|owS`>Wpl z^{EymD_2YL<_rR@{^9i&EFoM!I0K1LXYDcv>zwJE=|$Iz4nYiL2rN^G9daxffQy=i zVa9E)!8h5X1SiU)|4aH4H-?Nci;|y@O``FSqm(CHiJ~{D)TJ5MG*AuMT`wx+z}|MF zK3LwE+BY@SE|7oah_iC~_4G2^>R#vvi zg*e_lPFzVC7*ZHiJd(Q@qD12!5^4p~=ZZFg15rIr!=gpwc~D#%lxUN*nPSGJDS0$w zl9bR?Mwf~n6l=r_L4`;1jfES*`ufUqqZs7eBjyIv^Am3?9zZ%=eNGWIB{sEB?+7Hq zP0cQdImBx$*$Yc17+64fH>~F!Mx{tU056v%b>K~c1L#Ju1a%o(mm~3f_ISe=5*3Zj z-%$7Uq=_bx9+}j(FC(`jzR{BU!#CCu=wxckAIF$iT+@Cu0k!GkxYHBf?yP#;%g*$V zU)KZ=3Y<(X{D!Z_ZF2+*e_}Ag#9m`8sA`v0GZ#Vk?e49BLuA-yLW|Pky>apuO7&a@d9Jx`8W1ctX}EDINDT?9 z#bL6?$v1371=lRbnnRmVg9n27wnBAV!iy3zC^54mB*bDTHwGur!P5w9AnU+`09@Sb zGmkOfoN-M%q*P42=$%VdzKp+6*OSm0SkYuiA(;HjXE;6ZGcVW(GkBk(R6eY|p8$dI zV~@D*%EG-P_E3qt424Ed2&`zxgdVks2$uE}HW7xTa#4zPUX`pTd zP{;}^ejrl9+`4;1<&<|;p7m2w<1*|;RPP=wNETykwH7!^(}QPIe| zZ2yR=JK-}7cQSTo(N0o6voBqpgLeWBiwaqH#L|}X%)WCD;eavC$n^9gC<>2Yw z)<1Eq#WHB=8=`Mz>(`3f+#ElIT4k3|@joGQ={w8x{2@Ey`ZB!-DeI;RW0Rqe+OnDi zi2(CJ_91X2g%tj!uQnrA;T;(L0pTm>@!?={+t)$bD(k_u>&UKKkX9M3o=h23-&B@d z9ES_`eqz`Q^`0M6Q9~j~x(hqpPzY*`l=7|w)+y4#o*A=s&|pYW>Q>Rtgw1C6dQ$UO zN!8v=BQF~JZce0KEXnKZgXavU&Miw)5C^sLe`%ur6VkRk=H?`*f)+wzt4pvm_w9htHBi-?cD3|!QO#Gjmz zKKv81R#)MJSfo=v)zg1PZ(UbphzeeMS!@H^Ht9y05whaLFLNR1*Ylvn8Q!8`CpY3C z!Ip_^rCncm;!g4r8+$!V4;{8r&h8T%RYC6HqLY#~jrXO7p_Ik?sL!Bl-&wFIvF|~3 zYSBd6y_qbc>NfQ2Nr1)W2XXY}afiCUiI<~482UGWf($M&?)p%D#f^E0 zn=jEFN{>t^49M3Ld>;9Ry9F6@;M|uJv0$&n!7f!})z62~)+{z-*g59Jfu9Zw^8@{B z)g{2KS?h*nUWNIflqvPwv3UU)6$SjV&WqWi8Skc28C}e=*%cV|>k@tFu-TOejxX0? zZ~&1PU=fv!B6yOaWkAC=YZUF>(W&_*itZUmcQ@%X4r?^n;}@kdWk@$tdVm~`!Yu}y z0|+)PLxU^-P7zvifi&#;?d`vD3yGznJ;yrMQ3sz_sUe7AN~TnbLj~@IwJ$T+1hp(0 z6DG+K-}-MTA_AESxSdvl=0&5LI`ofLuA#$H&r$KKZwV4sf0>Yi|Q!z}&E{VtenmrAlC~z>Xy3TuoAK>uIpZqgWRkr?W zB1DSXMt-3JDGA2ezEbBNBvP9l!)V~qP=2J}UalH!_s2=)0ZAUp*_@ymt@9r!S2WP{8B{X@UQ zIiu8N;j4pMvZYky585s#!fBh}x0NW-lc_Xj01>G>?X1#oE9J=DA@rG0d4nwABn*(} zU^#w$xxTiwe?KX!p5x!1F_okxwugl2pHWgHBmqYDH_NJCX>V9rDi!J&%@xDt66sK`TO^HV~Su9IGo-3kJ!A{yC_vz+j|%tW@mz-^0ik1 zs*y;5G{iOkmGvKyyY6+=>op2Dn(guxx2jcZqtS+IzL4{#WiVUd0(>>?zH=R-O}TE3@nR6w7eh(tUnLz_@TCkI17F=#4TtdjkSXi#=LT}R4NTJ)iwCT4ixvK~+8Hc-LsG;R0!tE) z$IXD;6e8)^qxPoEx?=0_;3iKHelLQZ^td$ zw#sc{+8cjbF{EU(N}0`eAsFfX1agGNb&M?9-XvmSP+DDB>>hv_>Y*<5PWmG-9dXyZ zNzCfL^5QT6!3<#!x0}aL$~U-eq>UWY&i(ck+;R_J`&#K&PWPc`;}?$rEk+6sW<+AAz>8Ua z06WyiCkz-*1#BF!0d7IVlo~hA1!rIRKv}G{_>0r`WUo$Q#m&V~Po8VvQ$$Y{|lsRC8Y_+w&h-NQCYpLm3nmfWKOy#q`X_o>ZgcF393@3QZf@;ui3*zDW zuJ!-pXdz&r;P0Qi8o&S`s>i0DlqGK6;^$g36B~&8c^%DbHQ+;pp(^KzU$R%|zngS&rE|@)sBXUV!GwArC5$kI;TgdL1T469~E%h?3t@ zaBXMdC5jhWz-Znw40NwtvII9y(M4vmjB6Ol%etJQoVVn8YV3o@q41(5a5Z*{T77ik zX8{CtpD}gfy8#h`7}n2*dc2^{VY!oIZ+&EcM0okRLm_h|0Y!!0QrSSF?Acwkd!Rdg z1YPs?dHmw!jGm%W>+esX(xGwf{_pz*yO~ECFN2pajaaTeFrGgzG(x`F{ZgEXwnGdX z3>gy1q}5KhIL56Pm)wi#CgEpdEn%Ev-Ps5xrN|L&;m2f=#9Q3Ou-oEZl8iJGSRroB}}gof{8HLM56szo)QUT}z-w0awrZ`GJF3Ox>e zaUV1zwl-f{l8P}|Ea-UsY9lq zETP)AS9lsAK>pcBVg(ihfrZOpL=rMd8x=8tU{0hUgR8lyIP+D)R@H?OMlxQscrNvC z%?%8U=pfjQfhM>nsy^!GzWxXdY|~fu;vpyhAvoiF=yJRHy7qb5a@)B`d-nZ0ce>ZC z-x-d<>^O9!Kl(ms5cY*n*(r77OA)p;gX@YD2LzKrQ4HHY4f1>(k~ zt;6n)zA!bDxs2`O01#$C0pBP11Q@Vqz+%K9WH^d0SH>U9obaH!#_kLn7Izae9t;F z$f*wGWY1g2zepn#+5s`y7?f_9v=xQg0h4Y7wG~Ny?~hK9RUK4?1Mac`?ed=Ira!g= zvh6T!E9!*8O1Vun3B+kx$7ke37g^$4�=ywK-mn@^p!gjI-UzZg5@dG& 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.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/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/RECORD new file mode 100644 index 00000000..413fef4b --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/WHEEL new file mode 100644 index 00000000..ef99c6cf --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt new file mode 100644 index 00000000..3619483f --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/entry_points.txt @@ -0,0 +1,3 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract [i18n] + diff --git a/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt new file mode 100644 index 00000000..7f7afbf3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/Jinja2-2.11.2.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/LICENSE.txt @@ -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/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA new file mode 100644 index 00000000..c50370d6 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/METADATA @@ -0,0 +1,105 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 1.1.1 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: The Pallets Team +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Code, https://github.com/pallets/markupsafe +Project-URL: Issue tracker, https://github.com/pallets/markupsafe/issues +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +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/ +* License: `BSD-3-Clause `_ +* Releases: https://pypi.org/project/MarkupSafe/ +* Code: https://github.com/pallets/markupsafe +* Issue tracker: https://github.com/pallets/markupsafe/issues +* Test status: + + * Linux, Mac: https://travis-ci.org/pallets/markupsafe + * Windows: https://ci.appveyor.com/project/pallets/markupsafe + +* Test coverage: https://codecov.io/gh/pallets/markupsafe +* Official chat: https://discord.gg/t6rrQZH + + diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/RECORD new file mode 100644 index 00000000..95c33399 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-1.1.1.dist-info/METADATA,sha256=IFCP4hCNGjXJgMoSvdjPiKDLAMUTTWoxKXQsQvmyMNU,3653 +MarkupSafe-1.1.1.dist-info/RECORD,, +MarkupSafe-1.1.1.dist-info/WHEEL,sha256=VEyGcIFAmk_1KbI6gaZGw_mMiT-pdGweASQLX-DzYaY,108 +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=SbJwN321Xn7OPYGv5a6Ghzga75uT8RHQUGkoQUASF-o,48016 diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL new file mode 100644 index 00000000..ae40efdd --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.31.1) +Root-Is-Purelib: false +Tag: cp38-cp38-manylinux1_x86_64 + diff --git a/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/MarkupSafe-1.1.1.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/LICENSE new file mode 100644 index 00000000..3d82c281 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/METADATA new file mode 100644 index 00000000..a70dd202 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/RECORD new file mode 100644 index 00000000..cae61d97 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/WHEEL new file mode 100644 index 00000000..d193dea9 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/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/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt new file mode 100644 index 00000000..e6475e91 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/PyYAML-5.3.1.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_yaml +yaml diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py b/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py new file mode 100644 index 00000000..1229ba42 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/__init__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +"""Jinja is a template engine written in pure Python. It provides a +non-XML syntax that supports inline expressions and an optional +sandboxed environment. +""" +from markupsafe import escape +from markupsafe import Markup + +from .bccache import BytecodeCache +from .bccache import FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache +from .environment import Environment +from .environment import Template +from .exceptions import TemplateAssertionError +from .exceptions import TemplateError +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .filters import contextfilter +from .filters import environmentfilter +from .filters import evalcontextfilter +from .loaders import BaseLoader +from .loaders import ChoiceLoader +from .loaders import DictLoader +from .loaders import FileSystemLoader +from .loaders import FunctionLoader +from .loaders import ModuleLoader +from .loaders import PackageLoader +from .loaders import PrefixLoader +from .runtime import ChainableUndefined +from .runtime import DebugUndefined +from .runtime import make_logging_undefined +from .runtime import StrictUndefined +from .runtime import Undefined +from .utils import clear_caches +from .utils import contextfunction +from .utils import environmentfunction +from .utils import evalcontextfunction +from .utils import is_undefined +from .utils import select_autoescape + +__version__ = "2.11.2" diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py b/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py new file mode 100644 index 00000000..1f044954 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/_compat.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +# flake8: noqa +import marshal +import sys + +PY2 = sys.version_info[0] == 2 +PYPY = hasattr(sys, "pypy_translation_info") +_identity = lambda x: x + +if not PY2: + unichr = chr + range_type = range + text_type = str + string_types = (str,) + integer_types = (int,) + + iterkeys = lambda d: iter(d.keys()) + itervalues = lambda d: iter(d.values()) + iteritems = lambda d: iter(d.items()) + + import pickle + from io import BytesIO, StringIO + + NativeStringIO = StringIO + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + ifilter = filter + imap = map + izip = zip + intern = sys.intern + + implements_iterator = _identity + implements_to_string = _identity + encode_filename = _identity + + marshal_dump = marshal.dump + marshal_load = marshal.load + +else: + unichr = unichr + text_type = unicode + range_type = xrange + string_types = (str, unicode) + integer_types = (int, long) + + iterkeys = lambda d: d.iterkeys() + itervalues = lambda d: d.itervalues() + iteritems = lambda d: d.iteritems() + + import cPickle as pickle + from cStringIO import StringIO as BytesIO, StringIO + + NativeStringIO = BytesIO + + exec("def reraise(tp, value, tb=None):\n raise tp, value, tb") + + from itertools import imap, izip, ifilter + + intern = intern + + def implements_iterator(cls): + cls.next = cls.__next__ + del cls.__next__ + return cls + + def implements_to_string(cls): + cls.__unicode__ = cls.__str__ + cls.__str__ = lambda x: x.__unicode__().encode("utf-8") + return cls + + def encode_filename(filename): + if isinstance(filename, unicode): + return filename.encode("utf-8") + return filename + + def marshal_dump(code, f): + if isinstance(f, file): + marshal.dump(code, f) + else: + f.write(marshal.dumps(code)) + + def marshal_load(f): + if isinstance(f, file): + return marshal.load(f) + return marshal.loads(f.read()) + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instantiation that replaces + # itself with the actual metaclass. + class metaclass(type): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + return type.__new__(metaclass, "temporary_class", (), {}) + + +try: + from urllib.parse import quote_from_bytes as url_quote +except ImportError: + from urllib import quote as url_quote + + +try: + from collections import abc +except ImportError: + import collections as abc + + +try: + from os import fspath +except ImportError: + try: + from pathlib import PurePath + except ImportError: + PurePath = None + + def fspath(path): + if hasattr(path, "__fspath__"): + return path.__fspath__() + + # Python 3.5 doesn't have __fspath__ yet, use str. + if PurePath is not None and isinstance(path, PurePath): + return str(path) + + return path diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py b/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py new file mode 100644 index 00000000..224d5449 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/_identifier.py @@ -0,0 +1,6 @@ +import re + +# generated by scripts/generate_identifier_pattern.py +pattern = re.compile( + r"[\w·̀-ͯ·҃-֑҇-ׇֽֿׁׂׅׄؐ-ًؚ-ٰٟۖ-ۜ۟-۪ۤۧۨ-ܑۭܰ-݊ަ-ް߫-߳ࠖ-࠙ࠛ-ࠣࠥ-ࠧࠩ-࡙࠭-࡛ࣔ-ࣣ࣡-ःऺ-़ा-ॏ॑-ॗॢॣঁ-ঃ়া-ৄেৈো-্ৗৢৣਁ-ਃ਼ਾ-ੂੇੈੋ-੍ੑੰੱੵઁ-ઃ઼ા-ૅે-ૉો-્ૢૣଁ-ଃ଼ା-ୄେୈୋ-୍ୖୗୢୣஂா-ூெ-ைொ-்ௗఀ-ఃా-ౄె-ైొ-్ౕౖౢౣಁ-ಃ಼ಾ-ೄೆ-ೈೊ-್ೕೖೢೣഁ-ഃാ-ൄെ-ൈൊ-്ൗൢൣංඃ්ා-ුූෘ-ෟෲෳัิ-ฺ็-๎ັິ-ູົຼ່-ໍ༹༘༙༵༷༾༿ཱ-྄྆྇ྍ-ྗྙ-ྼ࿆ါ-ှၖ-ၙၞ-ၠၢ-ၤၧ-ၭၱ-ၴႂ-ႍႏႚ-ႝ፝-፟ᜒ-᜔ᜲ-᜴ᝒᝓᝲᝳ឴-៓៝᠋-᠍ᢅᢆᢩᤠ-ᤫᤰ-᤻ᨗ-ᨛᩕ-ᩞ᩠-᩿᩼᪰-᪽ᬀ-ᬄ᬴-᭄᭫-᭳ᮀ-ᮂᮡ-ᮭ᯦-᯳ᰤ-᰷᳐-᳔᳒-᳨᳭ᳲ-᳴᳸᳹᷀-᷵᷻-᷿‿⁀⁔⃐-⃥⃜⃡-⃰℘℮⳯-⵿⳱ⷠ-〪ⷿ-゙゚〯꙯ꙴ-꙽ꚞꚟ꛰꛱ꠂ꠆ꠋꠣ-ꠧꢀꢁꢴ-ꣅ꣠-꣱ꤦ-꤭ꥇ-꥓ꦀ-ꦃ꦳-꧀ꧥꨩ-ꨶꩃꩌꩍꩻ-ꩽꪰꪲ-ꪴꪷꪸꪾ꪿꫁ꫫ-ꫯꫵ꫶ꯣ-ꯪ꯬꯭ﬞ︀-️︠-︯︳︴﹍-﹏_𐇽𐋠𐍶-𐍺𐨁-𐨃𐨅𐨆𐨌-𐨏𐨸-𐨿𐨺𐫦𐫥𑀀-𑀂𑀸-𑁆𑁿-𑂂𑂰-𑂺𑄀-𑄂𑄧-𑅳𑄴𑆀-𑆂𑆳-𑇊𑇀-𑇌𑈬-𑈷𑈾𑋟-𑋪𑌀-𑌃𑌼𑌾-𑍄𑍇𑍈𑍋-𑍍𑍗𑍢𑍣𑍦-𑍬𑍰-𑍴𑐵-𑑆𑒰-𑓃𑖯-𑖵𑖸-𑗀𑗜𑗝𑘰-𑙀𑚫-𑚷𑜝-𑜫𑰯-𑰶𑰸-𑰿𑲒-𑲧𑲩-𑲶𖫰-𖫴𖬰-𖬶𖽑-𖽾𖾏-𖾒𛲝𛲞𝅥-𝅩𝅭-𝅲𝅻-𝆂𝆅-𝆋𝆪-𝆭𝉂-𝉄𝨀-𝨶𝨻-𝩬𝩵𝪄𝪛-𝪟𝪡-𝪯𞀀-𞀆𞀈-𞀘𞀛-𞀡𞀣𞀤𞀦-𞣐𞀪-𞣖𞥄-𞥊󠄀-󠇯]+" # noqa: B950 +) diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py b/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py new file mode 100644 index 00000000..3d98dbcc --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/asyncfilters.py @@ -0,0 +1,158 @@ +from functools import wraps + +from . import filters +from .asyncsupport import auto_aiter +from .asyncsupport import auto_await + + +async def auto_to_seq(value): + seq = [] + if hasattr(value, "__aiter__"): + async for item in value: + seq.append(item) + else: + for item in value: + seq.append(item) + return seq + + +async def async_select_or_reject(args, kwargs, modfunc, lookup_attr): + seq, func = filters.prepare_select_or_reject(args, kwargs, modfunc, lookup_attr) + if seq: + async for item in auto_aiter(seq): + if func(item): + yield item + + +def dualfilter(normal_filter, async_filter): + wrap_evalctx = False + if getattr(normal_filter, "environmentfilter", False) is True: + + def is_async(args): + return args[0].is_async + + wrap_evalctx = False + else: + has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) is True + has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True + wrap_evalctx = not has_evalctxfilter and not has_ctxfilter + + def is_async(args): + return args[0].environment.is_async + + @wraps(normal_filter) + def wrapper(*args, **kwargs): + b = is_async(args) + if wrap_evalctx: + args = args[1:] + if b: + return async_filter(*args, **kwargs) + return normal_filter(*args, **kwargs) + + if wrap_evalctx: + wrapper.evalcontextfilter = True + + wrapper.asyncfiltervariant = True + + return wrapper + + +def asyncfiltervariant(original): + def decorator(f): + return dualfilter(original, f) + + return decorator + + +@asyncfiltervariant(filters.do_first) +async def do_first(environment, seq): + try: + return await auto_aiter(seq).__anext__() + except StopAsyncIteration: + return environment.undefined("No first item, sequence was empty.") + + +@asyncfiltervariant(filters.do_groupby) +async def do_groupby(environment, value, attribute): + expr = filters.make_attrgetter(environment, attribute) + return [ + filters._GroupTuple(key, await auto_to_seq(values)) + for key, values in filters.groupby( + sorted(await auto_to_seq(value), key=expr), expr + ) + ] + + +@asyncfiltervariant(filters.do_join) +async def do_join(eval_ctx, value, d=u"", attribute=None): + return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute) + + +@asyncfiltervariant(filters.do_list) +async def do_list(value): + return await auto_to_seq(value) + + +@asyncfiltervariant(filters.do_reject) +async def do_reject(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: not x, False) + + +@asyncfiltervariant(filters.do_rejectattr) +async def do_rejectattr(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: not x, True) + + +@asyncfiltervariant(filters.do_select) +async def do_select(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: x, False) + + +@asyncfiltervariant(filters.do_selectattr) +async def do_selectattr(*args, **kwargs): + return async_select_or_reject(args, kwargs, lambda x: x, True) + + +@asyncfiltervariant(filters.do_map) +async def do_map(*args, **kwargs): + seq, func = filters.prepare_map(args, kwargs) + if seq: + async for item in auto_aiter(seq): + yield await auto_await(func(item)) + + +@asyncfiltervariant(filters.do_sum) +async def do_sum(environment, iterable, attribute=None, start=0): + rv = start + if attribute is not None: + func = filters.make_attrgetter(environment, attribute) + else: + + def func(x): + return x + + async for item in auto_aiter(iterable): + rv += func(item) + return rv + + +@asyncfiltervariant(filters.do_slice) +async def do_slice(value, slices, fill_with=None): + return filters.do_slice(await auto_to_seq(value), slices, fill_with) + + +ASYNC_FILTERS = { + "first": do_first, + "groupby": do_groupby, + "join": do_join, + "list": do_list, + # we intentionally do not support do_last because that would be + # ridiculous + "reject": do_reject, + "rejectattr": do_rejectattr, + "map": do_map, + "select": do_select, + "selectattr": do_selectattr, + "sum": do_sum, + "slice": do_slice, +} diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py b/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py new file mode 100644 index 00000000..78ba3739 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/asyncsupport.py @@ -0,0 +1,264 @@ +# -*- coding: utf-8 -*- +"""The code for async support. Importing this patches Jinja on supported +Python versions. +""" +import asyncio +import inspect +from functools import update_wrapper + +from markupsafe import Markup + +from .environment import TemplateModule +from .runtime import LoopContext +from .utils import concat +from .utils import internalcode +from .utils import missing + + +async def concat_async(async_gen): + rv = [] + + async def collect(): + async for event in async_gen: + rv.append(event) + + await collect() + return concat(rv) + + +async def generate_async(self, *args, **kwargs): + vars = dict(*args, **kwargs) + try: + async for event in self.root_render_func(self.new_context(vars)): + yield event + except Exception: + yield self.environment.handle_exception() + + +def wrap_generate_func(original_generate): + def _convert_generator(self, loop, args, kwargs): + async_gen = self.generate_async(*args, **kwargs) + try: + while 1: + yield loop.run_until_complete(async_gen.__anext__()) + except StopAsyncIteration: + pass + + def generate(self, *args, **kwargs): + if not self.environment.is_async: + return original_generate(self, *args, **kwargs) + return _convert_generator(self, asyncio.get_event_loop(), args, kwargs) + + return update_wrapper(generate, original_generate) + + +async def render_async(self, *args, **kwargs): + if not self.environment.is_async: + raise RuntimeError("The environment was not created with async mode enabled.") + + vars = dict(*args, **kwargs) + ctx = self.new_context(vars) + + try: + return await concat_async(self.root_render_func(ctx)) + except Exception: + return self.environment.handle_exception() + + +def wrap_render_func(original_render): + def render(self, *args, **kwargs): + if not self.environment.is_async: + return original_render(self, *args, **kwargs) + loop = asyncio.get_event_loop() + return loop.run_until_complete(self.render_async(*args, **kwargs)) + + return update_wrapper(render, original_render) + + +def wrap_block_reference_call(original_call): + @internalcode + async def async_call(self): + rv = await concat_async(self._stack[self._depth](self._context)) + if self._context.eval_ctx.autoescape: + rv = Markup(rv) + return rv + + @internalcode + def __call__(self): + if not self._context.environment.is_async: + return original_call(self) + return async_call(self) + + return update_wrapper(__call__, original_call) + + +def wrap_macro_invoke(original_invoke): + @internalcode + async def async_invoke(self, arguments, autoescape): + rv = await self._func(*arguments) + if autoescape: + rv = Markup(rv) + return rv + + @internalcode + def _invoke(self, arguments, autoescape): + if not self._environment.is_async: + return original_invoke(self, arguments, autoescape) + return async_invoke(self, arguments, autoescape) + + return update_wrapper(_invoke, original_invoke) + + +@internalcode +async def get_default_module_async(self): + if self._module is not None: + return self._module + self._module = rv = await self.make_module_async() + return rv + + +def wrap_default_module(original_default_module): + @internalcode + def _get_default_module(self): + if self.environment.is_async: + raise RuntimeError("Template module attribute is unavailable in async mode") + return original_default_module(self) + + return _get_default_module + + +async def make_module_async(self, vars=None, shared=False, locals=None): + context = self.new_context(vars, shared, locals) + body_stream = [] + async for item in self.root_render_func(context): + body_stream.append(item) + return TemplateModule(self, context, body_stream) + + +def patch_template(): + from . import Template + + Template.generate = wrap_generate_func(Template.generate) + Template.generate_async = update_wrapper(generate_async, Template.generate_async) + Template.render_async = update_wrapper(render_async, Template.render_async) + Template.render = wrap_render_func(Template.render) + Template._get_default_module = wrap_default_module(Template._get_default_module) + Template._get_default_module_async = get_default_module_async + Template.make_module_async = update_wrapper( + make_module_async, Template.make_module_async + ) + + +def patch_runtime(): + from .runtime import BlockReference, Macro + + BlockReference.__call__ = wrap_block_reference_call(BlockReference.__call__) + Macro._invoke = wrap_macro_invoke(Macro._invoke) + + +def patch_filters(): + from .filters import FILTERS + from .asyncfilters import ASYNC_FILTERS + + FILTERS.update(ASYNC_FILTERS) + + +def patch_all(): + patch_template() + patch_runtime() + patch_filters() + + +async def auto_await(value): + if inspect.isawaitable(value): + return await value + return value + + +async def auto_aiter(iterable): + if hasattr(iterable, "__aiter__"): + async for item in iterable: + yield item + return + for item in iterable: + yield item + + +class AsyncLoopContext(LoopContext): + _to_iterator = staticmethod(auto_aiter) + + @property + async def length(self): + if self._length is not None: + return self._length + + try: + self._length = len(self._iterable) + except TypeError: + iterable = [x async for x in self._iterator] + self._iterator = self._to_iterator(iterable) + self._length = len(iterable) + self.index + (self._after is not missing) + + return self._length + + @property + async def revindex0(self): + return await self.length - self.index + + @property + async def revindex(self): + return await self.length - self.index0 + + async def _peek_next(self): + if self._after is not missing: + return self._after + + try: + self._after = await self._iterator.__anext__() + except StopAsyncIteration: + self._after = missing + + return self._after + + @property + async def last(self): + return await self._peek_next() is missing + + @property + async def nextitem(self): + rv = await self._peek_next() + + if rv is missing: + return self._undefined("there is no next item") + + return rv + + def __aiter__(self): + return self + + async def __anext__(self): + if self._after is not missing: + rv = self._after + self._after = missing + else: + rv = await self._iterator.__anext__() + + self.index0 += 1 + self._before = self._current + self._current = rv + return rv, self + + +async def make_async_loop_context(iterable, undefined, recurse=None, depth0=0): + import warnings + + warnings.warn( + "This template must be recompiled with at least Jinja 2.11, or" + " it will fail in 3.0.", + DeprecationWarning, + stacklevel=2, + ) + return AsyncLoopContext(iterable, undefined, recurse, depth0) + + +patch_all() diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py b/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py new file mode 100644 index 00000000..9c066103 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/bccache.py @@ -0,0 +1,350 @@ +# -*- coding: utf-8 -*- +"""The optional bytecode cache system. This is useful if you have very +complex template situations and the compilation of all those templates +slows down your application too much. + +Situations where this is useful are often forking web applications that +are initialized on the first request. +""" +import errno +import fnmatch +import os +import stat +import sys +import tempfile +from hashlib import sha1 +from os import listdir +from os import path + +from ._compat import BytesIO +from ._compat import marshal_dump +from ._compat import marshal_load +from ._compat import pickle +from ._compat import text_type +from .utils import open_if_exists + +bc_version = 4 +# Magic bytes to identify Jinja bytecode cache files. Contains the +# Python major and minor version to avoid loading incompatible bytecode +# if a project upgrades its Python version. +bc_magic = ( + b"j2" + + pickle.dumps(bc_version, 2) + + pickle.dumps((sys.version_info[0] << 24) | sys.version_info[1], 2) +) + + +class Bucket(object): + """Buckets are used to store the bytecode for one template. It's created + and initialized by the bytecode cache and passed to the loading functions. + + The buckets get an internal checksum from the cache assigned and use this + to automatically reject outdated cache material. Individual bytecode + cache subclasses don't have to care about cache invalidation. + """ + + def __init__(self, environment, key, checksum): + self.environment = environment + self.key = key + self.checksum = checksum + self.reset() + + def reset(self): + """Resets the bucket (unloads the bytecode).""" + self.code = None + + def load_bytecode(self, f): + """Loads bytecode from a file or file like object.""" + # make sure the magic header is correct + magic = f.read(len(bc_magic)) + if magic != bc_magic: + self.reset() + return + # the source code of the file changed, we need to reload + checksum = pickle.load(f) + if self.checksum != checksum: + self.reset() + return + # if marshal_load fails then we need to reload + try: + self.code = marshal_load(f) + except (EOFError, ValueError, TypeError): + self.reset() + return + + def write_bytecode(self, f): + """Dump the bytecode into the file or file like object passed.""" + if self.code is None: + raise TypeError("can't write empty bucket") + f.write(bc_magic) + pickle.dump(self.checksum, f, 2) + marshal_dump(self.code, f) + + def bytecode_from_string(self, string): + """Load bytecode from a string.""" + self.load_bytecode(BytesIO(string)) + + def bytecode_to_string(self): + """Return the bytecode as string.""" + out = BytesIO() + self.write_bytecode(out) + return out.getvalue() + + +class BytecodeCache(object): + """To implement your own bytecode cache you have to subclass this class + and override :meth:`load_bytecode` and :meth:`dump_bytecode`. Both of + these methods are passed a :class:`~jinja2.bccache.Bucket`. + + A very basic bytecode cache that saves the bytecode on the file system:: + + from os import path + + class MyCache(BytecodeCache): + + def __init__(self, directory): + self.directory = directory + + def load_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + if path.exists(filename): + with open(filename, 'rb') as f: + bucket.load_bytecode(f) + + def dump_bytecode(self, bucket): + filename = path.join(self.directory, bucket.key) + with open(filename, 'wb') as f: + bucket.write_bytecode(f) + + A more advanced version of a filesystem based bytecode cache is part of + Jinja. + """ + + def load_bytecode(self, bucket): + """Subclasses have to override this method to load bytecode into a + bucket. If they are not able to find code in the cache for the + bucket, it must not do anything. + """ + raise NotImplementedError() + + def dump_bytecode(self, bucket): + """Subclasses have to override this method to write the bytecode + from a bucket back to the cache. If it unable to do so it must not + fail silently but raise an exception. + """ + raise NotImplementedError() + + def clear(self): + """Clears the cache. This method is not used by Jinja but should be + implemented to allow applications to clear the bytecode cache used + by a particular environment. + """ + + def get_cache_key(self, name, filename=None): + """Returns the unique hash key for this template name.""" + hash = sha1(name.encode("utf-8")) + if filename is not None: + filename = "|" + filename + if isinstance(filename, text_type): + filename = filename.encode("utf-8") + hash.update(filename) + return hash.hexdigest() + + def get_source_checksum(self, source): + """Returns a checksum for the source.""" + return sha1(source.encode("utf-8")).hexdigest() + + def get_bucket(self, environment, name, filename, source): + """Return a cache bucket for the given template. All arguments are + mandatory but filename may be `None`. + """ + key = self.get_cache_key(name, filename) + checksum = self.get_source_checksum(source) + bucket = Bucket(environment, key, checksum) + self.load_bytecode(bucket) + return bucket + + def set_bucket(self, bucket): + """Put the bucket into the cache.""" + self.dump_bytecode(bucket) + + +class FileSystemBytecodeCache(BytecodeCache): + """A bytecode cache that stores bytecode on the filesystem. It accepts + two arguments: The directory where the cache items are stored and a + pattern string that is used to build the filename. + + If no directory is specified a default cache directory is selected. On + Windows the user's temp directory is used, on UNIX systems a directory + is created for the user in the system temp directory. + + The pattern can be used to have multiple separate caches operate on the + same directory. The default pattern is ``'__jinja2_%s.cache'``. ``%s`` + is replaced with the cache key. + + >>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache') + + This bytecode cache supports clearing of the cache using the clear method. + """ + + def __init__(self, directory=None, pattern="__jinja2_%s.cache"): + if directory is None: + directory = self._get_default_cache_dir() + self.directory = directory + self.pattern = pattern + + def _get_default_cache_dir(self): + def _unsafe_dir(): + raise RuntimeError( + "Cannot determine safe temp directory. You " + "need to explicitly provide one." + ) + + tmpdir = tempfile.gettempdir() + + # On windows the temporary directory is used specific unless + # explicitly forced otherwise. We can just use that. + if os.name == "nt": + return tmpdir + if not hasattr(os, "getuid"): + _unsafe_dir() + + dirname = "_jinja2-cache-%d" % os.getuid() + actual_dir = os.path.join(tmpdir, dirname) + + try: + os.mkdir(actual_dir, stat.S_IRWXU) + except OSError as e: + if e.errno != errno.EEXIST: + raise + try: + os.chmod(actual_dir, stat.S_IRWXU) + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + except OSError as e: + if e.errno != errno.EEXIST: + raise + + actual_dir_stat = os.lstat(actual_dir) + if ( + actual_dir_stat.st_uid != os.getuid() + or not stat.S_ISDIR(actual_dir_stat.st_mode) + or stat.S_IMODE(actual_dir_stat.st_mode) != stat.S_IRWXU + ): + _unsafe_dir() + + return actual_dir + + def _get_cache_filename(self, bucket): + return path.join(self.directory, self.pattern % bucket.key) + + def load_bytecode(self, bucket): + f = open_if_exists(self._get_cache_filename(bucket), "rb") + if f is not None: + try: + bucket.load_bytecode(f) + finally: + f.close() + + def dump_bytecode(self, bucket): + f = open(self._get_cache_filename(bucket), "wb") + try: + bucket.write_bytecode(f) + finally: + f.close() + + def clear(self): + # imported lazily here because google app-engine doesn't support + # write access on the file system and the function does not exist + # normally. + from os import remove + + files = fnmatch.filter(listdir(self.directory), self.pattern % "*") + for filename in files: + try: + remove(path.join(self.directory, filename)) + except OSError: + pass + + +class MemcachedBytecodeCache(BytecodeCache): + """This class implements a bytecode cache that uses a memcache cache for + storing the information. It does not enforce a specific memcache library + (tummy's memcache or cmemcache) but will accept any class that provides + the minimal interface required. + + Libraries compatible with this class: + + - `cachelib `_ + - `python-memcached `_ + + (Unfortunately the django cache interface is not compatible because it + does not support storing binary data, only unicode. You can however pass + the underlying cache client to the bytecode cache which is available + as `django.core.cache.cache._client`.) + + The minimal interface for the client passed to the constructor is this: + + .. class:: MinimalClientInterface + + .. method:: set(key, value[, timeout]) + + Stores the bytecode in the cache. `value` is a string and + `timeout` the timeout of the key. If timeout is not provided + a default timeout or no timeout should be assumed, if it's + provided it's an integer with the number of seconds the cache + item should exist. + + .. method:: get(key) + + Returns the value for the cache key. If the item does not + exist in the cache the return value must be `None`. + + The other arguments to the constructor are the prefix for all keys that + is added before the actual cache key and the timeout for the bytecode in + the cache system. We recommend a high (or no) timeout. + + This bytecode cache does not support clearing of used items in the cache. + The clear method is a no-operation function. + + .. versionadded:: 2.7 + Added support for ignoring memcache errors through the + `ignore_memcache_errors` parameter. + """ + + def __init__( + self, + client, + prefix="jinja2/bytecode/", + timeout=None, + ignore_memcache_errors=True, + ): + self.client = client + self.prefix = prefix + self.timeout = timeout + self.ignore_memcache_errors = ignore_memcache_errors + + def load_bytecode(self, bucket): + try: + code = self.client.get(self.prefix + bucket.key) + except Exception: + if not self.ignore_memcache_errors: + raise + code = None + if code is not None: + bucket.bytecode_from_string(code) + + def dump_bytecode(self, bucket): + args = (self.prefix + bucket.key, bucket.bytecode_to_string()) + if self.timeout is not None: + args += (self.timeout,) + try: + self.client.set(*args) + except Exception: + if not self.ignore_memcache_errors: + raise diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py b/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py new file mode 100644 index 00000000..63297b42 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/compiler.py @@ -0,0 +1,1843 @@ +# -*- coding: utf-8 -*- +"""Compiles nodes from the parser into Python code.""" +from collections import namedtuple +from functools import update_wrapper +from itertools import chain +from keyword import iskeyword as is_python_keyword + +from markupsafe import escape +from markupsafe import Markup + +from . import nodes +from ._compat import imap +from ._compat import iteritems +from ._compat import izip +from ._compat import NativeStringIO +from ._compat import range_type +from ._compat import string_types +from ._compat import text_type +from .exceptions import TemplateAssertionError +from .idtracking import Symbols +from .idtracking import VAR_LOAD_ALIAS +from .idtracking import VAR_LOAD_PARAMETER +from .idtracking import VAR_LOAD_RESOLVE +from .idtracking import VAR_LOAD_UNDEFINED +from .nodes import EvalContext +from .optimizer import Optimizer +from .utils import concat +from .visitor import NodeVisitor + +operators = { + "eq": "==", + "ne": "!=", + "gt": ">", + "gteq": ">=", + "lt": "<", + "lteq": "<=", + "in": "in", + "notin": "not in", +} + +# what method to iterate over items do we want to use for dict iteration +# in generated code? on 2.x let's go with iteritems, on 3.x with items +if hasattr(dict, "iteritems"): + dict_item_iter = "iteritems" +else: + dict_item_iter = "items" + +code_features = ["division"] + +# does this python version support generator stops? (PEP 0479) +try: + exec("from __future__ import generator_stop") + code_features.append("generator_stop") +except SyntaxError: + pass + +# does this python version support yield from? +try: + exec("def f(): yield from x()") +except SyntaxError: + supports_yield_from = False +else: + supports_yield_from = True + + +def optimizeconst(f): + def new_func(self, node, frame, **kwargs): + # Only optimize if the frame is not volatile + if self.optimized and not frame.eval_ctx.volatile: + new_node = self.optimizer.visit(node, frame.eval_ctx) + if new_node != node: + return self.visit(new_node, frame) + return f(self, node, frame, **kwargs) + + return update_wrapper(new_func, f) + + +def generate( + node, environment, name, filename, stream=None, defer_init=False, optimized=True +): + """Generate the python source for a node tree.""" + if not isinstance(node, nodes.Template): + raise TypeError("Can't compile non template nodes") + generator = environment.code_generator_class( + environment, name, filename, stream, defer_init, optimized + ) + generator.visit(node) + if stream is None: + return generator.stream.getvalue() + + +def has_safe_repr(value): + """Does the node have a safe representation?""" + if value is None or value is NotImplemented or value is Ellipsis: + return True + if type(value) in (bool, int, float, complex, range_type, Markup) + string_types: + return True + if type(value) in (tuple, list, set, frozenset): + for item in value: + if not has_safe_repr(item): + return False + return True + elif type(value) is dict: + for key, value in iteritems(value): + if not has_safe_repr(key): + return False + if not has_safe_repr(value): + return False + return True + return False + + +def find_undeclared(nodes, names): + """Check if the names passed are accessed undeclared. The return value + is a set of all the undeclared names from the sequence of names found. + """ + visitor = UndeclaredNameVisitor(names) + try: + for node in nodes: + visitor.visit(node) + except VisitorExit: + pass + return visitor.undeclared + + +class MacroRef(object): + def __init__(self, node): + self.node = node + self.accesses_caller = False + self.accesses_kwargs = False + self.accesses_varargs = False + + +class Frame(object): + """Holds compile time information for us.""" + + def __init__(self, eval_ctx, parent=None, level=None): + self.eval_ctx = eval_ctx + self.symbols = Symbols(parent and parent.symbols or None, level=level) + + # a toplevel frame is the root + soft frames such as if conditions. + self.toplevel = False + + # the root frame is basically just the outermost frame, so no if + # conditions. This information is used to optimize inheritance + # situations. + self.rootlevel = False + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = parent and parent.require_output_check + + # inside some tags we are using a buffer rather than yield statements. + # this for example affects {% filter %} or {% macro %}. If a frame + # is buffered this variable points to the name of the list used as + # buffer. + self.buffer = None + + # the name of the block we're in, otherwise None. + self.block = parent and parent.block or None + + # the parent of this frame + self.parent = parent + + if parent is not None: + self.buffer = parent.buffer + + def copy(self): + """Create a copy of the current one.""" + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.symbols = self.symbols.copy() + return rv + + def inner(self, isolated=False): + """Return an inner frame.""" + if isolated: + return Frame(self.eval_ctx, level=self.symbols.level + 1) + return Frame(self.eval_ctx, self) + + def soft(self): + """Return a soft frame. A soft frame may not be modified as + standalone thing as it shares the resources with the frame it + was created of, but it's not a rootlevel frame any longer. + + This is only used to implement if-statements. + """ + rv = self.copy() + rv.rootlevel = False + return rv + + __copy__ = copy + + +class VisitorExit(RuntimeError): + """Exception used by the `UndeclaredNameVisitor` to signal a stop.""" + + +class DependencyFinderVisitor(NodeVisitor): + """A visitor that collects filter and test calls.""" + + def __init__(self): + self.filters = set() + self.tests = set() + + def visit_Filter(self, node): + self.generic_visit(node) + self.filters.add(node.name) + + def visit_Test(self, node): + self.generic_visit(node) + self.tests.add(node.name) + + def visit_Block(self, node): + """Stop visiting at blocks.""" + + +class UndeclaredNameVisitor(NodeVisitor): + """A visitor that checks if a name is accessed without being + declared. This is different from the frame visitor as it will + not stop at closure frames. + """ + + def __init__(self, names): + self.names = set(names) + self.undeclared = set() + + def visit_Name(self, node): + if node.ctx == "load" and node.name in self.names: + self.undeclared.add(node.name) + if self.undeclared == self.names: + raise VisitorExit() + else: + self.names.discard(node.name) + + def visit_Block(self, node): + """Stop visiting a blocks.""" + + +class CompilerExit(Exception): + """Raised if the compiler encountered a situation where it just + doesn't make sense to further process the code. Any block that + raises such an exception is not further processed. + """ + + +class CodeGenerator(NodeVisitor): + def __init__( + self, environment, name, filename, stream=None, defer_init=False, optimized=True + ): + if stream is None: + stream = NativeStringIO() + self.environment = environment + self.name = name + self.filename = filename + self.stream = stream + self.created_block_context = False + self.defer_init = defer_init + self.optimized = optimized + if optimized: + self.optimizer = Optimizer(environment) + + # aliases for imports + self.import_aliases = {} + + # a registry for all blocks. Because blocks are moved out + # into the global python scope they are registered here + self.blocks = {} + + # the number of extends statements so far + self.extends_so_far = 0 + + # some templates have a rootlevel extends. In this case we + # can safely assume that we're a child template and do some + # more optimizations. + self.has_known_extends = False + + # the current line number + self.code_lineno = 1 + + # registry of all filters and tests (global, not block local) + self.tests = {} + self.filters = {} + + # the debug information + self.debug_info = [] + self._write_debug_info = None + + # the number of new lines before the next write() + self._new_lines = 0 + + # the line number of the last written statement + self._last_line = 0 + + # true if nothing was written so far. + self._first_write = True + + # used by the `temporary_identifier` method to get new + # unique, temporary identifier + self._last_identifier = 0 + + # the current indentation + self._indentation = 0 + + # Tracks toplevel assignments + self._assign_stack = [] + + # Tracks parameter definition blocks + self._param_def_block = [] + + # Tracks the current context. + self._context_reference_stack = ["context"] + + # -- Various compilation helpers + + def fail(self, msg, lineno): + """Fail with a :exc:`TemplateAssertionError`.""" + raise TemplateAssertionError(msg, lineno, self.name, self.filename) + + def temporary_identifier(self): + """Get a new unique identifier.""" + self._last_identifier += 1 + return "t_%d" % self._last_identifier + + def buffer(self, frame): + """Enable buffering for the frame from that point onwards.""" + frame.buffer = self.temporary_identifier() + self.writeline("%s = []" % frame.buffer) + + def return_buffer_contents(self, frame, force_unescaped=False): + """Return the buffer contents of the frame.""" + if not force_unescaped: + if frame.eval_ctx.volatile: + self.writeline("if context.eval_ctx.autoescape:") + self.indent() + self.writeline("return Markup(concat(%s))" % frame.buffer) + self.outdent() + self.writeline("else:") + self.indent() + self.writeline("return concat(%s)" % frame.buffer) + self.outdent() + return + elif frame.eval_ctx.autoescape: + self.writeline("return Markup(concat(%s))" % frame.buffer) + return + self.writeline("return concat(%s)" % frame.buffer) + + def indent(self): + """Indent by one.""" + self._indentation += 1 + + def outdent(self, step=1): + """Outdent by step.""" + self._indentation -= step + + def start_write(self, frame, node=None): + """Yield or write into the frame buffer.""" + if frame.buffer is None: + self.writeline("yield ", node) + else: + self.writeline("%s.append(" % frame.buffer, node) + + def end_write(self, frame): + """End the writing process started by `start_write`.""" + if frame.buffer is not None: + self.write(")") + + def simple_write(self, s, frame, node=None): + """Simple shortcut for start_write + write + end_write.""" + self.start_write(frame, node) + self.write(s) + self.end_write(frame) + + def blockvisit(self, nodes, frame): + """Visit a list of nodes as block in a frame. If the current frame + is no buffer a dummy ``if 0: yield None`` is written automatically. + """ + try: + self.writeline("pass") + for node in nodes: + self.visit(node, frame) + except CompilerExit: + pass + + def write(self, x): + """Write a string into the output stream.""" + if self._new_lines: + if not self._first_write: + self.stream.write("\n" * self._new_lines) + self.code_lineno += self._new_lines + if self._write_debug_info is not None: + self.debug_info.append((self._write_debug_info, self.code_lineno)) + self._write_debug_info = None + self._first_write = False + self.stream.write(" " * self._indentation) + self._new_lines = 0 + self.stream.write(x) + + def writeline(self, x, node=None, extra=0): + """Combination of newline and write.""" + self.newline(node, extra) + self.write(x) + + def newline(self, node=None, extra=0): + """Add one or more newlines before the next write.""" + self._new_lines = max(self._new_lines, 1 + extra) + if node is not None and node.lineno != self._last_line: + self._write_debug_info = node.lineno + self._last_line = node.lineno + + def signature(self, node, frame, extra_kwargs=None): + """Writes a function call to the stream for the current node. + A leading comma is added automatically. The extra keyword + arguments may not include python keywords otherwise a syntax + error could occur. The extra keyword arguments should be given + as python dict. + """ + # if any of the given keyword arguments is a python keyword + # we have to make sure that no invalid call is created. + kwarg_workaround = False + for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()): + if is_python_keyword(kwarg): + kwarg_workaround = True + break + + for arg in node.args: + self.write(", ") + self.visit(arg, frame) + + if not kwarg_workaround: + for kwarg in node.kwargs: + self.write(", ") + self.visit(kwarg, frame) + if extra_kwargs is not None: + for key, value in iteritems(extra_kwargs): + self.write(", %s=%s" % (key, value)) + if node.dyn_args: + self.write(", *") + self.visit(node.dyn_args, frame) + + if kwarg_workaround: + if node.dyn_kwargs is not None: + self.write(", **dict({") + else: + self.write(", **{") + for kwarg in node.kwargs: + self.write("%r: " % kwarg.key) + self.visit(kwarg.value, frame) + self.write(", ") + if extra_kwargs is not None: + for key, value in iteritems(extra_kwargs): + self.write("%r: %s, " % (key, value)) + if node.dyn_kwargs is not None: + self.write("}, **") + self.visit(node.dyn_kwargs, frame) + self.write(")") + else: + self.write("}") + + elif node.dyn_kwargs is not None: + self.write(", **") + self.visit(node.dyn_kwargs, frame) + + def pull_dependencies(self, nodes): + """Pull all the dependencies.""" + visitor = DependencyFinderVisitor() + for node in nodes: + visitor.visit(node) + for dependency in "filters", "tests": + mapping = getattr(self, dependency) + for name in getattr(visitor, dependency): + if name not in mapping: + mapping[name] = self.temporary_identifier() + self.writeline( + "%s = environment.%s[%r]" % (mapping[name], dependency, name) + ) + + def enter_frame(self, frame): + undefs = [] + for target, (action, param) in iteritems(frame.symbols.loads): + if action == VAR_LOAD_PARAMETER: + pass + elif action == VAR_LOAD_RESOLVE: + self.writeline("%s = %s(%r)" % (target, self.get_resolve_func(), param)) + elif action == VAR_LOAD_ALIAS: + self.writeline("%s = %s" % (target, param)) + elif action == VAR_LOAD_UNDEFINED: + undefs.append(target) + else: + raise NotImplementedError("unknown load instruction") + if undefs: + self.writeline("%s = missing" % " = ".join(undefs)) + + def leave_frame(self, frame, with_python_scope=False): + if not with_python_scope: + undefs = [] + for target, _ in iteritems(frame.symbols.loads): + undefs.append(target) + if undefs: + self.writeline("%s = missing" % " = ".join(undefs)) + + def func(self, name): + if self.environment.is_async: + return "async def %s" % name + return "def %s" % name + + def macro_body(self, node, frame): + """Dump the function def of a macro or call block.""" + frame = frame.inner() + frame.symbols.analyze_node(node) + macro_ref = MacroRef(node) + + explicit_caller = None + skip_special_params = set() + args = [] + for idx, arg in enumerate(node.args): + if arg.name == "caller": + explicit_caller = idx + if arg.name in ("kwargs", "varargs"): + skip_special_params.add(arg.name) + args.append(frame.symbols.ref(arg.name)) + + undeclared = find_undeclared(node.body, ("caller", "kwargs", "varargs")) + + if "caller" in undeclared: + # In older Jinja versions there was a bug that allowed caller + # to retain the special behavior even if it was mentioned in + # the argument list. However thankfully this was only really + # working if it was the last argument. So we are explicitly + # checking this now and error out if it is anywhere else in + # the argument list. + if explicit_caller is not None: + try: + node.defaults[explicit_caller - len(node.args)] + except IndexError: + self.fail( + "When defining macros or call blocks the " + 'special "caller" argument must be omitted ' + "or be given a default.", + node.lineno, + ) + else: + args.append(frame.symbols.declare_parameter("caller")) + macro_ref.accesses_caller = True + if "kwargs" in undeclared and "kwargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("kwargs")) + macro_ref.accesses_kwargs = True + if "varargs" in undeclared and "varargs" not in skip_special_params: + args.append(frame.symbols.declare_parameter("varargs")) + macro_ref.accesses_varargs = True + + # macros are delayed, they never require output checks + frame.require_output_check = False + frame.symbols.analyze_node(node) + self.writeline("%s(%s):" % (self.func("macro"), ", ".join(args)), node) + self.indent() + + self.buffer(frame) + self.enter_frame(frame) + + self.push_parameter_definitions(frame) + for idx, arg in enumerate(node.args): + ref = frame.symbols.ref(arg.name) + self.writeline("if %s is missing:" % ref) + self.indent() + try: + default = node.defaults[idx - len(node.args)] + except IndexError: + self.writeline( + "%s = undefined(%r, name=%r)" + % (ref, "parameter %r was not provided" % arg.name, arg.name) + ) + else: + self.writeline("%s = " % ref) + self.visit(default, frame) + self.mark_parameter_stored(ref) + self.outdent() + self.pop_parameter_definitions() + + self.blockvisit(node.body, frame) + self.return_buffer_contents(frame, force_unescaped=True) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + return frame, macro_ref + + def macro_def(self, macro_ref, frame): + """Dump the macro definition for the def created by macro_body.""" + arg_tuple = ", ".join(repr(x.name) for x in macro_ref.node.args) + name = getattr(macro_ref.node, "name", None) + if len(macro_ref.node.args) == 1: + arg_tuple += "," + self.write( + "Macro(environment, macro, %r, (%s), %r, %r, %r, " + "context.eval_ctx.autoescape)" + % ( + name, + arg_tuple, + macro_ref.accesses_kwargs, + macro_ref.accesses_varargs, + macro_ref.accesses_caller, + ) + ) + + def position(self, node): + """Return a human readable position for the node.""" + rv = "line %d" % node.lineno + if self.name is not None: + rv += " in " + repr(self.name) + return rv + + def dump_local_context(self, frame): + return "{%s}" % ", ".join( + "%r: %s" % (name, target) + for name, target in iteritems(frame.symbols.dump_stores()) + ) + + def write_commons(self): + """Writes a common preamble that is used by root and block functions. + Primarily this sets up common local helpers and enforces a generator + through a dead branch. + """ + self.writeline("resolve = context.resolve_or_missing") + self.writeline("undefined = environment.undefined") + # always use the standard Undefined class for the implicit else of + # conditional expressions + self.writeline("cond_expr_undefined = Undefined") + self.writeline("if 0: yield None") + + def push_parameter_definitions(self, frame): + """Pushes all parameter targets from the given frame into a local + stack that permits tracking of yet to be assigned parameters. In + particular this enables the optimization from `visit_Name` to skip + undefined expressions for parameters in macros as macros can reference + otherwise unbound parameters. + """ + self._param_def_block.append(frame.symbols.dump_param_targets()) + + def pop_parameter_definitions(self): + """Pops the current parameter definitions set.""" + self._param_def_block.pop() + + def mark_parameter_stored(self, target): + """Marks a parameter in the current parameter definitions as stored. + This will skip the enforced undefined checks. + """ + if self._param_def_block: + self._param_def_block[-1].discard(target) + + def push_context_reference(self, target): + self._context_reference_stack.append(target) + + def pop_context_reference(self): + self._context_reference_stack.pop() + + def get_context_ref(self): + return self._context_reference_stack[-1] + + def get_resolve_func(self): + target = self._context_reference_stack[-1] + if target == "context": + return "resolve" + return "%s.resolve" % target + + def derive_context(self, frame): + return "%s.derived(%s)" % ( + self.get_context_ref(), + self.dump_local_context(frame), + ) + + def parameter_is_undeclared(self, target): + """Checks if a given target is an undeclared parameter.""" + if not self._param_def_block: + return False + return target in self._param_def_block[-1] + + def push_assign_tracking(self): + """Pushes a new layer for assignment tracking.""" + self._assign_stack.append(set()) + + def pop_assign_tracking(self, frame): + """Pops the topmost level for assignment tracking and updates the + context variables if necessary. + """ + vars = self._assign_stack.pop() + if not frame.toplevel or not vars: + return + public_names = [x for x in vars if x[:1] != "_"] + if len(vars) == 1: + name = next(iter(vars)) + ref = frame.symbols.ref(name) + self.writeline("context.vars[%r] = %s" % (name, ref)) + else: + self.writeline("context.vars.update({") + for idx, name in enumerate(vars): + if idx: + self.write(", ") + ref = frame.symbols.ref(name) + self.write("%r: %s" % (name, ref)) + self.write("})") + if public_names: + if len(public_names) == 1: + self.writeline("context.exported_vars.add(%r)" % public_names[0]) + else: + self.writeline( + "context.exported_vars.update((%s))" + % ", ".join(imap(repr, public_names)) + ) + + # -- Statement Visitors + + def visit_Template(self, node, frame=None): + assert frame is None, "no root frame allowed" + eval_ctx = EvalContext(self.environment, self.name) + + from .runtime import exported + + self.writeline("from __future__ import %s" % ", ".join(code_features)) + self.writeline("from jinja2.runtime import " + ", ".join(exported)) + + if self.environment.is_async: + self.writeline( + "from jinja2.asyncsupport import auto_await, " + "auto_aiter, AsyncLoopContext" + ) + + # if we want a deferred initialization we cannot move the + # environment into a local name + envenv = not self.defer_init and ", environment=environment" or "" + + # do we have an extends tag at all? If not, we can save some + # overhead by just not processing any inheritance code. + have_extends = node.find(nodes.Extends) is not None + + # find all blocks + for block in node.find_all(nodes.Block): + if block.name in self.blocks: + self.fail("block %r defined twice" % block.name, block.lineno) + self.blocks[block.name] = block + + # find all imports and import them + for import_ in node.find_all(nodes.ImportedName): + if import_.importname not in self.import_aliases: + imp = import_.importname + self.import_aliases[imp] = alias = self.temporary_identifier() + if "." in imp: + module, obj = imp.rsplit(".", 1) + self.writeline("from %s import %s as %s" % (module, obj, alias)) + else: + self.writeline("import %s as %s" % (imp, alias)) + + # add the load name + self.writeline("name = %r" % self.name) + + # generate the root render function. + self.writeline( + "%s(context, missing=missing%s):" % (self.func("root"), envenv), extra=1 + ) + self.indent() + self.write_commons() + + # process the root + frame = Frame(eval_ctx) + if "self" in find_undeclared(node.body, ("self",)): + ref = frame.symbols.declare_parameter("self") + self.writeline("%s = TemplateReference(context)" % ref) + frame.symbols.analyze_node(node) + frame.toplevel = frame.rootlevel = True + frame.require_output_check = have_extends and not self.has_known_extends + if have_extends: + self.writeline("parent_template = None") + self.enter_frame(frame) + self.pull_dependencies(node.body) + self.blockvisit(node.body, frame) + self.leave_frame(frame, with_python_scope=True) + self.outdent() + + # make sure that the parent root is called. + if have_extends: + if not self.has_known_extends: + self.indent() + self.writeline("if parent_template is not None:") + self.indent() + if supports_yield_from and not self.environment.is_async: + self.writeline("yield from parent_template.root_render_func(context)") + else: + self.writeline( + "%sfor event in parent_template." + "root_render_func(context):" + % (self.environment.is_async and "async " or "") + ) + self.indent() + self.writeline("yield event") + self.outdent() + self.outdent(1 + (not self.has_known_extends)) + + # at this point we now have the blocks collected and can visit them too. + for name, block in iteritems(self.blocks): + self.writeline( + "%s(context, missing=missing%s):" + % (self.func("block_" + name), envenv), + block, + 1, + ) + self.indent() + self.write_commons() + # It's important that we do not make this frame a child of the + # toplevel template. This would cause a variety of + # interesting issues with identifier tracking. + block_frame = Frame(eval_ctx) + undeclared = find_undeclared(block.body, ("self", "super")) + if "self" in undeclared: + ref = block_frame.symbols.declare_parameter("self") + self.writeline("%s = TemplateReference(context)" % ref) + if "super" in undeclared: + ref = block_frame.symbols.declare_parameter("super") + self.writeline("%s = context.super(%r, block_%s)" % (ref, name, name)) + block_frame.symbols.analyze_node(block) + block_frame.block = name + self.enter_frame(block_frame) + self.pull_dependencies(block.body) + self.blockvisit(block.body, block_frame) + self.leave_frame(block_frame, with_python_scope=True) + self.outdent() + + self.writeline( + "blocks = {%s}" % ", ".join("%r: block_%s" % (x, x) for x in self.blocks), + extra=1, + ) + + # add a function that returns the debug info + self.writeline( + "debug_info = %r" % "&".join("%s=%s" % x for x in self.debug_info) + ) + + def visit_Block(self, node, frame): + """Call a block and register it for the template.""" + level = 0 + if frame.toplevel: + # if we know that we are a child template, there is no need to + # check if we are one + if self.has_known_extends: + return + if self.extends_so_far > 0: + self.writeline("if parent_template is None:") + self.indent() + level += 1 + + if node.scoped: + context = self.derive_context(frame) + else: + context = self.get_context_ref() + + if ( + supports_yield_from + and not self.environment.is_async + and frame.buffer is None + ): + self.writeline( + "yield from context.blocks[%r][0](%s)" % (node.name, context), node + ) + else: + loop = self.environment.is_async and "async for" or "for" + self.writeline( + "%s event in context.blocks[%r][0](%s):" % (loop, node.name, context), + node, + ) + self.indent() + self.simple_write("event", frame) + self.outdent() + + self.outdent(level) + + def visit_Extends(self, node, frame): + """Calls the extender.""" + if not frame.toplevel: + self.fail("cannot use extend from a non top-level scope", node.lineno) + + # if the number of extends statements in general is zero so + # far, we don't have to add a check if something extended + # the template before this one. + if self.extends_so_far > 0: + + # if we have a known extends we just add a template runtime + # error into the generated code. We could catch that at compile + # time too, but i welcome it not to confuse users by throwing the + # same error at different times just "because we can". + if not self.has_known_extends: + self.writeline("if parent_template is not None:") + self.indent() + self.writeline("raise TemplateRuntimeError(%r)" % "extended multiple times") + + # if we have a known extends already we don't need that code here + # as we know that the template execution will end here. + if self.has_known_extends: + raise CompilerExit() + else: + self.outdent() + + self.writeline("parent_template = environment.get_template(", node) + self.visit(node.template, frame) + self.write(", %r)" % self.name) + self.writeline( + "for name, parent_block in parent_template.blocks.%s():" % dict_item_iter + ) + self.indent() + self.writeline("context.blocks.setdefault(name, []).append(parent_block)") + self.outdent() + + # if this extends statement was in the root level we can take + # advantage of that information and simplify the generated code + # in the top level from this point onwards + if frame.rootlevel: + self.has_known_extends = True + + # and now we have one more + self.extends_so_far += 1 + + def visit_Include(self, node, frame): + """Handles includes.""" + if node.ignore_missing: + self.writeline("try:") + self.indent() + + func_name = "get_or_select_template" + if isinstance(node.template, nodes.Const): + if isinstance(node.template.value, string_types): + func_name = "get_template" + elif isinstance(node.template.value, (tuple, list)): + func_name = "select_template" + elif isinstance(node.template, (nodes.Tuple, nodes.List)): + func_name = "select_template" + + self.writeline("template = environment.%s(" % func_name, node) + self.visit(node.template, frame) + self.write(", %r)" % self.name) + if node.ignore_missing: + self.outdent() + self.writeline("except TemplateNotFound:") + self.indent() + self.writeline("pass") + self.outdent() + self.writeline("else:") + self.indent() + + skip_event_yield = False + if node.with_context: + loop = self.environment.is_async and "async for" or "for" + self.writeline( + "%s event in template.root_render_func(" + "template.new_context(context.get_all(), True, " + "%s)):" % (loop, self.dump_local_context(frame)) + ) + elif self.environment.is_async: + self.writeline( + "for event in (await " + "template._get_default_module_async())" + "._body_stream:" + ) + else: + if supports_yield_from: + self.writeline("yield from template._get_default_module()._body_stream") + skip_event_yield = True + else: + self.writeline( + "for event in template._get_default_module()._body_stream:" + ) + + if not skip_event_yield: + self.indent() + self.simple_write("event", frame) + self.outdent() + + if node.ignore_missing: + self.outdent() + + def visit_Import(self, node, frame): + """Visit regular imports.""" + self.writeline("%s = " % frame.symbols.ref(node.target), node) + if frame.toplevel: + self.write("context.vars[%r] = " % node.target) + if self.environment.is_async: + self.write("await ") + self.write("environment.get_template(") + self.visit(node.template, frame) + self.write(", %r)." % self.name) + if node.with_context: + self.write( + "make_module%s(context.get_all(), True, %s)" + % ( + self.environment.is_async and "_async" or "", + self.dump_local_context(frame), + ) + ) + elif self.environment.is_async: + self.write("_get_default_module_async()") + else: + self.write("_get_default_module()") + if frame.toplevel and not node.target.startswith("_"): + self.writeline("context.exported_vars.discard(%r)" % node.target) + + def visit_FromImport(self, node, frame): + """Visit named imports.""" + self.newline(node) + self.write( + "included_template = %senvironment.get_template(" + % (self.environment.is_async and "await " or "") + ) + self.visit(node.template, frame) + self.write(", %r)." % self.name) + if node.with_context: + self.write( + "make_module%s(context.get_all(), True, %s)" + % ( + self.environment.is_async and "_async" or "", + self.dump_local_context(frame), + ) + ) + elif self.environment.is_async: + self.write("_get_default_module_async()") + else: + self.write("_get_default_module()") + + var_names = [] + discarded_names = [] + for name in node.names: + if isinstance(name, tuple): + name, alias = name + else: + alias = name + self.writeline( + "%s = getattr(included_template, " + "%r, missing)" % (frame.symbols.ref(alias), name) + ) + self.writeline("if %s is missing:" % frame.symbols.ref(alias)) + self.indent() + self.writeline( + "%s = undefined(%r %% " + "included_template.__name__, " + "name=%r)" + % ( + frame.symbols.ref(alias), + "the template %%r (imported on %s) does " + "not export the requested name %s" + % (self.position(node), repr(name)), + name, + ) + ) + self.outdent() + if frame.toplevel: + var_names.append(alias) + if not alias.startswith("_"): + discarded_names.append(alias) + + if var_names: + if len(var_names) == 1: + name = var_names[0] + self.writeline( + "context.vars[%r] = %s" % (name, frame.symbols.ref(name)) + ) + else: + self.writeline( + "context.vars.update({%s})" + % ", ".join( + "%r: %s" % (name, frame.symbols.ref(name)) for name in var_names + ) + ) + if discarded_names: + if len(discarded_names) == 1: + self.writeline("context.exported_vars.discard(%r)" % discarded_names[0]) + else: + self.writeline( + "context.exported_vars.difference_" + "update((%s))" % ", ".join(imap(repr, discarded_names)) + ) + + def visit_For(self, node, frame): + loop_frame = frame.inner() + test_frame = frame.inner() + else_frame = frame.inner() + + # try to figure out if we have an extended loop. An extended loop + # is necessary if the loop is in recursive mode if the special loop + # variable is accessed in the body. + extended_loop = node.recursive or "loop" in find_undeclared( + node.iter_child_nodes(only=("body",)), ("loop",) + ) + + loop_ref = None + if extended_loop: + loop_ref = loop_frame.symbols.declare_parameter("loop") + + loop_frame.symbols.analyze_node(node, for_branch="body") + if node.else_: + else_frame.symbols.analyze_node(node, for_branch="else") + + if node.test: + loop_filter_func = self.temporary_identifier() + test_frame.symbols.analyze_node(node, for_branch="test") + self.writeline("%s(fiter):" % self.func(loop_filter_func), node.test) + self.indent() + self.enter_frame(test_frame) + self.writeline(self.environment.is_async and "async for " or "for ") + self.visit(node.target, loop_frame) + self.write(" in ") + self.write(self.environment.is_async and "auto_aiter(fiter)" or "fiter") + self.write(":") + self.indent() + self.writeline("if ", node.test) + self.visit(node.test, test_frame) + self.write(":") + self.indent() + self.writeline("yield ") + self.visit(node.target, loop_frame) + self.outdent(3) + self.leave_frame(test_frame, with_python_scope=True) + + # if we don't have an recursive loop we have to find the shadowed + # variables at that point. Because loops can be nested but the loop + # variable is a special one we have to enforce aliasing for it. + if node.recursive: + self.writeline( + "%s(reciter, loop_render_func, depth=0):" % self.func("loop"), node + ) + self.indent() + self.buffer(loop_frame) + + # Use the same buffer for the else frame + else_frame.buffer = loop_frame.buffer + + # make sure the loop variable is a special one and raise a template + # assertion error if a loop tries to write to loop + if extended_loop: + self.writeline("%s = missing" % loop_ref) + + for name in node.find_all(nodes.Name): + if name.ctx == "store" and name.name == "loop": + self.fail( + "Can't assign to special loop variable in for-loop target", + name.lineno, + ) + + if node.else_: + iteration_indicator = self.temporary_identifier() + self.writeline("%s = 1" % iteration_indicator) + + self.writeline(self.environment.is_async and "async for " or "for ", node) + self.visit(node.target, loop_frame) + if extended_loop: + if self.environment.is_async: + self.write(", %s in AsyncLoopContext(" % loop_ref) + else: + self.write(", %s in LoopContext(" % loop_ref) + else: + self.write(" in ") + + if node.test: + self.write("%s(" % loop_filter_func) + if node.recursive: + self.write("reciter") + else: + if self.environment.is_async and not extended_loop: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async and not extended_loop: + self.write(")") + if node.test: + self.write(")") + + if node.recursive: + self.write(", undefined, loop_render_func, depth):") + else: + self.write(extended_loop and ", undefined):" or ":") + + self.indent() + self.enter_frame(loop_frame) + + self.blockvisit(node.body, loop_frame) + if node.else_: + self.writeline("%s = 0" % iteration_indicator) + self.outdent() + self.leave_frame( + loop_frame, with_python_scope=node.recursive and not node.else_ + ) + + if node.else_: + self.writeline("if %s:" % iteration_indicator) + self.indent() + self.enter_frame(else_frame) + self.blockvisit(node.else_, else_frame) + self.leave_frame(else_frame) + self.outdent() + + # if the node was recursive we have to return the buffer contents + # and start the iteration code + if node.recursive: + self.return_buffer_contents(loop_frame) + self.outdent() + self.start_write(frame, node) + if self.environment.is_async: + self.write("await ") + self.write("loop(") + if self.environment.is_async: + self.write("auto_aiter(") + self.visit(node.iter, frame) + if self.environment.is_async: + self.write(")") + self.write(", loop)") + self.end_write(frame) + + def visit_If(self, node, frame): + if_frame = frame.soft() + self.writeline("if ", node) + self.visit(node.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(node.body, if_frame) + self.outdent() + for elif_ in node.elif_: + self.writeline("elif ", elif_) + self.visit(elif_.test, if_frame) + self.write(":") + self.indent() + self.blockvisit(elif_.body, if_frame) + self.outdent() + if node.else_: + self.writeline("else:") + self.indent() + self.blockvisit(node.else_, if_frame) + self.outdent() + + def visit_Macro(self, node, frame): + macro_frame, macro_ref = self.macro_body(node, frame) + self.newline() + if frame.toplevel: + if not node.name.startswith("_"): + self.write("context.exported_vars.add(%r)" % node.name) + self.writeline("context.vars[%r] = " % node.name) + self.write("%s = " % frame.symbols.ref(node.name)) + self.macro_def(macro_ref, macro_frame) + + def visit_CallBlock(self, node, frame): + call_frame, macro_ref = self.macro_body(node, frame) + self.writeline("caller = ") + self.macro_def(macro_ref, call_frame) + self.start_write(frame, node) + self.visit_Call(node.call, frame, forward_caller=True) + self.end_write(frame) + + def visit_FilterBlock(self, node, frame): + filter_frame = frame.inner() + filter_frame.symbols.analyze_node(node) + self.enter_frame(filter_frame) + self.buffer(filter_frame) + self.blockvisit(node.body, filter_frame) + self.start_write(frame, node) + self.visit_Filter(node.filter, filter_frame) + self.end_write(frame) + self.leave_frame(filter_frame) + + def visit_With(self, node, frame): + with_frame = frame.inner() + with_frame.symbols.analyze_node(node) + self.enter_frame(with_frame) + for target, expr in izip(node.targets, node.values): + self.newline() + self.visit(target, with_frame) + self.write(" = ") + self.visit(expr, frame) + self.blockvisit(node.body, with_frame) + self.leave_frame(with_frame) + + def visit_ExprStmt(self, node, frame): + self.newline(node) + self.visit(node.node, frame) + + _FinalizeInfo = namedtuple("_FinalizeInfo", ("const", "src")) + #: The default finalize function if the environment isn't configured + #: with one. Or if the environment has one, this is called on that + #: function's output for constants. + _default_finalize = text_type + _finalize = None + + def _make_finalize(self): + """Build the finalize function to be used on constants and at + runtime. Cached so it's only created once for all output nodes. + + Returns a ``namedtuple`` with the following attributes: + + ``const`` + A function to finalize constant data at compile time. + + ``src`` + Source code to output around nodes to be evaluated at + runtime. + """ + if self._finalize is not None: + return self._finalize + + finalize = default = self._default_finalize + src = None + + if self.environment.finalize: + src = "environment.finalize(" + env_finalize = self.environment.finalize + + def finalize(value): + return default(env_finalize(value)) + + if getattr(env_finalize, "contextfunction", False) is True: + src += "context, " + finalize = None # noqa: F811 + elif getattr(env_finalize, "evalcontextfunction", False) is True: + src += "context.eval_ctx, " + finalize = None + elif getattr(env_finalize, "environmentfunction", False) is True: + src += "environment, " + + def finalize(value): + return default(env_finalize(self.environment, value)) + + self._finalize = self._FinalizeInfo(finalize, src) + return self._finalize + + def _output_const_repr(self, group): + """Given a group of constant values converted from ``Output`` + child nodes, produce a string to write to the template module + source. + """ + return repr(concat(group)) + + def _output_child_to_const(self, node, frame, finalize): + """Try to optimize a child of an ``Output`` node by trying to + convert it to constant, finalized data at compile time. + + If :exc:`Impossible` is raised, the node is not constant and + will be evaluated at runtime. Any other exception will also be + evaluated at runtime for easier debugging. + """ + const = node.as_const(frame.eval_ctx) + + if frame.eval_ctx.autoescape: + const = escape(const) + + # Template data doesn't go through finalize. + if isinstance(node, nodes.TemplateData): + return text_type(const) + + return finalize.const(const) + + def _output_child_pre(self, node, frame, finalize): + """Output extra source code before visiting a child of an + ``Output`` node. + """ + if frame.eval_ctx.volatile: + self.write("(escape if context.eval_ctx.autoescape else to_string)(") + elif frame.eval_ctx.autoescape: + self.write("escape(") + else: + self.write("to_string(") + + if finalize.src is not None: + self.write(finalize.src) + + def _output_child_post(self, node, frame, finalize): + """Output extra source code after visiting a child of an + ``Output`` node. + """ + self.write(")") + + if finalize.src is not None: + self.write(")") + + def visit_Output(self, node, frame): + # If an extends is active, don't render outside a block. + if frame.require_output_check: + # A top-level extends is known to exist at compile time. + if self.has_known_extends: + return + + self.writeline("if parent_template is None:") + self.indent() + + finalize = self._make_finalize() + body = [] + + # Evaluate constants at compile time if possible. Each item in + # body will be either a list of static data or a node to be + # evaluated at runtime. + for child in node.nodes: + try: + if not ( + # If the finalize function requires runtime context, + # constants can't be evaluated at compile time. + finalize.const + # Unless it's basic template data that won't be + # finalized anyway. + or isinstance(child, nodes.TemplateData) + ): + raise nodes.Impossible() + + const = self._output_child_to_const(child, frame, finalize) + except (nodes.Impossible, Exception): + # The node was not constant and needs to be evaluated at + # runtime. Or another error was raised, which is easier + # to debug at runtime. + body.append(child) + continue + + if body and isinstance(body[-1], list): + body[-1].append(const) + else: + body.append([const]) + + if frame.buffer is not None: + if len(body) == 1: + self.writeline("%s.append(" % frame.buffer) + else: + self.writeline("%s.extend((" % frame.buffer) + + self.indent() + + for item in body: + if isinstance(item, list): + # A group of constant data to join and output. + val = self._output_const_repr(item) + + if frame.buffer is None: + self.writeline("yield " + val) + else: + self.writeline(val + ",") + else: + if frame.buffer is None: + self.writeline("yield ", item) + else: + self.newline(item) + + # A node to be evaluated at runtime. + self._output_child_pre(item, frame, finalize) + self.visit(item, frame) + self._output_child_post(item, frame, finalize) + + if frame.buffer is not None: + self.write(",") + + if frame.buffer is not None: + self.outdent() + self.writeline(")" if len(body) == 1 else "))") + + if frame.require_output_check: + self.outdent() + + def visit_Assign(self, node, frame): + self.push_assign_tracking() + self.newline(node) + self.visit(node.target, frame) + self.write(" = ") + self.visit(node.node, frame) + self.pop_assign_tracking(frame) + + def visit_AssignBlock(self, node, frame): + self.push_assign_tracking() + block_frame = frame.inner() + # This is a special case. Since a set block always captures we + # will disable output checks. This way one can use set blocks + # toplevel even in extended templates. + block_frame.require_output_check = False + block_frame.symbols.analyze_node(node) + self.enter_frame(block_frame) + self.buffer(block_frame) + self.blockvisit(node.body, block_frame) + self.newline(node) + self.visit(node.target, frame) + self.write(" = (Markup if context.eval_ctx.autoescape else identity)(") + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write("concat(%s)" % block_frame.buffer) + self.write(")") + self.pop_assign_tracking(frame) + self.leave_frame(block_frame) + + # -- Expression Visitors + + def visit_Name(self, node, frame): + if node.ctx == "store" and frame.toplevel: + if self._assign_stack: + self._assign_stack[-1].add(node.name) + ref = frame.symbols.ref(node.name) + + # If we are looking up a variable we might have to deal with the + # case where it's undefined. We can skip that case if the load + # instruction indicates a parameter which are always defined. + if node.ctx == "load": + load = frame.symbols.find_load(ref) + if not ( + load is not None + and load[0] == VAR_LOAD_PARAMETER + and not self.parameter_is_undeclared(ref) + ): + self.write( + "(undefined(name=%r) if %s is missing else %s)" + % (node.name, ref, ref) + ) + return + + self.write(ref) + + def visit_NSRef(self, node, frame): + # NSRefs can only be used to store values; since they use the normal + # `foo.bar` notation they will be parsed as a normal attribute access + # when used anywhere but in a `set` context + ref = frame.symbols.ref(node.name) + self.writeline("if not isinstance(%s, Namespace):" % ref) + self.indent() + self.writeline( + "raise TemplateRuntimeError(%r)" + % "cannot assign attribute on non-namespace object" + ) + self.outdent() + self.writeline("%s[%r]" % (ref, node.attr)) + + def visit_Const(self, node, frame): + val = node.as_const(frame.eval_ctx) + if isinstance(val, float): + self.write(str(val)) + else: + self.write(repr(val)) + + def visit_TemplateData(self, node, frame): + try: + self.write(repr(node.as_const(frame.eval_ctx))) + except nodes.Impossible: + self.write( + "(Markup if context.eval_ctx.autoescape else identity)(%r)" % node.data + ) + + def visit_Tuple(self, node, frame): + self.write("(") + idx = -1 + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write(idx == 0 and ",)" or ")") + + def visit_List(self, node, frame): + self.write("[") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item, frame) + self.write("]") + + def visit_Dict(self, node, frame): + self.write("{") + for idx, item in enumerate(node.items): + if idx: + self.write(", ") + self.visit(item.key, frame) + self.write(": ") + self.visit(item.value, frame) + self.write("}") + + def binop(operator, interceptable=True): # noqa: B902 + @optimizeconst + def visitor(self, node, frame): + if ( + self.environment.sandboxed + and operator in self.environment.intercepted_binops + ): + self.write("environment.call_binop(context, %r, " % operator) + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(" %s " % operator) + self.visit(node.right, frame) + self.write(")") + + return visitor + + def uaop(operator, interceptable=True): # noqa: B902 + @optimizeconst + def visitor(self, node, frame): + if ( + self.environment.sandboxed + and operator in self.environment.intercepted_unops + ): + self.write("environment.call_unop(context, %r, " % operator) + self.visit(node.node, frame) + else: + self.write("(" + operator) + self.visit(node.node, frame) + self.write(")") + + return visitor + + visit_Add = binop("+") + visit_Sub = binop("-") + visit_Mul = binop("*") + visit_Div = binop("/") + visit_FloorDiv = binop("//") + visit_Pow = binop("**") + visit_Mod = binop("%") + visit_And = binop("and", interceptable=False) + visit_Or = binop("or", interceptable=False) + visit_Pos = uaop("+") + visit_Neg = uaop("-") + visit_Not = uaop("not ", interceptable=False) + del binop, uaop + + @optimizeconst + def visit_Concat(self, node, frame): + if frame.eval_ctx.volatile: + func_name = "(context.eval_ctx.volatile and markup_join or unicode_join)" + elif frame.eval_ctx.autoescape: + func_name = "markup_join" + else: + func_name = "unicode_join" + self.write("%s((" % func_name) + for arg in node.nodes: + self.visit(arg, frame) + self.write(", ") + self.write("))") + + @optimizeconst + def visit_Compare(self, node, frame): + self.write("(") + self.visit(node.expr, frame) + for op in node.ops: + self.visit(op, frame) + self.write(")") + + def visit_Operand(self, node, frame): + self.write(" %s " % operators[node.op]) + self.visit(node.expr, frame) + + @optimizeconst + def visit_Getattr(self, node, frame): + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getattr(") + self.visit(node.node, frame) + self.write(", %r)" % node.attr) + + if self.environment.is_async: + self.write("))") + + @optimizeconst + def visit_Getitem(self, node, frame): + # slices bypass the environment getitem method. + if isinstance(node.arg, nodes.Slice): + self.visit(node.node, frame) + self.write("[") + self.visit(node.arg, frame) + self.write("]") + else: + if self.environment.is_async: + self.write("(await auto_await(") + + self.write("environment.getitem(") + self.visit(node.node, frame) + self.write(", ") + self.visit(node.arg, frame) + self.write(")") + + if self.environment.is_async: + self.write("))") + + def visit_Slice(self, node, frame): + if node.start is not None: + self.visit(node.start, frame) + self.write(":") + if node.stop is not None: + self.visit(node.stop, frame) + if node.step is not None: + self.write(":") + self.visit(node.step, frame) + + @optimizeconst + def visit_Filter(self, node, frame): + if self.environment.is_async: + self.write("await auto_await(") + self.write(self.filters[node.name] + "(") + func = self.environment.filters.get(node.name) + if func is None: + self.fail("no filter named %r" % node.name, node.lineno) + if getattr(func, "contextfilter", False) is True: + self.write("context, ") + elif getattr(func, "evalcontextfilter", False) is True: + self.write("context.eval_ctx, ") + elif getattr(func, "environmentfilter", False) is True: + self.write("environment, ") + + # if the filter node is None we are inside a filter block + # and want to write to the current buffer + if node.node is not None: + self.visit(node.node, frame) + elif frame.eval_ctx.volatile: + self.write( + "(context.eval_ctx.autoescape and" + " Markup(concat(%s)) or concat(%s))" % (frame.buffer, frame.buffer) + ) + elif frame.eval_ctx.autoescape: + self.write("Markup(concat(%s))" % frame.buffer) + else: + self.write("concat(%s)" % frame.buffer) + self.signature(node, frame) + self.write(")") + if self.environment.is_async: + self.write(")") + + @optimizeconst + def visit_Test(self, node, frame): + self.write(self.tests[node.name] + "(") + if node.name not in self.environment.tests: + self.fail("no test named %r" % node.name, node.lineno) + self.visit(node.node, frame) + self.signature(node, frame) + self.write(")") + + @optimizeconst + def visit_CondExpr(self, node, frame): + def write_expr2(): + if node.expr2 is not None: + return self.visit(node.expr2, frame) + self.write( + "cond_expr_undefined(%r)" + % ( + "the inline if-" + "expression on %s evaluated to false and " + "no else section was defined." % self.position(node) + ) + ) + + self.write("(") + self.visit(node.expr1, frame) + self.write(" if ") + self.visit(node.test, frame) + self.write(" else ") + write_expr2() + self.write(")") + + @optimizeconst + def visit_Call(self, node, frame, forward_caller=False): + if self.environment.is_async: + self.write("await auto_await(") + if self.environment.sandboxed: + self.write("environment.call(context, ") + else: + self.write("context.call(") + self.visit(node.node, frame) + extra_kwargs = forward_caller and {"caller": "caller"} or None + self.signature(node, frame, extra_kwargs) + self.write(")") + if self.environment.is_async: + self.write(")") + + def visit_Keyword(self, node, frame): + self.write(node.key + "=") + self.visit(node.value, frame) + + # -- Unused nodes for extensions + + def visit_MarkSafe(self, node, frame): + self.write("Markup(") + self.visit(node.expr, frame) + self.write(")") + + def visit_MarkSafeIfAutoescape(self, node, frame): + self.write("(context.eval_ctx.autoescape and Markup or identity)(") + self.visit(node.expr, frame) + self.write(")") + + def visit_EnvironmentAttribute(self, node, frame): + self.write("environment." + node.name) + + def visit_ExtensionAttribute(self, node, frame): + self.write("environment.extensions[%r].%s" % (node.identifier, node.name)) + + def visit_ImportedName(self, node, frame): + self.write(self.import_aliases[node.importname]) + + def visit_InternalName(self, node, frame): + self.write(node.name) + + def visit_ContextReference(self, node, frame): + self.write("context") + + def visit_DerivedContextReference(self, node, frame): + self.write(self.derive_context(frame)) + + def visit_Continue(self, node, frame): + self.writeline("continue", node) + + def visit_Break(self, node, frame): + self.writeline("break", node) + + def visit_Scope(self, node, frame): + scope_frame = frame.inner() + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + + def visit_OverlayScope(self, node, frame): + ctx = self.temporary_identifier() + self.writeline("%s = %s" % (ctx, self.derive_context(frame))) + self.writeline("%s.vars = " % ctx) + self.visit(node.context, frame) + self.push_context_reference(ctx) + + scope_frame = frame.inner(isolated=True) + scope_frame.symbols.analyze_node(node) + self.enter_frame(scope_frame) + self.blockvisit(node.body, scope_frame) + self.leave_frame(scope_frame) + self.pop_context_reference() + + def visit_EvalContextModifier(self, node, frame): + for keyword in node.options: + self.writeline("context.eval_ctx.%s = " % keyword.key) + self.visit(keyword.value, frame) + try: + val = keyword.value.as_const(frame.eval_ctx) + except nodes.Impossible: + frame.eval_ctx.volatile = True + else: + setattr(frame.eval_ctx, keyword.key, val) + + def visit_ScopedEvalContextModifier(self, node, frame): + old_ctx_name = self.temporary_identifier() + saved_ctx = frame.eval_ctx.save() + self.writeline("%s = context.eval_ctx.save()" % old_ctx_name) + self.visit_EvalContextModifier(node, frame) + for child in node.body: + self.visit(child, frame) + frame.eval_ctx.revert(saved_ctx) + self.writeline("context.eval_ctx.revert(%s)" % old_ctx_name) diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/constants.py b/magma/squid_cnf/charms/squid/venv/jinja2/constants.py new file mode 100644 index 00000000..bf7f2ca7 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/constants.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +#: list of lorem ipsum words used by the lipsum() helper function +LOREM_IPSUM_WORDS = u"""\ +a ac accumsan ad adipiscing aenean aliquam aliquet amet ante aptent arcu at +auctor augue bibendum blandit class commodo condimentum congue consectetuer +consequat conubia convallis cras cubilia cum curabitur curae cursus dapibus +diam dictum dictumst dignissim dis dolor donec dui duis egestas eget eleifend +elementum elit enim erat eros est et etiam eu euismod facilisi facilisis fames +faucibus felis fermentum feugiat fringilla fusce gravida habitant habitasse hac +hendrerit hymenaeos iaculis id imperdiet in inceptos integer interdum ipsum +justo lacinia lacus laoreet lectus leo libero ligula litora lobortis lorem +luctus maecenas magna magnis malesuada massa mattis mauris metus mi molestie +mollis montes morbi mus nam nascetur natoque nec neque netus nibh nisi nisl non +nonummy nostra nulla nullam nunc odio orci ornare parturient pede pellentesque +penatibus per pharetra phasellus placerat platea porta porttitor posuere +potenti praesent pretium primis proin pulvinar purus quam quis quisque rhoncus +ridiculus risus rutrum sagittis sapien scelerisque sed sem semper senectus sit +sociis sociosqu sodales sollicitudin suscipit suspendisse taciti tellus tempor +tempus tincidunt torquent tortor tristique turpis ullamcorper ultrices +ultricies urna ut varius vehicula vel velit venenatis vestibulum vitae vivamus +viverra volutpat vulputate""" diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/debug.py b/magma/squid_cnf/charms/squid/venv/jinja2/debug.py new file mode 100644 index 00000000..5d8aec31 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/debug.py @@ -0,0 +1,268 @@ +import sys +from types import CodeType + +from . import TemplateSyntaxError +from ._compat import PYPY +from .utils import internal_code +from .utils import missing + + +def rewrite_traceback_stack(source=None): + """Rewrite the current exception to replace any tracebacks from + within compiled template code with tracebacks that look like they + came from the template source. + + This must be called within an ``except`` block. + + :param exc_info: A :meth:`sys.exc_info` tuple. If not provided, + the current ``exc_info`` is used. + :param source: For ``TemplateSyntaxError``, the original source if + known. + :return: A :meth:`sys.exc_info` tuple that can be re-raised. + """ + exc_type, exc_value, tb = sys.exc_info() + + if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated: + exc_value.translated = True + exc_value.source = source + + try: + # Remove the old traceback on Python 3, otherwise the frames + # from the compiler still show up. + exc_value.with_traceback(None) + except AttributeError: + pass + + # Outside of runtime, so the frame isn't executing template + # code, but it still needs to point at the template. + tb = fake_traceback( + exc_value, None, exc_value.filename or "", exc_value.lineno + ) + else: + # Skip the frame for the render function. + tb = tb.tb_next + + stack = [] + + # Build the stack of traceback object, replacing any in template + # code with the source file and line information. + while tb is not None: + # Skip frames decorated with @internalcode. These are internal + # calls that aren't useful in template debugging output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + template = tb.tb_frame.f_globals.get("__jinja_template__") + + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + fake_tb = fake_traceback(exc_value, tb, template.filename, lineno) + stack.append(fake_tb) + else: + stack.append(tb) + + tb = tb.tb_next + + tb_next = None + + # Assign tb_next in reverse to avoid circular references. + for tb in reversed(stack): + tb_next = tb_set_next(tb, tb_next) + + return exc_type, exc_value, tb_next + + +def fake_traceback(exc_value, tb, filename, lineno): + """Produce a new traceback object that looks like it came from the + template source instead of the compiled code. The filename, line + number, and location name will point to the template, and the local + variables will be the current template context. + + :param exc_value: The original exception to be re-raised to create + the new traceback. + :param tb: The original traceback to get the local variables and + code info from. + :param filename: The template filename. + :param lineno: The line number in the template source. + """ + if tb is not None: + # Replace the real locals with the context that would be + # available at that point in the template. + locals = get_template_locals(tb.tb_frame.f_locals) + locals.pop("__jinja_exception__", None) + else: + locals = {} + + globals = { + "__name__": filename, + "__file__": filename, + "__jinja_exception__": exc_value, + } + # Raise an exception at the correct line number. + code = compile("\n" * (lineno - 1) + "raise __jinja_exception__", filename, "exec") + + # Build a new code object that points to the template file and + # replaces the location with a block name. + try: + location = "template" + + if tb is not None: + function = tb.tb_frame.f_code.co_name + + if function == "root": + location = "top-level template code" + elif function.startswith("block_"): + location = 'block "%s"' % function[6:] + + # Collect arguments for the new code object. CodeType only + # accepts positional arguments, and arguments were inserted in + # new Python versions. + code_args = [] + + for attr in ( + "argcount", + "posonlyargcount", # Python 3.8 + "kwonlyargcount", # Python 3 + "nlocals", + "stacksize", + "flags", + "code", # codestring + "consts", # constants + "names", + "varnames", + ("filename", filename), + ("name", location), + "firstlineno", + "lnotab", + "freevars", + "cellvars", + ): + if isinstance(attr, tuple): + # Replace with given value. + code_args.append(attr[1]) + continue + + try: + # Copy original value if it exists. + code_args.append(getattr(code, "co_" + attr)) + except AttributeError: + # Some arguments were added later. + continue + + code = CodeType(*code_args) + except Exception: + # Some environments such as Google App Engine don't support + # modifying code objects. + pass + + # Execute the new code, which is guaranteed to raise, and return + # the new traceback without this frame. + try: + exec(code, globals, locals) + except BaseException: + return sys.exc_info()[2].tb_next + + +def get_template_locals(real_locals): + """Based on the runtime locals, get the context that would be + available at that point in the template. + """ + # Start with the current template context. + ctx = real_locals.get("context") + + if ctx: + data = ctx.get_all().copy() + else: + data = {} + + # Might be in a derived context that only sets local variables + # rather than pushing a context. Local variables follow the scheme + # l_depth_name. Find the highest-depth local that has a value for + # each name. + local_overrides = {} + + for name, value in real_locals.items(): + if not name.startswith("l_") or value is missing: + # Not a template variable, or no longer relevant. + continue + + try: + _, depth, name = name.split("_", 2) + depth = int(depth) + except ValueError: + continue + + cur_depth = local_overrides.get(name, (-1,))[0] + + if cur_depth < depth: + local_overrides[name] = (depth, value) + + # Modify the context with any derived context. + for name, (_, value) in local_overrides.items(): + if value is missing: + data.pop(name, None) + else: + data[name] = value + + return data + + +if sys.version_info >= (3, 7): + # tb_next is directly assignable as of Python 3.7 + def tb_set_next(tb, tb_next): + tb.tb_next = tb_next + return tb + + +elif PYPY: + # PyPy might have special support, and won't work with ctypes. + try: + import tputil + except ImportError: + # Without tproxy support, use the original traceback. + def tb_set_next(tb, tb_next): + return tb + + else: + # With tproxy support, create a proxy around the traceback that + # returns the new tb_next. + def tb_set_next(tb, tb_next): + def controller(op): + if op.opname == "__getattribute__" and op.args[0] == "tb_next": + return tb_next + + return op.delegate() + + return tputil.make_proxy(controller, obj=tb) + + +else: + # Use ctypes to assign tb_next at the C level since it's read-only + # from Python. + import ctypes + + class _CTraceback(ctypes.Structure): + _fields_ = [ + # Extra PyObject slots when compiled with Py_TRACE_REFS. + ("PyObject_HEAD", ctypes.c_byte * object().__sizeof__()), + # Only care about tb_next as an object, not a traceback. + ("tb_next", ctypes.py_object), + ] + + def tb_set_next(tb, tb_next): + c_tb = _CTraceback.from_address(id(tb)) + + # Clear out the old tb_next. + if tb.tb_next is not None: + c_tb_next = ctypes.py_object(tb.tb_next) + c_tb.tb_next = ctypes.py_object() + ctypes.pythonapi.Py_DecRef(c_tb_next) + + # Assign the new tb_next. + if tb_next is not None: + c_tb_next = ctypes.py_object(tb_next) + ctypes.pythonapi.Py_IncRef(c_tb_next) + c_tb.tb_next = c_tb_next + + return tb diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py b/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py new file mode 100644 index 00000000..8e0e7d77 --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/defaults.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +from ._compat import range_type +from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 +from .tests import TESTS as DEFAULT_TESTS # noqa: F401 +from .utils import Cycler +from .utils import generate_lorem_ipsum +from .utils import Joiner +from .utils import Namespace + +# defaults for the parser / lexer +BLOCK_START_STRING = "{%" +BLOCK_END_STRING = "%}" +VARIABLE_START_STRING = "{{" +VARIABLE_END_STRING = "}}" +COMMENT_START_STRING = "{#" +COMMENT_END_STRING = "#}" +LINE_STATEMENT_PREFIX = None +LINE_COMMENT_PREFIX = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE = "\n" +KEEP_TRAILING_NEWLINE = False + +# default filters, tests and namespace + +DEFAULT_NAMESPACE = { + "range": range_type, + "dict": dict, + "lipsum": generate_lorem_ipsum, + "cycler": Cycler, + "joiner": Joiner, + "namespace": Namespace, +} + +# default policies +DEFAULT_POLICIES = { + "compiler.ascii_str": True, + "urlize.rel": "noopener", + "urlize.target": None, + "truncate.leeway": 5, + "json.dumps_function": None, + "json.dumps_kwargs": {"sort_keys": True}, + "ext.i18n.trimmed": False, +} diff --git a/magma/squid_cnf/charms/squid/venv/jinja2/environment.py b/magma/squid_cnf/charms/squid/venv/jinja2/environment.py new file mode 100644 index 00000000..8430390e --- /dev/null +++ b/magma/squid_cnf/charms/squid/venv/jinja2/environment.py @@ -0,0 +1,1362 @@ +# -*- coding: utf-8 -*- +"""Classes for managing templates and their runtime and compile time +options. +""" +import os +import sys +import weakref +from functools import partial +from functools import reduce + +from markupsafe import Markup + +from . import nodes +from ._compat import encode_filename +from ._compat import implements_iterator +from ._compat import implements_to_string +from ._compat import iteritems +from ._compat import PY2 +from ._compat import PYPY +from ._compat import reraise +from ._compat import string_types +from ._compat import text_type +from .compiler import CodeGenerator +from .compiler import generate +from .defaults import BLOCK_END_STRING +from .defaults import BLOCK_START_STRING +from .defaults import COMMENT_END_STRING +from .defaults import COMMENT_START_STRING +from .defaults import DEFAULT_FILTERS +from .defaults import DEFAULT_NAMESPACE +from .defaults import DEFAULT_POLICIES +from .defaults import DEFAULT_TESTS +from .defaults import KEEP_TRAILING_NEWLINE +from .defaults import LINE_COMMENT_PREFIX +from .defaults import LINE_STATEMENT_PREFIX +from .defaults import LSTRIP_BLOCKS +from .defaults import NEWLINE_SEQUENCE +from .defaults import TRIM_BLOCKS +from .defaults import VARIABLE_END_STRING +from .defaults import VARIABLE_START_STRING +from .exceptions import TemplateNotFound +from .exceptions import TemplateRuntimeError +from .exceptions import TemplatesNotFound +from .exceptions import TemplateSyntaxError +from .exceptions import UndefinedError +from .lexer import get_lexer +from .lexer import TokenStream +from .nodes import EvalContext +from .parser import Parser +from .runtime import Context +from .runtime import new_context +from .runtime import Undefined +from .utils import concat +from .utils import consume +from .utils import have_async_gen +from .utils import import_string +from .utils import internalcode +from .utils import LRUCache +from .utils import missing + +# for direct template usage we have up to ten living environments +_spontaneous_environments = LRUCache(10) + + +def get_spontaneous_environment(cls, *args): + """Return a new spontaneous environment. A spontaneous environment + is used for templates created directly rather than through an + existing environment. + + :param cls: Environment class to create. + :param args: Positional arguments passed to environment. + """ + key = (cls, args) + + try: + return _spontaneous_environments[key] + except KeyError: + _spontaneous_environments[key] = env = cls(*args) + env.shared = True + return env + + +def create_cache(size): + """Return the cache class for the given size.""" + if size == 0: + return None + if size < 0: + return {} + return LRUCache(size) + + +def copy_cache(cache): + """Create an empty copy of the given cache.""" + if cache is None: + return None + elif type(cache) is dict: + return {} + return LRUCache(cache.capacity) + + +def load_extensions(environment, extensions): + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated environments. + """ + result = {} + for extension in extensions: + if isinstance(extension, string_types): + extension = import_string(extension) + result[extension.identifier] = extension(environment) + return result + + +def fail_for_missing_callable(string, name): + msg = string % name + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = "%s (%s; did you forget to quote the callable name?)" % (msg, e) + raise TemplateRuntimeError(msg) + + +def _environment_sanity_check(environment): + """Perform a sanity check on the environment.""" + assert issubclass( + environment.undefined, Undefined + ), "undefined must be a subclass of undefined because filters depend on it." + assert ( + environment.block_start_string + != environment.variable_start_string + != environment.comment_start_string + ), "block, variable and comment start strings must be different" + assert environment.newline_sequence in ( + "\r", + "\r\n", + "\n", + ), "newline_sequence set to unknown line ending string." + return environment + + +class Environment(object): + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is ``True``. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + ``None`` implicitly into an empty string here. + + `autoescape` + If set to ``True`` the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~markupsafe.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return ``True`` or ``False`` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + ``auto_reload`` is set to ``True`` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + + `enable_async` + If set to true this enables async template execution which allows + you to take advantage of newer Python features. This requires + Python 3.6 or later. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class = CodeGenerator + + #: the context class thatis used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class = Context + + def __init__( + self, + block_start_string=BLOCK_START_STRING, + block_end_string=BLOCK_END_STRING, + variable_start_string=VARIABLE_START_STRING, + variable_end_string=VARIABLE_END_STRING, + comment_start_string=COMMENT_START_STRING, + comment_end_string=COMMENT_END_STRING, + line_statement_prefix=LINE_STATEMENT_PREFIX, + line_comment_prefix=LINE_COMMENT_PREFIX, + trim_blocks=TRIM_BLOCKS, + lstrip_blocks=LSTRIP_BLOCKS, + newline_sequence=NEWLINE_SEQUENCE, + keep_trailing_newline=KEEP_TRAILING_NEWLINE, + extensions=(), + optimized=True, + undefined=Undefined, + finalize=None, + autoescape=False, + loader=None, + cache_size=400, + auto_reload=True, + bytecode_cache=None, + enable_async=False, + ): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # configurable policies + self.policies = DEFAULT_POLICIES.copy() + + # load extensions + self.extensions = load_extensions(self, extensions) + + self.enable_async = enable_async + self.is_async = self.enable_async and have_async_gen + if self.is_async: + # runs patch_all() to enable async support + from . import asyncsupport # noqa: F401 + + _environment_sanity_check(self) + + def add_extension(self, extension): + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes): + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in iteritems(attributes): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay( + self, + block_start_string=missing, + block_end_string=missing, + variable_start_string=missing, + variable_end_string=missing, + comment_start_string=missing, + comment_end_string=missing, + line_statement_prefix=missing, + line_comment_prefix=missing, + trim_blocks=missing, + lstrip_blocks=missing, + extensions=missing, + optimized=missing, + undefined=missing, + finalize=missing, + autoescape=missing, + loader=missing, + cache_size=missing, + auto_reload=missing, + bytecode_cache=missing, + ): + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + """ + args = dict(locals()) + del args["self"], args["cache_size"], args["extensions"] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in iteritems(args): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in iteritems(self.extensions): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + return _environment_sanity_check(rv) + + lexer = property(get_lexer, doc="The lexer for this environment.") + + def iter_extensions(self): + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) + + def getitem(self, obj, argument): + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (AttributeError, TypeError, LookupError): + if isinstance(argument, string_types): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj, attribute): + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a bytestring. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def call_filter( + self, name, value, args=None, kwargs=None, context=None, eval_ctx=None + ): + """Invokes a filter on a value the same way the compiler does it. + + Note that on Python 3 this might return a coroutine in case the + filter is running from an environment in async mode and the filter + supports async execution. It's your responsibility to await this + if needed. + + .. versionadded:: 2.7 + """ + func = self.filters.get(name) + if func is None: + fail_for_missing_callable("no filter named %r", name) + args = [value] + list(args or ()) + if getattr(func, "contextfilter", False) is True: + if context is None: + raise TemplateRuntimeError( + "Attempted to invoke context filter without context" + ) + args.insert(0, context) + elif getattr(func, "evalcontextfilter", False) is True: + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + args.insert(0, eval_ctx) + elif getattr(func, "environmentfilter", False) is True: + args.insert(0, self) + return func(*args, **(kwargs or {})) + + def call_test(self, name, value, args=None, kwargs=None): + """Invokes a test on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.tests.get(name) + if func is None: + fail_for_missing_callable("no test named %r", name) + return func(value, *(args or ()), **(kwargs or {})) + + @internalcode + def parse(self, source, name=None, filename=None): + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def _parse(self, source, name, filename): + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, encode_filename(filename)).parse() + + def lex(self, source, name=None, filename=None): + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = text_type(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + self.handle_exception(source=source) + + def preprocess(self, source, name=None, filename=None): + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce( + lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), + text_type(source), + ) + + def _tokenize(self, source, name, filename=None, state=None): + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + return stream + + def _generate(self, source, name, filename, defer_init=False): + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate( + source, + self, + name, + filename, + defer_init=defer_init, + optimized=self.optimized, + ) + + def _compile(self, source, filename): + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, "exec") + + @internalcode + def compile(self, source, name=None, filename=None, raw=False, defer_init=False): + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, string_types): + source_hint = source + source = self._parse(source, name, filename) + source = self._generate(source, name, filename, defer_init=defer_init) + if raw: + return source + if filename is None: + filename = "