From fac3eaeaa70aabcc8a6e799b7cbda76e89a0b15e Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Tue, 27 Jul 2021 09:02:42 +0800 Subject: [PATCH] Revendor packages and update patches --- pipenv/patched/crayons.LICENSE | 21 +- pipenv/patched/notpip/COPYING | 14 + pipenv/patched/notpip/LICENSE | 31 + pipenv/patched/notpip/LICENSE.APACHE | 177 + pipenv/patched/notpip/LICENSE.BSD | 23 + pipenv/patched/notpip/LICENSE.rst | 80 + pipenv/patched/notpip/LICENSE.txt | 35 +- pipenv/patched/notpip/appdirs.LICENSE.txt | 23 + .../notpip}/contextlib2.LICENSE.txt | 0 pipenv/patched/notpip/distro.LICENSE | 202 + .../notpip/{_vendor => }/ipaddress.LICENSE | 0 pipenv/patched/notpip/pyparsing.LICENSE | 18 + pipenv/patched/notpip/retrying.LICENSE | 202 + pipenv/patched/notpip/six.LICENSE | 18 + pipenv/patched/piptools/utils.py | 4 +- pipenv/patched/yaml2/LICENSE | 2 +- pipenv/patched/yaml2/__init__.py | 2 +- pipenv/patched/yaml2/constructor.py | 30 +- pipenv/patched/yaml2/cyaml.py | 2 +- pipenv/patched/yaml2/reader.py | 9 +- pipenv/patched/yaml2/resolver.py | 4 +- pipenv/patched/yaml3/LICENSE | 2 +- pipenv/patched/yaml3/__init__.py | 2 +- pipenv/patched/yaml3/constructor.py | 24 +- pipenv/patched/yaml3/cyaml.py | 2 +- pipenv/patched/yaml3/resolver.py | 4 +- pipenv/vendor/HISTORY.rst | 237 + pipenv/vendor/LICENSE | 21 + .../2021-05-14-16-06-02.bpo-44095.v_pLwY.rst | 2 + pipenv/vendor/README.rst | 451 + pipenv/vendor/attr/__init__.py | 4 +- pipenv/vendor/attr/__init__.pyi | 126 +- pipenv/vendor/attr/_cmp.py | 152 + pipenv/vendor/attr/_cmp.pyi | 14 + pipenv/vendor/attr/_compat.py | 11 + pipenv/vendor/attr/_funcs.py | 11 +- pipenv/vendor/attr/_make.py | 475 +- pipenv/vendor/attr/_next_gen.py | 10 +- pipenv/vendor/attr/converters.py | 28 +- pipenv/vendor/attr/converters.pyi | 4 +- pipenv/vendor/attr/exceptions.py | 2 +- pipenv/vendor/attr/exceptions.pyi | 1 + pipenv/vendor/attr/filters.pyi | 4 +- pipenv/vendor/attr/setters.pyi | 8 +- pipenv/vendor/attr/validators.pyi | 22 +- pipenv/vendor/backports/__init__.py | 6 +- .../backports/functools_lru_cache.LICENSE | 7 - .../vendor/backports/functools_lru_cache.py | 8 +- pipenv/vendor/cached-property.LICENSE | 12 + pipenv/vendor/cerberus/__init__.py | 4 +- pipenv/vendor/cerberus/benchmarks/__init__.py | 4 + .../benchmarks/test_overall_performance_1.py | 212 + .../benchmarks/test_overall_performance_2.py | 54 + pipenv/vendor/cerberus/errors.py | 98 +- pipenv/vendor/cerberus/platform.py | 3 + pipenv/vendor/cerberus/schema.py | 98 +- pipenv/vendor/cerberus/tests/__init__.py | 16 +- .../cerberus/tests/test_customization.py | 5 +- pipenv/vendor/cerberus/tests/test_errors.py | 131 +- pipenv/vendor/cerberus/tests/test_schema.py | 6 +- .../vendor/cerberus/tests/test_validation.py | 51 +- pipenv/vendor/cerberus/utils.py | 16 +- pipenv/vendor/cerberus/validator.py | 351 +- pipenv/vendor/certifi/LICENSE | 2 +- pipenv/vendor/certifi/__init__.py | 2 +- pipenv/vendor/certifi/cacert.pem | 891 +- pipenv/vendor/chardet/__init__.py | 48 +- pipenv/vendor/chardet/charsetgroupprober.py | 1 + pipenv/vendor/chardet/cli/chardetect.py | 7 +- pipenv/vendor/chardet/compat.py | 6 +- pipenv/vendor/chardet/langbulgarianmodel.py | 4862 ++++++- pipenv/vendor/chardet/langcyrillicmodel.py | 333 - pipenv/vendor/chardet/langgreekmodel.py | 4607 +++++- pipenv/vendor/chardet/langhebrewmodel.py | 4571 +++++- pipenv/vendor/chardet/langhungarianmodel.py | 4859 ++++++- pipenv/vendor/chardet/langrussianmodel.py | 5718 ++++++++ pipenv/vendor/chardet/langthaimodel.py | 4570 +++++- pipenv/vendor/chardet/langturkishmodel.py | 4562 +++++- .../docs => chardet/metadata}/__init__.py | 0 pipenv/vendor/chardet/metadata/languages.py | 310 + pipenv/vendor/chardet/sbcharsetprober.py | 45 +- pipenv/vendor/chardet/sbcsgroupprober.py | 76 +- pipenv/vendor/chardet/universaldetector.py | 8 +- pipenv/vendor/chardet/version.py | 2 +- pipenv/vendor/charset_normalizer/LICENSE | 21 + pipenv/vendor/charset_normalizer/__init__.py | 31 + pipenv/vendor/charset_normalizer/api.py | 421 + .../charset_normalizer/assets/__init__.py | 52 + pipenv/vendor/charset_normalizer/cd.py | 261 + .../cli}/__init__.py | 0 .../charset_normalizer/cli/normalizer.py | 210 + pipenv/vendor/charset_normalizer/constant.py | 343 + pipenv/vendor/charset_normalizer/legacy.py | 38 + pipenv/vendor/charset_normalizer/md.py | 451 + pipenv/vendor/charset_normalizer/models.py | 355 + .../py.typed} | 0 pipenv/vendor/charset_normalizer/utils.py | 248 + pipenv/vendor/charset_normalizer/version.py | 6 + pipenv/vendor/click/__init__.py | 140 +- pipenv/vendor/click/_bashcomplete.py | 375 - pipenv/vendor/click/_compat.py | 815 +- pipenv/vendor/click/_termui_impl.py | 390 +- pipenv/vendor/click/_textwrap.py | 20 +- pipenv/vendor/click/_unicodefun.py | 151 +- pipenv/vendor/click/_winconsole.py | 219 +- pipenv/vendor/click/core.py | 2157 ++- pipenv/vendor/click/decorators.py | 414 +- pipenv/vendor/click/exceptions.py | 200 +- pipenv/vendor/click/formatting.py | 110 +- pipenv/vendor/click/globals.py | 34 +- pipenv/vendor/click/parser.py | 291 +- .../data03/__init__.py => click/py.typed} | 0 pipenv/vendor/click/shell_completion.py | 574 + pipenv/vendor/click/termui.py | 486 +- pipenv/vendor/click/testing.py | 343 +- pipenv/vendor/click/types.py | 848 +- pipenv/vendor/click/utils.py | 456 +- pipenv/vendor/contextlib2.py | 518 - pipenv/vendor/contextlib2/LICENSE.txt | 124 + pipenv/vendor/contextlib2/__init__.py | 798 ++ pipenv/vendor/contextlib2/__init__.pyi | 132 + .../resource1.txt => contextlib2/py.typed} | 0 pipenv/vendor/dateutil/LICENSE | 54 - pipenv/vendor/dateutil/_version.py | 3 +- pipenv/vendor/dateutil/easter.py | 16 +- pipenv/vendor/dateutil/parser/_parser.py | 44 +- pipenv/vendor/dateutil/parser/isoparser.py | 17 +- pipenv/vendor/dateutil/rrule.py | 24 +- pipenv/vendor/dateutil/tz/tz.py | 2 +- pipenv/vendor/dateutil/utils.py | 2 +- .../zoneinfo/dateutil-zoneinfo.tar.gz | Bin 153315 -> 174394 bytes pipenv/vendor/dateutil/zoneinfo/rebuild.py | 34 +- pipenv/vendor/delegator.py | 4 +- pipenv/vendor/distlib/__init__.py | 2 +- pipenv/vendor/distlib/index.py | 27 +- pipenv/vendor/distlib/locators.py | 20 +- pipenv/vendor/distlib/markers.py | 3 +- pipenv/vendor/distlib/metadata.py | 6 +- pipenv/vendor/distlib/resources.py | 7 +- pipenv/vendor/distlib/scripts.py | 26 +- pipenv/vendor/distlib/util.py | 210 +- pipenv/vendor/distlib/version.py | 3 + pipenv/vendor/distlib/wheel.py | 50 +- pipenv/vendor/dotenv/__init__.py | 19 +- pipenv/vendor/dotenv/cli.py | 39 +- pipenv/vendor/dotenv/compat.py | 49 - pipenv/vendor/dotenv/ipython.py | 2 - pipenv/vendor/dotenv/main.py | 265 +- pipenv/vendor/dotenv/parser.py | 127 +- pipenv/vendor/dotenv/variables.py | 88 + pipenv/vendor/dotenv/version.py | 2 +- pipenv/vendor/dparse/__init__.py | 6 +- pipenv/vendor/idna/LICENSE.md | 29 + pipenv/vendor/idna/LICENSE.rst | 34 - pipenv/vendor/idna/__init__.py | 44 +- pipenv/vendor/idna/codec.py | 63 +- pipenv/vendor/idna/compat.py | 6 +- pipenv/vendor/idna/core.py | 157 +- pipenv/vendor/idna/idnadata.py | 2 +- pipenv/vendor/idna/intranges.py | 5 + pipenv/vendor/idna/package_data.py | 2 +- .../tests/__init__.py => idna/py.typed} | 0 pipenv/vendor/idna/uts46data.py | 11743 ++++++++-------- pipenv/vendor/importlib_metadata/__init__.py | 682 +- pipenv/vendor/importlib_metadata/_adapters.py | 68 + .../vendor/importlib_metadata/_collections.py | 30 + pipenv/vendor/importlib_metadata/_compat.py | 104 +- .../vendor/importlib_metadata/_functools.py | 85 + .../vendor/importlib_metadata/_itertools.py | 19 + pipenv/vendor/importlib_metadata/_meta.py | 48 + pipenv/vendor/importlib_metadata/_text.py | 99 + .../importlib_metadata/docs/changelog.rst | 307 - pipenv/vendor/importlib_metadata/docs/conf.py | 185 - .../vendor/importlib_metadata/docs/index.rst | 50 - .../vendor/importlib_metadata/docs/using.rst | 260 - .../py.typed} | 0 .../tests/data/example-21.12-py3-none-any.whl | Bin 1455 -> 0 bytes .../importlib_metadata/tests/fixtures.py | 232 - .../importlib_metadata/tests/test_api.py | 177 - .../tests/test_integration.py | 54 - .../importlib_metadata/tests/test_main.py | 285 - .../importlib_metadata/tests/test_zip.py | 80 - pipenv/vendor/importlib_resources/__init__.py | 51 +- .../vendor/importlib_resources/_adapters.py | 170 + pipenv/vendor/importlib_resources/_common.py | 44 +- pipenv/vendor/importlib_resources/_compat.py | 129 +- .../vendor/importlib_resources/_itertools.py | 19 + pipenv/vendor/importlib_resources/_legacy.py | 85 + pipenv/vendor/importlib_resources/_py2.py | 107 - pipenv/vendor/importlib_resources/_py3.py | 160 - pipenv/vendor/importlib_resources/abc.py | 47 +- pipenv/vendor/importlib_resources/readers.py | 47 +- pipenv/vendor/importlib_resources/simple.py | 116 + .../importlib_resources/tests/_compat.py | 19 + .../tests/namespacedata01/binary.file | Bin 0 -> 4 bytes .../tests/namespacedata01/utf-16.file | Bin 0 -> 44 bytes .../tests/namespacedata01/utf-8.file | 1 + .../tests/test_compatibilty_files.py | 102 + .../tests/test_contents.py | 42 + .../importlib_resources/tests/test_files.py | 11 +- .../importlib_resources/tests/test_open.py | 28 +- .../importlib_resources/tests/test_path.py | 23 +- .../importlib_resources/tests/test_read.py | 22 +- .../importlib_resources/tests/test_reader.py | 128 + .../tests/test_resource.py | 230 +- .../importlib_resources/tests/update-zips.py | 53 + .../vendor/importlib_resources/tests/util.py | 159 +- .../tests/zipdata01/ziptestdata.zip | Bin 876 -> 876 bytes .../tests/zipdata02/ziptestdata.zip | Bin 698 -> 698 bytes pipenv/vendor/importlib_resources/trees.py | 6 - pipenv/vendor/iso8601/__init__.pyi | 1 + pipenv/vendor/iso8601/iso8601.py | 2 +- pipenv/vendor/iso8601/iso8601.pyi | 67 + pipenv/vendor/jinja2/__init__.py | 67 +- pipenv/vendor/jinja2/_compat.py | 132 - pipenv/vendor/jinja2/async_utils.py | 68 + pipenv/vendor/jinja2/asyncfilters.py | 158 - pipenv/vendor/jinja2/asyncsupport.py | 264 - pipenv/vendor/jinja2/bccache.py | 148 +- pipenv/vendor/jinja2/compiler.py | 1191 +- pipenv/vendor/jinja2/constants.py | 3 +- pipenv/vendor/jinja2/debug.py | 83 +- pipenv/vendor/jinja2/defaults.py | 18 +- pipenv/vendor/jinja2/environment.py | 1046 +- pipenv/vendor/jinja2/exceptions.py | 103 +- pipenv/vendor/jinja2/ext.py | 481 +- pipenv/vendor/jinja2/filters.py | 1030 +- pipenv/vendor/jinja2/idtracking.py | 178 +- pipenv/vendor/jinja2/lexer.py | 429 +- pipenv/vendor/jinja2/loaders.py | 384 +- pipenv/vendor/jinja2/meta.py | 62 +- pipenv/vendor/jinja2/nativetypes.py | 56 +- pipenv/vendor/jinja2/nodes.py | 471 +- pipenv/vendor/jinja2/optimizer.py | 18 +- pipenv/vendor/jinja2/parser.py | 371 +- pipenv/vendor/jinja2/py.typed | 0 pipenv/vendor/jinja2/runtime.py | 846 +- pipenv/vendor/jinja2/sandbox.py | 264 +- pipenv/vendor/jinja2/tests.py | 114 +- pipenv/vendor/jinja2/utils.py | 720 +- pipenv/vendor/jinja2/visitor.py | 31 +- pipenv/vendor/markupsafe/__init__.py | 327 +- pipenv/vendor/markupsafe/_compat.py | 33 - pipenv/vendor/markupsafe/_constants.py | 264 - pipenv/vendor/markupsafe/_native.py | 42 +- pipenv/vendor/markupsafe/_speedups.c | 423 - pipenv/vendor/markupsafe/_speedups.pyi | 9 + pipenv/vendor/markupsafe/py.typed | 0 pipenv/vendor/more_itertools/__init__.py | 6 +- pipenv/vendor/more_itertools/__init__.pyi | 2 + pipenv/vendor/more_itertools/more.py | 2030 ++- pipenv/vendor/more_itertools/more.pyi | 480 + pipenv/vendor/more_itertools/py.typed | 0 pipenv/vendor/more_itertools/recipes.py | 237 +- pipenv/vendor/more_itertools/recipes.pyi | 103 + .../vendor/more_itertools/tests/test_more.py | 2313 --- .../more_itertools/tests/test_recipes.py | 616 - pipenv/vendor/packaging/__about__.py | 3 +- pipenv/vendor/packaging/__init__.py | 1 - pipenv/vendor/packaging/_compat.py | 38 - pipenv/vendor/packaging/_manylinux.py | 301 + pipenv/vendor/packaging/_musllinux.py | 136 + pipenv/vendor/packaging/_structures.py | 59 +- pipenv/vendor/packaging/markers.py | 134 +- pipenv/vendor/packaging/requirements.py | 75 +- pipenv/vendor/packaging/specifiers.py | 298 +- pipenv/vendor/packaging/tags.py | 566 +- pipenv/vendor/packaging/utils.py | 119 +- pipenv/vendor/packaging/version.py | 236 +- pipenv/vendor/parse.py | 49 +- pipenv/vendor/pathlib2/__init__.py | 69 +- pipenv/vendor/pep517/__init__.py | 2 +- pipenv/vendor/pep517/build.py | 11 +- pipenv/vendor/pep517/check.py | 10 +- pipenv/vendor/pep517/compat.py | 8 + pipenv/vendor/pep517/envbuild.py | 10 +- pipenv/vendor/pep517/in_process/__init__.py | 17 + .../pep517/{ => in_process}/_in_process.py | 79 +- pipenv/vendor/pep517/wrappers.py | 68 +- pipenv/vendor/pip_shims/compat.py | 2 +- pipenv/vendor/pipdeptree.py | 556 +- pipenv/vendor/pipreqs/pipreqs.py | 5 +- pipenv/vendor/plette/__init__.py | 2 +- pipenv/vendor/ptyprocess/__init__.py | 2 +- pipenv/vendor/ptyprocess/ptyprocess.py | 12 +- .../{pep514tools.LICENSE => LICENSE} | 0 pipenv/vendor/pythonfinder/__init__.py | 2 +- pipenv/vendor/pythonfinder/models/mixins.py | 12 +- pipenv/vendor/pythonfinder/models/path.py | 12 +- pipenv/vendor/pythonfinder/pythonfinder.py | 4 +- pipenv/vendor/pythonfinder/utils.py | 2 +- pipenv/vendor/requests/__init__.py | 39 +- pipenv/vendor/requests/__version__.py | 4 +- pipenv/vendor/requests/api.py | 2 - pipenv/vendor/requests/compat.py | 5 +- pipenv/vendor/requests/exceptions.py | 4 + pipenv/vendor/requests/help.py | 20 +- pipenv/vendor/requests/models.py | 22 +- pipenv/vendor/requests/packages.py | 14 +- pipenv/vendor/requests/sessions.py | 6 +- pipenv/vendor/requests/utils.py | 33 +- pipenv/vendor/resolvelib/LICENSE | 13 - pipenv/vendor/resolvelib/__init__.py | 26 - .../resolvelib/compat/collections_abc.py | 6 - pipenv/vendor/resolvelib/providers.py | 119 - pipenv/vendor/resolvelib/reporters.py | 37 - pipenv/vendor/resolvelib/resolvers.py | 415 - pipenv/vendor/resolvelib/structs.py | 143 - pipenv/vendor/shellingham/__init__.py | 13 +- pipenv/vendor/shellingham/_consts.py | 7 - pipenv/vendor/shellingham/_core.py | 14 +- pipenv/vendor/shellingham/nt.py | 233 +- pipenv/vendor/shellingham/posix.py | 56 - pipenv/vendor/shellingham/posix/__init__.py | 27 +- pipenv/vendor/shellingham/posix/_core.py | 2 +- pipenv/vendor/shellingham/posix/_proc.py | 35 - pipenv/vendor/shellingham/posix/_ps.py | 27 - pipenv/vendor/shellingham/posix/proc.py | 25 +- pipenv/vendor/shellingham/posix/ps.py | 16 +- pipenv/vendor/six.py | 18 +- pipenv/vendor/termcolor.COPYING.txt | 20 + pipenv/vendor/{yaspin => }/termcolor.py | 0 pipenv/vendor/tomli/LICENSE | 21 + pipenv/vendor/tomli/__init__.py | 6 + pipenv/vendor/tomli/_parser.py | 667 + pipenv/vendor/tomli/_re.py | 102 + pipenv/vendor/tomli/py.typed | 1 + pipenv/vendor/tomlkit/__init__.py | 2 +- pipenv/vendor/tomlkit/_compat.py | 5 + pipenv/vendor/tomlkit/_utils.py | 1 + pipenv/vendor/tomlkit/api.py | 2 + pipenv/vendor/tomlkit/container.py | 93 +- pipenv/vendor/tomlkit/exceptions.py | 4 + pipenv/vendor/tomlkit/items.py | 103 +- pipenv/vendor/tomlkit/parser.py | 14 +- pipenv/vendor/tomlkit/py.typed | 0 pipenv/vendor/tomlkit/source.py | 4 + pipenv/vendor/tomlkit/toml_file.py | 3 + pipenv/vendor/urllib3/_version.py | 2 +- pipenv/vendor/urllib3/connection.py | 14 +- pipenv/vendor/urllib3/connectionpool.py | 4 +- pipenv/vendor/urllib3/contrib/appengine.py | 2 +- pipenv/vendor/urllib3/contrib/ntlmpool.py | 9 + pipenv/vendor/urllib3/contrib/pyopenssl.py | 2 + .../vendor/urllib3/contrib/securetransport.py | 4 +- pipenv/vendor/urllib3/contrib/socks.py | 2 +- pipenv/vendor/urllib3/exceptions.py | 12 +- pipenv/vendor/urllib3/packages/six.py | 124 +- .../packages/ssl_match_hostname/__init__.py | 6 +- pipenv/vendor/urllib3/util/connection.py | 2 +- pipenv/vendor/urllib3/util/retry.py | 9 +- pipenv/vendor/urllib3/util/ssl_.py | 53 +- pipenv/vendor/urllib3/util/ssltransport.py | 2 +- pipenv/vendor/urllib3/util/url.py | 8 +- pipenv/vendor/vendor.txt | 98 +- pipenv/vendor/wheel/LICENSE.txt | 22 + pipenv/vendor/wheel/__init__.py | 1 + pipenv/vendor/wheel/__main__.py | 19 + pipenv/vendor/wheel/bdist_wheel.py | 492 + pipenv/vendor/wheel/cli/__init__.py | 88 + pipenv/vendor/wheel/cli/convert.py | 269 + pipenv/vendor/wheel/cli/pack.py | 79 + pipenv/vendor/wheel/cli/unpack.py | 25 + pipenv/vendor/wheel/macosx_libfile.py | 428 + pipenv/vendor/wheel/metadata.py | 133 + pipenv/vendor/wheel/pkginfo.py | 43 + pipenv/vendor/wheel/util.py | 46 + pipenv/vendor/wheel/vendored/__init__.py | 0 .../wheel/vendored/packaging/__init__.py | 0 .../{ => wheel/vendored}/packaging/_typing.py | 0 .../vendor/wheel/vendored/packaging/tags.py | 852 ++ pipenv/vendor/wheel/wheelfile.py | 169 + pipenv/vendor/yaspin/LICENSE | 2 +- pipenv/vendor/yaspin/__init__.py | 7 +- pipenv/vendor/yaspin/api.py | 5 +- pipenv/vendor/yaspin/base_spinner.py | 7 +- pipenv/vendor/yaspin/compat.py | 36 - pipenv/vendor/yaspin/constants.py | 13 +- pipenv/vendor/yaspin/core.py | 142 +- pipenv/vendor/yaspin/data/spinners.json | 126 +- pipenv/vendor/yaspin/helpers.py | 7 +- pipenv/vendor/yaspin/signal_handlers.py | 8 +- pipenv/vendor/yaspin/spinners.py | 8 +- pipenv/vendor/zipp.py | 12 + .../vendor/pipdeptree-update-pip-import.patch | 6 +- .../patches/vendor/tomlkit-fix.patch | 128 - .../vendor/yaspin-signal-handling.patch | 28 +- tests/integration/test_lock.py | 2 - 388 files changed, 67321 insertions(+), 26163 deletions(-) create mode 100644 pipenv/patched/notpip/COPYING create mode 100644 pipenv/patched/notpip/LICENSE create mode 100644 pipenv/patched/notpip/LICENSE.APACHE create mode 100644 pipenv/patched/notpip/LICENSE.BSD create mode 100644 pipenv/patched/notpip/LICENSE.rst create mode 100644 pipenv/patched/notpip/appdirs.LICENSE.txt rename pipenv/{vendor => patched/notpip}/contextlib2.LICENSE.txt (100%) create mode 100644 pipenv/patched/notpip/distro.LICENSE rename pipenv/patched/notpip/{_vendor => }/ipaddress.LICENSE (100%) create mode 100644 pipenv/patched/notpip/pyparsing.LICENSE create mode 100644 pipenv/patched/notpip/retrying.LICENSE create mode 100644 pipenv/patched/notpip/six.LICENSE create mode 100644 pipenv/vendor/HISTORY.rst create mode 100644 pipenv/vendor/LICENSE create mode 100644 pipenv/vendor/Misc/NEWS.d/next/Library/2021-05-14-16-06-02.bpo-44095.v_pLwY.rst create mode 100644 pipenv/vendor/README.rst create mode 100644 pipenv/vendor/attr/_cmp.py create mode 100644 pipenv/vendor/attr/_cmp.pyi delete mode 100644 pipenv/vendor/backports/functools_lru_cache.LICENSE create mode 100644 pipenv/vendor/cached-property.LICENSE create mode 100644 pipenv/vendor/cerberus/benchmarks/__init__.py create mode 100644 pipenv/vendor/cerberus/benchmarks/test_overall_performance_1.py create mode 100644 pipenv/vendor/cerberus/benchmarks/test_overall_performance_2.py delete mode 100644 pipenv/vendor/chardet/langcyrillicmodel.py create mode 100644 pipenv/vendor/chardet/langrussianmodel.py rename pipenv/vendor/{importlib_metadata/docs => chardet/metadata}/__init__.py (100%) create mode 100644 pipenv/vendor/chardet/metadata/languages.py create mode 100644 pipenv/vendor/charset_normalizer/LICENSE create mode 100644 pipenv/vendor/charset_normalizer/__init__.py create mode 100644 pipenv/vendor/charset_normalizer/api.py create mode 100644 pipenv/vendor/charset_normalizer/assets/__init__.py create mode 100644 pipenv/vendor/charset_normalizer/cd.py rename pipenv/vendor/{importlib_metadata/tests => charset_normalizer/cli}/__init__.py (100%) create mode 100644 pipenv/vendor/charset_normalizer/cli/normalizer.py create mode 100644 pipenv/vendor/charset_normalizer/constant.py create mode 100644 pipenv/vendor/charset_normalizer/legacy.py create mode 100644 pipenv/vendor/charset_normalizer/md.py create mode 100644 pipenv/vendor/charset_normalizer/models.py rename pipenv/vendor/{importlib_metadata/tests/data/__init__.py => charset_normalizer/py.typed} (100%) create mode 100644 pipenv/vendor/charset_normalizer/utils.py create mode 100644 pipenv/vendor/charset_normalizer/version.py delete mode 100644 pipenv/vendor/click/_bashcomplete.py rename pipenv/vendor/{importlib_resources/tests/data03/__init__.py => click/py.typed} (100%) create mode 100644 pipenv/vendor/click/shell_completion.py delete mode 100644 pipenv/vendor/contextlib2.py create mode 100644 pipenv/vendor/contextlib2/LICENSE.txt create mode 100644 pipenv/vendor/contextlib2/__init__.py create mode 100644 pipenv/vendor/contextlib2/__init__.pyi rename pipenv/vendor/{importlib_resources/tests/data03/namespace/resource1.txt => contextlib2/py.typed} (100%) delete mode 100644 pipenv/vendor/dateutil/LICENSE delete mode 100644 pipenv/vendor/dotenv/compat.py create mode 100644 pipenv/vendor/dotenv/variables.py create mode 100644 pipenv/vendor/idna/LICENSE.md delete mode 100644 pipenv/vendor/idna/LICENSE.rst rename pipenv/vendor/{more_itertools/tests/__init__.py => idna/py.typed} (100%) create mode 100644 pipenv/vendor/importlib_metadata/_adapters.py create mode 100644 pipenv/vendor/importlib_metadata/_collections.py create mode 100644 pipenv/vendor/importlib_metadata/_functools.py create mode 100644 pipenv/vendor/importlib_metadata/_itertools.py create mode 100644 pipenv/vendor/importlib_metadata/_meta.py create mode 100644 pipenv/vendor/importlib_metadata/_text.py delete mode 100644 pipenv/vendor/importlib_metadata/docs/changelog.rst delete mode 100644 pipenv/vendor/importlib_metadata/docs/conf.py delete mode 100644 pipenv/vendor/importlib_metadata/docs/index.rst delete mode 100644 pipenv/vendor/importlib_metadata/docs/using.rst rename pipenv/vendor/{resolvelib/compat/__init__.py => importlib_metadata/py.typed} (100%) delete mode 100644 pipenv/vendor/importlib_metadata/tests/data/example-21.12-py3-none-any.whl delete mode 100644 pipenv/vendor/importlib_metadata/tests/fixtures.py delete mode 100644 pipenv/vendor/importlib_metadata/tests/test_api.py delete mode 100644 pipenv/vendor/importlib_metadata/tests/test_integration.py delete mode 100644 pipenv/vendor/importlib_metadata/tests/test_main.py delete mode 100644 pipenv/vendor/importlib_metadata/tests/test_zip.py create mode 100644 pipenv/vendor/importlib_resources/_adapters.py create mode 100644 pipenv/vendor/importlib_resources/_itertools.py create mode 100644 pipenv/vendor/importlib_resources/_legacy.py delete mode 100644 pipenv/vendor/importlib_resources/_py2.py delete mode 100644 pipenv/vendor/importlib_resources/_py3.py create mode 100644 pipenv/vendor/importlib_resources/simple.py create mode 100644 pipenv/vendor/importlib_resources/tests/_compat.py create mode 100644 pipenv/vendor/importlib_resources/tests/namespacedata01/binary.file create mode 100644 pipenv/vendor/importlib_resources/tests/namespacedata01/utf-16.file create mode 100644 pipenv/vendor/importlib_resources/tests/namespacedata01/utf-8.file create mode 100644 pipenv/vendor/importlib_resources/tests/test_compatibilty_files.py create mode 100644 pipenv/vendor/importlib_resources/tests/test_contents.py create mode 100644 pipenv/vendor/importlib_resources/tests/test_reader.py create mode 100644 pipenv/vendor/importlib_resources/tests/update-zips.py delete mode 100644 pipenv/vendor/importlib_resources/trees.py create mode 100644 pipenv/vendor/iso8601/__init__.pyi create mode 100644 pipenv/vendor/iso8601/iso8601.pyi delete mode 100644 pipenv/vendor/jinja2/_compat.py create mode 100644 pipenv/vendor/jinja2/async_utils.py delete mode 100644 pipenv/vendor/jinja2/asyncfilters.py delete mode 100644 pipenv/vendor/jinja2/asyncsupport.py create mode 100644 pipenv/vendor/jinja2/py.typed delete mode 100644 pipenv/vendor/markupsafe/_compat.py delete mode 100644 pipenv/vendor/markupsafe/_constants.py delete mode 100644 pipenv/vendor/markupsafe/_speedups.c create mode 100644 pipenv/vendor/markupsafe/_speedups.pyi create mode 100644 pipenv/vendor/markupsafe/py.typed create mode 100644 pipenv/vendor/more_itertools/__init__.pyi create mode 100644 pipenv/vendor/more_itertools/more.pyi create mode 100644 pipenv/vendor/more_itertools/py.typed create mode 100644 pipenv/vendor/more_itertools/recipes.pyi delete mode 100644 pipenv/vendor/more_itertools/tests/test_more.py delete mode 100644 pipenv/vendor/more_itertools/tests/test_recipes.py delete mode 100644 pipenv/vendor/packaging/_compat.py create mode 100644 pipenv/vendor/packaging/_manylinux.py create mode 100644 pipenv/vendor/packaging/_musllinux.py create mode 100644 pipenv/vendor/pep517/in_process/__init__.py rename pipenv/vendor/pep517/{ => in_process}/_in_process.py (75%) rename pipenv/vendor/pythonfinder/{pep514tools.LICENSE => LICENSE} (100%) delete mode 100644 pipenv/vendor/resolvelib/LICENSE delete mode 100644 pipenv/vendor/resolvelib/__init__.py delete mode 100644 pipenv/vendor/resolvelib/compat/collections_abc.py delete mode 100644 pipenv/vendor/resolvelib/providers.py delete mode 100644 pipenv/vendor/resolvelib/reporters.py delete mode 100644 pipenv/vendor/resolvelib/resolvers.py delete mode 100644 pipenv/vendor/resolvelib/structs.py delete mode 100644 pipenv/vendor/shellingham/_consts.py delete mode 100644 pipenv/vendor/shellingham/posix.py delete mode 100644 pipenv/vendor/shellingham/posix/_proc.py delete mode 100644 pipenv/vendor/shellingham/posix/_ps.py create mode 100644 pipenv/vendor/termcolor.COPYING.txt rename pipenv/vendor/{yaspin => }/termcolor.py (100%) create mode 100644 pipenv/vendor/tomli/LICENSE create mode 100644 pipenv/vendor/tomli/__init__.py create mode 100644 pipenv/vendor/tomli/_parser.py create mode 100644 pipenv/vendor/tomli/_re.py create mode 100644 pipenv/vendor/tomli/py.typed create mode 100644 pipenv/vendor/tomlkit/py.typed create mode 100644 pipenv/vendor/wheel/LICENSE.txt create mode 100644 pipenv/vendor/wheel/__init__.py create mode 100644 pipenv/vendor/wheel/__main__.py create mode 100644 pipenv/vendor/wheel/bdist_wheel.py create mode 100644 pipenv/vendor/wheel/cli/__init__.py create mode 100644 pipenv/vendor/wheel/cli/convert.py create mode 100644 pipenv/vendor/wheel/cli/pack.py create mode 100644 pipenv/vendor/wheel/cli/unpack.py create mode 100644 pipenv/vendor/wheel/macosx_libfile.py create mode 100644 pipenv/vendor/wheel/metadata.py create mode 100644 pipenv/vendor/wheel/pkginfo.py create mode 100644 pipenv/vendor/wheel/util.py create mode 100644 pipenv/vendor/wheel/vendored/__init__.py create mode 100644 pipenv/vendor/wheel/vendored/packaging/__init__.py rename pipenv/vendor/{ => wheel/vendored}/packaging/_typing.py (100%) create mode 100644 pipenv/vendor/wheel/vendored/packaging/tags.py create mode 100644 pipenv/vendor/wheel/wheelfile.py delete mode 100644 pipenv/vendor/yaspin/compat.py delete mode 100644 tasks/vendoring/patches/vendor/tomlkit-fix.patch diff --git a/pipenv/patched/crayons.LICENSE b/pipenv/patched/crayons.LICENSE index 9b00903f..7f0daf5f 100644 --- a/pipenv/patched/crayons.LICENSE +++ b/pipenv/patched/crayons.LICENSE @@ -1,7 +1,22 @@ +The MIT License (MIT) + Copyright 2017 Kenneth Reitz +Copyright 2019 Matthew Peveler -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: +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 above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE 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. \ No newline at end of file diff --git a/pipenv/patched/notpip/COPYING b/pipenv/patched/notpip/COPYING new file mode 100644 index 00000000..f067af3a --- /dev/null +++ b/pipenv/patched/notpip/COPYING @@ -0,0 +1,14 @@ +Copyright (C) 2008-2011 INADA Naoki + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/pipenv/patched/notpip/LICENSE b/pipenv/patched/notpip/LICENSE new file mode 100644 index 00000000..3d0d3e70 --- /dev/null +++ b/pipenv/patched/notpip/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2012 by Simon Sapin. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pipenv/patched/notpip/LICENSE.APACHE b/pipenv/patched/notpip/LICENSE.APACHE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/pipenv/patched/notpip/LICENSE.APACHE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/pipenv/patched/notpip/LICENSE.BSD b/pipenv/patched/notpip/LICENSE.BSD new file mode 100644 index 00000000..42ce7b75 --- /dev/null +++ b/pipenv/patched/notpip/LICENSE.BSD @@ -0,0 +1,23 @@ +Copyright (c) Donald Stufft and individual contributors. +All rights reserved. + +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. + +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/pipenv/patched/notpip/LICENSE.rst b/pipenv/patched/notpip/LICENSE.rst new file mode 100644 index 00000000..3ee64fba --- /dev/null +++ b/pipenv/patched/notpip/LICENSE.rst @@ -0,0 +1,80 @@ +License +------- + +Copyright (c) 2013-2018, Kim Davies. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +#. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +#. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided with + the distribution. + +#. Neither the name of the copyright holder nor the names of the + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +#. THIS SOFTWARE IS PROVIDED BY THE 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 HOLDERS 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. + +Portions of the codec implementation and unit tests are derived from the +Python standard library, which carries the `Python Software Foundation +License `_: + + Copyright (c) 2001-2014 Python Software Foundation; All Rights Reserved + +Portions of the unit tests are derived from the Unicode standard, which +is subject to the Unicode, Inc. License Agreement: + + Copyright (c) 1991-2014 Unicode, Inc. All rights reserved. + Distributed under the Terms of Use in + . + + Permission is hereby granted, free of charge, to any person obtaining + a copy of the Unicode data files and any associated documentation + (the "Data Files") or Unicode software and any associated documentation + (the "Software") to deal in the Data Files or Software + without restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, and/or sell copies of + the Data Files or Software, and to permit persons to whom the Data Files + or Software are furnished to do so, provided that + + (a) this copyright and permission notice appear with all copies + of the Data Files or Software, + + (b) this copyright and permission notice appear in associated + documentation, and + + (c) there is clear notice in each modified Data File or in the Software + as well as in the documentation associated with the Data File(s) or + Software that the data or software has been modified. + + THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS + NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL + DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THE DATA FILES OR SOFTWARE. + + Except as contained in this notice, the name of a copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in these Data Files or Software without prior + written authorization of the copyright holder. diff --git a/pipenv/patched/notpip/LICENSE.txt b/pipenv/patched/notpip/LICENSE.txt index 737fec5c..c89cf27b 100644 --- a/pipenv/patched/notpip/LICENSE.txt +++ b/pipenv/patched/notpip/LICENSE.txt @@ -1,20 +1,21 @@ -Copyright (c) 2008-2019 The pip developers (see AUTHORS.txt file) +MIT License -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) 2008-2019 Andrey Petrov and contributors (see CONTRIBUTORS.txt) -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The 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/pipenv/patched/notpip/appdirs.LICENSE.txt b/pipenv/patched/notpip/appdirs.LICENSE.txt new file mode 100644 index 00000000..107c6140 --- /dev/null +++ b/pipenv/patched/notpip/appdirs.LICENSE.txt @@ -0,0 +1,23 @@ +# This is the MIT license + +Copyright (c) 2010 ActiveState Software Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/pipenv/vendor/contextlib2.LICENSE.txt b/pipenv/patched/notpip/contextlib2.LICENSE.txt similarity index 100% rename from pipenv/vendor/contextlib2.LICENSE.txt rename to pipenv/patched/notpip/contextlib2.LICENSE.txt diff --git a/pipenv/patched/notpip/distro.LICENSE b/pipenv/patched/notpip/distro.LICENSE new file mode 100644 index 00000000..e06d2081 --- /dev/null +++ b/pipenv/patched/notpip/distro.LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/pipenv/patched/notpip/_vendor/ipaddress.LICENSE b/pipenv/patched/notpip/ipaddress.LICENSE similarity index 100% rename from pipenv/patched/notpip/_vendor/ipaddress.LICENSE rename to pipenv/patched/notpip/ipaddress.LICENSE diff --git a/pipenv/patched/notpip/pyparsing.LICENSE b/pipenv/patched/notpip/pyparsing.LICENSE new file mode 100644 index 00000000..1bf98523 --- /dev/null +++ b/pipenv/patched/notpip/pyparsing.LICENSE @@ -0,0 +1,18 @@ +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/pipenv/patched/notpip/retrying.LICENSE b/pipenv/patched/notpip/retrying.LICENSE new file mode 100644 index 00000000..7a4a3ea2 --- /dev/null +++ b/pipenv/patched/notpip/retrying.LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/pipenv/patched/notpip/six.LICENSE b/pipenv/patched/notpip/six.LICENSE new file mode 100644 index 00000000..de663311 --- /dev/null +++ b/pipenv/patched/notpip/six.LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2010-2020 Benjamin Peterson + +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/pipenv/patched/piptools/utils.py b/pipenv/patched/piptools/utils.py index 1123fb64..c92be084 100644 --- a/pipenv/patched/piptools/utils.py +++ b/pipenv/patched/piptools/utils.py @@ -141,13 +141,13 @@ def _requirement_to_str_lowercase_name(requirement): Formats a packaging.requirements.Requirement with a lowercase name. This is simply a copy of - https://github.com/pypa/pipenv/patched/packaging/blob/pipenv/patched/16.8/packaging/requirements.py#L109-L124 + https://github.com/pypa/pipenv/patched/pipenv/patched/packaging/blob/pipenv/patched/pipenv/patched/16.8/packaging/requirements.py#L109-L124 modified to lowercase the dependency name. Previously, we were invoking the original Requirement.__str__ method and lowercasing the entire result, which would lowercase the name, *and* other, important stuff that should not be lowercased (such as the marker). See - this issue for more information: https://github.com/pypa/pipenv/patched/pipenv/issues/2113. + this issue for more information: https://github.com/pypa/pipenv/patched/pipenv/patched/pipenv/issues/2113. """ parts = [requirement.name.lower()] diff --git a/pipenv/patched/yaml2/LICENSE b/pipenv/patched/yaml2/LICENSE index 3d82c281..2f1b8e15 100644 --- a/pipenv/patched/yaml2/LICENSE +++ b/pipenv/patched/yaml2/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017-2020 Ingy döt Net +Copyright (c) 2017-2021 Ingy döt Net Copyright (c) 2006-2016 Kirill Simonov Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/pipenv/patched/yaml2/__init__.py b/pipenv/patched/yaml2/__init__.py index 211fc866..1263d96f 100644 --- a/pipenv/patched/yaml2/__init__.py +++ b/pipenv/patched/yaml2/__init__.py @@ -8,7 +8,7 @@ from nodes import * from loader import * from dumper import * -__version__ = '5.3.1' +__version__ = '5.4' try: from cyaml import * diff --git a/pipenv/patched/yaml2/constructor.py b/pipenv/patched/yaml2/constructor.py index 794681cb..ff4e3682 100644 --- a/pipenv/patched/yaml2/constructor.py +++ b/pipenv/patched/yaml2/constructor.py @@ -38,6 +38,12 @@ class timezone(datetime.tzinfo): def dst(self, dt=None): return datetime.timedelta(0) + def __copy__(self): + return self.__deepcopy__() + + def __deepcopy__(self, memodict={}): + return self.__class__(self.utcoffset()) + __repr__ = __str__ = tzname @@ -722,18 +728,6 @@ FullConstructor.add_multi_constructor( u'tag:yaml.org,2002:python/name:', FullConstructor.construct_python_name) -FullConstructor.add_multi_constructor( - u'tag:yaml.org,2002:python/module:', - FullConstructor.construct_python_module) - -FullConstructor.add_multi_constructor( - u'tag:yaml.org,2002:python/object:', - FullConstructor.construct_python_object) - -FullConstructor.add_multi_constructor( - u'tag:yaml.org,2002:python/object/new:', - FullConstructor.construct_python_object_new) - class UnsafeConstructor(FullConstructor): def find_python_module(self, name, mark): @@ -750,6 +744,18 @@ class UnsafeConstructor(FullConstructor): return super(UnsafeConstructor, self).set_python_instance_state( instance, state, unsafe=True) +UnsafeConstructor.add_multi_constructor( + u'tag:yaml.org,2002:python/module:', + UnsafeConstructor.construct_python_module) + +UnsafeConstructor.add_multi_constructor( + u'tag:yaml.org,2002:python/object:', + UnsafeConstructor.construct_python_object) + +UnsafeConstructor.add_multi_constructor( + u'tag:yaml.org,2002:python/object/new:', + UnsafeConstructor.construct_python_object_new) + UnsafeConstructor.add_multi_constructor( u'tag:yaml.org,2002:python/object/apply:', UnsafeConstructor.construct_python_object_apply) diff --git a/pipenv/patched/yaml2/cyaml.py b/pipenv/patched/yaml2/cyaml.py index ebb89593..768b49d6 100644 --- a/pipenv/patched/yaml2/cyaml.py +++ b/pipenv/patched/yaml2/cyaml.py @@ -4,7 +4,7 @@ __all__ = [ 'CBaseDumper', 'CSafeDumper', 'CDumper' ] -from _yaml import CParser, CEmitter +from yaml._yaml import CParser, CEmitter from constructor import * diff --git a/pipenv/patched/yaml2/reader.py b/pipenv/patched/yaml2/reader.py index 4b377d61..4c421509 100644 --- a/pipenv/patched/yaml2/reader.py +++ b/pipenv/patched/yaml2/reader.py @@ -137,9 +137,14 @@ class Reader(object): self.update(1) if has_ucs4: - NON_PRINTABLE = re.compile(u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]') + NON_PRINTABLE = u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]' + elif sys.platform.startswith('java'): + # Jython doesn't support lone surrogates https://bugs.jython.org/issue2048 + NON_PRINTABLE = u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD]' else: - NON_PRINTABLE = re.compile(u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uFFFD]|(?:^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF](?:[^\uDC00-\uDFFF]|$)') + # Need to use eval here due to the above Jython issue + NON_PRINTABLE = eval(r"u'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uFFFD]|(?:^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF](?:[^\uDC00-\uDFFF]|$)'") + NON_PRINTABLE = re.compile(NON_PRINTABLE) def check_printable(self, data): match = self.NON_PRINTABLE.search(data) if match: diff --git a/pipenv/patched/yaml2/resolver.py b/pipenv/patched/yaml2/resolver.py index 528fbc0e..ba9aeab2 100644 --- a/pipenv/patched/yaml2/resolver.py +++ b/pipenv/patched/yaml2/resolver.py @@ -146,8 +146,8 @@ class BaseResolver(object): resolvers = self.yaml_implicit_resolvers.get(u'', []) else: resolvers = self.yaml_implicit_resolvers.get(value[0], []) - resolvers += self.yaml_implicit_resolvers.get(None, []) - for tag, regexp in resolvers: + wildcard_resolvers = self.yaml_implicit_resolvers.get(None, []) + for tag, regexp in resolvers + wildcard_resolvers: if regexp.match(value): return tag implicit = implicit[1] diff --git a/pipenv/patched/yaml3/LICENSE b/pipenv/patched/yaml3/LICENSE index 3d82c281..2f1b8e15 100644 --- a/pipenv/patched/yaml3/LICENSE +++ b/pipenv/patched/yaml3/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017-2020 Ingy döt Net +Copyright (c) 2017-2021 Ingy döt Net Copyright (c) 2006-2016 Kirill Simonov Permission is hereby granted, free of charge, to any person obtaining a copy of diff --git a/pipenv/patched/yaml3/__init__.py b/pipenv/patched/yaml3/__init__.py index 13d687c5..ee3d4b3e 100644 --- a/pipenv/patched/yaml3/__init__.py +++ b/pipenv/patched/yaml3/__init__.py @@ -8,7 +8,7 @@ from .nodes import * from .loader import * from .dumper import * -__version__ = '5.3.1' +__version__ = '5.4' try: from .cyaml import * __with_libyaml__ = True diff --git a/pipenv/patched/yaml3/constructor.py b/pipenv/patched/yaml3/constructor.py index 1948b125..619acd30 100644 --- a/pipenv/patched/yaml3/constructor.py +++ b/pipenv/patched/yaml3/constructor.py @@ -710,18 +710,6 @@ FullConstructor.add_multi_constructor( 'tag:yaml.org,2002:python/name:', FullConstructor.construct_python_name) -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/module:', - FullConstructor.construct_python_module) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/object:', - FullConstructor.construct_python_object) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/object/new:', - FullConstructor.construct_python_object_new) - class UnsafeConstructor(FullConstructor): def find_python_module(self, name, mark): @@ -738,6 +726,18 @@ class UnsafeConstructor(FullConstructor): return super(UnsafeConstructor, self).set_python_instance_state( instance, state, unsafe=True) +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/module:', + UnsafeConstructor.construct_python_module) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/object:', + UnsafeConstructor.construct_python_object) + +UnsafeConstructor.add_multi_constructor( + 'tag:yaml.org,2002:python/object/new:', + UnsafeConstructor.construct_python_object_new) + UnsafeConstructor.add_multi_constructor( 'tag:yaml.org,2002:python/object/apply:', UnsafeConstructor.construct_python_object_apply) diff --git a/pipenv/patched/yaml3/cyaml.py b/pipenv/patched/yaml3/cyaml.py index 1e606c74..0c213458 100644 --- a/pipenv/patched/yaml3/cyaml.py +++ b/pipenv/patched/yaml3/cyaml.py @@ -4,7 +4,7 @@ __all__ = [ 'CBaseDumper', 'CSafeDumper', 'CDumper' ] -from _yaml import CParser, CEmitter +from yaml._yaml import CParser, CEmitter from .constructor import * diff --git a/pipenv/patched/yaml3/resolver.py b/pipenv/patched/yaml3/resolver.py index 02b82e73..013896d2 100644 --- a/pipenv/patched/yaml3/resolver.py +++ b/pipenv/patched/yaml3/resolver.py @@ -146,8 +146,8 @@ class BaseResolver: resolvers = self.yaml_implicit_resolvers.get('', []) else: resolvers = self.yaml_implicit_resolvers.get(value[0], []) - resolvers += self.yaml_implicit_resolvers.get(None, []) - for tag, regexp in resolvers: + wildcard_resolvers = self.yaml_implicit_resolvers.get(None, []) + for tag, regexp in resolvers + wildcard_resolvers: if regexp.match(value): return tag implicit = implicit[1] diff --git a/pipenv/vendor/HISTORY.rst b/pipenv/vendor/HISTORY.rst new file mode 100644 index 00000000..fcdb8aad --- /dev/null +++ b/pipenv/vendor/HISTORY.rst @@ -0,0 +1,237 @@ +Release History +=============== + +2.0.0 / 2021-05-25 +------------------ + +* Drop Python 2.7 and 3.5 support +* Make ``termcolor`` an external dependency +* Run CI tests under Ubuntu 20.04 +* Update dependencies + + +1.5.0 / 2021-03-21 +------------------ + +* Update cli-spinners to ``v2.6.0`` +* Update dependencies + + +1.4.1 / 2021-02-28 +------------------ + +* Fix timer round-up behavior (#118) + + +1.4.0 / 2021-02-21 +------------------ + +* Add spinner timer (#99, #108) +* fix(#107): use ``poetry_core`` as build backend +* fix(#34): allow ``write()`` to print non-string objects +* Update dependencies + + +1.3.0 / 2021-01-17 +------------------ + +* Optimization: wait of stop event instead of sleep +* Update dependencies + + +1.2.0 / 2020-10-19 +------------------ + +* Update cli-spinners to ``v2.5.0`` +* Add support for Python 3.9 + + +1.1.0 / 2020-10-04 +------------------ + +* Add ``hidden()`` context manager #68 +* fix(#70): ``hidden()`` exceptions handling +* Replace coveralls.io with codecov.io +* Update dependencies + + +1.0.0 / 2020-08-02 +------------------ + +* "Stabilize" yaspin; ``1.*`` branch will contain stable release with Python 2 +support. Drop Python 2 and switch to Python 3 completely is planned for versions +``2.*``. + + +0.18.0 / 2020-07-21 +------------------- + +* Update cli-spinners to ``v2.4.0`` +* Update dependencies +* fix(#59): remove ``tests/`` and ``examples/`` from wheels distribution + + +0.17.0 / 2020-05-08 +------------------- + +* Migrate to ``poetry`` for dependencies management, building and publishing project +* Add tests for Python 3.8 +* Deprecate support for Python 3.4 +* Run tests under Ubuntu 18.04 +* Update dev dependencies to the most recent ones (compatible with Python 2.7) +* Remove Tox from the project (use CI for tests under different versions of Python) + + +0.16.0 / 2020-01-11 +------------------- + +* Allow use inside zip bundled package +* Code improvements + + +0.15.0 / 2019-08-09 +------------------- + +* Update cli-spinners to v2.2.0 + + +0.14.3 / 2019-05-12 +------------------- + +* fix(#29): race condition between spinner thread and ``write()`` + + +0.14.2 / 2019-04-27 +------------------- + +* fix: remove extra ``\b`` written to stdout. Fixes ``write()`` in rxvt terminal + + +0.14.1 / 2019-01-28 +------------------- + +* fix(#26): traceback on PYTHONOPTIMIZE=2 + + +0.14.0 / 2018-09-05 +------------------- + +* Support for handling POSIX signals +* New function in public API: ``kbi_safe_yaspin`` + + +0.13.0 / 2018-08-14 +------------------- + +* API improvements: ``spinner``, ``color``, ``on_color``, ``attrs`` and ``side`` argument values are handled via ``__getattr__`` +* New ``yaspin`` arguments: ``on_color``, ``attrs`` +* ``right=False`` argument replaced with ``side="left"`` +* ``Yaspin.right`` replaced with ``Yaspin.side`` +* ``reverse`` argument replaced with ``reversal`` +* ``Yaspin.reverse`` replaced with ``Yaspin.reversal`` +* Remove default text stripping in ``Yaspin._freeze`` + + +0.12.0 / 2018-07-16 +------------------- + +* Add support for Python 3.7 +* Drop support for Python 2.6 and 3.3 + +* dev: Migrate to Pipfile +* dev: Speedup local unittests with pytest-xdist + + +0.11.1 / 2018-07-10 +------------------- + +* fix(#16): remove default text stripping in ``Yaspin.write`` to allow printing of the hierarchical text + + +0.11.0 / 2018-06-23 +------------------- + +* Update cli-spinners to v1.3.1 + + +0.10.0 / 2018-03-23 +------------------- + +* New ``hide`` and ``show`` methods to toggle the display of the spinner + + +0.9.0 / 2018-02-26 +------------------ + +* New ``write`` method for writing text into terminal without breaking the spinner + + +0.8.0 / 2017-12-31 +------------------ + +* Speedup reading spinners collection with simplejson + + +0.7.1 / 2017-12-02 +------------------ + +* fix(#7): handling bytes sequences in ``Spinner.frames`` + + +0.7.0 / 2017-11-28 +------------------ + +* Reverse spinner support + + +0.6.0 / 2017-11-26 +------------------ + +* Right spinner support + + +0.5.0 / 2017-11-24 +------------------ + +* Colors support + + +0.4.2 / 2017-11-17 +------------------ + +* RST vs PyPI episode 2 + + +0.4.1 / 2017-11-17 +------------------ + +* RST vs PyPI episode 1 + + +0.4.0 / 2017-11-17 +------------------ + +* Support for success and failure finalizers + + +0.3.0 / 2017-11-14 +------------------ + +* Support for changing spinner properties on the fly + + +0.2.0 / 2017-11-10 +------------------ + +* Support all spinners from `cli-spinners`_ +* API changes: + - ``yaspin.spinner`` -> ``yaspin.yaspin`` + + +0.1.0 / 2017-10-31 +------------------ + +* First version + + +.. _cli-spinners: https://github.com/sindresorhus/cli-spinners diff --git a/pipenv/vendor/LICENSE b/pipenv/vendor/LICENSE new file mode 100644 index 00000000..c4902dbf --- /dev/null +++ b/pipenv/vendor/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Pavlo Dmytrenko + +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/pipenv/vendor/Misc/NEWS.d/next/Library/2021-05-14-16-06-02.bpo-44095.v_pLwY.rst b/pipenv/vendor/Misc/NEWS.d/next/Library/2021-05-14-16-06-02.bpo-44095.v_pLwY.rst new file mode 100644 index 00000000..ee03e933 --- /dev/null +++ b/pipenv/vendor/Misc/NEWS.d/next/Library/2021-05-14-16-06-02.bpo-44095.v_pLwY.rst @@ -0,0 +1,2 @@ +:class:`zipfile.Path` now supports :attr:`zipfile.Path.stem`, +:attr:`zipfile.Path.suffixes`, and :attr:`zipfile.Path.suffix` attributes. diff --git a/pipenv/vendor/README.rst b/pipenv/vendor/README.rst new file mode 100644 index 00000000..4bd0c520 --- /dev/null +++ b/pipenv/vendor/README.rst @@ -0,0 +1,451 @@ +|Logo| + +===================================================================== +``yaspin``: **Y**\ et **A**\ nother Terminal **Spin**\ ner for Python +===================================================================== + +|Build Status| |Coverage| |Codacy| |pyup| |black-fmt| + +|pypi| |Versions| |Wheel| |Examples| + +|DownloadsTot| |DownloadsW| + + +``Yaspin`` provides a full-featured terminal spinner to show the progress during long-hanging operations. + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/demo.gif + +It is easy to integrate into existing codebase by using it as a `context manager`_ +or as a function `decorator`_: + +.. code:: python + + import time + from yaspin import yaspin + + # Context manager: + with yaspin(): + time.sleep(3) # time consuming code + + # Function decorator: + @yaspin(text="Loading...") + def some_operations(): + time.sleep(3) # time consuming code + + some_operations() + + +**Yaspin** also provides an intuitive and powerful API. For example, you can easily summon a shark: + +.. code:: python + + import time + from yaspin import yaspin + + with yaspin().white.bold.shark.on_blue as sp: + sp.text = "White bold shark in a blue sea" + time.sleep(5) + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/shark.gif + + +Features +-------- + +- Runs at all major **CPython** versions (*3.6*, *3.7*, *3.8*, *3.9*), **PyPy** +- Supports all (70+) spinners from `cli-spinners`_ +- Supports all *colors*, *highlights*, *attributes* and their mixes from `termcolor`_ library +- Easy to combine with other command-line libraries, e.g. `prompt-toolkit`_ +- Flexible API, easy to integrate with existing code +- User-friendly API for handling POSIX `signals`_ +- Safe **pipes** and **redirects**: + +.. code-block:: bash + + $ python script_that_uses_yaspin.py > script.log + $ python script_that_uses_yaspin.py | grep ERROR + + +Installation +------------ + +From `PyPI`_ using ``pip`` package manager: + +.. code-block:: bash + + pip install --upgrade yaspin + + +Or install the latest sources from GitHub: + +.. code-block:: bash + + pip install https://github.com/pavdmyt/yaspin/archive/master.zip + + +Usage +----- + +Basic Example +///////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_example.gif + +.. code:: python + + import time + from random import randint + from yaspin import yaspin + + with yaspin(text="Loading", color="yellow") as spinner: + time.sleep(2) # time consuming code + + success = randint(0, 1) + if success: + spinner.ok("✅ ") + else: + spinner.fail("💥 ") + + +It is also possible to control spinner manually: + +.. code:: python + + import time + from yaspin import yaspin + + spinner = yaspin() + spinner.start() + + time.sleep(3) # time consuming tasks + + spinner.stop() + + +Run any spinner from `cli-spinners`_ +//////////////////////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/cli_spinners.gif + +.. code:: python + + import time + from yaspin import yaspin + from yaspin.spinners import Spinners + + with yaspin(Spinners.earth, text="Earth") as sp: + time.sleep(2) # time consuming code + + # change spinner + sp.spinner = Spinners.moon + sp.text = "Moon" + + time.sleep(2) # time consuming code + + +Any Colour You Like `🌈`_ +///////////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_colors.gif + +.. code:: python + + import time + from yaspin import yaspin + + with yaspin(text="Colors!") as sp: + # Support all basic termcolor text colors + colors = ("red", "green", "yellow", "blue", "magenta", "cyan", "white") + + for color in colors: + sp.color, sp.text = color, color + time.sleep(1) + + +Advanced colors usage +///////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/advanced_colors.gif + +.. code:: python + + import time + from yaspin import yaspin + from yaspin.spinners import Spinners + + text = "Bold blink magenta spinner on cyan color" + with yaspin().bold.blink.magenta.bouncingBall.on_cyan as sp: + sp.text = text + time.sleep(3) + + # The same result can be achieved by passing arguments directly + with yaspin( + Spinners.bouncingBall, + color="magenta", + on_color="on_cyan", + attrs=["bold", "blink"], + ) as sp: + sp.text = text + time.sleep(3) + + +Run any spinner you want +//////////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/custom_spinners.gif + +.. code:: python + + import time + from yaspin import yaspin, Spinner + + # Compose new spinners with custom frame sequence and interval value + sp = Spinner(["😸", "😹", "😺", "😻", "😼", "😽", "😾", "😿", "🙀"], 200) + + with yaspin(sp, text="Cat!"): + time.sleep(3) # cat consuming code :) + + +Change spinner properties on the fly +//////////////////////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/sp_properties.gif + +.. code:: python + + import time + from yaspin import yaspin + from yaspin.spinners import Spinners + + with yaspin(Spinners.noise, text="Noise spinner") as sp: + time.sleep(2) + + sp.spinner = Spinners.arc # spinner type + sp.text = "Arc spinner" # text along with spinner + sp.color = "green" # spinner color + sp.side = "right" # put spinner to the right + sp.reversal = True # reverse spin direction + + time.sleep(2) + + +Spinner with timer +////////////////// + +.. code:: python + + import time + from yaspin import yaspin + + with yaspin(text="elapsed time", timer=True) as sp: + time.sleep(3.1415) + sp.ok() + + +Writing messages +//////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/write_text.gif + +You should not write any message in the terminal using ``print`` while spinner is open. +To write messages in the terminal without any collision with ``yaspin`` spinner, a ``.write()`` method is provided: + +.. code:: python + + import time + from yaspin import yaspin + + with yaspin(text="Downloading images", color="cyan") as sp: + # task 1 + time.sleep(1) + sp.write("> image 1 download complete") + + # task 2 + time.sleep(2) + sp.write("> image 2 download complete") + + # finalize + sp.ok("✔") + + +Integration with other libraries +//////////////////////////////// + +.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/hide_show.gif + +Utilizing ``hidden`` context manager it is possible to toggle the display of +the spinner in order to call custom methods that write to the terminal. This is +helpful for allowing easy usage in other frameworks like `prompt-toolkit`_. +Using the powerful ``print_formatted_text`` function allows you even to apply +HTML formats and CSS styles to the output: + +.. code:: python + + import sys + import time + + from yaspin import yaspin + from prompt_toolkit import HTML, print_formatted_text + from prompt_toolkit.styles import Style + + # override print with feature-rich ``print_formatted_text`` from prompt_toolkit + print = print_formatted_text + + # build a basic prompt_toolkit style for styling the HTML wrapped text + style = Style.from_dict({ + 'msg': '#4caf50 bold', + 'sub-msg': '#616161 italic' + }) + + + with yaspin(text='Downloading images') as sp: + # task 1 + time.sleep(1) + with sp.hidden(): + print(HTML( + u'> image 1 download complete' + ), style=style) + + # task 2 + time.sleep(2) + with sp.hidden(): + print(HTML( + u'> image 2 download complete' + ), style=style) + + # finalize + sp.ok() + + +Handling POSIX `signals`_ +///////////////////////// + +Handling keyboard interrupts (pressing Control-C): + +.. code:: python + + import time + + from yaspin import kbi_safe_yaspin + + + with kbi_safe_yaspin(text="Press Control+C to send SIGINT (Keyboard Interrupt) signal"): + time.sleep(5) # time consuming code + + +Handling other types of signals: + +.. code:: python + + import os + import time + from signal import SIGTERM, SIGUSR1 + + from yaspin import yaspin + from yaspin.signal_handlers import default_handler, fancy_handler + + + sigmap = {SIGUSR1: default_handler, SIGTERM: fancy_handler} + with yaspin(sigmap=sigmap, text="Handling SIGUSR1 and SIGTERM signals") as sp: + sp.write("Send signals using `kill` command") + sp.write("E.g. $ kill -USR1 {0}".format(os.getpid())) + time.sleep(20) # time consuming code + + +More `examples`_. + + +Development +----------- + +Clone the repository: + +.. code-block:: bash + + git clone https://github.com/pavdmyt/yaspin.git + + +Install dev dependencies: + +.. code-block:: bash + + poetry install + + # if you don't have poetry installed: + pip install -r requirements.txt + + +Lint code: + +.. code-block:: bash + + make lint + + +Format code: + +.. code-block:: bash + + make black-fmt + + +Run tests: + +.. code-block:: bash + + make test + + +Contributing +------------ + +1. Fork it! +2. Create your feature branch: ``git checkout -b my-new-feature`` +3. Commit your changes: ``git commit -m 'Add some feature'`` +4. Push to the branch: ``git push origin my-new-feature`` +5. Submit a pull request +6. Make sure tests are passing + + +License +------- + +* MIT - Pavlo Dmytrenko; https://twitter.com/pavdmyt +* Contains data from `cli-spinners`_: MIT License, Copyright (c) Sindre Sorhus sindresorhus@gmail.com (sindresorhus.com) + + +.. |Logo| image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/static/logo_80.png + :alt: yaspin Logo +.. |Build Status| image:: https://travis-ci.org/pavdmyt/yaspin.svg?branch=master + :target: https://travis-ci.org/pavdmyt/yaspin +.. |Coverage| image:: https://codecov.io/gh/pavdmyt/yaspin/branch/master/graph/badge.svg + :target: https://codecov.io/gh/pavdmyt/yaspin +.. |Codacy| image:: https://api.codacy.com/project/badge/Grade/797c7772d0d3467c88a5e2e9dc79ec98 + :target: https://www.codacy.com/app/pavdmyt/yaspin?utm_source=github.com&utm_medium=referral&utm_content=pavdmyt/yaspin&utm_campaign=Badge_Grade +.. |pypi| image:: https://img.shields.io/pypi/v/yaspin.svg + :target: https://pypi.org/project/yaspin/ +.. |Versions| image:: https://img.shields.io/pypi/pyversions/yaspin.svg + :target: https://pypi.org/project/yaspin/ +.. |Wheel| image:: https://img.shields.io/pypi/wheel/yaspin.svg + :target: https://pypi.org/project/yaspin/ +.. |Examples| image:: https://img.shields.io/badge/learn%20by-examples-0077b3.svg + :target: https://github.com/pavdmyt/yaspin/tree/master/examples +.. |pyup| image:: https://pyup.io/repos/github/pavdmyt/yaspin/shield.svg + :target: https://pyup.io/repos/github/pavdmyt/yaspin/ +.. |black-fmt| image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/ambv/black +.. |DownloadsTot| image:: https://pepy.tech/badge/yaspin + :target: https://pepy.tech/project/yaspin +.. |DownloadsW| image:: https://pepy.tech/badge/yaspin/week + :target: https://pepy.tech/project/yaspin + + +.. _context manager: https://docs.python.org/3/reference/datamodel.html#context-managers +.. _decorator: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/ +.. _cli-spinners: https://github.com/sindresorhus/cli-spinners +.. _termcolor: https://pypi.org/project/termcolor/ +.. _PyPI: https://pypi.org/ +.. _🌈: https://en.wikipedia.org/wiki/Any_Colour_You_Like +.. _examples: https://github.com/pavdmyt/yaspin/tree/master/examples +.. _prompt-toolkit: https://github.com/jonathanslenders/python-prompt-toolkit/ +.. _signals: https://www.computerhope.com/unix/signals.htm diff --git a/pipenv/vendor/attr/__init__.py b/pipenv/vendor/attr/__init__.py index bf329cad..b1ce7fe2 100644 --- a/pipenv/vendor/attr/__init__.py +++ b/pipenv/vendor/attr/__init__.py @@ -5,6 +5,7 @@ import sys from functools import partial from . import converters, exceptions, filters, setters, validators +from ._cmp import cmp_using from ._config import get_run_validators, set_run_validators from ._funcs import asdict, assoc, astuple, evolve, has, resolve_types from ._make import ( @@ -21,7 +22,7 @@ from ._make import ( from ._version_info import VersionInfo -__version__ = "20.3.0" +__version__ = "21.2.0" __version_info__ = VersionInfo._from_version_string(__version__) __title__ = "attrs" @@ -52,6 +53,7 @@ __all__ = [ "attrib", "attributes", "attrs", + "cmp_using", "converters", "evolve", "exceptions", diff --git a/pipenv/vendor/attr/__init__.pyi b/pipenv/vendor/attr/__init__.pyi index 442d6e77..3503b073 100644 --- a/pipenv/vendor/attr/__init__.pyi +++ b/pipenv/vendor/attr/__init__.pyi @@ -1,12 +1,14 @@ +import sys + from typing import ( Any, Callable, Dict, Generic, List, + Mapping, Optional, Sequence, - Mapping, Tuple, Type, TypeVar, @@ -15,14 +17,14 @@ from typing import ( ) # `import X as X` is required to make these public +from . import converters as converters from . import exceptions as exceptions from . import filters as filters -from . import converters as converters from . import setters as setters from . import validators as validators - from ._version_info import VersionInfo + __version__: str __version_info__: VersionInfo __title__: str @@ -37,6 +39,7 @@ __copyright__: str _T = TypeVar("_T") _C = TypeVar("_C", bound=type) +_EqOrderType = Union[bool, Callable[[Any], Any]] _ValidatorType = Callable[[Any, Attribute[_T], _T], Any] _ConverterType = Callable[[Any], Any] _FilterType = Callable[[Attribute[_T], _T], bool] @@ -46,7 +49,7 @@ _OnSetAttrType = Callable[[Any, Attribute[Any], Any], Any] _OnSetAttrArgType = Union[ _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType ] -_FieldTransformer = Callable[[type, List[Attribute]], List[Attribute]] +_FieldTransformer = Callable[[type, List[Attribute[Any]]], List[Attribute[Any]]] # FIXME: in reality, if multiple validators are passed they must be in a list # or tuple, but those are invariant and so would prevent subtypes of # _ValidatorType from working when passed in a list or tuple. @@ -59,22 +62,54 @@ NOTHING: object # NOTE: Factory lies about its return type to make this possible: # `x: List[int] # = Factory(list)` # Work around mypy issue #4554 in the common case by using an overload. -@overload -def Factory(factory: Callable[[], _T]) -> _T: ... -@overload -def Factory( - factory: Union[Callable[[Any], _T], Callable[[], _T]], - takes_self: bool = ..., -) -> _T: ... +if sys.version_info >= (3, 8): + from typing import Literal + + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Callable[[Any], _T], + takes_self: Literal[True], + ) -> _T: ... + @overload + def Factory( + factory: Callable[[], _T], + takes_self: Literal[False], + ) -> _T: ... +else: + @overload + def Factory(factory: Callable[[], _T]) -> _T: ... + @overload + def Factory( + factory: Union[Callable[[Any], _T], Callable[[], _T]], + takes_self: bool = ..., + ) -> _T: ... + +# Static type inference support via __dataclass_transform__ implemented as per: +# https://github.com/microsoft/pyright/blob/1.1.135/specs/dataclass_transforms.md +# This annotation must be applied to all overloads of "define" and "attrs" +# +# NOTE: This is a typing construct and does not exist at runtime. Extensions +# wrapping attrs decorators should declare a separate __dataclass_transform__ +# signature in the extension module using the specification linked above to +# provide pyright support. +def __dataclass_transform__( + *, + eq_default: bool = True, + order_default: bool = False, + kw_only_default: bool = False, + field_descriptors: Tuple[Union[type, Callable[..., Any]], ...] = (()), +) -> Callable[[_T], _T]: ... class Attribute(Generic[_T]): name: str default: Optional[_T] validator: Optional[_ValidatorType[_T]] repr: _ReprArgType - cmp: bool - eq: bool - order: bool + cmp: _EqOrderType + eq: _EqOrderType + order: _EqOrderType hash: Optional[bool] init: bool converter: Optional[_ConverterType] @@ -83,6 +118,8 @@ class Attribute(Generic[_T]): kw_only: bool on_setattr: _OnSetAttrType + def evolve(self, **changes: Any) -> "Attribute[Any]": ... + # NOTE: We had several choices for the annotation to use for type arg: # 1) Type[_T] # - Pros: Handles simple cases correctly @@ -112,7 +149,7 @@ def attrib( default: None = ..., validator: None = ..., repr: _ReprArgType = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -120,8 +157,8 @@ def attrib( converter: None = ..., factory: None = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @@ -132,7 +169,7 @@ def attrib( default: None = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -140,8 +177,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -151,7 +188,7 @@ def attrib( default: _T, validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -159,8 +196,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -170,7 +207,7 @@ def attrib( default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: _ReprArgType = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Optional[Mapping[Any, Any]] = ..., @@ -178,8 +215,8 @@ def attrib( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @overload @@ -213,8 +250,8 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -231,8 +268,8 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> _T: ... @@ -249,17 +286,18 @@ def field( converter: Optional[_ConverterType] = ..., factory: Optional[Callable[[], _T]] = ..., kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., ) -> Any: ... @overload +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) def attrs( maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -270,8 +308,8 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., auto_detect: bool = ..., collect_by_mro: bool = ..., getstate_setstate: Optional[bool] = ..., @@ -279,12 +317,13 @@ def attrs( field_transformer: Optional[_FieldTransformer] = ..., ) -> _C: ... @overload +@__dataclass_transform__(order_default=True, field_descriptors=(attrib, field)) def attrs( maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -295,8 +334,8 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., auto_detect: bool = ..., collect_by_mro: bool = ..., getstate_setstate: Optional[bool] = ..., @@ -304,6 +343,7 @@ def attrs( field_transformer: Optional[_FieldTransformer] = ..., ) -> Callable[[_C], _C]: ... @overload +@__dataclass_transform__(field_descriptors=(attrib, field)) def define( maybe_cls: _C, *, @@ -327,6 +367,7 @@ def define( field_transformer: Optional[_FieldTransformer] = ..., ) -> _C: ... @overload +@__dataclass_transform__(field_descriptors=(attrib, field)) def define( maybe_cls: None = ..., *, @@ -364,6 +405,7 @@ def resolve_types( cls: _C, globalns: Optional[Dict[str, Any]] = ..., localns: Optional[Dict[str, Any]] = ..., + attribs: Optional[List[Attribute[Any]]] = ..., ) -> _C: ... # TODO: add support for returning a proper attrs class from the mypy plugin @@ -375,7 +417,7 @@ def make_class( bases: Tuple[type, ...] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., - cmp: Optional[bool] = ..., + cmp: Optional[_EqOrderType] = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., @@ -386,8 +428,8 @@ def make_class( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., + eq: Optional[_EqOrderType] = ..., + order: Optional[_EqOrderType] = ..., collect_by_mro: bool = ..., on_setattr: Optional[_OnSetAttrArgType] = ..., field_transformer: Optional[_FieldTransformer] = ..., @@ -406,7 +448,7 @@ def asdict( filter: Optional[_FilterType[Any]] = ..., dict_factory: Type[Mapping[Any, Any]] = ..., retain_collection_types: bool = ..., - value_serializer: Optional[Callable[[type, Attribute, Any], Any]] = ..., + value_serializer: Optional[Callable[[type, Attribute[Any], Any], Any]] = ..., ) -> Dict[str, Any]: ... # TODO: add support for returning NamedTuple from the mypy plugin diff --git a/pipenv/vendor/attr/_cmp.py b/pipenv/vendor/attr/_cmp.py new file mode 100644 index 00000000..b747b603 --- /dev/null +++ b/pipenv/vendor/attr/_cmp.py @@ -0,0 +1,152 @@ +from __future__ import absolute_import, division, print_function + +import functools + +from ._compat import new_class +from ._make import _make_ne + + +_operation_names = {"eq": "==", "lt": "<", "le": "<=", "gt": ">", "ge": ">="} + + +def cmp_using( + eq=None, + lt=None, + le=None, + gt=None, + ge=None, + require_same_type=True, + class_name="Comparable", +): + """ + Create a class that can be passed into `attr.ib`'s ``eq``, ``order``, and + ``cmp`` arguments to customize field comparison. + + The resulting class will have a full set of ordering methods if + at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. + + :param Optional[callable] eq: `callable` used to evaluate equality + of two objects. + :param Optional[callable] lt: `callable` used to evaluate whether + one object is less than another object. + :param Optional[callable] le: `callable` used to evaluate whether + one object is less than or equal to another object. + :param Optional[callable] gt: `callable` used to evaluate whether + one object is greater than another object. + :param Optional[callable] ge: `callable` used to evaluate whether + one object is greater than or equal to another object. + + :param bool require_same_type: When `True`, equality and ordering methods + will return `NotImplemented` if objects are not of the same type. + + :param Optional[str] class_name: Name of class. Defaults to 'Comparable'. + + See `comparison` for more details. + + .. versionadded:: 21.1.0 + """ + + body = { + "__slots__": ["value"], + "__init__": _make_init(), + "_requirements": [], + "_is_comparable_to": _is_comparable_to, + } + + # Add operations. + num_order_functions = 0 + has_eq_function = False + + if eq is not None: + has_eq_function = True + body["__eq__"] = _make_operator("eq", eq) + body["__ne__"] = _make_ne() + + if lt is not None: + num_order_functions += 1 + body["__lt__"] = _make_operator("lt", lt) + + if le is not None: + num_order_functions += 1 + body["__le__"] = _make_operator("le", le) + + if gt is not None: + num_order_functions += 1 + body["__gt__"] = _make_operator("gt", gt) + + if ge is not None: + num_order_functions += 1 + body["__ge__"] = _make_operator("ge", ge) + + type_ = new_class(class_name, (object,), {}, lambda ns: ns.update(body)) + + # Add same type requirement. + if require_same_type: + type_._requirements.append(_check_same_type) + + # Add total ordering if at least one operation was defined. + if 0 < num_order_functions < 4: + if not has_eq_function: + # functools.total_ordering requires __eq__ to be defined, + # so raise early error here to keep a nice stack. + raise ValueError( + "eq must be define is order to complete ordering from " + "lt, le, gt, ge." + ) + type_ = functools.total_ordering(type_) + + return type_ + + +def _make_init(): + """ + Create __init__ method. + """ + + def __init__(self, value): + """ + Initialize object with *value*. + """ + self.value = value + + return __init__ + + +def _make_operator(name, func): + """ + Create operator method. + """ + + def method(self, other): + if not self._is_comparable_to(other): + return NotImplemented + + result = func(self.value, other.value) + if result is NotImplemented: + return NotImplemented + + return result + + method.__name__ = "__%s__" % (name,) + method.__doc__ = "Return a %s b. Computed by attrs." % ( + _operation_names[name], + ) + + return method + + +def _is_comparable_to(self, other): + """ + Check whether `other` is comparable to `self`. + """ + for func in self._requirements: + if not func(self, other): + return False + return True + + +def _check_same_type(self, other): + """ + Return True if *self* and *other* are of the same type, False otherwise. + """ + return other.value.__class__ is self.value.__class__ diff --git a/pipenv/vendor/attr/_cmp.pyi b/pipenv/vendor/attr/_cmp.pyi new file mode 100644 index 00000000..7093550f --- /dev/null +++ b/pipenv/vendor/attr/_cmp.pyi @@ -0,0 +1,14 @@ +from typing import Type + +from . import _CompareWithType + + +def cmp_using( + eq: Optional[_CompareWithType], + lt: Optional[_CompareWithType], + le: Optional[_CompareWithType], + gt: Optional[_CompareWithType], + ge: Optional[_CompareWithType], + require_same_type: bool, + class_name: str, +) -> Type: ... diff --git a/pipenv/vendor/attr/_compat.py b/pipenv/vendor/attr/_compat.py index b0ead6e1..6939f338 100644 --- a/pipenv/vendor/attr/_compat.py +++ b/pipenv/vendor/attr/_compat.py @@ -28,6 +28,15 @@ if PY2: def isclass(klass): return isinstance(klass, (type, types.ClassType)) + def new_class(name, bases, kwds, exec_body): + """ + A minimal stub of types.new_class that we need for make_class. + """ + ns = {} + exec_body(ns) + + return type(name, bases, ns) + # TYPE is used in exceptions, repr(int) is different on Python 2 and 3. TYPE = "type" @@ -122,6 +131,8 @@ else: # Python 3 and later. def iteritems(d): return d.items() + new_class = types.new_class + def metadata_proxy(d): return types.MappingProxyType(dict(d)) diff --git a/pipenv/vendor/attr/_funcs.py b/pipenv/vendor/attr/_funcs.py index e6c930cb..fda508c5 100644 --- a/pipenv/vendor/attr/_funcs.py +++ b/pipenv/vendor/attr/_funcs.py @@ -343,7 +343,7 @@ def evolve(inst, **changes): return cls(**changes) -def resolve_types(cls, globalns=None, localns=None): +def resolve_types(cls, globalns=None, localns=None, attribs=None): """ Resolve any strings and forward annotations in type annotations. @@ -360,10 +360,13 @@ def resolve_types(cls, globalns=None, localns=None): :param type cls: Class to resolve. :param Optional[dict] globalns: Dictionary containing global variables. :param Optional[dict] localns: Dictionary containing local variables. + :param Optional[list] attribs: List of attribs for the given class. + This is necessary when calling from inside a ``field_transformer`` + since *cls* is not an ``attrs`` class yet. :raise TypeError: If *cls* is not a class. :raise attr.exceptions.NotAnAttrsClassError: If *cls* is not an ``attrs`` - class. + class and you didn't pass any attribs. :raise NameError: If types cannot be resolved because of missing variables. :returns: *cls* so you can use this function also as a class decorator. @@ -371,6 +374,8 @@ def resolve_types(cls, globalns=None, localns=None): the decorator has to come in the line **before** `attr.s`. .. versionadded:: 20.1.0 + .. versionadded:: 21.1.0 *attribs* + """ try: # Since calling get_type_hints is expensive we cache whether we've @@ -380,7 +385,7 @@ def resolve_types(cls, globalns=None, localns=None): import typing hints = typing.get_type_hints(cls, globalns=globalns, localns=localns) - for field in fields(cls): + for field in fields(cls) if attribs is None else attribs: if field.name in hints: # Since fields have been frozen we must work around it. _obj_setattr(field, "type", hints[field.name]) diff --git a/pipenv/vendor/attr/_make.py b/pipenv/vendor/attr/_make.py index 49484f93..a1912b12 100644 --- a/pipenv/vendor/attr/_make.py +++ b/pipenv/vendor/attr/_make.py @@ -1,6 +1,7 @@ from __future__ import absolute_import, division, print_function import copy +import inspect import linecache import sys import threading @@ -16,6 +17,7 @@ from ._compat import ( isclass, iteritems, metadata_proxy, + new_class, ordered_dict, set_closure_cell, ) @@ -28,6 +30,10 @@ from .exceptions import ( ) +if not PY2: + import typing + + # This is used at least twice, so cache it here. _obj_setattr = object.__setattr__ _init_converter_pat = "__attr_converter_%s" @@ -35,7 +41,12 @@ _init_factory_pat = "__attr_factory_{}" _tuple_property_pat = ( " {attr_name} = _attrs_property(_attrs_itemgetter({index}))" ) -_classvar_prefixes = ("typing.ClassVar", "t.ClassVar", "ClassVar") +_classvar_prefixes = ( + "typing.ClassVar", + "t.ClassVar", + "ClassVar", + "typing_extensions.ClassVar", +) # we don't use a double-underscore prefix because that triggers # name mangling when trying to create a slot for the field # (when slots=True) @@ -52,6 +63,8 @@ class _Nothing(object): Sentinel class to indicate the lack of a value when ``None`` is ambiguous. ``_Nothing`` is a singleton. There is only ever one of it. + + .. versionchanged:: 21.1.0 ``bool(NOTHING)`` is now False. """ _singleton = None @@ -64,6 +77,12 @@ class _Nothing(object): def __repr__(self): return "NOTHING" + def __bool__(self): + return False + + def __len__(self): + return 0 # __bool__ for Python 2 + NOTHING = _Nothing() """ @@ -165,13 +184,25 @@ def attrib( as-is, i.e. it will be used directly *instead* of calling ``repr()`` (the default). :type repr: a `bool` or a `callable` to use a custom function. - :param bool eq: If ``True`` (default), include this attribute in the + + :param eq: If ``True`` (default), include this attribute in the generated ``__eq__`` and ``__ne__`` methods that check two instances - for equality. - :param bool order: If ``True`` (default), include this attributes in the + for equality. To override how the attribute value is compared, + pass a ``callable`` that takes a single value and returns the value + to be compared. + :type eq: a `bool` or a `callable`. + + :param order: If ``True`` (default), include this attributes in the generated ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. - :param bool cmp: Setting to ``True`` is equivalent to setting ``eq=True, - order=True``. Deprecated in favor of *eq* and *order*. + To override how the attribute value is ordered, + pass a ``callable`` that takes a single value and returns the value + to be ordered. + :type order: a `bool` or a `callable`. + + :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the + same value. Must not be mixed with *eq* or *order*. + :type cmp: a `bool` or a `callable`. + :param Optional[bool] hash: Include this attribute in the generated ``__hash__`` method. If ``None`` (default), mirror *eq*'s value. This is the correct behavior according the Python spec. Setting this value @@ -219,14 +250,19 @@ def attrib( .. versionadded:: 18.1.0 ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. .. versionadded:: 18.2.0 *kw_only* - .. versionchanged:: 19.2.0 *convert* keyword argument removed + .. versionchanged:: 19.2.0 *convert* keyword argument removed. .. versionchanged:: 19.2.0 *repr* also accepts a custom callable. .. deprecated:: 19.2.0 *cmp* Removal on or after 2021-06-01. .. versionadded:: 19.2.0 *eq* and *order* .. versionadded:: 20.1.0 *on_setattr* .. versionchanged:: 20.3.0 *kw_only* backported to Python 2 + .. versionchanged:: 21.1.0 + *eq*, *order*, and *cmp* also accept a custom callable + .. versionchanged:: 21.1.0 *cmp* undeprecated """ - eq, order = _determine_eq_order(cmp, eq, order, True) + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq, order, True + ) if hash is not None and hash is not True and hash is not False: raise TypeError( @@ -268,11 +304,43 @@ def attrib( type=type, kw_only=kw_only, eq=eq, + eq_key=eq_key, order=order, + order_key=order_key, on_setattr=on_setattr, ) +def _compile_and_eval(script, globs, locs=None, filename=""): + """ + "Exec" the script with the given global (globs) and local (locs) variables. + """ + bytecode = compile(script, filename, "exec") + eval(bytecode, globs, locs) + + +def _make_method(name, script, filename, globs=None): + """ + Create the method with the script given and return the method object. + """ + locs = {} + if globs is None: + globs = {} + + _compile_and_eval(script, globs, locs, filename) + + # In order of debuggers like PDB being able to step through the code, + # we add a fake linecache entry. + linecache.cache[filename] = ( + len(script), + None, + script.splitlines(True), + filename, + ) + + return locs[name] + + def _make_attr_tuple_class(cls_name, attr_names): """ Create a tuple subclass to hold `Attribute`s for an `attrs` class. @@ -296,8 +364,7 @@ def _make_attr_tuple_class(cls_name, attr_names): else: attr_class_template.append(" pass") globs = {"_attrs_itemgetter": itemgetter, "_attrs_property": property} - eval(compile("\n".join(attr_class_template), "", "exec"), globs) - + _compile_and_eval("\n".join(attr_class_template), globs) return globs[attr_class_name] @@ -324,7 +391,13 @@ def _is_class_var(annot): annotations which would put attrs-based classes at a performance disadvantage compared to plain old classes. """ - return str(annot).startswith(_classvar_prefixes) + annot = str(annot) + + # Annotation can be quoted. + if annot.startswith(("'", '"')) and annot.endswith(("'", '"')): + annot = annot[1:-1] + + return annot.startswith(_classvar_prefixes) def _has_own_attribute(cls, attrib_name): @@ -575,6 +648,7 @@ class _ClassBuilder(object): "_cls_dict", "_delete_attribs", "_frozen", + "_has_pre_init", "_has_post_init", "_is_exc", "_on_setattr", @@ -620,6 +694,7 @@ class _ClassBuilder(object): self._frozen = frozen self._weakref_slot = weakref_slot self._cache_hash = cache_hash + self._has_pre_init = bool(getattr(cls, "__attrs_pre_init__", False)) self._has_post_init = bool(getattr(cls, "__attrs_post_init__", False)) self._delete_attribs = not bool(these) self._is_exc = is_exc @@ -698,7 +773,6 @@ class _ClassBuilder(object): """ Build and return a new class with a `__slots__` attribute. """ - base_names = self._base_names cd = { k: v for k, v in iteritems(self._cls_dict) @@ -722,12 +796,21 @@ class _ClassBuilder(object): cd["__setattr__"] = object.__setattr__ break - # Traverse the MRO to check for an existing __weakref__. + # Traverse the MRO to collect existing slots + # and check for an existing __weakref__. + existing_slots = dict() weakref_inherited = False for base_cls in self._cls.__mro__[1:-1]: if base_cls.__dict__.get("__weakref__", None) is not None: weakref_inherited = True - break + existing_slots.update( + { + name: getattr(base_cls, name) + for name in getattr(base_cls, "__slots__", []) + } + ) + + base_names = set(self._base_names) names = self._attr_names if ( @@ -741,6 +824,17 @@ class _ClassBuilder(object): # We only add the names of attributes that aren't inherited. # Setting __slots__ to inherited attributes wastes memory. slot_names = [name for name in names if name not in base_names] + # There are slots for attributes from current class + # that are defined in parent classes. + # As their descriptors may be overriden by a child class, + # we collect them here and update the class dict + reused_slots = { + slot: slot_descriptor + for slot, slot_descriptor in iteritems(existing_slots) + if slot in slot_names + } + slot_names = [name for name in slot_names if name not in reused_slots] + cd.update(reused_slots) if self._cache_hash: slot_names.append(_hash_cache_field) cd["__slots__"] = tuple(slot_names) @@ -763,6 +857,10 @@ class _ClassBuilder(object): # Class- and staticmethods hide their functions inside. # These might need to be rewritten as well. closure_cells = getattr(item.__func__, "__closure__", None) + elif isinstance(item, property): + # Workaround for property `super()` shortcut (PY3-only). + # There is no universal way for other descriptors. + closure_cells = getattr(item.fget, "__closure__", None) else: closure_cells = getattr(item, "__closure__", None) @@ -853,6 +951,7 @@ class _ClassBuilder(object): _make_init( self._cls, self._attrs, + self._has_pre_init, self._has_post_init, self._frozen, self._slots, @@ -861,6 +960,27 @@ class _ClassBuilder(object): self._is_exc, self._on_setattr is not None and self._on_setattr is not setters.NO_OP, + attrs_init=False, + ) + ) + + return self + + def add_attrs_init(self): + self._cls_dict["__attrs_init__"] = self._add_method_dunders( + _make_init( + self._cls, + self._attrs, + self._has_pre_init, + self._has_post_init, + self._frozen, + self._slots, + self._cache_hash, + self._base_attr_map, + self._is_exc, + self._on_setattr is not None + and self._on_setattr is not setters.NO_OP, + attrs_init=True, ) ) @@ -954,7 +1074,7 @@ _CMP_DEPRECATION = ( ) -def _determine_eq_order(cmp, eq, order, default_eq): +def _determine_attrs_eq_order(cmp, eq, order, default_eq): """ Validate the combination of *cmp*, *eq*, and *order*. Derive the effective values of eq and order. If *eq* is None, set it to *default_eq*. @@ -964,8 +1084,6 @@ def _determine_eq_order(cmp, eq, order, default_eq): # cmp takes precedence due to bw-compatibility. if cmp is not None: - warnings.warn(_CMP_DEPRECATION, DeprecationWarning, stacklevel=3) - return cmp, cmp # If left None, equality is set to the specified default and ordering @@ -982,6 +1100,47 @@ def _determine_eq_order(cmp, eq, order, default_eq): return eq, order +def _determine_attrib_eq_order(cmp, eq, order, default_eq): + """ + Validate the combination of *cmp*, *eq*, and *order*. Derive the effective + values of eq and order. If *eq* is None, set it to *default_eq*. + """ + if cmp is not None and any((eq is not None, order is not None)): + raise ValueError("Don't mix `cmp` with `eq' and `order`.") + + def decide_callable_or_boolean(value): + """ + Decide whether a key function is used. + """ + if callable(value): + value, key = True, value + else: + key = None + return value, key + + # cmp takes precedence due to bw-compatibility. + if cmp is not None: + cmp, cmp_key = decide_callable_or_boolean(cmp) + return cmp, cmp_key, cmp, cmp_key + + # If left None, equality is set to the specified default and ordering + # mirrors equality. + if eq is None: + eq, eq_key = default_eq, None + else: + eq, eq_key = decide_callable_or_boolean(eq) + + if order is None: + order, order_key = eq, eq_key + else: + order, order_key = decide_callable_or_boolean(order) + + if eq is False and order is True: + raise ValueError("`order` can only be True if `eq` is True too.") + + return eq, eq_key, order, order_key + + def _determine_whether_to_implement( cls, flag, auto_detect, dunders, default=True ): @@ -1064,7 +1223,7 @@ def attrs( inherited from some base class). So for example by implementing ``__eq__`` on a class yourself, - ``attrs`` will deduce ``eq=False`` and won't create *neither* + ``attrs`` will deduce ``eq=False`` and will create *neither* ``__eq__`` *nor* ``__ne__`` (but Python classes come with a sensible ``__ne__`` by default, so it *should* be enough to only implement ``__eq__`` in most cases). @@ -1097,10 +1256,8 @@ def attrs( ``__gt__``, and ``__ge__`` methods that behave like *eq* above and allow instances to be ordered. If ``None`` (default) mirror value of *eq*. - :param Optional[bool] cmp: Setting to ``True`` is equivalent to setting - ``eq=True, order=True``. Deprecated in favor of *eq* and *order*, has - precedence over them for backward-compatibility though. Must not be - mixed with *eq* or *order*. + :param Optional[bool] cmp: Setting *cmp* is equivalent to setting *eq* + and *order* to the same value. Must not be mixed with *eq* or *order*. :param Optional[bool] hash: If ``None`` (default), the ``__hash__`` method is generated according how *eq* and *frozen* are set. @@ -1121,9 +1278,16 @@ def attrs( behavior `_ for more details. :param bool init: Create a ``__init__`` method that initializes the - ``attrs`` attributes. Leading underscores are stripped for the - argument name. If a ``__attrs_post_init__`` method exists on the - class, it will be called after the class is fully initialized. + ``attrs`` attributes. Leading underscores are stripped for the argument + name. If a ``__attrs_pre_init__`` method exists on the class, it will + be called before the class is initialized. If a ``__attrs_post_init__`` + method exists on the class, it will be called after the class is fully + initialized. + + If ``init`` is ``False``, an ``__attrs_init__`` method will be + injected instead. This allows you to define a custom ``__init__`` + method that can do pre-init work such as ``super().__init__()``, + and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. :param bool slots: Create a `slotted class ` that's more memory-efficient. Slotted classes are generally superior to the default dict classes, but have some gotchas you should know about, so we @@ -1164,11 +1328,20 @@ def attrs( If you assign a value to those attributes (e.g. ``x: int = 42``), that value becomes the default value like if it were passed using ``attr.ib(default=42)``. Passing an instance of `Factory` also - works as expected. + works as expected in most cases (see warning below). Attributes annotated as `typing.ClassVar`, and attributes that are neither annotated nor set to an `attr.ib` are **ignored**. + .. warning:: + For features that use the attribute name to create decorators (e.g. + `validators `), you still *must* assign `attr.ib` to + them. Otherwise Python will either not find the name or try to use + the default value to call e.g. ``validator`` on it. + + These errors can be quite confusing and probably the most common bug + report on our bug tracker. + .. _`PEP 526`: https://www.python.org/dev/peps/pep-0526/ :param bool kw_only: Make all attributes keyword-only (Python 3+) in the generated ``__init__`` (if ``init`` is ``False``, this @@ -1263,13 +1436,17 @@ def attrs( .. versionadded:: 20.1.0 *getstate_setstate* .. versionadded:: 20.1.0 *on_setattr* .. versionadded:: 20.3.0 *field_transformer* + .. versionchanged:: 21.1.0 + ``init=False`` injects ``__attrs_init__`` + .. versionchanged:: 21.1.0 Support for ``__attrs_pre_init__`` + .. versionchanged:: 21.1.0 *cmp* undeprecated """ if auto_detect and PY2: raise PythonTooOldError( "auto_detect only works on Python 3 and later." ) - eq_, order_ = _determine_eq_order(cmp, eq, order, None) + eq_, order_ = _determine_attrs_eq_order(cmp, eq, order, None) hash_ = hash # work around the lack of nonlocal if isinstance(on_setattr, (list, tuple)): @@ -1372,6 +1549,7 @@ def attrs( ): builder.add_init() else: + builder.add_attrs_init() if cache_hash: raise TypeError( "Invalid value for cache_hash. To use hash caching," @@ -1419,13 +1597,6 @@ else: return cls.__setattr__ == _frozen_setattrs -def _attrs_to_tuple(obj, attrs): - """ - Create a tuple of all values of *obj*'s *attrs*. - """ - return tuple(getattr(obj, a.name) for a in attrs) - - def _generate_unique_filename(cls, func_name): """ Create a "filename" suitable for a function being generated. @@ -1519,21 +1690,7 @@ def _make_hash(cls, attrs, frozen, cache_hash): append_hash_computation_lines("return ", tab) script = "\n".join(method_lines) - globs = {} - locs = {} - bytecode = compile(script, unique_filename, "exec") - eval(bytecode, globs, locs) - - # In order of debuggers like PDB being able to step through the code, - # we add a fake linecache entry. - linecache.cache[unique_filename] = ( - len(script), - None, - script.splitlines(True), - unique_filename, - ) - - return locs["__hash__"] + return _make_method("__hash__", script, unique_filename) def _add_hash(cls, attrs): @@ -1575,34 +1732,44 @@ def _make_eq(cls, attrs): " if other.__class__ is not self.__class__:", " return NotImplemented", ] + # We can't just do a big self.x = other.x and... clause due to # irregularities like nan == nan is false but (nan,) == (nan,) is true. + globs = {} if attrs: lines.append(" return (") others = [" ) == ("] for a in attrs: - lines.append(" self.%s," % (a.name,)) - others.append(" other.%s," % (a.name,)) + if a.eq_key: + cmp_name = "_%s_key" % (a.name,) + # Add the key function to the global namespace + # of the evaluated function. + globs[cmp_name] = a.eq_key + lines.append( + " %s(self.%s)," + % ( + cmp_name, + a.name, + ) + ) + others.append( + " %s(other.%s)," + % ( + cmp_name, + a.name, + ) + ) + else: + lines.append(" self.%s," % (a.name,)) + others.append(" other.%s," % (a.name,)) lines += others + [" )"] else: lines.append(" return True") script = "\n".join(lines) - globs = {} - locs = {} - bytecode = compile(script, unique_filename, "exec") - eval(bytecode, globs, locs) - # In order of debuggers like PDB being able to step through the code, - # we add a fake linecache entry. - linecache.cache[unique_filename] = ( - len(script), - None, - script.splitlines(True), - unique_filename, - ) - return locs["__eq__"] + return _make_method("__eq__", script, unique_filename, globs) def _make_order(cls, attrs): @@ -1615,7 +1782,12 @@ def _make_order(cls, attrs): """ Save us some typing. """ - return _attrs_to_tuple(obj, attrs) + return tuple( + key(value) if key else value + for value, key in ( + (getattr(obj, a.name), a.order_key) for a in attrs + ) + ) def __lt__(self, other): """ @@ -1829,6 +2001,7 @@ def _is_slot_attr(a_name, base_attr_map): def _make_init( cls, attrs, + pre_init, post_init, frozen, slots, @@ -1836,6 +2009,7 @@ def _make_init( base_attr_map, is_exc, has_global_on_setattr, + attrs_init, ): if frozen and has_global_on_setattr: raise ValueError("Frozen classes can't use on_setattr.") @@ -1866,15 +2040,19 @@ def _make_init( filtered_attrs, frozen, slots, + pre_init, post_init, cache_hash, base_attr_map, is_exc, needs_cached_setattr, has_global_on_setattr, + attrs_init, ) - locs = {} - bytecode = compile(script, unique_filename, "exec") + if cls.__module__ in sys.modules: + # This makes typing.get_type_hints(CLS.__init__) resolve string types. + globs.update(sys.modules[cls.__module__].__dict__) + globs.update({"NOTHING": NOTHING, "attr_dict": attr_dict}) if needs_cached_setattr: @@ -1882,21 +2060,15 @@ def _make_init( # setattr hooks. globs["_cached_setattr"] = _obj_setattr - eval(bytecode, globs, locs) - - # In order of debuggers like PDB being able to step through the code, - # we add a fake linecache entry. - linecache.cache[unique_filename] = ( - len(script), - None, - script.splitlines(True), + init = _make_method( + "__attrs_init__" if attrs_init else "__init__", + script, unique_filename, + globs, ) + init.__annotations__ = annotations - __init__ = locs["__init__"] - __init__.__annotations__ = annotations - - return __init__ + return init def _setattr(attr_name, value_var, has_on_setattr): @@ -2005,12 +2177,14 @@ def _attrs_to_init_script( attrs, frozen, slots, + pre_init, post_init, cache_hash, base_attr_map, is_exc, needs_cached_setattr, has_global_on_setattr, + attrs_init, ): """ Return a script of an initializer for *attrs* and a dict of globals. @@ -2021,6 +2195,9 @@ def _attrs_to_init_script( a cached ``object.__setattr__``. """ lines = [] + if pre_init: + lines.append("self.__attrs_pre_init__()") + if needs_cached_setattr: lines.append( # Circumvent the __setattr__ descriptor to save one lookup per @@ -2210,8 +2387,24 @@ def _attrs_to_init_script( else: lines.append(fmt_setter(attr_name, arg_name, has_on_setattr)) - if a.init is True and a.converter is None and a.type is not None: - annotations[arg_name] = a.type + if a.init is True: + if a.type is not None and a.converter is None: + annotations[arg_name] = a.type + elif a.converter is not None and not PY2: + # Try to get the type from the converter. + sig = None + try: + sig = inspect.signature(a.converter) + except (ValueError, TypeError): # inspect failed + pass + if sig: + sig_params = list(sig.parameters.values()) + if ( + sig_params + and sig_params[0].annotation + is not inspect.Parameter.empty + ): + annotations[arg_name] = sig_params[0].annotation if attrs_to_validate: # we can skip this if there are no validators. names_for_globals["_config"] = _config @@ -2265,10 +2458,12 @@ def _attrs_to_init_script( ) return ( """\ -def __init__(self, {args}): +def {init_name}(self, {args}): {lines} """.format( - args=args, lines="\n ".join(lines) if lines else "pass" + init_name=("__attrs_init__" if attrs_init else "__init__"), + args=args, + lines="\n ".join(lines) if lines else "pass", ), names_for_globals, annotations, @@ -2297,6 +2492,7 @@ class Attribute(object): .. versionadded:: 20.1.0 *on_setattr* .. versionchanged:: 20.2.0 *inherited* is not taken into account for equality checks and hashing anymore. + .. versionadded:: 21.1.0 *eq_key* and *order_key* For the full version history of the fields, see `attr.ib`. """ @@ -2307,7 +2503,9 @@ class Attribute(object): "validator", "repr", "eq", + "eq_key", "order", + "order_key", "hash", "init", "metadata", @@ -2333,10 +2531,14 @@ class Attribute(object): converter=None, kw_only=False, eq=None, + eq_key=None, order=None, + order_key=None, on_setattr=None, ): - eq, order = _determine_eq_order(cmp, eq, order, True) + eq, eq_key, order, order_key = _determine_attrib_eq_order( + cmp, eq_key or eq, order_key or order, True + ) # Cache this descriptor here to speed things up later. bound_setattr = _obj_setattr.__get__(self, Attribute) @@ -2348,7 +2550,9 @@ class Attribute(object): bound_setattr("validator", validator) bound_setattr("repr", repr) bound_setattr("eq", eq) + bound_setattr("eq_key", eq_key) bound_setattr("order", order) + bound_setattr("order_key", order_key) bound_setattr("hash", hash) bound_setattr("init", init) bound_setattr("converter", converter) @@ -2495,7 +2699,9 @@ class _CountingAttr(object): "_default", "repr", "eq", + "eq_key", "order", + "order_key", "hash", "init", "metadata", @@ -2516,7 +2722,9 @@ class _CountingAttr(object): init=True, kw_only=False, eq=True, + eq_key=None, order=False, + order_key=None, inherited=False, on_setattr=None, ) @@ -2541,7 +2749,9 @@ class _CountingAttr(object): init=True, kw_only=False, eq=True, + eq_key=None, order=False, + order_key=None, inherited=False, on_setattr=None, ), @@ -2553,7 +2763,7 @@ class _CountingAttr(object): default, validator, repr, - cmp, # XXX: unused, remove along with cmp + cmp, hash, init, converter, @@ -2561,7 +2771,9 @@ class _CountingAttr(object): type, kw_only, eq, + eq_key, order, + order_key, on_setattr, ): _CountingAttr.cls_counter += 1 @@ -2571,7 +2783,9 @@ class _CountingAttr(object): self.converter = converter self.repr = repr self.eq = eq + self.eq_key = eq_key self.order = order + self.order_key = order_key self.hash = hash self.init = init self.metadata = metadata @@ -2614,7 +2828,6 @@ class _CountingAttr(object): _CountingAttr = _add_eq(_add_repr(_CountingAttr)) -@attrs(slots=True, init=False, hash=True) class Factory(object): """ Stores a factory callable. @@ -2630,8 +2843,7 @@ class Factory(object): .. versionadded:: 17.1.0 *takes_self* """ - factory = attrib() - takes_self = attrib() + __slots__ = ("factory", "takes_self") def __init__(self, factory, takes_self=False): """ @@ -2641,6 +2853,38 @@ class Factory(object): self.factory = factory self.takes_self = takes_self + def __getstate__(self): + """ + Play nice with pickle. + """ + return tuple(getattr(self, name) for name in self.__slots__) + + def __setstate__(self, state): + """ + Play nice with pickle. + """ + for name, value in zip(self.__slots__, state): + setattr(self, name, value) + + +_f = [ + Attribute( + name=name, + default=NOTHING, + validator=None, + repr=True, + cmp=None, + eq=True, + order=False, + hash=True, + init=True, + inherited=False, + ) + for name in Factory.__slots__ +] + +Factory = _add_hash(_add_eq(_add_repr(Factory, attrs=_f), attrs=_f), attrs=_f) + def make_class(name, attrs, bases=(object,), **attributes_arguments): """ @@ -2674,12 +2918,20 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): else: raise TypeError("attrs argument must be a dict or a list.") + pre_init = cls_dict.pop("__attrs_pre_init__", None) post_init = cls_dict.pop("__attrs_post_init__", None) - type_ = type( - name, - bases, - {} if post_init is None else {"__attrs_post_init__": post_init}, - ) + user_init = cls_dict.pop("__init__", None) + + body = {} + if pre_init is not None: + body["__attrs_pre_init__"] = pre_init + if post_init is not None: + body["__attrs_post_init__"] = post_init + if user_init is not None: + body["__init__"] = user_init + + type_ = new_class(name, bases, {}, lambda ns: ns.update(body)) + # For pickling to work, the __module__ variable needs to be set to the # frame where the class is created. Bypass this step in environments where # sys._getframe is not defined (Jython for example) or sys._getframe is not @@ -2696,7 +2948,7 @@ def make_class(name, attrs, bases=(object,), **attributes_arguments): ( attributes_arguments["eq"], attributes_arguments["order"], - ) = _determine_eq_order( + ) = _determine_attrs_eq_order( cmp, attributes_arguments.get("eq"), attributes_arguments.get("order"), @@ -2751,6 +3003,9 @@ def pipe(*converters): When called on a value, it runs all wrapped converters, returning the *last* value. + Type annotations will be inferred from the wrapped converters', if + they have any. + :param callables converters: Arbitrary number of converters. .. versionadded:: 20.1.0 @@ -2762,4 +3017,36 @@ def pipe(*converters): return val + if not PY2: + if not converters: + # If the converter list is empty, pipe_converter is the identity. + A = typing.TypeVar("A") + pipe_converter.__annotations__ = {"val": A, "return": A} + else: + # Get parameter type. + sig = None + try: + sig = inspect.signature(converters[0]) + except (ValueError, TypeError): # inspect failed + pass + if sig: + params = list(sig.parameters.values()) + if ( + params + and params[0].annotation is not inspect.Parameter.empty + ): + pipe_converter.__annotations__["val"] = params[ + 0 + ].annotation + # Get return type. + sig = None + try: + sig = inspect.signature(converters[-1]) + except (ValueError, TypeError): # inspect failed + pass + if sig and sig.return_annotation is not inspect.Signature().empty: + pipe_converter.__annotations__[ + "return" + ] = sig.return_annotation + return pipe_converter diff --git a/pipenv/vendor/attr/_next_gen.py b/pipenv/vendor/attr/_next_gen.py index 2b5565c5..fab0af96 100644 --- a/pipenv/vendor/attr/_next_gen.py +++ b/pipenv/vendor/attr/_next_gen.py @@ -1,8 +1,6 @@ """ -This is a Python 3.6 and later-only, keyword-only, and **provisional** API that -calls `attr.s` with different default values. - -Provisional APIs that shall become "import attrs" one glorious day. +These are Python 3.6+-only and keyword-only APIs that call `attr.s` and +`attr.ib` with different default values. """ from functools import partial @@ -42,8 +40,8 @@ def define( :param Optional[bool] auto_attribs: If set to `True` or `False`, it behaves exactly like `attr.s`. If left `None`, `attr.s` will try to guess: - 1. If all attributes are annotated and no `attr.ib` is found, it assumes - *auto_attribs=True*. + 1. If any attributes are annotated and no unannotated `attr.ib`\ s + are found, it assumes *auto_attribs=True*. 2. Otherwise it assumes *auto_attribs=False* and tries to collect `attr.ib`\ s. diff --git a/pipenv/vendor/attr/converters.py b/pipenv/vendor/attr/converters.py index 715ce178..2777db6d 100644 --- a/pipenv/vendor/attr/converters.py +++ b/pipenv/vendor/attr/converters.py @@ -4,9 +4,15 @@ Commonly useful converters. from __future__ import absolute_import, division, print_function +from ._compat import PY2 from ._make import NOTHING, Factory, pipe +if not PY2: + import inspect + import typing + + __all__ = [ "pipe", "optional", @@ -19,6 +25,9 @@ def optional(converter): A converter that allows an attribute to be optional. An optional attribute is one which can be set to ``None``. + Type annotations will be inferred from the wrapped converter's, if it + has any. + :param callable converter: the converter that is used for non-``None`` values. @@ -30,6 +39,23 @@ def optional(converter): return None return converter(val) + if not PY2: + sig = None + try: + sig = inspect.signature(converter) + except (ValueError, TypeError): # inspect failed + pass + if sig: + params = list(sig.parameters.values()) + if params and params[0].annotation is not inspect.Parameter.empty: + optional_converter.__annotations__["val"] = typing.Optional[ + params[0].annotation + ] + if sig.return_annotation is not inspect.Signature.empty: + optional_converter.__annotations__["return"] = typing.Optional[ + sig.return_annotation + ] + return optional_converter @@ -41,7 +67,7 @@ def default_if_none(default=NOTHING, factory=None): :param default: Value to be used if ``None`` is passed. Passing an instance of `attr.Factory` is supported, however the ``takes_self`` option is *not*. - :param callable factory: A callable that takes not parameters whose result + :param callable factory: A callable that takes no parameters whose result is used if ``None`` is passed. :raises TypeError: If **neither** *default* or *factory* is passed. diff --git a/pipenv/vendor/attr/converters.pyi b/pipenv/vendor/attr/converters.pyi index 7b0caa14..84a57590 100644 --- a/pipenv/vendor/attr/converters.pyi +++ b/pipenv/vendor/attr/converters.pyi @@ -1,6 +1,8 @@ -from typing import TypeVar, Optional, Callable, overload +from typing import Callable, Optional, TypeVar, overload + from . import _ConverterType + _T = TypeVar("_T") def pipe(*validators: _ConverterType) -> _ConverterType: ... diff --git a/pipenv/vendor/attr/exceptions.py b/pipenv/vendor/attr/exceptions.py index fcd89106..f6f9861b 100644 --- a/pipenv/vendor/attr/exceptions.py +++ b/pipenv/vendor/attr/exceptions.py @@ -3,7 +3,7 @@ from __future__ import absolute_import, division, print_function class FrozenError(AttributeError): """ - A frozen/immutable instance or attribute haave been attempted to be + A frozen/immutable instance or attribute have been attempted to be modified. It mirrors the behavior of ``namedtuples`` by using the same error message diff --git a/pipenv/vendor/attr/exceptions.pyi b/pipenv/vendor/attr/exceptions.pyi index f2680118..a800fb26 100644 --- a/pipenv/vendor/attr/exceptions.pyi +++ b/pipenv/vendor/attr/exceptions.pyi @@ -1,5 +1,6 @@ from typing import Any + class FrozenError(AttributeError): msg: str = ... diff --git a/pipenv/vendor/attr/filters.pyi b/pipenv/vendor/attr/filters.pyi index 68368fe2..f7b63f1b 100644 --- a/pipenv/vendor/attr/filters.pyi +++ b/pipenv/vendor/attr/filters.pyi @@ -1,5 +1,7 @@ -from typing import Union, Any +from typing import Any, Union + from . import Attribute, _FilterType + def include(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... def exclude(*what: Union[type, Attribute[Any]]) -> _FilterType[Any]: ... diff --git a/pipenv/vendor/attr/setters.pyi b/pipenv/vendor/attr/setters.pyi index 19bc33fd..a921e07d 100644 --- a/pipenv/vendor/attr/setters.pyi +++ b/pipenv/vendor/attr/setters.pyi @@ -1,10 +1,12 @@ -from . import _OnSetAttrType, Attribute -from typing import TypeVar, Any, NewType, NoReturn, cast +from typing import Any, NewType, NoReturn, TypeVar, cast + +from . import Attribute, _OnSetAttrType + _T = TypeVar("_T") def frozen( - instance: Any, attribute: Attribute, new_value: Any + instance: Any, attribute: Attribute[Any], new_value: Any ) -> NoReturn: ... def pipe(*setters: _OnSetAttrType) -> _OnSetAttrType: ... def validate(instance: Any, attribute: Attribute[_T], new_value: _T) -> _T: ... diff --git a/pipenv/vendor/attr/validators.pyi b/pipenv/vendor/attr/validators.pyi index 9a22abb1..fe92aac4 100644 --- a/pipenv/vendor/attr/validators.pyi +++ b/pipenv/vendor/attr/validators.pyi @@ -1,21 +1,23 @@ from typing import ( - Container, - List, - Union, - TypeVar, - Type, Any, + AnyStr, + Callable, + Container, + Iterable, + List, + Mapping, + Match, Optional, Tuple, - Iterable, - Mapping, - Callable, - Match, - AnyStr, + Type, + TypeVar, + Union, overload, ) + from . import _ValidatorType + _T = TypeVar("_T") _T1 = TypeVar("_T1") _T2 = TypeVar("_T2") diff --git a/pipenv/vendor/backports/__init__.py b/pipenv/vendor/backports/__init__.py index cf897602..cc575a85 100644 --- a/pipenv/vendor/backports/__init__.py +++ b/pipenv/vendor/backports/__init__.py @@ -1,5 +1,5 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) -from . import shutil_get_terminal_size -from . import weakref +__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore from . import enum from . import functools_lru_cache +from . import shutil_get_terminal_size +from . import weakref diff --git a/pipenv/vendor/backports/functools_lru_cache.LICENSE b/pipenv/vendor/backports/functools_lru_cache.LICENSE deleted file mode 100644 index 5e795a61..00000000 --- a/pipenv/vendor/backports/functools_lru_cache.LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright Jason R. Coombs - -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/pipenv/vendor/backports/functools_lru_cache.py b/pipenv/vendor/backports/functools_lru_cache.py index e0b19d95..8be4515f 100644 --- a/pipenv/vendor/backports/functools_lru_cache.py +++ b/pipenv/vendor/backports/functools_lru_cache.py @@ -4,7 +4,7 @@ import functools from collections import namedtuple from threading import RLock -_CacheInfo = namedtuple("CacheInfo", ["hits", "misses", "maxsize", "currsize"]) +_CacheInfo = namedtuple("_CacheInfo", ["hits", "misses", "maxsize", "currsize"]) @functools.wraps(functools.update_wrapper) @@ -63,7 +63,7 @@ def _make_key( return _HashedSeq(key) -def lru_cache(maxsize=100, typed=False): +def lru_cache(maxsize=100, typed=False): # noqa: C901 """Least-recently-used cache decorator. If *maxsize* is set to None, the LRU features are disabled and the cache @@ -136,7 +136,7 @@ def lru_cache(maxsize=100, typed=False): if link is not None: # record recent use of the key by moving it # to the front of the list - root, = nonlocal_root + (root,) = nonlocal_root link_prev, link_next, key, result = link link_prev[NEXT] = link_next link_next[PREV] = link_prev @@ -148,7 +148,7 @@ def lru_cache(maxsize=100, typed=False): return result result = user_function(*args, **kwds) with lock: - root, = nonlocal_root + (root,) = nonlocal_root if key in cache: # getting here means that this same key was added to the # cache while the lock was released. since the link diff --git a/pipenv/vendor/cached-property.LICENSE b/pipenv/vendor/cached-property.LICENSE new file mode 100644 index 00000000..a181761c --- /dev/null +++ b/pipenv/vendor/cached-property.LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2015, Daniel Greenfeld +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of cached-property 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/pipenv/vendor/cerberus/__init__.py b/pipenv/vendor/cerberus/__init__.py index 1e0f0d54..e4dedf6c 100644 --- a/pipenv/vendor/cerberus/__init__.py +++ b/pipenv/vendor/cerberus/__init__.py @@ -1,10 +1,10 @@ """ Extensible validation for Python dictionaries. - :copyright: 2012-2016 by Nicola Iarocci. + :copyright: 2012-2021 by Nicola Iarocci. :license: ISC, see LICENSE for more details. - Full documentation is available at http://python-cerberus.org/ + Full documentation is available at https://python-cerberus.org/ """ diff --git a/pipenv/vendor/cerberus/benchmarks/__init__.py b/pipenv/vendor/cerberus/benchmarks/__init__.py new file mode 100644 index 00000000..7cdc925f --- /dev/null +++ b/pipenv/vendor/cerberus/benchmarks/__init__.py @@ -0,0 +1,4 @@ +from pathlib import Path + + +DOCUMENTS_PATH = Path(__file__).parent / "documents" diff --git a/pipenv/vendor/cerberus/benchmarks/test_overall_performance_1.py b/pipenv/vendor/cerberus/benchmarks/test_overall_performance_1.py new file mode 100644 index 00000000..a1f76201 --- /dev/null +++ b/pipenv/vendor/cerberus/benchmarks/test_overall_performance_1.py @@ -0,0 +1,212 @@ +""" +some notes regarding this test suite: +- results are only comparable using the semantically equal schema against and + identical set of documents in the same execution environment +- the module can be executed to generate a new set of test documents +- it is intended to detect *significant* changes in validation time +- benchmarks should run with as few other processes running on the system as + possible (e.g. an Alpine Linux on bare metal w/o a Desktop environment) +""" + +import json +from collections import Counter +from pathlib import Path +from random import choice, randrange +from typing import Callable, List + +from pytest import mark + +from cerberus import rules_set_registry, schema_registry, TypeDefinition, Validator +from cerberus.benchmarks import DOCUMENTS_PATH + + +rules_set_registry.add("path_rules", {"coerce": Path, "type": "path"}) + + +schema_registry.add( + "field_3_schema", + { + # an outer rule requires all fields' values to be a list + "field_31": {"contains": 0, "empty": False}, + "field_32": { + "default": [None, None, None], + "items": [ + {"type": "integer"}, + {"type": "string"}, + {"type": ["integer", "string"]}, + ], + "schema": {"nullable": True}, + }, + }, +) + + +def schema_1_field_3_allow_unknown_check_with(field, value, error): + if len(value) > 9: + error(field, "Requires a smaller list.") + + +schema_1 = { + "field_1": { + "type": "dict", + "required": True, + "allow_unknown": True, + "keysrules": {"regex": r"field_1[12345]"}, + "minlength": 3, + "maxlength": 5, + "schema": { + "field_11": { + "type": "integer", + "allowed": list(range(100)), + "dependencies": {"field_12": 0, "^field_1.field_13": 0}, + }, + "field_12": { + "type": "integer", + "default_setter": lambda _: 1, + "forbidden": (1,), + }, + "field_13": {"type": "integer"}, + "field_14": {"rename": "field_13"}, + }, + }, + "field_2": { + "type": "dict", + "allow_unknown": False, + "schema": { + "field_21": { + "type": "integer", + "coerce": [str.strip, int], + "min": 9, + "max": 89, + "anyof": [{"dependencies": "field_22"}, {"dependencies": "field_23"}], + }, + "field_22": {"excludes": "field_23", "nullable": True}, + "field_23": {"nullable": True}, + }, + }, + "field_3": { + "allow_unknown": {"check_with": schema_1_field_3_allow_unknown_check_with}, + "valuesrules": {"type": "list"}, + "require_all": True, + "schema": "field_3_schema", + }, + "field_4": "path_rules", +} + + +def init_validator(): + class TestValidator(Validator): + types_mapping = { + **Validator.types_mapping, + "path": TypeDefinition("path", (Path,), ()), + } + + return TestValidator(schema_1, purge_unknown=True) + + +def load_documents(): + with (DOCUMENTS_PATH / "overall_documents_1.json").open() as f: + documents = json.load(f) + return documents + + +def validate_documents(init_validator: Callable, documents: List[dict]): + doc_count = failed_count = 0 + error_paths = Counter() + validator = init_validator() + + def count_errors(errors): + if errors is None: + return + for error in errors: + if error.is_group_error: + count_errors(error.child_errors) + else: + error_paths[error.schema_path] += 1 + + for document in documents: + if validator.validated(document) is None: + failed_count += 1 + count_errors(validator._errors) + doc_count += 1 + + print( + f"{failed_count} out of {doc_count} documents failed with " + f"{len(error_paths)} different error leafs." + ) + print("Top 3 errors, excluding container errors:") + for path, count in error_paths.most_common(3): + print(f"{count}: {path}") + + +@mark.benchmark(group="overall-1") +def test_overall_performance_1(benchmark): + benchmark.pedantic(validate_documents, (init_validator, load_documents()), rounds=5) + + +# + + +def generate_sample_document_1() -> dict: + result = {} + for i in (1, 2, 3, 4, 5): + if randrange(100): + result[f"field_{i}"] = globals()[f"generate_document_1_field_{i}"]() + return result + + +def generate_document_1_field_1() -> dict: + result = {"field_11": randrange(100), "field_13": 0} + if randrange(100): + result["field_12"] = 0 + if not randrange(100): + result["field_14"] = None + if randrange(100): + result["field_15"] = None + return result + + +def generate_document_1_field_2() -> dict: + x = "*" if not randrange(50) else " " + result = {"field_21": x + str(randrange(100)) + x} + + if randrange(100): + result["field_22"] = None + if "field_22" in result and not randrange(100): + result["field_23"] = None + + return result + + +def generate_document_1_field_3() -> dict: + result = {} + if randrange(100): + result["field_31"] = [randrange(2) for _ in range(randrange(20))] + else: + result["field_31"] = None + if randrange(100): + result["field_32"] = [ + choice((0, 0, 0, 0, 0, 0, 0, 0, "", None)), + choice(("", "", "", "", "", "", "", "", 0, None)), + choice((0, 0, 0, 0, "", "", "", "", None)), + ] + if not randrange(10): + result["3_unknown"] = [0] * (randrange(10) + 1) + return result + + +def generate_document_1_field_4(): + return "/foo/bar" if randrange(100) else 0 + + +def generate_document_1_field_5(): + return None + + +def write_sample_documents(): + with (DOCUMENTS_PATH / "overall_documents_1.json").open("wt") as f: + json.dump([generate_sample_document_1() for _ in range(10_000)], f) + + +if __name__ == "__main__": + write_sample_documents() diff --git a/pipenv/vendor/cerberus/benchmarks/test_overall_performance_2.py b/pipenv/vendor/cerberus/benchmarks/test_overall_performance_2.py new file mode 100644 index 00000000..8bf49a59 --- /dev/null +++ b/pipenv/vendor/cerberus/benchmarks/test_overall_performance_2.py @@ -0,0 +1,54 @@ +import json +from collections import Counter +from typing import Callable, List +from typing import Counter as CounterType + +from pytest import mark + +from cerberus import Validator +from cerberus.benchmarks.schemas.overalll_schema_2 import product_schema +from cerberus.benchmarks import DOCUMENTS_PATH + + +def init_validator(): + return Validator(product_schema, purge_unknown=True) + + +def load_documents(): + with (DOCUMENTS_PATH / "overall_documents_2.json").open() as f: + documents = json.load(f) + return documents + + +def validate_documents(init_validator: Callable, documents: List[dict]) -> None: + doc_count = failed_count = 0 + error_paths: CounterType[tuple] = Counter() + validator = init_validator() + + def count_errors(errors): + if errors is None: + return + for error in errors: + if error.is_group_error: + count_errors(error.child_errors) + else: + error_paths[error.schema_path] += 1 + + for document in documents: + if validator.validated(document) is None: + failed_count += 1 + count_errors(validator._errors) + doc_count += 1 + + print( + f"{failed_count} out of {doc_count} documents failed with " + f"{len(error_paths)} different error leafs." + ) + print("Top 3 errors, excluding container errors:") + for path, count in error_paths.most_common(3): + print(f"{count}: {path}") + + +@mark.benchmark(group="overall-2") +def test_overall_performance_2(benchmark): + benchmark.pedantic(validate_documents, (init_validator, load_documents()), rounds=5) diff --git a/pipenv/vendor/cerberus/errors.py b/pipenv/vendor/cerberus/errors.py index 41564cab..97afc045 100644 --- a/pipenv/vendor/cerberus/errors.py +++ b/pipenv/vendor/cerberus/errors.py @@ -89,7 +89,7 @@ SCHEMA_ERROR_MISSING = "validation schema missing" class ValidationError(object): - """ A simple class to store and query basic error information. """ + """A simple class to store and query basic error information.""" def __init__(self, document_path, schema_path, code, rule, constraint, value, info): self.document_path = document_path @@ -111,11 +111,11 @@ class ValidationError(object): Type: :class:`tuple` """ def __eq__(self, other): - """ Assumes the errors relate to the same document and schema. """ + """Assumes the errors relate to the same document and schema.""" return hash(self) == hash(other) def __hash__(self): - """ Expects that all other properties are transitively determined. """ + """Expects that all other properties are transitively determined.""" return hash(self.document_path) ^ hash(self.schema_path) ^ hash(self.code) def __lt__(self, other): @@ -153,9 +153,10 @@ class ValidationError(object): @property def definitions_errors(self): - """ Dictionary with errors of an *of-rule mapped to the index of the - definition it occurred in. Returns :obj:`None` if not applicable. - """ + """ + Dictionary with errors of an \*of-rule mapped to the index of the definition it + occurred in. Returns :obj:`None` if not applicable. + """ if not self.is_logic_error: return None @@ -167,7 +168,7 @@ class ValidationError(object): @property def field(self): - """ Field of the contextual mapping, possibly :obj:`None`. """ + """Field of the contextual mapping, possibly :obj:`None`.""" if self.document_path: return self.document_path[-1] else: @@ -175,25 +176,27 @@ class ValidationError(object): @property def is_group_error(self): - """ ``True`` for errors of bulk validations. """ + """``True`` for errors of bulk validations.""" return bool(self.code & ERROR_GROUP.code) @property def is_logic_error(self): - """ ``True`` for validation errors against different schemas with - *of-rules. """ + """ + ``True`` for validation errors against different schemas with \*of-rules. + """ return bool(self.code & LOGICAL.code - ERROR_GROUP.code) @property def is_normalization_error(self): - """ ``True`` for normalization errors. """ + """``True`` for normalization errors.""" return bool(self.code & NORMALIZATION.code) class ErrorList(list): - """ A list for :class:`~cerberus.errors.ValidationError` instances that - can be queried with the ``in`` keyword for a particular - :class:`~cerberus.errors.ErrorDefinition`. """ + """ + A list for :class:`~cerberus.errors.ValidationError` instances that can be queried + with the ``in`` keyword for a particular :class:`~cerberus.errors.ErrorDefinition`. + """ def __contains__(self, error_definition): if not isinstance(error_definition, ErrorDefinition): @@ -277,8 +280,10 @@ class ErrorTreeNode(MutableMapping): class ErrorTree(ErrorTreeNode): - """ Base class for :class:`~cerberus.errors.DocumentErrorTree` and - :class:`~cerberus.errors.SchemaErrorTree`. """ + """ + Base class for :class:`~cerberus.errors.DocumentErrorTree` and + :class:`~cerberus.errors.SchemaErrorTree`. + """ def __init__(self, errors=()): self.parent_node = None @@ -290,7 +295,8 @@ class ErrorTree(ErrorTreeNode): self.add(error) def add(self, error): - """ Add an error to the tree. + """ + Add an error to the tree. :param error: :class:`~cerberus.errors.ValidationError` """ @@ -301,7 +307,8 @@ class ErrorTree(ErrorTreeNode): super(ErrorTree, self).add(error) def fetch_errors_from(self, path): - """ Returns all errors for a particular path. + """ + Returns all errors for a particular path. :param path: :class:`tuple` of :term:`hashable` s. :rtype: :class:`~cerberus.errors.ErrorList` @@ -313,7 +320,8 @@ class ErrorTree(ErrorTreeNode): return ErrorList() def fetch_node_from(self, path): - """ Returns a node for a path. + """ + Returns a node for a path. :param path: Tuple of :term:`hashable` s. :rtype: :class:`~cerberus.errors.ErrorTreeNode` or :obj:`None` @@ -327,29 +335,34 @@ class ErrorTree(ErrorTreeNode): class DocumentErrorTree(ErrorTree): - """ Implements a dict-like class to query errors by indexes following the - structure of a validated document. """ + """ + Implements a dict-like class to query errors by indexes following the structure of a + validated document. + """ tree_type = 'document' class SchemaErrorTree(ErrorTree): - """ Implements a dict-like class to query errors by indexes following the - structure of the used schema. """ + """ + Implements a dict-like class to query errors by indexes following the structure of + the used schema. + """ tree_type = 'schema' class BaseErrorHandler(object): - """ Base class for all error handlers. - Subclasses are identified as error-handlers with an instance-test. """ + """Base class for all error handlers. + Subclasses are identified as error-handlers with an instance-test.""" def __init__(self, *args, **kwargs): - """ Optionally initialize a new instance. """ + """Optionally initialize a new instance.""" pass def __call__(self, errors): - """ Returns errors in a handler-specific format. + """ + Returns errors in a handler-specific format. :param errors: An object containing the errors. :type errors: :term:`iterable` of @@ -359,11 +372,12 @@ class BaseErrorHandler(object): raise NotImplementedError def __iter__(self): - """ Be a superhero and implement an iterator over errors. """ + """Be a superhero and implement an iterator over errors.""" raise NotImplementedError def add(self, error): - """ Add an error to the errors' container object of a handler. + """ + Add an error to the errors' container object of a handler. :param error: The error to add. :type error: :class:`~cerberus.errors.ValidationError` @@ -371,8 +385,9 @@ class BaseErrorHandler(object): raise NotImplementedError def emit(self, error): - """ Optionally emits an error in the handler's format to a stream. - Or light a LED, or even shut down a power plant. + """ + Optionally emits an error in the handler's format to a stream. Or light a LED, + or even shut down a power plant. :param error: The error to emit. :type error: :class:`~cerberus.errors.ValidationError` @@ -380,14 +395,17 @@ class BaseErrorHandler(object): pass def end(self, validator): - """ Gets called when a validation ends. + """ + Gets called when a validation ends. :param validator: The calling validator. - :type validator: :class:`~cerberus.Validator` """ + :type validator: :class:`~cerberus.Validator` + """ pass def extend(self, errors): - """ Adds all errors to the handler's container object. + """ + Adds all errors to the handler's container object. :param errors: The errors to add. :type errors: :term:`iterable` of @@ -397,7 +415,8 @@ class BaseErrorHandler(object): self.add(error) def start(self, validator): - """ Gets called when a validation starts. + """ + Gets called when a validation starts. :param validator: The calling validator. :type validator: :class:`~cerberus.Validator` @@ -441,9 +460,9 @@ def encode_unicode(f): class BasicErrorHandler(BaseErrorHandler): - """ Models cerberus' legacy. Returns a :class:`dict`. When mangled - through :class:`str` a pretty-formatted representation of that - tree is returned. + """ + Models cerberus' legacy. Returns a :class:`dict`. When mangled through :class:`str` + a pretty-formatted representation of that tree is returned. """ messages = { @@ -532,7 +551,8 @@ class BasicErrorHandler(BaseErrorHandler): ) def _insert_error(self, path, node): - """ Adds an error or sub-tree to :attr:tree. + """ + Adds an error or sub-tree to :attr:tree. :param path: Path to the error. :type path: Tuple of strings and integers. diff --git a/pipenv/vendor/cerberus/platform.py b/pipenv/vendor/cerberus/platform.py index 66b1d5f0..ae229c7b 100644 --- a/pipenv/vendor/cerberus/platform.py +++ b/pipenv/vendor/cerberus/platform.py @@ -2,6 +2,9 @@ import sys +if sys.flags.optimize == 2: + raise RuntimeError("Cerberus can't be run with Python's optimization level 2.") + PYTHON_VERSION = float(sys.version_info[0]) + float(sys.version_info[1]) / 10 diff --git a/pipenv/vendor/cerberus/schema.py b/pipenv/vendor/cerberus/schema.py index 3841384e..da313274 100644 --- a/pipenv/vendor/cerberus/schema.py +++ b/pipenv/vendor/cerberus/schema.py @@ -1,6 +1,5 @@ from __future__ import absolute_import -from copy import copy from warnings import warn from cerberus import errors @@ -25,14 +24,15 @@ class _Abort(Exception): class SchemaError(Exception): - """ Raised when the validation schema is missing, has the wrong format or - contains errors. """ + """ + Raised when the validation schema is missing, has the wrong format or contains + errors.""" pass class DefinitionSchema(MutableMapping): - """ A dict-subclass for caching of validated schemas. """ + """A dict-subclass for caching of validated schemas.""" def __new__(cls, *args, **kwargs): if 'SchemaValidator' not in globals(): @@ -134,7 +134,8 @@ class DefinitionSchema(MutableMapping): @classmethod def _expand_logical_shortcuts(cls, schema): - """ Expand agglutinated rules in a definition-schema. + """ + Expand agglutinated rules in a definition-schema. :param schema: The schema-definition to expand. :return: The expanded schema-definition. @@ -160,8 +161,10 @@ class DefinitionSchema(MutableMapping): return isinstance(schema[field], Mapping) and 'schema' in schema[field] def has_mapping_schema(): - """ Tries to determine heuristically if the schema-constraints are - aimed to mappings. """ + """ + Tries to determine heuristically if the schema-constraints are aimed to + mappings. + """ try: return all( isinstance(x, Mapping) for x in schema[field]['schema'].values() @@ -249,12 +252,14 @@ class DefinitionSchema(MutableMapping): self.validation_schema = SchemaValidationSchema(self.validator) def validate(self, schema=None): - """ Validates a schema that defines rules against supported rules. + """ + Validates a schema that defines rules against supported rules. :param schema: The schema to be validated as a legal cerberus schema according to the rules of the assigned Validator object. Raises a :class:`~cerberus.base.SchemaError` when an invalid - schema is encountered. """ + schema is encountered. + """ if schema is None: schema = self.schema _hash = (mapping_hash(schema), mapping_hash(self.validator.types_mapping)) @@ -266,15 +271,17 @@ class DefinitionSchema(MutableMapping): if isinstance(schema, _str_type): schema = self.validator.schema_registry.get(schema, schema) - if schema is None: - raise SchemaError(errors.SCHEMA_ERROR_MISSING) + test_schema = {} + for field, rules in schema.items(): + if isinstance(rules, _str_type): + test_schema[field] = rules_set_registry.get(rules, rules) + else: + test_rules = {} + for rule, constraint in rules.items(): + test_rules[rule.replace(" ", "_")] = constraint + test_schema[field] = test_rules - schema = copy(schema) - for field in schema: - if isinstance(schema[field], _str_type): - schema[field] = rules_set_registry.get(schema[field], schema[field]) - - if not self.schema_validator(schema, normalize=False): + if not self.schema_validator(test_schema, normalize=False): raise SchemaError(self.schema_validator.errors) @@ -303,8 +310,10 @@ class SchemaValidationSchema(UnvalidatedSchema): class SchemaValidatorMixin(object): - """ This validator mixin provides mechanics to validate schemas passed to a Cerberus - validator. """ + """ + This validator mixin provides mechanics to validate schemas passed to a Cerberus + validator. + """ def __init__(self, *args, **kwargs): kwargs.setdefault('known_rules_set_refs', set()) @@ -313,22 +322,22 @@ class SchemaValidatorMixin(object): @property def known_rules_set_refs(self): - """ The encountered references to rules set registry items. """ + """The encountered references to rules set registry items.""" return self._config['known_rules_set_refs'] @property def known_schema_refs(self): - """ The encountered references to schema registry items. """ + """The encountered references to schema registry items.""" return self._config['known_schema_refs'] @property def target_schema(self): - """ The schema that is being validated. """ + """The schema that is being validated.""" return self._config['target_schema'] @property def target_validator(self): - """ The validator whose schema is being validated. """ + """The validator whose schema is being validated.""" return self._config['target_validator'] def _check_with_bulk_schema(self, field, value): @@ -434,7 +443,7 @@ class SchemaValidatorMixin(object): return definition def _validate_logical(self, rule, field, value): - """ {'allowed': ('allof', 'anyof', 'noneof', 'oneof')} """ + """{'allowed': ('allof', 'anyof', 'noneof', 'oneof')}""" if not isinstance(value, Sequence): self._error(field, errors.BAD_TYPE) return @@ -464,59 +473,70 @@ class SchemaValidatorMixin(object): class Registry(object): - """ A registry to store and retrieve schemas and parts of it by a name - that can be used in validation schemas. + """ + A registry to store and retrieve schemas and parts of it by a name that can be used + in validation schemas. :param definitions: Optional, initial definitions. - :type definitions: any :term:`mapping` """ + :type definitions: any :term:`mapping` + """ def __init__(self, definitions={}): self._storage = {} self.extend(definitions) def add(self, name, definition): - """ Register a definition to the registry. Existing definitions are - replaced silently. + """ + Register a definition to the registry. Existing definitions are replaced + silently. :param name: The name which can be used as reference in a validation schema. :type name: :class:`str` :param definition: The definition. - :type definition: any :term:`mapping` """ + :type definition: any :term:`mapping` + """ self._storage[name] = self._expand_definition(definition) def all(self): - """ Returns a :class:`dict` with all registered definitions mapped to - their name. """ + """ + Returns a :class:`dict` with all registered definitions mapped to their name. + """ return self._storage def clear(self): - """ Purge all definitions in the registry. """ + """Purge all definitions in the registry.""" self._storage.clear() def extend(self, definitions): - """ Add several definitions at once. Existing definitions are + """ + Add several definitions at once. Existing definitions are replaced silently. :param definitions: The names and definitions. :type definitions: a :term:`mapping` or an :term:`iterable` with - two-value :class:`tuple` s """ + two-value :class:`tuple` s + """ for name, definition in dict(definitions).items(): self.add(name, definition) def get(self, name, default=None): - """ Retrieve a definition from the registry. + """ + Retrieve a definition from the registry. :param name: The reference that points to the definition. :type name: :class:`str` - :param default: Return value if the reference isn't registered. """ + :param default: Return value if the reference isn't registered. + """ return self._storage.get(name, default) def remove(self, *names): - """ Unregister definitions from the registry. + """ + Unregister definitions from the registry. :param names: The names of the definitions that are to be - unregistered. """ + unregistered. + """ for name in names: self._storage.pop(name, None) diff --git a/pipenv/vendor/cerberus/tests/__init__.py b/pipenv/vendor/cerberus/tests/__init__.py index c014f3b1..7e136cc2 100644 --- a/pipenv/vendor/cerberus/tests/__init__.py +++ b/pipenv/vendor/cerberus/tests/__init__.py @@ -9,8 +9,10 @@ from cerberus.tests.conftest import sample_schema def assert_exception(exception, document={}, schema=None, validator=None, msg=None): - """ Tests whether a specific exception is raised. Optionally also tests - whether the exception message is as expected. """ + """ + Tests whether a specific exception is raised. Optionally also tests whether the + exception message is as expected. + """ if validator is None: validator = Validator() if msg is None: @@ -22,14 +24,12 @@ def assert_exception(exception, document={}, schema=None, validator=None, msg=No def assert_schema_error(*args): - """ Tests whether a validation raises an exception due to a malformed - schema. """ + """Tests whether a validation raises an exception due to a malformed schema.""" assert_exception(SchemaError, *args) def assert_document_error(*args): - """ Tests whether a validation raises an exception due to a malformed - document. """ + """Tests whether a validation raises an exception due to a malformed document.""" assert_exception(DocumentError, *args) @@ -42,7 +42,7 @@ def assert_fail( errors=None, child_errors=None, ): - """ Tests whether a validation fails. """ + """Tests whether a validation fails.""" if validator is None: validator = Validator(sample_schema) result = validator(document, schema, update) @@ -72,7 +72,7 @@ def assert_fail( def assert_success(document, schema=None, validator=None, update=False): - """ Tests whether a validation succeeds. """ + """Tests whether a validation succeeds.""" if validator is None: validator = Validator(sample_schema) result = validator(document, schema, update) diff --git a/pipenv/vendor/cerberus/tests/test_customization.py b/pipenv/vendor/cerberus/tests/test_customization.py index 8bc3f464..1af4b537 100644 --- a/pipenv/vendor/cerberus/tests/test_customization.py +++ b/pipenv/vendor/cerberus/tests/test_customization.py @@ -28,11 +28,12 @@ def test_contextual_data_preservation(): def test_docstring_parsing(): class CustomValidator(cerberus.Validator): def _validate_foo(self, argument, field, value): - """ {'type': 'zap'} """ + """{'type': 'zap'}""" pass def _validate_bar(self, value): - """ Test the barreness of a value. + """ + Test the barreness of a value. The rule's arguments are validated against this schema: {'type': 'boolean'} diff --git a/pipenv/vendor/cerberus/tests/test_errors.py b/pipenv/vendor/cerberus/tests/test_errors.py index d64da78e..2ada7fde 100644 --- a/pipenv/vendor/cerberus/tests/test_errors.py +++ b/pipenv/vendor/cerberus/tests/test_errors.py @@ -101,6 +101,16 @@ def test_error_tree_from_anyof(validator): def test_nested_error_paths(validator): + # interpreters of the same version on some platforms showed different sort results + # over various runs: + def assert_has_all_errors(errors, *ref_errs): + for ref_err in ref_errs: + for error in errors: + if error == ref_err: + break + else: + raise AssertionError + schema = { 'a_dict': { 'keysrules': {'type': 'integer'}, @@ -114,27 +124,27 @@ def test_nested_error_paths(validator): } assert_fail(document, schema, validator=validator) - _det = validator.document_error_tree - _set = validator.schema_error_tree + det = validator.document_error_tree + set = validator.schema_error_tree - assert len(_det.errors) == 0 - assert len(_set.errors) == 0 + assert len(det.errors) == 0 + assert len(set.errors) == 0 - assert len(_det['a_dict'].errors) == 2 - assert len(_set['a_dict'].errors) == 0 + assert len(det['a_dict'].errors) == 2 + assert len(set['a_dict'].errors) == 0 - assert _det['a_dict'][0] is None - assert len(_det['a_dict']['one'].errors) == 1 - assert len(_det['a_dict'][2].errors) == 1 - assert len(_det['a_dict']['three'].errors) == 2 + assert det['a_dict'][0] is None + assert len(det['a_dict']['one'].errors) == 1 + assert len(det['a_dict'][2].errors) == 1 + assert len(det['a_dict']['three'].errors) == 2 - assert len(_set['a_dict']['keysrules'].errors) == 1 - assert len(_set['a_dict']['valuesrules'].errors) == 1 + assert len(set['a_dict']['keysrules'].errors) == 1 + assert len(set['a_dict']['valuesrules'].errors) == 1 - assert len(_set['a_dict']['keysrules']['type'].errors) == 2 - assert len(_set['a_dict']['valuesrules']['regex'].errors) == 2 + assert len(set['a_dict']['keysrules']['type'].errors) == 2 + assert len(set['a_dict']['valuesrules']['regex'].errors) == 2 - _ref_err = ValidationError( + ref_err1 = ValidationError( ('a_dict', 'one'), ('a_dict', 'keysrules', 'type'), errors.BAD_TYPE.code, @@ -143,10 +153,8 @@ def test_nested_error_paths(validator): 'one', (), ) - assert _det['a_dict']['one'].errors[0] == _ref_err - assert _set['a_dict']['keysrules']['type'].errors[0] == _ref_err - _ref_err = ValidationError( + ref_err2 = ValidationError( ('a_dict', 2), ('a_dict', 'valuesrules', 'regex'), errors.REGEX_MISMATCH.code, @@ -155,10 +163,8 @@ def test_nested_error_paths(validator): 'aBc', (), ) - assert _det['a_dict'][2].errors[0] == _ref_err - assert _set['a_dict']['valuesrules']['regex'].errors[0] == _ref_err - _ref_err = ValidationError( + ref_err3 = ValidationError( ('a_dict', 'three'), ('a_dict', 'keysrules', 'type'), errors.BAD_TYPE.code, @@ -167,10 +173,7 @@ def test_nested_error_paths(validator): 'three', (), ) - assert _det['a_dict']['three'].errors[0] == _ref_err - assert _set['a_dict']['keysrules']['type'].errors[1] == _ref_err - - _ref_err = ValidationError( + ref_err4 = ValidationError( ('a_dict', 'three'), ('a_dict', 'valuesrules', 'regex'), errors.REGEX_MISMATCH.code, @@ -179,20 +182,25 @@ def test_nested_error_paths(validator): 'abC', (), ) - assert _det['a_dict']['three'].errors[1] == _ref_err - assert _set['a_dict']['valuesrules']['regex'].errors[1] == _ref_err + assert det['a_dict'][2].errors[0] == ref_err2 + assert det['a_dict']['one'].errors[0] == ref_err1 + assert_has_all_errors(det['a_dict']['three'].errors, ref_err3, ref_err4) + assert_has_all_errors(set['a_dict']['keysrules']['type'].errors, ref_err1, ref_err3) + assert_has_all_errors( + set['a_dict']['valuesrules']['regex'].errors, ref_err2, ref_err4 + ) - assert len(_det['a_list'].errors) == 1 - assert len(_det['a_list'][0].errors) == 1 - assert _det['a_list'][1] is None - assert len(_det['a_list'][2].errors) == 3 - assert len(_set['a_list'].errors) == 0 - assert len(_set['a_list']['schema'].errors) == 1 - assert len(_set['a_list']['schema']['type'].errors) == 1 - assert len(_set['a_list']['schema']['oneof'][0]['regex'].errors) == 1 - assert len(_set['a_list']['schema']['oneof'][1]['regex'].errors) == 1 + assert len(det['a_list'].errors) == 1 + assert len(det['a_list'][0].errors) == 1 + assert det['a_list'][1] is None + assert len(det['a_list'][2].errors) == 3 + assert len(set['a_list'].errors) == 0 + assert len(set['a_list']['schema'].errors) == 1 + assert len(set['a_list']['schema']['type'].errors) == 1 + assert len(set['a_list']['schema']['oneof'][0]['regex'].errors) == 1 + assert len(set['a_list']['schema']['oneof'][1]['regex'].errors) == 1 - _ref_err = ValidationError( + ref_err5 = ValidationError( ('a_list', 0), ('a_list', 'schema', 'type'), errors.BAD_TYPE.code, @@ -201,10 +209,7 @@ def test_nested_error_paths(validator): 0, (), ) - assert _det['a_list'][0].errors[0] == _ref_err - assert _set['a_list']['schema']['type'].errors[0] == _ref_err - - _ref_err = ValidationError( + ref_err6 = ValidationError( ('a_list', 2), ('a_list', 'schema', 'oneof'), errors.ONEOF.code, @@ -213,10 +218,7 @@ def test_nested_error_paths(validator): 'abC', (), ) - assert _det['a_list'][2].errors[0] == _ref_err - assert _set['a_list']['schema']['oneof'].errors[0] == _ref_err - - _ref_err = ValidationError( + ref_err7 = ValidationError( ('a_list', 2), ('a_list', 'schema', 'oneof', 0, 'regex'), errors.REGEX_MISMATCH.code, @@ -225,10 +227,7 @@ def test_nested_error_paths(validator): 'abC', (), ) - assert _det['a_list'][2].errors[1] == _ref_err - assert _set['a_list']['schema']['oneof'][0]['regex'].errors[0] == _ref_err - - _ref_err = ValidationError( + ref_err8 = ValidationError( ('a_list', 2), ('a_list', 'schema', 'oneof', 1, 'regex'), errors.REGEX_MISMATCH.code, @@ -237,8 +236,38 @@ def test_nested_error_paths(validator): 'abC', (), ) - assert _det['a_list'][2].errors[2] == _ref_err - assert _set['a_list']['schema']['oneof'][1]['regex'].errors[0] == _ref_err + + assert det['a_list'][0].errors[0] == ref_err5 + assert_has_all_errors(det['a_list'][2].errors, ref_err6, ref_err7, ref_err8) + assert set['a_list']['schema']['oneof'].errors[0] == ref_err6 + assert set['a_list']['schema']['oneof'][0]['regex'].errors[0] == ref_err7 + assert set['a_list']['schema']['oneof'][1]['regex'].errors[0] == ref_err8 + assert set['a_list']['schema']['type'].errors[0] == ref_err5 + + +def test_path_resolution_for_registry_references(): + class CustomValidator(Validator): + def _normalize_coerce_custom(self, value): + raise Exception("Failed coerce") + + validator = CustomValidator() + validator.schema_registry.add( + "schema1", {"child": {"type": "boolean", "coerce": "custom"}} + ) + validator.schema = {"parent": {"schema": "schema1"}} + validator.validate({"parent": {"child": "["}}) + + expected = { + 'parent': [ + { + 'child': [ + "must be of boolean type", + "field 'child' cannot be coerced: Failed coerce", + ] + } + ] + } + assert validator.errors == expected def test_queries(): diff --git a/pipenv/vendor/cerberus/tests/test_schema.py b/pipenv/vendor/cerberus/tests/test_schema.py index 509f446f..28b5dd34 100644 --- a/pipenv/vendor/cerberus/tests/test_schema.py +++ b/pipenv/vendor/cerberus/tests/test_schema.py @@ -88,7 +88,7 @@ def test_validated_schema_cache(): v = Validator({'foozifix': {'coerce': int}}) assert len(v._valid_schemas) == cache_size - max_cache_size = 161 + max_cache_size = 163 assert cache_size <= max_cache_size, ( "There's an unexpected high amount (%s) of cached valid " "definition schemas. Unless you added further tests, " @@ -172,3 +172,7 @@ def test_anyof_check_with(): assert validator.schema == { 'field': {'anyof': [{'check_with': foo}, {'check_with': bar}]} } + + +def test_rulename_space_is_normalized(): + Validator(schema={"field": {"default setter": lambda x: x, "type": "string"}}) diff --git a/pipenv/vendor/cerberus/tests/test_validation.py b/pipenv/vendor/cerberus/tests/test_validation.py index ead79517..ae5f5444 100644 --- a/pipenv/vendor/cerberus/tests/test_validation.py +++ b/pipenv/vendor/cerberus/tests/test_validation.py @@ -479,7 +479,7 @@ def test_array_unallowed(): (field, 'allowed'), errors.UNALLOWED_VALUES, ['agent', 'client', 'vendor'], - ['profit'], + (('profit',),), ), ) @@ -596,6 +596,11 @@ def test_regex(validator): ) +def test_regex_with_flag(): + assert_success({"item": "hOly grAil"}, {"item": {"regex": "(?i)holy grail"}}) + assert_fail({"item": "hOly grAil"}, {"item": {"regex": "holy grail"}}) + + def test_a_list_of_dicts(): assert_success( { @@ -742,7 +747,7 @@ def test_custom_datatype(): def test_custom_datatype_rule(): class MyValidator(Validator): def _validate_min_number(self, min_number, field, value): - """ {'type': 'number'} """ + """{'type': 'number'}""" if value < min_number: self._error(field, 'Below the min') @@ -769,7 +774,7 @@ def test_custom_datatype_rule(): def test_custom_validator(): class MyValidator(Validator): def _validate_isodd(self, isodd, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" if isodd and not bool(value & 1): self._error(field, 'Not an odd number') @@ -1114,15 +1119,15 @@ def test_options_passed_to_nested_validators(validator): def test_self_root_document(): - """ Make sure self.root_document is always the root document. - See: + """ + Make sure self.root_document is always the root document. See: * https://github.com/pyeve/cerberus/pull/42 * https://github.com/pyeve/eve/issues/295 """ class MyValidator(Validator): def _validate_root_doc(self, root_doc, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" if 'sub' not in self.root_document or len(self.root_document['sub']) != 2: self._error(field, 'self.context is not the root doc!') @@ -1251,8 +1256,10 @@ def test_unicode_allowed(): @mark.skipif(sys.version_info[0] < 3, reason='requires python 3.x') def test_unicode_allowed_py3(): - """ All strings are unicode in Python 3.x. Input doc and schema - have equal strings and validation yield success.""" + """ + All strings are unicode in Python 3.x. Input doc and schema have equal strings and + validation yield success. + """ # issue 280 doc = {'letters': u'♄εℓł☺'} @@ -1262,9 +1269,11 @@ def test_unicode_allowed_py3(): @mark.skipif(sys.version_info[0] > 2, reason='requires python 2.x') def test_unicode_allowed_py2(): - """ Python 2.x encodes value of allowed using default encoding if - the string includes characters outside ASCII range. Produced string - does not match input which is an unicode string.""" + """ + Python 2.x encodes value of allowed using default encoding if the string includes + characters outside ASCII range. Produced string does not match input which is an + unicode string. + """ # issue 280 doc = {'letters': u'♄εℓł☺'} @@ -1646,7 +1655,7 @@ def test_dependencies_on_boolean_field_with_value_in_list(): def test_document_path(): class DocumentPathTester(Validator): def _validate_trail(self, constraint, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" test_doc = self.root_document for crumb in self.document_path: test_doc = test_doc[crumb] @@ -1946,3 +1955,21 @@ def test_require_all_and_exclude(): assert_success({'foo': 'value'}, schema, validator) assert_success({'bar': 'value'}, schema, validator) assert_fail({'foo': 'value', 'bar': 'value'}, schema, validator) + + +def test_allowed_when_passing_list_of_dicts(): + # https://github.com/pyeve/cerberus/issues/524 + doc = {'letters': [{'some': 'dict'}]} + schema = {'letters': {'type': 'list', 'allowed': ['a', 'b', 'c']}} + + assert_fail( + doc, + schema, + error=( + 'letters', + ('letters', 'allowed'), + errors.UNALLOWED_VALUES, + ['a', 'b', 'c'], + (({'some': 'dict'},),), + ), + ) diff --git a/pipenv/vendor/cerberus/utils.py b/pipenv/vendor/cerberus/utils.py index 5a015d64..f84b0966 100644 --- a/pipenv/vendor/cerberus/utils.py +++ b/pipenv/vendor/cerberus/utils.py @@ -59,10 +59,11 @@ def mapping_hash(schema): def mapping_to_frozenset(mapping): - """ Be aware that this treats any sequence type with the equal members as - equal. As it is used to identify equality of schemas, this can be - considered okay as definitions are semantically equal regardless the - container type. """ + """ + Be aware that this treats any sequence type with the equal members as equal. As it + is used to identify equality of schemas, this can be considered okay as definitions + are semantically equal regardless the container type. + """ aggregation = {} @@ -102,9 +103,10 @@ class readonly_classproperty(property): def validator_factory(name, bases=None, namespace={}): - """ Dynamically create a :class:`~cerberus.Validator` subclass. - Docstrings of mixin-classes will be added to the resulting - class' one if ``__doc__`` is not in :obj:`namespace`. + """ + Dynamically create a :class:`~cerberus.Validator` subclass. + Docstrings of mixin-classes will be added to the resulting class' one if ``__doc__`` + is not in :obj:`namespace`. :param name: The name of the new class. :type name: :class:`str` diff --git a/pipenv/vendor/cerberus/validator.py b/pipenv/vendor/cerberus/validator.py index ed1c1536..7d50b2da 100644 --- a/pipenv/vendor/cerberus/validator.py +++ b/pipenv/vendor/cerberus/validator.py @@ -52,20 +52,23 @@ def dummy_for_rule_validation(rule_constraints): class DocumentError(Exception): - """ Raised when the target document is missing or has the wrong format """ + """Raised when the target document is missing or has the wrong format""" pass class _SchemaRuleTypeError(Exception): - """ Raised when a schema (list) validation encounters a mapping. - Not supposed to be used outside this module. """ + """ + Raised when a schema (list) validation encounters a mapping. + Not supposed to be used outside this module. + """ pass class BareValidator(object): - """ Validator class. Normalizes and/or validates any mapping against a + """ + Validator class. Normalizes and/or validates any mapping against a validation-schema which is provided as an argument at class instantiation or upon calling the :meth:`~cerberus.Validator.validate`, :meth:`~cerberus.Validator.validated` or @@ -112,12 +115,16 @@ class BareValidator(object): """ # noqa: E501 mandatory_validations = ('nullable',) - """ Rules that are evaluated on any field, regardless whether defined in - the schema or not. - Type: :class:`tuple` """ + """ + Rules that are evaluated on any field, regardless whether defined in the schema or + not. + Type: :class:`tuple` + """ priority_validations = ('nullable', 'readonly', 'type', 'empty') - """ Rules that will be processed in that order before any other. - Type: :class:`tuple` """ + """ + Rules that will be processed in that order before any other. + Type: :class:`tuple` + """ types_mapping = { 'binary': TypeDefinition('binary', (bytes, bytearray), ()), 'boolean': TypeDefinition('boolean', (bool,), ()), @@ -130,16 +137,21 @@ class BareValidator(object): 'list': TypeDefinition('list', (Sequence,), (_str_type,)), 'number': TypeDefinition('number', (_int_types, float), (bool,)), 'set': TypeDefinition('set', (set,), ()), - 'string': TypeDefinition('string', (_str_type), ()), + 'string': TypeDefinition('string', (_str_type,), ()), } - """ This mapping holds all available constraints for the type rule and - their assigned :class:`~cerberus.TypeDefinition`. """ + """ + This mapping holds all available constraints for the type rule and their assigned + :class:`~cerberus.TypeDefinition`. + """ _valid_schemas = set() - """ A :class:`set` of hashes derived from validation schemas that are - legit for a particular ``Validator`` class. """ + """ + A :class:`set` of hashes derived from validation schemas that are legit for a + particular ``Validator`` class. + """ def __init__(self, *args, **kwargs): - """ The arguments will be treated as with this signature: + """ + The arguments will be treated as with this signature: __init__(self, schema=None, ignore_none_values=False, allow_unknown=False, require_all=False, @@ -205,7 +217,7 @@ class BareValidator(object): raise RuntimeError('Invalid error_handler.') def __store_config(self, args, kwargs): - """ Assign args to kwargs and store configuration. """ + """Assign args to kwargs and store configuration.""" signature = ( 'schema', 'ignore_none_values', @@ -226,11 +238,12 @@ class BareValidator(object): @classmethod def clear_caches(cls): - """ Purge the cache of known valid schemas. """ + """Purge the cache of known valid schemas.""" cls._valid_schemas.clear() def _error(self, *args): - """ Creates and adds one or multiple errors. + """ + Creates and adds one or multiple errors. :param args: Accepts different argument's signatures. @@ -290,15 +303,17 @@ class BareValidator(object): if not rule: constraint = None else: - field_definitions = self._resolve_rules_set(self.schema[field]) + rules_set = self._resolve_rules_set( + self._resolve_schema(self.schema)[field] + ) if rule == 'nullable': - constraint = field_definitions.get(rule, False) + constraint = rules_set.get(rule, False) elif rule == 'required': - constraint = field_definitions.get(rule, self.require_all) - if rule not in field_definitions: + constraint = rules_set.get(rule, self.require_all) + if rule not in rules_set: schema_path = "__require_all__" else: - constraint = field_definitions[rule] + constraint = rules_set[rule] value = self.document.get(field) @@ -308,9 +323,10 @@ class BareValidator(object): self._error([self.recent_error]) def _get_child_validator(self, document_crumb=None, schema_crumb=None, **kwargs): - """ Creates a new instance of Validator-(sub-)class. All initial - parameters of the parent are passed to the initialization, unless - a parameter is given as an explicit *keyword*-parameter. + """ + Creates a new instance of Validator-(sub-)class. All initial parameters of the + parent are passed to the initialization, unless a parameter is given as an + explicit *keyword*-parameter. :param document_crumb: Extends the :attr:`~cerberus.Validator.document_path` @@ -364,8 +380,8 @@ class BareValidator(object): return result def _drop_nodes_from_errorpaths(self, _errors, dp_items, sp_items): - """ Removes nodes by index from an errorpath, relatively to the - basepaths of self. + """ + Removes nodes by index from an errorpath, relatively to the basepaths of self. :param errors: A list of :class:`errors.ValidationError` instances. :param dp_items: A list of integers, pointing at the nodes to drop from @@ -387,8 +403,9 @@ class BareValidator(object): self._drop_nodes_from_errorpaths(error.child_errors, dp_items, sp_items) def _lookup_field(self, path): - """ Searches for a field as defined by path. This method is used by the - ``dependency`` evaluation logic. + """ + Searches for a field as defined by path. This method is used by the + ``dependency`` evaluation logic. :param path: Path elements are separated by a ``.``. A leading ``^`` indicates that the path relates to the document root, @@ -433,11 +450,12 @@ class BareValidator(object): @property def allow_unknown(self): - """ If ``True`` unknown fields that are not defined in the schema will - be ignored. If a mapping with a validation schema is given, any - undefined field will be validated against its rules. - Also see :ref:`allowing-the-unknown`. - Type: :class:`bool` or any :term:`mapping` """ + """ + If ``True`` unknown fields that are not defined in the schema will be ignored. + If a mapping with a validation schema is given, any undefined field will be + validated against its rules. Also see :ref:`allowing-the-unknown`. + Type: :class:`bool` or any :term:`mapping` + """ return self._config.get('allow_unknown', False) @allow_unknown.setter @@ -448,9 +466,10 @@ class BareValidator(object): @property def require_all(self): - """ If ``True`` known fields that are defined in the schema will - be required. - Type: :class:`bool` """ + """ + If ``True`` known fields that are defined in the schema will be required. + Type: :class:`bool` + """ return self._config.get('require_all', False) @require_all.setter @@ -459,14 +478,18 @@ class BareValidator(object): @property def errors(self): - """ The errors of the last processing formatted by the handler that is - bound to :attr:`~cerberus.Validator.error_handler`. """ + """ + The errors of the last processing formatted by the handler that is bound to + :attr:`~cerberus.Validator.error_handler`. + """ return self.error_handler(self._errors) @property def ignore_none_values(self): - """ Whether to not process :obj:`None`-values in a document or not. - Type: :class:`bool` """ + """ + Whether to not process :obj:`None`-values in a document or not. + Type: :class:`bool` + """ return self._config.get('ignore_none_values', False) @ignore_none_values.setter @@ -475,14 +498,16 @@ class BareValidator(object): @property def is_child(self): - """ ``True`` for child-validators obtained with + """ + ``True`` for child-validators obtained with :meth:`~cerberus.Validator._get_child_validator`. - Type: :class:`bool` """ + Type: :class:`bool` + """ return self._config.get('is_child', False) @property def _is_normalized(self): - """ ``True`` if the document is already normalized. """ + """``True`` if the document is already normalized.""" return self._config.get('_is_normalized', False) @_is_normalized.setter @@ -491,9 +516,12 @@ class BareValidator(object): @property def purge_unknown(self): - """ If ``True``, unknown fields will be deleted from the document - unless a validation is called with disabled normalization. - Also see :ref:`purging-unknown-fields`. Type: :class:`bool` """ + """ + If ``True``, unknown fields will be deleted from the document unless a + validation is called with disabled normalization. Also see + :ref:`purging-unknown-fields`. + Type: :class:`bool` + """ return self._config.get('purge_unknown', False) @purge_unknown.setter @@ -502,9 +530,11 @@ class BareValidator(object): @property def purge_readonly(self): - """ If ``True``, fields declared as readonly will be deleted from the - document unless a validation is called with disabled normalization. - Type: :class:`bool` """ + """ + If ``True``, fields declared as readonly will be deleted from the document + unless a validation is called with disabled normalization. + Type: :class:`bool` + """ return self._config.get('purge_readonly', False) @purge_readonly.setter @@ -513,26 +543,34 @@ class BareValidator(object): @property def root_allow_unknown(self): - """ The :attr:`~cerberus.Validator.allow_unknown` attribute of the - first level ancestor of a child validator. """ + """ + The :attr:`~cerberus.Validator.allow_unknown` attribute of the first level + ancestor of a child validator. + """ return self._config.get('root_allow_unknown', self.allow_unknown) @property def root_require_all(self): - """ The :attr:`~cerberus.Validator.require_all` attribute of - the first level ancestor of a child validator. """ + """ + The :attr:`~cerberus.Validator.require_all` attribute of the first level + ancestor of a child validator. + """ return self._config.get('root_require_all', self.require_all) @property def root_document(self): - """ The :attr:`~cerberus.Validator.document` attribute of the - first level ancestor of a child validator. """ + """ + The :attr:`~cerberus.Validator.document` attribute of the first level ancestor + of a child validator. + """ return self._config.get('root_document', self.document) @property def rules_set_registry(self): - """ The registry that holds referenced rules sets. - Type: :class:`~cerberus.Registry` """ + """ + The registry that holds referenced rules sets. + Type: :class:`~cerberus.Registry` + """ return self._config.get('rules_set_registry', rules_set_registry) @rules_set_registry.setter @@ -541,15 +579,19 @@ class BareValidator(object): @property def root_schema(self): - """ The :attr:`~cerberus.Validator.schema` attribute of the - first level ancestor of a child validator. """ + """ + The :attr:`~cerberus.Validator.schema` attribute of the first level ancestor of + a child validator. + """ return self._config.get('root_schema', self.schema) @property def schema(self): - """ The validation schema of a validator. When a schema is passed to - a method, it replaces this attribute. - Type: any :term:`mapping` or :obj:`None` """ + """ + The validation schema of a validator. When a schema is passed to a method, it + replaces this attribute. + Type: any :term:`mapping` or :obj:`None` + """ return self._schema @schema.setter @@ -563,8 +605,10 @@ class BareValidator(object): @property def schema_registry(self): - """ The registry that holds referenced schemas. - Type: :class:`~cerberus.Registry` """ + """ + The registry that holds referenced schemas. + Type: :class:`~cerberus.Registry` + """ return self._config.get('schema_registry', schema_registry) @schema_registry.setter @@ -575,8 +619,10 @@ class BareValidator(object): # in the API docs @readonly_classproperty def types(cls): - """ The constraints that can be used for the 'type' rule. - Type: A tuple of strings. """ + """ + The constraints that can be used for the 'type' rule. + Type: A tuple of strings. + """ redundant_types = set(cls.types_mapping) & set(cls._types_from_methods) if redundant_types: warn( @@ -611,9 +657,10 @@ class BareValidator(object): self.error_handler.start(self) def _drop_remaining_rules(self, *rules): - """ Drops rules from the queue of the rules that still need to be - evaluated for the currently processed field. - If no arguments are given, the whole queue is emptied. + """ + Drops rules from the queue of the rules that still need to be evaluated for the + currently processed field. If no arguments are given, the whole queue is + emptied. """ if rules: for rule in rules: @@ -627,8 +674,8 @@ class BareValidator(object): # # Normalizing def normalized(self, document, schema=None, always_return_document=False): - """ Returns the document normalized according to the specified rules - of a schema. + """ + Returns the document normalized according to the specified rules of a schema. :param document: The document to normalize. :type document: any :term:`mapping` @@ -673,13 +720,15 @@ class BareValidator(object): return mapping def _normalize_coerce(self, mapping, schema): - """ {'oneof': [ - {'type': 'callable'}, - {'type': 'list', - 'schema': {'oneof': [{'type': 'callable'}, - {'type': 'string'}]}}, - {'type': 'string'} - ]} """ + """ + {'oneof': [ + {'type': 'callable'}, + {'type': 'list', + 'schema': {'oneof': [{'type': 'callable'}, + {'type': 'string'}]}}, + {'type': 'string'} + ]} + """ error = errors.COERCION_FAILED for field in mapping: @@ -853,7 +902,7 @@ class BareValidator(object): @staticmethod def _normalize_purge_unknown(mapping, schema): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" for field in [x for x in mapping if x not in schema]: mapping.pop(field) return mapping @@ -873,19 +922,21 @@ class BareValidator(object): return mapping def _normalize_rename(self, mapping, schema, field): - """ {'type': 'hashable'} """ + """{'type': 'hashable'}""" if 'rename' in schema[field]: mapping[schema[field]['rename']] = mapping[field] del mapping[field] def _normalize_rename_handler(self, mapping, schema, field): - """ {'oneof': [ - {'type': 'callable'}, - {'type': 'list', - 'schema': {'oneof': [{'type': 'callable'}, - {'type': 'string'}]}}, - {'type': 'string'} - ]} """ + """ + {'oneof': [ + {'type': 'callable'}, + {'type': 'list', + 'schema': {'oneof': [{'type': 'callable'}, + {'type': 'string'}]}}, + {'type': 'string'} + ]} + """ if 'rename_handler' not in schema[field]: return new_name = self.__normalize_coerce( @@ -947,14 +998,16 @@ class BareValidator(object): known_fields_states.add(fields_processing_state) def _normalize_default(self, mapping, schema, field): - """ {'nullable': True} """ + """{'nullable': True}""" mapping[field] = schema[field]['default'] def _normalize_default_setter(self, mapping, schema, field): - """ {'oneof': [ - {'type': 'callable'}, - {'type': 'string'} - ]} """ + """ + {'oneof': [ + {'type': 'callable'}, + {'type': 'string'} + ]} + """ if 'default_setter' in schema[field]: setter = schema[field]['default_setter'] if isinstance(setter, _str_type): @@ -964,8 +1017,8 @@ class BareValidator(object): # # Validating def validate(self, document, schema=None, update=False, normalize=True): - """ Normalizes and validates a mapping against a validation-schema of - defined rules. + """ + Normalizes and validates a mapping against a validation-schema of defined rules. :param document: The document to normalize. :type document: any :term:`mapping` @@ -1008,9 +1061,10 @@ class BareValidator(object): __call__ = validate def validated(self, *args, **kwargs): - """ Wrapper around :meth:`~cerberus.Validator.validate` that returns - the normalized and validated document or :obj:`None` if validation - failed. """ + """ + Wrapper around :meth:`~cerberus.Validator.validate` that returns the normalized + and validated document or :obj:`None` if validation failed. + """ always_return_document = kwargs.pop('always_return_document', False) self.validate(*args, **kwargs) if self._errors and not always_return_document: @@ -1034,7 +1088,7 @@ class BareValidator(object): self._error(field, errors.UNKNOWN_FIELD) def __validate_definitions(self, definitions, field): - """ Validate a field's value against its defined rules. """ + """Validate a field's value against its defined rules.""" def validate_rule(rule): validator = self.__get_rule_handler('validate', rule) @@ -1082,23 +1136,25 @@ class BareValidator(object): ) def _validate_allowed(self, allowed_values, field, value): - """ {'type': 'container'} """ + """{'type': 'container'}""" if isinstance(value, Iterable) and not isinstance(value, _str_type): - unallowed = set(value) - set(allowed_values) + unallowed = tuple(x for x in value if x not in allowed_values) if unallowed: - self._error(field, errors.UNALLOWED_VALUES, list(unallowed)) + self._error(field, errors.UNALLOWED_VALUES, unallowed) else: if value not in allowed_values: self._error(field, errors.UNALLOWED_VALUE, value) def _validate_check_with(self, checks, field, value): - """ {'oneof': [ - {'type': 'callable'}, - {'type': 'list', - 'schema': {'oneof': [{'type': 'callable'}, - {'type': 'string'}]}}, - {'type': 'string'} - ]} """ + """ + {'oneof': [ + {'type': 'callable'}, + {'type': 'list', + 'schema': {'oneof': [{'type': 'callable'}, + {'type': 'string'}]}}, + {'type': 'string'} + ]} + """ if isinstance(checks, _str_type): try: value_checker = self.__get_rule_handler('check_with', checks) @@ -1118,7 +1174,7 @@ class BareValidator(object): checks(field, value, self._error) def _validate_contains(self, expected_values, field, value): - """ {'empty': False } """ + """{'empty': False }""" if not isinstance(value, Iterable): return @@ -1134,8 +1190,7 @@ class BareValidator(object): self._error(field, errors.MISSING_MEMBERS, missing_values) def _validate_dependencies(self, dependencies, field, value): - """ {'type': ('dict', 'hashable', 'list'), - 'check_with': 'dependencies'} """ + """{'type': ('dict', 'hashable', 'list'), 'check_with': 'dependencies'}""" if isinstance(dependencies, _str_type) or not isinstance( dependencies, (Iterable, Mapping) ): @@ -1178,7 +1233,7 @@ class BareValidator(object): self._error(field, errors.DEPENDENCIES_FIELD, dependency) def _validate_empty(self, empty, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" if isinstance(value, Sized) and len(value) == 0: self._drop_remaining_rules( 'allowed', @@ -1193,8 +1248,7 @@ class BareValidator(object): self._error(field, errors.EMPTY_NOT_ALLOWED) def _validate_excludes(self, excluded_fields, field, value): - """ {'type': ('hashable', 'list'), - 'schema': {'type': 'hashable'}} """ + """{'type': ('hashable', 'list'), 'schema': {'type': 'hashable'}}""" if isinstance(excluded_fields, Hashable): excluded_fields = [excluded_fields] @@ -1217,7 +1271,7 @@ class BareValidator(object): self._error(field, errors.EXCLUDES_FIELD, exclusion_str) def _validate_forbidden(self, forbidden_values, field, value): - """ {'type': 'list'} """ + """{'type': 'list'}""" if isinstance(value, Sequence) and not isinstance(value, _str_type): forbidden = set(value) & set(forbidden_values) if forbidden: @@ -1227,7 +1281,7 @@ class BareValidator(object): self._error(field, errors.FORBIDDEN_VALUE, value) def _validate_items(self, items, field, values): - """ {'type': 'list', 'check_with': 'items'} """ + """{'type': 'list', 'check_with': 'items'}""" if len(items) != len(values): self._error(field, errors.ITEMS_LENGTH, len(items), len(values)) else: @@ -1247,8 +1301,10 @@ class BareValidator(object): self._error(field, errors.BAD_ITEMS, validator._errors) def __validate_logical(self, operator, definitions, field, value): - """ Validates value against all definitions and logs errors according - to the operator. """ + """ + Validates value against all definitions and logs errors according to the + operator. + """ valid_counter = 0 _errors = errors.ErrorList() @@ -1272,31 +1328,31 @@ class BareValidator(object): return valid_counter, _errors def _validate_anyof(self, definitions, field, value): - """ {'type': 'list', 'logical': 'anyof'} """ + """{'type': 'list', 'logical': 'anyof'}""" valids, _errors = self.__validate_logical('anyof', definitions, field, value) if valids < 1: self._error(field, errors.ANYOF, _errors, valids, len(definitions)) def _validate_allof(self, definitions, field, value): - """ {'type': 'list', 'logical': 'allof'} """ + """{'type': 'list', 'logical': 'allof'}""" valids, _errors = self.__validate_logical('allof', definitions, field, value) if valids < len(definitions): self._error(field, errors.ALLOF, _errors, valids, len(definitions)) def _validate_noneof(self, definitions, field, value): - """ {'type': 'list', 'logical': 'noneof'} """ + """{'type': 'list', 'logical': 'noneof'}""" valids, _errors = self.__validate_logical('noneof', definitions, field, value) if valids > 0: self._error(field, errors.NONEOF, _errors, valids, len(definitions)) def _validate_oneof(self, definitions, field, value): - """ {'type': 'list', 'logical': 'oneof'} """ + """{'type': 'list', 'logical': 'oneof'}""" valids, _errors = self.__validate_logical('oneof', definitions, field, value) if valids != 1: self._error(field, errors.ONEOF, _errors, valids, len(definitions)) def _validate_max(self, max_value, field, value): - """ {'nullable': False } """ + """{'nullable': False }""" try: if value > max_value: self._error(field, errors.MAX_VALUE) @@ -1304,7 +1360,7 @@ class BareValidator(object): pass def _validate_min(self, min_value, field, value): - """ {'nullable': False } """ + """{'nullable': False }""" try: if value < min_value: self._error(field, errors.MIN_VALUE) @@ -1312,19 +1368,19 @@ class BareValidator(object): pass def _validate_maxlength(self, max_length, field, value): - """ {'type': 'integer'} """ + """{'type': 'integer'}""" if isinstance(value, Iterable) and len(value) > max_length: self._error(field, errors.MAX_LENGTH, len(value)) _validate_meta = dummy_for_rule_validation('') def _validate_minlength(self, min_length, field, value): - """ {'type': 'integer'} """ + """{'type': 'integer'}""" if isinstance(value, Iterable) and len(value) < min_length: self._error(field, errors.MIN_LENGTH, len(value)) def _validate_nullable(self, nullable, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" if value is None: if not nullable: self._error(field, errors.NOT_NULLABLE) @@ -1345,8 +1401,11 @@ class BareValidator(object): ) def _validate_keysrules(self, schema, field, value): - """ {'type': ['dict', 'string'], 'check_with': 'bulk_schema', - 'forbidden': ['rename', 'rename_handler']} """ + """ + {'type': ['dict', 'string'], + 'check_with': 'bulk_schema', + 'forbidden': ['rename', 'rename_handler']} + """ if isinstance(value, Mapping): validator = self._get_child_validator( document_crumb=field, @@ -1358,7 +1417,7 @@ class BareValidator(object): self._error(field, errors.KEYSRULES, validator._errors) def _validate_readonly(self, readonly, field, value): - """ {'type': 'boolean'} """ + """{'type': 'boolean'}""" if readonly: if not self._is_normalized: self._error(field, errors.READONLY_FIELD) @@ -1375,7 +1434,7 @@ class BareValidator(object): self._drop_remaining_rules() def _validate_regex(self, pattern, field, value): - """ {'type': 'string'} """ + """{'type': 'string'}""" if not isinstance(value, _str_type): return if not pattern.endswith('$'): @@ -1389,7 +1448,8 @@ class BareValidator(object): _validate_require_all = dummy_for_rule_validation(""" {'type': 'boolean'} """) def __validate_required_fields(self, document): - """ Validates that required fields are not missing. + """ + Validates that required fields are not missing. :param document: The document being validated. """ @@ -1424,9 +1484,11 @@ class BareValidator(object): self._error(field, errors.REQUIRED_FIELD) def _validate_schema(self, schema, field, value): - """ {'type': ['dict', 'string'], - 'anyof': [{'check_with': 'schema'}, - {'check_with': 'bulk_schema'}]} """ + """ + {'type': ['dict', 'string'], + 'anyof': [{'check_with': 'schema'}, + {'check_with': 'bulk_schema'}]} + """ if schema is None: return @@ -1472,8 +1534,10 @@ class BareValidator(object): self._error(field, errors.SEQUENCE_SCHEMA, validator._errors) def _validate_type(self, data_type, field, value): - """ {'type': ['string', 'list'], - 'check_with': 'type'} """ + """ + {'type': ['string', 'list'], + 'check_with': 'type'} + """ if not data_type: return @@ -1504,8 +1568,11 @@ class BareValidator(object): self._drop_remaining_rules() def _validate_valuesrules(self, schema, field, value): - """ {'type': ['dict', 'string'], 'check_with': 'bulk_schema', - 'forbidden': ['rename', 'rename_handler']} """ + """ + {'type': ['dict', 'string'], + 'check_with': 'bulk_schema', + 'forbidden': ['rename', 'rename_handler']} + """ schema_crumb = (field, 'valuesrules') if isinstance(value, Mapping): validator = self._get_child_validator( @@ -1523,7 +1590,7 @@ RULE_SCHEMA_SEPARATOR = "The rule's arguments are validated against this schema: class InspectedValidator(type): - """ Metaclass for all validators """ + """Metaclass for all validators""" def __new__(cls, *args): if '__doc__' not in args[2]: diff --git a/pipenv/vendor/certifi/LICENSE b/pipenv/vendor/certifi/LICENSE index 802b53ff..c2fda9a2 100644 --- a/pipenv/vendor/certifi/LICENSE +++ b/pipenv/vendor/certifi/LICENSE @@ -1,4 +1,4 @@ -This packge contains a modified version of ca-bundle.crt: +This package contains a modified version of ca-bundle.crt: ca-bundle.crt -- Bundle of CA Root Certificates diff --git a/pipenv/vendor/certifi/__init__.py b/pipenv/vendor/certifi/__init__.py index 4e5133b2..eebdf888 100644 --- a/pipenv/vendor/certifi/__init__.py +++ b/pipenv/vendor/certifi/__init__.py @@ -1,3 +1,3 @@ from .core import contents, where -__version__ = "2020.11.08" +__version__ = "2021.05.30" diff --git a/pipenv/vendor/certifi/cacert.pem b/pipenv/vendor/certifi/cacert.pem index a1072085..96e2fc65 100644 --- a/pipenv/vendor/certifi/cacert.pem +++ b/pipenv/vendor/certifi/cacert.pem @@ -155,112 +155,6 @@ eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m 0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- -# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Global CA O=GeoTrust Inc. -# Label: "GeoTrust Global CA" -# Serial: 144470 -# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5 -# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12 -# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a ------BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc. -# Label: "GeoTrust Universal CA" -# Serial: 1 -# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48 -# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79 -# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12 ------BEGIN CERTIFICATE----- -MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy -c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE -BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 -IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV -VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 -cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT -QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh -F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v -c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w -mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd -VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX -teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ -f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe -Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ -nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY -MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc -aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX -IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn -ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z -uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN -Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja -QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW -koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 -ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt -DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm -bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc. -# Label: "GeoTrust Universal CA 2" -# Serial: 1 -# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7 -# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79 -# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW -MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy -c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD -VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 -c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 -WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG -FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq -XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL -se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb -KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd -IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 -y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt -hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc -QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 -Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV -HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV -HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ -KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z -dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ -L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr -Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo -ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY -T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz -GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m -1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV -OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH -6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX -QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS ------END CERTIFICATE----- - # Issuer: CN=AAA Certificate Services O=Comodo CA Limited # Subject: CN=AAA Certificate Services O=Comodo CA Limited # Label: "Comodo AAA Services root" @@ -294,48 +188,6 @@ l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- -# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority -# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority -# Label: "QuoVadis Root CA" -# Serial: 985026699 -# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24 -# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9 -# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73 ------BEGIN CERTIFICATE----- -MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC -TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz -MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw -IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR -dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp -li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D -rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ -WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug -F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU -xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC -Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv -dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw -ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl -IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh -c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy -ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh -Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI -KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T -KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq -y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p -dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD -VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk -fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 -7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R -cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y -mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW -xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK -SnQ2+Q== ------END CERTIFICATE----- - # Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Label: "QuoVadis Root CA 2" @@ -451,33 +303,6 @@ JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== -----END CERTIFICATE----- -# Issuer: CN=Sonera Class2 CA O=Sonera -# Subject: CN=Sonera Class2 CA O=Sonera -# Label: "Sonera Class 2 Root CA" -# Serial: 29 -# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb -# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27 -# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27 ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- - # Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com # Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com # Label: "XRamp Global CA Root" @@ -776,104 +601,6 @@ hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- -# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc. -# Label: "GeoTrust Primary Certification Authority" -# Serial: 32798226551256963324313806436981982369 -# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf -# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96 -# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY -MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo -R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx -MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK -Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 -AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA -ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 -7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W -kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI -mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ -KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 -6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl -4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K -oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj -UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU -AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA" -# Serial: 69529181992039203566298953787712940909 -# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12 -# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81 -# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB -qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV -BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw -NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j -LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG -A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl -IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs -W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta -3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk -6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 -Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J -NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP -r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU -DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz -YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX -xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 -/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ -LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 -jVaMaA== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G5" -# Serial: 33037644167568058970164719475676101450 -# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c -# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5 -# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB -yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW -ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 -aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 -nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex -t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz -SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG -BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ -rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ -NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E -BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH -BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy -aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv -MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE -p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y -5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK -WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ -4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N -hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq ------END CERTIFICATE----- - # Issuer: CN=SecureTrust CA O=SecureTrust Corporation # Subject: CN=SecureTrust CA O=SecureTrust Corporation # Label: "SecureTrust CA" @@ -1151,185 +878,6 @@ i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 9u6wWk5JRFRYX0KD -----END CERTIFICATE----- -# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G3" -# Serial: 28809105769928564313984085209975885599 -# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05 -# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd -# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4 ------BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB -mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT -MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s -eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv -cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ -BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg -MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 -BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg -LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz -+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm -hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn -5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W -JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL -DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC -huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw -HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB -AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB -zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN -kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD -AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH -SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G -spki4cErx5z481+oghLrGREt ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G2" -# Serial: 71758320672825410020661621085256472406 -# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f -# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12 -# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57 ------BEGIN CERTIFICATE----- -MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp -IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi -BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw -MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh -d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig -YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v -dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ -BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 -papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E -BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K -DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 -KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox -XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== ------END CERTIFICATE----- - -# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only -# Label: "thawte Primary Root CA - G3" -# Serial: 127614157056681299805556476275995414779 -# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31 -# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2 -# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c ------BEGIN CERTIFICATE----- -MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB -rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf -Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw -MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV -BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa -Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl -LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u -MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl -ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm -gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 -YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf -b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 -9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S -zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk -OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV -HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA -2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW -oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu -t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c -KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM -m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu -MdRAGmI0Nj81Aa6sY6A= ------END CERTIFICATE----- - -# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only -# Label: "GeoTrust Primary Certification Authority - G2" -# Serial: 80682863203381065782177908751794619243 -# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a -# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0 -# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66 ------BEGIN CERTIFICATE----- -MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL -MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj -KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 -MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 -eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV -BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw -NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV -BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH -MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL -So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal -tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO -BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG -CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT -qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz -rD6ogRLQy7rQkgu2npaqBA+K ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Universal Root Certification Authority" -# Serial: 85209574734084581917763752644031726877 -# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19 -# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54 -# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- - -# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only -# Label: "VeriSign Class 3 Public Primary Certification Authority - G4" -# Serial: 63143484348153506665311985501458640051 -# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41 -# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a -# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79 ------BEGIN CERTIFICATE----- -MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL -MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW -ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln -biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp -U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y -aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp -U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg -SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln -biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm -GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve -fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw -AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ -aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj -aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW -kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC -4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga -FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== ------END CERTIFICATE----- - # Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) # Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) # Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" @@ -1565,105 +1113,6 @@ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- -# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. -# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A. -# Label: "Chambers of Commerce Root - 2008" -# Serial: 11806822484801597146 -# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7 -# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c -# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0 ------BEGIN CERTIFICATE----- -MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz -IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz -MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj -dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw -EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp -MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G -CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 -28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq -VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q -DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR -5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL -ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a -Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl -UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s -+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 -Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj -ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx -hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV -HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 -+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN -YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t -L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy -ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt -IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV -HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w -DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW -PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF -5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 -glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH -FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 -pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD -xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG -tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq -jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De -fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg -OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ -d0jQ ------END CERTIFICATE----- - -# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. -# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A. -# Label: "Global Chambersign Root - 2008" -# Serial: 14541511773111788494 -# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3 -# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c -# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx -MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy -cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG -A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl -BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed -KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 -G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 -zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 -ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG -HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 -Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V -yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e -beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r -6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog -zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW -BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr -ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp -ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk -cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt -YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC -CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow -KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI -hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ -UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz -X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x -fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz -a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd -Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd -SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O -AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso -M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge -v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- - # Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. # Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. # Label: "Go Daddy Root Certificate Authority - G2" @@ -2075,35 +1524,6 @@ LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- -# Issuer: O=Trustis Limited OU=Trustis FPS Root CA -# Subject: O=Trustis Limited OU=Trustis FPS Root CA -# Label: "Trustis FPS Root CA" -# Serial: 36053640375399034304724988975563710553 -# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d -# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04 -# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d ------BEGIN CERTIFICATE----- -MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL -ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx -MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc -MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ -AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH -iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj -vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA -0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB -OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ -BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E -FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 -GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW -zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 -1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE -f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F -jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN -ZetX2fNXlrtIzYE= ------END CERTIFICATE----- - # Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 # Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 # Label: "Buypass Class 2 Root CA" @@ -2965,46 +2385,6 @@ KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg xwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- -# Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden -# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden -# Label: "Staat der Nederlanden Root CA - G3" -# Serial: 10003001 -# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37 -# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc -# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28 ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO -TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh -dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX -DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl -ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv -b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP -cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW -IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX -xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy -KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR -9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az -5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 -6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 -Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP -bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt -BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt -XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF -MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd -INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD -U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp -LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 -Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp -gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh -/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw -0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A -fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq -4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR -1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ -QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM -94B7IWcnMFk= ------END CERTIFICATE----- - # Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden # Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden # Label: "Staat der Nederlanden EV Root CA" @@ -4604,3 +3984,274 @@ AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu Sw== -----END CERTIFICATE----- + +# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Label: "NAVER Global Root Certification Authority" +# Serial: 9013692873798656336226253319739695165984492813 +# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b +# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 +# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- + +# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" +# Serial: 131542671362353147877283741781055151509 +# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb +# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a +# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Label: "GlobalSign Root R46" +# Serial: 1552617688466950547958867513931858518042577 +# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef +# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 +# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Label: "GlobalSign Root E46" +# Serial: 1552617690338932563915843282459653771421763 +# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f +# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 +# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Label: "GLOBALTRUST 2020" +# Serial: 109160994242082918454945253 +# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8 +# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2 +# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Label: "ANF Secure Server Root CA" +# Serial: 996390341000653745 +# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 +# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 +# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum EC-384 CA" +# Serial: 160250656287871593594747141429395092468 +# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 +# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed +# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Root CA" +# Serial: 40870380103424195783807378461123655149 +# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 +# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 +# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/pipenv/vendor/chardet/__init__.py b/pipenv/vendor/chardet/__init__.py index 0f9f820e..80ad2546 100644 --- a/pipenv/vendor/chardet/__init__.py +++ b/pipenv/vendor/chardet/__init__.py @@ -16,11 +16,14 @@ ######################### END LICENSE BLOCK ######################### -from .compat import PY2, PY3 from .universaldetector import UniversalDetector +from .enums import InputState from .version import __version__, VERSION +__all__ = ['UniversalDetector', 'detect', 'detect_all', '__version__', 'VERSION'] + + def detect(byte_str): """ Detect the encoding of the given byte string. @@ -31,9 +34,50 @@ def detect(byte_str): if not isinstance(byte_str, bytearray): if not isinstance(byte_str, bytes): raise TypeError('Expected object of type bytes or bytearray, got: ' - '{0}'.format(type(byte_str))) + '{}'.format(type(byte_str))) else: byte_str = bytearray(byte_str) detector = UniversalDetector() detector.feed(byte_str) return detector.close() + + +def detect_all(byte_str): + """ + Detect all the possible encodings of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + + detector = UniversalDetector() + detector.feed(byte_str) + detector.close() + + if detector._input_state == InputState.HIGH_BYTE: + results = [] + for prober in detector._charset_probers: + if prober.get_confidence() > detector.MINIMUM_THRESHOLD: + charset_name = prober.charset_name + lower_charset_name = prober.charset_name.lower() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if detector._has_win_bytes: + charset_name = detector.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + results.append({ + 'encoding': charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language, + }) + if len(results) > 0: + return sorted(results, key=lambda result: -result['confidence']) + + return [detector.result] diff --git a/pipenv/vendor/chardet/charsetgroupprober.py b/pipenv/vendor/chardet/charsetgroupprober.py index 8b3738ef..5812cef0 100644 --- a/pipenv/vendor/chardet/charsetgroupprober.py +++ b/pipenv/vendor/chardet/charsetgroupprober.py @@ -73,6 +73,7 @@ class CharSetGroupProber(CharSetProber): continue if state == ProbingState.FOUND_IT: self._best_guess_prober = prober + self._state = ProbingState.FOUND_IT return self.state elif state == ProbingState.NOT_ME: prober.active = False diff --git a/pipenv/vendor/chardet/cli/chardetect.py b/pipenv/vendor/chardet/cli/chardetect.py index f0a4cc5d..e1d8cd69 100644 --- a/pipenv/vendor/chardet/cli/chardetect.py +++ b/pipenv/vendor/chardet/cli/chardetect.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """ Script which takes one or more file paths and reports on their detected encodings @@ -45,10 +44,10 @@ def description_of(lines, name='stdin'): if PY2: name = name.decode(sys.getfilesystemencoding(), 'ignore') if result['encoding']: - return '{0}: {1} with confidence {2}'.format(name, result['encoding'], + return '{}: {} with confidence {}'.format(name, result['encoding'], result['confidence']) else: - return '{0}: no result'.format(name) + return '{}: no result'.format(name) def main(argv=None): @@ -69,7 +68,7 @@ def main(argv=None): type=argparse.FileType('rb'), nargs='*', default=[sys.stdin if PY2 else sys.stdin.buffer]) parser.add_argument('--version', action='version', - version='%(prog)s {0}'.format(__version__)) + version='%(prog)s {}'.format(__version__)) args = parser.parse_args(argv) for f in args.input: diff --git a/pipenv/vendor/chardet/compat.py b/pipenv/vendor/chardet/compat.py index ddd74687..8941572b 100644 --- a/pipenv/vendor/chardet/compat.py +++ b/pipenv/vendor/chardet/compat.py @@ -25,10 +25,12 @@ import sys if sys.version_info < (3, 0): PY2 = True PY3 = False - base_str = (str, unicode) + string_types = (str, unicode) text_type = unicode + iteritems = dict.iteritems else: PY2 = False PY3 = True - base_str = (bytes, str) + string_types = (bytes, str) text_type = str + iteritems = dict.items diff --git a/pipenv/vendor/chardet/langbulgarianmodel.py b/pipenv/vendor/chardet/langbulgarianmodel.py index 2aa4fb2e..561bfd90 100644 --- a/pipenv/vendor/chardet/langbulgarianmodel.py +++ b/pipenv/vendor/chardet/langbulgarianmodel.py @@ -1,228 +1,4650 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +BULGARIAN_LANG_MODEL = { + 63: { # 'e' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 1, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 0, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 45: { # '\xad' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 1, # 'М' + 36: 0, # 'Н' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 31: { # 'А' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 2, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 1, # 'К' + 46: 2, # 'Л' + 38: 1, # 'М' + 36: 2, # 'Н' + 41: 1, # 'О' + 30: 2, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 2, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 0, # 'и' + 26: 2, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 1, # 'у' + 29: 2, # 'ф' + 25: 1, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 32: { # 'Б' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 2, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 2, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 1, # 'Щ' + 61: 2, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 1, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 35: { # 'В' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 0, # 'Х' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 2, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 2, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 43: { # 'Г' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 1, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 37: { # 'Д' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 2, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 2, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 44: { # 'Е' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 2, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 1, # 'М' + 36: 2, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Х' + 53: 2, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 0, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 1, # 'т' + 19: 1, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 55: { # 'Ж' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 47: { # 'З' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 2, # 'Н' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 40: { # 'И' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 2, # 'М' + 36: 2, # 'Н' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 2, # 'Я' + 1: 1, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 3, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 0, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 59: { # 'Й' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 33: { # 'К' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 2, # 'Н' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'р' + 8: 1, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 46: { # 'Л' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 2, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 38: { # 'М' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 2, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 36: { # 'Н' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 2, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 1, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 2, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 41: { # 'О' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 2, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 2, # 'М' + 36: 2, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 0, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 3, # 'т' + 19: 1, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 1, # 'ц' + 21: 2, # 'ч' + 27: 0, # 'ш' + 24: 2, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 30: { # 'П' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 2, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 2, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 39: { # 'Р' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 2, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 1, # 'с' + 5: 0, # 'т' + 19: 3, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 28: { # 'С' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 3, # 'А' + 32: 2, # 'Б' + 35: 2, # 'В' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 3, # 'т' + 19: 2, # 'у' + 29: 2, # 'ф' + 25: 1, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 34: { # 'Т' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 2, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 51: { # 'У' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 2, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 2, # 'с' + 5: 1, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 48: { # 'Ф' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 49: { # 'Х' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 53: { # 'Ц' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 50: { # 'Ч' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'А' + 32: 1, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 1, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 54: { # 'Ш' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 1, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 57: { # 'Щ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 1, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 61: { # 'Ъ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 2, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Х' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 60: { # 'Ю' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 1, # 'Б' + 35: 0, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 1, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'М' + 36: 1, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 0, # 'е' + 23: 2, # 'ж' + 15: 1, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 56: { # 'Я' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 1, # 'Б' + 35: 1, # 'В' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'М' + 36: 1, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 1, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 1, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 1: { # 'а' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 3, # 'ф' + 25: 3, # 'х' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 18: { # 'б' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 0, # 'т' + 19: 3, # 'у' + 29: 0, # 'ф' + 25: 2, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 3, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 9: { # 'в' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 1, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 0, # 'в' + 20: 2, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 20: { # 'г' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 11: { # 'д' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 1, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 3: { # 'е' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 2, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 2, # 'у' + 29: 3, # 'ф' + 25: 3, # 'х' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 23: { # 'ж' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 15: { # 'з' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 2: { # 'и' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 1, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 2, # 'у' + 29: 3, # 'ф' + 25: 3, # 'х' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 2, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 26: { # 'й' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 1, # 'у' + 29: 2, # 'ф' + 25: 1, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 12: { # 'к' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 1, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 3, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 10: { # 'л' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 1, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 2, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 2, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 2, # 'ь' + 42: 3, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 14: { # 'м' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 1, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 1, # 'т' + 19: 3, # 'у' + 29: 2, # 'ф' + 25: 1, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 6: { # 'н' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 2, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 3, # 'ф' + 25: 2, # 'х' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 2, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 4: { # 'о' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 2, # 'у' + 29: 3, # 'ф' + 25: 3, # 'х' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 13: { # 'п' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 7: { # 'р' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 1, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 2, # 'ф' + 25: 3, # 'х' + 22: 3, # 'ц' + 21: 2, # 'ч' + 27: 3, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 1, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 8: { # 'с' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 1, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 2, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ъ' + 52: 2, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 5: { # 'т' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 3, # 'у' + 29: 1, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ъ' + 52: 2, # 'ь' + 42: 2, # 'ю' + 16: 3, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 19: { # 'у' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 2, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 1, # 'у' + 29: 2, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 2, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 29: { # 'ф' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 2, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 2, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 25: { # 'х' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'р' + 8: 1, # 'с' + 5: 2, # 'т' + 19: 3, # 'у' + 29: 0, # 'ф' + 25: 1, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 22: { # 'ц' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'р' + 8: 1, # 'с' + 5: 1, # 'т' + 19: 2, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 0, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 21: { # 'ч' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'р' + 8: 0, # 'с' + 5: 2, # 'т' + 19: 3, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 27: { # 'ш' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 2, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 1, # 'т' + 19: 2, # 'у' + 29: 1, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ъ' + 52: 1, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 24: { # 'щ' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 1, # 'р' + 8: 0, # 'с' + 5: 2, # 'т' + 19: 3, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 1, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 2, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 17: { # 'ъ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 1, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 1, # 'у' + 29: 1, # 'ф' + 25: 2, # 'х' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 3, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 2, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 52: { # 'ь' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 1, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 1, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 1, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 42: { # 'ю' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 1, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 1, # 'е' + 23: 2, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 1, # 'о' + 13: 1, # 'п' + 7: 2, # 'р' + 8: 2, # 'с' + 5: 2, # 'т' + 19: 1, # 'у' + 29: 1, # 'ф' + 25: 1, # 'х' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 16: { # 'я' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 1, # 'о' + 13: 2, # 'п' + 7: 2, # 'р' + 8: 3, # 'с' + 5: 3, # 'т' + 19: 1, # 'у' + 29: 1, # 'ф' + 25: 3, # 'х' + 22: 2, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 2, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 1, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 58: { # 'є' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, + 62: { # '№' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'А' + 32: 0, # 'Б' + 35: 0, # 'В' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'М' + 36: 0, # 'Н' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Х' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'р' + 8: 0, # 'с' + 5: 0, # 'т' + 19: 0, # 'у' + 29: 0, # 'ф' + 25: 0, # 'х' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ъ' + 52: 0, # 'ь' + 42: 0, # 'ю' + 16: 0, # 'я' + 58: 0, # 'є' + 62: 0, # '№' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# Character Mapping Table: -# this table is modified base on win1251BulgarianCharToOrderMap, so -# only number <64 is sure valid - -Latin5_BulgarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 -110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 -253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 -116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 -194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209, # 80 -210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225, # 90 - 81,226,227,228,229,230,105,231,232,233,234,235,236, 45,237,238, # a0 - 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # b0 - 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,239, 67,240, 60, 56, # c0 - 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # d0 - 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,241, 42, 16, # e0 - 62,242,243,244, 58,245, 98,246,247,248,249,250,251, 91,252,253, # f0 -) - -win1251BulgarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 77, 90, 99,100, 72,109,107,101, 79,185, 81,102, 76, 94, 82, # 40 -110,186,108, 91, 74,119, 84, 96,111,187,115,253,253,253,253,253, # 50 -253, 65, 69, 70, 66, 63, 68,112,103, 92,194,104, 95, 86, 87, 71, # 60 -116,195, 85, 93, 97,113,196,197,198,199,200,253,253,253,253,253, # 70 -206,207,208,209,210,211,212,213,120,214,215,216,217,218,219,220, # 80 -221, 78, 64, 83,121, 98,117,105,222,223,224,225,226,227,228,229, # 90 - 88,230,231,232,233,122, 89,106,234,235,236,237,238, 45,239,240, # a0 - 73, 80,118,114,241,242,243,244,245, 62, 58,246,247,248,249,250, # b0 - 31, 32, 35, 43, 37, 44, 55, 47, 40, 59, 33, 46, 38, 36, 41, 30, # c0 - 39, 28, 34, 51, 48, 49, 53, 50, 54, 57, 61,251, 67,252, 60, 56, # d0 - 1, 18, 9, 20, 11, 3, 23, 15, 2, 26, 12, 10, 14, 6, 4, 13, # e0 - 7, 8, 5, 19, 29, 25, 22, 21, 27, 24, 17, 75, 52,253, 42, 16, # f0 -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 96.9392% -# first 1024 sequences:3.0618% -# rest sequences: 0.2992% -# negative sequences: 0.0020% -BulgarianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,3,3,3,3,3, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,2,2,1,2,2, -3,1,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,0,1, -0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,3,3,0,3,1,0, -0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,1,3,2,3,3,3,3,3,3,3,3,0,3,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,2,2,1,3,3,3,3,2,2,2,1,1,2,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,2,3,2,2,3,3,1,1,2,3,3,2,3,3,3,3,2,1,2,0,2,0,3,0,0, -0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,1,3,3,3,3,3,2,3,2,3,3,3,3,3,2,3,3,1,3,0,3,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,1,3,3,2,3,3,3,1,3,3,2,3,2,2,2,0,0,2,0,2,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,0,3,3,3,2,2,3,3,3,1,2,2,3,2,1,1,2,0,2,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,2,3,3,1,2,3,2,2,2,3,3,3,3,3,2,2,3,1,2,0,2,1,2,0,0, -0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,1,3,3,3,3,3,2,3,3,3,2,3,3,2,3,2,2,2,3,1,2,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,1,1,1,2,2,1,3,1,3,2,2,3,0,0,1,0,1,0,1,0,0, -0,0,0,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,2,2,3,2,2,3,1,2,1,1,1,2,3,1,3,1,2,2,0,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,1,3,2,2,3,3,1,2,3,1,1,3,3,3,3,1,2,2,1,1,1,0,2,0,2,0,1, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,2,2,3,3,3,2,2,1,1,2,0,2,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,0,1,2,1,3,3,2,3,3,3,3,3,2,3,2,1,0,3,1,2,1,2,1,2,3,2,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,1,3,3,2,3,3,2,2,2,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,0,3,3,3,3,3,2,1,1,2,1,3,3,0,3,1,1,1,1,3,2,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,2,2,2,3,3,3,3,3,3,3,3,3,3,3,1,1,3,1,3,3,2,3,2,2,2,3,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,3,2,2,3,2,1,1,1,1,1,3,1,3,1,1,0,0,0,1,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,2,0,3,2,0,3,0,2,0,0,2,1,3,1,0,0,1,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,2,1,1,1,1,2,1,1,2,1,1,1,2,2,1,2,1,1,1,0,1,1,0,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,2,1,3,1,1,2,1,3,2,1,1,0,1,2,3,2,1,1,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,2,2,1,0,1,0,0,1,0,0,0,2,1,0,3,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,2,3,2,3,3,1,3,2,1,1,1,2,1,1,2,1,3,0,1,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,2,2,3,3,2,3,2,2,2,3,1,2,2,1,1,2,1,1,2,2,0,1,1,0,1,0,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,3,1,0,2,2,1,3,2,1,0,0,2,0,2,0,1,0,0,0,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,3,1,2,0,2,3,1,2,3,2,0,1,3,1,2,1,1,1,0,0,1,0,0,2,2,2,3, -2,2,2,2,1,2,1,1,2,2,1,1,2,0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,1,0,1, -3,3,3,3,3,2,1,2,2,1,2,0,2,0,1,0,1,2,1,2,1,1,0,0,0,1,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1, -3,3,2,3,3,1,1,3,1,0,3,2,1,0,0,0,1,2,0,2,0,1,0,0,0,1,0,1,2,1,2,2, -1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,0,1,2,1,1,1,0,0,0,0,0,1,1,0,0, -3,1,0,1,0,2,3,2,2,2,3,2,2,2,2,2,1,0,2,1,2,1,1,1,0,1,2,1,2,2,2,1, -1,1,2,2,2,2,1,2,1,1,0,1,2,1,2,2,2,1,1,1,0,1,1,1,1,2,0,1,0,0,0,0, -2,3,2,3,3,0,0,2,1,0,2,1,0,0,0,0,2,3,0,2,0,0,0,0,0,1,0,0,2,0,1,2, -2,1,2,1,2,2,1,1,1,2,1,1,1,0,1,2,2,1,1,1,1,1,0,1,1,1,0,0,1,2,0,0, -3,3,2,2,3,0,2,3,1,1,2,0,0,0,1,0,0,2,0,2,0,0,0,1,0,1,0,1,2,0,2,2, -1,1,1,1,2,1,0,1,2,2,2,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,0, -2,3,2,3,3,0,0,3,0,1,1,0,1,0,0,0,2,2,1,2,0,0,0,0,0,0,0,0,2,0,1,2, -2,2,1,1,1,1,1,2,2,2,1,0,2,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0, -3,3,3,3,2,2,2,2,2,0,2,1,1,1,1,2,1,2,1,1,0,2,0,1,0,1,0,0,2,0,1,2, -1,1,1,1,1,1,1,2,2,1,1,0,2,0,1,0,2,0,0,1,1,1,0,0,2,0,0,0,1,1,0,0, -2,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0,0,0,0,1,2,0,1,2, -2,2,2,1,1,2,1,1,2,2,2,1,2,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,1,1,0,0, -2,3,3,3,3,0,2,2,0,2,1,0,0,0,1,1,1,2,0,2,0,0,0,3,0,0,0,0,2,0,2,2, -1,1,1,2,1,2,1,1,2,2,2,1,2,0,1,1,1,0,1,1,1,1,0,2,1,0,0,0,1,1,0,0, -2,3,3,3,3,0,2,1,0,0,2,0,0,0,0,0,1,2,0,2,0,0,0,0,0,0,0,0,2,0,1,2, -1,1,1,2,1,1,1,1,2,2,2,0,1,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,0,1,0,0, -3,3,2,2,3,0,1,0,1,0,0,0,0,0,0,0,1,1,0,3,0,0,0,0,0,0,0,0,1,0,2,2, -1,1,1,1,1,2,1,1,2,2,1,2,2,1,0,1,1,1,1,1,0,1,0,0,1,0,0,0,1,1,0,0, -3,1,0,1,0,2,2,2,2,3,2,1,1,1,2,3,0,0,1,0,2,1,1,0,1,1,1,1,2,1,1,1, -1,2,2,1,2,1,2,2,1,1,0,1,2,1,2,2,1,1,1,0,0,1,1,1,2,1,0,1,0,0,0,0, -2,1,0,1,0,3,1,2,2,2,2,1,2,2,1,1,1,0,2,1,2,2,1,1,2,1,1,0,2,1,1,1, -1,2,2,2,2,2,2,2,1,2,0,1,1,0,2,1,1,1,1,1,0,0,1,1,1,1,0,1,0,0,0,0, -2,1,1,1,1,2,2,2,2,1,2,2,2,1,2,2,1,1,2,1,2,3,2,2,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,3,2,0,1,2,0,1,2,1,1,0,1,0,1,2,1,2,0,0,0,1,1,0,0,0,1,0,0,2, -1,1,0,0,1,1,0,1,1,1,1,0,2,0,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0, -2,0,0,0,0,1,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,2,1,1,1, -1,2,2,2,2,1,1,2,1,2,1,1,1,0,2,1,2,1,1,1,0,2,1,1,1,1,0,1,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, -1,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,3,2,0,0,0,0,1,0,0,0,0,0,0,1,1,0,2,0,0,0,0,0,0,0,0,1,0,1,2, -1,1,1,1,1,1,0,0,2,2,2,2,2,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,1, -2,3,1,2,1,0,1,1,0,2,2,2,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,1,2, -1,1,1,1,2,1,1,1,1,1,1,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0, -2,2,2,2,2,0,0,2,0,0,2,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,0,2,2, -1,1,1,1,1,0,0,1,2,1,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,2,0,1,1,0,0,0,1,0,0,2,0,2,0,0,0,0,0,0,0,0,0,0,1,1, -0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,3,2,0,0,1,0,0,1,0,0,0,0,0,0,1,0,2,0,0,0,1,0,0,0,0,0,0,0,2, -1,1,0,0,1,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,1,2,2,2,1,2,1,2,2,1,1,2,1,1,1,0,1,1,1,1,2,0,1,0,1,1,1,1,0,1,1, -1,1,2,1,1,1,1,1,1,0,0,1,2,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0, -1,0,0,1,3,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,1,0,0,1,0,2,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,2,0,0,1, -0,2,0,1,0,0,1,1,2,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,1,1,0,2,1,0,1,1,1,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,1, -0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,2,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, -0,1,0,1,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,0,1,2,1,1,1,1,1,1,2,2,1,0,0,1,0,1,0,0,0,0,1,1,1,1,0,0,0, -1,1,2,1,1,1,1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,1,2,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -0,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, -1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,2,0,0,2,0,1,0,0,1,0,0,1, -1,1,0,0,1,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0, -1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -) - -Latin5BulgarianModel = { - 'char_to_order_map': Latin5_BulgarianCharToOrderMap, - 'precedence_matrix': BulgarianLangModel, - 'typical_positive_ratio': 0.969392, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-5", - 'language': 'Bulgairan', +# Character Mapping Table(s): +ISO_8859_5_BULGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 77, # 'A' + 66: 90, # 'B' + 67: 99, # 'C' + 68: 100, # 'D' + 69: 72, # 'E' + 70: 109, # 'F' + 71: 107, # 'G' + 72: 101, # 'H' + 73: 79, # 'I' + 74: 185, # 'J' + 75: 81, # 'K' + 76: 102, # 'L' + 77: 76, # 'M' + 78: 94, # 'N' + 79: 82, # 'O' + 80: 110, # 'P' + 81: 186, # 'Q' + 82: 108, # 'R' + 83: 91, # 'S' + 84: 74, # 'T' + 85: 119, # 'U' + 86: 84, # 'V' + 87: 96, # 'W' + 88: 111, # 'X' + 89: 187, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 65, # 'a' + 98: 69, # 'b' + 99: 70, # 'c' + 100: 66, # 'd' + 101: 63, # 'e' + 102: 68, # 'f' + 103: 112, # 'g' + 104: 103, # 'h' + 105: 92, # 'i' + 106: 194, # 'j' + 107: 104, # 'k' + 108: 95, # 'l' + 109: 86, # 'm' + 110: 87, # 'n' + 111: 71, # 'o' + 112: 116, # 'p' + 113: 195, # 'q' + 114: 85, # 'r' + 115: 93, # 's' + 116: 97, # 't' + 117: 113, # 'u' + 118: 196, # 'v' + 119: 197, # 'w' + 120: 198, # 'x' + 121: 199, # 'y' + 122: 200, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 194, # '\x80' + 129: 195, # '\x81' + 130: 196, # '\x82' + 131: 197, # '\x83' + 132: 198, # '\x84' + 133: 199, # '\x85' + 134: 200, # '\x86' + 135: 201, # '\x87' + 136: 202, # '\x88' + 137: 203, # '\x89' + 138: 204, # '\x8a' + 139: 205, # '\x8b' + 140: 206, # '\x8c' + 141: 207, # '\x8d' + 142: 208, # '\x8e' + 143: 209, # '\x8f' + 144: 210, # '\x90' + 145: 211, # '\x91' + 146: 212, # '\x92' + 147: 213, # '\x93' + 148: 214, # '\x94' + 149: 215, # '\x95' + 150: 216, # '\x96' + 151: 217, # '\x97' + 152: 218, # '\x98' + 153: 219, # '\x99' + 154: 220, # '\x9a' + 155: 221, # '\x9b' + 156: 222, # '\x9c' + 157: 223, # '\x9d' + 158: 224, # '\x9e' + 159: 225, # '\x9f' + 160: 81, # '\xa0' + 161: 226, # 'Ё' + 162: 227, # 'Ђ' + 163: 228, # 'Ѓ' + 164: 229, # 'Є' + 165: 230, # 'Ѕ' + 166: 105, # 'І' + 167: 231, # 'Ї' + 168: 232, # 'Ј' + 169: 233, # 'Љ' + 170: 234, # 'Њ' + 171: 235, # 'Ћ' + 172: 236, # 'Ќ' + 173: 45, # '\xad' + 174: 237, # 'Ў' + 175: 238, # 'Џ' + 176: 31, # 'А' + 177: 32, # 'Б' + 178: 35, # 'В' + 179: 43, # 'Г' + 180: 37, # 'Д' + 181: 44, # 'Е' + 182: 55, # 'Ж' + 183: 47, # 'З' + 184: 40, # 'И' + 185: 59, # 'Й' + 186: 33, # 'К' + 187: 46, # 'Л' + 188: 38, # 'М' + 189: 36, # 'Н' + 190: 41, # 'О' + 191: 30, # 'П' + 192: 39, # 'Р' + 193: 28, # 'С' + 194: 34, # 'Т' + 195: 51, # 'У' + 196: 48, # 'Ф' + 197: 49, # 'Х' + 198: 53, # 'Ц' + 199: 50, # 'Ч' + 200: 54, # 'Ш' + 201: 57, # 'Щ' + 202: 61, # 'Ъ' + 203: 239, # 'Ы' + 204: 67, # 'Ь' + 205: 240, # 'Э' + 206: 60, # 'Ю' + 207: 56, # 'Я' + 208: 1, # 'а' + 209: 18, # 'б' + 210: 9, # 'в' + 211: 20, # 'г' + 212: 11, # 'д' + 213: 3, # 'е' + 214: 23, # 'ж' + 215: 15, # 'з' + 216: 2, # 'и' + 217: 26, # 'й' + 218: 12, # 'к' + 219: 10, # 'л' + 220: 14, # 'м' + 221: 6, # 'н' + 222: 4, # 'о' + 223: 13, # 'п' + 224: 7, # 'р' + 225: 8, # 'с' + 226: 5, # 'т' + 227: 19, # 'у' + 228: 29, # 'ф' + 229: 25, # 'х' + 230: 22, # 'ц' + 231: 21, # 'ч' + 232: 27, # 'ш' + 233: 24, # 'щ' + 234: 17, # 'ъ' + 235: 75, # 'ы' + 236: 52, # 'ь' + 237: 241, # 'э' + 238: 42, # 'ю' + 239: 16, # 'я' + 240: 62, # '№' + 241: 242, # 'ё' + 242: 243, # 'ђ' + 243: 244, # 'ѓ' + 244: 58, # 'є' + 245: 245, # 'ѕ' + 246: 98, # 'і' + 247: 246, # 'ї' + 248: 247, # 'ј' + 249: 248, # 'љ' + 250: 249, # 'њ' + 251: 250, # 'ћ' + 252: 251, # 'ќ' + 253: 91, # '§' + 254: 252, # 'ў' + 255: 253, # 'џ' } -Win1251BulgarianModel = { - 'char_to_order_map': win1251BulgarianCharToOrderMap, - 'precedence_matrix': BulgarianLangModel, - 'typical_positive_ratio': 0.969392, - 'keep_english_letter': False, - 'charset_name': "windows-1251", - 'language': 'Bulgarian', +ISO_8859_5_BULGARIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-5', + language='Bulgarian', + char_to_order_map=ISO_8859_5_BULGARIAN_CHAR_TO_ORDER, + language_model=BULGARIAN_LANG_MODEL, + typical_positive_ratio=0.969392, + keep_ascii_letters=False, + alphabet='АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя') + +WINDOWS_1251_BULGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 77, # 'A' + 66: 90, # 'B' + 67: 99, # 'C' + 68: 100, # 'D' + 69: 72, # 'E' + 70: 109, # 'F' + 71: 107, # 'G' + 72: 101, # 'H' + 73: 79, # 'I' + 74: 185, # 'J' + 75: 81, # 'K' + 76: 102, # 'L' + 77: 76, # 'M' + 78: 94, # 'N' + 79: 82, # 'O' + 80: 110, # 'P' + 81: 186, # 'Q' + 82: 108, # 'R' + 83: 91, # 'S' + 84: 74, # 'T' + 85: 119, # 'U' + 86: 84, # 'V' + 87: 96, # 'W' + 88: 111, # 'X' + 89: 187, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 65, # 'a' + 98: 69, # 'b' + 99: 70, # 'c' + 100: 66, # 'd' + 101: 63, # 'e' + 102: 68, # 'f' + 103: 112, # 'g' + 104: 103, # 'h' + 105: 92, # 'i' + 106: 194, # 'j' + 107: 104, # 'k' + 108: 95, # 'l' + 109: 86, # 'm' + 110: 87, # 'n' + 111: 71, # 'o' + 112: 116, # 'p' + 113: 195, # 'q' + 114: 85, # 'r' + 115: 93, # 's' + 116: 97, # 't' + 117: 113, # 'u' + 118: 196, # 'v' + 119: 197, # 'w' + 120: 198, # 'x' + 121: 199, # 'y' + 122: 200, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 206, # 'Ђ' + 129: 207, # 'Ѓ' + 130: 208, # '‚' + 131: 209, # 'ѓ' + 132: 210, # '„' + 133: 211, # '…' + 134: 212, # '†' + 135: 213, # '‡' + 136: 120, # '€' + 137: 214, # '‰' + 138: 215, # 'Љ' + 139: 216, # '‹' + 140: 217, # 'Њ' + 141: 218, # 'Ќ' + 142: 219, # 'Ћ' + 143: 220, # 'Џ' + 144: 221, # 'ђ' + 145: 78, # '‘' + 146: 64, # '’' + 147: 83, # '“' + 148: 121, # '”' + 149: 98, # '•' + 150: 117, # '–' + 151: 105, # '—' + 152: 222, # None + 153: 223, # '™' + 154: 224, # 'љ' + 155: 225, # '›' + 156: 226, # 'њ' + 157: 227, # 'ќ' + 158: 228, # 'ћ' + 159: 229, # 'џ' + 160: 88, # '\xa0' + 161: 230, # 'Ў' + 162: 231, # 'ў' + 163: 232, # 'Ј' + 164: 233, # '¤' + 165: 122, # 'Ґ' + 166: 89, # '¦' + 167: 106, # '§' + 168: 234, # 'Ё' + 169: 235, # '©' + 170: 236, # 'Є' + 171: 237, # '«' + 172: 238, # '¬' + 173: 45, # '\xad' + 174: 239, # '®' + 175: 240, # 'Ї' + 176: 73, # '°' + 177: 80, # '±' + 178: 118, # 'І' + 179: 114, # 'і' + 180: 241, # 'ґ' + 181: 242, # 'µ' + 182: 243, # '¶' + 183: 244, # '·' + 184: 245, # 'ё' + 185: 62, # '№' + 186: 58, # 'є' + 187: 246, # '»' + 188: 247, # 'ј' + 189: 248, # 'Ѕ' + 190: 249, # 'ѕ' + 191: 250, # 'ї' + 192: 31, # 'А' + 193: 32, # 'Б' + 194: 35, # 'В' + 195: 43, # 'Г' + 196: 37, # 'Д' + 197: 44, # 'Е' + 198: 55, # 'Ж' + 199: 47, # 'З' + 200: 40, # 'И' + 201: 59, # 'Й' + 202: 33, # 'К' + 203: 46, # 'Л' + 204: 38, # 'М' + 205: 36, # 'Н' + 206: 41, # 'О' + 207: 30, # 'П' + 208: 39, # 'Р' + 209: 28, # 'С' + 210: 34, # 'Т' + 211: 51, # 'У' + 212: 48, # 'Ф' + 213: 49, # 'Х' + 214: 53, # 'Ц' + 215: 50, # 'Ч' + 216: 54, # 'Ш' + 217: 57, # 'Щ' + 218: 61, # 'Ъ' + 219: 251, # 'Ы' + 220: 67, # 'Ь' + 221: 252, # 'Э' + 222: 60, # 'Ю' + 223: 56, # 'Я' + 224: 1, # 'а' + 225: 18, # 'б' + 226: 9, # 'в' + 227: 20, # 'г' + 228: 11, # 'д' + 229: 3, # 'е' + 230: 23, # 'ж' + 231: 15, # 'з' + 232: 2, # 'и' + 233: 26, # 'й' + 234: 12, # 'к' + 235: 10, # 'л' + 236: 14, # 'м' + 237: 6, # 'н' + 238: 4, # 'о' + 239: 13, # 'п' + 240: 7, # 'р' + 241: 8, # 'с' + 242: 5, # 'т' + 243: 19, # 'у' + 244: 29, # 'ф' + 245: 25, # 'х' + 246: 22, # 'ц' + 247: 21, # 'ч' + 248: 27, # 'ш' + 249: 24, # 'щ' + 250: 17, # 'ъ' + 251: 75, # 'ы' + 252: 52, # 'ь' + 253: 253, # 'э' + 254: 42, # 'ю' + 255: 16, # 'я' } + +WINDOWS_1251_BULGARIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1251', + language='Bulgarian', + char_to_order_map=WINDOWS_1251_BULGARIAN_CHAR_TO_ORDER, + language_model=BULGARIAN_LANG_MODEL, + typical_positive_ratio=0.969392, + keep_ascii_letters=False, + alphabet='АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрстуфхцчшщъьюя') + diff --git a/pipenv/vendor/chardet/langcyrillicmodel.py b/pipenv/vendor/chardet/langcyrillicmodel.py deleted file mode 100644 index e5f9a1fd..00000000 --- a/pipenv/vendor/chardet/langcyrillicmodel.py +++ /dev/null @@ -1,333 +0,0 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### - -# KOI8-R language model -# Character Mapping Table: -KOI8R_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, # 80 -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, # 90 -223,224,225, 68,226,227,228,229,230,231,232,233,234,235,236,237, # a0 -238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253, # b0 - 27, 3, 21, 28, 13, 2, 39, 19, 26, 4, 23, 11, 8, 12, 5, 1, # c0 - 15, 16, 9, 7, 6, 14, 24, 10, 17, 18, 20, 25, 30, 29, 22, 54, # d0 - 59, 37, 44, 58, 41, 48, 53, 46, 55, 42, 60, 36, 49, 38, 31, 34, # e0 - 35, 43, 45, 32, 40, 52, 56, 33, 61, 62, 51, 57, 47, 63, 50, 70, # f0 -) - -win1251_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, -239,240,241,242,243,244,245,246, 68,247,248,249,250,251,252,253, - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -) - -latin5_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, -) - -macCyrillic_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, -239,240,241,242,243,244,245,246,247,248,249,250,251,252, 68, 16, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27,255, -) - -IBM855_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 -191,192,193,194, 68,195,196,197,198,199,200,201,202,203,204,205, -206,207,208,209,210,211,212,213,214,215,216,217, 27, 59, 54, 70, - 3, 37, 21, 44, 28, 58, 13, 41, 2, 48, 39, 53, 19, 46,218,219, -220,221,222,223,224, 26, 55, 4, 42,225,226,227,228, 23, 60,229, -230,231,232,233,234,235, 11, 36,236,237,238,239,240,241,242,243, - 8, 49, 12, 38, 5, 31, 1, 34, 15,244,245,246,247, 35, 16,248, - 43, 9, 45, 7, 32, 6, 40, 14, 52, 24, 56, 10, 33, 17, 61,249, -250, 18, 62, 20, 51, 25, 57, 30, 47, 29, 63, 22, 50,251,252,255, -) - -IBM866_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,142,143,144,145,146,147,148,149,150,151,152, 74,153, 75,154, # 40 -155,156,157,158,159,160,161,162,163,164,165,253,253,253,253,253, # 50 -253, 71,172, 66,173, 65,174, 76,175, 64,176,177, 77, 72,178, 69, # 60 - 67,179, 78, 73,180,181, 79,182,183,184,185,253,253,253,253,253, # 70 - 37, 44, 33, 46, 41, 48, 56, 51, 42, 60, 36, 49, 38, 31, 34, 35, - 45, 32, 40, 52, 53, 55, 58, 50, 57, 63, 70, 62, 61, 47, 59, 43, - 3, 21, 10, 19, 13, 2, 24, 20, 4, 23, 11, 8, 12, 5, 1, 15, -191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206, -207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222, -223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238, - 9, 7, 6, 14, 39, 26, 28, 22, 25, 29, 54, 18, 17, 30, 27, 16, -239, 68,240,241,242,243,244,245,246,247,248,249,250,251,252,255, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 97.6601% -# first 1024 sequences: 2.3389% -# rest sequences: 0.1237% -# negative sequences: 0.0009% -RussianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,3,3,3,3,1,3,3,3,2,3,2,3,3, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,2,2,2,2,2,0,0,2, -3,3,3,2,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,2,3,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,2,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,2,3,3,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, -0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,2,1, -0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,2,2,2,3,1,3,3,1,3,3,3,3,2,2,3,0,2,2,2,3,3,2,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,3,3,2,2,3,2,3,3,3,2,1,2,2,0,1,2,2,2,2,2,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,3,0,2,2,3,3,2,1,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,1,2,3,2,2,3,2,3,3,3,3,2,2,3,0,3,2,2,3,1,1,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,3,3,3,3,2,2,2,0,3,3,3,2,2,2,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,2,3,2,3,3,3,3,3,3,2,3,2,2,0,1,3,2,1,2,2,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,2,1,1,3,0,1,1,1,1,2,1,1,0,2,2,2,1,2,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,2,2,2,2,1,3,2,3,2,3,2,1,2,2,0,1,1,2,1,2,1,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,2,3,3,3,2,2,2,2,0,2,2,2,2,3,1,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,2,3,2,2,3,3,3,3,3,3,3,3,3,1,3,2,0,0,3,3,3,3,2,3,3,3,3,2,3,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,3,2,2,3,3,0,2,1,0,3,2,3,2,3,0,0,1,2,0,0,1,0,1,2,1,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,3,0,2,3,3,3,3,2,3,3,3,3,1,2,2,0,0,2,3,2,2,2,3,2,3,2,2,3,0,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,0,2,3,2,3,0,1,2,3,3,2,0,2,3,0,0,2,3,2,2,0,1,3,1,3,2,2,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,3,0,2,3,3,3,3,3,3,3,3,2,1,3,2,0,0,2,2,3,3,3,2,3,3,0,2,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,2,2,2,3,3,0,0,1,1,1,1,1,2,0,0,1,1,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,3,3,3,3,3,0,3,2,3,3,2,3,2,0,2,1,0,1,1,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,2,2,2,2,3,1,3,2,3,1,1,2,1,0,2,2,2,2,1,3,1,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -2,2,3,3,3,3,3,1,2,2,1,3,1,0,3,0,0,3,0,0,0,1,1,0,1,2,1,0,0,0,0,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,2,1,1,3,3,3,2,2,1,2,2,3,1,1,2,0,0,2,2,1,3,0,0,2,1,1,2,1,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,3,3,3,1,2,2,2,1,2,1,3,3,1,1,2,1,2,1,2,2,0,2,0,0,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,3,2,1,3,2,2,3,2,0,3,2,0,3,0,1,0,1,1,0,0,1,1,1,1,0,1,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,3,3,3,2,2,2,3,3,1,2,1,2,1,0,1,0,1,1,0,1,0,0,2,1,1,1,0,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,1,1,2,1,2,3,3,2,2,1,2,2,3,0,2,1,0,0,2,2,3,2,1,2,2,2,2,2,3,1,0, -0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,1,1,0,1,1,2,2,1,1,3,0,0,1,3,1,1,1,0,0,0,1,0,1,1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,3,3,3,2,0,0,0,2,1,0,1,0,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,0,2,3,2,2,2,1,2,2,2,1,2,1,0,0,1,1,1,0,2,0,1,1,1,0,0,1,1, -1,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,3,0,0,0,0,1,0,0,0,0,3,0,1,2,1,0,0,0,0,0,0,0,1,1,0,0,1,1, -1,0,1,0,1,2,0,0,1,1,2,1,0,1,1,1,1,0,1,1,1,1,0,1,0,0,1,0,0,1,1,0, -2,2,3,2,2,2,3,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,0,1,0,1,1,1,0,2,1, -1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1,0, -3,3,3,2,2,2,2,3,2,2,1,1,2,2,2,2,1,1,3,1,2,1,2,0,0,1,1,0,1,0,2,1, -1,1,1,1,1,2,1,0,1,1,1,1,0,1,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,1,0, -2,0,0,1,0,3,2,2,2,2,1,2,1,2,1,2,0,0,0,2,1,2,2,1,1,2,2,0,1,1,0,2, -1,1,1,1,1,0,1,1,1,2,1,1,1,2,1,0,1,2,1,1,1,1,0,1,1,1,0,0,1,0,0,1, -1,3,2,2,2,1,1,1,2,3,0,0,0,0,2,0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,1,1, -1,0,1,1,0,1,0,1,1,0,1,1,0,2,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, -2,3,2,3,2,1,2,2,2,2,1,0,0,0,2,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,2,1, -1,1,2,1,0,2,0,0,1,0,1,0,0,1,0,0,1,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0, -3,0,0,1,0,2,2,2,3,2,2,2,2,2,2,2,0,0,0,2,1,2,1,1,1,2,2,0,0,0,1,2, -1,1,1,1,1,0,1,2,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,1, -2,3,2,3,3,2,0,1,1,1,0,0,1,0,2,0,1,1,3,1,0,0,0,0,0,0,0,1,0,0,2,1, -1,1,1,1,1,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,0,0,0,0,0,0,1,0, -2,3,3,3,3,1,2,2,2,2,0,1,1,0,2,1,1,1,2,1,0,1,1,0,0,1,0,1,0,0,2,0, -0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,3,3,2,0,0,1,1,2,2,1,0,0,2,0,1,1,3,0,0,1,0,0,0,0,0,1,0,1,2,1, -1,1,2,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,1,0,1,1,0, -1,3,2,3,2,1,0,0,2,2,2,0,1,0,2,0,1,1,1,0,1,0,0,0,3,0,1,1,0,0,2,1, -1,1,1,0,1,1,0,0,0,0,1,1,0,1,0,0,2,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0, -3,1,2,1,1,2,2,2,2,2,2,1,2,2,1,1,0,0,0,2,2,2,0,0,0,1,2,1,0,1,0,1, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,1,1,1,0,1,0,1,1,0,1,1,1,0,0,1, -3,0,0,0,0,2,0,1,1,1,1,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0,1, -1,1,0,0,1,0,0,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1, -1,3,3,2,2,0,0,0,2,2,0,0,0,1,2,0,1,1,2,0,0,0,0,0,0,0,0,1,0,0,2,1, -0,1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -2,3,2,3,2,0,0,0,0,1,1,0,0,0,2,0,2,0,2,0,0,0,0,0,1,0,0,1,0,0,1,1, -1,1,2,0,1,2,1,0,1,1,2,1,1,1,1,1,2,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0, -1,3,2,2,2,1,0,0,2,2,1,0,1,2,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1, -0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,0,2,3,1,2,2,2,2,2,2,1,1,0,0,0,1,0,1,0,2,1,1,1,0,0,0,0,1, -1,1,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -2,0,2,0,0,1,0,3,2,1,2,1,2,2,0,1,0,0,0,2,1,0,0,2,1,1,1,1,0,2,0,2, -2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,0,1, -1,2,2,2,2,1,0,0,1,0,0,0,0,0,2,0,1,1,1,1,0,0,0,0,1,0,1,2,0,0,2,0, -1,0,1,1,1,2,1,0,1,0,1,1,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0, -2,1,2,2,2,0,3,0,1,1,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0, -1,2,2,3,2,2,0,0,1,1,2,0,1,2,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1, -0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0, -2,2,1,1,2,1,2,2,2,2,2,1,2,2,0,1,0,0,0,1,2,2,2,1,2,1,1,1,1,1,2,1, -1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,0,1, -1,2,2,2,2,0,1,0,2,2,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0, -0,0,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,0,2,2,2,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1, -0,1,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,2,0,0,0,0,1,0,0,1,1,2,0,0,0,0,1,0,1,0,0,1,0,0,2,0,0,0,1, -0,0,1,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0, -1,2,2,2,1,1,2,0,2,1,1,1,1,0,2,2,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1, -0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -1,0,2,1,2,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0, -0,0,1,0,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -1,0,0,0,0,2,0,1,2,1,0,1,1,1,0,1,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,1, -0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, -2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,1,0,1,0,1,0,0,1,1,1,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,0,1,1,0,1,0,1,0,0,0,0,1,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0, -0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, -) - -Koi8rModel = { - 'char_to_order_map': KOI8R_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "KOI8-R", - 'language': 'Russian', -} - -Win1251CyrillicModel = { - 'char_to_order_map': win1251_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "windows-1251", - 'language': 'Russian', -} - -Latin5CyrillicModel = { - 'char_to_order_map': latin5_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-5", - 'language': 'Russian', -} - -MacCyrillicModel = { - 'char_to_order_map': macCyrillic_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "MacCyrillic", - 'language': 'Russian', -} - -Ibm866Model = { - 'char_to_order_map': IBM866_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "IBM866", - 'language': 'Russian', -} - -Ibm855Model = { - 'char_to_order_map': IBM855_char_to_order_map, - 'precedence_matrix': RussianLangModel, - 'typical_positive_ratio': 0.976601, - 'keep_english_letter': False, - 'charset_name': "IBM855", - 'language': 'Russian', -} diff --git a/pipenv/vendor/chardet/langgreekmodel.py b/pipenv/vendor/chardet/langgreekmodel.py index 53322216..02b94de6 100644 --- a/pipenv/vendor/chardet/langgreekmodel.py +++ b/pipenv/vendor/chardet/langgreekmodel.py @@ -1,225 +1,4398 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +GREEK_LANG_MODEL = { + 60: { # 'e' + 60: 2, # 'e' + 55: 1, # 'o' + 58: 2, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 55: { # 'o' + 60: 0, # 'e' + 55: 2, # 'o' + 58: 2, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 1, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 58: { # 't' + 60: 2, # 'e' + 55: 1, # 'o' + 58: 1, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 1, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 36: { # '·' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 61: { # 'Ά' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 1, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 1, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 46: { # 'Έ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 2, # 'β' + 20: 2, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 1, # 'σ' + 2: 2, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 54: { # 'Ό' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 2, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 31: { # 'Α' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 2, # 'Β' + 43: 2, # 'Γ' + 41: 1, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 2, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 1, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Υ' + 56: 2, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 2, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 1, # 'θ' + 5: 0, # 'ι' + 11: 2, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 2, # 'ς' + 7: 2, # 'σ' + 2: 0, # 'τ' + 12: 3, # 'υ' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 51: { # 'Β' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 1, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 43: { # 'Γ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 1, # 'Α' + 51: 0, # 'Β' + 43: 2, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 1, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 2, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 41: { # 'Δ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 1, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 34: { # 'Ε' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 2, # 'Γ' + 41: 2, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 1, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Υ' + 56: 0, # 'Φ' + 50: 2, # 'Χ' + 57: 2, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 1, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 1, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 2, # 'σ' + 2: 2, # 'τ' + 12: 2, # 'υ' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 1, # 'ύ' + 27: 0, # 'ώ' + }, + 40: { # 'Η' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 1, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 2, # 'Θ' + 47: 0, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 1, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 52: { # 'Θ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 1, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 1, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 47: { # 'Ι' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 1, # 'Β' + 43: 1, # 'Γ' + 41: 2, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Υ' + 56: 2, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 2, # 'σ' + 2: 1, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 1, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 44: { # 'Κ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 1, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 2, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 1, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 53: { # 'Λ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 2, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 2, # 'Σ' + 33: 0, # 'Τ' + 45: 2, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 1, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 38: { # 'Μ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 2, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 2, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 49: { # 'Ν' + 60: 2, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 1, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 1, # 'ω' + 19: 2, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 59: { # 'Ξ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 39: { # 'Ο' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 1, # 'Β' + 43: 2, # 'Γ' + 41: 2, # 'Δ' + 34: 2, # 'Ε' + 40: 1, # 'Η' + 52: 2, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Υ' + 56: 2, # 'Φ' + 50: 2, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 2, # 'τ' + 12: 2, # 'υ' + 28: 1, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 35: { # 'Π' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 2, # 'Λ' + 38: 1, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 1, # 'έ' + 22: 1, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ό' + 26: 0, # 'ύ' + 27: 3, # 'ώ' + }, + 48: { # 'Ρ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 1, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 1, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 1, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 1, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 37: { # 'Σ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Υ' + 56: 0, # 'Φ' + 50: 2, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 2, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 2, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 2, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 33: { # 'Τ' + 60: 0, # 'e' + 55: 1, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 2, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 1, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 2, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 2, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ό' + 26: 2, # 'ύ' + 27: 3, # 'ώ' + }, + 45: { # 'Υ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 2, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 2, # 'Η' + 52: 2, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 2, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 1, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 56: { # 'Φ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 1, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 2, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 1, # 'ύ' + 27: 1, # 'ώ' + }, + 50: { # 'Χ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 1, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 1, # 'Ν' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 1, # 'Ω' + 17: 2, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 2, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 57: { # 'Ω' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 1, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Μ' + 49: 2, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 2, # 'ρ' + 14: 2, # 'ς' + 7: 2, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 17: { # 'ά' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 3, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 3, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 18: { # 'έ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 3, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 22: { # 'ή' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 15: { # 'ί' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 3, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 1, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 1: { # 'α' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 2, # 'ε' + 32: 3, # 'ζ' + 13: 1, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ό' + 26: 2, # 'ύ' + 27: 0, # 'ώ' + }, + 29: { # 'β' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 2, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 3, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 20: { # 'γ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 2, # 'ύ' + 27: 3, # 'ώ' + }, + 21: { # 'δ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 3: { # 'ε' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 2, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 2, # 'ε' + 32: 2, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ό' + 26: 3, # 'ύ' + 27: 2, # 'ώ' + }, + 32: { # 'ζ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 1, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ό' + 26: 0, # 'ύ' + 27: 2, # 'ώ' + }, + 13: { # 'η' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 25: { # 'θ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 1, # 'λ' + 10: 3, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 5: { # 'ι' + 60: 0, # 'e' + 55: 1, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 0, # 'ύ' + 27: 3, # 'ώ' + }, + 11: { # 'κ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 2, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 16: { # 'λ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 1, # 'β' + 20: 2, # 'γ' + 21: 1, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 10: { # 'μ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 2, # 'υ' + 28: 3, # 'φ' + 23: 0, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 6: { # 'ν' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 1, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 30: { # 'ξ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 2, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ό' + 26: 3, # 'ύ' + 27: 1, # 'ώ' + }, + 4: { # 'ο' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 2, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 1, # 'ό' + 26: 3, # 'ύ' + 27: 2, # 'ώ' + }, + 9: { # 'π' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 3, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 2, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 2, # 'ύ' + 27: 3, # 'ώ' + }, + 8: { # 'ρ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 1, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 3, # 'ο' + 9: 2, # 'π' + 8: 2, # 'ρ' + 14: 0, # 'ς' + 7: 2, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 14: { # 'ς' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 0, # 'τ' + 12: 0, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 7: { # 'σ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 2, # 'ώ' + }, + 2: { # 'τ' + 60: 0, # 'e' + 55: 2, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 12: { # 'υ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 2, # 'ε' + 32: 2, # 'ζ' + 13: 2, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ό' + 26: 0, # 'ύ' + 27: 2, # 'ώ' + }, + 28: { # 'φ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 1, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 2, # 'ύ' + 27: 2, # 'ώ' + }, + 23: { # 'χ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'π' + 8: 3, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 3, # 'τ' + 12: 3, # 'υ' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ό' + 26: 3, # 'ύ' + 27: 3, # 'ώ' + }, + 42: { # 'ψ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 1, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'π' + 8: 0, # 'ρ' + 14: 0, # 'ς' + 7: 0, # 'σ' + 2: 2, # 'τ' + 12: 1, # 'υ' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 24: { # 'ω' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 1, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 19: { # 'ό' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 1, # 'ε' + 32: 2, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 1, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 26: { # 'ύ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 2, # 'β' + 20: 2, # 'γ' + 21: 1, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, + 27: { # 'ώ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'Ό' + 31: 0, # 'Α' + 51: 0, # 'Β' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Μ' + 49: 0, # 'Ν' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Υ' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 1, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 1, # 'η' + 25: 2, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 1, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'π' + 8: 3, # 'ρ' + 14: 3, # 'ς' + 7: 3, # 'σ' + 2: 3, # 'τ' + 12: 0, # 'υ' + 28: 1, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ό' + 26: 0, # 'ύ' + 27: 0, # 'ώ' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# Character Mapping Table: -Latin7_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 - 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 -253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 - 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 -253,233, 90,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 -253,253,253,253,247,248, 61, 36, 46, 71, 73,253, 54,253,108,123, # b0 -110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 - 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 -124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 - 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 -) - -win1253_char_to_order_map = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 82,100,104, 94, 98,101,116,102,111,187,117, 92, 88,113, 85, # 40 - 79,118,105, 83, 67,114,119, 95, 99,109,188,253,253,253,253,253, # 50 -253, 72, 70, 80, 81, 60, 96, 93, 89, 68,120, 97, 77, 86, 69, 55, # 60 - 78,115, 65, 66, 58, 76,106,103, 87,107,112,253,253,253,253,253, # 70 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 80 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 90 -253,233, 61,253,253,253,253,253,253,253,253,253,253, 74,253,253, # a0 -253,253,253,253,247,253,253, 36, 46, 71, 73,253, 54,253,108,123, # b0 -110, 31, 51, 43, 41, 34, 91, 40, 52, 47, 44, 53, 38, 49, 59, 39, # c0 - 35, 48,250, 37, 33, 45, 56, 50, 84, 57,120,121, 17, 18, 22, 15, # d0 -124, 1, 29, 20, 21, 3, 32, 13, 25, 5, 11, 16, 10, 6, 30, 4, # e0 - 9, 8, 14, 7, 2, 12, 28, 23, 42, 24, 64, 75, 19, 26, 27,253, # f0 -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 98.2851% -# first 1024 sequences:1.7001% -# rest sequences: 0.0359% -# negative sequences: 0.0148% -GreekLangModel = ( -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,2,2,3,3,3,3,3,3,3,3,1,3,3,3,0,2,2,3,3,0,3,0,3,2,0,3,3,3,0, -3,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,0,3,3,0,3,2,3,3,0,3,2,3,3,3,0,0,3,0,3,0,3,3,2,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,2,3,2,2,3,3,3,3,3,3,3,3,0,3,3,3,3,0,2,3,3,0,3,3,3,3,2,3,3,3,0, -2,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,0,2,1,3,3,3,3,2,3,3,2,3,3,2,0, -0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,3,2,3,3,0, -2,0,1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,3,0,0,0,0,3,3,0,3,1,3,3,3,0,3,3,0,3,3,3,3,0,0,0,0, -2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,0,3,0,3,3,3,3,3,0,3,2,2,2,3,0,2,3,3,3,3,3,2,3,3,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,3,2,2,2,3,3,3,3,0,3,1,3,3,3,3,2,3,3,3,3,3,3,3,2,2,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,3,0,0,0,3,3,2,3,3,3,3,3,0,0,3,2,3,0,2,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,3,0,0,3,3,0,2,3,0,3,0,3,3,3,0,0,3,0,3,0,2,2,3,3,0,0, -0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,3,2,3,3,3,3,0,3,3,3,3,3,0,3,3,2,3,2,3,3,2,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,2,3,2,3,3,3,3,3,3,0,2,3,2,3,2,2,2,3,2,3,3,2,3,0,2,2,2,3,0, -2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,0,3,3,3,2,3,3,0,0,3,0,3,0,0,0,3,2,0,3,0,3,0,0,2,0,2,0, -0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,3,3,0,3,0,0,0,3,3,0,3,3,3,0,0,1,2,3,0, -3,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,2,0,0,3,2,2,3,3,0,3,3,3,3,3,2,1,3,0,3,2,3,3,2,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,3,0,2,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,3,0,3,2,3,0,0,3,3,3,0, -3,0,0,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,0,3,3,3,3,3,3,0,0,3,0,3,0,0,0,3,2,0,3,2,3,0,0,3,2,3,0, -2,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,1,2,2,3,3,3,3,3,3,0,2,3,0,3,0,0,0,3,3,0,3,0,2,0,0,2,3,1,0, -2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,3,0,3,0,3,3,2,3,0,3,3,3,3,3,3,0,3,3,3,0,2,3,0,0,3,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,0,0,3,0,0,0,3,3,0,3,0,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,0,3,3,3,3,3,3,0,0,3,0,2,0,0,0,3,3,0,3,0,3,0,0,2,0,2,0, -0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,3,0,3,0,2,0,3,2,0,3,2,3,2,3,0,0,3,2,3,2,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,2,3,3,3,3,3,0,0,0,3,0,2,1,0,0,3,2,2,2,0,3,0,0,2,2,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,2,0,3,0,3,0,3,3,0,2,1,2,3,3,0,0,3,0,3,0,3,3,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,3,0,3,3,3,3,3,3,0,2,3,0,3,0,0,0,2,1,0,2,2,3,0,0,2,2,2,0, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,3,0,0,2,3,3,3,2,3,0,0,1,3,0,2,0,0,0,0,3,0,1,0,2,0,0,1,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,3,1,0,3,0,0,0,3,2,0,3,2,3,3,3,0,0,3,0,3,2,2,2,1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,3,3,3,0,0,3,0,0,0,0,2,0,2,3,3,2,2,2,2,3,0,2,0,2,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,3,3,3,2,0,0,0,0,0,0,2,3,0,2,0,2,3,2,0,0,3,0,3,0,3,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,3,2,3,3,2,2,3,0,2,0,3,0,0,0,2,0,0,0,0,1,2,0,2,0,2,0, -0,2,0,2,0,2,2,0,0,1,0,2,2,2,0,2,2,2,0,2,2,2,0,0,2,0,0,1,0,0,0,0, -0,2,0,3,3,2,0,0,0,0,0,0,1,3,0,2,0,2,2,2,0,0,2,0,3,0,0,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,0,2,3,2,0,2,2,0,2,0,2,2,0,2,0,2,2,2,0,0,0,0,0,0,2,3,0,0,0,2, -0,1,2,0,0,0,0,2,2,0,0,0,2,1,0,2,2,0,0,0,0,0,0,1,0,2,0,0,0,0,0,0, -0,0,2,1,0,2,3,2,2,3,2,3,2,0,0,3,3,3,0,0,3,2,0,0,0,1,1,0,2,0,2,2, -0,2,0,2,0,2,2,0,0,2,0,2,2,2,0,2,2,2,2,0,0,2,0,0,0,2,0,1,0,0,0,0, -0,3,0,3,3,2,2,0,3,0,0,0,2,2,0,2,2,2,1,2,0,0,1,2,2,0,0,3,0,0,0,2, -0,1,2,0,0,0,1,2,0,0,0,0,0,0,0,2,2,0,1,0,0,2,0,0,0,2,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,3,3,2,2,0,0,0,2,0,2,3,3,0,2,0,0,0,0,0,0,2,2,2,0,2,2,0,2,0,2, -0,2,2,0,0,2,2,2,2,1,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0, -0,2,0,3,2,3,0,0,0,3,0,0,2,2,0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,0,2, -0,0,2,2,0,0,2,2,2,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,3,2,0,2,2,2,2,2,0,0,0,2,0,0,0,0,2,0,1,0,0,2,0,1,0,0,0, -0,2,2,2,0,2,2,0,1,2,0,2,2,2,0,2,2,2,2,1,2,2,0,0,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,2,0,2,0,2,2,0,0,0,0,1,2,1,0,0,2,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,3,2,3,0,0,2,0,0,0,2,2,0,2,0,0,0,1,0,0,2,0,2,0,2,2,0,0,0,0, -0,0,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0, -0,2,2,3,2,2,0,0,0,0,0,0,1,3,0,2,0,2,2,0,0,0,1,0,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,0,2,0,3,2,0,2,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -0,0,2,0,0,0,0,1,1,0,0,2,1,2,0,2,2,0,1,0,0,1,0,0,0,2,0,0,0,0,0,0, -0,3,0,2,2,2,0,0,2,0,0,0,2,0,0,0,2,3,0,2,0,0,0,0,0,0,2,2,0,0,0,2, -0,1,2,0,0,0,1,2,2,1,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,1,2,0,2,2,0,2,0,0,2,0,0,0,0,1,2,1,0,2,1,0,0,0,0,0,0,0,0,0,0, -0,0,2,0,0,0,3,1,2,2,0,2,0,0,0,0,2,0,0,0,2,0,0,3,0,0,0,0,2,2,2,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,1,0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,2, -0,2,2,0,0,2,2,2,2,2,0,1,2,0,0,0,2,2,0,1,0,2,0,0,2,2,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,2, -0,1,2,0,0,0,0,2,2,1,0,1,0,1,0,2,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,2,0,1,2,0,0,0,0,0,0,0,0,0,0,2,0,0,2,2,0,0,0,0,1,0,0,0,0,0,0,2, -0,2,2,0,0,0,0,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0, -0,2,2,2,2,0,0,0,3,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,1, -0,0,2,0,0,0,0,1,2,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,2,0,2,2,2,0,0,2,0,0,0,0,0,0,0,2,2,2,0,0,0,2,0,0,0,0,0,0,0,0,2, -0,0,1,0,0,0,0,2,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,3,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,2, -0,0,2,0,0,0,0,2,2,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,2,0,2,2,1,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,0,0,0,2, -0,0,2,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0, -0,0,3,0,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0, -0,2,2,2,2,2,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1, -0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,2,2,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,2,0,0,0,2,0,0,0,0,0,1,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,2,0,0,0, -0,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,2,0,2,0,0,0, -0,0,0,0,0,0,0,0,2,1,0,0,0,0,0,0,2,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -Latin7GreekModel = { - 'char_to_order_map': Latin7_char_to_order_map, - 'precedence_matrix': GreekLangModel, - 'typical_positive_ratio': 0.982851, - 'keep_english_letter': False, - 'charset_name': "ISO-8859-7", - 'language': 'Greek', +# Character Mapping Table(s): +WINDOWS_1253_GREEK_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 82, # 'A' + 66: 100, # 'B' + 67: 104, # 'C' + 68: 94, # 'D' + 69: 98, # 'E' + 70: 101, # 'F' + 71: 116, # 'G' + 72: 102, # 'H' + 73: 111, # 'I' + 74: 187, # 'J' + 75: 117, # 'K' + 76: 92, # 'L' + 77: 88, # 'M' + 78: 113, # 'N' + 79: 85, # 'O' + 80: 79, # 'P' + 81: 118, # 'Q' + 82: 105, # 'R' + 83: 83, # 'S' + 84: 67, # 'T' + 85: 114, # 'U' + 86: 119, # 'V' + 87: 95, # 'W' + 88: 99, # 'X' + 89: 109, # 'Y' + 90: 188, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 72, # 'a' + 98: 70, # 'b' + 99: 80, # 'c' + 100: 81, # 'd' + 101: 60, # 'e' + 102: 96, # 'f' + 103: 93, # 'g' + 104: 89, # 'h' + 105: 68, # 'i' + 106: 120, # 'j' + 107: 97, # 'k' + 108: 77, # 'l' + 109: 86, # 'm' + 110: 69, # 'n' + 111: 55, # 'o' + 112: 78, # 'p' + 113: 115, # 'q' + 114: 65, # 'r' + 115: 66, # 's' + 116: 58, # 't' + 117: 76, # 'u' + 118: 106, # 'v' + 119: 103, # 'w' + 120: 87, # 'x' + 121: 107, # 'y' + 122: 112, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 255, # '€' + 129: 255, # None + 130: 255, # '‚' + 131: 255, # 'ƒ' + 132: 255, # '„' + 133: 255, # '…' + 134: 255, # '†' + 135: 255, # '‡' + 136: 255, # None + 137: 255, # '‰' + 138: 255, # None + 139: 255, # '‹' + 140: 255, # None + 141: 255, # None + 142: 255, # None + 143: 255, # None + 144: 255, # None + 145: 255, # '‘' + 146: 255, # '’' + 147: 255, # '“' + 148: 255, # '”' + 149: 255, # '•' + 150: 255, # '–' + 151: 255, # '—' + 152: 255, # None + 153: 255, # '™' + 154: 255, # None + 155: 255, # '›' + 156: 255, # None + 157: 255, # None + 158: 255, # None + 159: 255, # None + 160: 253, # '\xa0' + 161: 233, # '΅' + 162: 61, # 'Ά' + 163: 253, # '£' + 164: 253, # '¤' + 165: 253, # '¥' + 166: 253, # '¦' + 167: 253, # '§' + 168: 253, # '¨' + 169: 253, # '©' + 170: 253, # None + 171: 253, # '«' + 172: 253, # '¬' + 173: 74, # '\xad' + 174: 253, # '®' + 175: 253, # '―' + 176: 253, # '°' + 177: 253, # '±' + 178: 253, # '²' + 179: 253, # '³' + 180: 247, # '΄' + 181: 253, # 'µ' + 182: 253, # '¶' + 183: 36, # '·' + 184: 46, # 'Έ' + 185: 71, # 'Ή' + 186: 73, # 'Ί' + 187: 253, # '»' + 188: 54, # 'Ό' + 189: 253, # '½' + 190: 108, # 'Ύ' + 191: 123, # 'Ώ' + 192: 110, # 'ΐ' + 193: 31, # 'Α' + 194: 51, # 'Β' + 195: 43, # 'Γ' + 196: 41, # 'Δ' + 197: 34, # 'Ε' + 198: 91, # 'Ζ' + 199: 40, # 'Η' + 200: 52, # 'Θ' + 201: 47, # 'Ι' + 202: 44, # 'Κ' + 203: 53, # 'Λ' + 204: 38, # 'Μ' + 205: 49, # 'Ν' + 206: 59, # 'Ξ' + 207: 39, # 'Ο' + 208: 35, # 'Π' + 209: 48, # 'Ρ' + 210: 250, # None + 211: 37, # 'Σ' + 212: 33, # 'Τ' + 213: 45, # 'Υ' + 214: 56, # 'Φ' + 215: 50, # 'Χ' + 216: 84, # 'Ψ' + 217: 57, # 'Ω' + 218: 120, # 'Ϊ' + 219: 121, # 'Ϋ' + 220: 17, # 'ά' + 221: 18, # 'έ' + 222: 22, # 'ή' + 223: 15, # 'ί' + 224: 124, # 'ΰ' + 225: 1, # 'α' + 226: 29, # 'β' + 227: 20, # 'γ' + 228: 21, # 'δ' + 229: 3, # 'ε' + 230: 32, # 'ζ' + 231: 13, # 'η' + 232: 25, # 'θ' + 233: 5, # 'ι' + 234: 11, # 'κ' + 235: 16, # 'λ' + 236: 10, # 'μ' + 237: 6, # 'ν' + 238: 30, # 'ξ' + 239: 4, # 'ο' + 240: 9, # 'π' + 241: 8, # 'ρ' + 242: 14, # 'ς' + 243: 7, # 'σ' + 244: 2, # 'τ' + 245: 12, # 'υ' + 246: 28, # 'φ' + 247: 23, # 'χ' + 248: 42, # 'ψ' + 249: 24, # 'ω' + 250: 64, # 'ϊ' + 251: 75, # 'ϋ' + 252: 19, # 'ό' + 253: 26, # 'ύ' + 254: 27, # 'ώ' + 255: 253, # None } -Win1253GreekModel = { - 'char_to_order_map': win1253_char_to_order_map, - 'precedence_matrix': GreekLangModel, - 'typical_positive_ratio': 0.982851, - 'keep_english_letter': False, - 'charset_name': "windows-1253", - 'language': 'Greek', +WINDOWS_1253_GREEK_MODEL = SingleByteCharSetModel(charset_name='windows-1253', + language='Greek', + char_to_order_map=WINDOWS_1253_GREEK_CHAR_TO_ORDER, + language_model=GREEK_LANG_MODEL, + typical_positive_ratio=0.982851, + keep_ascii_letters=False, + alphabet='ΆΈΉΊΌΎΏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩάέήίαβγδεζηθικλμνξοπρςστυφχψωόύώ') + +ISO_8859_7_GREEK_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 82, # 'A' + 66: 100, # 'B' + 67: 104, # 'C' + 68: 94, # 'D' + 69: 98, # 'E' + 70: 101, # 'F' + 71: 116, # 'G' + 72: 102, # 'H' + 73: 111, # 'I' + 74: 187, # 'J' + 75: 117, # 'K' + 76: 92, # 'L' + 77: 88, # 'M' + 78: 113, # 'N' + 79: 85, # 'O' + 80: 79, # 'P' + 81: 118, # 'Q' + 82: 105, # 'R' + 83: 83, # 'S' + 84: 67, # 'T' + 85: 114, # 'U' + 86: 119, # 'V' + 87: 95, # 'W' + 88: 99, # 'X' + 89: 109, # 'Y' + 90: 188, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 72, # 'a' + 98: 70, # 'b' + 99: 80, # 'c' + 100: 81, # 'd' + 101: 60, # 'e' + 102: 96, # 'f' + 103: 93, # 'g' + 104: 89, # 'h' + 105: 68, # 'i' + 106: 120, # 'j' + 107: 97, # 'k' + 108: 77, # 'l' + 109: 86, # 'm' + 110: 69, # 'n' + 111: 55, # 'o' + 112: 78, # 'p' + 113: 115, # 'q' + 114: 65, # 'r' + 115: 66, # 's' + 116: 58, # 't' + 117: 76, # 'u' + 118: 106, # 'v' + 119: 103, # 'w' + 120: 87, # 'x' + 121: 107, # 'y' + 122: 112, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 255, # '\x80' + 129: 255, # '\x81' + 130: 255, # '\x82' + 131: 255, # '\x83' + 132: 255, # '\x84' + 133: 255, # '\x85' + 134: 255, # '\x86' + 135: 255, # '\x87' + 136: 255, # '\x88' + 137: 255, # '\x89' + 138: 255, # '\x8a' + 139: 255, # '\x8b' + 140: 255, # '\x8c' + 141: 255, # '\x8d' + 142: 255, # '\x8e' + 143: 255, # '\x8f' + 144: 255, # '\x90' + 145: 255, # '\x91' + 146: 255, # '\x92' + 147: 255, # '\x93' + 148: 255, # '\x94' + 149: 255, # '\x95' + 150: 255, # '\x96' + 151: 255, # '\x97' + 152: 255, # '\x98' + 153: 255, # '\x99' + 154: 255, # '\x9a' + 155: 255, # '\x9b' + 156: 255, # '\x9c' + 157: 255, # '\x9d' + 158: 255, # '\x9e' + 159: 255, # '\x9f' + 160: 253, # '\xa0' + 161: 233, # '‘' + 162: 90, # '’' + 163: 253, # '£' + 164: 253, # '€' + 165: 253, # '₯' + 166: 253, # '¦' + 167: 253, # '§' + 168: 253, # '¨' + 169: 253, # '©' + 170: 253, # 'ͺ' + 171: 253, # '«' + 172: 253, # '¬' + 173: 74, # '\xad' + 174: 253, # None + 175: 253, # '―' + 176: 253, # '°' + 177: 253, # '±' + 178: 253, # '²' + 179: 253, # '³' + 180: 247, # '΄' + 181: 248, # '΅' + 182: 61, # 'Ά' + 183: 36, # '·' + 184: 46, # 'Έ' + 185: 71, # 'Ή' + 186: 73, # 'Ί' + 187: 253, # '»' + 188: 54, # 'Ό' + 189: 253, # '½' + 190: 108, # 'Ύ' + 191: 123, # 'Ώ' + 192: 110, # 'ΐ' + 193: 31, # 'Α' + 194: 51, # 'Β' + 195: 43, # 'Γ' + 196: 41, # 'Δ' + 197: 34, # 'Ε' + 198: 91, # 'Ζ' + 199: 40, # 'Η' + 200: 52, # 'Θ' + 201: 47, # 'Ι' + 202: 44, # 'Κ' + 203: 53, # 'Λ' + 204: 38, # 'Μ' + 205: 49, # 'Ν' + 206: 59, # 'Ξ' + 207: 39, # 'Ο' + 208: 35, # 'Π' + 209: 48, # 'Ρ' + 210: 250, # None + 211: 37, # 'Σ' + 212: 33, # 'Τ' + 213: 45, # 'Υ' + 214: 56, # 'Φ' + 215: 50, # 'Χ' + 216: 84, # 'Ψ' + 217: 57, # 'Ω' + 218: 120, # 'Ϊ' + 219: 121, # 'Ϋ' + 220: 17, # 'ά' + 221: 18, # 'έ' + 222: 22, # 'ή' + 223: 15, # 'ί' + 224: 124, # 'ΰ' + 225: 1, # 'α' + 226: 29, # 'β' + 227: 20, # 'γ' + 228: 21, # 'δ' + 229: 3, # 'ε' + 230: 32, # 'ζ' + 231: 13, # 'η' + 232: 25, # 'θ' + 233: 5, # 'ι' + 234: 11, # 'κ' + 235: 16, # 'λ' + 236: 10, # 'μ' + 237: 6, # 'ν' + 238: 30, # 'ξ' + 239: 4, # 'ο' + 240: 9, # 'π' + 241: 8, # 'ρ' + 242: 14, # 'ς' + 243: 7, # 'σ' + 244: 2, # 'τ' + 245: 12, # 'υ' + 246: 28, # 'φ' + 247: 23, # 'χ' + 248: 42, # 'ψ' + 249: 24, # 'ω' + 250: 64, # 'ϊ' + 251: 75, # 'ϋ' + 252: 19, # 'ό' + 253: 26, # 'ύ' + 254: 27, # 'ώ' + 255: 253, # None } + +ISO_8859_7_GREEK_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-7', + language='Greek', + char_to_order_map=ISO_8859_7_GREEK_CHAR_TO_ORDER, + language_model=GREEK_LANG_MODEL, + typical_positive_ratio=0.982851, + keep_ascii_letters=False, + alphabet='ΆΈΉΊΌΎΏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩάέήίαβγδεζηθικλμνξοπρςστυφχψωόύώ') + diff --git a/pipenv/vendor/chardet/langhebrewmodel.py b/pipenv/vendor/chardet/langhebrewmodel.py index 58f4c875..40fd674c 100644 --- a/pipenv/vendor/chardet/langhebrewmodel.py +++ b/pipenv/vendor/chardet/langhebrewmodel.py @@ -1,200 +1,4383 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Universal charset detector code. -# -# The Initial Developer of the Original Code is -# Simon Montagu -# Portions created by the Initial Developer are Copyright (C) 2005 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Shy Shalom - original C code -# Shoshannah Forbes - original C code (?) -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +HEBREW_LANG_MODEL = { + 50: { # 'a' + 50: 0, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 2, # 'l' + 54: 2, # 'n' + 49: 0, # 'o' + 51: 2, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 0, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 60: { # 'c' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 61: { # 'd' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 0, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 42: { # 'e' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 2, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 2, # 'l' + 54: 2, # 'n' + 49: 1, # 'o' + 51: 2, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 1, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 53: { # 'i' + 50: 1, # 'a' + 60: 2, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 0, # 'i' + 56: 1, # 'l' + 54: 2, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 56: { # 'l' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 2, # 'e' + 53: 2, # 'i' + 56: 2, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 54: { # 'n' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 49: { # 'o' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 2, # 'n' + 49: 1, # 'o' + 51: 2, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 51: { # 'r' + 50: 2, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 2, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 43: { # 's' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 2, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 2, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 44: { # 't' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 2, # 'e' + 53: 2, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 63: { # 'u' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 34: { # '\xa0' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 1, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 2, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 1, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 2, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 1, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 55: { # '´' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 2, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 1, # 'ן' + 12: 1, # 'נ' + 19: 1, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 48: { # '¼' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 39: { # '½' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 57: { # '¾' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 30: { # 'ְ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 1, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 1, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 2, # 'ג' + 16: 2, # 'ד' + 3: 2, # 'ה' + 2: 2, # 'ו' + 24: 2, # 'ז' + 14: 2, # 'ח' + 22: 2, # 'ט' + 1: 2, # 'י' + 25: 2, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 1, # 'ם' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 2, # 'נ' + 19: 2, # 'ס' + 13: 2, # 'ע' + 26: 0, # 'ף' + 18: 2, # 'פ' + 27: 0, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 59: { # 'ֱ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 1, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 2, # 'ל' + 11: 0, # 'ם' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 41: { # 'ֲ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 2, # 'ב' + 20: 1, # 'ג' + 16: 2, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 1, # 'י' + 25: 1, # 'ך' + 15: 1, # 'כ' + 4: 2, # 'ל' + 11: 0, # 'ם' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 2, # 'נ' + 19: 1, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 2, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 33: { # 'ִ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 1, # 'ִ' + 37: 0, # 'ֵ' + 36: 1, # 'ֶ' + 31: 0, # 'ַ' + 29: 1, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 1, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 2, # 'ב' + 20: 2, # 'ג' + 16: 2, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 2, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 2, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 2, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 37: { # 'ֵ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 1, # 'ֶ' + 31: 1, # 'ַ' + 29: 1, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 1, # 'ג' + 16: 2, # 'ד' + 3: 2, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 2, # 'ח' + 22: 1, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 1, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 1, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 1, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 1, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 36: { # 'ֶ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 1, # 'ֶ' + 31: 1, # 'ַ' + 29: 1, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 1, # 'ג' + 16: 2, # 'ד' + 3: 2, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 2, # 'ח' + 22: 1, # 'ט' + 1: 2, # 'י' + 25: 2, # 'ך' + 15: 1, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 2, # 'ס' + 13: 1, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 2, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 31: { # 'ַ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 1, # 'ֶ' + 31: 0, # 'ַ' + 29: 2, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 2, # 'ג' + 16: 2, # 'ד' + 3: 2, # 'ה' + 2: 1, # 'ו' + 24: 2, # 'ז' + 14: 2, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 2, # 'ס' + 13: 2, # 'ע' + 26: 2, # 'ף' + 18: 2, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 29: { # 'ָ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 1, # 'ַ' + 29: 2, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 1, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 2, # 'ג' + 16: 2, # 'ד' + 3: 3, # 'ה' + 2: 2, # 'ו' + 24: 2, # 'ז' + 14: 2, # 'ח' + 22: 1, # 'ט' + 1: 2, # 'י' + 25: 2, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 1, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 2, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 35: { # 'ֹ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 1, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 1, # 'ג' + 16: 2, # 'ד' + 3: 2, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 1, # 'י' + 25: 1, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 2, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 2, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 62: { # 'ֻ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 1, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 2, # 'ל' + 11: 1, # 'ם' + 6: 1, # 'מ' + 23: 1, # 'ן' + 12: 1, # 'נ' + 19: 1, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 28: { # 'ּ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 3, # 'ְ' + 59: 0, # 'ֱ' + 41: 1, # 'ֲ' + 33: 3, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 3, # 'ַ' + 29: 3, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 2, # 'ׁ' + 45: 1, # 'ׂ' + 9: 2, # 'א' + 8: 2, # 'ב' + 20: 1, # 'ג' + 16: 2, # 'ד' + 3: 1, # 'ה' + 2: 2, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 2, # 'י' + 25: 2, # 'ך' + 15: 2, # 'כ' + 4: 2, # 'ל' + 11: 1, # 'ם' + 6: 2, # 'מ' + 23: 1, # 'ן' + 12: 2, # 'נ' + 19: 1, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 1, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 38: { # 'ׁ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 2, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 45: { # 'ׂ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 1, # 'ֵ' + 36: 2, # 'ֶ' + 31: 1, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 1, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 2, # 'ו' + 24: 0, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 1, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 0, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 9: { # 'א' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 2, # 'ֱ' + 41: 2, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 2, # 'ע' + 26: 3, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 8: { # 'ב' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 3, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 1, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 20: { # 'ג' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 2, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 1, # 'ִ' + 37: 1, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 0, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 3, # 'ב' + 20: 2, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 2, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 1, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 2, # 'פ' + 27: 1, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 16: { # 'ד' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 1, # 'ז' + 14: 2, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 2, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 0, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 3: { # 'ה' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 1, # 'ֱ' + 41: 2, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 3, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 0, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 2: { # 'ו' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 1, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 3, # 'ֹ' + 62: 0, # 'ֻ' + 28: 3, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 3, # 'ף' + 18: 3, # 'פ' + 27: 3, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 24: { # 'ז' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 1, # 'ֲ' + 33: 1, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 2, # 'ב' + 20: 2, # 'ג' + 16: 2, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 2, # 'ח' + 22: 1, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 2, # 'נ' + 19: 1, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 1, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 14: { # 'ח' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 1, # 'ֱ' + 41: 2, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 3, # 'ב' + 20: 2, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 2, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 2, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 1, # 'ע' + 26: 2, # 'ף' + 18: 2, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 22: { # 'ט' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 1, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 1, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 1, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 1, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 3, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 2, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 2, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 1: { # 'י' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 3, # 'ף' + 18: 3, # 'פ' + 27: 3, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 25: { # 'ך' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 2, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 1, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 15: { # 'כ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 3, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 2, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 2, # 'ע' + 26: 3, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 4: { # 'ל' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 3, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 11: { # 'ם' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 1, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 0, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 1, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 6: { # 'מ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 0, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 23: { # 'ן' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 1, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 1, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 1, # 'ס' + 13: 1, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 12: { # 'נ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 19: { # 'ס' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 1, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 1, # 'ָ' + 35: 1, # 'ֹ' + 62: 2, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 1, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 3, # 'ף' + 18: 3, # 'פ' + 27: 0, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 1, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 13: { # 'ע' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 1, # 'ֱ' + 41: 2, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 1, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 2, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 2, # 'ע' + 26: 1, # 'ף' + 18: 2, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 26: { # 'ף' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 1, # 'ס' + 13: 0, # 'ע' + 26: 1, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 18: { # 'פ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 1, # 'ֵ' + 36: 2, # 'ֶ' + 31: 1, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 2, # 'ב' + 20: 3, # 'ג' + 16: 2, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 2, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 2, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 27: { # 'ץ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 1, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 21: { # 'צ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 2, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 1, # 'ז' + 14: 3, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 1, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 1, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 0, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 17: { # 'ק' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 1, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 2, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 1, # 'ך' + 15: 1, # 'כ' + 4: 3, # 'ל' + 11: 2, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 2, # 'ץ' + 21: 3, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 7: { # 'ר' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 2, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 1, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 2, # 'ֹ' + 62: 1, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 3, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 3, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 3, # 'ץ' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 10: { # 'ש' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 1, # 'ִ' + 37: 1, # 'ֵ' + 36: 1, # 'ֶ' + 31: 1, # 'ַ' + 29: 1, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 3, # 'ׁ' + 45: 2, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 3, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 3, # 'ח' + 22: 3, # 'ט' + 1: 3, # 'י' + 25: 3, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 1, # '…' + }, + 5: { # 'ת' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 1, # '½' + 57: 0, # '¾' + 30: 2, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 2, # 'ִ' + 37: 2, # 'ֵ' + 36: 2, # 'ֶ' + 31: 2, # 'ַ' + 29: 2, # 'ָ' + 35: 1, # 'ֹ' + 62: 1, # 'ֻ' + 28: 2, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 3, # 'א' + 8: 3, # 'ב' + 20: 3, # 'ג' + 16: 2, # 'ד' + 3: 3, # 'ה' + 2: 3, # 'ו' + 24: 2, # 'ז' + 14: 3, # 'ח' + 22: 2, # 'ט' + 1: 3, # 'י' + 25: 2, # 'ך' + 15: 3, # 'כ' + 4: 3, # 'ל' + 11: 3, # 'ם' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # 'נ' + 19: 2, # 'ס' + 13: 3, # 'ע' + 26: 2, # 'ף' + 18: 3, # 'פ' + 27: 1, # 'ץ' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, + 32: { # '–' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 1, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 1, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 1, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 52: { # '’' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 1, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 47: { # '“' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 2, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 1, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 1, # 'ח' + 22: 1, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 1, # 'ס' + 13: 1, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 46: { # '”' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 1, # 'ב' + 20: 1, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 1, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 0, # '†' + 40: 0, # '…' + }, + 58: { # '†' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 0, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 0, # 'ה' + 2: 0, # 'ו' + 24: 0, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 0, # 'י' + 25: 0, # 'ך' + 15: 0, # 'כ' + 4: 0, # 'ל' + 11: 0, # 'ם' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 0, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # '”' + 58: 2, # '†' + 40: 0, # '…' + }, + 40: { # '…' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'ְ' + 59: 0, # 'ֱ' + 41: 0, # 'ֲ' + 33: 0, # 'ִ' + 37: 0, # 'ֵ' + 36: 0, # 'ֶ' + 31: 0, # 'ַ' + 29: 0, # 'ָ' + 35: 0, # 'ֹ' + 62: 0, # 'ֻ' + 28: 0, # 'ּ' + 38: 0, # 'ׁ' + 45: 0, # 'ׂ' + 9: 1, # 'א' + 8: 0, # 'ב' + 20: 0, # 'ג' + 16: 0, # 'ד' + 3: 1, # 'ה' + 2: 1, # 'ו' + 24: 1, # 'ז' + 14: 0, # 'ח' + 22: 0, # 'ט' + 1: 1, # 'י' + 25: 0, # 'ך' + 15: 1, # 'כ' + 4: 1, # 'ל' + 11: 0, # 'ם' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # 'נ' + 19: 0, # 'ס' + 13: 0, # 'ע' + 26: 0, # 'ף' + 18: 1, # 'פ' + 27: 0, # 'ץ' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # '”' + 58: 0, # '†' + 40: 2, # '…' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# Windows-1255 language model -# Character Mapping Table: -WIN1255_CHAR_TO_ORDER_MAP = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 69, 91, 79, 80, 92, 89, 97, 90, 68,111,112, 82, 73, 95, 85, # 40 - 78,121, 86, 71, 67,102,107, 84,114,103,115,253,253,253,253,253, # 50 -253, 50, 74, 60, 61, 42, 76, 70, 64, 53,105, 93, 56, 65, 54, 49, # 60 - 66,110, 51, 43, 44, 63, 81, 77, 98, 75,108,253,253,253,253,253, # 70 -124,202,203,204,205, 40, 58,206,207,208,209,210,211,212,213,214, -215, 83, 52, 47, 46, 72, 32, 94,216,113,217,109,218,219,220,221, - 34,116,222,118,100,223,224,117,119,104,125,225,226, 87, 99,227, -106,122,123,228, 55,229,230,101,231,232,120,233, 48, 39, 57,234, - 30, 59, 41, 88, 33, 37, 36, 31, 29, 35,235, 62, 28,236,126,237, -238, 38, 45,239,240,241,242,243,127,244,245,246,247,248,249,250, - 9, 8, 20, 16, 3, 2, 24, 14, 22, 1, 25, 15, 4, 11, 6, 23, - 12, 19, 13, 26, 18, 27, 21, 17, 7, 10, 5,251,252,128, 96,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 98.4004% -# first 1024 sequences: 1.5981% -# rest sequences: 0.087% -# negative sequences: 0.0015% -HEBREW_LANG_MODEL = ( -0,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,3,2,1,2,0,1,0,0, -3,0,3,1,0,0,1,3,2,0,1,1,2,0,2,2,2,1,1,1,1,2,1,1,1,2,0,0,2,2,0,1, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2, -1,2,1,2,1,2,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2, -1,2,1,3,1,1,0,0,2,0,0,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,1,2,2,1,3, -1,2,1,1,2,2,0,0,2,2,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,2,2,2,3,2, -1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,2,3,2,2,3,2,2,2,1,2,2,2,2, -1,2,1,1,2,2,0,1,2,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,0,2,2,2,2,2, -0,2,0,2,2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,0,2,2,2, -0,2,1,2,2,2,0,0,2,1,0,0,0,0,1,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,2,1,2,3,2,2,2, -1,2,1,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,2,0,2, -0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,2,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,2,3,2,1,2,1,1,1, -0,1,1,1,1,1,3,0,1,0,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,0,1,0,0,1,0,0,0,0, -0,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,2,1,2,3,3,2,3,3,3,3,2,3,2,1,2,0,2,1,2, -0,2,0,2,2,2,0,0,1,2,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,1,2,2,3,3,2,3,2,3,2,2,3,1,2,2,0,2,2,2, -0,2,1,2,2,2,0,0,1,2,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,2,2,3,3,3,3,1,3,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,2,3,2,2,2,1,2,2,0,2,2,2,2, -0,2,0,2,2,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,1,3,2,3,3,2,3,3,2,2,1,2,2,2,2,2,2, -0,2,1,2,1,2,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,2,3,3,2,3,3,3,3,2,3,2,3,3,3,3,3,2,2,2,2,2,2,2,1, -0,2,0,1,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,2,1,2,3,3,3,3,3,3,3,2,3,2,3,2,1,2,3,0,2,1,2,2, -0,2,1,1,2,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,2,0, -3,3,3,3,3,3,3,3,3,2,3,3,3,3,2,1,3,1,2,2,2,1,2,3,3,1,2,1,2,2,2,2, -0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,0,2,3,3,3,1,3,3,3,1,2,2,2,2,1,1,2,2,2,2,2,2, -0,2,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,2,2,3,3,3,2,1,2,3,2,3,2,2,2,2,1,2,1,1,1,2,2, -0,2,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,0,0, -1,0,1,0,0,0,0,0,2,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,2,3,3,2,3,1,2,2,2,2,3,2,3,1,1,2,2,1,2,2,1,1,0,2,2,2,2, -0,1,0,1,2,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0, -3,0,0,1,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -3,2,2,1,2,2,2,2,2,2,2,1,2,2,1,2,2,1,1,1,1,1,1,1,1,2,1,1,0,3,3,3, -0,3,0,2,2,2,2,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -2,2,2,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,1,2,2,2,1,1,1,2,0,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,2,2,2,0,2,2,0,0,0,0,0,0, -0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,1,0,2,1,0, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,3,1,1,2,2,2,2,2,1,2,2,2,1,1,2,2,2,2,2,2,2,1,2,2,1,0,1,1,1,1,0, -0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,2,1,1,1,1,2,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, -0,0,2,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,0, -2,1,1,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,1,2,1,2,1,1,1,1,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,2,1,2,2,2,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,2,1,2,1,2,0,1,0,1, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,3,1,2,2,2,1,2,2,2,2,2,2,2,2,1,2,1,1,1,1,1,1,2,1,2,1,1,0,1,0,1, -0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, -0,2,0,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,1,1,1,1,1,1,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,1,1,1,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,1,1,0,0, -0,1,1,1,2,1,2,2,2,0,2,0,2,0,1,1,2,1,1,1,1,2,1,0,1,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,1,0,0,0,0,0,1,0,1,2,2,0,1,0,0,1,1,2,2,1,2,0,2,0,0,0,1,2,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,2,1,2,0,2,0,0,1,1,1,1,1,1,0,1,0,0,0,1,0,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,1,2,2,0,0,1,0,0,0,1,0,0,1, -1,1,2,1,0,1,1,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,2,2,1, -0,2,0,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,1,0,0,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,2,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,1,0,1,0,0,0,1,1,0,1, -2,0,1,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,1,2,1,1,2,0,1,0,0,0,1,1,0,1, -1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,0,0,2,1,1,2,0,2,0,0,0,1,1,0,1, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,2,2,1,2,1,1,0,1,0,0,0,1,1,0,1, -2,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,0,1,1,0,1,0,0,1,0,0,0,0,1,0,1, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,2,0,0,0,0,2,1,1,1,0,2,1,1,0,0,0,2,1,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,0,2,1,1,0,1,0,0,0,1,1,0,1, -2,2,1,1,1,0,1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,2,1,1,0,1,0,0,1,1,0,1,2,1,0,2,0,0,0,1,1,0,1, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0, -0,1,0,0,2,0,2,1,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,1,0,1,1,2,0,1,0,0,1,1,1,0,1,0,0,1,0,0,0,1,0,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,2,1,1,1,1,1,0,1,0,0,0,0,1,0,1, -0,1,1,1,2,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,1,2,1,0,0,0,0,0,1,1,1,1,1,0,1,0,0,0,1,1,0,0, -) - -Win1255HebrewModel = { - 'char_to_order_map': WIN1255_CHAR_TO_ORDER_MAP, - 'precedence_matrix': HEBREW_LANG_MODEL, - 'typical_positive_ratio': 0.984004, - 'keep_english_letter': False, - 'charset_name': "windows-1255", - 'language': 'Hebrew', +# Character Mapping Table(s): +WINDOWS_1255_HEBREW_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 69, # 'A' + 66: 91, # 'B' + 67: 79, # 'C' + 68: 80, # 'D' + 69: 92, # 'E' + 70: 89, # 'F' + 71: 97, # 'G' + 72: 90, # 'H' + 73: 68, # 'I' + 74: 111, # 'J' + 75: 112, # 'K' + 76: 82, # 'L' + 77: 73, # 'M' + 78: 95, # 'N' + 79: 85, # 'O' + 80: 78, # 'P' + 81: 121, # 'Q' + 82: 86, # 'R' + 83: 71, # 'S' + 84: 67, # 'T' + 85: 102, # 'U' + 86: 107, # 'V' + 87: 84, # 'W' + 88: 114, # 'X' + 89: 103, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 50, # 'a' + 98: 74, # 'b' + 99: 60, # 'c' + 100: 61, # 'd' + 101: 42, # 'e' + 102: 76, # 'f' + 103: 70, # 'g' + 104: 64, # 'h' + 105: 53, # 'i' + 106: 105, # 'j' + 107: 93, # 'k' + 108: 56, # 'l' + 109: 65, # 'm' + 110: 54, # 'n' + 111: 49, # 'o' + 112: 66, # 'p' + 113: 110, # 'q' + 114: 51, # 'r' + 115: 43, # 's' + 116: 44, # 't' + 117: 63, # 'u' + 118: 81, # 'v' + 119: 77, # 'w' + 120: 98, # 'x' + 121: 75, # 'y' + 122: 108, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 124, # '€' + 129: 202, # None + 130: 203, # '‚' + 131: 204, # 'ƒ' + 132: 205, # '„' + 133: 40, # '…' + 134: 58, # '†' + 135: 206, # '‡' + 136: 207, # 'ˆ' + 137: 208, # '‰' + 138: 209, # None + 139: 210, # '‹' + 140: 211, # None + 141: 212, # None + 142: 213, # None + 143: 214, # None + 144: 215, # None + 145: 83, # '‘' + 146: 52, # '’' + 147: 47, # '“' + 148: 46, # '”' + 149: 72, # '•' + 150: 32, # '–' + 151: 94, # '—' + 152: 216, # '˜' + 153: 113, # '™' + 154: 217, # None + 155: 109, # '›' + 156: 218, # None + 157: 219, # None + 158: 220, # None + 159: 221, # None + 160: 34, # '\xa0' + 161: 116, # '¡' + 162: 222, # '¢' + 163: 118, # '£' + 164: 100, # '₪' + 165: 223, # '¥' + 166: 224, # '¦' + 167: 117, # '§' + 168: 119, # '¨' + 169: 104, # '©' + 170: 125, # '×' + 171: 225, # '«' + 172: 226, # '¬' + 173: 87, # '\xad' + 174: 99, # '®' + 175: 227, # '¯' + 176: 106, # '°' + 177: 122, # '±' + 178: 123, # '²' + 179: 228, # '³' + 180: 55, # '´' + 181: 229, # 'µ' + 182: 230, # '¶' + 183: 101, # '·' + 184: 231, # '¸' + 185: 232, # '¹' + 186: 120, # '÷' + 187: 233, # '»' + 188: 48, # '¼' + 189: 39, # '½' + 190: 57, # '¾' + 191: 234, # '¿' + 192: 30, # 'ְ' + 193: 59, # 'ֱ' + 194: 41, # 'ֲ' + 195: 88, # 'ֳ' + 196: 33, # 'ִ' + 197: 37, # 'ֵ' + 198: 36, # 'ֶ' + 199: 31, # 'ַ' + 200: 29, # 'ָ' + 201: 35, # 'ֹ' + 202: 235, # None + 203: 62, # 'ֻ' + 204: 28, # 'ּ' + 205: 236, # 'ֽ' + 206: 126, # '־' + 207: 237, # 'ֿ' + 208: 238, # '׀' + 209: 38, # 'ׁ' + 210: 45, # 'ׂ' + 211: 239, # '׃' + 212: 240, # 'װ' + 213: 241, # 'ױ' + 214: 242, # 'ײ' + 215: 243, # '׳' + 216: 127, # '״' + 217: 244, # None + 218: 245, # None + 219: 246, # None + 220: 247, # None + 221: 248, # None + 222: 249, # None + 223: 250, # None + 224: 9, # 'א' + 225: 8, # 'ב' + 226: 20, # 'ג' + 227: 16, # 'ד' + 228: 3, # 'ה' + 229: 2, # 'ו' + 230: 24, # 'ז' + 231: 14, # 'ח' + 232: 22, # 'ט' + 233: 1, # 'י' + 234: 25, # 'ך' + 235: 15, # 'כ' + 236: 4, # 'ל' + 237: 11, # 'ם' + 238: 6, # 'מ' + 239: 23, # 'ן' + 240: 12, # 'נ' + 241: 19, # 'ס' + 242: 13, # 'ע' + 243: 26, # 'ף' + 244: 18, # 'פ' + 245: 27, # 'ץ' + 246: 21, # 'צ' + 247: 17, # 'ק' + 248: 7, # 'ר' + 249: 10, # 'ש' + 250: 5, # 'ת' + 251: 251, # None + 252: 252, # None + 253: 128, # '\u200e' + 254: 96, # '\u200f' + 255: 253, # None } + +WINDOWS_1255_HEBREW_MODEL = SingleByteCharSetModel(charset_name='windows-1255', + language='Hebrew', + char_to_order_map=WINDOWS_1255_HEBREW_CHAR_TO_ORDER, + language_model=HEBREW_LANG_MODEL, + typical_positive_ratio=0.984004, + keep_ascii_letters=False, + alphabet='אבגדהוזחטיךכלםמןנסעףפץצקרשתװױײ') + diff --git a/pipenv/vendor/chardet/langhungarianmodel.py b/pipenv/vendor/chardet/langhungarianmodel.py index bb7c095e..24a097f5 100644 --- a/pipenv/vendor/chardet/langhungarianmodel.py +++ b/pipenv/vendor/chardet/langhungarianmodel.py @@ -1,225 +1,4650 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +HUNGARIAN_LANG_MODEL = { + 28: { # 'A' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 2, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 2, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 2, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 1, # 'Á' + 44: 0, # 'É' + 61: 1, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 40: { # 'B' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 3, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 54: { # 'C' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 3, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 45: { # 'D' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 32: { # 'E' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 2, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 50: { # 'F' + 28: 1, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 0, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 49: { # 'G' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 2, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 38: { # 'H' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 0, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 1, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 2, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 2, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 39: { # 'I' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 2, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 53: { # 'J' + 28: 2, # 'A' + 40: 0, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 0, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 36: { # 'K' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 2, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 41: { # 'L' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 34: { # 'M' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 3, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 1, # 'ű' + }, + 35: { # 'N' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 2, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 2, # 'Y' + 52: 1, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 47: { # 'O' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 2, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 1, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 46: { # 'P' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ü' + 14: 3, # 'á' + 15: 2, # 'é' + 30: 0, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 0, # 'ű' + }, + 43: { # 'R' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 2, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 2, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 33: { # 'S' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 3, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 1, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 37: { # 'T' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 2, # 'Á' + 44: 2, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 57: { # 'U' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 1, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 48: { # 'V' + 28: 2, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 2, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 55: { # 'Y' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 2, # 'Z' + 2: 1, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 52: { # 'Z' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 1, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 2, # 'Á' + 44: 1, # 'É' + 61: 1, # 'Í' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 2: { # 'a' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 18: { # 'b' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 26: { # 'c' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 1, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 2, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 2, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 17: { # 'd' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 2, # 'k' + 6: 1, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 1: { # 'e' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 2, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 27: { # 'f' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 3, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 3, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 12: { # 'g' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 20: { # 'h' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 9: { # 'i' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 3, # 'ó' + 24: 1, # 'ö' + 31: 2, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 1, # 'ű' + }, + 22: { # 'j' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 1, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 1, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 7: { # 'k' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 1, # 'ú' + 29: 3, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 6: { # 'l' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 3, # 'ő' + 56: 1, # 'ű' + }, + 13: { # 'm' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 1, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 3, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 2, # 'ű' + }, + 4: { # 'n' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 1, # 'x' + 16: 3, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 8: { # 'o' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 23: { # 'p' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 10: { # 'r' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'ő' + 56: 2, # 'ű' + }, + 5: { # 's' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 3: { # 't' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 1, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 3, # 'ő' + 56: 2, # 'ű' + }, + 21: { # 'u' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 2, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 1, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 1, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 19: { # 'v' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 2, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 1, # 'ű' + }, + 62: { # 'x' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 16: { # 'y' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'ő' + 56: 2, # 'ű' + }, + 11: { # 'z' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'ő' + 56: 1, # 'ű' + }, + 51: { # 'Á' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 1, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 44: { # 'É' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 61: { # 'Í' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 0, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 58: { # 'Ó' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 2, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 1, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 59: { # 'Ö' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 60: { # 'Ú' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 2, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 63: { # 'Ü' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 14: { # 'á' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 15: { # 'é' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 30: { # 'í' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 25: { # 'ó' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 1, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 24: { # 'ö' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 0, # 'a' + 18: 3, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 31: { # 'ú' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 3, # 'j' + 7: 1, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 29: { # 'ü' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 0, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 42: { # 'ő' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, + 56: { # 'ű' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Á' + 44: 0, # 'É' + 61: 0, # 'Í' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ü' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'ő' + 56: 0, # 'ű' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# Character Mapping Table: -Latin2_HungarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, - 46, 71, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, -253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, - 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, -159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174, -175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190, -191,192,193,194,195,196,197, 75,198,199,200,201,202,203,204,205, - 79,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, -221, 51, 81,222, 78,223,224,225,226, 44,227,228,229, 61,230,231, -232,233,234, 58,235, 66, 59,236,237,238, 60, 69, 63,239,240,241, - 82, 14, 74,242, 70, 80,243, 72,244, 15, 83, 77, 84, 30, 76, 85, -245,246,247, 25, 73, 42, 24,248,249,250, 31, 56, 29,251,252,253, -) - -win1250HungarianCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253, 28, 40, 54, 45, 32, 50, 49, 38, 39, 53, 36, 41, 34, 35, 47, - 46, 72, 43, 33, 37, 57, 48, 64, 68, 55, 52,253,253,253,253,253, -253, 2, 18, 26, 17, 1, 27, 12, 20, 9, 22, 7, 6, 13, 4, 8, - 23, 67, 10, 5, 3, 21, 19, 65, 62, 16, 11,253,253,253,253,253, -161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176, -177,178,179,180, 78,181, 69,182,183,184,185,186,187,188,189,190, -191,192,193,194,195,196,197, 76,198,199,200,201,202,203,204,205, - 81,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220, -221, 51, 83,222, 80,223,224,225,226, 44,227,228,229, 61,230,231, -232,233,234, 58,235, 66, 59,236,237,238, 60, 70, 63,239,240,241, - 84, 14, 75,242, 71, 82,243, 73,244, 15, 85, 79, 86, 30, 77, 87, -245,246,247, 25, 74, 42, 24,248,249,250, 31, 56, 29,251,252,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 94.7368% -# first 1024 sequences:5.2623% -# rest sequences: 0.8894% -# negative sequences: 0.0009% -HungarianLangModel = ( -0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, -3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2,3,3,1,1,2,2,2,2,2,1,2, -3,2,2,3,3,3,3,3,2,3,3,3,3,3,3,1,2,3,3,3,3,2,3,3,1,1,3,3,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0, -3,2,1,3,3,3,3,3,2,3,3,3,3,3,1,1,2,3,3,3,3,3,3,3,1,1,3,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,1,1,2,3,3,3,1,3,3,3,3,3,1,3,3,2,2,0,3,2,3, -0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,3,3,2,3,3,2,2,3,2,3,2,0,3,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,1,2,3,2,2,3,1,2,3,3,2,2,0,3,3,3, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,0,2,3,2, -0,0,0,1,1,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,2,1,3,2,2,3,2,1,3,2,2,1,0,3,3,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,2,2,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,3,2,2,3,1,1,3,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,2,2,3,3,3,3,3,2,1,3,3,3,3,3,2,2,1,3,3,3,0,1,1,2, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,2,3,3,2,3,3,3,2,0,3,2,3, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,1,0, -3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,1,3,2,2,2,3,1,1,3,3,1,1,0,3,3,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,2,3,3,3,2,3,2,3,3,3,2,3,3,3,3,3,1,2,3,2,2,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,1,3,3,2,2,1,3,3,3,1,1,3,1,2,3,2,3,2,2,2,1,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,2,1,3,3,3,2,2,3,2,1,0,3,2,0,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,3,3,3,3,3,1,2,3,3,3,3,1,1,0,3,3,3,3,0,2,3,0,0,2,1,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,2,2,3,3,2,2,2,2,3,3,0,1,2,3,2,3,2,2,3,2,1,2,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -3,3,3,3,3,3,1,2,3,3,3,2,1,2,3,3,2,2,2,3,2,3,3,1,3,3,1,1,0,2,3,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,1,2,2,2,2,3,3,3,1,1,1,3,3,1,1,3,1,1,3,2,1,2,3,1,1,0,2,2,2, -0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,1,2,1,1,3,3,1,1,1,1,3,3,1,1,2,2,1,2,1,1,2,2,1,1,0,2,2,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,1,1,2,1,1,3,3,1,0,1,1,3,3,2,0,1,1,2,3,1,0,2,2,1,0,0,1,3,2, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,2,1,3,3,3,3,3,1,2,3,2,3,3,2,1,1,3,2,3,2,1,2,2,0,1,2,1,0,0,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,3,3,2,2,2,2,3,1,2,2,1,1,3,3,0,3,2,1,2,3,2,1,3,3,1,1,0,2,1,3, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,2,3,3,3,2,1,1,3,3,1,1,1,2,2,3,2,3,2,2,2,1,0,2,2,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -1,0,0,3,3,3,3,3,0,0,3,3,2,3,0,0,0,2,3,3,1,0,1,2,0,0,1,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,2,3,3,3,3,3,1,2,3,3,2,2,1,1,0,3,3,2,2,1,2,2,1,0,2,2,0,1,1,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,2,1,3,1,2,3,3,2,2,1,1,2,2,1,1,1,1,3,2,1,1,1,1,2,1,0,1,2,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -2,3,3,1,1,1,1,1,3,3,3,0,1,1,3,3,1,1,1,1,1,2,2,0,3,1,1,2,0,2,1,1, -0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0, -3,1,0,1,2,1,2,2,0,1,2,3,1,2,0,0,0,2,1,1,1,1,1,2,0,0,1,1,0,0,0,0, -1,2,1,2,2,2,1,2,1,2,0,2,0,2,2,1,1,2,1,1,2,1,1,1,0,1,0,0,0,1,1,0, -1,1,1,2,3,2,3,3,0,1,2,2,3,1,0,1,0,2,1,2,2,0,1,1,0,0,1,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,3,3,2,2,1,0,0,3,2,3,2,0,0,0,1,1,3,0,0,1,1,0,0,2,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,2,2,3,3,1,0,1,3,2,3,1,1,1,0,1,1,1,1,1,3,1,0,0,2,2,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,1,1,2,2,2,1,0,1,2,3,3,2,0,0,0,2,1,1,1,2,1,1,1,0,1,1,1,0,0,0, -1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,2,1,1,1,1,1,1,0,1,1,1,0,0,1,1, -3,2,2,1,0,0,1,1,2,2,0,3,0,1,2,1,1,0,0,1,1,1,0,1,1,1,1,0,2,1,1,1, -2,2,1,1,1,2,1,2,1,1,1,1,1,1,1,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,0,1, -2,3,3,0,1,0,0,0,3,3,1,0,0,1,2,2,1,0,0,0,0,2,0,0,1,1,1,0,2,1,1,1, -2,1,1,1,1,1,1,2,1,1,0,1,1,0,1,1,1,0,1,2,1,1,0,1,1,1,1,1,1,1,0,1, -2,3,3,0,1,0,0,0,2,2,0,0,0,0,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,1,0, -2,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, -3,2,2,0,1,0,1,0,2,3,2,0,0,1,2,2,1,0,0,1,1,1,0,0,2,1,0,1,2,2,1,1, -2,1,1,1,1,1,1,2,1,1,1,1,1,1,0,2,1,0,1,1,0,1,1,1,0,1,1,2,1,1,0,1, -2,2,2,0,0,1,0,0,2,2,1,1,0,0,2,1,1,0,0,0,1,2,0,0,2,1,0,0,2,1,1,1, -2,1,1,1,1,2,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,0,1, -1,2,3,0,0,0,1,0,3,2,1,0,0,1,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,2,1, -1,1,0,0,0,1,0,1,1,1,1,1,2,0,0,1,0,0,0,2,0,0,1,1,1,1,1,1,1,1,0,1, -3,0,0,2,1,2,2,1,0,0,2,1,2,2,0,0,0,2,1,1,1,0,1,1,0,0,1,1,2,0,0,0, -1,2,1,2,2,1,1,2,1,2,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,0,0,1, -1,3,2,0,0,0,1,0,2,2,2,0,0,0,2,2,1,0,0,0,0,3,1,1,1,1,0,0,2,1,1,1, -2,1,0,1,1,1,0,1,1,1,1,1,1,1,0,2,1,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1, -2,3,2,0,0,0,1,0,2,2,0,0,0,0,2,1,1,0,0,0,0,2,1,0,1,1,0,0,2,1,1,0, -2,1,1,1,1,2,1,2,1,2,0,1,1,1,0,2,1,1,1,2,1,1,1,1,0,1,1,1,1,1,0,1, -3,1,1,2,2,2,3,2,1,1,2,2,1,1,0,1,0,2,2,1,1,1,1,1,0,0,1,1,0,1,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,0,0,0,0,0,2,2,0,0,0,0,2,2,1,0,0,0,1,1,0,0,1,2,0,0,2,1,1,1, -2,2,1,1,1,2,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,1,1,0,1,2,1,1,1,0,1, -1,0,0,1,2,3,2,1,0,0,2,0,1,1,0,0,0,1,1,1,1,0,1,1,0,0,1,0,0,0,0,0, -1,2,1,2,1,2,1,1,1,2,0,2,1,1,1,0,1,2,0,0,1,1,1,0,0,0,0,0,0,0,0,0, -2,3,2,0,0,0,0,0,1,1,2,1,0,0,1,1,1,0,0,0,0,2,0,0,1,1,0,0,2,1,1,1, -2,1,1,1,1,1,1,2,1,0,1,1,1,1,0,2,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1, -1,2,2,0,1,1,1,0,2,2,2,0,0,0,3,2,1,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0, -1,1,0,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,0,0,1,1,1,0,1,0,1, -2,1,0,2,1,1,2,2,1,1,2,1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,1,1,1,0,0,0, -1,2,2,2,2,2,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,1,0, -1,2,3,0,0,0,1,0,2,2,0,0,0,0,2,2,0,0,0,0,0,1,0,0,1,0,0,0,2,0,1,0, -2,1,1,1,1,1,0,2,0,0,0,1,2,1,1,1,1,0,1,2,0,1,0,1,0,1,1,1,0,1,0,1, -2,2,2,0,0,0,1,0,2,1,2,0,0,0,1,1,2,0,0,0,0,1,0,0,1,1,0,0,2,1,0,1, -2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,1,1,1,1,1,0,1, -1,2,2,0,0,0,1,0,2,2,2,0,0,0,1,1,0,0,0,0,0,1,1,0,2,0,0,1,1,1,0,1, -1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,1, -1,0,0,1,0,1,2,1,0,0,1,1,1,2,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,0, -0,2,1,2,1,1,1,1,1,2,0,2,0,1,1,0,1,2,1,0,1,1,1,0,0,0,0,0,0,1,0,0, -2,1,1,0,1,2,0,0,1,1,1,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,2,1,0,1, -2,2,1,1,1,1,1,2,1,1,0,1,1,1,1,2,1,1,1,2,1,1,0,1,0,1,1,1,1,1,0,1, -1,2,2,0,0,0,0,0,1,1,0,0,0,0,2,1,0,0,0,0,0,2,0,0,2,2,0,0,2,0,0,1, -2,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,0,0,0,1,1,1,1,0,0,1,1,1,1,0,0,1, -1,1,2,0,0,3,1,0,2,1,1,1,0,0,1,1,1,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0, -1,2,1,0,1,1,1,2,1,1,0,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0, -2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,0,2,0,0,0, -2,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,2,1,1,0,0,1,1,1,1,1,0,1, -2,1,1,1,2,1,1,1,0,1,1,2,1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,0,1,1,1,1,1,0,0,1,1,2,1,0,0,0,1,1,0,0,0,1,1,0,0,1,0,1,0,0,0, -1,2,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0, -2,0,0,0,1,1,1,1,0,0,1,1,0,0,0,0,0,1,1,1,2,0,0,1,0,0,1,0,1,0,0,0, -0,1,1,1,1,1,1,1,1,2,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,1,0,0,2,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0, -0,1,1,1,1,1,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -0,1,1,1,1,1,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,1,1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0, -2,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,1,1,1,0,0,1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,1,1,1,1,1,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -) - -Latin2HungarianModel = { - 'char_to_order_map': Latin2_HungarianCharToOrderMap, - 'precedence_matrix': HungarianLangModel, - 'typical_positive_ratio': 0.947368, - 'keep_english_letter': True, - 'charset_name': "ISO-8859-2", - 'language': 'Hungarian', +# Character Mapping Table(s): +WINDOWS_1250_HUNGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 28, # 'A' + 66: 40, # 'B' + 67: 54, # 'C' + 68: 45, # 'D' + 69: 32, # 'E' + 70: 50, # 'F' + 71: 49, # 'G' + 72: 38, # 'H' + 73: 39, # 'I' + 74: 53, # 'J' + 75: 36, # 'K' + 76: 41, # 'L' + 77: 34, # 'M' + 78: 35, # 'N' + 79: 47, # 'O' + 80: 46, # 'P' + 81: 72, # 'Q' + 82: 43, # 'R' + 83: 33, # 'S' + 84: 37, # 'T' + 85: 57, # 'U' + 86: 48, # 'V' + 87: 64, # 'W' + 88: 68, # 'X' + 89: 55, # 'Y' + 90: 52, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 2, # 'a' + 98: 18, # 'b' + 99: 26, # 'c' + 100: 17, # 'd' + 101: 1, # 'e' + 102: 27, # 'f' + 103: 12, # 'g' + 104: 20, # 'h' + 105: 9, # 'i' + 106: 22, # 'j' + 107: 7, # 'k' + 108: 6, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 8, # 'o' + 112: 23, # 'p' + 113: 67, # 'q' + 114: 10, # 'r' + 115: 5, # 's' + 116: 3, # 't' + 117: 21, # 'u' + 118: 19, # 'v' + 119: 65, # 'w' + 120: 62, # 'x' + 121: 16, # 'y' + 122: 11, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 161, # '€' + 129: 162, # None + 130: 163, # '‚' + 131: 164, # None + 132: 165, # '„' + 133: 166, # '…' + 134: 167, # '†' + 135: 168, # '‡' + 136: 169, # None + 137: 170, # '‰' + 138: 171, # 'Š' + 139: 172, # '‹' + 140: 173, # 'Ś' + 141: 174, # 'Ť' + 142: 175, # 'Ž' + 143: 176, # 'Ź' + 144: 177, # None + 145: 178, # '‘' + 146: 179, # '’' + 147: 180, # '“' + 148: 78, # '”' + 149: 181, # '•' + 150: 69, # '–' + 151: 182, # '—' + 152: 183, # None + 153: 184, # '™' + 154: 185, # 'š' + 155: 186, # '›' + 156: 187, # 'ś' + 157: 188, # 'ť' + 158: 189, # 'ž' + 159: 190, # 'ź' + 160: 191, # '\xa0' + 161: 192, # 'ˇ' + 162: 193, # '˘' + 163: 194, # 'Ł' + 164: 195, # '¤' + 165: 196, # 'Ą' + 166: 197, # '¦' + 167: 76, # '§' + 168: 198, # '¨' + 169: 199, # '©' + 170: 200, # 'Ş' + 171: 201, # '«' + 172: 202, # '¬' + 173: 203, # '\xad' + 174: 204, # '®' + 175: 205, # 'Ż' + 176: 81, # '°' + 177: 206, # '±' + 178: 207, # '˛' + 179: 208, # 'ł' + 180: 209, # '´' + 181: 210, # 'µ' + 182: 211, # '¶' + 183: 212, # '·' + 184: 213, # '¸' + 185: 214, # 'ą' + 186: 215, # 'ş' + 187: 216, # '»' + 188: 217, # 'Ľ' + 189: 218, # '˝' + 190: 219, # 'ľ' + 191: 220, # 'ż' + 192: 221, # 'Ŕ' + 193: 51, # 'Á' + 194: 83, # 'Â' + 195: 222, # 'Ă' + 196: 80, # 'Ä' + 197: 223, # 'Ĺ' + 198: 224, # 'Ć' + 199: 225, # 'Ç' + 200: 226, # 'Č' + 201: 44, # 'É' + 202: 227, # 'Ę' + 203: 228, # 'Ë' + 204: 229, # 'Ě' + 205: 61, # 'Í' + 206: 230, # 'Î' + 207: 231, # 'Ď' + 208: 232, # 'Đ' + 209: 233, # 'Ń' + 210: 234, # 'Ň' + 211: 58, # 'Ó' + 212: 235, # 'Ô' + 213: 66, # 'Ő' + 214: 59, # 'Ö' + 215: 236, # '×' + 216: 237, # 'Ř' + 217: 238, # 'Ů' + 218: 60, # 'Ú' + 219: 70, # 'Ű' + 220: 63, # 'Ü' + 221: 239, # 'Ý' + 222: 240, # 'Ţ' + 223: 241, # 'ß' + 224: 84, # 'ŕ' + 225: 14, # 'á' + 226: 75, # 'â' + 227: 242, # 'ă' + 228: 71, # 'ä' + 229: 82, # 'ĺ' + 230: 243, # 'ć' + 231: 73, # 'ç' + 232: 244, # 'č' + 233: 15, # 'é' + 234: 85, # 'ę' + 235: 79, # 'ë' + 236: 86, # 'ě' + 237: 30, # 'í' + 238: 77, # 'î' + 239: 87, # 'ď' + 240: 245, # 'đ' + 241: 246, # 'ń' + 242: 247, # 'ň' + 243: 25, # 'ó' + 244: 74, # 'ô' + 245: 42, # 'ő' + 246: 24, # 'ö' + 247: 248, # '÷' + 248: 249, # 'ř' + 249: 250, # 'ů' + 250: 31, # 'ú' + 251: 56, # 'ű' + 252: 29, # 'ü' + 253: 251, # 'ý' + 254: 252, # 'ţ' + 255: 253, # '˙' } -Win1250HungarianModel = { - 'char_to_order_map': win1250HungarianCharToOrderMap, - 'precedence_matrix': HungarianLangModel, - 'typical_positive_ratio': 0.947368, - 'keep_english_letter': True, - 'charset_name': "windows-1250", - 'language': 'Hungarian', +WINDOWS_1250_HUNGARIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1250', + language='Hungarian', + char_to_order_map=WINDOWS_1250_HUNGARIAN_CHAR_TO_ORDER, + language_model=HUNGARIAN_LANG_MODEL, + typical_positive_ratio=0.947368, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVZabcdefghijklmnoprstuvzÁÉÍÓÖÚÜáéíóöúüŐőŰű') + +ISO_8859_2_HUNGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 28, # 'A' + 66: 40, # 'B' + 67: 54, # 'C' + 68: 45, # 'D' + 69: 32, # 'E' + 70: 50, # 'F' + 71: 49, # 'G' + 72: 38, # 'H' + 73: 39, # 'I' + 74: 53, # 'J' + 75: 36, # 'K' + 76: 41, # 'L' + 77: 34, # 'M' + 78: 35, # 'N' + 79: 47, # 'O' + 80: 46, # 'P' + 81: 71, # 'Q' + 82: 43, # 'R' + 83: 33, # 'S' + 84: 37, # 'T' + 85: 57, # 'U' + 86: 48, # 'V' + 87: 64, # 'W' + 88: 68, # 'X' + 89: 55, # 'Y' + 90: 52, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 2, # 'a' + 98: 18, # 'b' + 99: 26, # 'c' + 100: 17, # 'd' + 101: 1, # 'e' + 102: 27, # 'f' + 103: 12, # 'g' + 104: 20, # 'h' + 105: 9, # 'i' + 106: 22, # 'j' + 107: 7, # 'k' + 108: 6, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 8, # 'o' + 112: 23, # 'p' + 113: 67, # 'q' + 114: 10, # 'r' + 115: 5, # 's' + 116: 3, # 't' + 117: 21, # 'u' + 118: 19, # 'v' + 119: 65, # 'w' + 120: 62, # 'x' + 121: 16, # 'y' + 122: 11, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 159, # '\x80' + 129: 160, # '\x81' + 130: 161, # '\x82' + 131: 162, # '\x83' + 132: 163, # '\x84' + 133: 164, # '\x85' + 134: 165, # '\x86' + 135: 166, # '\x87' + 136: 167, # '\x88' + 137: 168, # '\x89' + 138: 169, # '\x8a' + 139: 170, # '\x8b' + 140: 171, # '\x8c' + 141: 172, # '\x8d' + 142: 173, # '\x8e' + 143: 174, # '\x8f' + 144: 175, # '\x90' + 145: 176, # '\x91' + 146: 177, # '\x92' + 147: 178, # '\x93' + 148: 179, # '\x94' + 149: 180, # '\x95' + 150: 181, # '\x96' + 151: 182, # '\x97' + 152: 183, # '\x98' + 153: 184, # '\x99' + 154: 185, # '\x9a' + 155: 186, # '\x9b' + 156: 187, # '\x9c' + 157: 188, # '\x9d' + 158: 189, # '\x9e' + 159: 190, # '\x9f' + 160: 191, # '\xa0' + 161: 192, # 'Ą' + 162: 193, # '˘' + 163: 194, # 'Ł' + 164: 195, # '¤' + 165: 196, # 'Ľ' + 166: 197, # 'Ś' + 167: 75, # '§' + 168: 198, # '¨' + 169: 199, # 'Š' + 170: 200, # 'Ş' + 171: 201, # 'Ť' + 172: 202, # 'Ź' + 173: 203, # '\xad' + 174: 204, # 'Ž' + 175: 205, # 'Ż' + 176: 79, # '°' + 177: 206, # 'ą' + 178: 207, # '˛' + 179: 208, # 'ł' + 180: 209, # '´' + 181: 210, # 'ľ' + 182: 211, # 'ś' + 183: 212, # 'ˇ' + 184: 213, # '¸' + 185: 214, # 'š' + 186: 215, # 'ş' + 187: 216, # 'ť' + 188: 217, # 'ź' + 189: 218, # '˝' + 190: 219, # 'ž' + 191: 220, # 'ż' + 192: 221, # 'Ŕ' + 193: 51, # 'Á' + 194: 81, # 'Â' + 195: 222, # 'Ă' + 196: 78, # 'Ä' + 197: 223, # 'Ĺ' + 198: 224, # 'Ć' + 199: 225, # 'Ç' + 200: 226, # 'Č' + 201: 44, # 'É' + 202: 227, # 'Ę' + 203: 228, # 'Ë' + 204: 229, # 'Ě' + 205: 61, # 'Í' + 206: 230, # 'Î' + 207: 231, # 'Ď' + 208: 232, # 'Đ' + 209: 233, # 'Ń' + 210: 234, # 'Ň' + 211: 58, # 'Ó' + 212: 235, # 'Ô' + 213: 66, # 'Ő' + 214: 59, # 'Ö' + 215: 236, # '×' + 216: 237, # 'Ř' + 217: 238, # 'Ů' + 218: 60, # 'Ú' + 219: 69, # 'Ű' + 220: 63, # 'Ü' + 221: 239, # 'Ý' + 222: 240, # 'Ţ' + 223: 241, # 'ß' + 224: 82, # 'ŕ' + 225: 14, # 'á' + 226: 74, # 'â' + 227: 242, # 'ă' + 228: 70, # 'ä' + 229: 80, # 'ĺ' + 230: 243, # 'ć' + 231: 72, # 'ç' + 232: 244, # 'č' + 233: 15, # 'é' + 234: 83, # 'ę' + 235: 77, # 'ë' + 236: 84, # 'ě' + 237: 30, # 'í' + 238: 76, # 'î' + 239: 85, # 'ď' + 240: 245, # 'đ' + 241: 246, # 'ń' + 242: 247, # 'ň' + 243: 25, # 'ó' + 244: 73, # 'ô' + 245: 42, # 'ő' + 246: 24, # 'ö' + 247: 248, # '÷' + 248: 249, # 'ř' + 249: 250, # 'ů' + 250: 31, # 'ú' + 251: 56, # 'ű' + 252: 29, # 'ü' + 253: 251, # 'ý' + 254: 252, # 'ţ' + 255: 253, # '˙' } + +ISO_8859_2_HUNGARIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-2', + language='Hungarian', + char_to_order_map=ISO_8859_2_HUNGARIAN_CHAR_TO_ORDER, + language_model=HUNGARIAN_LANG_MODEL, + typical_positive_ratio=0.947368, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVZabcdefghijklmnoprstuvzÁÉÍÓÖÚÜáéíóöúüŐőŰű') + diff --git a/pipenv/vendor/chardet/langrussianmodel.py b/pipenv/vendor/chardet/langrussianmodel.py new file mode 100644 index 00000000..569689d0 --- /dev/null +++ b/pipenv/vendor/chardet/langrussianmodel.py @@ -0,0 +1,5718 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +RUSSIAN_LANG_MODEL = { + 37: { # 'А' + 37: 0, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 2, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 2, # 'ф' + 26: 2, # 'х' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 44: { # 'Б' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 2, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 33: { # 'В' + 37: 2, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ъ' + 18: 3, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 0, # 'ю' + 16: 1, # 'я' + }, + 46: { # 'Г' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 1, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 41: { # 'Д' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 3, # 'ж' + 20: 1, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 48: { # 'Е' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 2, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 2, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 1, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'р' + 7: 3, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 56: { # 'Ж' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 1, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 2, # 'ю' + 16: 0, # 'я' + }, + 51: { # 'З' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 1, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 1, # 'я' + }, + 42: { # 'И' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 2, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 1, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 60: { # 'Й' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 36: { # 'К' + 37: 2, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 2, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 49: { # 'Л' + 37: 2, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 0, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 2, # 'ю' + 16: 1, # 'я' + }, + 38: { # 'М' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 1, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 1, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 31: { # 'Н' + 37: 2, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 2, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 3, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 34: { # 'О' + 37: 0, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 2, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 2, # 'Л' + 38: 1, # 'М' + 31: 2, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 1, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 35: { # 'П' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'р' + 7: 1, # 'с' + 6: 1, # 'т' + 14: 2, # 'у' + 39: 1, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 0, # 'ю' + 16: 2, # 'я' + }, + 45: { # 'Р' + 37: 2, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 2, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 2, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 2, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 2, # 'я' + }, + 32: { # 'С' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 2, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 1, # 'с' + 6: 3, # 'т' + 14: 2, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 40: { # 'Т' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 2, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 1, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 52: { # 'У' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 1, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 1, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 0, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 53: { # 'Ф' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 1, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 55: { # 'Х' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 1, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 1, # 'ь' + 30: 1, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 58: { # 'Ц' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 1, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 50: { # 'Ч' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 3, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 1, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 57: { # 'Ш' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 63: { # 'Щ' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 1, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 62: { # 'Ы' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 61: { # 'Ь' + 37: 0, # 'А' + 44: 1, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 47: { # 'Э' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 1, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 59: { # 'Ю' + 37: 1, # 'А' + 44: 1, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'р' + 7: 1, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 43: { # 'Я' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 1, # 'В' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Х' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 1, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'р' + 7: 1, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 3: { # 'а' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 2, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 21: { # 'б' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 0, # 'ф' + 26: 2, # 'х' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 2, # 'ю' + 16: 3, # 'я' + }, + 10: { # 'в' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 3, # 'я' + }, + 19: { # 'г' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 13: { # 'д' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 3, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 1, # 'э' + 27: 2, # 'ю' + 16: 3, # 'я' + }, + 2: { # 'е' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 2, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 2, # 'ю' + 16: 3, # 'я' + }, + 24: { # 'ж' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 1, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 0, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 20: { # 'з' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 3, # 'я' + }, + 4: { # 'и' + 37: 1, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 2, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 2, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 23: { # 'й' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 2, # 'ф' + 26: 1, # 'х' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 2, # 'я' + }, + 11: { # 'к' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 3, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 2, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 1, # 'ы' + 17: 1, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 8: { # 'л' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 3, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 1, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 2, # 'х' + 28: 1, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 1, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 12: { # 'м' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 2, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 2, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 3, # 'я' + }, + 5: { # 'н' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 2, # 'х' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 2, # 'щ' + 54: 1, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 1, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 1: { # 'о' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 2, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 2, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 15: { # 'п' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 0, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 2, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 3, # 'я' + }, + 9: { # 'р' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 2, # 'э' + 27: 2, # 'ю' + 16: 3, # 'я' + }, + 7: { # 'с' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 2, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 6: { # 'т' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 2, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 2, # 'щ' + 54: 2, # 'ъ' + 18: 3, # 'ы' + 17: 3, # 'ь' + 30: 2, # 'э' + 27: 2, # 'ю' + 16: 3, # 'я' + }, + 14: { # 'у' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 2, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 2, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 2, # 'э' + 27: 3, # 'ю' + 16: 2, # 'я' + }, + 39: { # 'ф' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 2, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 2, # 'ы' + 17: 1, # 'ь' + 30: 2, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 26: { # 'х' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 3, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 3, # 'р' + 7: 2, # 'с' + 6: 2, # 'т' + 14: 2, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ъ' + 18: 0, # 'ы' + 17: 1, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 28: { # 'ц' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'р' + 7: 0, # 'с' + 6: 1, # 'т' + 14: 3, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 1, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 3, # 'ы' + 17: 1, # 'ь' + 30: 0, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 22: { # 'ч' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 1, # 'с' + 6: 3, # 'т' + 14: 3, # 'у' + 39: 1, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 3, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 25: { # 'ш' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 1, # 'с' + 6: 2, # 'т' + 14: 3, # 'у' + 39: 2, # 'ф' + 26: 1, # 'х' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 3, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 0, # 'я' + }, + 29: { # 'щ' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 2, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 2, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 2, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 0, # 'я' + }, + 54: { # 'ъ' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'р' + 7: 0, # 'с' + 6: 0, # 'т' + 14: 0, # 'у' + 39: 0, # 'ф' + 26: 0, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 1, # 'ю' + 16: 2, # 'я' + }, + 18: { # 'ы' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 1, # 'о' + 15: 3, # 'п' + 9: 3, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 0, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 0, # 'ю' + 16: 2, # 'я' + }, + 17: { # 'ь' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 0, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 1, # 'р' + 7: 3, # 'с' + 6: 2, # 'т' + 14: 0, # 'у' + 39: 2, # 'ф' + 26: 1, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 3, # 'ю' + 16: 3, # 'я' + }, + 30: { # 'э' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 1, # 'М' + 31: 1, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 2, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 2, # 'ф' + 26: 1, # 'х' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 1, # 'ю' + 16: 1, # 'я' + }, + 27: { # 'ю' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 1, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 0, # 'у' + 39: 1, # 'ф' + 26: 2, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 1, # 'э' + 27: 2, # 'ю' + 16: 1, # 'я' + }, + 16: { # 'я' + 37: 0, # 'А' + 44: 0, # 'Б' + 33: 0, # 'В' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'М' + 31: 0, # 'Н' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Х' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 2, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'р' + 7: 3, # 'с' + 6: 3, # 'т' + 14: 1, # 'у' + 39: 1, # 'ф' + 26: 3, # 'х' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ъ' + 18: 0, # 'ы' + 17: 0, # 'ь' + 30: 0, # 'э' + 27: 2, # 'ю' + 16: 2, # 'я' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +IBM866_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 37, # 'А' + 129: 44, # 'Б' + 130: 33, # 'В' + 131: 46, # 'Г' + 132: 41, # 'Д' + 133: 48, # 'Е' + 134: 56, # 'Ж' + 135: 51, # 'З' + 136: 42, # 'И' + 137: 60, # 'Й' + 138: 36, # 'К' + 139: 49, # 'Л' + 140: 38, # 'М' + 141: 31, # 'Н' + 142: 34, # 'О' + 143: 35, # 'П' + 144: 45, # 'Р' + 145: 32, # 'С' + 146: 40, # 'Т' + 147: 52, # 'У' + 148: 53, # 'Ф' + 149: 55, # 'Х' + 150: 58, # 'Ц' + 151: 50, # 'Ч' + 152: 57, # 'Ш' + 153: 63, # 'Щ' + 154: 70, # 'Ъ' + 155: 62, # 'Ы' + 156: 61, # 'Ь' + 157: 47, # 'Э' + 158: 59, # 'Ю' + 159: 43, # 'Я' + 160: 3, # 'а' + 161: 21, # 'б' + 162: 10, # 'в' + 163: 19, # 'г' + 164: 13, # 'д' + 165: 2, # 'е' + 166: 24, # 'ж' + 167: 20, # 'з' + 168: 4, # 'и' + 169: 23, # 'й' + 170: 11, # 'к' + 171: 8, # 'л' + 172: 12, # 'м' + 173: 5, # 'н' + 174: 1, # 'о' + 175: 15, # 'п' + 176: 191, # '░' + 177: 192, # '▒' + 178: 193, # '▓' + 179: 194, # '│' + 180: 195, # '┤' + 181: 196, # '╡' + 182: 197, # '╢' + 183: 198, # '╖' + 184: 199, # '╕' + 185: 200, # '╣' + 186: 201, # '║' + 187: 202, # '╗' + 188: 203, # '╝' + 189: 204, # '╜' + 190: 205, # '╛' + 191: 206, # '┐' + 192: 207, # '└' + 193: 208, # '┴' + 194: 209, # '┬' + 195: 210, # '├' + 196: 211, # '─' + 197: 212, # '┼' + 198: 213, # '╞' + 199: 214, # '╟' + 200: 215, # '╚' + 201: 216, # '╔' + 202: 217, # '╩' + 203: 218, # '╦' + 204: 219, # '╠' + 205: 220, # '═' + 206: 221, # '╬' + 207: 222, # '╧' + 208: 223, # '╨' + 209: 224, # '╤' + 210: 225, # '╥' + 211: 226, # '╙' + 212: 227, # '╘' + 213: 228, # '╒' + 214: 229, # '╓' + 215: 230, # '╫' + 216: 231, # '╪' + 217: 232, # '┘' + 218: 233, # '┌' + 219: 234, # '█' + 220: 235, # '▄' + 221: 236, # '▌' + 222: 237, # '▐' + 223: 238, # '▀' + 224: 9, # 'р' + 225: 7, # 'с' + 226: 6, # 'т' + 227: 14, # 'у' + 228: 39, # 'ф' + 229: 26, # 'х' + 230: 28, # 'ц' + 231: 22, # 'ч' + 232: 25, # 'ш' + 233: 29, # 'щ' + 234: 54, # 'ъ' + 235: 18, # 'ы' + 236: 17, # 'ь' + 237: 30, # 'э' + 238: 27, # 'ю' + 239: 16, # 'я' + 240: 239, # 'Ё' + 241: 68, # 'ё' + 242: 240, # 'Є' + 243: 241, # 'є' + 244: 242, # 'Ї' + 245: 243, # 'ї' + 246: 244, # 'Ў' + 247: 245, # 'ў' + 248: 246, # '°' + 249: 247, # '∙' + 250: 248, # '·' + 251: 249, # '√' + 252: 250, # '№' + 253: 251, # '¤' + 254: 252, # '■' + 255: 255, # '\xa0' +} + +IBM866_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='IBM866', + language='Russian', + char_to_order_map=IBM866_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + +WINDOWS_1251_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # 'Ђ' + 129: 192, # 'Ѓ' + 130: 193, # '‚' + 131: 194, # 'ѓ' + 132: 195, # '„' + 133: 196, # '…' + 134: 197, # '†' + 135: 198, # '‡' + 136: 199, # '€' + 137: 200, # '‰' + 138: 201, # 'Љ' + 139: 202, # '‹' + 140: 203, # 'Њ' + 141: 204, # 'Ќ' + 142: 205, # 'Ћ' + 143: 206, # 'Џ' + 144: 207, # 'ђ' + 145: 208, # '‘' + 146: 209, # '’' + 147: 210, # '“' + 148: 211, # '”' + 149: 212, # '•' + 150: 213, # '–' + 151: 214, # '—' + 152: 215, # None + 153: 216, # '™' + 154: 217, # 'љ' + 155: 218, # '›' + 156: 219, # 'њ' + 157: 220, # 'ќ' + 158: 221, # 'ћ' + 159: 222, # 'џ' + 160: 223, # '\xa0' + 161: 224, # 'Ў' + 162: 225, # 'ў' + 163: 226, # 'Ј' + 164: 227, # '¤' + 165: 228, # 'Ґ' + 166: 229, # '¦' + 167: 230, # '§' + 168: 231, # 'Ё' + 169: 232, # '©' + 170: 233, # 'Є' + 171: 234, # '«' + 172: 235, # '¬' + 173: 236, # '\xad' + 174: 237, # '®' + 175: 238, # 'Ї' + 176: 239, # '°' + 177: 240, # '±' + 178: 241, # 'І' + 179: 242, # 'і' + 180: 243, # 'ґ' + 181: 244, # 'µ' + 182: 245, # '¶' + 183: 246, # '·' + 184: 68, # 'ё' + 185: 247, # '№' + 186: 248, # 'є' + 187: 249, # '»' + 188: 250, # 'ј' + 189: 251, # 'Ѕ' + 190: 252, # 'ѕ' + 191: 253, # 'ї' + 192: 37, # 'А' + 193: 44, # 'Б' + 194: 33, # 'В' + 195: 46, # 'Г' + 196: 41, # 'Д' + 197: 48, # 'Е' + 198: 56, # 'Ж' + 199: 51, # 'З' + 200: 42, # 'И' + 201: 60, # 'Й' + 202: 36, # 'К' + 203: 49, # 'Л' + 204: 38, # 'М' + 205: 31, # 'Н' + 206: 34, # 'О' + 207: 35, # 'П' + 208: 45, # 'Р' + 209: 32, # 'С' + 210: 40, # 'Т' + 211: 52, # 'У' + 212: 53, # 'Ф' + 213: 55, # 'Х' + 214: 58, # 'Ц' + 215: 50, # 'Ч' + 216: 57, # 'Ш' + 217: 63, # 'Щ' + 218: 70, # 'Ъ' + 219: 62, # 'Ы' + 220: 61, # 'Ь' + 221: 47, # 'Э' + 222: 59, # 'Ю' + 223: 43, # 'Я' + 224: 3, # 'а' + 225: 21, # 'б' + 226: 10, # 'в' + 227: 19, # 'г' + 228: 13, # 'д' + 229: 2, # 'е' + 230: 24, # 'ж' + 231: 20, # 'з' + 232: 4, # 'и' + 233: 23, # 'й' + 234: 11, # 'к' + 235: 8, # 'л' + 236: 12, # 'м' + 237: 5, # 'н' + 238: 1, # 'о' + 239: 15, # 'п' + 240: 9, # 'р' + 241: 7, # 'с' + 242: 6, # 'т' + 243: 14, # 'у' + 244: 39, # 'ф' + 245: 26, # 'х' + 246: 28, # 'ц' + 247: 22, # 'ч' + 248: 25, # 'ш' + 249: 29, # 'щ' + 250: 54, # 'ъ' + 251: 18, # 'ы' + 252: 17, # 'ь' + 253: 30, # 'э' + 254: 27, # 'ю' + 255: 16, # 'я' +} + +WINDOWS_1251_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1251', + language='Russian', + char_to_order_map=WINDOWS_1251_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + +IBM855_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # 'ђ' + 129: 192, # 'Ђ' + 130: 193, # 'ѓ' + 131: 194, # 'Ѓ' + 132: 68, # 'ё' + 133: 195, # 'Ё' + 134: 196, # 'є' + 135: 197, # 'Є' + 136: 198, # 'ѕ' + 137: 199, # 'Ѕ' + 138: 200, # 'і' + 139: 201, # 'І' + 140: 202, # 'ї' + 141: 203, # 'Ї' + 142: 204, # 'ј' + 143: 205, # 'Ј' + 144: 206, # 'љ' + 145: 207, # 'Љ' + 146: 208, # 'њ' + 147: 209, # 'Њ' + 148: 210, # 'ћ' + 149: 211, # 'Ћ' + 150: 212, # 'ќ' + 151: 213, # 'Ќ' + 152: 214, # 'ў' + 153: 215, # 'Ў' + 154: 216, # 'џ' + 155: 217, # 'Џ' + 156: 27, # 'ю' + 157: 59, # 'Ю' + 158: 54, # 'ъ' + 159: 70, # 'Ъ' + 160: 3, # 'а' + 161: 37, # 'А' + 162: 21, # 'б' + 163: 44, # 'Б' + 164: 28, # 'ц' + 165: 58, # 'Ц' + 166: 13, # 'д' + 167: 41, # 'Д' + 168: 2, # 'е' + 169: 48, # 'Е' + 170: 39, # 'ф' + 171: 53, # 'Ф' + 172: 19, # 'г' + 173: 46, # 'Г' + 174: 218, # '«' + 175: 219, # '»' + 176: 220, # '░' + 177: 221, # '▒' + 178: 222, # '▓' + 179: 223, # '│' + 180: 224, # '┤' + 181: 26, # 'х' + 182: 55, # 'Х' + 183: 4, # 'и' + 184: 42, # 'И' + 185: 225, # '╣' + 186: 226, # '║' + 187: 227, # '╗' + 188: 228, # '╝' + 189: 23, # 'й' + 190: 60, # 'Й' + 191: 229, # '┐' + 192: 230, # '└' + 193: 231, # '┴' + 194: 232, # '┬' + 195: 233, # '├' + 196: 234, # '─' + 197: 235, # '┼' + 198: 11, # 'к' + 199: 36, # 'К' + 200: 236, # '╚' + 201: 237, # '╔' + 202: 238, # '╩' + 203: 239, # '╦' + 204: 240, # '╠' + 205: 241, # '═' + 206: 242, # '╬' + 207: 243, # '¤' + 208: 8, # 'л' + 209: 49, # 'Л' + 210: 12, # 'м' + 211: 38, # 'М' + 212: 5, # 'н' + 213: 31, # 'Н' + 214: 1, # 'о' + 215: 34, # 'О' + 216: 15, # 'п' + 217: 244, # '┘' + 218: 245, # '┌' + 219: 246, # '█' + 220: 247, # '▄' + 221: 35, # 'П' + 222: 16, # 'я' + 223: 248, # '▀' + 224: 43, # 'Я' + 225: 9, # 'р' + 226: 45, # 'Р' + 227: 7, # 'с' + 228: 32, # 'С' + 229: 6, # 'т' + 230: 40, # 'Т' + 231: 14, # 'у' + 232: 52, # 'У' + 233: 24, # 'ж' + 234: 56, # 'Ж' + 235: 10, # 'в' + 236: 33, # 'В' + 237: 17, # 'ь' + 238: 61, # 'Ь' + 239: 249, # '№' + 240: 250, # '\xad' + 241: 18, # 'ы' + 242: 62, # 'Ы' + 243: 20, # 'з' + 244: 51, # 'З' + 245: 25, # 'ш' + 246: 57, # 'Ш' + 247: 30, # 'э' + 248: 47, # 'Э' + 249: 29, # 'щ' + 250: 63, # 'Щ' + 251: 22, # 'ч' + 252: 50, # 'Ч' + 253: 251, # '§' + 254: 252, # '■' + 255: 255, # '\xa0' +} + +IBM855_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='IBM855', + language='Russian', + char_to_order_map=IBM855_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + +KOI8_R_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # '─' + 129: 192, # '│' + 130: 193, # '┌' + 131: 194, # '┐' + 132: 195, # '└' + 133: 196, # '┘' + 134: 197, # '├' + 135: 198, # '┤' + 136: 199, # '┬' + 137: 200, # '┴' + 138: 201, # '┼' + 139: 202, # '▀' + 140: 203, # '▄' + 141: 204, # '█' + 142: 205, # '▌' + 143: 206, # '▐' + 144: 207, # '░' + 145: 208, # '▒' + 146: 209, # '▓' + 147: 210, # '⌠' + 148: 211, # '■' + 149: 212, # '∙' + 150: 213, # '√' + 151: 214, # '≈' + 152: 215, # '≤' + 153: 216, # '≥' + 154: 217, # '\xa0' + 155: 218, # '⌡' + 156: 219, # '°' + 157: 220, # '²' + 158: 221, # '·' + 159: 222, # '÷' + 160: 223, # '═' + 161: 224, # '║' + 162: 225, # '╒' + 163: 68, # 'ё' + 164: 226, # '╓' + 165: 227, # '╔' + 166: 228, # '╕' + 167: 229, # '╖' + 168: 230, # '╗' + 169: 231, # '╘' + 170: 232, # '╙' + 171: 233, # '╚' + 172: 234, # '╛' + 173: 235, # '╜' + 174: 236, # '╝' + 175: 237, # '╞' + 176: 238, # '╟' + 177: 239, # '╠' + 178: 240, # '╡' + 179: 241, # 'Ё' + 180: 242, # '╢' + 181: 243, # '╣' + 182: 244, # '╤' + 183: 245, # '╥' + 184: 246, # '╦' + 185: 247, # '╧' + 186: 248, # '╨' + 187: 249, # '╩' + 188: 250, # '╪' + 189: 251, # '╫' + 190: 252, # '╬' + 191: 253, # '©' + 192: 27, # 'ю' + 193: 3, # 'а' + 194: 21, # 'б' + 195: 28, # 'ц' + 196: 13, # 'д' + 197: 2, # 'е' + 198: 39, # 'ф' + 199: 19, # 'г' + 200: 26, # 'х' + 201: 4, # 'и' + 202: 23, # 'й' + 203: 11, # 'к' + 204: 8, # 'л' + 205: 12, # 'м' + 206: 5, # 'н' + 207: 1, # 'о' + 208: 15, # 'п' + 209: 16, # 'я' + 210: 9, # 'р' + 211: 7, # 'с' + 212: 6, # 'т' + 213: 14, # 'у' + 214: 24, # 'ж' + 215: 10, # 'в' + 216: 17, # 'ь' + 217: 18, # 'ы' + 218: 20, # 'з' + 219: 25, # 'ш' + 220: 30, # 'э' + 221: 29, # 'щ' + 222: 22, # 'ч' + 223: 54, # 'ъ' + 224: 59, # 'Ю' + 225: 37, # 'А' + 226: 44, # 'Б' + 227: 58, # 'Ц' + 228: 41, # 'Д' + 229: 48, # 'Е' + 230: 53, # 'Ф' + 231: 46, # 'Г' + 232: 55, # 'Х' + 233: 42, # 'И' + 234: 60, # 'Й' + 235: 36, # 'К' + 236: 49, # 'Л' + 237: 38, # 'М' + 238: 31, # 'Н' + 239: 34, # 'О' + 240: 35, # 'П' + 241: 43, # 'Я' + 242: 45, # 'Р' + 243: 32, # 'С' + 244: 40, # 'Т' + 245: 52, # 'У' + 246: 56, # 'Ж' + 247: 33, # 'В' + 248: 61, # 'Ь' + 249: 62, # 'Ы' + 250: 51, # 'З' + 251: 57, # 'Ш' + 252: 47, # 'Э' + 253: 63, # 'Щ' + 254: 50, # 'Ч' + 255: 70, # 'Ъ' +} + +KOI8_R_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='KOI8-R', + language='Russian', + char_to_order_map=KOI8_R_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + +MACCYRILLIC_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 37, # 'А' + 129: 44, # 'Б' + 130: 33, # 'В' + 131: 46, # 'Г' + 132: 41, # 'Д' + 133: 48, # 'Е' + 134: 56, # 'Ж' + 135: 51, # 'З' + 136: 42, # 'И' + 137: 60, # 'Й' + 138: 36, # 'К' + 139: 49, # 'Л' + 140: 38, # 'М' + 141: 31, # 'Н' + 142: 34, # 'О' + 143: 35, # 'П' + 144: 45, # 'Р' + 145: 32, # 'С' + 146: 40, # 'Т' + 147: 52, # 'У' + 148: 53, # 'Ф' + 149: 55, # 'Х' + 150: 58, # 'Ц' + 151: 50, # 'Ч' + 152: 57, # 'Ш' + 153: 63, # 'Щ' + 154: 70, # 'Ъ' + 155: 62, # 'Ы' + 156: 61, # 'Ь' + 157: 47, # 'Э' + 158: 59, # 'Ю' + 159: 43, # 'Я' + 160: 191, # '†' + 161: 192, # '°' + 162: 193, # 'Ґ' + 163: 194, # '£' + 164: 195, # '§' + 165: 196, # '•' + 166: 197, # '¶' + 167: 198, # 'І' + 168: 199, # '®' + 169: 200, # '©' + 170: 201, # '™' + 171: 202, # 'Ђ' + 172: 203, # 'ђ' + 173: 204, # '≠' + 174: 205, # 'Ѓ' + 175: 206, # 'ѓ' + 176: 207, # '∞' + 177: 208, # '±' + 178: 209, # '≤' + 179: 210, # '≥' + 180: 211, # 'і' + 181: 212, # 'µ' + 182: 213, # 'ґ' + 183: 214, # 'Ј' + 184: 215, # 'Є' + 185: 216, # 'є' + 186: 217, # 'Ї' + 187: 218, # 'ї' + 188: 219, # 'Љ' + 189: 220, # 'љ' + 190: 221, # 'Њ' + 191: 222, # 'њ' + 192: 223, # 'ј' + 193: 224, # 'Ѕ' + 194: 225, # '¬' + 195: 226, # '√' + 196: 227, # 'ƒ' + 197: 228, # '≈' + 198: 229, # '∆' + 199: 230, # '«' + 200: 231, # '»' + 201: 232, # '…' + 202: 233, # '\xa0' + 203: 234, # 'Ћ' + 204: 235, # 'ћ' + 205: 236, # 'Ќ' + 206: 237, # 'ќ' + 207: 238, # 'ѕ' + 208: 239, # '–' + 209: 240, # '—' + 210: 241, # '“' + 211: 242, # '”' + 212: 243, # '‘' + 213: 244, # '’' + 214: 245, # '÷' + 215: 246, # '„' + 216: 247, # 'Ў' + 217: 248, # 'ў' + 218: 249, # 'Џ' + 219: 250, # 'џ' + 220: 251, # '№' + 221: 252, # 'Ё' + 222: 68, # 'ё' + 223: 16, # 'я' + 224: 3, # 'а' + 225: 21, # 'б' + 226: 10, # 'в' + 227: 19, # 'г' + 228: 13, # 'д' + 229: 2, # 'е' + 230: 24, # 'ж' + 231: 20, # 'з' + 232: 4, # 'и' + 233: 23, # 'й' + 234: 11, # 'к' + 235: 8, # 'л' + 236: 12, # 'м' + 237: 5, # 'н' + 238: 1, # 'о' + 239: 15, # 'п' + 240: 9, # 'р' + 241: 7, # 'с' + 242: 6, # 'т' + 243: 14, # 'у' + 244: 39, # 'ф' + 245: 26, # 'х' + 246: 28, # 'ц' + 247: 22, # 'ч' + 248: 25, # 'ш' + 249: 29, # 'щ' + 250: 54, # 'ъ' + 251: 18, # 'ы' + 252: 17, # 'ь' + 253: 30, # 'э' + 254: 27, # 'ю' + 255: 255, # '€' +} + +MACCYRILLIC_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='MacCyrillic', + language='Russian', + char_to_order_map=MACCYRILLIC_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + +ISO_8859_5_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # '\x80' + 129: 192, # '\x81' + 130: 193, # '\x82' + 131: 194, # '\x83' + 132: 195, # '\x84' + 133: 196, # '\x85' + 134: 197, # '\x86' + 135: 198, # '\x87' + 136: 199, # '\x88' + 137: 200, # '\x89' + 138: 201, # '\x8a' + 139: 202, # '\x8b' + 140: 203, # '\x8c' + 141: 204, # '\x8d' + 142: 205, # '\x8e' + 143: 206, # '\x8f' + 144: 207, # '\x90' + 145: 208, # '\x91' + 146: 209, # '\x92' + 147: 210, # '\x93' + 148: 211, # '\x94' + 149: 212, # '\x95' + 150: 213, # '\x96' + 151: 214, # '\x97' + 152: 215, # '\x98' + 153: 216, # '\x99' + 154: 217, # '\x9a' + 155: 218, # '\x9b' + 156: 219, # '\x9c' + 157: 220, # '\x9d' + 158: 221, # '\x9e' + 159: 222, # '\x9f' + 160: 223, # '\xa0' + 161: 224, # 'Ё' + 162: 225, # 'Ђ' + 163: 226, # 'Ѓ' + 164: 227, # 'Є' + 165: 228, # 'Ѕ' + 166: 229, # 'І' + 167: 230, # 'Ї' + 168: 231, # 'Ј' + 169: 232, # 'Љ' + 170: 233, # 'Њ' + 171: 234, # 'Ћ' + 172: 235, # 'Ќ' + 173: 236, # '\xad' + 174: 237, # 'Ў' + 175: 238, # 'Џ' + 176: 37, # 'А' + 177: 44, # 'Б' + 178: 33, # 'В' + 179: 46, # 'Г' + 180: 41, # 'Д' + 181: 48, # 'Е' + 182: 56, # 'Ж' + 183: 51, # 'З' + 184: 42, # 'И' + 185: 60, # 'Й' + 186: 36, # 'К' + 187: 49, # 'Л' + 188: 38, # 'М' + 189: 31, # 'Н' + 190: 34, # 'О' + 191: 35, # 'П' + 192: 45, # 'Р' + 193: 32, # 'С' + 194: 40, # 'Т' + 195: 52, # 'У' + 196: 53, # 'Ф' + 197: 55, # 'Х' + 198: 58, # 'Ц' + 199: 50, # 'Ч' + 200: 57, # 'Ш' + 201: 63, # 'Щ' + 202: 70, # 'Ъ' + 203: 62, # 'Ы' + 204: 61, # 'Ь' + 205: 47, # 'Э' + 206: 59, # 'Ю' + 207: 43, # 'Я' + 208: 3, # 'а' + 209: 21, # 'б' + 210: 10, # 'в' + 211: 19, # 'г' + 212: 13, # 'д' + 213: 2, # 'е' + 214: 24, # 'ж' + 215: 20, # 'з' + 216: 4, # 'и' + 217: 23, # 'й' + 218: 11, # 'к' + 219: 8, # 'л' + 220: 12, # 'м' + 221: 5, # 'н' + 222: 1, # 'о' + 223: 15, # 'п' + 224: 9, # 'р' + 225: 7, # 'с' + 226: 6, # 'т' + 227: 14, # 'у' + 228: 39, # 'ф' + 229: 26, # 'х' + 230: 28, # 'ц' + 231: 22, # 'ч' + 232: 25, # 'ш' + 233: 29, # 'щ' + 234: 54, # 'ъ' + 235: 18, # 'ы' + 236: 17, # 'ь' + 237: 30, # 'э' + 238: 27, # 'ю' + 239: 16, # 'я' + 240: 239, # '№' + 241: 68, # 'ё' + 242: 240, # 'ђ' + 243: 241, # 'ѓ' + 244: 242, # 'є' + 245: 243, # 'ѕ' + 246: 244, # 'і' + 247: 245, # 'ї' + 248: 246, # 'ј' + 249: 247, # 'љ' + 250: 248, # 'њ' + 251: 249, # 'ћ' + 252: 250, # 'ќ' + 253: 251, # '§' + 254: 252, # 'ў' + 255: 255, # 'џ' +} + +ISO_8859_5_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-5', + language='Russian', + char_to_order_map=ISO_8859_5_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ЁАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяё') + diff --git a/pipenv/vendor/chardet/langthaimodel.py b/pipenv/vendor/chardet/langthaimodel.py index 15f94c2d..d0191f24 100644 --- a/pipenv/vendor/chardet/langthaimodel.py +++ b/pipenv/vendor/chardet/langthaimodel.py @@ -1,199 +1,4383 @@ -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### +#!/usr/bin/env python +# -*- coding: utf-8 -*- -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +THAI_LANG_MODEL = { + 5: { # 'ก' + 5: 2, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 3, # 'ฎ' + 57: 2, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 2, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 2, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 3, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 1, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 30: { # 'ข' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 0, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 2, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 2, # 'ี' + 40: 3, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 24: { # 'ค' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 2, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'แ' + 41: 3, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 8: { # 'ง' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 1, # 'ฉ' + 34: 2, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'ฝ' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 2, # 'ศ' + 46: 1, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 3, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 26: { # 'จ' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 3, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 52: { # 'ฉ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 3, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 1, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 34: { # 'ช' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 1, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 51: { # 'ซ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 3, # 'ึ' + 27: 2, # 'ื' + 32: 1, # 'ุ' + 35: 1, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 1, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 47: { # 'ญ' + 5: 1, # 'ก' + 30: 1, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 3, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 2, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 58: { # 'ฎ' + 5: 2, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 1, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 57: { # 'ฏ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 49: { # 'ฐ' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 53: { # 'ฑ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 55: { # 'ฒ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 43: { # 'ณ' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 3, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 3, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 3, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 20: { # 'ด' + 5: 2, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 2, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 1, # 'ึ' + 27: 2, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 2, # 'ๆ' + 37: 2, # '็' + 6: 1, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 19: { # 'ต' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 2, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 2, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 1, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 2, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 44: { # 'ถ' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 3, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 14: { # 'ท' + 5: 1, # 'ก' + 30: 1, # 'ข' + 24: 3, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 3, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 1, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 3, # 'ศ' + 46: 1, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 48: { # 'ธ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 2, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 2, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 3: { # 'น' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 1, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 2, # 'ถ' + 14: 3, # 'ท' + 48: 3, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 1, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 3, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 3, # 'โ' + 29: 3, # 'ใ' + 33: 3, # 'ไ' + 50: 2, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 17: { # 'บ' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 1, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 2, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 2, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 25: { # 'ป' + 5: 2, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 1, # 'ฎ' + 57: 3, # 'ฏ' + 49: 1, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 1, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 2, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 1, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 39: { # 'ผ' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 1, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 0, # 'ุ' + 35: 3, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 1, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 62: { # 'ฝ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 1, # 'ี' + 40: 2, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 1, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 31: { # 'พ' + 5: 1, # 'ก' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 2, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 1, # 'ึ' + 27: 3, # 'ื' + 32: 1, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 0, # '่' + 7: 1, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 54: { # 'ฟ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 45: { # 'ภ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 2, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 9: { # 'ม' + 5: 2, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 3, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 2, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 1, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 2, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 16: { # 'ย' + 5: 3, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 2, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 1, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 2, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 2: { # 'ร' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 2, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 3, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 3, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 3, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'ฝ' + 31: 2, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 2, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 3, # 'เ' + 28: 3, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 61: { # 'ฤ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 2, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 15: { # 'ล' + 5: 2, # 'ก' + 30: 3, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 3, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 2, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 2, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 12: { # 'ว' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 2, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 42: { # 'ศ' + 5: 1, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 2, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 3, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 2, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'แ' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 46: { # 'ษ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 2, # 'ฎ' + 57: 1, # 'ฏ' + 49: 2, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 18: { # 'ส' + 5: 2, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 3, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 2, # 'ภ' + 9: 3, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 0, # 'แ' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 1, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 21: { # 'ห' + 5: 3, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 4: { # 'อ' + 5: 3, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 63: { # 'ฯ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 22: { # 'ะ' + 5: 3, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 1, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 10: { # 'ั' + 5: 3, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 3, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 2, # 'ฐ' + 53: 0, # 'ฑ' + 55: 3, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 1: { # 'า' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 1, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 2, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'ฝ' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 3, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 3, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 36: { # 'ำ' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 1, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 23: { # 'ิ' + 5: 3, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 3, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'ฝ' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 2, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 3, # 'ศ' + 46: 2, # 'ษ' + 18: 2, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 13: { # 'ี' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 40: { # 'ึ' + 5: 3, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 3, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 27: { # 'ื' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 32: { # 'ุ' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 3, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 1, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 1, # 'ศ' + 46: 2, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'แ' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 35: { # 'ู' + 5: 3, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'แ' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 11: { # 'เ' + 5: 3, # 'ก' + 30: 3, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 3, # 'ฉ' + 34: 3, # 'ช' + 51: 2, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 3, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'ฝ' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 3, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 28: { # 'แ' + 5: 3, # 'ก' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 3, # 'ต' + 44: 2, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 3, # 'ผ' + 62: 0, # 'ฝ' + 31: 2, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 41: { # 'โ' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 1, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 29: { # 'ใ' + 5: 2, # 'ก' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 33: { # 'ไ' + 5: 1, # 'ก' + 30: 2, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 1, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 2, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 50: { # 'ๆ' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 37: { # '็' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 6: { # '่' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 1, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'ฝ' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 7: { # '้' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 38: { # '์' + 5: 2, # 'ก' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 1, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'แ' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 56: { # '๑' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 2, # '๑' + 59: 1, # '๒' + 60: 1, # '๕' + }, + 59: { # '๒' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 1, # '๑' + 59: 1, # '๒' + 60: 3, # '๕' + }, + 60: { # '๕' + 5: 0, # 'ก' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'ญ' + 58: 0, # 'ฎ' + 57: 0, # 'ฏ' + 49: 0, # 'ฐ' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'ฝ' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'แ' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 2, # '๑' + 59: 1, # '๒' + 60: 0, # '๕' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# The following result for thai was collected from a limited sample (1M). - -# Character Mapping Table: -TIS620CharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,254,255,255,254,255,255, # 00 -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, # 10 -253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, # 20 -252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253, # 30 -253,182,106,107,100,183,184,185,101, 94,186,187,108,109,110,111, # 40 -188,189,190, 89, 95,112,113,191,192,193,194,253,253,253,253,253, # 50 -253, 64, 72, 73,114, 74,115,116,102, 81,201,117, 90,103, 78, 82, # 60 - 96,202, 91, 79, 84,104,105, 97, 98, 92,203,253,253,253,253,253, # 70 -209,210,211,212,213, 88,214,215,216,217,218,219,220,118,221,222, -223,224, 99, 85, 83,225,226,227,228,229,230,231,232,233,234,235, -236, 5, 30,237, 24,238, 75, 8, 26, 52, 34, 51,119, 47, 58, 57, - 49, 53, 55, 43, 20, 19, 44, 14, 48, 3, 17, 25, 39, 62, 31, 54, - 45, 9, 16, 2, 61, 15,239, 12, 42, 46, 18, 21, 76, 4, 66, 63, - 22, 10, 1, 36, 23, 13, 40, 27, 32, 35, 86,240,241,242,243,244, - 11, 28, 41, 29, 33,245, 50, 37, 6, 7, 67, 77, 38, 93,246,247, - 68, 56, 59, 65, 69, 60, 70, 80, 71, 87,248,249,250,251,252,253, -) - -# Model Table: -# total sequences: 100% -# first 512 sequences: 92.6386% -# first 1024 sequences:7.3177% -# rest sequences: 1.0230% -# negative sequences: 0.0436% -ThaiLangModel = ( -0,1,3,3,3,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,0,0,3,3,3,0,3,3,3,3, -0,3,3,0,0,0,1,3,0,3,3,2,3,3,0,1,2,3,3,3,3,0,2,0,2,0,0,3,2,1,2,2, -3,0,3,3,2,3,0,0,3,3,0,3,3,0,3,3,3,3,3,3,3,3,3,0,3,2,3,0,2,2,2,3, -0,2,3,0,0,0,0,1,0,1,2,3,1,1,3,2,2,0,1,1,0,0,1,0,0,0,0,0,0,0,1,1, -3,3,3,2,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,3,3,2,3,2,3,3,2,2,2, -3,1,2,3,0,3,3,2,2,1,2,3,3,1,2,0,1,3,0,1,0,0,1,0,0,0,0,0,0,0,1,1, -3,3,2,2,3,3,3,3,1,2,3,3,3,3,3,2,2,2,2,3,3,2,2,3,3,2,2,3,2,3,2,2, -3,3,1,2,3,1,2,2,3,3,1,0,2,1,0,0,3,1,2,1,0,0,1,0,0,0,0,0,0,1,0,1, -3,3,3,3,3,3,2,2,3,3,3,3,2,3,2,2,3,3,2,2,3,2,2,2,2,1,1,3,1,2,1,1, -3,2,1,0,2,1,0,1,0,1,1,0,1,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,3,2,3,2,3,3,2,2,3,2,3,3,2,3,1,1,2,3,2,2,2,3,2,2,2,2,2,1,2,1, -2,2,1,1,3,3,2,1,0,1,2,2,0,1,3,0,0,0,1,1,0,0,0,0,0,2,3,0,0,2,1,1, -3,3,2,3,3,2,0,0,3,3,0,3,3,0,2,2,3,1,2,2,1,1,1,0,2,2,2,0,2,2,1,1, -0,2,1,0,2,0,0,2,0,1,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0, -3,3,2,3,3,2,0,0,3,3,0,2,3,0,2,1,2,2,2,2,1,2,0,0,2,2,2,0,2,2,1,1, -0,2,1,0,2,0,0,2,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, -3,3,2,3,2,3,2,0,2,2,1,3,2,1,3,2,1,2,3,2,2,3,0,2,3,2,2,1,2,2,2,2, -1,2,2,0,0,0,0,2,0,1,2,0,1,1,1,0,1,0,3,1,1,0,0,0,0,0,0,0,0,0,1,0, -3,3,2,3,3,2,3,2,2,2,3,2,2,3,2,2,1,2,3,2,2,3,1,3,2,2,2,3,2,2,2,3, -3,2,1,3,0,1,1,1,0,2,1,1,1,1,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,2,0,0, -1,0,0,3,0,3,3,3,3,3,0,0,3,0,2,2,3,3,3,3,3,0,0,0,1,1,3,0,0,0,0,2, -0,0,1,0,0,0,0,0,0,0,2,3,0,0,0,3,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -2,0,3,3,3,3,0,0,2,3,0,0,3,0,3,3,2,3,3,3,3,3,0,0,3,3,3,0,0,0,3,3, -0,0,3,0,0,0,0,2,0,0,2,1,1,3,0,0,1,0,0,2,3,0,1,0,0,0,0,0,0,0,1,0, -3,3,3,3,2,3,3,3,3,3,3,3,1,2,1,3,3,2,2,1,2,2,2,3,1,1,2,0,2,1,2,1, -2,2,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0, -3,0,2,1,2,3,3,3,0,2,0,2,2,0,2,1,3,2,2,1,2,1,0,0,2,2,1,0,2,1,2,2, -0,1,1,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,3,3,1,1,3,0,2,3,1,1,3,2,1,1,2,0,2,2,3,2,1,1,1,1,1,2, -3,0,0,1,3,1,2,1,2,0,3,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, -3,3,1,1,3,2,3,3,3,1,3,2,1,3,2,1,3,2,2,2,2,1,3,3,1,2,1,3,1,2,3,0, -2,1,1,3,2,2,2,1,2,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2, -3,3,2,3,2,3,3,2,3,2,3,2,3,3,2,1,0,3,2,2,2,1,2,2,2,1,2,2,1,2,1,1, -2,2,2,3,0,1,3,1,1,1,1,0,1,1,0,2,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,3,2,2,1,1,3,2,3,2,3,2,0,3,2,2,1,2,0,2,2,2,1,2,2,2,2,1, -3,2,1,2,2,1,0,2,0,1,0,0,1,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1, -3,3,3,3,3,2,3,1,2,3,3,2,2,3,0,1,1,2,0,3,3,2,2,3,0,1,1,3,0,0,0,0, -3,1,0,3,3,0,2,0,2,1,0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,3,2,3,3,0,1,3,1,1,2,1,2,1,1,3,1,1,0,2,3,1,1,1,1,1,1,1,1, -3,1,1,2,2,2,2,1,1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,2,2,1,1,2,1,3,3,2,3,2,2,3,2,2,3,1,2,2,1,2,0,3,2,1,2,2,2,2,2,1, -3,2,1,2,2,2,1,1,1,1,0,0,1,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,1,3,3,0,2,1,0,3,2,0,0,3,1,0,1,1,0,1,0,0,0,0,0,1, -1,0,0,1,0,3,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,2,2,2,3,0,0,1,3,0,3,2,0,3,2,2,3,3,3,3,3,1,0,2,2,2,0,2,2,1,2, -0,2,3,0,0,0,0,1,0,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -3,0,2,3,1,3,3,2,3,3,0,3,3,0,3,2,2,3,2,3,3,3,0,0,2,2,3,0,1,1,1,3, -0,0,3,0,0,0,2,2,0,1,3,0,1,2,2,2,3,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1, -3,2,3,3,2,0,3,3,2,2,3,1,3,2,1,3,2,0,1,2,2,0,2,3,2,1,0,3,0,0,0,0, -3,0,0,2,3,1,3,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,1,3,2,2,2,1,2,0,1,3,1,1,3,1,3,0,0,2,1,1,1,1,2,1,1,1,0,2,1,0,1, -1,2,0,0,0,3,1,1,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,3,1,0,0,0,1,0, -3,3,3,3,2,2,2,2,2,1,3,1,1,1,2,0,1,1,2,1,2,1,3,2,0,0,3,1,1,1,1,1, -3,1,0,2,3,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,2,3,0,3,3,0,2,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,2,3,1,3,0,0,1,2,0,0,2,0,3,3,2,3,3,3,2,3,0,0,2,2,2,0,0,0,2,2, -0,0,1,0,0,0,0,3,0,0,0,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -0,0,0,3,0,2,0,0,0,0,0,0,0,0,0,0,1,2,3,1,3,3,0,0,1,0,3,0,0,0,0,0, -0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,1,2,3,1,2,3,1,0,3,0,2,2,1,0,2,1,1,2,0,1,0,0,1,1,1,1,0,1,0,0, -1,0,0,0,0,1,1,0,3,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,2,1,0,1,1,1,3,1,2,2,2,2,2,2,1,1,1,1,0,3,1,0,1,3,1,1,1,1, -1,1,0,2,0,1,3,1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1, -3,0,2,2,1,3,3,2,3,3,0,1,1,0,2,2,1,2,1,3,3,1,0,0,3,2,0,0,0,0,2,1, -0,1,0,0,0,0,1,2,0,1,1,3,1,1,2,2,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, -0,0,3,0,0,1,0,0,0,3,0,0,3,0,3,1,0,1,1,1,3,2,0,0,0,3,0,0,0,0,2,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -3,3,1,3,2,1,3,3,1,2,2,0,1,2,1,0,1,2,0,0,0,0,0,3,0,0,0,3,0,0,0,0, -3,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,2,0,3,3,3,2,2,0,1,1,0,1,3,0,0,0,2,2,0,0,0,0,3,1,0,1,0,0,0, -0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,2,3,1,2,0,0,2,1,0,3,1,0,1,2,0,1,1,1,1,3,0,0,3,1,1,0,2,2,1,1, -0,2,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,3,1,2,0,0,2,2,0,1,2,0,1,0,1,3,1,2,1,0,0,0,2,0,3,0,0,0,1,0, -0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,1,1,2,2,0,0,0,2,0,2,1,0,1,1,0,1,1,1,2,1,0,0,1,1,1,0,2,1,1,1, -0,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1, -0,0,0,2,0,1,3,1,1,1,1,0,0,0,0,3,2,0,1,0,0,0,1,2,0,0,0,1,0,0,0,0, -0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,0,2,3,2,2,0,0,0,1,0,0,0,0,2,3,2,1,2,2,3,0,0,0,2,3,1,0,0,0,1,1, -0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0, -3,3,2,2,0,1,0,0,0,0,2,0,2,0,1,0,0,0,1,1,0,0,0,2,1,0,1,0,1,1,0,0, -0,1,0,2,0,0,1,0,3,0,1,0,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,1,0,0,1,0,0,0,0,0,1,1,2,0,0,0,0,1,0,0,1,3,1,0,0,0,0,1,1,0,0, -0,1,0,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0, -3,3,1,1,1,1,2,3,0,0,2,1,1,1,1,1,0,2,1,1,0,0,0,2,1,0,1,2,1,1,0,1, -2,1,0,3,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,3,1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1, -0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,0,0,0,0,1,2,1,0,1,1,0,2,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,2,0,0,0,1,3,0,1,0,0,0,2,0,0,0,0,0,0,0,1,2,0,0,0,0,0, -3,3,0,0,1,1,2,0,0,1,2,1,0,1,1,1,0,1,1,0,0,2,1,1,0,1,0,0,1,1,1,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,1,0,0,0,0,1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,3,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,0,1,2,0,1,2,0,0,1,1,0,2,0,1,0,0,1,0,0,0,0,1,0,0,0,2,0,0,0,0, -1,0,0,1,0,1,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,2,1,3,0,0,0,0,1,1,0,0,0,0,0,0,0,3, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,1,0,1,0,0,2,0,0,2,0,0,1,1,2,0,0,1,1,0,0,0,1,0,0,0,1,1,0,0,0, -1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0, -1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,1,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,3,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0, -1,0,0,0,0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,1,0,0,2,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -TIS620ThaiModel = { - 'char_to_order_map': TIS620CharToOrderMap, - 'precedence_matrix': ThaiLangModel, - 'typical_positive_ratio': 0.926386, - 'keep_english_letter': False, - 'charset_name': "TIS-620", - 'language': 'Thai', +# Character Mapping Table(s): +TIS_620_THAI_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 182, # 'A' + 66: 106, # 'B' + 67: 107, # 'C' + 68: 100, # 'D' + 69: 183, # 'E' + 70: 184, # 'F' + 71: 185, # 'G' + 72: 101, # 'H' + 73: 94, # 'I' + 74: 186, # 'J' + 75: 187, # 'K' + 76: 108, # 'L' + 77: 109, # 'M' + 78: 110, # 'N' + 79: 111, # 'O' + 80: 188, # 'P' + 81: 189, # 'Q' + 82: 190, # 'R' + 83: 89, # 'S' + 84: 95, # 'T' + 85: 112, # 'U' + 86: 113, # 'V' + 87: 191, # 'W' + 88: 192, # 'X' + 89: 193, # 'Y' + 90: 194, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 64, # 'a' + 98: 72, # 'b' + 99: 73, # 'c' + 100: 114, # 'd' + 101: 74, # 'e' + 102: 115, # 'f' + 103: 116, # 'g' + 104: 102, # 'h' + 105: 81, # 'i' + 106: 201, # 'j' + 107: 117, # 'k' + 108: 90, # 'l' + 109: 103, # 'm' + 110: 78, # 'n' + 111: 82, # 'o' + 112: 96, # 'p' + 113: 202, # 'q' + 114: 91, # 'r' + 115: 79, # 's' + 116: 84, # 't' + 117: 104, # 'u' + 118: 105, # 'v' + 119: 97, # 'w' + 120: 98, # 'x' + 121: 92, # 'y' + 122: 203, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 209, # '\x80' + 129: 210, # '\x81' + 130: 211, # '\x82' + 131: 212, # '\x83' + 132: 213, # '\x84' + 133: 88, # '\x85' + 134: 214, # '\x86' + 135: 215, # '\x87' + 136: 216, # '\x88' + 137: 217, # '\x89' + 138: 218, # '\x8a' + 139: 219, # '\x8b' + 140: 220, # '\x8c' + 141: 118, # '\x8d' + 142: 221, # '\x8e' + 143: 222, # '\x8f' + 144: 223, # '\x90' + 145: 224, # '\x91' + 146: 99, # '\x92' + 147: 85, # '\x93' + 148: 83, # '\x94' + 149: 225, # '\x95' + 150: 226, # '\x96' + 151: 227, # '\x97' + 152: 228, # '\x98' + 153: 229, # '\x99' + 154: 230, # '\x9a' + 155: 231, # '\x9b' + 156: 232, # '\x9c' + 157: 233, # '\x9d' + 158: 234, # '\x9e' + 159: 235, # '\x9f' + 160: 236, # None + 161: 5, # 'ก' + 162: 30, # 'ข' + 163: 237, # 'ฃ' + 164: 24, # 'ค' + 165: 238, # 'ฅ' + 166: 75, # 'ฆ' + 167: 8, # 'ง' + 168: 26, # 'จ' + 169: 52, # 'ฉ' + 170: 34, # 'ช' + 171: 51, # 'ซ' + 172: 119, # 'ฌ' + 173: 47, # 'ญ' + 174: 58, # 'ฎ' + 175: 57, # 'ฏ' + 176: 49, # 'ฐ' + 177: 53, # 'ฑ' + 178: 55, # 'ฒ' + 179: 43, # 'ณ' + 180: 20, # 'ด' + 181: 19, # 'ต' + 182: 44, # 'ถ' + 183: 14, # 'ท' + 184: 48, # 'ธ' + 185: 3, # 'น' + 186: 17, # 'บ' + 187: 25, # 'ป' + 188: 39, # 'ผ' + 189: 62, # 'ฝ' + 190: 31, # 'พ' + 191: 54, # 'ฟ' + 192: 45, # 'ภ' + 193: 9, # 'ม' + 194: 16, # 'ย' + 195: 2, # 'ร' + 196: 61, # 'ฤ' + 197: 15, # 'ล' + 198: 239, # 'ฦ' + 199: 12, # 'ว' + 200: 42, # 'ศ' + 201: 46, # 'ษ' + 202: 18, # 'ส' + 203: 21, # 'ห' + 204: 76, # 'ฬ' + 205: 4, # 'อ' + 206: 66, # 'ฮ' + 207: 63, # 'ฯ' + 208: 22, # 'ะ' + 209: 10, # 'ั' + 210: 1, # 'า' + 211: 36, # 'ำ' + 212: 23, # 'ิ' + 213: 13, # 'ี' + 214: 40, # 'ึ' + 215: 27, # 'ื' + 216: 32, # 'ุ' + 217: 35, # 'ู' + 218: 86, # 'ฺ' + 219: 240, # None + 220: 241, # None + 221: 242, # None + 222: 243, # None + 223: 244, # '฿' + 224: 11, # 'เ' + 225: 28, # 'แ' + 226: 41, # 'โ' + 227: 29, # 'ใ' + 228: 33, # 'ไ' + 229: 245, # 'ๅ' + 230: 50, # 'ๆ' + 231: 37, # '็' + 232: 6, # '่' + 233: 7, # '้' + 234: 67, # '๊' + 235: 77, # '๋' + 236: 38, # '์' + 237: 93, # 'ํ' + 238: 246, # '๎' + 239: 247, # '๏' + 240: 68, # '๐' + 241: 56, # '๑' + 242: 59, # '๒' + 243: 65, # '๓' + 244: 69, # '๔' + 245: 60, # '๕' + 246: 70, # '๖' + 247: 80, # '๗' + 248: 71, # '๘' + 249: 87, # '๙' + 250: 248, # '๚' + 251: 249, # '๛' + 252: 250, # None + 253: 251, # None + 254: 252, # None + 255: 253, # None } + +TIS_620_THAI_MODEL = SingleByteCharSetModel(charset_name='TIS-620', + language='Thai', + char_to_order_map=TIS_620_THAI_CHAR_TO_ORDER, + language_model=THAI_LANG_MODEL, + typical_positive_ratio=0.926386, + keep_ascii_letters=False, + alphabet='กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛') + diff --git a/pipenv/vendor/chardet/langturkishmodel.py b/pipenv/vendor/chardet/langturkishmodel.py index a427a457..8ba93224 100644 --- a/pipenv/vendor/chardet/langturkishmodel.py +++ b/pipenv/vendor/chardet/langturkishmodel.py @@ -1,193 +1,4383 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- -######################## BEGIN LICENSE BLOCK ######################## -# The Original Code is Mozilla Communicator client code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# Mark Pilgrim - port to Python -# Özgür Baskın - Turkish Language Model -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA -# 02110-1301 USA -######################### END LICENSE BLOCK ######################### -# 255: Control characters that usually does not exist in any text +from chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +TURKISH_LANG_MODEL = { + 23: { # 'A' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 37: { # 'B' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, + 47: { # 'C' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 1, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 39: { # 'D' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 1, # 'Ş' + 19: 0, # 'ş' + }, + 29: { # 'E' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 52: { # 'F' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 1, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 2, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 2, # 'ş' + }, + 36: { # 'G' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 2, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 1, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 2, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 45: { # 'H' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 2, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 2, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ğ' + 41: 1, # 'İ' + 6: 0, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 53: { # 'I' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, + 60: { # 'J' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 16: { # 'K' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 1, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 1, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 49: { # 'L' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 2, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 20: { # 'M' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 0, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 46: { # 'N' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 1, # 'İ' + 6: 2, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, + 42: { # 'O' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 2, # 'İ' + 6: 1, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, + 48: { # 'P' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 0, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 44: { # 'R' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, + 35: { # 'S' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 1, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 2, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 31: { # 'T' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 2, # 't' + 14: 2, # 'u' + 32: 1, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 51: { # 'U' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 38: { # 'V' + 23: 1, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 1, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 3, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 62: { # 'W' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 43: { # 'Y' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 0, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 1, # 'Ü' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 0, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 56: { # 'Z' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 1: { # 'a' + 23: 3, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 1, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 21: { # 'b' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 3, # 'g' + 25: 1, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 2, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 28: { # 'c' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 2, # 'T' + 51: 2, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 3, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 1, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 1, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 2, # 'ğ' + 41: 1, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 2, # 'ş' + }, + 12: { # 'd' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 2: { # 'e' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 18: { # 'f' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 1, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 1, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 27: { # 'g' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 25: { # 'h' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 3: { # 'i' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 1, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 3, # 'g' + 25: 1, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 1, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 24: { # 'j' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 10: { # 'k' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 2, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 5: { # 'l' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 1, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 2, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 13: { # 'm' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 2, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 4: { # 'n' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 15: { # 'o' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 2, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ğ' + 41: 2, # 'İ' + 6: 3, # 'ı' + 40: 2, # 'Ş' + 19: 2, # 'ş' + }, + 26: { # 'p' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 7: { # 'r' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 1, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 8: { # 's' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 9: { # 't' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 14: { # 'u' + 23: 3, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 2, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 2, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 32: { # 'v' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 57: { # 'w' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 1, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 58: { # 'x' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 11: { # 'y' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 22: { # 'z' + 23: 2, # 'A' + 37: 2, # 'B' + 47: 1, # 'C' + 39: 2, # 'D' + 29: 3, # 'E' + 52: 1, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 2, # 'N' + 42: 2, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 3, # 'T' + 51: 2, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 1, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 2, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ü' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 2, # 'ğ' + 41: 1, # 'İ' + 6: 3, # 'ı' + 40: 1, # 'Ş' + 19: 2, # 'ş' + }, + 63: { # '·' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 54: { # 'Ç' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 3, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 50: { # 'Ö' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 2, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 1, # 'N' + 42: 2, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 1, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 1, # 's' + 9: 2, # 't' + 14: 0, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 1, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 55: { # 'Ü' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 0, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 59: { # 'â' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 1, # 'Ş' + 19: 0, # 'ş' + }, + 33: { # 'ç' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 0, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 61: { # 'î' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 1, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 1, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 34: { # 'ö' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 1, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 3, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ğ' + 41: 1, # 'İ' + 6: 1, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 17: { # 'ü' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 30: { # 'ğ' + 23: 0, # 'A' + 37: 2, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 2, # 'N' + 42: 2, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 3, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 2, # 'İ' + 6: 2, # 'ı' + 40: 2, # 'Ş' + 19: 1, # 'ş' + }, + 41: { # 'İ' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ü' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 2, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 1, # 'ş' + }, + 6: { # 'ı' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ğ' + 41: 0, # 'İ' + 6: 3, # 'ı' + 40: 0, # 'Ş' + 19: 0, # 'ş' + }, + 40: { # 'Ş' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 2, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 0, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 3, # 'f' + 27: 0, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 1, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ü' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 1, # 'ü' + 30: 2, # 'ğ' + 41: 0, # 'İ' + 6: 2, # 'ı' + 40: 1, # 'Ş' + 19: 2, # 'ş' + }, + 19: { # 'ş' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 2, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ü' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 1, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ğ' + 41: 1, # 'İ' + 6: 1, # 'ı' + 40: 1, # 'Ş' + 19: 1, # 'ş' + }, +} + +# 255: Undefined characters that did not exist in training text # 254: Carriage/Return # 253: symbol (punctuation) that does not belong to word # 252: 0 - 9 +# 251: Control characters -# Character Mapping Table: -Latin5_TurkishCharToOrderMap = ( -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, -255, 23, 37, 47, 39, 29, 52, 36, 45, 53, 60, 16, 49, 20, 46, 42, - 48, 69, 44, 35, 31, 51, 38, 62, 65, 43, 56,255,255,255,255,255, -255, 1, 21, 28, 12, 2, 18, 27, 25, 3, 24, 10, 5, 13, 4, 15, - 26, 64, 7, 8, 9, 14, 32, 57, 58, 11, 22,255,255,255,255,255, -180,179,178,177,176,175,174,173,172,171,170,169,168,167,166,165, -164,163,162,161,160,159,101,158,157,156,155,154,153,152,151,106, -150,149,148,147,146,145,144,100,143,142,141,140,139,138,137,136, - 94, 80, 93,135,105,134,133, 63,132,131,130,129,128,127,126,125, -124,104, 73, 99, 79, 85,123, 54,122, 98, 92,121,120, 91,103,119, - 68,118,117, 97,116,115, 50, 90,114,113,112,111, 55, 41, 40, 86, - 89, 70, 59, 78, 71, 82, 88, 33, 77, 66, 84, 83,110, 75, 61, 96, - 30, 67,109, 74, 87,102, 34, 95, 81,108, 76, 72, 17, 6, 19,107, -) - -TurkishLangModel = ( -3,2,3,3,3,1,3,3,3,3,3,3,3,3,2,1,1,3,3,1,3,3,0,3,3,3,3,3,0,3,1,3, -3,2,1,0,0,1,1,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, -3,2,2,3,3,0,3,3,3,3,3,3,3,2,3,1,0,3,3,1,3,3,0,3,3,3,3,3,0,3,0,3, -3,1,1,0,1,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,2,2,0,0,0,1,0,1, -3,3,2,3,3,0,3,3,3,3,3,3,3,2,3,1,1,3,3,0,3,3,1,2,3,3,3,3,0,3,0,3, -3,1,1,0,0,0,1,0,0,0,0,1,1,0,1,2,1,0,0,0,1,0,0,0,0,2,0,0,0,0,0,1, -3,3,3,3,3,3,2,3,3,3,3,3,3,3,3,1,3,3,2,0,3,2,1,2,2,1,3,3,0,0,0,2, -2,2,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,1, -3,3,3,2,3,3,1,2,3,3,3,3,3,3,3,1,3,2,1,0,3,2,0,1,2,3,3,2,1,0,0,2, -2,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0, -1,0,1,3,3,1,3,3,3,3,3,3,3,1,2,0,0,2,3,0,2,3,0,0,2,2,2,3,0,3,0,1, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,3,0,3,2,0,2,3,2,3,3,1,0,0,2, -3,2,0,0,1,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,1,1,0,2,0,0,1, -3,3,3,2,3,3,2,3,3,3,3,2,3,3,3,0,3,3,0,0,2,1,0,0,2,3,2,2,0,0,0,2, -2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,0,1,0,2,0,0,1, -3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,0,1,3,2,1,1,3,2,3,2,1,0,0,2, -2,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, -3,3,3,2,3,3,3,3,3,3,3,2,3,3,3,0,3,2,2,0,2,3,0,0,2,2,2,2,0,0,0,2, -3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, -3,3,3,3,3,3,3,2,2,2,2,3,2,3,3,0,3,3,1,1,2,2,0,0,2,2,3,2,0,0,1,3, -0,3,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1, -3,3,3,2,3,3,3,2,1,2,2,3,2,3,3,0,3,2,0,0,1,1,0,1,1,2,1,2,0,0,0,1, -0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0, -3,3,3,2,3,3,2,3,2,2,2,3,3,3,3,1,3,1,1,0,3,2,1,1,3,3,2,3,1,0,0,1, -1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,1, -3,2,2,3,3,0,3,3,3,3,3,3,3,2,2,1,0,3,3,1,3,3,0,1,3,3,2,3,0,3,0,3, -2,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -2,2,2,3,3,0,3,3,3,3,3,3,3,3,3,0,0,3,2,0,3,3,0,3,2,3,3,3,0,3,1,3, -2,0,0,0,0,0,0,0,0,0,0,1,0,1,2,0,1,0,0,0,0,0,0,0,2,2,0,0,1,0,0,1, -3,3,3,1,2,3,3,1,0,0,1,0,0,3,3,2,3,0,0,2,0,0,2,0,2,0,0,0,2,0,2,0, -0,3,1,0,1,0,0,0,2,2,1,0,1,1,2,1,2,2,2,0,2,1,1,0,0,0,2,0,0,0,0,0, -1,2,1,3,3,0,3,3,3,3,3,2,3,0,0,0,0,2,3,0,2,3,1,0,2,3,1,3,0,3,0,2, -3,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,3,3,2,2,3,2,2,0,1,2,3,0,1,2,1,0,1,0,0,0,1,0,2,2,0,0,0,1, -1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0, -3,3,3,1,3,3,1,1,3,3,1,1,3,3,1,0,2,1,2,0,2,1,0,0,1,1,2,1,0,0,0,2, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,0,2,1,3,0,0,2,0,0,3,3,0,3,0,0,1,0,1,2,0,0,1,1,2,2,0,1,0, -0,1,2,1,1,0,1,0,1,1,1,1,1,0,1,1,1,2,2,1,2,0,1,0,0,0,0,0,0,1,0,0, -3,3,3,2,3,2,3,3,0,2,2,2,3,3,3,0,3,0,0,0,2,2,0,1,2,1,1,1,0,0,0,1, -0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -3,3,3,3,3,3,2,1,2,2,3,3,3,3,2,0,2,0,0,0,2,2,0,0,2,1,3,3,0,0,1,1, -1,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0, -1,1,2,3,3,0,3,3,3,3,3,3,2,2,0,2,0,2,3,2,3,2,2,2,2,2,2,2,1,3,2,3, -2,0,2,1,2,2,2,2,1,1,2,2,1,2,2,1,2,0,0,2,1,1,0,2,1,0,0,1,0,0,0,1, -2,3,3,1,1,1,0,1,1,1,2,3,2,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0, -0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,2,2,3,2,3,2,2,1,3,3,3,0,2,1,2,0,2,1,0,0,1,1,1,1,1,0,0,1, -2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0, -3,3,3,2,3,3,3,3,3,2,3,1,2,3,3,1,2,0,0,0,0,0,0,0,3,2,1,1,0,0,0,0, -2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -3,3,3,2,2,3,3,2,1,1,1,1,1,3,3,0,3,1,0,0,1,1,0,0,3,1,2,1,0,0,0,0, -0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0, -3,3,3,2,2,3,2,2,2,3,2,1,1,3,3,0,3,0,0,0,0,1,0,0,3,1,1,2,0,0,0,1, -1,0,0,1,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, -1,1,1,3,3,0,3,3,3,3,3,2,2,2,1,2,0,2,1,2,2,1,1,0,1,2,2,2,2,2,2,2, -0,0,2,1,2,1,2,1,0,1,1,3,1,2,1,1,2,0,0,2,0,1,0,1,0,1,0,0,0,1,0,1, -3,3,3,1,3,3,3,0,1,1,0,2,2,3,1,0,3,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,2,2,1,0,0,1,0,0,3,3,1,3,0,0,1,1,0,2,0,3,0,0,0,2,0,1,1, -0,1,2,0,1,2,2,0,2,2,2,2,1,0,2,1,1,0,2,0,2,1,2,0,0,0,0,0,0,0,0,0, -3,3,3,1,3,2,3,2,0,2,2,2,1,3,2,0,2,1,2,0,1,2,0,0,1,0,2,2,0,0,0,2, -1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0, -3,3,3,0,3,3,1,1,2,3,1,0,3,2,3,0,3,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0, -1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,3,3,0,3,3,2,3,3,2,2,0,0,0,0,1,2,0,1,3,0,0,0,3,1,1,0,3,0,2, -2,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,1,2,2,1,0,3,1,1,1,1,3,3,2,3,0,0,1,0,1,2,0,2,2,0,2,2,0,2,1, -0,2,2,1,1,1,1,0,2,1,1,0,1,1,1,1,2,1,2,1,2,0,1,0,1,0,0,0,0,0,0,0, -3,3,3,0,1,1,3,0,0,1,1,0,0,2,2,0,3,0,0,1,1,0,1,0,0,0,0,0,2,0,0,0, -0,3,1,0,1,0,1,0,2,0,0,1,0,1,0,1,1,1,2,1,1,0,2,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,0,2,0,1,1,1,0,0,3,3,0,2,0,0,1,0,0,2,1,1,0,1,0,1,0,1,0, -0,2,0,1,2,0,2,0,2,1,1,0,1,0,2,1,1,0,2,1,1,0,1,0,0,0,1,1,0,0,0,0, -3,2,3,0,1,0,0,0,0,0,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,0,2,0,0,0, -0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,2,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,0,0,2,3,0,0,1,0,1,0,2,3,2,3,0,0,1,3,0,2,1,0,0,0,0,2,0,1,0, -0,2,1,0,0,1,1,0,2,1,0,0,1,0,0,1,1,0,1,1,2,0,1,0,0,0,0,1,0,0,0,0, -3,2,2,0,0,1,1,0,0,0,0,0,0,3,1,1,1,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0, -0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,3,3,0,2,3,2,2,1,2,2,1,1,2,0,1,3,2,2,2,0,0,2,2,0,0,0,1,2,1, -3,0,2,1,1,0,1,1,1,0,1,2,2,2,1,1,2,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0, -0,1,1,2,3,0,3,3,3,2,2,2,2,1,0,1,0,1,0,1,2,2,0,0,2,2,1,3,1,1,2,1, -0,0,1,1,2,0,1,1,0,0,1,2,0,2,1,1,2,0,0,1,0,0,0,1,0,1,0,1,0,0,0,0, -3,3,2,0,0,3,1,0,0,0,0,0,0,3,2,1,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, -0,2,1,1,0,0,1,0,1,2,0,0,1,1,0,0,2,1,1,1,1,0,2,0,0,0,0,0,0,0,0,0, -3,3,2,0,0,1,0,0,0,0,1,0,0,3,3,2,2,0,0,1,0,0,2,0,1,0,0,0,2,0,1,0, -0,0,1,1,0,0,2,0,2,1,0,0,1,1,2,1,2,0,2,1,2,1,1,1,0,0,1,1,0,0,0,0, -3,3,2,0,0,2,2,0,0,0,1,1,0,2,2,1,3,1,0,1,0,1,2,0,0,0,0,0,1,0,1,0, -0,1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,2,0,0,0,1,0,0,1,0,0,2,3,1,2,0,0,1,0,0,2,0,0,0,1,0,2,0,2,0, -0,1,1,2,2,1,2,0,2,1,1,0,0,1,1,0,1,1,1,1,2,1,1,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,1,2,1,0,0,1,1,0,3,3,1,2,0,0,1,0,0,2,0,2,0,1,1,2,0,0,0, -0,0,1,1,1,1,2,0,1,1,0,1,1,1,1,0,0,0,1,1,1,0,1,0,0,0,1,0,0,0,0,0, -3,3,3,0,2,2,3,2,0,0,1,0,0,2,3,1,0,0,0,0,0,0,2,0,2,0,0,0,2,0,0,0, -0,1,1,0,0,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, -3,2,3,0,0,0,0,0,0,0,1,0,0,2,2,2,2,0,0,1,0,0,2,0,0,0,0,0,2,0,1,0, -0,0,2,1,1,0,1,0,2,1,1,0,0,1,1,2,1,0,2,0,2,0,1,0,0,0,2,0,0,0,0,0, -0,0,0,2,2,0,2,1,1,1,1,2,2,0,0,1,0,1,0,0,1,3,0,0,0,0,1,0,0,2,1,0, -0,0,1,0,1,0,0,0,0,0,2,1,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0, -2,0,0,2,3,0,2,3,1,2,2,0,2,0,0,2,0,2,1,1,1,2,1,0,0,1,2,1,1,2,1,0, -1,0,2,0,1,0,1,1,0,0,2,2,1,2,1,1,2,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, -3,3,3,0,2,1,2,0,0,0,1,0,0,3,2,0,1,0,0,1,0,0,2,0,0,0,1,2,1,0,1,0, -0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,2,2,0,2,2,1,1,0,1,1,1,1,1,0,0,1,2,1,1,1,0,1,0,0,0,1,1,1,1, -0,0,2,1,0,1,1,1,0,1,1,2,1,2,1,1,2,0,1,1,2,1,0,2,0,0,0,0,0,0,0,0, -3,2,2,0,0,2,0,0,0,0,0,0,0,2,2,0,2,0,0,1,0,0,2,0,0,0,0,0,2,0,0,0, -0,2,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,3,2,0,2,2,0,1,1,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0, -2,0,1,0,1,0,1,1,0,0,1,2,0,1,0,1,1,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0, -2,2,2,0,1,1,0,0,0,1,0,0,0,1,2,0,1,0,0,1,0,0,1,0,0,0,0,1,2,0,1,0, -0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,2,1,0,1,1,1,0,0,0,0,1,2,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0, -1,1,2,0,1,0,0,0,1,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,1, -0,0,1,2,2,0,2,1,2,1,1,2,2,0,0,0,0,1,0,0,1,1,0,0,2,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, -2,2,2,0,0,0,1,0,0,0,0,0,0,2,2,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, -0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -2,2,2,0,1,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,1,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -) - -Latin5TurkishModel = { - 'char_to_order_map': Latin5_TurkishCharToOrderMap, - 'precedence_matrix': TurkishLangModel, - 'typical_positive_ratio': 0.970290, - 'keep_english_letter': True, - 'charset_name': "ISO-8859-9", - 'language': 'Turkish', +# Character Mapping Table(s): +ISO_8859_9_TURKISH_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 255, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 255, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 255, # ' ' + 33: 255, # '!' + 34: 255, # '"' + 35: 255, # '#' + 36: 255, # '$' + 37: 255, # '%' + 38: 255, # '&' + 39: 255, # "'" + 40: 255, # '(' + 41: 255, # ')' + 42: 255, # '*' + 43: 255, # '+' + 44: 255, # ',' + 45: 255, # '-' + 46: 255, # '.' + 47: 255, # '/' + 48: 255, # '0' + 49: 255, # '1' + 50: 255, # '2' + 51: 255, # '3' + 52: 255, # '4' + 53: 255, # '5' + 54: 255, # '6' + 55: 255, # '7' + 56: 255, # '8' + 57: 255, # '9' + 58: 255, # ':' + 59: 255, # ';' + 60: 255, # '<' + 61: 255, # '=' + 62: 255, # '>' + 63: 255, # '?' + 64: 255, # '@' + 65: 23, # 'A' + 66: 37, # 'B' + 67: 47, # 'C' + 68: 39, # 'D' + 69: 29, # 'E' + 70: 52, # 'F' + 71: 36, # 'G' + 72: 45, # 'H' + 73: 53, # 'I' + 74: 60, # 'J' + 75: 16, # 'K' + 76: 49, # 'L' + 77: 20, # 'M' + 78: 46, # 'N' + 79: 42, # 'O' + 80: 48, # 'P' + 81: 69, # 'Q' + 82: 44, # 'R' + 83: 35, # 'S' + 84: 31, # 'T' + 85: 51, # 'U' + 86: 38, # 'V' + 87: 62, # 'W' + 88: 65, # 'X' + 89: 43, # 'Y' + 90: 56, # 'Z' + 91: 255, # '[' + 92: 255, # '\\' + 93: 255, # ']' + 94: 255, # '^' + 95: 255, # '_' + 96: 255, # '`' + 97: 1, # 'a' + 98: 21, # 'b' + 99: 28, # 'c' + 100: 12, # 'd' + 101: 2, # 'e' + 102: 18, # 'f' + 103: 27, # 'g' + 104: 25, # 'h' + 105: 3, # 'i' + 106: 24, # 'j' + 107: 10, # 'k' + 108: 5, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 15, # 'o' + 112: 26, # 'p' + 113: 64, # 'q' + 114: 7, # 'r' + 115: 8, # 's' + 116: 9, # 't' + 117: 14, # 'u' + 118: 32, # 'v' + 119: 57, # 'w' + 120: 58, # 'x' + 121: 11, # 'y' + 122: 22, # 'z' + 123: 255, # '{' + 124: 255, # '|' + 125: 255, # '}' + 126: 255, # '~' + 127: 255, # '\x7f' + 128: 180, # '\x80' + 129: 179, # '\x81' + 130: 178, # '\x82' + 131: 177, # '\x83' + 132: 176, # '\x84' + 133: 175, # '\x85' + 134: 174, # '\x86' + 135: 173, # '\x87' + 136: 172, # '\x88' + 137: 171, # '\x89' + 138: 170, # '\x8a' + 139: 169, # '\x8b' + 140: 168, # '\x8c' + 141: 167, # '\x8d' + 142: 166, # '\x8e' + 143: 165, # '\x8f' + 144: 164, # '\x90' + 145: 163, # '\x91' + 146: 162, # '\x92' + 147: 161, # '\x93' + 148: 160, # '\x94' + 149: 159, # '\x95' + 150: 101, # '\x96' + 151: 158, # '\x97' + 152: 157, # '\x98' + 153: 156, # '\x99' + 154: 155, # '\x9a' + 155: 154, # '\x9b' + 156: 153, # '\x9c' + 157: 152, # '\x9d' + 158: 151, # '\x9e' + 159: 106, # '\x9f' + 160: 150, # '\xa0' + 161: 149, # '¡' + 162: 148, # '¢' + 163: 147, # '£' + 164: 146, # '¤' + 165: 145, # '¥' + 166: 144, # '¦' + 167: 100, # '§' + 168: 143, # '¨' + 169: 142, # '©' + 170: 141, # 'ª' + 171: 140, # '«' + 172: 139, # '¬' + 173: 138, # '\xad' + 174: 137, # '®' + 175: 136, # '¯' + 176: 94, # '°' + 177: 80, # '±' + 178: 93, # '²' + 179: 135, # '³' + 180: 105, # '´' + 181: 134, # 'µ' + 182: 133, # '¶' + 183: 63, # '·' + 184: 132, # '¸' + 185: 131, # '¹' + 186: 130, # 'º' + 187: 129, # '»' + 188: 128, # '¼' + 189: 127, # '½' + 190: 126, # '¾' + 191: 125, # '¿' + 192: 124, # 'À' + 193: 104, # 'Á' + 194: 73, # 'Â' + 195: 99, # 'Ã' + 196: 79, # 'Ä' + 197: 85, # 'Å' + 198: 123, # 'Æ' + 199: 54, # 'Ç' + 200: 122, # 'È' + 201: 98, # 'É' + 202: 92, # 'Ê' + 203: 121, # 'Ë' + 204: 120, # 'Ì' + 205: 91, # 'Í' + 206: 103, # 'Î' + 207: 119, # 'Ï' + 208: 68, # 'Ğ' + 209: 118, # 'Ñ' + 210: 117, # 'Ò' + 211: 97, # 'Ó' + 212: 116, # 'Ô' + 213: 115, # 'Õ' + 214: 50, # 'Ö' + 215: 90, # '×' + 216: 114, # 'Ø' + 217: 113, # 'Ù' + 218: 112, # 'Ú' + 219: 111, # 'Û' + 220: 55, # 'Ü' + 221: 41, # 'İ' + 222: 40, # 'Ş' + 223: 86, # 'ß' + 224: 89, # 'à' + 225: 70, # 'á' + 226: 59, # 'â' + 227: 78, # 'ã' + 228: 71, # 'ä' + 229: 82, # 'å' + 230: 88, # 'æ' + 231: 33, # 'ç' + 232: 77, # 'è' + 233: 66, # 'é' + 234: 84, # 'ê' + 235: 83, # 'ë' + 236: 110, # 'ì' + 237: 75, # 'í' + 238: 61, # 'î' + 239: 96, # 'ï' + 240: 30, # 'ğ' + 241: 67, # 'ñ' + 242: 109, # 'ò' + 243: 74, # 'ó' + 244: 87, # 'ô' + 245: 102, # 'õ' + 246: 34, # 'ö' + 247: 95, # '÷' + 248: 81, # 'ø' + 249: 108, # 'ù' + 250: 76, # 'ú' + 251: 72, # 'û' + 252: 17, # 'ü' + 253: 6, # 'ı' + 254: 19, # 'ş' + 255: 107, # 'ÿ' } + +ISO_8859_9_TURKISH_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-9', + language='Turkish', + char_to_order_map=ISO_8859_9_TURKISH_CHAR_TO_ORDER, + language_model=TURKISH_LANG_MODEL, + typical_positive_ratio=0.97029, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVYZabcdefghijklmnoprstuvyzÂÇÎÖÛÜâçîöûüĞğİıŞş') + diff --git a/pipenv/vendor/importlib_metadata/docs/__init__.py b/pipenv/vendor/chardet/metadata/__init__.py similarity index 100% rename from pipenv/vendor/importlib_metadata/docs/__init__.py rename to pipenv/vendor/chardet/metadata/__init__.py diff --git a/pipenv/vendor/chardet/metadata/languages.py b/pipenv/vendor/chardet/metadata/languages.py new file mode 100644 index 00000000..3237d5ab --- /dev/null +++ b/pipenv/vendor/chardet/metadata/languages.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Metadata about languages used by our model training code for our +SingleByteCharSetProbers. Could be used for other things in the future. + +This code is based on the language metadata from the uchardet project. +""" +from __future__ import absolute_import, print_function + +from string import ascii_letters + + +# TODO: Add Ukranian (KOI8-U) + +class Language(object): + """Metadata about a language useful for training models + + :ivar name: The human name for the language, in English. + :type name: str + :ivar iso_code: 2-letter ISO 639-1 if possible, 3-letter ISO code otherwise, + or use another catalog as a last resort. + :type iso_code: str + :ivar use_ascii: Whether or not ASCII letters should be included in trained + models. + :type use_ascii: bool + :ivar charsets: The charsets we want to support and create data for. + :type charsets: list of str + :ivar alphabet: The characters in the language's alphabet. If `use_ascii` is + `True`, you only need to add those not in the ASCII set. + :type alphabet: str + :ivar wiki_start_pages: The Wikipedia pages to start from if we're crawling + Wikipedia for training data. + :type wiki_start_pages: list of str + """ + def __init__(self, name=None, iso_code=None, use_ascii=True, charsets=None, + alphabet=None, wiki_start_pages=None): + super(Language, self).__init__() + self.name = name + self.iso_code = iso_code + self.use_ascii = use_ascii + self.charsets = charsets + if self.use_ascii: + if alphabet: + alphabet += ascii_letters + else: + alphabet = ascii_letters + elif not alphabet: + raise ValueError('Must supply alphabet if use_ascii is False') + self.alphabet = ''.join(sorted(set(alphabet))) if alphabet else None + self.wiki_start_pages = wiki_start_pages + + def __repr__(self): + return '{}({})'.format(self.__class__.__name__, + ', '.join('{}={!r}'.format(k, v) + for k, v in self.__dict__.items() + if not k.startswith('_'))) + + +LANGUAGES = {'Arabic': Language(name='Arabic', + iso_code='ar', + use_ascii=False, + # We only support encodings that use isolated + # forms, because the current recommendation is + # that the rendering system handles presentation + # forms. This means we purposefully skip IBM864. + charsets=['ISO-8859-6', 'WINDOWS-1256', + 'CP720', 'CP864'], + alphabet=u'ءآأؤإئابةتثجحخدذرزسشصضطظعغػؼؽؾؿـفقكلمنهوىيًٌٍَُِّ', + wiki_start_pages=[u'الصفحة_الرئيسية']), + 'Belarusian': Language(name='Belarusian', + iso_code='be', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'IBM866', 'MacCyrillic'], + alphabet=(u'АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШЫЬЭЮЯ' + u'абвгдеёжзійклмнопрстуўфхцчшыьэюяʼ'), + wiki_start_pages=[u'Галоўная_старонка']), + 'Bulgarian': Language(name='Bulgarian', + iso_code='bg', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'IBM855'], + alphabet=(u'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЬЮЯ' + u'абвгдежзийклмнопрстуфхцчшщъьюя'), + wiki_start_pages=[u'Начална_страница']), + 'Czech': Language(name='Czech', + iso_code='cz', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'áčďéěíňóřšťúůýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ', + wiki_start_pages=[u'Hlavní_strana']), + 'Danish': Language(name='Danish', + iso_code='da', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'æøåÆØÅ', + wiki_start_pages=[u'Forside']), + 'German': Language(name='German', + iso_code='de', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + alphabet=u'äöüßÄÖÜ', + wiki_start_pages=[u'Wikipedia:Hauptseite']), + 'Greek': Language(name='Greek', + iso_code='el', + use_ascii=False, + charsets=['ISO-8859-7', 'WINDOWS-1253'], + alphabet=(u'αβγδεζηθικλμνξοπρσςτυφχψωάέήίόύώ' + u'ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΣΤΥΦΧΨΩΆΈΉΊΌΎΏ'), + wiki_start_pages=[u'Πύλη:Κύρια']), + 'English': Language(name='English', + iso_code='en', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + wiki_start_pages=[u'Main_Page']), + 'Esperanto': Language(name='Esperanto', + iso_code='eo', + # Q, W, X, and Y not used at all + use_ascii=False, + charsets=['ISO-8859-3'], + alphabet=(u'abcĉdefgĝhĥijĵklmnoprsŝtuŭvz' + u'ABCĈDEFGĜHĤIJĴKLMNOPRSŜTUŬVZ'), + wiki_start_pages=[u'Vikipedio:Ĉefpaĝo']), + 'Spanish': Language(name='Spanish', + iso_code='es', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ñáéíóúüÑÁÉÍÓÚÜ', + wiki_start_pages=[u'Wikipedia:Portada']), + 'Estonian': Language(name='Estonian', + iso_code='et', + use_ascii=False, + charsets=['ISO-8859-4', 'ISO-8859-13', + 'WINDOWS-1257'], + # C, F, Š, Q, W, X, Y, Z, Ž are only for + # loanwords + alphabet=(u'ABDEGHIJKLMNOPRSTUVÕÄÖÜ' + u'abdeghijklmnoprstuvõäöü'), + wiki_start_pages=[u'Esileht']), + 'Finnish': Language(name='Finnish', + iso_code='fi', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÅÄÖŠŽåäöšž', + wiki_start_pages=[u'Wikipedia:Etusivu']), + 'French': Language(name='French', + iso_code='fr', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'œàâçèéîïùûêŒÀÂÇÈÉÎÏÙÛÊ', + wiki_start_pages=[u'Wikipédia:Accueil_principal', + u'Bœuf (animal)']), + 'Hebrew': Language(name='Hebrew', + iso_code='he', + use_ascii=False, + charsets=['ISO-8859-8', 'WINDOWS-1255'], + alphabet=u'אבגדהוזחטיךכלםמןנסעףפץצקרשתװױײ', + wiki_start_pages=[u'עמוד_ראשי']), + 'Croatian': Language(name='Croatian', + iso_code='hr', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcčćdđefghijklmnoprsštuvzž' + u'ABCČĆDĐEFGHIJKLMNOPRSŠTUVZŽ'), + wiki_start_pages=[u'Glavna_stranica']), + 'Hungarian': Language(name='Hungarian', + iso_code='hu', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcdefghijklmnoprstuvzáéíóöőúüű' + u'ABCDEFGHIJKLMNOPRSTUVZÁÉÍÓÖŐÚÜŰ'), + wiki_start_pages=[u'Kezdőlap']), + 'Italian': Language(name='Italian', + iso_code='it', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÀÈÉÌÒÓÙàèéìòóù', + wiki_start_pages=[u'Pagina_principale']), + 'Lithuanian': Language(name='Lithuanian', + iso_code='lt', + use_ascii=False, + charsets=['ISO-8859-13', 'WINDOWS-1257', + 'ISO-8859-4'], + # Q, W, and X not used at all + alphabet=(u'AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ' + u'aąbcčdeęėfghiįyjklmnoprsštuųūvzž'), + wiki_start_pages=[u'Pagrindinis_puslapis']), + 'Latvian': Language(name='Latvian', + iso_code='lv', + use_ascii=False, + charsets=['ISO-8859-13', 'WINDOWS-1257', + 'ISO-8859-4'], + # Q, W, X, Y are only for loanwords + alphabet=(u'AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ' + u'aābcčdeēfgģhiījkķlļmnņoprsštuūvzž'), + wiki_start_pages=[u'Sākumlapa']), + 'Macedonian': Language(name='Macedonian', + iso_code='mk', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'MacCyrillic', 'IBM855'], + alphabet=(u'АБВГДЃЕЖЗЅИЈКЛЉМНЊОПРСТЌУФХЦЧЏШ' + u'абвгдѓежзѕијклљмнњопрстќуфхцчџш'), + wiki_start_pages=[u'Главна_страница']), + 'Dutch': Language(name='Dutch', + iso_code='nl', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + wiki_start_pages=[u'Hoofdpagina']), + 'Polish': Language(name='Polish', + iso_code='pl', + # Q and X are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWYZŹŻ' + u'aąbcćdeęfghijklłmnńoóprsśtuwyzźż'), + wiki_start_pages=[u'Wikipedia:Strona_główna']), + 'Portuguese': Language(name='Portuguese', + iso_code='pt', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÁÂÃÀÇÉÊÍÓÔÕÚáâãàçéêíóôõú', + wiki_start_pages=[u'Wikipédia:Página_principal']), + 'Romanian': Language(name='Romanian', + iso_code='ro', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'ăâîșțĂÂÎȘȚ', + wiki_start_pages=[u'Pagina_principală']), + 'Russian': Language(name='Russian', + iso_code='ru', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'KOI8-R', 'MacCyrillic', 'IBM866', + 'IBM855'], + alphabet=(u'абвгдеёжзийклмнопрстуфхцчшщъыьэюя' + u'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'), + wiki_start_pages=[u'Заглавная_страница']), + 'Slovak': Language(name='Slovak', + iso_code='sk', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'áäčďéíĺľňóôŕšťúýžÁÄČĎÉÍĹĽŇÓÔŔŠŤÚÝŽ', + wiki_start_pages=[u'Hlavná_stránka']), + 'Slovene': Language(name='Slovene', + iso_code='sl', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcčdefghijklmnoprsštuvzž' + u'ABCČDEFGHIJKLMNOPRSŠTUVZŽ'), + wiki_start_pages=[u'Glavna_stran']), + # Serbian can be written in both Latin and Cyrillic, but there's no + # simple way to get the Latin alphabet pages from Wikipedia through + # the API, so for now we just support Cyrillic. + 'Serbian': Language(name='Serbian', + iso_code='sr', + alphabet=(u'АБВГДЂЕЖЗИЈКЛЉМНЊОПРСТЋУФХЦЧЏШ' + u'абвгдђежзијклљмнњопрстћуфхцчџш'), + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'MacCyrillic', 'IBM855'], + wiki_start_pages=[u'Главна_страна']), + 'Thai': Language(name='Thai', + iso_code='th', + use_ascii=False, + charsets=['ISO-8859-11', 'TIS-620', 'CP874'], + alphabet=u'กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛', + wiki_start_pages=[u'หน้าหลัก']), + 'Turkish': Language(name='Turkish', + iso_code='tr', + # Q, W, and X are not used by Turkish + use_ascii=False, + charsets=['ISO-8859-3', 'ISO-8859-9', + 'WINDOWS-1254'], + alphabet=(u'abcçdefgğhıijklmnoöprsştuüvyzâîû' + u'ABCÇDEFGĞHIİJKLMNOÖPRSŞTUÜVYZÂÎÛ'), + wiki_start_pages=[u'Ana_Sayfa']), + 'Vietnamese': Language(name='Vietnamese', + iso_code='vi', + use_ascii=False, + # Windows-1258 is the only common 8-bit + # Vietnamese encoding supported by Python. + # From Wikipedia: + # For systems that lack support for Unicode, + # dozens of 8-bit Vietnamese code pages are + # available.[1] The most common are VISCII + # (TCVN 5712:1993), VPS, and Windows-1258.[3] + # Where ASCII is required, such as when + # ensuring readability in plain text e-mail, + # Vietnamese letters are often encoded + # according to Vietnamese Quoted-Readable + # (VIQR) or VSCII Mnemonic (VSCII-MNEM),[4] + # though usage of either variable-width + # scheme has declined dramatically following + # the adoption of Unicode on the World Wide + # Web. + charsets=['WINDOWS-1258'], + alphabet=(u'aăâbcdđeêghiklmnoôơpqrstuưvxy' + u'AĂÂBCDĐEÊGHIKLMNOÔƠPQRSTUƯVXY'), + wiki_start_pages=[u'Chữ_Quốc_ngữ']), + } diff --git a/pipenv/vendor/chardet/sbcharsetprober.py b/pipenv/vendor/chardet/sbcharsetprober.py index 0adb51de..46ba835c 100644 --- a/pipenv/vendor/chardet/sbcharsetprober.py +++ b/pipenv/vendor/chardet/sbcharsetprober.py @@ -26,10 +26,22 @@ # 02110-1301 USA ######################### END LICENSE BLOCK ######################### +from collections import namedtuple + from .charsetprober import CharSetProber from .enums import CharacterCategory, ProbingState, SequenceLikelihood +SingleByteCharSetModel = namedtuple('SingleByteCharSetModel', + ['charset_name', + 'language', + 'char_to_order_map', + 'language_model', + 'typical_positive_ratio', + 'keep_ascii_letters', + 'alphabet']) + + class SingleByteCharSetProber(CharSetProber): SAMPLE_SIZE = 64 SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 @@ -65,25 +77,25 @@ class SingleByteCharSetProber(CharSetProber): if self._name_prober: return self._name_prober.charset_name else: - return self._model['charset_name'] + return self._model.charset_name @property def language(self): if self._name_prober: return self._name_prober.language else: - return self._model.get('language') + return self._model.language def feed(self, byte_str): - if not self._model['keep_english_letter']: + # TODO: Make filter_international_words keep things in self.alphabet + if not self._model.keep_ascii_letters: byte_str = self.filter_international_words(byte_str) if not byte_str: return self.state - char_to_order_map = self._model['char_to_order_map'] - for i, c in enumerate(byte_str): - # XXX: Order is in range 1-64, so one would think we want 0-63 here, - # but that leads to 27 more test failures than before. - order = char_to_order_map[c] + char_to_order_map = self._model.char_to_order_map + language_model = self._model.language_model + for char in byte_str: + order = char_to_order_map.get(char, CharacterCategory.UNDEFINED) # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but # CharacterCategory.SYMBOL is actually 253, so we use CONTROL # to make it closer to the original intent. The only difference @@ -91,20 +103,21 @@ class SingleByteCharSetProber(CharSetProber): # _total_char purposes. if order < CharacterCategory.CONTROL: self._total_char += 1 + # TODO: Follow uchardet's lead and discount confidence for frequent + # control characters. + # See https://github.com/BYVoid/uchardet/commit/55b4f23971db61 if order < self.SAMPLE_SIZE: self._freq_char += 1 if self._last_order < self.SAMPLE_SIZE: self._total_seqs += 1 if not self._reversed: - i = (self._last_order * self.SAMPLE_SIZE) + order - model = self._model['precedence_matrix'][i] - else: # reverse the order of the letters in the lookup - i = (order * self.SAMPLE_SIZE) + self._last_order - model = self._model['precedence_matrix'][i] - self._seq_counters[model] += 1 + lm_cat = language_model[self._last_order][order] + else: + lm_cat = language_model[order][self._last_order] + self._seq_counters[lm_cat] += 1 self._last_order = order - charset_name = self._model['charset_name'] + charset_name = self._model.charset_name if self.state == ProbingState.DETECTING: if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: confidence = self.get_confidence() @@ -125,7 +138,7 @@ class SingleByteCharSetProber(CharSetProber): r = 0.01 if self._total_seqs > 0: r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / - self._total_seqs / self._model['typical_positive_ratio']) + self._total_seqs / self._model.typical_positive_ratio) r = r * self._freq_char / self._total_char if r >= 1.0: r = 0.99 diff --git a/pipenv/vendor/chardet/sbcsgroupprober.py b/pipenv/vendor/chardet/sbcsgroupprober.py index 98e95dc1..bdeef4e1 100644 --- a/pipenv/vendor/chardet/sbcsgroupprober.py +++ b/pipenv/vendor/chardet/sbcsgroupprober.py @@ -27,47 +27,57 @@ ######################### END LICENSE BLOCK ######################### from .charsetgroupprober import CharSetGroupProber -from .sbcharsetprober import SingleByteCharSetProber -from .langcyrillicmodel import (Win1251CyrillicModel, Koi8rModel, - Latin5CyrillicModel, MacCyrillicModel, - Ibm866Model, Ibm855Model) -from .langgreekmodel import Latin7GreekModel, Win1253GreekModel -from .langbulgarianmodel import Latin5BulgarianModel, Win1251BulgarianModel -# from .langhungarianmodel import Latin2HungarianModel, Win1250HungarianModel -from .langthaimodel import TIS620ThaiModel -from .langhebrewmodel import Win1255HebrewModel from .hebrewprober import HebrewProber -from .langturkishmodel import Latin5TurkishModel +from .langbulgarianmodel import (ISO_8859_5_BULGARIAN_MODEL, + WINDOWS_1251_BULGARIAN_MODEL) +from .langgreekmodel import ISO_8859_7_GREEK_MODEL, WINDOWS_1253_GREEK_MODEL +from .langhebrewmodel import WINDOWS_1255_HEBREW_MODEL +# from .langhungarianmodel import (ISO_8859_2_HUNGARIAN_MODEL, +# WINDOWS_1250_HUNGARIAN_MODEL) +from .langrussianmodel import (IBM855_RUSSIAN_MODEL, IBM866_RUSSIAN_MODEL, + ISO_8859_5_RUSSIAN_MODEL, KOI8_R_RUSSIAN_MODEL, + MACCYRILLIC_RUSSIAN_MODEL, + WINDOWS_1251_RUSSIAN_MODEL) +from .langthaimodel import TIS_620_THAI_MODEL +from .langturkishmodel import ISO_8859_9_TURKISH_MODEL +from .sbcharsetprober import SingleByteCharSetProber class SBCSGroupProber(CharSetGroupProber): def __init__(self): super(SBCSGroupProber, self).__init__() + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(WINDOWS_1255_HEBREW_MODEL, + False, hebrew_prober) + # TODO: See if using ISO-8859-8 Hebrew model works better here, since + # it's actually the visual one + visual_hebrew_prober = SingleByteCharSetProber(WINDOWS_1255_HEBREW_MODEL, + True, hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, + visual_hebrew_prober) + # TODO: ORDER MATTERS HERE. I changed the order vs what was in master + # and several tests failed that did not before. Some thought + # should be put into the ordering, and we should consider making + # order not matter here, because that is very counter-intuitive. self.probers = [ - SingleByteCharSetProber(Win1251CyrillicModel), - SingleByteCharSetProber(Koi8rModel), - SingleByteCharSetProber(Latin5CyrillicModel), - SingleByteCharSetProber(MacCyrillicModel), - SingleByteCharSetProber(Ibm866Model), - SingleByteCharSetProber(Ibm855Model), - SingleByteCharSetProber(Latin7GreekModel), - SingleByteCharSetProber(Win1253GreekModel), - SingleByteCharSetProber(Latin5BulgarianModel), - SingleByteCharSetProber(Win1251BulgarianModel), + SingleByteCharSetProber(WINDOWS_1251_RUSSIAN_MODEL), + SingleByteCharSetProber(KOI8_R_RUSSIAN_MODEL), + SingleByteCharSetProber(ISO_8859_5_RUSSIAN_MODEL), + SingleByteCharSetProber(MACCYRILLIC_RUSSIAN_MODEL), + SingleByteCharSetProber(IBM866_RUSSIAN_MODEL), + SingleByteCharSetProber(IBM855_RUSSIAN_MODEL), + SingleByteCharSetProber(ISO_8859_7_GREEK_MODEL), + SingleByteCharSetProber(WINDOWS_1253_GREEK_MODEL), + SingleByteCharSetProber(ISO_8859_5_BULGARIAN_MODEL), + SingleByteCharSetProber(WINDOWS_1251_BULGARIAN_MODEL), # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) # after we retrain model. - # SingleByteCharSetProber(Latin2HungarianModel), - # SingleByteCharSetProber(Win1250HungarianModel), - SingleByteCharSetProber(TIS620ThaiModel), - SingleByteCharSetProber(Latin5TurkishModel), + # SingleByteCharSetProber(ISO_8859_2_HUNGARIAN_MODEL), + # SingleByteCharSetProber(WINDOWS_1250_HUNGARIAN_MODEL), + SingleByteCharSetProber(TIS_620_THAI_MODEL), + SingleByteCharSetProber(ISO_8859_9_TURKISH_MODEL), + hebrew_prober, + logical_hebrew_prober, + visual_hebrew_prober, ] - hebrew_prober = HebrewProber() - logical_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, - False, hebrew_prober) - visual_hebrew_prober = SingleByteCharSetProber(Win1255HebrewModel, True, - hebrew_prober) - hebrew_prober.set_model_probers(logical_hebrew_prober, visual_hebrew_prober) - self.probers.extend([hebrew_prober, logical_hebrew_prober, - visual_hebrew_prober]) - self.reset() diff --git a/pipenv/vendor/chardet/universaldetector.py b/pipenv/vendor/chardet/universaldetector.py index 7b4e92d6..055a8ac1 100644 --- a/pipenv/vendor/chardet/universaldetector.py +++ b/pipenv/vendor/chardet/universaldetector.py @@ -266,7 +266,7 @@ class UniversalDetector(object): 'language': max_prober.language} # Log all prober confidences if none met MINIMUM_THRESHOLD - if self.logger.getEffectiveLevel() == logging.DEBUG: + if self.logger.getEffectiveLevel() <= logging.DEBUG: if self.result['encoding'] is None: self.logger.debug('no probers hit minimum threshold') for group_prober in self._charset_probers: @@ -280,7 +280,7 @@ class UniversalDetector(object): prober.get_confidence()) else: self.logger.debug('%s %s confidence = %s', - prober.charset_name, - prober.language, - prober.get_confidence()) + group_prober.charset_name, + group_prober.language, + group_prober.get_confidence()) return self.result diff --git a/pipenv/vendor/chardet/version.py b/pipenv/vendor/chardet/version.py index bb2a34a7..70369b9d 100644 --- a/pipenv/vendor/chardet/version.py +++ b/pipenv/vendor/chardet/version.py @@ -5,5 +5,5 @@ from within setup.py and from chardet subpackages. :author: Dan Blanchard (dan.blanchard@gmail.com) """ -__version__ = "3.0.4" +__version__ = "4.0.0" VERSION = __version__.split('.') diff --git a/pipenv/vendor/charset_normalizer/LICENSE b/pipenv/vendor/charset_normalizer/LICENSE new file mode 100644 index 00000000..ad82355b --- /dev/null +++ b/pipenv/vendor/charset_normalizer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 TAHRI Ahmed R. + +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. \ No newline at end of file diff --git a/pipenv/vendor/charset_normalizer/__init__.py b/pipenv/vendor/charset_normalizer/__init__.py new file mode 100644 index 00000000..f14a90b1 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/__init__.py @@ -0,0 +1,31 @@ +""" +Charset-Normalizer +~~~~~~~~~~~~~~ +The Real First Universal Charset Detector. +A library that helps you read text from an unknown charset encoding. +Motivated by chardet, This package is trying to resolve the issue by taking a new approach. +All IANA character set names for which the Python core library provides codecs are supported. + +Basic usage: + >>> from charset_normalizer import from_bytes + >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието трябва да бъде безплатно, поне що се отнася до началното и основното образование.'.encode('utf_8')) + >>> "utf_8" in results + True + >>> best_result = results.best() + >>> str(best_result) + 'Bсеки човек има право на образование. Oбразованието трябва да бъде безплатно, поне що се отнася до началното и основното образование.' + +Others methods and usages are available - see the full documentation +at . +:copyright: (c) 2021 by Ahmed TAHRI +:license: MIT, see LICENSE for more details. +""" +from charset_normalizer.api import from_fp, from_path, from_bytes, normalize +from charset_normalizer.legacy import detect +from charset_normalizer.version import __version__, VERSION +from charset_normalizer.models import CharsetMatch, CharsetMatches + +# Backward-compatible v1 imports +from charset_normalizer.models import CharsetNormalizerMatch +import charset_normalizer.api as CharsetDetector +CharsetNormalizerMatches = CharsetDetector diff --git a/pipenv/vendor/charset_normalizer/api.py b/pipenv/vendor/charset_normalizer/api.py new file mode 100644 index 00000000..7ad912cb --- /dev/null +++ b/pipenv/vendor/charset_normalizer/api.py @@ -0,0 +1,421 @@ +from os.path import splitext, basename +from typing import List, BinaryIO, Optional, Set, Union + +try: + from os import PathLike +except ImportError: + PathLike = Union[str, 'os.PathLike[str]'] # type: ignore + +from charset_normalizer.constant import TOO_SMALL_SEQUENCE, TOO_BIG_SEQUENCE, IANA_SUPPORTED +from charset_normalizer.md import mess_ratio +from charset_normalizer.models import CharsetMatches, CharsetMatch +from warnings import warn +import logging + +from charset_normalizer.utils import any_specified_encoding, is_multi_byte_encoding, identify_sig_or_bom, \ + should_strip_sig_or_bom, is_cp_similar, iana_name +from charset_normalizer.cd import coherence_ratio, encoding_languages, mb_encoding_languages, merge_coherence_ratios + +logger = logging.getLogger("charset_normalizer") +logger.setLevel(logging.DEBUG) + +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter('%(asctime)s | %(levelname)s | %(message)s')) +logger.addHandler(handler) + + +def from_bytes( + sequences: bytes, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.2, + cp_isolation: List[str] = None, + cp_exclusion: List[str] = None, + preemptive_behaviour: bool = True, + explain: bool = False +) -> CharsetMatches: + """ + Given a raw bytes sequence, return the best possibles charset usable to render str objects. + If there is no results, it is a strong indicator that the source is binary/not text. + By default, the process will extract 5 blocs of 512o each to assess the mess and coherence of a given sequence. + And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. + + The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page + but never take it for granted. Can improve the performance. + + You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that + purpose. + + This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. + """ + + if not explain: + logger.setLevel(logging.CRITICAL) + else: + logger.setLevel(logging.INFO) + + length = len(sequences) # type: int + + if length == 0: + logger.warning("Given content is empty, stopping the process very early, returning empty utf_8 str match") + return CharsetMatches( + [ + CharsetMatch( + sequences, + "utf_8", + 0., + False, + [], + "" + ) + ] + ) + + if cp_isolation is not None: + logger.warning('cp_isolation is set. use this flag for debugging purpose. ' + 'limited list of encoding allowed : %s.', + ', '.join(cp_isolation)) + cp_isolation = [iana_name(cp, False) for cp in cp_isolation] + else: + cp_isolation = [] + + if cp_exclusion is not None: + logger.warning( + 'cp_exclusion is set. use this flag for debugging purpose. ' + 'limited list of encoding excluded : %s.', + ', '.join(cp_exclusion)) + cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] + else: + cp_exclusion = [] + + if length <= (chunk_size * steps): + logger.warning( + 'override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.', + steps, chunk_size, length) + steps = 1 + chunk_size = length + + if steps > 1 and length / steps < chunk_size: + chunk_size = int(length / steps) + + is_too_small_sequence = len(sequences) < TOO_SMALL_SEQUENCE # type: bool + is_too_large_sequence = len(sequences) >= TOO_BIG_SEQUENCE # type: bool + + if is_too_small_sequence: + warn('Trying to detect encoding from a tiny portion of ({}) byte(s).'.format(length)) + + prioritized_encodings = [] # type: List[str] + + specified_encoding = any_specified_encoding(sequences) if preemptive_behaviour is True else None # type: Optional[str] + + if specified_encoding is not None: + prioritized_encodings.append(specified_encoding) + logger.info('Detected declarative mark in sequence. Priority +1 given for %s.', specified_encoding) + + tested = set() # type: Set[str] + tested_but_hard_failure = [] # type: List[str] + tested_but_soft_failure = [] # type: List[str] + + fallback_ascii = None # type: Optional[CharsetMatch] + fallback_u8 = None # type: Optional[CharsetMatch] + + single_byte_hard_failure_count = 0 # type: int + single_byte_soft_failure_count = 0 # type: int + + results = CharsetMatches() # type: CharsetMatches + + sig_encoding, sig_payload = identify_sig_or_bom(sequences) + + if sig_encoding is not None: + prioritized_encodings.append(sig_encoding) + logger.info('Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.', len(sig_payload), sig_encoding) + + prioritized_encodings.append("ascii") + + if "utf_8" not in prioritized_encodings: + prioritized_encodings.append("utf_8") + + for encoding_iana in prioritized_encodings+IANA_SUPPORTED: + + if cp_isolation and encoding_iana not in cp_isolation: + continue + + if cp_exclusion and encoding_iana in cp_exclusion: + continue + + if encoding_iana in tested: + continue + + tested.add(encoding_iana) + + decoded_payload = None # type: Optional[str] + bom_or_sig_available = sig_encoding == encoding_iana # type: bool + strip_sig_or_bom = bom_or_sig_available and should_strip_sig_or_bom(encoding_iana) # type: bool + + if encoding_iana in {"utf_16", "utf_32"} and bom_or_sig_available is False: + logger.info("Encoding %s wont be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", encoding_iana) + continue + + try: + is_multi_byte_decoder = is_multi_byte_encoding(encoding_iana) # type: bool + except (ModuleNotFoundError, ImportError): + logger.debug("Encoding %s does not provide an IncrementalDecoder", encoding_iana) + continue + + try: + if is_too_large_sequence and is_multi_byte_decoder is False: + str( + sequences[:int(50e4)] if strip_sig_or_bom is False else sequences[len(sig_payload):int(50e4)], + encoding=encoding_iana + ) + else: + decoded_payload = str( + sequences if strip_sig_or_bom is False else sequences[len(sig_payload):], + encoding=encoding_iana + ) + except UnicodeDecodeError as e: + logger.warning('Code page %s does not fit given bytes sequence at ALL. %s', encoding_iana, str(e)) + tested_but_hard_failure.append(encoding_iana) + if not is_multi_byte_decoder: + single_byte_hard_failure_count += 1 + continue + except LookupError: + tested_but_hard_failure.append(encoding_iana) + if not is_multi_byte_decoder: + single_byte_hard_failure_count += 1 + continue + + similar_soft_failure_test = False # type: bool + + for encoding_soft_failed in tested_but_soft_failure: + if is_cp_similar(encoding_iana, encoding_soft_failed): + similar_soft_failure_test = True + break + + if similar_soft_failure_test: + logger.warning("%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", encoding_iana, encoding_soft_failed) + continue + + r_ = range( + 0 if bom_or_sig_available is False else len(sig_payload), + length, + int(length / steps) + ) + + multi_byte_bonus = is_multi_byte_decoder and decoded_payload is not None and len(decoded_payload) < length # type: bool + + if multi_byte_bonus: + logger.info('Code page %s is a multi byte encoding table and it appear that at least one character was encoded using n-bytes. Should not be a coincidence. Priority +1 given.', encoding_iana) + + max_chunk_gave_up = int(len(r_) / 4) # type: int + + if max_chunk_gave_up < 2: + max_chunk_gave_up = 2 + + early_stop_count = 0 # type: int + + md_chunks = [] # type: List[str] + md_ratios = [] + + for i in r_: + cut_sequence = sequences[i:i + chunk_size] + + if bom_or_sig_available and strip_sig_or_bom is False: + cut_sequence = sig_payload+cut_sequence + + chunk = cut_sequence.decode(encoding_iana, errors="ignore") # type: str + + md_chunks.append(chunk) + + md_ratios.append( + mess_ratio( + chunk, + threshold + ) + ) + + if md_ratios[-1] >= threshold: + early_stop_count += 1 + + if (early_stop_count >= max_chunk_gave_up) or (bom_or_sig_available and strip_sig_or_bom is False): + break + + if md_ratios: + mean_mess_ratio = sum(md_ratios) / len(md_ratios) # type: float + else: + mean_mess_ratio = 0. + + if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: + tested_but_soft_failure.append(encoding_iana) + if not is_multi_byte_decoder: + single_byte_soft_failure_count += 1 + logger.warning('%s was excluded because of initial chaos probing. Gave up %i time(s). ' + 'Computed mean chaos is %f %%.', + encoding_iana, + early_stop_count, + round(mean_mess_ratio * 100, ndigits=3)) + # Preparing those fallbacks in case we got nothing. + if encoding_iana in ["ascii", "utf_8"]: + fallback_entry = CharsetMatch( + sequences, + encoding_iana, + threshold, + False, + [], + decoded_payload + ) + if encoding_iana == "ascii": + fallback_ascii = fallback_entry + else: + fallback_u8 = fallback_entry + continue + + logger.info( + '%s passed initial chaos probing. Mean measured chaos is %f %%', + encoding_iana, + round(mean_mess_ratio * 100, ndigits=3) + ) + + if not is_multi_byte_decoder: + target_languages = encoding_languages(encoding_iana) # type: List[str] + else: + target_languages = mb_encoding_languages(encoding_iana) + + if target_languages: + logger.info("{} should target any language(s) of {}".format(encoding_iana, str(target_languages))) + + cd_ratios = [] + + for chunk in md_chunks: + chunk_languages = coherence_ratio(chunk, 0.1, ",".join(target_languages) if target_languages else None) + + cd_ratios.append( + chunk_languages + ) + + cd_ratios_merged = merge_coherence_ratios(cd_ratios) + + if cd_ratios_merged: + logger.info("We detected language {} using {}".format(cd_ratios_merged, encoding_iana)) + + results.append( + CharsetMatch( + sequences, + encoding_iana, + mean_mess_ratio, + bom_or_sig_available, + cd_ratios_merged, + decoded_payload + ) + ) + + if encoding_iana in [specified_encoding, "ascii", "utf_8"] and mean_mess_ratio < 0.1: + logger.info("%s is most likely the one. Stopping the process.", encoding_iana) + return CharsetMatches( + [results[encoding_iana]] + ) + + if encoding_iana == sig_encoding: + logger.info( + "%s is most likely the one as we detected a BOM or SIG within the beginning of the sequence.", + encoding_iana + ) + return CharsetMatches( + [results[encoding_iana]] + ) + + if results[-1].languages: + logger.info( + "Using %s code page we detected the following languages: %s", + encoding_iana, + results[-1]._languages + ) + + if len(results) == 0: + if fallback_u8 or fallback_ascii: + logger.warning("Nothing got out of the detection process. Using ASCII/UTF-8 fallback.") + + if (fallback_u8 and fallback_ascii is None) or (fallback_u8 and fallback_u8.fingerprint != fallback_ascii.fingerprint): + logger.warning("utf_8 will be used as a fallback match") + results.append(fallback_u8) + elif fallback_ascii: + logger.warning("ascii will be used as a fallback match") + results.append(fallback_ascii) + + return results + + +def from_fp( + fp: BinaryIO, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: List[str] = None, + cp_exclusion: List[str] = None, + preemptive_behaviour: bool = True, + explain: bool = False +) -> CharsetMatches: + """ + Same thing than the function from_bytes but using a file pointer that is already ready. + Will not close the file pointer. + """ + return from_bytes( + fp.read(), + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour, + explain + ) + + +def from_path( + path: PathLike, + steps: int = 5, + chunk_size: int = 512, + threshold: float = 0.20, + cp_isolation: List[str] = None, + cp_exclusion: List[str] = None, + preemptive_behaviour: bool = True, + explain: bool = False +) -> CharsetMatches: + """ + Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. + Can raise IOError. + """ + with open(path, 'rb') as fp: + return from_fp(fp, steps, chunk_size, threshold, cp_isolation, cp_exclusion, preemptive_behaviour, explain) + + +def normalize(path: PathLike, steps: int = 5, chunk_size: int = 512, threshold: float = 0.20, cp_isolation: List[str] = None, cp_exclusion: List[str] = None, preemptive_behaviour: bool = True) -> CharsetMatch: + """ + Take a (text-based) file path and try to create another file next to it, this time using UTF-8. + """ + results = from_path( + path, + steps, + chunk_size, + threshold, + cp_isolation, + cp_exclusion, + preemptive_behaviour + ) + + filename = basename(path) + target_extensions = list(splitext(filename)) + + if len(results) == 0: + raise IOError('Unable to normalize "{}", no encoding charset seems to fit.'.format(filename)) + + result = results.best() + + target_extensions[0] += '-' + result.encoding # type: ignore + + with open('{}'.format(path.replace(filename, ''.join(target_extensions))), 'wb') as fp: + fp.write( + result.output() # type: ignore + ) + + return result # type: ignore diff --git a/pipenv/vendor/charset_normalizer/assets/__init__.py b/pipenv/vendor/charset_normalizer/assets/__init__.py new file mode 100644 index 00000000..2d937736 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/assets/__init__.py @@ -0,0 +1,52 @@ +""" +This submodule purpose is to load attached JSON asset. +Will be loaded once per package import / python init. + +The file 'frequencies.json' is mandatory for language/coherence detection. Not having it will weaker considerably +the core detection. +""" +from collections import OrderedDict + + +FREQUENCIES = OrderedDict( + [ + ('English', ['e', 'a', 't', 'i', 'o', 'n', 's', 'r', 'h', 'l', 'd', 'c', 'u', 'm', 'f', 'p', 'g', 'w', 'y', 'b', 'v', 'k', 'x', 'j', 'z', 'q']), + ('German', ['e', 'n', 'i', 'r', 's', 't', 'a', 'd', 'h', 'u', 'l', 'g', 'o', 'c', 'm', 'b', 'f', 'k', 'w', 'z', 'p', 'v', 'ü', 'ä', 'ö', 'j']), + ('French', ['e', 'a', 's', 'n', 'i', 't', 'r', 'l', 'u', 'o', 'd', 'c', 'p', 'm', 'é', 'v', 'g', 'f', 'b', 'h', 'q', 'à', 'x', 'è', 'y', 'j']), + ('Dutch', ['e', 'n', 'a', 'i', 'r', 't', 'o', 'd', 's', 'l', 'g', 'h', 'v', 'm', 'u', 'k', 'c', 'p', 'b', 'w', 'j', 'z', 'f', 'y', 'x', 'ë']), + ('Italian', ['e', 'i', 'a', 'o', 'n', 'l', 't', 'r', 's', 'c', 'd', 'u', 'p', 'm', 'g', 'v', 'f', 'b', 'z', 'h', 'q', 'è', 'à', 'k', 'y', 'ò']), + ('Polish', ['a', 'i', 'o', 'e', 'n', 'r', 'z', 'w', 's', 'c', 't', 'k', 'y', 'd', 'p', 'm', 'u', 'l', 'j', 'ł', 'g', 'b', 'h', 'ą', 'ę', 'ó']), + ('Spanish', ['e', 'a', 'o', 'n', 's', 'r', 'i', 'l', 'd', 't', 'c', 'u', 'm', 'p', 'b', 'g', 'v', 'f', 'y', 'ó', 'h', 'q', 'í', 'j', 'z', 'á']), + ('Russian', ['о', 'а', 'е', 'и', 'н', 'с', 'т', 'р', 'в', 'л', 'к', 'м', 'д', 'п', 'у', 'г', 'я', 'ы', 'з', 'б', 'й', 'ь', 'ч', 'х', 'ж', 'ц']), + ('Japanese', ['の', 'に', 'る', 'た', 'は', 'ー', 'と', 'し', 'を', 'で', 'て', 'が', 'い', 'ン', 'れ', 'な', '年', 'ス', 'っ', 'ル', 'か', 'ら', 'あ', 'さ', 'も', 'り']), + ('Portuguese', ['a', 'e', 'o', 's', 'i', 'r', 'd', 'n', 't', 'm', 'u', 'c', 'l', 'p', 'g', 'v', 'b', 'f', 'h', 'ã', 'q', 'é', 'ç', 'á', 'z', 'í']), + ('Swedish', ['e', 'a', 'n', 'r', 't', 's', 'i', 'l', 'd', 'o', 'm', 'k', 'g', 'v', 'h', 'f', 'u', 'p', 'ä', 'c', 'b', 'ö', 'å', 'y', 'j', 'x']), + ('Chinese', ['的', '一', '是', '不', '了', '在', '人', '有', '我', '他', '这', '个', '们', '中', '来', '上', '大', '为', '和', '国', '地', '到', '以', '说', '时', '要', '就', '出', '会']), + ('Ukrainian', ['о', 'а', 'н', 'і', 'и', 'р', 'в', 'т', 'е', 'с', 'к', 'л', 'у', 'д', 'м', 'п', 'з', 'я', 'ь', 'б', 'г', 'й', 'ч', 'х', 'ц', 'ї']), + ('Norwegian', ['e', 'r', 'n', 't', 'a', 's', 'i', 'o', 'l', 'd', 'g', 'k', 'm', 'v', 'f', 'p', 'u', 'b', 'h', 'å', 'y', 'j', 'ø', 'c', 'æ', 'w']), + ('Finnish', ['a', 'i', 'n', 't', 'e', 's', 'l', 'o', 'u', 'k', 'ä', 'm', 'r', 'v', 'j', 'h', 'p', 'y', 'd', 'ö', 'g', 'c', 'b', 'f', 'w', 'z']), + ('Vietnamese', ['n', 'h', 't', 'i', 'c', 'g', 'a', 'o', 'u', 'm', 'l', 'r', 'à', 'đ', 's', 'e', 'v', 'p', 'b', 'y', 'ư', 'd', 'á', 'k', 'ộ', 'ế']), + ('Czech', ['o', 'e', 'a', 'n', 't', 's', 'i', 'l', 'v', 'r', 'k', 'd', 'u', 'm', 'p', 'í', 'c', 'h', 'z', 'á', 'y', 'j', 'b', 'ě', 'é', 'ř']), + ('Hungarian', ['e', 'a', 't', 'l', 's', 'n', 'k', 'r', 'i', 'o', 'z', 'á', 'é', 'g', 'm', 'b', 'y', 'v', 'd', 'h', 'u', 'p', 'j', 'ö', 'f', 'c']), + ('Korean', ['이', '다', '에', '의', '는', '로', '하', '을', '가', '고', '지', '서', '한', '은', '기', '으', '년', '대', '사', '시', '를', '리', '도', '인', '스', '일']), + ('Indonesian', ['a', 'n', 'e', 'i', 'r', 't', 'u', 's', 'd', 'k', 'm', 'l', 'g', 'p', 'b', 'o', 'h', 'y', 'j', 'c', 'w', 'f', 'v', 'z', 'x', 'q']), + ('Turkish', ['a', 'e', 'i', 'n', 'r', 'l', 'ı', 'k', 'd', 't', 's', 'm', 'y', 'u', 'o', 'b', 'ü', 'ş', 'v', 'g', 'z', 'h', 'c', 'p', 'ç', 'ğ']), + ('Romanian', ['e', 'i', 'a', 'r', 'n', 't', 'u', 'l', 'o', 'c', 's', 'd', 'p', 'm', 'ă', 'f', 'v', 'î', 'g', 'b', 'ș', 'ț', 'z', 'h', 'â', 'j']), + ('Farsi', ['ا', 'ی', 'ر', 'د', 'ن', 'ه', 'و', 'م', 'ت', 'ب', 'س', 'ل', 'ک', 'ش', 'ز', 'ف', 'گ', 'ع', 'خ', 'ق', 'ج', 'آ', 'پ', 'ح', 'ط', 'ص']), + ('Arabic', ['ا', 'ل', 'ي', 'م', 'و', 'ن', 'ر', 'ت', 'ب', 'ة', 'ع', 'د', 'س', 'ف', 'ه', 'ك', 'ق', 'أ', 'ح', 'ج', 'ش', 'ط', 'ص', 'ى', 'خ', 'إ']), + ('Danish', ['e', 'r', 'n', 't', 'a', 'i', 's', 'd', 'l', 'o', 'g', 'm', 'k', 'f', 'v', 'u', 'b', 'h', 'p', 'å', 'y', 'ø', 'æ', 'c', 'j', 'w']), + ('Serbian', ['а', 'и', 'о', 'е', 'н', 'р', 'с', 'у', 'т', 'к', 'ј', 'в', 'д', 'м', 'п', 'л', 'г', 'з', 'б', 'a', 'i', 'e', 'o', 'n', 'ц', 'ш']), + ('Lithuanian', ['i', 'a', 's', 'o', 'r', 'e', 't', 'n', 'u', 'k', 'm', 'l', 'p', 'v', 'd', 'j', 'g', 'ė', 'b', 'y', 'ų', 'š', 'ž', 'c', 'ą', 'į']), + ('Slovene', ['e', 'a', 'i', 'o', 'n', 'r', 's', 'l', 't', 'j', 'v', 'k', 'd', 'p', 'm', 'u', 'z', 'b', 'g', 'h', 'č', 'c', 'š', 'ž', 'f', 'y']), + ('Slovak', ['o', 'a', 'e', 'n', 'i', 'r', 'v', 't', 's', 'l', 'k', 'd', 'm', 'p', 'u', 'c', 'h', 'j', 'b', 'z', 'á', 'y', 'ý', 'í', 'č', 'é']), + ('Hebrew', ['י', 'ו', 'ה', 'ל', 'ר', 'ב', 'ת', 'מ', 'א', 'ש', 'נ', 'ע', 'ם', 'ד', 'ק', 'ח', 'פ', 'ס', 'כ', 'ג', 'ט', 'צ', 'ן', 'ז', 'ך']), + ('Bulgarian', ['а', 'и', 'о', 'е', 'н', 'т', 'р', 'с', 'в', 'л', 'к', 'д', 'п', 'м', 'з', 'г', 'я', 'ъ', 'у', 'б', 'ч', 'ц', 'й', 'ж', 'щ', 'х']), + ('Croatian', ['a', 'i', 'o', 'e', 'n', 'r', 'j', 's', 't', 'u', 'k', 'l', 'v', 'd', 'm', 'p', 'g', 'z', 'b', 'c', 'č', 'h', 'š', 'ž', 'ć', 'f']), + ('Hindi', ['क', 'र', 'स', 'न', 'त', 'म', 'ह', 'प', 'य', 'ल', 'व', 'ज', 'द', 'ग', 'ब', 'श', 'ट', 'अ', 'ए', 'थ', 'भ', 'ड', 'च', 'ध', 'ष', 'इ']), + ('Estonian', ['a', 'i', 'e', 's', 't', 'l', 'u', 'n', 'o', 'k', 'r', 'd', 'm', 'v', 'g', 'p', 'j', 'h', 'ä', 'b', 'õ', 'ü', 'f', 'c', 'ö', 'y']), + ('Simple English', ['e', 'a', 't', 'i', 'o', 'n', 's', 'r', 'h', 'l', 'd', 'c', 'm', 'u', 'f', 'p', 'g', 'w', 'b', 'y', 'v', 'k', 'j', 'x', 'z', 'q']), + ('Thai', ['า', 'น', 'ร', 'อ', 'ก', 'เ', 'ง', 'ม', 'ย', 'ล', 'ว', 'ด', 'ท', 'ส', 'ต', 'ะ', 'ป', 'บ', 'ค', 'ห', 'แ', 'จ', 'พ', 'ช', 'ข', 'ใ']), + ('Greek', ['α', 'τ', 'ο', 'ι', 'ε', 'ν', 'ρ', 'σ', 'κ', 'η', 'π', 'ς', 'υ', 'μ', 'λ', 'ί', 'ό', 'ά', 'γ', 'έ', 'δ', 'ή', 'ω', 'χ', 'θ', 'ύ']), + ('Tamil', ['க', 'த', 'ப', 'ட', 'ர', 'ம', 'ல', 'ன', 'வ', 'ற', 'ய', 'ள', 'ச', 'ந', 'இ', 'ண', 'அ', 'ஆ', 'ழ', 'ங', 'எ', 'உ', 'ஒ', 'ஸ']), + ('Classical Chinese', ['之', '年', '為', '也', '以', '一', '人', '其', '者', '國', '有', '二', '十', '於', '曰', '三', '不', '大', '而', '子', '中', '五', '四'])] +) diff --git a/pipenv/vendor/charset_normalizer/cd.py b/pipenv/vendor/charset_normalizer/cd.py new file mode 100644 index 00000000..c4fc1ba5 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/cd.py @@ -0,0 +1,261 @@ +from codecs import IncrementalDecoder +from functools import lru_cache +from typing import List, Set, Optional, Tuple, Dict +import importlib + +from charset_normalizer.models import CoherenceMatches +from charset_normalizer.utils import unicode_range, is_unicode_range_secondary, is_multi_byte_encoding +from charset_normalizer.md import is_suspiciously_successive_range +from charset_normalizer.assets import FREQUENCIES +from collections import Counter + + +def encoding_unicode_range(iana_name: str) -> List[str]: + """ + Return associated unicode ranges in a single byte code page. + """ + if is_multi_byte_encoding(iana_name): + raise IOError("Function not supported on multi-byte code page") + + decoder = importlib.import_module('encodings.{}'.format(iana_name)).IncrementalDecoder # type: ignore + + p = decoder(errors="ignore") # type: IncrementalDecoder + seen_ranges = set() # type: Set[str] + + for i in range(48, 255): + chunk = p.decode( + bytes([i]) + ) # type: str + + if chunk: + character_range = unicode_range(chunk) # type: Optional[str] + + if character_range is None: + continue + + if is_unicode_range_secondary(character_range) is False: + seen_ranges.add(character_range) + + return sorted(list(seen_ranges)) + + +def unicode_range_languages(primary_range: str) -> List[str]: + """ + Return inferred languages used with a unicode range. + """ + languages = [] # type: List[str] + + for language, characters in FREQUENCIES.items(): + for character in characters: + if unicode_range(character) == primary_range: + languages.append(language) + break + + return languages + + +@lru_cache() +def encoding_languages(iana_name: str) -> List[str]: + """ + Single-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + unicode_ranges = encoding_unicode_range(iana_name) # type: List[str] + primary_range = None # type: Optional[str] + + for specified_range in unicode_ranges: + if "Latin" not in specified_range: + primary_range = specified_range + break + + if primary_range is None: + return ["Latin Based"] + + return unicode_range_languages(primary_range) + + +def mb_encoding_languages(iana_name: str) -> List[str]: + """ + Multi-byte encoding language association. Some code page are heavily linked to particular language(s). + This function does the correspondence. + """ + if iana_name.startswith("shift_") or iana_name.startswith("iso2022_jp") or iana_name.startswith("euc_j") or iana_name in {"cp932"}: + return ["Japanese"] + if iana_name.startswith("gb") or iana_name in {"big5", "cp950", "big5hkscs"}: + return ["Chinese", "Classical Chinese"] + if iana_name.startswith("iso2022_kr") or iana_name in {"johab", "cp949", "euc_kr"}: + return ["Korean"] + + return [] + + +def alphabet_languages(characters: List[str]) -> List[str]: + """ + Return associated languages associated to given characters. + """ + languages = [] # type: List[str] + + for language, language_characters in FREQUENCIES.items(): + character_match_count = 0 # type: int + character_count = len(language_characters) # type: int + + for character in language_characters: + if character in characters: + character_match_count += 1 + + if character_match_count / character_count >= 0.2: + languages.append(language) + + return languages + + +def characters_popularity_compare(language: str, ordered_characters: List[str]) -> float: + """ + Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. + The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). + Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) + """ + if language not in FREQUENCIES: + raise ValueError("{} not available".format(language)) + + character_approved_count = 0 # type: int + + for character in ordered_characters: + if character not in FREQUENCIES[language]: + continue + + characters_before_source = FREQUENCIES[language][0:FREQUENCIES[language].index(character)] # type: List[str] + characters_after_source = FREQUENCIES[language][FREQUENCIES[language].index(character):] # type: List[str] + + characters_before = ordered_characters[0:ordered_characters.index(character)] # type: List[str] + characters_after = ordered_characters[ordered_characters.index(character):] # type: List[str] + + before_match_count = [e in characters_before for e in characters_before_source].count(True) # type: int + after_match_count = [e in characters_after for e in characters_after_source].count(True) # type: int + + if len(characters_before_source) == 0 and before_match_count <= 4: + character_approved_count += 1 + continue + + if len(characters_after_source) == 0 and after_match_count <= 4: + character_approved_count += 1 + continue + + if before_match_count / len(characters_before_source) >= 0.4 or after_match_count / len(characters_after_source) >= 0.4: + character_approved_count += 1 + continue + + return character_approved_count / len(ordered_characters) + + +def alpha_unicode_split(decoded_sequence: str) -> List[str]: + """ + Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. + Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; + One containing the latin letters and the other hebrew. + """ + layers = {} # type: Dict[str, str] + + for character in decoded_sequence: + if character.isalpha() is False: + continue + + character_range = unicode_range(character) # type: str + + layer_target_range = None # type: Optional[str] + + for discovered_range in layers: + if is_suspiciously_successive_range(discovered_range, character_range) is False: + layer_target_range = discovered_range + break + + if layer_target_range is None: + layer_target_range = character_range + + if layer_target_range not in layers: + layers[layer_target_range] = character.lower() + continue + + layers[layer_target_range] += character.lower() + + return list(layers.values()) + + +def merge_coherence_ratios(results: List[CoherenceMatches]) -> CoherenceMatches: + """ + This function merge results previously given by the function coherence_ratio. + The return type is the same as coherence_ratio. + """ + per_language_ratios = {} # type: Dict[str, List[float]] + merge = [] # type: CoherenceMatches + + for result in results: + for sub_result in result: + language, ratio = sub_result + if language not in per_language_ratios: + per_language_ratios[language] = [ratio] + continue + per_language_ratios[language].append( + ratio + ) + + for language in per_language_ratios: + merge.append( + ( + language, + round( + sum( + per_language_ratios[language] + ) / len(per_language_ratios[language]), + 4 + ) + ) + ) + + return sorted(merge, key=lambda x: x[1], reverse=True) + + +@lru_cache(maxsize=2048) +def coherence_ratio(decoded_sequence: str, threshold: float = 0.1, lg_inclusion: Optional[str] = None) -> CoherenceMatches: + """ + Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. + A layer = Character extraction by alphabets/ranges. + """ + + results = [] # type: List[Tuple[str, float]] + + sufficient_match_count = 0 # type: int + + if lg_inclusion is not None: + lg_inclusion = lg_inclusion.split(",") + + if lg_inclusion is not None and "Latin Based" in lg_inclusion: + lg_inclusion.remove("Latin Based") + + for layer in alpha_unicode_split(decoded_sequence): + sequence_frequencies = Counter(layer) # type: Counter + most_common = sequence_frequencies.most_common() + + character_count = sum([o for c, o in most_common]) # type: int + + if character_count <= 32: + continue + + popular_character_ordered = [c for c, o in most_common] # type: List[str] + + for language in lg_inclusion or alphabet_languages(popular_character_ordered): + ratio = characters_popularity_compare(language, popular_character_ordered) # type: float + + if ratio < threshold: + continue + elif ratio >= 0.8: + sufficient_match_count += 1 + + results.append( + (language, round(ratio, 4)) + ) + + if sufficient_match_count >= 3: + break + + return sorted(results, key=lambda x: x[1], reverse=True) diff --git a/pipenv/vendor/importlib_metadata/tests/__init__.py b/pipenv/vendor/charset_normalizer/cli/__init__.py similarity index 100% rename from pipenv/vendor/importlib_metadata/tests/__init__.py rename to pipenv/vendor/charset_normalizer/cli/__init__.py diff --git a/pipenv/vendor/charset_normalizer/cli/normalizer.py b/pipenv/vendor/charset_normalizer/cli/normalizer.py new file mode 100644 index 00000000..189dde3c --- /dev/null +++ b/pipenv/vendor/charset_normalizer/cli/normalizer.py @@ -0,0 +1,210 @@ +import argparse +import sys +from os.path import abspath +from json import dumps + +from charset_normalizer import from_fp +from charset_normalizer.models import CliDetectionResult +from charset_normalizer.version import __version__ + +from platform import python_version + + +def query_yes_no(question, default="yes"): + """Ask a yes/no question via input() and return their answer. + + "question" is a string that is presented to the user. + "default" is the presumed answer if the user just hits . + It must be "yes" (the default), "no" or None (meaning + an answer is required of the user). + + The "answer" return value is True for "yes" or False for "no". + + Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input + """ + valid = {"yes": True, "y": True, "ye": True, + "no": False, "n": False} + if default is None: + prompt = " [y/n] " + elif default == "yes": + prompt = " [Y/n] " + elif default == "no": + prompt = " [y/N] " + else: + raise ValueError("invalid default answer: '%s'" % default) + + while True: + sys.stdout.write(question + prompt) + choice = input().lower() + if default is not None and choice == '': + return valid[default] + elif choice in valid: + return valid[choice] + else: + sys.stdout.write("Please respond with 'yes' or 'no' " + "(or 'y' or 'n').\n") + + +def cli_detect(argv=None): + """ + CLI assistant using ARGV and ArgumentParser + :param argv: + :return: 0 if everything is fine, anything else equal trouble + """ + parser = argparse.ArgumentParser( + description="The Real First Universal Charset Detector. " + "Discover originating encoding used on text file. " + "Normalize text to unicode." + ) + + parser.add_argument('files', type=argparse.FileType('rb'), nargs='+', help='File(s) to be analysed') + parser.add_argument('-v', '--verbose', action="store_true", default=False, dest='verbose', + help='Display complementary information about file if any. Stdout will contain logs about the detection process.') + parser.add_argument('-a', '--with-alternative', action="store_true", default=False, dest='alternatives', + help='Output complementary possibilities if any. Top-level JSON WILL be a list.') + parser.add_argument('-n', '--normalize', action="store_true", default=False, dest='normalize', + help='Permit to normalize input file. If not set, program does not write anything.') + parser.add_argument('-m', '--minimal', action="store_true", default=False, dest='minimal', + help='Only output the charset detected to STDOUT. Disabling JSON output.') + parser.add_argument('-r', '--replace', action="store_true", default=False, dest='replace', + help='Replace file when trying to normalize it instead of creating a new one.') + parser.add_argument('-f', '--force', action="store_true", default=False, dest='force', + help='Replace file without asking if you are sure, use this flag with caution.') + parser.add_argument('-t', '--threshold', action="store", default=0.1, type=float, dest='threshold', + help="Define a custom maximum amount of chaos allowed in decoded content. 0. <= chaos <= 1.") + parser.add_argument( + "--version", + action="version", + version="Charset-Normalizer {} - Python {}".format(__version__, python_version()), + help="Show version information and exit." + ) + + args = parser.parse_args(argv) + + if args.replace is True and args.normalize is False: + print('Use --replace in addition of --normalize only.', file=sys.stderr) + return 1 + + if args.force is True and args.replace is False: + print('Use --force in addition of --replace only.', file=sys.stderr) + return 1 + + if args.threshold < 0. or args.threshold > 1.: + print('--threshold VALUE should be between 0. AND 1.', file=sys.stderr) + return 1 + + for my_file in args.files: + + matches = from_fp( + my_file, + threshold=args.threshold, + explain=args.verbose + ) + + if len(matches) == 0: + print('Unable to identify originating encoding for "{}". {}'.format(my_file.name, 'Maybe try increasing maximum amount of chaos.' if args.threshold < 1. else ''), file=sys.stderr) + if my_file.closed is False: + my_file.close() + continue + + x_ = [] + + r_ = matches.best() + p_ = r_.first() + + x_.append( + CliDetectionResult( + abspath(my_file.name), + p_.encoding, + p_.encoding_aliases, + [cp for cp in p_.could_be_from_charset if cp != p_.encoding], + p_.language, + p_.alphabets, + p_.bom, + p_.percent_chaos, + p_.percent_coherence, + None, + True + ) + ) + + if len(matches) > 1 and args.alternatives: + for el in matches: + if el != p_: + x_.append( + CliDetectionResult( + abspath(my_file.name), + el.encoding, + el.encoding_aliases, + [cp for cp in el.could_be_from_charset if cp != el.encoding], + el.language, + el.alphabets, + el.bom, + el.percent_chaos, + el.percent_coherence, + None, + False + ) + ) + + if args.normalize is True: + + if p_.encoding.startswith('utf') is True: + print('"{}" file does not need to be normalized, as it already came from unicode.'.format(my_file.name), file=sys.stderr) + if my_file.closed is False: + my_file.close() + continue + + o_ = my_file.name.split('.') # type: list[str] + + if args.replace is False: + o_.insert(-1, p_.encoding) + if my_file.closed is False: + my_file.close() + else: + if args.force is False and query_yes_no( + 'Are you sure to normalize "{}" by replacing it ?'.format(my_file.name), 'no') is False: + if my_file.closed is False: + my_file.close() + continue + + try: + x_[0].unicode_path = './{}'.format('.'.join(o_)) + + with open(x_[0].unicode_path, 'w', encoding='utf-8') as fp: + fp.write( + str(p_) + ) + except IOError as e: + print(str(e), file=sys.stderr) + if my_file.closed is False: + my_file.close() + return 2 + + if my_file.closed is False: + my_file.close() + + if args.minimal is False: + print( + dumps( + [ + el.__dict__ for el in x_ + ] if args.alternatives else x_[0].__dict__, + ensure_ascii=True, + indent=4 + ) + ) + else: + print( + ', '.join( + [ + el.encoding for el in x_ + ] + ) + ) + + return 0 + + +if __name__ == '__main__': + cli_detect() diff --git a/pipenv/vendor/charset_normalizer/constant.py b/pipenv/vendor/charset_normalizer/constant.py new file mode 100644 index 00000000..c9c96555 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/constant.py @@ -0,0 +1,343 @@ +from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE +from typing import Dict, List, Union +from encodings.aliases import aliases +from re import compile as re_compile, IGNORECASE +from collections import OrderedDict + +# Contain for each eligible encoding a list of/item bytes SIG/BOM +ENCODING_MARKS = OrderedDict([ + ('utf_8', BOM_UTF8), + ('utf_7', [ + b'\x2b\x2f\x76\x38', + b'\x2b\x2f\x76\x39', + b'\x2b\x2f\x76\x2b', + b'\x2b\x2f\x76\x2f', + b'\x2b\x2f\x76\x38\x2d' + ]), + ('gb18030', b'\x84\x31\x95\x33'), + ('utf_32', [ + BOM_UTF32_BE, + BOM_UTF32_LE + ]), + ('utf_16', [ + BOM_UTF16_BE, + BOM_UTF16_LE + ]), +]) # type: Dict[str, Union[bytes, List[bytes]]] + +TOO_SMALL_SEQUENCE = 32 # type: int +TOO_BIG_SEQUENCE = int(10e6) # type: int + +UTF8_MAXIMAL_ALLOCATION = 1112064 # type: int + +UNICODE_RANGES_COMBINED = {'Control character': range(0, 31+1), 'Basic Latin': range(32, 127+1), 'Latin-1 Supplement': range(128, 255+1), 'Latin Extended-A': range(256, 383+1), 'Latin Extended-B': range(384, 591+1), 'IPA Extensions': range(592, 687+1), 'Spacing Modifier Letters': range(688, 767+1), 'Combining Diacritical Marks': range(768, 879+1), 'Greek and Coptic': range(880, 1023+1), 'Cyrillic': range(1024, 1279+1), 'Cyrillic Supplement': range(1280, 1327+1), 'Armenian': range(1328, 1423+1), 'Hebrew': range(1424, 1535+1), 'Arabic': range(1536, 1791+1), 'Syriac': range(1792, 1871+1), 'Arabic Supplement': range(1872, 1919+1), 'Thaana': range(1920, 1983+1), 'NKo': range(1984, 2047+1), 'Samaritan': range(2048, 2111+1), 'Mandaic': range(2112, 2143+1), 'Syriac Supplement': range(2144, 2159+1), 'Arabic Extended-A': range(2208, 2303+1), 'Devanagari': range(2304, 2431+1), 'Bengali': range(2432, 2559+1), 'Gurmukhi': range(2560, 2687+1), 'Gujarati': range(2688, 2815+1), 'Oriya': range(2816, 2943+1), 'Tamil': range(2944, 3071+1), 'Telugu': range(3072, 3199+1), 'Kannada': range(3200, 3327+1), 'Malayalam': range(3328, 3455+1), 'Sinhala': range(3456, 3583+1), 'Thai': range(3584, 3711+1), 'Lao': range(3712, 3839+1), 'Tibetan': range(3840, 4095+1), 'Myanmar': range(4096, 4255+1), 'Georgian': range(4256, 4351+1), 'Hangul Jamo': range(4352, 4607+1), 'Ethiopic': range(4608, 4991+1), 'Ethiopic Supplement': range(4992, 5023+1), 'Cherokee': range(5024, 5119+1), 'Unified Canadian Aboriginal Syllabics': range(5120, 5759+1), 'Ogham': range(5760, 5791+1), 'Runic': range(5792, 5887+1), 'Tagalog': range(5888, 5919+1), 'Hanunoo': range(5920, 5951+1), 'Buhid': range(5952, 5983+1), 'Tagbanwa': range(5984, 6015+1), 'Khmer': range(6016, 6143+1), 'Mongolian': range(6144, 6319+1), 'Unified Canadian Aboriginal Syllabics Extended': range(6320, 6399+1), 'Limbu': range(6400, 6479+1), 'Tai Le': range(6480, 6527+1), 'New Tai Lue': range(6528, 6623+1), 'Khmer Symbols': range(6624, 6655+1), 'Buginese': range(6656, 6687+1), 'Tai Tham': range(6688, 6831+1), 'Combining Diacritical Marks Extended': range(6832, 6911+1), 'Balinese': range(6912, 7039+1), 'Sundanese': range(7040, 7103+1), 'Batak': range(7104, 7167+1), 'Lepcha': range(7168, 7247+1), 'Ol Chiki': range(7248, 7295+1), 'Cyrillic Extended C': range(7296, 7311+1), 'Sundanese Supplement': range(7360, 7375+1), 'Vedic Extensions': range(7376, 7423+1), 'Phonetic Extensions': range(7424, 7551+1), 'Phonetic Extensions Supplement': range(7552, 7615+1), 'Combining Diacritical Marks Supplement': range(7616, 7679+1), 'Latin Extended Additional': range(7680, 7935+1), 'Greek Extended': range(7936, 8191+1), 'General Punctuation': range(8192, 8303+1), 'Superscripts and Subscripts': range(8304, 8351+1), 'Currency Symbols': range(8352, 8399+1), 'Combining Diacritical Marks for Symbols': range(8400, 8447+1), 'Letterlike Symbols': range(8448, 8527+1), 'Number Forms': range(8528, 8591+1), 'Arrows': range(8592, 8703+1), 'Mathematical Operators': range(8704, 8959+1), 'Miscellaneous Technical': range(8960, 9215+1), 'Control Pictures': range(9216, 9279+1), 'Optical Character Recognition': range(9280, 9311+1), 'Enclosed Alphanumerics': range(9312, 9471+1), 'Box Drawing': range(9472, 9599+1), 'Block Elements': range(9600, 9631+1), 'Geometric Shapes': range(9632, 9727+1), 'Miscellaneous Symbols': range(9728, 9983+1), 'Dingbats': range(9984, 10175+1), 'Miscellaneous Mathematical Symbols-A': range(10176, 10223+1), 'Supplemental Arrows-A': range(10224, 10239+1), 'Braille Patterns': range(10240, 10495+1), 'Supplemental Arrows-B': range(10496, 10623+1), 'Miscellaneous Mathematical Symbols-B': range(10624, 10751+1), 'Supplemental Mathematical Operators': range(10752, 11007+1), 'Miscellaneous Symbols and Arrows': range(11008, 11263+1), 'Glagolitic': range(11264, 11359+1), 'Latin Extended-C': range(11360, 11391+1), 'Coptic': range(11392, 11519+1), 'Georgian Supplement': range(11520, 11567+1), 'Tifinagh': range(11568, 11647+1), 'Ethiopic Extended': range(11648, 11743+1), 'Cyrillic Extended-A': range(11744, 11775+1), 'Supplemental Punctuation': range(11776, 11903+1), 'CJK Radicals Supplement': range(11904, 12031+1), 'Kangxi Radicals': range(12032, 12255+1), 'Ideographic Description Characters': range(12272, 12287+1), 'CJK Symbols and Punctuation': range(12288, 12351+1), 'Hiragana': range(12352, 12447+1), 'Katakana': range(12448, 12543+1), 'Bopomofo': range(12544, 12591+1), 'Hangul Compatibility Jamo': range(12592, 12687+1), 'Kanbun': range(12688, 12703+1), 'Bopomofo Extended': range(12704, 12735+1), 'CJK Strokes': range(12736, 12783+1), 'Katakana Phonetic Extensions': range(12784, 12799+1), 'Enclosed CJK Letters and Months': range(12800, 13055+1), 'CJK Compatibility': range(13056, 13311+1), 'CJK Unified Ideographs Extension A': range(13312, 19903+1), 'Yijing Hexagram Symbols': range(19904, 19967+1), 'CJK Unified Ideographs': range(19968, 40959+1), 'Yi Syllables': range(40960, 42127+1), 'Yi Radicals': range(42128, 42191+1), 'Lisu': range(42192, 42239+1), 'Vai': range(42240, 42559+1), 'Cyrillic Extended-B': range(42560, 42655+1), 'Bamum': range(42656, 42751+1), 'Modifier Tone Letters': range(42752, 42783+1), 'Latin Extended-D': range(42784, 43007+1), 'Syloti Nagri': range(43008, 43055+1), 'Common Indic Number Forms': range(43056, 43071+1), 'Phags-pa': range(43072, 43135+1), 'Saurashtra': range(43136, 43231+1), 'Devanagari Extended': range(43232, 43263+1), 'Kayah Li': range(43264, 43311+1), 'Rejang': range(43312, 43359+1), 'Hangul Jamo Extended-A': range(43360, 43391+1), 'Javanese': range(43392, 43487+1), 'Myanmar Extended-B': range(43488, 43519+1), 'Cham': range(43520, 43615+1), 'Myanmar Extended-A': range(43616, 43647+1), 'Tai Viet': range(43648, 43743+1), 'Meetei Mayek Extensions': range(43744, 43775+1), 'Ethiopic Extended-A': range(43776, 43823+1), 'Latin Extended-E': range(43824, 43887+1), 'Cherokee Supplement': range(43888, 43967+1), 'Meetei Mayek': range(43968, 44031+1), 'Hangul Syllables': range(44032, 55215+1), 'Hangul Jamo Extended-B': range(55216, 55295+1), 'High Surrogates': range(55296, 56191+1), 'High Private Use Surrogates': range(56192, 56319+1), 'Low Surrogates': range(56320, 57343+1), 'Private Use Area': range(57344, 63743+1), 'CJK Compatibility Ideographs': range(63744, 64255+1), 'Alphabetic Presentation Forms': range(64256, 64335+1), 'Arabic Presentation Forms-A': range(64336, 65023+1), 'Variation Selectors': range(65024, 65039+1), 'Vertical Forms': range(65040, 65055+1), 'Combining Half Marks': range(65056, 65071+1), 'CJK Compatibility Forms': range(65072, 65103+1), 'Small Form Variants': range(65104, 65135+1), 'Arabic Presentation Forms-B': range(65136, 65279+1), 'Halfwidth and Fullwidth Forms': range(65280, 65519+1), 'Specials': range(65520, 65535+1), 'Linear B Syllabary': range(65536, 65663+1), 'Linear B Ideograms': range(65664, 65791+1), 'Aegean Numbers': range(65792, 65855+1), 'Ancient Greek Numbers': range(65856, 65935+1), 'Ancient Symbols': range(65936, 65999+1), 'Phaistos Disc': range(66000, 66047+1), 'Lycian': range(66176, 66207+1), 'Carian': range(66208, 66271+1), 'Coptic Epact Numbers': range(66272, 66303+1), 'Old Italic': range(66304, 66351+1), 'Gothic': range(66352, 66383+1), 'Old Permic': range(66384, 66431+1), 'Ugaritic': range(66432, 66463+1), 'Old Persian': range(66464, 66527+1), 'Deseret': range(66560, 66639+1), 'Shavian': range(66640, 66687+1), 'Osmanya': range(66688, 66735+1), 'Osage': range(66736, 66815+1), 'Elbasan': range(66816, 66863+1), 'Caucasian Albanian': range(66864, 66927+1), 'Linear A': range(67072, 67455+1), 'Cypriot Syllabary': range(67584, 67647+1), 'Imperial Aramaic': range(67648, 67679+1), 'Palmyrene': range(67680, 67711+1), 'Nabataean': range(67712, 67759+1), 'Hatran': range(67808, 67839+1), 'Phoenician': range(67840, 67871+1), 'Lydian': range(67872, 67903+1), 'Meroitic Hieroglyphs': range(67968, 67999+1), 'Meroitic Cursive': range(68000, 68095+1), 'Kharoshthi': range(68096, 68191+1), 'Old South Arabian': range(68192, 68223+1), 'Old North Arabian': range(68224, 68255+1), 'Manichaean': range(68288, 68351+1), 'Avestan': range(68352, 68415+1), 'Inscriptional Parthian': range(68416, 68447+1), 'Inscriptional Pahlavi': range(68448, 68479+1), 'Psalter Pahlavi': range(68480, 68527+1), 'Old Turkic': range(68608, 68687+1), 'Old Hungarian': range(68736, 68863+1), 'Rumi Numeral Symbols': range(69216, 69247+1), 'Brahmi': range(69632, 69759+1), 'Kaithi': range(69760, 69839+1), 'Sora Sompeng': range(69840, 69887+1), 'Chakma': range(69888, 69967+1), 'Mahajani': range(69968, 70015+1), 'Sharada': range(70016, 70111+1), 'Sinhala Archaic Numbers': range(70112, 70143+1), 'Khojki': range(70144, 70223+1), 'Multani': range(70272, 70319+1), 'Khudawadi': range(70320, 70399+1), 'Grantha': range(70400, 70527+1), 'Newa': range(70656, 70783+1), 'Tirhuta': range(70784, 70879+1), 'Siddham': range(71040, 71167+1), 'Modi': range(71168, 71263+1), 'Mongolian Supplement': range(71264, 71295+1), 'Takri': range(71296, 71375+1), 'Ahom': range(71424, 71487+1), 'Warang Citi': range(71840, 71935+1), 'Zanabazar Square': range(72192, 72271+1), 'Soyombo': range(72272, 72367+1), 'Pau Cin Hau': range(72384, 72447+1), 'Bhaiksuki': range(72704, 72815+1), 'Marchen': range(72816, 72895+1), 'Masaram Gondi': range(72960, 73055+1), 'Cuneiform': range(73728, 74751+1), 'Cuneiform Numbers and Punctuation': range(74752, 74879+1), 'Early Dynastic Cuneiform': range(74880, 75087+1), 'Egyptian Hieroglyphs': range(77824, 78895+1), 'Anatolian Hieroglyphs': range(82944, 83583+1), 'Bamum Supplement': range(92160, 92735+1), 'Mro': range(92736, 92783+1), 'Bassa Vah': range(92880, 92927+1), 'Pahawh Hmong': range(92928, 93071+1), 'Miao': range(93952, 94111+1), 'Ideographic Symbols and Punctuation': range(94176, 94207+1), 'Tangut': range(94208, 100351+1), 'Tangut Components': range(100352, 101119+1), 'Kana Supplement': range(110592, 110847+1), 'Kana Extended-A': range(110848, 110895+1), 'Nushu': range(110960, 111359+1), 'Duployan': range(113664, 113823+1), 'Shorthand Format Controls': range(113824, 113839+1), 'Byzantine Musical Symbols': range(118784, 119039+1), 'Musical Symbols': range(119040, 119295+1), 'Ancient Greek Musical Notation': range(119296, 119375+1), 'Tai Xuan Jing Symbols': range(119552, 119647+1), 'Counting Rod Numerals': range(119648, 119679+1), 'Mathematical Alphanumeric Symbols': range(119808, 120831+1), 'Sutton SignWriting': range(120832, 121519+1), 'Glagolitic Supplement': range(122880, 122927+1), 'Mende Kikakui': range(124928, 125151+1), 'Adlam': range(125184, 125279+1), 'Arabic Mathematical Alphabetic Symbols': range(126464, 126719+1), 'Mahjong Tiles': range(126976, 127023+1), 'Domino Tiles': range(127024, 127135+1), 'Playing Cards': range(127136, 127231+1), 'Enclosed Alphanumeric Supplement': range(127232, 127487+1), 'Enclosed Ideographic Supplement': range(127488, 127743+1), 'Miscellaneous Symbols and Pictographs': range(127744, 128511+1), 'Emoticons range(Emoji)': range(128512, 128591+1), 'Ornamental Dingbats': range(128592, 128639+1), 'Transport and Map Symbols': range(128640, 128767+1), 'Alchemical Symbols': range(128768, 128895+1), 'Geometric Shapes Extended': range(128896, 129023+1), 'Supplemental Arrows-C': range(129024, 129279+1), 'Supplemental Symbols and Pictographs': range(129280, 129535+1), 'CJK Unified Ideographs Extension B': range(131072, 173791+1), 'CJK Unified Ideographs Extension C': range(173824, 177983+1), 'CJK Unified Ideographs Extension D': range(177984, 178207+1), 'CJK Unified Ideographs Extension E': range(178208, 183983+1), 'CJK Unified Ideographs Extension F': range(183984, 191471+1), 'CJK Compatibility Ideographs Supplement': range(194560, 195103+1), 'Tags': range(917504, 917631+1), 'Variation Selectors Supplement': range(917760, 917999+1)} # type: Dict[str, range] + +UNICODE_SECONDARY_RANGE_KEYWORD = [ + 'Supplement', + 'Extended', + 'Extensions', + 'Modifier', + 'Marks', + 'Punctuation', + 'Symbols', + 'Forms', + 'Operators', + 'Miscellaneous', + 'Drawing', + 'Block', + 'Shapes', + 'Supplemental', + 'Tags' +] # type: List[str] + +RE_POSSIBLE_ENCODING_INDICATION = re_compile( + r'(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)', + IGNORECASE +) + +IANA_SUPPORTED = sorted( + filter( + lambda x: x.endswith("_codec") is False and x not in {"rot_13", "tactis", "mbcs"}, + list(set(aliases.values())) + ) +) # type: List[str] + +IANA_SUPPORTED_COUNT = len(IANA_SUPPORTED) # type: int + +# pre-computed code page that are similar using the function cp_similarity. +IANA_SUPPORTED_SIMILAR = { + "cp037": [ + "cp1026", + "cp1140", + "cp273", + "cp500" + ], + "cp1026": [ + "cp037", + "cp1140", + "cp273", + "cp500" + ], + "cp1125": [ + "cp866" + ], + "cp1140": [ + "cp037", + "cp1026", + "cp273", + "cp500" + ], + "cp1250": [ + "iso8859_2" + ], + "cp1251": [ + "kz1048", + "ptcp154" + ], + "cp1252": [ + "cp1258", + "iso8859_15", + "iso8859_9", + "latin_1" + ], + "cp1253": [ + "iso8859_7" + ], + "cp1254": [ + "cp1258", + "iso8859_15", + "iso8859_9", + "latin_1" + ], + "cp1257": [ + "iso8859_13" + ], + "cp1258": [ + "cp1252", + "cp1254", + "iso8859_9", + "latin_1" + ], + "cp273": [ + "cp037", + "cp1026", + "cp1140", + "cp500" + ], + "cp437": [ + "cp850", + "cp858", + "cp860", + "cp861", + "cp862", + "cp863", + "cp865" + ], + "cp500": [ + "cp037", + "cp1026", + "cp1140", + "cp273" + ], + "cp850": [ + "cp437", + "cp857", + "cp858", + "cp865" + ], + "cp857": [ + "cp850", + "cp858", + "cp865" + ], + "cp858": [ + "cp437", + "cp850", + "cp857", + "cp865" + ], + "cp860": [ + "cp437", + "cp861", + "cp862", + "cp863", + "cp865" + ], + "cp861": [ + "cp437", + "cp860", + "cp862", + "cp863", + "cp865" + ], + "cp862": [ + "cp437", + "cp860", + "cp861", + "cp863", + "cp865" + ], + "cp863": [ + "cp437", + "cp860", + "cp861", + "cp862", + "cp865" + ], + "cp865": [ + "cp437", + "cp850", + "cp857", + "cp858", + "cp860", + "cp861", + "cp862", + "cp863" + ], + "cp866": [ + "cp1125" + ], + "iso8859_10": [ + "iso8859_14", + "iso8859_15", + "iso8859_4", + "iso8859_9", + "latin_1" + ], + "iso8859_11": [ + "tis_620" + ], + "iso8859_13": [ + "cp1257" + ], + "iso8859_14": [ + "iso8859_10", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1" + ], + "iso8859_15": [ + "cp1252", + "cp1254", + "iso8859_10", + "iso8859_14", + "iso8859_16", + "iso8859_3", + "iso8859_9", + "latin_1" + ], + "iso8859_16": [ + "iso8859_14", + "iso8859_15", + "iso8859_2", + "iso8859_3", + "iso8859_9", + "latin_1" + ], + "iso8859_2": [ + "cp1250", + "iso8859_16", + "iso8859_4" + ], + "iso8859_3": [ + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_9", + "latin_1" + ], + "iso8859_4": [ + "iso8859_10", + "iso8859_2", + "iso8859_9", + "latin_1" + ], + "iso8859_7": [ + "cp1253" + ], + "iso8859_9": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "latin_1" + ], + "kz1048": [ + "cp1251", + "ptcp154" + ], + "latin_1": [ + "cp1252", + "cp1254", + "cp1258", + "iso8859_10", + "iso8859_14", + "iso8859_15", + "iso8859_16", + "iso8859_3", + "iso8859_4", + "iso8859_9" + ], + "mac_iceland": [ + "mac_roman", + "mac_turkish" + ], + "mac_roman": [ + "mac_iceland", + "mac_turkish" + ], + "mac_turkish": [ + "mac_iceland", + "mac_roman" + ], + "ptcp154": [ + "cp1251", + "kz1048" + ], + "tis_620": [ + "iso8859_11" + ] +} # type: Dict[str, List[str]] + + +CHARDET_CORRESPONDENCE = { + 'iso2022_kr': 'ISO-2022-KR', + 'iso2022_jp': 'ISO-2022-JP', + 'euc_kr': 'EUC-KR', + 'tis_620': 'TIS-620', + 'utf_32': 'UTF-32', + 'euc_jp': 'EUC-JP', + 'koi8_r': 'KOI8-R', + 'iso8859_1': 'ISO-8859-1', + 'iso8859_2': 'ISO-8859-2', + 'iso8859_5': 'ISO-8859-5', + 'iso8859_6': 'ISO-8859-6', + 'iso8859_7': 'ISO-8859-7', + 'iso8859_8': 'ISO-8859-8', + 'utf_16': 'UTF-16', + 'cp855': 'IBM855', + 'mac_cyrillic': 'MacCyrillic', + 'gb2312': 'GB2312', + 'gb18030': 'GB18030', + 'cp932': 'CP932', + 'cp866': 'IBM866', + 'utf_8': 'utf-8', + 'utf_8_sig': 'UTF-8-SIG', + 'shift_jis': 'SHIFT_JIS', + 'big5': 'Big5', + 'cp1250': 'windows-1250', + 'cp1251': 'windows-1251', + 'cp1252': 'Windows-1252', + 'cp1253': 'windows-1253', + 'cp1255': 'windows-1255', + 'cp1256': 'windows-1256', + 'cp1254': 'Windows-1254', + 'cp949': 'CP949' +} # type: Dict[str, str] diff --git a/pipenv/vendor/charset_normalizer/legacy.py b/pipenv/vendor/charset_normalizer/legacy.py new file mode 100644 index 00000000..7b28cb48 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/legacy.py @@ -0,0 +1,38 @@ +from charset_normalizer.api import from_bytes +from charset_normalizer.constant import CHARDET_CORRESPONDENCE +from typing import Dict, Optional, Union + + +def detect(byte_str: bytes) -> Dict[str, Optional[Union[str, float]]]: + """ + chardet legacy method + Detect the encoding of the given byte string. It should be mostly backward-compatible. + Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) + This function is deprecated and should be used to migrate your project easily, consult the documentation for + further information. Not planned for removal. + + :param byte_str: The byte sequence to examine. + """ + if not isinstance(byte_str, (bytearray, bytes)): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{0}'.format(type(byte_str))) + + if isinstance(byte_str, bytearray): + byte_str = bytes(byte_str) + + r = from_bytes(byte_str).best() + + encoding = r.encoding if r is not None else None + language = r.language if r is not None and r.language != 'Unknown' else '' + confidence = 1. - r.chaos if r is not None else None + + # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process + # but chardet does return 'utf-8-sig' and it is a valid codec name. + if r is not None and encoding == 'utf_8' and r.bom: + encoding += '_sig' + + return { + 'encoding': encoding if encoding not in CHARDET_CORRESPONDENCE else CHARDET_CORRESPONDENCE[encoding], + 'language': language, + 'confidence': confidence + } diff --git a/pipenv/vendor/charset_normalizer/md.py b/pipenv/vendor/charset_normalizer/md.py new file mode 100644 index 00000000..4f9c7140 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/md.py @@ -0,0 +1,451 @@ +from functools import lru_cache +from typing import Optional, List + +from charset_normalizer.constant import UNICODE_SECONDARY_RANGE_KEYWORD +from charset_normalizer.utils import is_punctuation, is_symbol, unicode_range, is_accentuated, is_latin, \ + remove_accent, is_separator, is_cjk + + +class MessDetectorPlugin: + """ + Base abstract class used for mess detection plugins. + All detectors MUST extend and implement given methods. + """ + + def eligible(self, character: str) -> bool: + """ + Determine if given character should be fed in. + """ + raise NotImplementedError # pragma: nocover + + def feed(self, character: str) -> None: + """ + The main routine to be executed upon character. + Insert the logic in witch the text would be considered chaotic. + """ + raise NotImplementedError # pragma: nocover + + def reset(self) -> None: + """ + Permit to reset the plugin to the initial state. + """ + raise NotImplementedError # pragma: nocover + + @property + def ratio(self) -> float: + """ + Compute the chaos ratio based on what your feed() has seen. + Must NOT be lower than 0.; No restriction gt 0. + """ + raise NotImplementedError # pragma: nocover + + +class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): + + def __init__(self): + self._punctuation_count = 0 # type: int + self._symbol_count = 0 # type: int + self._character_count = 0 # type: int + + self._last_printable_char = None # type: Optional[str] + self._frenzy_symbol_in_word = False # type: bool + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if character != self._last_printable_char and character not in ["<", ">", "=", ":", "/", "&", ";", "{", "}", "[", "]"]: + if is_punctuation(character): + self._punctuation_count += 1 + elif character.isdigit() is False and is_symbol(character): + self._symbol_count += 2 + + self._last_printable_char = character + + def reset(self) -> None: + self._punctuation_count = 0 + self._character_count = 0 + self._symbol_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + + ratio_of_punctuation = (self._punctuation_count + self._symbol_count) / self._character_count # type: float + + return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0. + + +class TooManyAccentuatedPlugin(MessDetectorPlugin): + + def __init__(self): + self._character_count = 0 # type: int + self._accentuated_count = 0 # type: int + + def eligible(self, character: str) -> bool: + return character.isalpha() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if is_accentuated(character): + self._accentuated_count += 1 + + def reset(self) -> None: + self._character_count = 0 + self._accentuated_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + ratio_of_accentuation = self._accentuated_count / self._character_count # type: float + return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0. + + +class UnprintablePlugin(MessDetectorPlugin): + + def __init__(self): + self._unprintable_count = 0 # type: int + self._character_count = 0 # type: int + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character not in {'\n', '\t', '\r'} and character.isprintable() is False: + self._unprintable_count += 1 + self._character_count += 1 + + def reset(self) -> None: + self._unprintable_count = 0 + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + + return (self._unprintable_count * 8) / self._character_count + + +class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): + + def __init__(self): + self._successive_count = 0 # type: int + self._character_count = 0 # type: int + + self._last_latin_character = None # type: Optional[str] + + def eligible(self, character: str) -> bool: + return is_latin(character) + + def feed(self, character: str) -> None: + if self._last_latin_character is not None: + if is_accentuated(character) and is_accentuated(self._last_latin_character): + if remove_accent(character) == remove_accent(self._last_latin_character): + self._successive_count += 1 + self._last_latin_character = character + + def reset(self) -> None: + self._successive_count = 0 + self._character_count = 0 + self._last_latin_character = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + + return (self._successive_count * 2) / self._character_count + + +class SuspiciousRange(MessDetectorPlugin): + + def __init__(self): + self._suspicious_successive_range_count = 0 # type: int + self._character_count = 0 # type: int + self._last_printable_seen = None # type: Optional[str] + + def eligible(self, character: str) -> bool: + return character.isprintable() + + def feed(self, character: str) -> None: + self._character_count += 1 + + if self._last_printable_seen is None: + self._last_printable_seen = character + return + + if character.isspace() or is_punctuation(character): + self._last_printable_seen = None + return + + unicode_range_a = unicode_range(self._last_printable_seen) # type: Optional[str] + unicode_range_b = unicode_range(character) # type: Optional[str] + + if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): + self._suspicious_successive_range_count += 1 + + self._last_printable_seen = character + + def reset(self) -> None: + self._character_count = 0 + self._suspicious_successive_range_count = 0 + self._last_printable_seen = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + + ratio_of_suspicious_range_usage = (self._suspicious_successive_range_count * 2) / self._character_count # type: float + + if ratio_of_suspicious_range_usage < 0.1: + return 0. + + return ratio_of_suspicious_range_usage + + +class SuperWeirdWordPlugin(MessDetectorPlugin): + + def __init__(self): + self._word_count = 0 # type: int + self._bad_word_count = 0 # type: int + self._is_current_word_bad = False # type: bool + + self._character_count = 0 # type: int + self._bad_character_count = 0 # type: int + + self._buffer = "" # type: str + self._buffer_accent_count = 0 # type: int + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character.isalpha(): + self._buffer = "".join([self._buffer, character]) + if is_accentuated(character): + self._buffer_accent_count += 1 + return + if not self._buffer: + return + if (character.isspace() or is_punctuation(character) or is_separator(character)) and self._buffer: + self._word_count += 1 + buffer_length = len(self._buffer) # type: int + + self._character_count += buffer_length + + if buffer_length >= 4 and self._buffer_accent_count / buffer_length >= 0.3: + self._is_current_word_bad = True + + if self._is_current_word_bad: + self._bad_word_count += 1 + self._bad_character_count += len(self._buffer) + self._is_current_word_bad = False + + self._buffer = "" + self._buffer_accent_count = 0 + elif character not in {"<", ">", "-", "="} and character.isdigit() is False and is_symbol(character): + self._is_current_word_bad = True + self._buffer += character + + def reset(self) -> None: + self._buffer = "" + self._is_current_word_bad = False + self._bad_word_count = 0 + self._word_count = 0 + self._character_count = 0 + self._bad_character_count = 0 + + @property + def ratio(self) -> float: + if self._word_count <= 16: + return 0. + + return self._bad_character_count / self._character_count + + +class CjkInvalidStopPlugin(MessDetectorPlugin): + """ + GB(Chinese) based encoding often render the stop incorrectly when the content does not fit and can be easily detected. + Searching for the overuse of '丅' and '丄'. + """ + + def __init__(self): + self._wrong_stop_count = 0 # type: int + self._cjk_character_count = 0 # type: int + + def eligible(self, character: str) -> bool: + return True + + def feed(self, character: str) -> None: + if character in ["丅", "丄"]: + self._wrong_stop_count += 1 + return + if is_cjk(character): + self._cjk_character_count += 1 + + def reset(self) -> None: + self._wrong_stop_count = 0 + self._cjk_character_count = 0 + + @property + def ratio(self) -> float: + if self._cjk_character_count < 16: + return 0. + return self._wrong_stop_count / self._cjk_character_count + + +class ArchaicUpperLowerPlugin(MessDetectorPlugin): + + def __init__(self): + self._buf = False # type: bool + + self._character_count_since_last_sep = 0 # type: int + + self._successive_upper_lower_count = 0 # type: int + self._successive_upper_lower_count_final = 0 # type: int + + self._character_count = 0 # type: int + + self._last_alpha_seen = None # type: Optional[str] + + def eligible(self, character: str) -> bool: + return character.isspace() or character.isalpha() + + def feed(self, character: str) -> None: + if is_separator(character): + if self._character_count_since_last_sep < 24: + self._successive_upper_lower_count_final += self._successive_upper_lower_count + self._successive_upper_lower_count = 0 + self._character_count_since_last_sep = 0 + + if self._last_alpha_seen is not None: + if (character.isupper() and self._last_alpha_seen.islower()) or (character.islower() and self._last_alpha_seen.isupper()): + if self._buf is True: + self._successive_upper_lower_count += 1 + else: + self._buf = True + else: + self._buf = False + + self._character_count += 1 + self._last_alpha_seen = character + + def reset(self) -> None: + self._character_count = 0 + self._character_count_since_last_sep = 0 + self._successive_upper_lower_count = 0 + self._successive_upper_lower_count_final = 0 + self._last_alpha_seen = None + + @property + def ratio(self) -> float: + if self._character_count == 0: + return 0. + + return (self._successive_upper_lower_count_final * 2) / self._character_count + + +def is_suspiciously_successive_range(unicode_range_a: Optional[str], unicode_range_b: Optional[str]) -> bool: + """ + Determine if two Unicode range seen next to each other can be considered as suspicious. + """ + if unicode_range_a is None or unicode_range_b is None: + return True + + if unicode_range_a == unicode_range_b: + return False + + if "Latin" in unicode_range_a and "Latin" in unicode_range_b: + return False + + if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: + return False + + keywords_range_a, keywords_range_b = unicode_range_a.split(" "), unicode_range_b.split(" ") + + for el in keywords_range_a: + if el in UNICODE_SECONDARY_RANGE_KEYWORD: + continue + if el in keywords_range_b: + return False + + # Japanese Exception + if unicode_range_a in ['Katakana', 'Hiragana'] and unicode_range_b in ['Katakana', 'Hiragana']: + return False + + if unicode_range_a in ['Katakana', 'Hiragana'] or unicode_range_b in ['Katakana', 'Hiragana']: + if "CJK" in unicode_range_a or "CJK" in unicode_range_b: + return False + + if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: + if "CJK" in unicode_range_a or "CJK" in unicode_range_b: + return False + if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": + return False + + # Chinese/Japanese use dedicated range for punctuation and/or separators. + if ('CJK' in unicode_range_a or 'CJK' in unicode_range_b) or (unicode_range_a in ['Katakana', 'Hiragana'] and unicode_range_b in ['Katakana', 'Hiragana']): + if 'Punctuation' in unicode_range_a or 'Punctuation' in unicode_range_b: + return False + if 'Forms' in unicode_range_a or 'Forms' in unicode_range_b: + return False + + return True + + +@lru_cache(maxsize=2048) +def mess_ratio(decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False) -> float: + """ + Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. + """ + detectors = [] # type: List[MessDetectorPlugin] + + for md_class in MessDetectorPlugin.__subclasses__(): + detectors.append( + md_class() + ) + + length = len(decoded_sequence) # type: int + + mean_mess_ratio = 0. # type: float + + if length < 512: + intermediary_mean_mess_ratio_calc = 32 # type: int + elif length <= 1024: + intermediary_mean_mess_ratio_calc = 64 + else: + intermediary_mean_mess_ratio_calc = 128 + + for character, index in zip(decoded_sequence, range(0, length)): + for detector in detectors: + if detector.eligible(character): + detector.feed(character) + + if (index > 0 and index % intermediary_mean_mess_ratio_calc == 0) or index == length-1: + mean_mess_ratio = sum( + [ + dt.ratio for dt in detectors + ] + ) + + if mean_mess_ratio >= maximum_threshold: + break + + if debug: + for dt in detectors: # pragma: nocover + print( + dt.__class__, + dt.ratio + ) + + return round( + mean_mess_ratio, + 3 + ) + diff --git a/pipenv/vendor/charset_normalizer/models.py b/pipenv/vendor/charset_normalizer/models.py new file mode 100644 index 00000000..2bf75a4e --- /dev/null +++ b/pipenv/vendor/charset_normalizer/models.py @@ -0,0 +1,355 @@ +import warnings +from encodings.aliases import aliases +from hashlib import sha256 +from json import dumps +from typing import Optional, List, Tuple, Set +from collections import Counter +from re import sub, compile as re_compile + +from charset_normalizer.constant import TOO_BIG_SEQUENCE +from charset_normalizer.md import mess_ratio +from charset_normalizer.utils import iana_name, is_multi_byte_encoding, unicode_range + + +class CharsetMatch: + def __init__( + self, + payload: bytes, + guessed_encoding: str, + mean_mess_ratio: float, + has_sig_or_bom: bool, + languages: "CoherenceMatches", + decoded_payload: Optional[str] = None + ): + self._payload = payload # type: bytes + + self._encoding = guessed_encoding # type: str + self._mean_mess_ratio = mean_mess_ratio # type: float + self._languages = languages # type: CoherenceMatches + self._has_sig_or_bom = has_sig_or_bom # type: bool + self._unicode_ranges = None # type: Optional[List[str]] + + self._leaves = [] # type: List[CharsetMatch] + self._mean_coherence_ratio = 0. # type: float + + self._output_payload = None # type: Optional[bytes] + self._output_encoding = None # type: Optional[str] + + self._string = decoded_payload # type: Optional[str] + + def __eq__(self, other) -> bool: + if not isinstance(other, CharsetMatch): + raise TypeError('__eq__ cannot be invoked on {} and {}.'.format(str(other.__class__), str(self.__class__))) + return self.encoding == other.encoding and self.fingerprint == other.fingerprint + + def __lt__(self, other) -> bool: + """ + Implemented to make sorted available upon CharsetMatches items. + """ + if not isinstance(other, CharsetMatch): + raise ValueError + + chaos_difference = abs(self.chaos - other.chaos) # type: float + + # Bellow 1% difference --> Use Coherence + if chaos_difference < 0.01: + return self.coherence > other.coherence + + return self.chaos < other.chaos + + @property + def chaos_secondary_pass(self) -> float: + """ + Check once again chaos in decoded text, except this time, with full content. + Use with caution, this can be very slow. + Notice: Will be removed in 3.0 + """ + warnings.warn("chaos_secondary_pass is deprecated and will be removed in 3.0", DeprecationWarning) + return mess_ratio( + str(self), + 1. + ) + + @property + def coherence_non_latin(self) -> float: + """ + Coherence ratio on the first non-latin language detected if ANY. + Notice: Will be removed in 3.0 + """ + warnings.warn("coherence_non_latin is deprecated and will be removed in 3.0", DeprecationWarning) + return 0. + + @property + def w_counter(self) -> Counter: + """ + Word counter instance on decoded text. + Notice: Will be removed in 3.0 + """ + warnings.warn("w_counter is deprecated and will be removed in 3.0", DeprecationWarning) + not_printable_pattern = re_compile(r'[0-9\W\n\r\t]+') + string_printable_only = sub(not_printable_pattern, ' ', str(self).lower()) + + return Counter(string_printable_only.split()) + + def __str__(self) -> str: + # Lazy Str Loading + if self._string is None: + self._string = str(self._payload, self._encoding, "strict") + return self._string + + def __repr__(self) -> str: + return "".format(self.encoding, self.fingerprint) + + def add_submatch(self, other: "CharsetMatch") -> None: + if not isinstance(other, CharsetMatch) or other == self: + raise ValueError("Unable to add instance <{}> as a submatch of a CharsetMatch".format(other.__class__)) + + other._string = None # Unload RAM usage; dirty trick. + self._leaves.append(other) + + @property + def encoding(self) -> str: + return self._encoding + + @property + def encoding_aliases(self) -> List[str]: + """ + Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. + """ + also_known_as = [] # type: List[str] + for u, p in aliases.items(): + if self.encoding == u: + also_known_as.append(p) + elif self.encoding == p: + also_known_as.append(u) + return also_known_as + + @property + def bom(self) -> bool: + return self._has_sig_or_bom + + @property + def byte_order_mark(self) -> bool: + return self._has_sig_or_bom + + @property + def languages(self) -> List[str]: + """ + Return the complete list of possible languages found in decoded sequence. + Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. + """ + return [e[0] for e in self._languages] + + @property + def language(self) -> str: + """ + Most probable language found in decoded sequence. If none were detected or inferred, the property will return + "Unknown". + """ + if not self._languages: + # Trying to infer the language based on the given encoding + # Its either English or we should not pronounce ourselves in certain cases. + if "ascii" in self.could_be_from_charset: + return "English" + + # doing it there to avoid circular import + from charset_normalizer.cd import mb_encoding_languages, encoding_languages + + languages = mb_encoding_languages(self.encoding) if is_multi_byte_encoding(self.encoding) else encoding_languages(self.encoding) + + if len(languages) == 0 or "Latin Based" in languages: + return "Unknown" + + return languages[0] + + return self._languages[0][0] + + @property + def chaos(self) -> float: + return self._mean_mess_ratio + + @property + def coherence(self) -> float: + if not self._languages: + return 0. + return self._languages[0][1] + + @property + def percent_chaos(self) -> float: + return round(self.chaos * 100, ndigits=3) + + @property + def percent_coherence(self) -> float: + return round(self.coherence * 100, ndigits=3) + + @property + def raw(self) -> bytes: + """ + Original untouched bytes. + """ + return self._payload + + @property + def submatch(self) -> List["CharsetMatch"]: + return self._leaves + + @property + def has_submatch(self) -> bool: + return len(self._leaves) > 0 + + @property + def alphabets(self) -> List[str]: + if self._unicode_ranges is not None: + return self._unicode_ranges + detected_ranges = set() # type: Set[str] + for character in str(self): + detected_ranges.add( + unicode_range(character) + ) + self._unicode_ranges = sorted(list(detected_ranges)) + return self._unicode_ranges + + @property + def could_be_from_charset(self) -> List[str]: + """ + The complete list of encoding that output the exact SAME str result and therefore could be the originating + encoding. + This list does include the encoding available in property 'encoding'. + """ + return [self._encoding] + [m.encoding for m in self._leaves] + + def first(self) -> "CharsetMatch": + """ + Kept for BC reasons. Will be removed in 3.0. + """ + return self + + def best(self) -> "CharsetMatch": + """ + Kept for BC reasons. Will be removed in 3.0. + """ + return self + + def output(self, encoding: str = "utf_8") -> bytes: + """ + Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. + Any errors will be simply ignored by the encoder NOT replaced. + """ + if self._output_encoding is None or self._output_encoding != encoding: + self._output_encoding = encoding + self._output_payload = str(self).encode(encoding, "replace") + + return self._output_payload # type: ignore + + @property + def fingerprint(self) -> str: + """ + Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. + """ + return sha256(self.output()).hexdigest() + + +class CharsetMatches: + """ + Container with every CharsetMatch items ordered by default from most probable to the less one. + Act like a list(iterable) but does not implements all related methods. + """ + def __init__(self, results: List[CharsetMatch] = None): + self._results = sorted(results) if results else [] # type: List[CharsetMatch] + + def __iter__(self): + for result in self._results: + yield result + + def __getitem__(self, item) -> CharsetMatch: + """ + Retrieve a single item either by its position or encoding name (alias may be used here). + Raise KeyError upon invalid index or encoding not present in results. + """ + if isinstance(item, int): + return self._results[item] + if isinstance(item, str): + item = iana_name(item, False) + for result in self._results: + if item in result.could_be_from_charset: + return result + raise KeyError + + def __len__(self) -> int: + return len(self._results) + + def append(self, item: CharsetMatch) -> None: + """ + Insert a single match. Will be inserted accordingly to preserve sort. + Can be inserted as a submatch. + """ + if not isinstance(item, CharsetMatch): + raise ValueError("Cannot append instance '{}' to CharsetMatches".format(str(item.__class__))) + # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) + if len(item.raw) <= TOO_BIG_SEQUENCE: + for match in self._results: + if match.fingerprint == item.fingerprint: + match.add_submatch(item) + return + self._results.append(item) + self._results = sorted(self._results) + + def best(self) -> Optional["CharsetMatch"]: + """ + Simply return the first match. Strict equivalent to matches[0]. + """ + if not self._results: + return None + return self._results[0] + + def first(self) -> Optional["CharsetMatch"]: + """ + Redundant method, call the method best(). Kept for BC reasons. + """ + return self.best() + + +CoherenceMatch = Tuple[str, float] +CoherenceMatches = List[CoherenceMatch] + + +class CliDetectionResult: + + def __init__(self, path: str, encoding: str, encoding_aliases: List[str], alternative_encodings: List[str], language: str, alphabets: List[str], has_sig_or_bom: bool, chaos: float, coherence: float, unicode_path: Optional[str], is_preferred: bool): + self.path = path # type: str + self.unicode_path = unicode_path # type: Optional[str] + self.encoding = encoding # type: str + self.encoding_aliases = encoding_aliases # type: List[str] + self.alternative_encodings = alternative_encodings # type: List[str] + self.language = language # type: str + self.alphabets = alphabets # type: List[str] + self.has_sig_or_bom = has_sig_or_bom # type: bool + self.chaos = chaos # type: float + self.coherence = coherence # type: float + self.is_preferred = is_preferred # type: bool + + @property + def __dict__(self): + return { + 'path': self.path, + 'encoding': self.encoding, + 'encoding_aliases': self.encoding_aliases, + 'alternative_encodings': self.alternative_encodings, + 'language': self.language, + 'alphabets': self.alphabets, + 'has_sig_or_bom': self.has_sig_or_bom, + 'chaos': self.chaos, + 'coherence': self.coherence, + 'unicode_path': self.unicode_path, + 'is_preferred': self.is_preferred + } + + def to_json(self) -> str: + return dumps( + self.__dict__, + ensure_ascii=True, + indent=4 + ) + + +CharsetNormalizerMatch = CharsetMatch diff --git a/pipenv/vendor/importlib_metadata/tests/data/__init__.py b/pipenv/vendor/charset_normalizer/py.typed similarity index 100% rename from pipenv/vendor/importlib_metadata/tests/data/__init__.py rename to pipenv/vendor/charset_normalizer/py.typed diff --git a/pipenv/vendor/charset_normalizer/utils.py b/pipenv/vendor/charset_normalizer/utils.py new file mode 100644 index 00000000..db59739f --- /dev/null +++ b/pipenv/vendor/charset_normalizer/utils.py @@ -0,0 +1,248 @@ +try: + import unicodedata2 as unicodedata +except ImportError: + import unicodedata + +from codecs import IncrementalDecoder +from re import findall +from typing import Optional, Tuple, Union, List, Set +import importlib +from _multibytecodec import MultibyteIncrementalDecoder # type: ignore + +from encodings.aliases import aliases +from functools import lru_cache + +from charset_normalizer.constant import UNICODE_RANGES_COMBINED, UNICODE_SECONDARY_RANGE_KEYWORD, \ + RE_POSSIBLE_ENCODING_INDICATION, ENCODING_MARKS, UTF8_MAXIMAL_ALLOCATION, IANA_SUPPORTED_SIMILAR + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_accentuated(character: str) -> bool: + try: + description = unicodedata.name(character) # type: str + except ValueError: + return False + return "WITH GRAVE" in description or "WITH ACUTE" in description or "WITH CEDILLA" in description + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def remove_accent(character: str) -> str: + decomposed = unicodedata.decomposition(character) # type: str + if not decomposed: + return character + + codes = decomposed.split(" ") # type: List[str] + + return chr( + int( + codes[0], + 16 + ) + ) + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def unicode_range(character: str) -> Optional[str]: + """ + Retrieve the Unicode range official name from a single character. + """ + character_ord = ord(character) # type: int + + for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): + if character_ord in ord_range: + return range_name + + return None + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_latin(character: str) -> bool: + try: + description = unicodedata.name(character) # type: str + except ValueError: + return False + return "LATIN" in description + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_punctuation(character: str) -> bool: + character_category = unicodedata.category(character) # type: str + + if "P" in character_category: + return True + + character_range = unicode_range(character) # type: Optional[str] + + if character_range is None: + return False + + return "Punctuation" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_symbol(character: str) -> bool: + character_category = unicodedata.category(character) # type: str + + if "S" in character_category or "N" in character_category: + return True + + character_range = unicode_range(character) # type: Optional[str] + + if character_range is None: + return False + + return "Forms" in character_range + + +@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) +def is_separator(character: str) -> bool: + if character.isspace() or character in ["|", "+"]: + return True + + character_category = unicodedata.category(character) # type: str + + return "Z" in character_category + + +def is_private_use_only(character: str) -> bool: + character_category = unicodedata.category(character) # type: str + + return "Co" == character_category + + +def is_cjk(character: str) -> bool: + try: + character_name = unicodedata.name(character) + except ValueError: + return False + + return "CJK" in character_name + + +@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) +def is_unicode_range_secondary(range_name: str) -> bool: + for keyword in UNICODE_SECONDARY_RANGE_KEYWORD: + if keyword in range_name: + return True + + return False + + +def any_specified_encoding(sequence: bytes, search_zone: int = 4096) -> Optional[str]: + """ + Extract using ASCII-only decoder any specified encoding in the first n-bytes. + """ + if not isinstance(sequence, bytes): + raise TypeError + + seq_len = len(sequence) # type: int + + results = findall( + RE_POSSIBLE_ENCODING_INDICATION, + sequence[:seq_len if seq_len <= search_zone else search_zone].decode('ascii', errors='ignore') + ) # type: List[str] + + if len(results) == 0: + return None + + for specified_encoding in results: + specified_encoding = specified_encoding.lower().replace('-', '_') + + for encoding_alias, encoding_iana in aliases.items(): + if encoding_alias == specified_encoding: + return encoding_iana + if encoding_iana == specified_encoding: + return encoding_iana + + return None + + +@lru_cache(maxsize=128) +def is_multi_byte_encoding(name: str) -> bool: + """ + Verify is a specific encoding is a multi byte one based on it IANA name + """ + return name in {"utf_8", "utf_8_sig", "utf_16", "utf_16_be", "utf_16_le", "utf_32", "utf_32_le", "utf_32_be", "utf_7"} or issubclass( + importlib.import_module('encodings.{}'.format(name)).IncrementalDecoder, # type: ignore + MultibyteIncrementalDecoder + ) + + +def identify_sig_or_bom(sequence: bytes) -> Tuple[Optional[str], bytes]: + """ + Identify and extract SIG/BOM in given sequence. + """ + + for iana_encoding in ENCODING_MARKS: + marks = ENCODING_MARKS[iana_encoding] # type: Union[bytes, List[bytes]] + + if isinstance(marks, bytes): + marks = [marks] + + for mark in marks: + if sequence.startswith(mark): + return iana_encoding, mark + + return None, b"" + + +def should_strip_sig_or_bom(iana_encoding: str) -> bool: + return iana_encoding not in {"utf_16", "utf_32"} + + +def iana_name(cp_name: str, strict: bool = True) -> str: + cp_name = cp_name.lower().replace('-', '_') + + for encoding_alias, encoding_iana in aliases.items(): + if cp_name == encoding_alias or cp_name == encoding_iana: + return encoding_iana + + if strict: + raise ValueError("Unable to retrieve IANA for '{}'".format(cp_name)) + + return cp_name + + +def range_scan(decoded_sequence: str) -> List[str]: + ranges = set() # type: Set[str] + + for character in decoded_sequence: + character_range = unicode_range(character) # type: Optional[str] + + if character_range is None: + continue + + ranges.add( + character_range + ) + + return list(ranges) + + +def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: + + if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): + return 0. + + decoder_a = importlib.import_module('encodings.{}'.format(iana_name_a)).IncrementalDecoder # type: ignore + decoder_b = importlib.import_module('encodings.{}'.format(iana_name_b)).IncrementalDecoder # type: ignore + + id_a = decoder_a(errors="ignore") # type: IncrementalDecoder + id_b = decoder_b(errors="ignore") # type: IncrementalDecoder + + character_match_count = 0 # type: int + + for i in range(0, 255): + to_be_decoded = bytes([i]) # type: bytes + if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): + character_match_count += 1 + + return character_match_count / 254 + + +def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: + """ + Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using + the function cp_similarity. + """ + return iana_name_a in IANA_SUPPORTED_SIMILAR and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] diff --git a/pipenv/vendor/charset_normalizer/version.py b/pipenv/vendor/charset_normalizer/version.py new file mode 100644 index 00000000..12f4b340 --- /dev/null +++ b/pipenv/vendor/charset_normalizer/version.py @@ -0,0 +1,6 @@ +""" +Expose version +""" + +__version__ = "2.0.3" +VERSION = __version__.split('.') diff --git a/pipenv/vendor/click/__init__.py b/pipenv/vendor/click/__init__.py index 2b6008f2..9e0afb23 100644 --- a/pipenv/vendor/click/__init__.py +++ b/pipenv/vendor/click/__init__.py @@ -4,76 +4,72 @@ writing command line scripts fun. Unlike other modules, it's based around a simple API that does not come with too much magic and is composable. """ -from .core import Argument -from .core import BaseCommand -from .core import Command -from .core import CommandCollection -from .core import Context -from .core import Group -from .core import MultiCommand -from .core import Option -from .core import Parameter -from .decorators import argument -from .decorators import command -from .decorators import confirmation_option -from .decorators import group -from .decorators import help_option -from .decorators import make_pass_decorator -from .decorators import option -from .decorators import pass_context -from .decorators import pass_obj -from .decorators import password_option -from .decorators import version_option -from .exceptions import Abort -from .exceptions import BadArgumentUsage -from .exceptions import BadOptionUsage -from .exceptions import BadParameter -from .exceptions import ClickException -from .exceptions import FileError -from .exceptions import MissingParameter -from .exceptions import NoSuchOption -from .exceptions import UsageError -from .formatting import HelpFormatter -from .formatting import wrap_text -from .globals import get_current_context -from .parser import OptionParser -from .termui import clear -from .termui import confirm -from .termui import echo_via_pager -from .termui import edit -from .termui import get_terminal_size -from .termui import getchar -from .termui import launch -from .termui import pause -from .termui import progressbar -from .termui import prompt -from .termui import secho -from .termui import style -from .termui import unstyle -from .types import BOOL -from .types import Choice -from .types import DateTime -from .types import File -from .types import FLOAT -from .types import FloatRange -from .types import INT -from .types import IntRange -from .types import ParamType -from .types import Path -from .types import STRING -from .types import Tuple -from .types import UNPROCESSED -from .types import UUID -from .utils import echo -from .utils import format_filename -from .utils import get_app_dir -from .utils import get_binary_stream -from .utils import get_os_args -from .utils import get_text_stream -from .utils import open_file +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import get_terminal_size as get_terminal_size +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_os_args as get_os_args +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file -# Controls if click should emit the warning about the use of unicode -# literals. -disable_unicode_literals_warning = False - -__version__ = "7.1.2" +__version__ = "8.0.1" diff --git a/pipenv/vendor/click/_bashcomplete.py b/pipenv/vendor/click/_bashcomplete.py deleted file mode 100644 index 8bca2448..00000000 --- a/pipenv/vendor/click/_bashcomplete.py +++ /dev/null @@ -1,375 +0,0 @@ -import copy -import os -import re - -from .core import Argument -from .core import MultiCommand -from .core import Option -from .parser import split_arg_string -from .types import Choice -from .utils import echo - -try: - from collections import abc -except ImportError: - import collections as abc - -WORDBREAK = "=" - -# Note, only BASH version 4.4 and later have the nosort option. -COMPLETION_SCRIPT_BASH = """ -%(complete_func)s() { - local IFS=$'\n' - COMPREPLY=( $( env COMP_WORDS="${COMP_WORDS[*]}" \\ - COMP_CWORD=$COMP_CWORD \\ - %(autocomplete_var)s=complete $1 ) ) - return 0 -} - -%(complete_func)setup() { - local COMPLETION_OPTIONS="" - local BASH_VERSION_ARR=(${BASH_VERSION//./ }) - # Only BASH version 4.4 and later have the nosort option. - if [ ${BASH_VERSION_ARR[0]} -gt 4 ] || ([ ${BASH_VERSION_ARR[0]} -eq 4 ] \ -&& [ ${BASH_VERSION_ARR[1]} -ge 4 ]); then - COMPLETION_OPTIONS="-o nosort" - fi - - complete $COMPLETION_OPTIONS -F %(complete_func)s %(script_names)s -} - -%(complete_func)setup -""" - -COMPLETION_SCRIPT_ZSH = """ -#compdef %(script_names)s - -%(complete_func)s() { - local -a completions - local -a completions_with_descriptions - local -a response - (( ! $+commands[%(script_names)s] )) && return 1 - - response=("${(@f)$( env COMP_WORDS=\"${words[*]}\" \\ - COMP_CWORD=$((CURRENT-1)) \\ - %(autocomplete_var)s=\"complete_zsh\" \\ - %(script_names)s )}") - - for key descr in ${(kv)response}; do - if [[ "$descr" == "_" ]]; then - completions+=("$key") - else - completions_with_descriptions+=("$key":"$descr") - fi - done - - if [ -n "$completions_with_descriptions" ]; then - _describe -V unsorted completions_with_descriptions -U - fi - - if [ -n "$completions" ]; then - compadd -U -V unsorted -a completions - fi - compstate[insert]="automenu" -} - -compdef %(complete_func)s %(script_names)s -""" - -COMPLETION_SCRIPT_FISH = ( - "complete --no-files --command %(script_names)s --arguments" - ' "(env %(autocomplete_var)s=complete_fish' - " COMP_WORDS=(commandline -cp) COMP_CWORD=(commandline -t)" - ' %(script_names)s)"' -) - -_completion_scripts = { - "bash": COMPLETION_SCRIPT_BASH, - "zsh": COMPLETION_SCRIPT_ZSH, - "fish": COMPLETION_SCRIPT_FISH, -} - -_invalid_ident_char_re = re.compile(r"[^a-zA-Z0-9_]") - - -def get_completion_script(prog_name, complete_var, shell): - cf_name = _invalid_ident_char_re.sub("", prog_name.replace("-", "_")) - script = _completion_scripts.get(shell, COMPLETION_SCRIPT_BASH) - return ( - script - % { - "complete_func": "_{}_completion".format(cf_name), - "script_names": prog_name, - "autocomplete_var": complete_var, - } - ).strip() + ";" - - -def resolve_ctx(cli, prog_name, args): - """Parse into a hierarchy of contexts. Contexts are connected - through the parent variable. - - :param cli: command definition - :param prog_name: the program that is running - :param args: full list of args - :return: the final context/command parsed - """ - ctx = cli.make_context(prog_name, args, resilient_parsing=True) - args = ctx.protected_args + ctx.args - while args: - if isinstance(ctx.command, MultiCommand): - if not ctx.command.chain: - cmd_name, cmd, args = ctx.command.resolve_command(ctx, args) - if cmd is None: - return ctx - ctx = cmd.make_context( - cmd_name, args, parent=ctx, resilient_parsing=True - ) - args = ctx.protected_args + ctx.args - else: - # Walk chained subcommand contexts saving the last one. - while args: - cmd_name, cmd, args = ctx.command.resolve_command(ctx, args) - if cmd is None: - return ctx - sub_ctx = cmd.make_context( - cmd_name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - resilient_parsing=True, - ) - args = sub_ctx.args - ctx = sub_ctx - args = sub_ctx.protected_args + sub_ctx.args - else: - break - return ctx - - -def start_of_option(param_str): - """ - :param param_str: param_str to check - :return: whether or not this is the start of an option declaration - (i.e. starts "-" or "--") - """ - return param_str and param_str[:1] == "-" - - -def is_incomplete_option(all_args, cmd_param): - """ - :param all_args: the full original list of args supplied - :param cmd_param: the current command paramter - :return: whether or not the last option declaration (i.e. starts - "-" or "--") is incomplete and corresponds to this cmd_param. In - other words whether this cmd_param option can still accept - values - """ - if not isinstance(cmd_param, Option): - return False - if cmd_param.is_flag: - return False - last_option = None - for index, arg_str in enumerate( - reversed([arg for arg in all_args if arg != WORDBREAK]) - ): - if index + 1 > cmd_param.nargs: - break - if start_of_option(arg_str): - last_option = arg_str - - return True if last_option and last_option in cmd_param.opts else False - - -def is_incomplete_argument(current_params, cmd_param): - """ - :param current_params: the current params and values for this - argument as already entered - :param cmd_param: the current command parameter - :return: whether or not the last argument is incomplete and - corresponds to this cmd_param. In other words whether or not the - this cmd_param argument can still accept values - """ - if not isinstance(cmd_param, Argument): - return False - current_param_values = current_params[cmd_param.name] - if current_param_values is None: - return True - if cmd_param.nargs == -1: - return True - if ( - isinstance(current_param_values, abc.Iterable) - and cmd_param.nargs > 1 - and len(current_param_values) < cmd_param.nargs - ): - return True - return False - - -def get_user_autocompletions(ctx, args, incomplete, cmd_param): - """ - :param ctx: context associated with the parsed command - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :param cmd_param: command definition - :return: all the possible user-specified completions for the param - """ - results = [] - if isinstance(cmd_param.type, Choice): - # Choices don't support descriptions. - results = [ - (c, None) for c in cmd_param.type.choices if str(c).startswith(incomplete) - ] - elif cmd_param.autocompletion is not None: - dynamic_completions = cmd_param.autocompletion( - ctx=ctx, args=args, incomplete=incomplete - ) - results = [ - c if isinstance(c, tuple) else (c, None) for c in dynamic_completions - ] - return results - - -def get_visible_commands_starting_with(ctx, starts_with): - """ - :param ctx: context associated with the parsed command - :starts_with: string that visible commands must start with. - :return: all visible (not hidden) commands that start with starts_with. - """ - for c in ctx.command.list_commands(ctx): - if c.startswith(starts_with): - command = ctx.command.get_command(ctx, c) - if not command.hidden: - yield command - - -def add_subcommand_completions(ctx, incomplete, completions_out): - # Add subcommand completions. - if isinstance(ctx.command, MultiCommand): - completions_out.extend( - [ - (c.name, c.get_short_help_str()) - for c in get_visible_commands_starting_with(ctx, incomplete) - ] - ) - - # Walk up the context list and add any other completion - # possibilities from chained commands - while ctx.parent is not None: - ctx = ctx.parent - if isinstance(ctx.command, MultiCommand) and ctx.command.chain: - remaining_commands = [ - c - for c in get_visible_commands_starting_with(ctx, incomplete) - if c.name not in ctx.protected_args - ] - completions_out.extend( - [(c.name, c.get_short_help_str()) for c in remaining_commands] - ) - - -def get_choices(cli, prog_name, args, incomplete): - """ - :param cli: command definition - :param prog_name: the program that is running - :param args: full list of args - :param incomplete: the incomplete text to autocomplete - :return: all the possible completions for the incomplete - """ - all_args = copy.deepcopy(args) - - ctx = resolve_ctx(cli, prog_name, args) - if ctx is None: - return [] - - has_double_dash = "--" in all_args - - # In newer versions of bash long opts with '='s are partitioned, but - # it's easier to parse without the '=' - if start_of_option(incomplete) and WORDBREAK in incomplete: - partition_incomplete = incomplete.partition(WORDBREAK) - all_args.append(partition_incomplete[0]) - incomplete = partition_incomplete[2] - elif incomplete == WORDBREAK: - incomplete = "" - - completions = [] - if not has_double_dash and start_of_option(incomplete): - # completions for partial options - for param in ctx.command.params: - if isinstance(param, Option) and not param.hidden: - param_opts = [ - param_opt - for param_opt in param.opts + param.secondary_opts - if param_opt not in all_args or param.multiple - ] - completions.extend( - [(o, param.help) for o in param_opts if o.startswith(incomplete)] - ) - return completions - # completion for option values from user supplied values - for param in ctx.command.params: - if is_incomplete_option(all_args, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - # completion for argument values from user supplied values - for param in ctx.command.params: - if is_incomplete_argument(ctx.params, param): - return get_user_autocompletions(ctx, all_args, incomplete, param) - - add_subcommand_completions(ctx, incomplete, completions) - # Sort before returning so that proper ordering can be enforced in custom types. - return sorted(completions) - - -def do_complete(cli, prog_name, include_descriptions): - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - for item in get_choices(cli, prog_name, args, incomplete): - echo(item[0]) - if include_descriptions: - # ZSH has trouble dealing with empty array parameters when - # returned from commands, use '_' to indicate no description - # is present. - echo(item[1] if item[1] else "_") - - return True - - -def do_complete_fish(cli, prog_name): - cwords = split_arg_string(os.environ["COMP_WORDS"]) - incomplete = os.environ["COMP_CWORD"] - args = cwords[1:] - - for item in get_choices(cli, prog_name, args, incomplete): - if item[1]: - echo("{arg}\t{desc}".format(arg=item[0], desc=item[1])) - else: - echo(item[0]) - - return True - - -def bashcomplete(cli, prog_name, complete_var, complete_instr): - if "_" in complete_instr: - command, shell = complete_instr.split("_", 1) - else: - command = complete_instr - shell = "bash" - - if command == "source": - echo(get_completion_script(prog_name, complete_var, shell)) - return True - elif command == "complete": - if shell == "fish": - return do_complete_fish(cli, prog_name) - elif shell in {"bash", "zsh"}: - return do_complete(cli, prog_name, shell == "zsh") - - return False diff --git a/pipenv/vendor/click/_compat.py b/pipenv/vendor/click/_compat.py index 60cb115b..b9e1f0d3 100644 --- a/pipenv/vendor/click/_compat.py +++ b/pipenv/vendor/click/_compat.py @@ -1,12 +1,11 @@ -# flake8: noqa import codecs import io import os import re import sys +import typing as t from weakref import WeakKeyDictionary -PY2 = sys.version_info[0] == 2 CYGWIN = sys.platform.startswith("cygwin") MSYS2 = sys.platform.startswith("win") and ("GCC" in sys.version) # Determine local App Engine environment, per Google's own suggestion @@ -14,19 +13,21 @@ APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ. "SERVER_SOFTWARE", "" ) WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2 -DEFAULT_COLUMNS = 80 - - +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None _ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") -def get_filesystem_encoding(): +def get_filesystem_encoding() -> str: return sys.getfilesystemencoding() or sys.getdefaultencoding() def _make_text_stream( - stream, encoding, errors, force_readable=False, force_writable=False -): + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: if encoding is None: encoding = get_best_encoding(stream) if errors is None: @@ -41,7 +42,7 @@ def _make_text_stream( ) -def is_ascii_encoding(encoding): +def is_ascii_encoding(encoding: str) -> bool: """Checks if a given encoding is ascii.""" try: return codecs.lookup(encoding).name == "ascii" @@ -49,7 +50,7 @@ def is_ascii_encoding(encoding): return False -def get_best_encoding(stream): +def get_best_encoding(stream: t.IO) -> str: """Returns the default stream encoding if not found.""" rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() if is_ascii_encoding(rv): @@ -60,46 +61,30 @@ def get_best_encoding(stream): class _NonClosingTextIOWrapper(io.TextIOWrapper): def __init__( self, - stream, - encoding, - errors, - force_readable=False, - force_writable=False, - **extra - ): - self._stream = stream = _FixupStream(stream, force_readable, force_writable) - io.TextIOWrapper.__init__(self, stream, encoding, errors, **extra) + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) - # The io module is a place where the Python 3 text behavior - # was forced upon Python 2, so we need to unbreak - # it to look like Python 2. - if PY2: - - def write(self, x): - if isinstance(x, str) or is_bytes(x): - try: - self.flush() - except Exception: - pass - return self.buffer.write(str(x)) - return io.TextIOWrapper.write(self, x) - - def writelines(self, lines): - for line in lines: - self.write(line) - - def __del__(self): + def __del__(self) -> None: try: self.detach() except Exception: pass - def isatty(self): + def isatty(self) -> bool: # https://bitbucket.org/pypy/pypy/issue/1803 return self._stream.isatty() -class _FixupStream(object): +class _FixupStream: """The new io interface needs more from streams than streams traditionally implement. As such, this fix-up code is necessary in some circumstances. @@ -109,45 +94,47 @@ class _FixupStream(object): of jupyter notebook). """ - def __init__(self, stream, force_readable=False, force_writable=False): + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): self._stream = stream self._force_readable = force_readable self._force_writable = force_writable - def __getattr__(self, name): + def __getattr__(self, name: str) -> t.Any: return getattr(self._stream, name) - def read1(self, size): + def read1(self, size: int) -> bytes: f = getattr(self._stream, "read1", None) + if f is not None: - return f(size) - # We only dispatch to readline instead of read in Python 2 as we - # do not want cause problems with the different implementation - # of line buffering. - if PY2: - return self._stream.readline(size) + return t.cast(bytes, f(size)) + return self._stream.read(size) - def readable(self): + def readable(self) -> bool: if self._force_readable: return True x = getattr(self._stream, "readable", None) if x is not None: - return x() + return t.cast(bool, x()) try: self._stream.read(0) except Exception: return False return True - def writable(self): + def writable(self) -> bool: if self._force_writable: return True x = getattr(self._stream, "writable", None) if x is not None: - return x() + return t.cast(bool, x()) try: - self._stream.write("") + self._stream.write("") # type: ignore except Exception: try: self._stream.write(b"") @@ -155,10 +142,10 @@ class _FixupStream(object): return False return True - def seekable(self): + def seekable(self) -> bool: x = getattr(self._stream, "seekable", None) if x is not None: - return x() + return t.cast(bool, x()) try: self._stream.seek(self._stream.tell()) except Exception: @@ -166,351 +153,239 @@ class _FixupStream(object): return True -if PY2: - text_type = unicode - raw_input = raw_input - string_types = (str, unicode) - int_types = (int, long) - iteritems = lambda x: x.iteritems() - range_type = xrange - - def is_bytes(x): - return isinstance(x, (buffer, bytearray)) - - _identifier_re = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$") - - # For Windows, we need to force stdout/stdin/stderr to binary if it's - # fetched for that. This obviously is not the most correct way to do - # it as it changes global state. Unfortunately, there does not seem to - # be a clear better way to do it as just reopening the file in binary - # mode does not change anything. - # - # An option would be to do what Python 3 does and to open the file as - # binary only, patch it back to the system, and then use a wrapper - # stream that converts newlines. It's not quite clear what's the - # correct option here. - # - # This code also lives in _winconsole for the fallback to the console - # emulation stream. - # - # There are also Windows environments where the `msvcrt` module is not - # available (which is why we use try-catch instead of the WIN variable - # here), such as the Google App Engine development server on Windows. In - # those cases there is just nothing we can do. - def set_binary_mode(f): - return f - +def _is_binary_reader(stream: t.IO, default: bool = False) -> bool: try: - import msvcrt - except ImportError: - pass - else: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - msvcrt.setmode(fileno, os.O_BINARY) - return f +def _is_binary_writer(stream: t.IO, default: bool = False) -> bool: try: - import fcntl - except ImportError: - pass + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO, bool], bool], + find_binary: t.Callable[[t.IO], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream - def set_binary_mode(f): - try: - fileno = f.fileno() - except Exception: - pass - else: - flags = fcntl.fcntl(fileno, fcntl.F_GETFL) - fcntl.fcntl(fileno, fcntl.F_SETFL, flags & ~os.O_NONBLOCK) - return f + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) - def isidentifier(x): - return _identifier_re.search(x) is not None + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream - def get_binary_stdin(): - return set_binary_mode(sys.stdin) + binary_reader = possible_binary_reader - def get_binary_stdout(): - _wrap_std_stream("stdout") - return set_binary_mode(sys.stdout) + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" - def get_binary_stderr(): - _wrap_std_stream("stderr") - return set_binary_mode(sys.stderr) - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdin, encoding, errors, force_readable=True) - - def get_text_stdout(encoding=None, errors=None): - _wrap_std_stream("stdout") - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stdout, encoding, errors, force_writable=True) - - def get_text_stderr(encoding=None, errors=None): - _wrap_std_stream("stderr") - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _make_text_stream(sys.stderr, encoding, errors, force_writable=True) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), "replace") - return value - - -else: - import io - - text_type = str - raw_input = input - string_types = (str,) - int_types = (int,) - range_type = range - isidentifier = lambda x: x.isidentifier() - iteritems = lambda x: iter(x.items()) - - def is_bytes(x): - return isinstance(x, (bytes, memoryview, bytearray)) - - def _is_binary_reader(stream, default=False): - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - def _is_binary_writer(stream, default=False): - try: - stream.write(b"") - except Exception: - try: - stream.write("") - return False - except Exception: - pass - return default - return True - - def _find_binary_reader(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_reader(stream, False): - return stream - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_reader(buf, True): - return buf - - def _find_binary_writer(stream): - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detatching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_writer(stream, False): - return stream - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_writer(buf, True): - return buf - - def _stream_is_misconfigured(stream): - """A stream is misconfigured if its encoding is ASCII.""" - # If the stream does not have an encoding set, we assume it's set - # to ASCII. This appears to happen in certain unittest - # environments. It's not quite clear what the correct behavior is - # but this at least will force Click to recover somehow. - return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") - - def _is_compat_stream_attr(stream, attr, value): - """A stream attribute is compatible if it is equal to the - desired value or the desired value is unset and the attribute - has a value. - """ - stream_value = getattr(stream, attr, None) - return stream_value == value or (value is None and stream_value is not None) - - def _is_compatible_text_stream(stream, encoding, errors): - """Check if a stream's encoding and errors attributes are - compatible with the desired values. - """ - return _is_compat_stream_attr( - stream, "encoding", encoding - ) and _is_compat_stream_attr(stream, "errors", errors) - - def _force_correct_text_stream( - text_stream, + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, encoding, errors, - is_binary, - find_binary, - force_readable=False, - force_writable=False, - ): - if is_binary(text_stream, False): - binary_reader = text_stream - else: - # If the stream looks compatible, and won't default to a - # misconfigured ascii encoding, return it as-is. - if _is_compatible_text_stream(text_stream, encoding, errors) and not ( - encoding is None and _stream_is_misconfigured(text_stream) - ): - return text_stream - - # Otherwise, get the underlying binary reader. - binary_reader = find_binary(text_stream) - - # If that's not possible, silently use the original reader - # and get mojibake instead of exceptions. - if binary_reader is None: - return text_stream - - # Default errors to replace instead of strict in order to get - # something that works. - if errors is None: - errors = "replace" - - # Wrap the binary stream in a text stream with the correct - # encoding parameters. - return _make_text_stream( - binary_reader, - encoding, - errors, - force_readable=force_readable, - force_writable=force_writable, - ) - - def _force_correct_text_reader(text_reader, encoding, errors, force_readable=False): - return _force_correct_text_stream( - text_reader, - encoding, - errors, - _is_binary_reader, - _find_binary_reader, - force_readable=force_readable, - ) - - def _force_correct_text_writer(text_writer, encoding, errors, force_writable=False): - return _force_correct_text_stream( - text_writer, - encoding, - errors, - _is_binary_writer, - _find_binary_writer, - force_writable=force_writable, - ) - - def get_binary_stdin(): - reader = _find_binary_reader(sys.stdin) - if reader is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdin.") - return reader - - def get_binary_stdout(): - writer = _find_binary_writer(sys.stdout) - if writer is None: - raise RuntimeError( - "Was not able to determine binary stream for sys.stdout." - ) - return writer - - def get_binary_stderr(): - writer = _find_binary_writer(sys.stderr) - if writer is None: - raise RuntimeError( - "Was not able to determine binary stream for sys.stderr." - ) - return writer - - def get_text_stdin(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_reader( - sys.stdin, encoding, errors, force_readable=True - ) - - def get_text_stdout(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer( - sys.stdout, encoding, errors, force_writable=True - ) - - def get_text_stderr(encoding=None, errors=None): - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer( - sys.stderr, encoding, errors, force_writable=True - ) - - def filename_to_ui(value): - if isinstance(value, bytes): - value = value.decode(get_filesystem_encoding(), "replace") - else: - value = value.encode("utf-8", "surrogateescape").decode("utf-8", "replace") - return value + force_readable=force_readable, + force_writable=force_writable, + ) -def get_streerror(e, default=None): - if hasattr(e, "strerror"): - msg = e.strerror - else: - if default is not None: - msg = default - else: - msg = str(e) - if isinstance(msg, bytes): - msg = msg.decode("utf-8", "replace") - return msg +def _force_correct_text_reader( + text_reader: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) -def _wrap_io_open(file, mode, encoding, errors): - """On Python 2, :func:`io.open` returns a text file wrapper that - requires passing ``unicode`` to ``write``. Need to open the file in - binary mode then wrap it in a subclass that can write ``str`` and - ``unicode``. - - Also handles not passing ``encoding`` and ``errors`` in binary mode. - """ - binary = "b" in mode - - if binary: - kwargs = {} - else: - kwargs = {"encoding": encoding, "errors": errors} - - if not PY2 or binary: - return io.open(file, mode, **kwargs) - - f = io.open(file, "{}b".format(mode.replace("t", ""))) - return _make_text_stream(f, **kwargs) +def _force_correct_text_writer( + text_writer: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) -def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False): +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, os.PathLike, int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO, bool]: binary = "b" in mode # Standard streams first. These are simple because they don't need @@ -549,7 +424,7 @@ def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False import random try: - perm = os.stat(filename).st_mode + perm: t.Optional[int] = os.stat(filename).st_mode except OSError: perm = None @@ -561,7 +436,7 @@ def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False while True: tmp_filename = os.path.join( os.path.dirname(filename), - ".__atomic-write{:08x}".format(random.randrange(1 << 32)), + f".__atomic-write{random.randrange(1 << 32):08x}", ) try: fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) @@ -580,76 +455,55 @@ def open_stream(filename, mode="r", encoding=None, errors="strict", atomic=False os.chmod(tmp_filename, perm) # in case perm includes bits in umask f = _wrap_io_open(fd, mode, encoding, errors) - return _AtomicFile(f, tmp_filename, os.path.realpath(filename)), True + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO, af), True -# Used in a destructor call, needs extra protection from interpreter cleanup. -if hasattr(os, "replace"): - _replace = os.replace - _can_replace = True -else: - _replace = os.rename - _can_replace = not WIN - - -class _AtomicFile(object): - def __init__(self, f, tmp_filename, real_filename): +class _AtomicFile: + def __init__(self, f: t.IO, tmp_filename: str, real_filename: str) -> None: self._f = f self._tmp_filename = tmp_filename self._real_filename = real_filename self.closed = False @property - def name(self): + def name(self) -> str: return self._real_filename - def close(self, delete=False): + def close(self, delete: bool = False) -> None: if self.closed: return self._f.close() - if not _can_replace: - try: - os.remove(self._real_filename) - except OSError: - pass - _replace(self._tmp_filename, self._real_filename) + os.replace(self._tmp_filename, self._real_filename) self.closed = True - def __getattr__(self, name): + def __getattr__(self, name: str) -> t.Any: return getattr(self._f, name) - def __enter__(self): + def __enter__(self) -> "_AtomicFile": return self - def __exit__(self, exc_type, exc_value, tb): + def __exit__(self, exc_type, exc_value, tb): # type: ignore self.close(delete=exc_type is not None) - def __repr__(self): + def __repr__(self) -> str: return repr(self._f) -auto_wrap_for_ansi = None -colorama = None -get_winterm_size = None - - -def strip_ansi(value): +def strip_ansi(value: str) -> str: return _ansi_re.sub("", value) -def _is_jupyter_kernel_output(stream): - if WIN: - # TODO: Couldn't test on Windows, should't try to support until - # someone tests the details wrt colorama. - return - +def _is_jupyter_kernel_output(stream: t.IO) -> bool: while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): stream = stream._stream return stream.__class__.__module__.startswith("ipykernel.") -def should_strip_ansi(stream=None, color=None): +def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None +) -> bool: if color is None: if stream is None: stream = sys.stdin @@ -657,99 +511,85 @@ def should_strip_ansi(stream=None, color=None): return not color -# If we're on Windows, we provide transparent integration through -# colorama. This will make ANSI colors through the echo function -# work automatically. -if WIN: - # Windows has a smaller terminal - DEFAULT_COLUMNS = 79 +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream - from ._winconsole import _get_windows_console_stream, _wrap_std_stream - - def _get_argv_encoding(): + def _get_argv_encoding() -> str: import locale return locale.getpreferredencoding() - if PY2: + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - def raw_input(prompt=""): - sys.stderr.flush() - if prompt: - stdout = _default_text_stdout() - stdout.write(prompt) - stdin = _default_text_stdin() - return stdin.readline().rstrip("\r\n") + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached - try: import colorama - except ImportError: - pass - else: - _ansi_stream_wrappers = WeakKeyDictionary() - def auto_wrap_for_ansi(stream, color=None): - """This function wraps a stream so that calls through colorama - are issued to the win32 console API to recolor on demand. It - also ensures to reset the colors if a write call is interrupted - to not destroy the console afterwards. - """ + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): try: - cached = _ansi_stream_wrappers.get(stream) - except Exception: - cached = None - if cached is not None: - return cached - strip = should_strip_ansi(stream, color) - ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) - rv = ansi_wrapper.stream - _write = rv.write + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise - def _safe_write(s): - try: - return _write(s) - except: - ansi_wrapper.reset_all() - raise + rv.write = _safe_write - rv.write = _safe_write - try: - _ansi_stream_wrappers[stream] = rv - except Exception: - pass - return rv + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass - def get_winterm_size(): - win = colorama.win32.GetConsoleScreenBufferInfo( - colorama.win32.STDOUT - ).srWindow - return win.Right - win.Left, win.Bottom - win.Top + return rv else: - def _get_argv_encoding(): + def _get_argv_encoding() -> str: return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding() - _get_windows_console_stream = lambda *x: None - _wrap_std_stream = lambda *x: None + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None -def term_len(x): +def term_len(x: str) -> int: return len(strip_ansi(x)) -def isatty(stream): +def isatty(stream: t.IO) -> bool: try: return stream.isatty() except Exception: return False -def _make_cached_stream_func(src_func, wrapper_func): - cache = WeakKeyDictionary() +def _make_cached_stream_func( + src_func: t.Callable[[], t.TextIO], wrapper_func: t.Callable[[], t.TextIO] +) -> t.Callable[[], t.TextIO]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - def func(): + def func() -> t.TextIO: stream = src_func() try: rv = cache.get(stream) @@ -759,7 +599,6 @@ def _make_cached_stream_func(src_func, wrapper_func): return rv rv = wrapper_func() try: - stream = src_func() # In case wrapper_func() modified the stream cache[stream] = rv except Exception: pass @@ -773,13 +612,15 @@ _default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_std _default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) -binary_streams = { +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { "stdin": get_binary_stdin, "stdout": get_binary_stdout, "stderr": get_binary_stderr, } -text_streams = { +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { "stdin": get_text_stdin, "stdout": get_text_stdout, "stderr": get_text_stderr, diff --git a/pipenv/vendor/click/_termui_impl.py b/pipenv/vendor/click/_termui_impl.py index 88bec377..06cf2b77 100644 --- a/pipenv/vendor/click/_termui_impl.py +++ b/pipenv/vendor/click/_termui_impl.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ This module contains implementations for the termui module. To keep the import time of Click down, some infrequently used functionality is @@ -9,20 +8,22 @@ import math import os import sys import time +import typing as t +from gettext import gettext as _ from ._compat import _default_text_stdout from ._compat import CYGWIN from ._compat import get_best_encoding -from ._compat import int_types from ._compat import isatty from ._compat import open_stream -from ._compat import range_type from ._compat import strip_ansi from ._compat import term_len from ._compat import WIN from .exceptions import ClickException from .utils import echo +V = t.TypeVar("V") + if os.name == "nt": BEFORE_BAR = "\r" AFTER_BAR = "\n" @@ -31,42 +32,25 @@ else: AFTER_BAR = "\033[?25h\n" -def _length_hint(obj): - """Returns the length hint of an object.""" - try: - return len(obj) - except (AttributeError, TypeError): - try: - get_hint = type(obj).__length_hint__ - except AttributeError: - return None - try: - hint = get_hint(obj) - except TypeError: - return None - if hint is NotImplemented or not isinstance(hint, int_types) or hint < 0: - return None - return hint - - -class ProgressBar(object): +class ProgressBar(t.Generic[V]): def __init__( self, - iterable, - length=None, - fill_char="#", - empty_char=" ", - bar_template="%(bar)s", - info_sep=" ", - show_eta=True, - show_percent=None, - show_pos=False, - item_show_func=None, - label=None, - file=None, - color=None, - width=30, - ): + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: self.fill_char = fill_char self.empty_char = empty_char self.bar_template = bar_template @@ -80,45 +64,50 @@ class ProgressBar(object): file = _default_text_stdout() self.file = file self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 self.width = width self.autowidth = width == 0 if length is None: - length = _length_hint(iterable) + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None if iterable is None: if length is None: raise TypeError("iterable or length is required") - iterable = range_type(length) + iterable = t.cast(t.Iterable[V], range(length)) self.iter = iter(iterable) self.length = length - self.length_known = length is not None self.pos = 0 - self.avg = [] + self.avg: t.List[float] = [] self.start = self.last_eta = time.time() self.eta_known = False self.finished = False - self.max_width = None + self.max_width: t.Optional[int] = None self.entered = False - self.current_item = None + self.current_item: t.Optional[V] = None self.is_hidden = not isatty(self.file) - self._last_line = None - self.short_limit = 0.5 + self._last_line: t.Optional[str] = None - def __enter__(self): + def __enter__(self) -> "ProgressBar": self.entered = True self.render_progress() return self - def __exit__(self, exc_type, exc_value, tb): + def __exit__(self, exc_type, exc_value, tb): # type: ignore self.render_finish() - def __iter__(self): + def __iter__(self) -> t.Iterator[V]: if not self.entered: raise RuntimeError("You need to use progress bars in a with block.") self.render_progress() return self.generator() - def __next__(self): + def __next__(self) -> V: # Iteration is defined in terms of a generator function, # returned by iter(self); use that to define next(). This works # because `self.iter` is an iterable consumed by that generator, @@ -126,37 +115,31 @@ class ProgressBar(object): # twice works and does "what you want". return next(iter(self)) - # Python 2 compat - next = __next__ - - def is_fast(self): - return time.time() - self.start <= self.short_limit - - def render_finish(self): - if self.is_hidden or self.is_fast(): + def render_finish(self) -> None: + if self.is_hidden: return self.file.write(AFTER_BAR) self.file.flush() @property - def pct(self): + def pct(self) -> float: if self.finished: return 1.0 - return min(self.pos / (float(self.length) or 1), 1.0) + return min(self.pos / (float(self.length or 1) or 1), 1.0) @property - def time_per_iteration(self): + def time_per_iteration(self) -> float: if not self.avg: return 0.0 return sum(self.avg) / float(len(self.avg)) @property - def eta(self): - if self.length_known and not self.finished: + def eta(self) -> float: + if self.length is not None and not self.finished: return self.time_per_iteration * (self.length - self.pos) return 0.0 - def format_eta(self): + def format_eta(self) -> str: if self.eta_known: t = int(self.eta) seconds = t % 60 @@ -166,44 +149,44 @@ class ProgressBar(object): hours = t % 24 t //= 24 if t > 0: - return "{}d {:02}:{:02}:{:02}".format(t, hours, minutes, seconds) + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" else: - return "{:02}:{:02}:{:02}".format(hours, minutes, seconds) + return f"{hours:02}:{minutes:02}:{seconds:02}" return "" - def format_pos(self): + def format_pos(self) -> str: pos = str(self.pos) - if self.length_known: - pos += "/{}".format(self.length) + if self.length is not None: + pos += f"/{self.length}" return pos - def format_pct(self): - return "{: 4}%".format(int(self.pct * 100))[1:] + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] - def format_bar(self): - if self.length_known: + def format_bar(self) -> str: + if self.length is not None: bar_length = int(self.pct * self.width) bar = self.fill_char * bar_length bar += self.empty_char * (self.width - bar_length) elif self.finished: bar = self.fill_char * self.width else: - bar = list(self.empty_char * (self.width or 1)) + chars = list(self.empty_char * (self.width or 1)) if self.time_per_iteration != 0: - bar[ + chars[ int( (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) * self.width ) ] = self.fill_char - bar = "".join(bar) + bar = "".join(chars) return bar - def format_progress_line(self): + def format_progress_line(self) -> str: show_percent = self.show_percent info_bits = [] - if self.length_known and show_percent is None: + if self.length is not None and show_percent is None: show_percent = not self.show_pos if self.show_pos: @@ -226,10 +209,16 @@ class ProgressBar(object): } ).rstrip() - def render_progress(self): - from .termui import get_terminal_size + def render_progress(self) -> None: + import shutil if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + return buf = [] @@ -238,10 +227,10 @@ class ProgressBar(object): old_width = self.width self.width = 0 clutter_length = term_len(self.format_progress_line()) - new_width = max(0, get_terminal_size()[0] - clutter_length) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) if new_width < old_width: buf.append(BEFORE_BAR) - buf.append(" " * self.max_width) + buf.append(" " * self.max_width) # type: ignore self.max_width = new_width self.width = new_width @@ -260,14 +249,14 @@ class ProgressBar(object): line = "".join(buf) # Render the line only if it changed. - if line != self._last_line and not self.is_fast(): + if line != self._last_line: self._last_line = line echo(line, file=self.file, color=self.color, nl=False) self.file.flush() - def make_step(self, n_steps): + def make_step(self, n_steps: int) -> None: self.pos += n_steps - if self.length_known and self.pos >= self.length: + if self.length is not None and self.pos >= self.length: self.finished = True if (time.time() - self.last_eta) < 1.0: @@ -285,18 +274,40 @@ class ProgressBar(object): self.avg = self.avg[-6:] + [step] - self.eta_known = self.length_known + self.eta_known = self.length is not None - def update(self, n_steps): - self.make_step(n_steps) - self.render_progress() + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. - def finish(self): - self.eta_known = 0 + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False self.current_item = None self.finished = True - def generator(self): + def generator(self) -> t.Iterator[V]: """Return a generator which yields the items added to the bar during construction, and updates the progress bar *after* the yielded block returns. @@ -312,18 +323,25 @@ class ProgressBar(object): raise RuntimeError("You need to use progress bars in a with block.") if self.is_hidden: - for rv in self.iter: - yield rv + yield from self.iter else: for rv in self.iter: self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + yield rv self.update(1) + self.finish() self.render_progress() -def pager(generator, color=None): +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: """Decide what method to use for paging through text.""" stdout = _default_text_stdout() if not isatty(sys.stdin) or not isatty(stdout): @@ -345,14 +363,14 @@ def pager(generator, color=None): fd, filename = tempfile.mkstemp() os.close(fd) try: - if hasattr(os, "system") and os.system('more "{}"'.format(filename)) == 0: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: return _pipepager(generator, "more", color) return _nullpager(stdout, generator, color) finally: os.unlink(filename) -def _pipepager(generator, cmd, color): +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: """Page through text by feeding it to another program. Invoking a pager through this might support colors. """ @@ -364,7 +382,7 @@ def _pipepager(generator, cmd, color): # condition that cmd_detail = cmd.rsplit("/", 1)[-1].split() if color is None and cmd_detail[0] == "less": - less_flags = "{}{}".format(os.environ.get("LESS", ""), " ".join(cmd_detail[1:])) + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" if not less_flags: env["LESS"] = "-R" color = True @@ -372,17 +390,18 @@ def _pipepager(generator, cmd, color): color = True c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) - encoding = get_best_encoding(c.stdin) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) try: for text in generator: if not color: text = strip_ansi(text) - c.stdin.write(text.encode(encoding, "replace")) - except (IOError, KeyboardInterrupt): + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): pass else: - c.stdin.close() + stdin.close() # Less doesn't respect ^C, but catches it for its own UI purposes (aborting # search or other commands inside less). @@ -401,11 +420,13 @@ def _pipepager(generator, cmd, color): break -def _tempfilepager(generator, cmd, color): +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: """Page through text by invoking a program on a temporary file.""" import tempfile - filename = tempfile.mktemp() + _, filename = tempfile.mkstemp() # TODO: This never terminates if the passed generator never terminates. text = "".join(generator) if not color: @@ -414,12 +435,14 @@ def _tempfilepager(generator, cmd, color): with open_stream(filename, "wb")[0] as f: f.write(text.encode(encoding)) try: - os.system('{} "{}"'.format(cmd, filename)) + os.system(f'{cmd} "{filename}"') finally: os.unlink(filename) -def _nullpager(stream, generator, color): +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: """Simply print unformatted text. This is the ultimate fallback.""" for text in generator: if not color: @@ -427,14 +450,20 @@ def _nullpager(stream, generator, color): stream.write(text) -class Editor(object): - def __init__(self, editor=None, env=None, require_save=True, extension=".txt"): +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: self.editor = editor self.env = env self.require_save = require_save self.extension = extension - def get_editor(self): + def get_editor(self) -> str: if self.editor is not None: return self.editor for key in "VISUAL", "EDITOR": @@ -444,48 +473,62 @@ class Editor(object): if WIN: return "notepad" for editor in "sensible-editor", "vim", "nano": - if os.system("which {} >/dev/null 2>&1".format(editor)) == 0: + if os.system(f"which {editor} >/dev/null 2>&1") == 0: return editor return "vi" - def edit_file(self, filename): + def edit_file(self, filename: str) -> None: import subprocess editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + if self.env: environ = os.environ.copy() environ.update(self.env) - else: - environ = None + try: - c = subprocess.Popen( - '{} "{}"'.format(editor, filename), env=environ, shell=True, - ) + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) exit_code = c.wait() if exit_code != 0: - raise ClickException("{}: Editing failed!".format(editor)) + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) except OSError as e: - raise ClickException("{}: Editing failed: {}".format(editor, e)) + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) - def edit(self, text): + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: import tempfile - text = text or "" - if text and not text.endswith("\n"): - text += "\n" + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) - try: - if WIN: - encoding = "utf-8-sig" - text = text.replace("\n", "\r\n") - else: - encoding = "utf-8" - text = text.encode(encoding) + f: t.BinaryIO - f = os.fdopen(fd, "wb") - f.write(text) - f.close() + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. timestamp = os.path.getmtime(name) self.edit_file(name) @@ -493,26 +536,26 @@ class Editor(object): if self.require_save and os.path.getmtime(name) == timestamp: return None - f = open(name, "rb") - try: + with open(name, "rb") as f: rv = f.read() - finally: - f.close() - return rv.decode("utf-8-sig").replace("\r\n", "\n") + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore finally: os.unlink(name) -def open_url(url, wait=False, locate=False): +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: import subprocess - def _unquote_file(url): - try: - import urllib - except ImportError: - import urllib + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + if url.startswith("file://"): - url = urllib.unquote(url[7:]) + url = unquote(url[7:]) + return url if sys.platform == "darwin": @@ -529,19 +572,21 @@ def open_url(url, wait=False, locate=False): null.close() elif WIN: if locate: - url = _unquote_file(url) - args = 'explorer /select,"{}"'.format(_unquote_file(url.replace('"', ""))) + url = _unquote_file(url.replace('"', "")) + args = f'explorer /select,"{url}"' else: - args = 'start {} "" "{}"'.format( - "/WAIT" if wait else "", url.replace('"', "") - ) + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' return os.system(args) elif CYGWIN: if locate: - url = _unquote_file(url) - args = 'cygstart "{}"'.format(os.path.dirname(url).replace('"', "")) + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' else: - args = 'cygstart {} "{}"'.format("-w" if wait else "", url.replace('"', "")) + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' return os.system(args) try: @@ -562,23 +607,27 @@ def open_url(url, wait=False, locate=False): return 1 -def _translate_ch_to_exc(ch): - if ch == u"\x03": +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": raise KeyboardInterrupt() - if ch == u"\x04" and not WIN: # Unix-like, Ctrl+D + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D raise EOFError() - if ch == u"\x1a" and WIN: # Windows, Ctrl+Z + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z raise EOFError() + return None + if WIN: import msvcrt @contextlib.contextmanager - def raw_terminal(): - yield + def raw_terminal() -> t.Iterator[int]: + yield -1 - def getchar(echo): + def getchar(echo: bool) -> str: # The function `getch` will return a bytes object corresponding to # the pressed character. Since Windows 10 build 1803, it will also # return \x00 when called a second time after pressing a regular key. @@ -608,16 +657,20 @@ if WIN: # # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + if echo: - func = msvcrt.getwche + func = msvcrt.getwche # type: ignore else: - func = msvcrt.getwch + func = msvcrt.getwch # type: ignore rv = func() - if rv in (u"\x00", u"\xe0"): + + if rv in ("\x00", "\xe0"): # \x00 and \xe0 are control characters that indicate special key, # see above. rv += func() + _translate_ch_to_exc(rv) return rv @@ -627,31 +680,38 @@ else: import termios @contextlib.contextmanager - def raw_terminal(): + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + if not isatty(sys.stdin): f = open("/dev/tty") fd = f.fileno() else: fd = sys.stdin.fileno() f = None + try: old_settings = termios.tcgetattr(fd) + try: tty.setraw(fd) yield fd finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) sys.stdout.flush() + if f is not None: f.close() except termios.error: pass - def getchar(echo): + def getchar(echo: bool) -> str: with raw_terminal() as fd: - ch = os.read(fd, 32) - ch = ch.decode(get_best_encoding(sys.stdin), "replace") + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + if echo and isatty(sys.stdout): sys.stdout.write(ch) + _translate_ch_to_exc(ch) return ch diff --git a/pipenv/vendor/click/_textwrap.py b/pipenv/vendor/click/_textwrap.py index 6959087b..b47dcbd4 100644 --- a/pipenv/vendor/click/_textwrap.py +++ b/pipenv/vendor/click/_textwrap.py @@ -1,9 +1,16 @@ import textwrap +import typing as t from contextlib import contextmanager class TextWrapper(textwrap.TextWrapper): - def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: space_left = max(width - cur_len, 1) if self.break_long_words: @@ -16,22 +23,27 @@ class TextWrapper(textwrap.TextWrapper): cur_line.append(reversed_chunks.pop()) @contextmanager - def extra_indent(self, indent): + def extra_indent(self, indent: str) -> t.Iterator[None]: old_initial_indent = self.initial_indent old_subsequent_indent = self.subsequent_indent self.initial_indent += indent self.subsequent_indent += indent + try: yield finally: self.initial_indent = old_initial_indent self.subsequent_indent = old_subsequent_indent - def indent_only(self, text): + def indent_only(self, text: str) -> str: rv = [] + for idx, line in enumerate(text.splitlines()): indent = self.initial_indent + if idx > 0: indent = self.subsequent_indent - rv.append(indent + line) + + rv.append(f"{indent}{line}") + return "\n".join(rv) diff --git a/pipenv/vendor/click/_unicodefun.py b/pipenv/vendor/click/_unicodefun.py index 781c3652..9cb30c38 100644 --- a/pipenv/vendor/click/_unicodefun.py +++ b/pipenv/vendor/click/_unicodefun.py @@ -1,131 +1,100 @@ import codecs import os -import sys - -from ._compat import PY2 +from gettext import gettext as _ -def _find_unicode_literals_frame(): - import __future__ - - if not hasattr(sys, "_getframe"): # not all Python implementations have it - return 0 - frm = sys._getframe(1) - idx = 1 - while frm is not None: - if frm.f_globals.get("__name__", "").startswith("click."): - frm = frm.f_back - idx += 1 - elif frm.f_code.co_flags & __future__.unicode_literals.compiler_flag: - return idx - else: - break - return 0 - - -def _check_for_unicode_literals(): - if not __debug__: - return - - from . import disable_unicode_literals_warning - - if not PY2 or disable_unicode_literals_warning: - return - bad_frame = _find_unicode_literals_frame() - if bad_frame <= 0: - return - from warnings import warn - - warn( - Warning( - "Click detected the use of the unicode_literals __future__" - " import. This is heavily discouraged because it can" - " introduce subtle bugs in your code. You should instead" - ' use explicit u"" literals for your unicode strings. For' - " more information see" - " https://click.palletsprojects.com/python3/" - ), - stacklevel=bad_frame, - ) - - -def _verify_python3_env(): - """Ensures that the environment is good for unicode on Python 3.""" - if PY2: - return +def _verify_python_env() -> None: + """Ensures that the environment is good for Unicode.""" try: - import locale + from locale import getpreferredencoding - fs_enc = codecs.lookup(locale.getpreferredencoding()).name + fs_enc = codecs.lookup(getpreferredencoding()).name except Exception: fs_enc = "ascii" + if fs_enc != "ascii": return - extra = "" + extra = [ + _( + "Click will abort further execution because Python was" + " configured to use ASCII as encoding for the environment." + " Consult https://click.palletsprojects.com/unicode-support/" + " for mitigation steps." + ) + ] + if os.name == "posix": import subprocess try: rv = subprocess.Popen( - ["locale", "-a"], stdout=subprocess.PIPE, stderr=subprocess.PIPE + ["locale", "-a"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="ascii", + errors="replace", ).communicate()[0] except OSError: - rv = b"" + rv = "" + good_locales = set() has_c_utf8 = False - # Make sure we're operating on text here. - if isinstance(rv, bytes): - rv = rv.decode("ascii", "replace") - for line in rv.splitlines(): locale = line.strip() + if locale.lower().endswith((".utf-8", ".utf8")): good_locales.add(locale) + if locale.lower() in ("c.utf8", "c.utf-8"): has_c_utf8 = True - extra += "\n\n" if not good_locales: - extra += ( - "Additional information: on this system no suitable" - " UTF-8 locales were discovered. This most likely" - " requires resolving by reconfiguring the locale" - " system." + extra.append( + _( + "Additional information: on this system no suitable" + " UTF-8 locales were discovered. This most likely" + " requires resolving by reconfiguring the locale" + " system." + ) ) elif has_c_utf8: - extra += ( - "This system supports the C.UTF-8 locale which is" - " recommended. You might be able to resolve your issue" - " by exporting the following environment variables:\n\n" - " export LC_ALL=C.UTF-8\n" - " export LANG=C.UTF-8" + extra.append( + _( + "This system supports the C.UTF-8 locale which is" + " recommended. You might be able to resolve your" + " issue by exporting the following environment" + " variables:" + ) ) + extra.append(" export LC_ALL=C.UTF-8\n export LANG=C.UTF-8") else: - extra += ( - "This system lists a couple of UTF-8 supporting locales" - " that you can pick from. The following suitable" - " locales were discovered: {}".format(", ".join(sorted(good_locales))) + extra.append( + _( + "This system lists some UTF-8 supporting locales" + " that you can pick from. The following suitable" + " locales were discovered: {locales}" + ).format(locales=", ".join(sorted(good_locales))) ) bad_locale = None - for locale in os.environ.get("LC_ALL"), os.environ.get("LANG"): - if locale and locale.lower().endswith((".utf-8", ".utf8")): - bad_locale = locale - if locale is not None: + + for env_locale in os.environ.get("LC_ALL"), os.environ.get("LANG"): + if env_locale and env_locale.lower().endswith((".utf-8", ".utf8")): + bad_locale = env_locale + + if env_locale is not None: break + if bad_locale is not None: - extra += ( - "\n\nClick discovered that you exported a UTF-8 locale" - " but the locale system could not pick up from it" - " because it does not exist. The exported locale is" - " '{}' but it is not supported".format(bad_locale) + extra.append( + _( + "Click discovered that you exported a UTF-8 locale" + " but the locale system could not pick up from it" + " because it does not exist. The exported locale is" + " {locale!r} but it is not supported." + ).format(locale=bad_locale) ) - raise RuntimeError( - "Click will abort further execution because Python 3 was" - " configured to use ASCII as encoding for the environment." - " Consult https://click.palletsprojects.com/python3/ for" - " mitigation steps.{}".format(extra) - ) + raise RuntimeError("\n\n".join(extra)) diff --git a/pipenv/vendor/click/_winconsole.py b/pipenv/vendor/click/_winconsole.py index b6c4274a..6b20df31 100644 --- a/pipenv/vendor/click/_winconsole.py +++ b/pipenv/vendor/click/_winconsole.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # This module is based on the excellent work by Adam Bartoš who # provided a lot of what went into the implementation here in # the discussion to issue1602 in the Python bug tracker. @@ -6,13 +5,11 @@ # There are some general differences in regards to how this works # compared to the original patches as we do not need to patch # the entire interpreter but just work in our little world of -# echo and prmopt. -import ctypes +# echo and prompt. import io -import os import sys import time -import zlib +import typing as t from ctypes import byref from ctypes import c_char from ctypes import c_char_p @@ -22,28 +19,18 @@ from ctypes import c_ulong from ctypes import c_void_p from ctypes import POINTER from ctypes import py_object -from ctypes import windll -from ctypes import WinError -from ctypes import WINFUNCTYPE +from ctypes import Structure from ctypes.wintypes import DWORD from ctypes.wintypes import HANDLE from ctypes.wintypes import LPCWSTR from ctypes.wintypes import LPWSTR -import msvcrt - from ._compat import _NonClosingTextIOWrapper -from ._compat import PY2 -from ._compat import text_type - -try: - from ctypes import pythonapi - - PyObject_GetBuffer = pythonapi.PyObject_GetBuffer - PyBuffer_Release = pythonapi.PyBuffer_Release -except ImportError: - pythonapi = None +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 c_ssize_p = POINTER(c_ssize_t) @@ -57,16 +44,12 @@ GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( ("CommandLineToArgvW", windll.shell32) ) -LocalFree = WINFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p)( - ("LocalFree", windll.kernel32) -) - +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) STDIN_HANDLE = GetStdHandle(-10) STDOUT_HANDLE = GetStdHandle(-11) STDERR_HANDLE = GetStdHandle(-12) - PyBUF_SIMPLE = 0 PyBUF_WRITABLE = 1 @@ -81,36 +64,37 @@ STDERR_FILENO = 2 EOF = b"\x1a" MAX_BYTES_WRITTEN = 32767 - -class Py_buffer(ctypes.Structure): - _fields_ = [ - ("buf", c_void_p), - ("obj", py_object), - ("len", c_ssize_t), - ("itemsize", c_ssize_t), - ("readonly", c_int), - ("ndim", c_int), - ("format", c_char_p), - ("shape", c_ssize_p), - ("strides", c_ssize_p), - ("suboffsets", c_ssize_p), - ("internal", c_void_p), - ] - - if PY2: - _fields_.insert(-1, ("smalltable", c_ssize_t * 2)) - - -# On PyPy we cannot get buffers so our ability to operate here is -# serverly limited. -if pythonapi is None: +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. get_buffer = None else: + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + def get_buffer(obj, writable=False): buf = Py_buffer() flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE PyObject_GetBuffer(py_object(obj), byref(buf), flags) + try: buffer_type = c_char * buf.len return buffer_type.from_address(buf.buf) @@ -123,7 +107,7 @@ class _WindowsConsoleRawIOBase(io.RawIOBase): self.handle = handle def isatty(self): - io.RawIOBase.isatty(self) + super().isatty() return True @@ -155,7 +139,7 @@ class _WindowsConsoleReader(_WindowsConsoleRawIOBase): # wait for KeyboardInterrupt time.sleep(0.1) if not rv: - raise OSError("Windows error: {}".format(GetLastError())) + raise OSError(f"Windows error: {GetLastError()}") if buffer[0] == EOF: return 0 @@ -172,7 +156,7 @@ class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): return "ERROR_SUCCESS" elif errno == ERROR_NOT_ENOUGH_MEMORY: return "ERROR_NOT_ENOUGH_MEMORY" - return "Windows error {}".format(errno) + return f"Windows error {errno}" def write(self, b): bytes_to_be_written = len(b) @@ -194,17 +178,17 @@ class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): return bytes_written -class ConsoleStream(object): - def __init__(self, text_stream, byte_stream): +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: self._text_stream = text_stream self.buffer = byte_stream @property - def name(self): + def name(self) -> str: return self.buffer.name - def write(self, x): - if isinstance(x, text_type): + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): return self._text_stream.write(x) try: self.flush() @@ -212,159 +196,84 @@ class ConsoleStream(object): pass return self.buffer.write(x) - def writelines(self, lines): + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: for line in lines: self.write(line) - def __getattr__(self, name): + def __getattr__(self, name: str) -> t.Any: return getattr(self._text_stream, name) - def isatty(self): + def isatty(self) -> bool: return self.buffer.isatty() def __repr__(self): - return "".format( - self.name, self.encoding - ) + return f"" -class WindowsChunkedWriter(object): - """ - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()' which we wrap to write in - limited chunks due to a Windows limitation on binary console streams. - """ - - def __init__(self, wrapped): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def write(self, text): - total_to_write = len(text) - written = 0 - - while written < total_to_write: - to_write = min(total_to_write - written, MAX_BYTES_WRITTEN) - self.__wrapped.write(text[written : written + to_write]) - written += to_write - - -_wrapped_std_streams = set() - - -def _wrap_std_stream(name): - # Python 2 & Windows 7 and below - if ( - PY2 - and sys.getwindowsversion()[:2] <= (6, 1) - and name not in _wrapped_std_streams - ): - setattr(sys, name, WindowsChunkedWriter(getattr(sys, name))) - _wrapped_std_streams.add(name) - - -def _get_text_stdin(buffer_stream): +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: text_stream = _NonClosingTextIOWrapper( io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), "utf-16-le", "strict", line_buffering=True, ) - return ConsoleStream(text_stream, buffer_stream) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) -def _get_text_stdout(buffer_stream): +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: text_stream = _NonClosingTextIOWrapper( io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), "utf-16-le", "strict", line_buffering=True, ) - return ConsoleStream(text_stream, buffer_stream) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) -def _get_text_stderr(buffer_stream): +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: text_stream = _NonClosingTextIOWrapper( io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), "utf-16-le", "strict", line_buffering=True, ) - return ConsoleStream(text_stream, buffer_stream) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) -if PY2: - - def _hash_py_argv(): - return zlib.crc32("\x00".join(sys.argv[1:])) - - _initial_argv_hash = _hash_py_argv() - - def _get_windows_argv(): - argc = c_int(0) - argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) - if not argv_unicode: - raise WinError() - try: - argv = [argv_unicode[i] for i in range(0, argc.value)] - finally: - LocalFree(argv_unicode) - del argv_unicode - - if not hasattr(sys, "frozen"): - argv = argv[1:] - while len(argv) > 0: - arg = argv[0] - if not arg.startswith("-") or arg == "-": - break - argv = argv[1:] - if arg.startswith(("-c", "-m")): - break - - return argv[1:] - - -_stream_factories = { +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { 0: _get_text_stdin, 1: _get_text_stdout, 2: _get_text_stderr, } -def _is_console(f): +def _is_console(f: t.TextIO) -> bool: if not hasattr(f, "fileno"): return False try: fileno = f.fileno() - except OSError: + except (OSError, io.UnsupportedOperation): return False handle = msvcrt.get_osfhandle(fileno) return bool(GetConsoleMode(handle, byref(DWORD()))) -def _get_windows_console_stream(f, encoding, errors): +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: if ( get_buffer is not None - and encoding in ("utf-16-le", None) - and errors in ("strict", None) + and encoding in {"utf-16-le", None} + and errors in {"strict", None} and _is_console(f) ): func = _stream_factories.get(f.fileno()) if func is not None: - if not PY2: - f = getattr(f, "buffer", None) - if f is None: - return None - else: - # If we are on Python 2 we need to set the stream that we - # deal with to binary mode as otherwise the exercise if a - # bit moot. The same problems apply as for - # get_binary_stdin and friends from _compat. - msvcrt.setmode(f.fileno(), os.O_BINARY) - return func(f) + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/pipenv/vendor/click/core.py b/pipenv/vendor/click/core.py index f58bf26d..e2ccf59a 100644 --- a/pipenv/vendor/click/core.py +++ b/pipenv/vendor/click/core.py @@ -1,17 +1,20 @@ +import enum import errno -import inspect import os import sys +import typing +import typing as t +from collections import abc from contextlib import contextmanager +from contextlib import ExitStack +from functools import partial from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext from itertools import repeat -from ._compat import isidentifier -from ._compat import iteritems -from ._compat import PY2 -from ._compat import string_types -from ._unicodefun import _check_for_unicode_literals -from ._unicodefun import _verify_python3_env +from . import types +from ._unicodefun import _verify_python_env from .exceptions import Abort from .exceptions import BadParameter from .exceptions import ClickException @@ -22,58 +25,60 @@ from .formatting import HelpFormatter from .formatting import join_options from .globals import pop_context from .globals import push_context +from .parser import _flag_needs_value from .parser import OptionParser from .parser import split_opt from .termui import confirm from .termui import prompt from .termui import style -from .types import BOOL -from .types import convert_type -from .types import IntRange +from .utils import _detect_program_name +from .utils import _expand_args from .utils import echo -from .utils import get_os_args from .utils import make_default_short_help from .utils import make_str from .utils import PacifyFlushWrapper -_missing = object() +if t.TYPE_CHECKING: + import typing_extensions as te + from .shell_completion import CompletionItem -SUBCOMMAND_METAVAR = "COMMAND [ARGS]..." -SUBCOMMANDS_METAVAR = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." - -DEPRECATED_HELP_NOTICE = " (DEPRECATED)" -DEPRECATED_INVOKE_NOTICE = "DeprecationWarning: The command %(name)s is deprecated." +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") -def _maybe_show_deprecated_notice(cmd): - if cmd.deprecated: - echo(style(DEPRECATED_INVOKE_NOTICE % {"name": cmd.name}, fg="red"), err=True) +def _fast_exit(code: int) -> "te.NoReturn": + """Low-level exit that skips Python's cleanup but speeds up exit by + about 10ms for things like shell completion. - -def fast_exit(code): - """Exit without garbage collection, this speeds up exit by about 10ms for - things like bash completion. + :param code: Exit code. """ sys.stdout.flush() sys.stderr.flush() os._exit(code) -def _bashcomplete(cmd, prog_name, complete_var=None): - """Internal handler for the bash completion support.""" - if complete_var is None: - complete_var = "_{}_COMPLETE".format(prog_name.replace("-", "_").upper()) - complete_instr = os.environ.get(complete_var) - if not complete_instr: - return +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. - from ._bashcomplete import bashcomplete + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) - if bashcomplete(cmd, prog_name, complete_var, complete_instr): - fast_exit(1) + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command -def _check_multicommand(base_command, cmd_name, cmd, register=False): +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: if not base_command.chain or not isinstance(cmd, MultiCommand): return if register: @@ -87,44 +92,22 @@ def _check_multicommand(base_command, cmd_name, cmd, register=False): " that is in chain mode. This is not supported." ) raise RuntimeError( - "{}. Command '{}' is set to chain and '{}' was added as" - " subcommand but it in itself is a multi command. ('{}' is a {}" - " within a chained {} named '{}').".format( - hint, - base_command.name, - cmd_name, - cmd_name, - cmd.__class__.__name__, - base_command.__class__.__name__, - base_command.name, - ) + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." ) -def batch(iterable, batch_size): +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: return list(zip(*repeat(iter(iterable), batch_size))) -def invoke_param_callback(callback, ctx, param, value): - code = getattr(callback, "__code__", None) - args = getattr(code, "co_argcount", 3) - - if args < 3: - from warnings import warn - - warn( - "Parameter callbacks take 3 args, (ctx, param, value). The" - " 2-arg style is deprecated and will be removed in 8.0.".format(callback), - DeprecationWarning, - stacklevel=3, - ) - return callback(ctx, value) - - return callback(ctx, param, value) - - @contextmanager -def augment_usage_errors(ctx, param=None): +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: """Context manager that attaches extra information to exceptions.""" try: yield @@ -140,23 +123,53 @@ def augment_usage_errors(ctx, param=None): raise -def iter_params_for_processing(invocation_order, declaration_order): +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: """Given a sequence of parameters in the order as should be considered for processing and an iterable of parameters that exist, this returns a list in the correct order as they should be processed. """ - def sort_key(item): + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: try: - idx = invocation_order.index(item) + idx: float = invocation_order.index(item) except ValueError: idx = float("inf") - return (not item.is_eager, idx) + + return not item.is_eager, idx return sorted(declaration_order, key=sort_key) -class Context(object): +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: """The context is a special internal object that holds state relevant for the script execution at every single level. It's normally invisible to commands unless they opt-in to getting access to it. @@ -168,21 +181,6 @@ class Context(object): A context can be used as context manager in which case it will call :meth:`close` on teardown. - .. versionadded:: 2.0 - Added the `resilient_parsing`, `help_option_names`, - `token_normalize_func` parameters. - - .. versionadded:: 3.0 - Added the `allow_extra_args` and `allow_interspersed_args` - parameters. - - .. versionadded:: 4.0 - Added the `color`, `ignore_unknown_options`, and - `max_content_width` parameters. - - .. versionadded:: 7.1 - Added the `show_default` parameter. - :param command: the command class for this context. :param parent: the parent context. :param info_name: the info name for this invocation. Generally this @@ -237,60 +235,88 @@ class Context(object): codes are used in texts that Click prints which is by default not the case. This for instance would affect help output. - :param show_default: if True, shows defaults for all options. - Even if an option is later created with show_default=False, - this command-level setting overrides it. + :param show_default: Show defaults for all options. If not set, + defaults to the value from a parent context. Overrides an + option's ``show_default`` argument. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. """ + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + def __init__( self, - command, - parent=None, - info_name=None, - obj=None, - auto_envvar_prefix=None, - default_map=None, - terminal_width=None, - max_content_width=None, - resilient_parsing=False, - allow_extra_args=None, - allow_interspersed_args=None, - ignore_unknown_options=None, - help_option_names=None, - token_normalize_func=None, - color=None, - show_default=None, - ): + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.Dict[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: #: the parent context or `None` if none exists. self.parent = parent #: the :class:`Command` for this context. self.command = command #: the descriptive information name self.info_name = info_name - #: the parsed parameters except if the value is hidden in which - #: case it's not remembered. - self.params = {} + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} #: the leftover arguments. - self.args = [] + self.args: t.List[str] = [] #: protected arguments. These are arguments that are prepended #: to `args` when certain parsing scenarios are encountered but #: must be never propagated to another arguments. This is used #: to implement nested parsing. - self.protected_args = [] + self.protected_args: t.List[str] = [] + if obj is None and parent is not None: obj = parent.obj + #: the user object stored. - self.obj = obj - self._meta = getattr(parent, "meta", {}) + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) #: A dictionary (-like object) with defaults for parameters. if ( default_map is None + and info_name is not None and parent is not None and parent.default_map is not None ): default_map = parent.default_map.get(info_name) - self.default_map = default_map + + self.default_map: t.Optional[t.Dict[str, t.Any]] = default_map #: This flag indicates if a subcommand is going to be executed. A #: group callback can use this information to figure out if it's @@ -301,22 +327,25 @@ class Context(object): #: If chaining is enabled this will be set to ``'*'`` in case #: any commands are executed. It is however not possible to #: figure out which ones. If you require this knowledge you - #: should use a :func:`resultcallback`. - self.invoked_subcommand = None + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None if terminal_width is None and parent is not None: terminal_width = parent.terminal_width + #: The width of the terminal (None is autodetection). - self.terminal_width = terminal_width + self.terminal_width: t.Optional[int] = terminal_width if max_content_width is None and parent is not None: max_content_width = parent.max_content_width + #: The maximum width of formatted content (None implies a sensible #: default which is 80 for most things). - self.max_content_width = max_content_width + self.max_content_width: t.Optional[int] = max_content_width if allow_extra_args is None: allow_extra_args = command.allow_extra_args + #: Indicates if the context allows extra args or if it should #: fail on parsing. #: @@ -325,14 +354,16 @@ class Context(object): if allow_interspersed_args is None: allow_interspersed_args = command.allow_interspersed_args + #: Indicates if the context allows mixing of arguments and #: options or not. #: #: .. versionadded:: 3.0 - self.allow_interspersed_args = allow_interspersed_args + self.allow_interspersed_args: bool = allow_interspersed_args if ignore_unknown_options is None: ignore_unknown_options = command.ignore_unknown_options + #: Instructs click to ignore options that a command does not #: understand and will store it on the context for later #: processing. This is primarily useful for situations where you @@ -341,7 +372,7 @@ class Context(object): #: forward all arguments. #: #: .. versionadded:: 4.0 - self.ignore_unknown_options = ignore_unknown_options + self.ignore_unknown_options: bool = ignore_unknown_options if help_option_names is None: if parent is not None: @@ -350,19 +381,21 @@ class Context(object): help_option_names = ["--help"] #: The names for the help options. - self.help_option_names = help_option_names + self.help_option_names: t.List[str] = help_option_names if token_normalize_func is None and parent is not None: token_normalize_func = parent.token_normalize_func #: An optional normalization function for tokens. This is #: options, choices, commands etc. - self.token_normalize_func = token_normalize_func + self.token_normalize_func: t.Optional[ + t.Callable[[str], str] + ] = token_normalize_func #: Indicates if resilient parsing is enabled. In that case Click #: will do its best to not cause any failures and default values #: will be ignored. Useful for completion. - self.resilient_parsing = resilient_parsing + self.resilient_parsing: bool = resilient_parsing # If there is no envvar prefix yet, but the parent has one and # the command on this level has a name, we can expand the envvar @@ -373,39 +406,68 @@ class Context(object): and parent.auto_envvar_prefix is not None and self.info_name is not None ): - auto_envvar_prefix = "{}_{}".format( - parent.auto_envvar_prefix, self.info_name.upper() + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" ) else: auto_envvar_prefix = auto_envvar_prefix.upper() + if auto_envvar_prefix is not None: auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") - self.auto_envvar_prefix = auto_envvar_prefix + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix if color is None and parent is not None: color = parent.color #: Controls if styling output is wanted or not. - self.color = color + self.color: t.Optional[bool] = color - self.show_default = show_default + if show_default is None and parent is not None: + show_default = parent.show_default - self._close_callbacks = [] + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() - def __enter__(self): + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": self._depth += 1 push_context(self) return self - def __exit__(self, exc_type, exc_value, tb): + def __exit__(self, exc_type, exc_value, tb): # type: ignore self._depth -= 1 if self._depth == 0: self.close() pop_context() @contextmanager - def scope(self, cleanup=True): + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: """This helper method can be used with the context object to promote it to the current thread local (see :func:`get_current_context`). The default behavior of this is to invoke the cleanup functions which @@ -443,7 +505,7 @@ class Context(object): self._depth -= 1 @property - def meta(self): + def meta(self) -> t.Dict[str, t.Any]: """This is a dictionary which is shared with all the contexts that are nested. It exists so that click utilities can store some state here if they need to. It is however the responsibility of @@ -470,32 +532,72 @@ class Context(object): """ return self._meta - def make_formatter(self): - """Creates the formatter for the help and usage output.""" - return HelpFormatter( + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( width=self.terminal_width, max_width=self.max_content_width ) - def call_on_close(self, f): - """This decorator remembers a function as callback that should be - executed when the context tears down. This is most useful to bind - resource handling to the script execution. For instance, file objects - opened by the :class:`File` type will register their close callbacks - here. + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. - :param f: the function to execute on teardown. + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 """ - self._close_callbacks.append(f) - return f + return self._exit_stack.enter_context(context_manager) - def close(self): - """Invokes all close callbacks.""" - for cb in self._close_callbacks: - cb() - self._close_callbacks = [] + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() @property - def command_path(self): + def command_path(self) -> str: """The computed command path. This is used for the ``usage`` information on the help page. It's automatically created by combining the info names of the chain of contexts to the root. @@ -504,25 +606,35 @@ class Context(object): if self.info_name is not None: rv = self.info_name if self.parent is not None: - rv = "{} {}".format(self.parent.command_path, rv) + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" return rv.lstrip() - def find_root(self): + def find_root(self) -> "Context": """Finds the outermost context.""" node = self while node.parent is not None: node = node.parent return node - def find_object(self, object_type): + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: """Finds the closest object of a given type.""" - node = self + node: t.Optional["Context"] = self + while node is not None: if isinstance(node.obj, object_type): return node.obj + node = node.parent - def ensure_object(self, object_type): + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: """Like :meth:`find_object` but sets the innermost object to a new instance of `object_type` if it does not exist. """ @@ -531,17 +643,39 @@ class Context(object): self.obj = rv = object_type() return rv - def lookup_default(self, name): - """Looks up the default for a parameter name. This by default - looks into the :attr:`default_map` if available. + @typing.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @typing.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. """ if self.default_map is not None: - rv = self.default_map.get(name) - if callable(rv): - rv = rv() - return rv + value = self.default_map.get(name) - def fail(self, message): + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": """Aborts the execution of the program with a specific error message. @@ -549,27 +683,40 @@ class Context(object): """ raise UsageError(message, self) - def abort(self): + def abort(self) -> "te.NoReturn": """Aborts the script.""" raise Abort() - def exit(self, code=0): + def exit(self, code: int = 0) -> "te.NoReturn": """Exits the application with a given exit code.""" raise Exit(code) - def get_usage(self): + def get_usage(self) -> str: """Helper method to get formatted usage string for the current context and command. """ return self.command.get_usage(self) - def get_help(self): + def get_help(self) -> str: """Helper method to get formatted help page for the current context and command. """ return self.command.get_help(self) - def invoke(*args, **kwargs): # noqa: B902 + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", t.Callable[..., t.Any]], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: """Invokes a command callback in exactly the way it expects. There are two ways to invoke this method: @@ -584,51 +731,87 @@ class Context(object): in against the intention of this code and no context was created. For more information about this change and why it was done in a bugfix release see :ref:`upgrade-to-3.2`. - """ - self, callback = args[:2] - ctx = self - # It's also possible to invoke another command which might or - # might not have a callback. In that case we also fill - # in defaults and make a new context for this command. - if isinstance(callback, Command): - other_cmd = callback - callback = other_cmd.callback - ctx = Context(other_cmd, info_name=other_cmd.name, parent=self) - if callback is None: + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: raise TypeError( "The given command does not have a callback that can be invoked." ) + else: + __callback = other_cmd.callback + + ctx = __self._make_sub_context(other_cmd) for param in other_cmd.params: if param.name not in kwargs and param.expose_value: - kwargs[param.name] = param.get_default(ctx) + kwargs[param.name] = param.get_default(ctx) # type: ignore - args = args[2:] - with augment_usage_errors(self): + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): with ctx: - return callback(*args, **kwargs) + return __callback(*args, **kwargs) - def forward(*args, **kwargs): # noqa: B902 + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> t.Any: """Similar to :meth:`invoke` but fills in default keyword arguments from the current context if the other command expects it. This cannot invoke callbacks directly, only other commands. - """ - self, cmd = args[:2] - # It's also possible to invoke another command which might or - # might not have a callback. - if not isinstance(cmd, Command): + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): raise TypeError("Callback is not a command.") - for param in self.params: + for param in __self.params: if param not in kwargs: - kwargs[param] = self.params[param] + kwargs[param] = __self.params[param] - return self.invoke(cmd, **kwargs) + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) -class BaseCommand(object): +class BaseCommand: """The base command implements the minimal API contract of commands. Most code will never use this as it does not implement a lot of useful functionality but it can act as the direct subclass of alternative @@ -650,6 +833,10 @@ class BaseCommand(object): passed to the context object. """ + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context #: the default for the :attr:`Context.allow_extra_args` flag. allow_extra_args = False #: the default for the :attr:`Context.allow_interspersed_args` flag. @@ -657,70 +844,158 @@ class BaseCommand(object): #: the default for the :attr:`Context.ignore_unknown_options` flag. ignore_unknown_options = False - def __init__(self, name, context_settings=None): + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + ) -> None: #: the name the command thinks it has. Upon registering a command #: on a :class:`Group` the group will default the command name #: with this information. You should instead use the #: :class:`Context`\'s :attr:`~Context.info_name` attribute. self.name = name + if context_settings is None: context_settings = {} + #: an optional dictionary with defaults passed to the context. - self.context_settings = context_settings + self.context_settings: t.Dict[str, t.Any] = context_settings - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, self.name) + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. - def get_usage(self, ctx): + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: raise NotImplementedError("Base commands cannot get usage") - def get_help(self, ctx): + def get_help(self, ctx: Context) -> str: raise NotImplementedError("Base commands cannot get help") - def make_context(self, info_name, args, parent=None, **extra): + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: """This function when given an info name and arguments will kick off the parsing and create a new :class:`Context`. It does not invoke the actual command callback though. - :param info_name: the info name for this invokation. Generally this + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this is the most descriptive name for the script or command. For the toplevel script it's usually the name of the script, for commands below it it's - the name of the script. + the name of the command. :param args: the arguments to parse as list of strings. :param parent: the parent context if available. :param extra: extra keyword arguments forwarded to the context constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. """ - for key, value in iteritems(self.context_settings): + for key, value in self.context_settings.items(): if key not in extra: extra[key] = value - ctx = Context(self, info_name=info_name, parent=parent, **extra) + + ctx = self.context_class( + self, info_name=info_name, parent=parent, **extra # type: ignore + ) + with ctx.scope(cleanup=False): self.parse_args(ctx, args) return ctx - def parse_args(self, ctx, args): + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: """Given a context and a list of arguments this creates the parser and parses the arguments, then modifies the context as necessary. This is automatically invoked by :meth:`make_context`. """ raise NotImplementedError("Base commands do not know how to parse arguments.") - def invoke(self, ctx): + def invoke(self, ctx: Context) -> t.Any: """Given a context, this invokes the command. The default implementation is raising a not implemented error. """ raise NotImplementedError("Base commands are not invokable by default") + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @typing.overload def main( self, - args=None, - prog_name=None, - complete_var=None, - standalone_mode=True, - **extra - ): + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @typing.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: """This is the way to invoke a script with all the bells and whistles as a command line application. This will always terminate the application after a call. If this is not wanted, ``SystemExit`` @@ -729,9 +1004,6 @@ class BaseCommand(object): This method is also available by directly calling the instance of a :class:`Command`. - .. versionadded:: 3.0 - Added the `standalone_mode` flag to control the standalone mode. - :param args: the arguments that should be used for parsing. If not provided, ``sys.argv[1:]`` is used. :param prog_name: the program name that should be used. By default @@ -750,31 +1022,39 @@ class BaseCommand(object): propagated to the caller and the return value of this function is the return value of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. :param extra: extra keyword arguments are forwarded to the context constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. """ - # If we are in Python 3, we will verify that the environment is - # sane at this point or reject further execution to avoid a - # broken script. - if not PY2: - _verify_python3_env() - else: - _check_for_unicode_literals() + # Verify that the environment is configured correctly, or reject + # further execution to avoid a broken script. + _verify_python_env() if args is None: - args = get_os_args() + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) else: args = list(args) if prog_name is None: - prog_name = make_str( - os.path.basename(sys.argv[0] if sys.argv else __file__) - ) + prog_name = _detect_program_name() - # Hook for the Bash completion. This only activates if the Bash - # completion is actually enabled, otherwise this is quite a fast - # noop. - _bashcomplete(self, prog_name, complete_var) + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) try: try: @@ -798,10 +1078,10 @@ class BaseCommand(object): raise e.show() sys.exit(e.exit_code) - except IOError as e: + except OSError as e: if e.errno == errno.EPIPE: - sys.stdout = PacifyFlushWrapper(sys.stdout) - sys.stderr = PacifyFlushWrapper(sys.stderr) + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) sys.exit(1) else: raise @@ -821,10 +1101,38 @@ class BaseCommand(object): except Abort: if not standalone_mode: raise - echo("Aborted!", file=sys.stderr) + echo(_("Aborted!"), file=sys.stderr) sys.exit(1) - def __call__(self, *args, **kwargs): + def _main_shell_completion( + self, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + """ + if complete_var is None: + complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + _fast_exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: """Alias for :meth:`main`.""" return self.main(*args, **kwargs) @@ -836,6 +1144,8 @@ class Command(BaseCommand): .. versionchanged:: 2.0 Added the `context_settings` parameter. + .. versionchanged:: 8.0 + Added repr showing the command name .. versionchanged:: 7.1 Added the `no_args_is_help` parameter. @@ -864,31 +1174,33 @@ class Command(BaseCommand): def __init__( self, - name, - context_settings=None, - callback=None, - params=None, - help=None, - epilog=None, - short_help=None, - options_metavar="[OPTIONS]", - add_help_option=True, - no_args_is_help=False, - hidden=False, - deprecated=False, - ): - BaseCommand.__init__(self, name, context_settings) + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) #: the callback to execute when the command fires. This might be #: `None` in which case nothing happens. self.callback = callback #: the list of parameters for this command in the order they #: should show up in the help page and execute. Eager parameters #: will automatically be handled before non eager ones. - self.params = params or [] + self.params: t.List["Parameter"] = params or [] + # if a form feed (page break) is found in the help text, truncate help # text to the content preceding the first form feed if help and "\f" in help: help = help.split("\f", 1)[0] + self.help = help self.epilog = epilog self.options_metavar = options_metavar @@ -898,7 +1210,19 @@ class Command(BaseCommand): self.hidden = hidden self.deprecated = deprecated - def get_usage(self, ctx): + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: """Formats the usage line into a string and returns it. Calls :meth:`format_usage` internally. @@ -907,14 +1231,16 @@ class Command(BaseCommand): self.format_usage(ctx, formatter) return formatter.getvalue().rstrip("\n") - def get_params(self, ctx): + def get_params(self, ctx: Context) -> t.List["Parameter"]: rv = self.params help_option = self.get_help_option(ctx) + if help_option is not None: - rv = rv + [help_option] + rv = [*rv, help_option] + return rv - def format_usage(self, ctx, formatter): + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: """Writes the usage line into the formatter. This is a low-level method called by :meth:`get_usage`. @@ -922,30 +1248,33 @@ class Command(BaseCommand): pieces = self.collect_usage_pieces(ctx) formatter.write_usage(ctx.command_path, " ".join(pieces)) - def collect_usage_pieces(self, ctx): + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: """Returns all the pieces that go into the usage line and returns it as a list of strings. """ - rv = [self.options_metavar] + rv = [self.options_metavar] if self.options_metavar else [] + for param in self.get_params(ctx): rv.extend(param.get_usage_pieces(ctx)) + return rv - def get_help_option_names(self, ctx): + def get_help_option_names(self, ctx: Context) -> t.List[str]: """Returns the names for the help option.""" all_names = set(ctx.help_option_names) for param in self.params: all_names.difference_update(param.opts) all_names.difference_update(param.secondary_opts) - return all_names + return list(all_names) - def get_help_option(self, ctx): + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: """Returns the help option object.""" help_options = self.get_help_option_names(ctx) - if not help_options or not self.add_help_option: - return - def show_help(ctx, param, value): + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: if value and not ctx.resilient_parsing: echo(ctx.get_help(), color=ctx.color) ctx.exit() @@ -956,17 +1285,17 @@ class Command(BaseCommand): is_eager=True, expose_value=False, callback=show_help, - help="Show this message and exit.", + help=_("Show this message and exit."), ) - def make_parser(self, ctx): + def make_parser(self, ctx: Context) -> OptionParser: """Creates the underlying option parser for this command.""" parser = OptionParser(ctx) for param in self.get_params(ctx): param.add_to_parser(parser, ctx) return parser - def get_help(self, ctx): + def get_help(self, ctx: Context) -> str: """Formats the help into a string and returns it. Calls :meth:`format_help` internally. @@ -975,18 +1304,21 @@ class Command(BaseCommand): self.format_help(ctx, formatter) return formatter.getvalue().rstrip("\n") - def get_short_help_str(self, limit=45): + def get_short_help_str(self, limit: int = 45) -> str: """Gets short help for the command or makes it by shortening the long help string. """ - return ( - self.short_help - or self.help - and make_default_short_help(self.help, limit) - or "" - ) + text = self.short_help or "" - def format_help(self, ctx, formatter): + if not text and self.help: + text = make_default_short_help(self.help, limit) + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: """Writes the help into the formatter if it exists. This is a low-level method called by :meth:`get_help`. @@ -1003,21 +1335,20 @@ class Command(BaseCommand): self.format_options(ctx, formatter) self.format_epilog(ctx, formatter) - def format_help_text(self, ctx, formatter): + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: """Writes the help text to the formatter if it exists.""" - if self.help: - formatter.write_paragraph() - with formatter.indentation(): - help_text = self.help - if self.deprecated: - help_text += DEPRECATED_HELP_NOTICE - formatter.write_text(help_text) - elif self.deprecated: - formatter.write_paragraph() - with formatter.indentation(): - formatter.write_text(DEPRECATED_HELP_NOTICE) + text = self.help or "" - def format_options(self, ctx, formatter): + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: """Writes all the options into the formatter if they exist.""" opts = [] for param in self.get_params(ctx): @@ -1026,17 +1357,17 @@ class Command(BaseCommand): opts.append(rv) if opts: - with formatter.section("Options"): + with formatter.section(_("Options")): formatter.write_dl(opts) - def format_epilog(self, ctx, formatter): + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: """Writes the epilog into the formatter if it exists.""" if self.epilog: formatter.write_paragraph() with formatter.indentation(): formatter.write_text(self.epilog) - def parse_args(self, ctx, args): + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: if not args and self.no_args_is_help and not ctx.resilient_parsing: echo(ctx.get_help(), color=ctx.color) ctx.exit() @@ -1049,22 +1380,64 @@ class Command(BaseCommand): if args and not ctx.allow_extra_args and not ctx.resilient_parsing: ctx.fail( - "Got unexpected extra argument{} ({})".format( - "s" if len(args) != 1 else "", " ".join(map(make_str, args)) - ) + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) ) ctx.args = args return args - def invoke(self, ctx): + def invoke(self, ctx: Context) -> t.Any: """Given a context, this invokes the attached callback (if it exists) in the right way. """ - _maybe_show_deprecated_notice(self) + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + if self.callback is not None: return ctx.invoke(self.callback, **ctx.params) + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + class MultiCommand(Command): """A multi command is the basic implementation of a command that @@ -1086,8 +1459,9 @@ class MultiCommand(Command): is enabled. This restricts the form of commands in that they cannot have optional arguments but it allows multiple commands to be chained together. - :param result_callback: the result callback to attach to this multi - command. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. """ allow_extra_args = True @@ -1095,29 +1469,33 @@ class MultiCommand(Command): def __init__( self, - name=None, - invoke_without_command=False, - no_args_is_help=None, - subcommand_metavar=None, - chain=False, - result_callback=None, - **attrs - ): - Command.__init__(self, name, **attrs) + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + if no_args_is_help is None: no_args_is_help = not invoke_without_command + self.no_args_is_help = no_args_is_help self.invoke_without_command = invoke_without_command + if subcommand_metavar is None: if chain: - subcommand_metavar = SUBCOMMANDS_METAVAR + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." else: - subcommand_metavar = SUBCOMMAND_METAVAR + subcommand_metavar = "COMMAND [ARGS]..." + self.subcommand_metavar = subcommand_metavar self.chain = chain - #: The result callback that is stored. This can be set or - #: overridden with the :func:`resultcallback` decorator. - self.result_callback = result_callback + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback if self.chain: for param in self.params: @@ -1127,17 +1505,35 @@ class MultiCommand(Command): " optional arguments." ) - def collect_usage_pieces(self, ctx): - rv = Command.collect_usage_pieces(self, ctx) + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) rv.append(self.subcommand_metavar) return rv - def format_options(self, ctx, formatter): - Command.format_options(self, ctx, formatter) + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) self.format_commands(ctx, formatter) - def resultcallback(self, replace=False): - """Adds a result callback to the chain command. By default if a + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a result callback is already registered this will chain them but this can be disabled with the `replace` parameter. The result callback is invoked with the return value of the subcommand @@ -1152,31 +1548,47 @@ class MultiCommand(Command): def cli(input): return 42 - @cli.resultcallback() + @cli.result_callback() def process_result(result, input): return result + input - .. versionadded:: 3.0 - :param replace: if set to `True` an already existing result callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 """ - def decorator(f): - old_callback = self.result_callback + def decorator(f: F) -> F: + old_callback = self._result_callback + if old_callback is None or replace: - self.result_callback = f + self._result_callback = f return f - def function(__value, *args, **kwargs): - return f(old_callback(__value, *args, **kwargs), *args, **kwargs) + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) # type: ignore + return f(inner, *args, **kwargs) - self.result_callback = rv = update_wrapper(function, f) + self._result_callback = rv = update_wrapper(t.cast(F, function), f) return rv return decorator - def format_commands(self, ctx, formatter): + def resultcallback(self, replace: bool = False) -> t.Callable[[F], F]: + import warnings + + warnings.warn( + "'resultcallback' has been renamed to 'result_callback'." + " The old name will be removed in Click 8.1.", + DeprecationWarning, + stacklevel=2, + ) + return self.result_callback(replace=replace) + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: """Extra format methods for multi methods that adds all the commands after the options. """ @@ -1201,15 +1613,16 @@ class MultiCommand(Command): rows.append((subcommand, help)) if rows: - with formatter.section("Commands"): + with formatter.section(_("Commands")): formatter.write_dl(rows) - def parse_args(self, ctx, args): + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: if not args and self.no_args_is_help and not ctx.resilient_parsing: echo(ctx.get_help(), color=ctx.color) ctx.exit() - rest = Command.parse_args(self, ctx, args) + rest = super().parse_args(ctx, args) + if self.chain: ctx.protected_args = rest ctx.args = [] @@ -1218,29 +1631,24 @@ class MultiCommand(Command): return ctx.args - def invoke(self, ctx): - def _process_result(value): - if self.result_callback is not None: - value = ctx.invoke(self.result_callback, value, **ctx.params) + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) return value if not ctx.protected_args: - # If we are invoked without command the chain flag controls - # how this happens. If we are not in chain mode, the return - # value here is the return value of the command. - # If however we are in chain mode, the return value is the - # return value of the result processor invoked with an empty - # list (which means that no subcommand actually was executed). if self.invoke_without_command: - if not self.chain: - return Command.invoke(self, ctx) + # No subcommand was invoked, so the result callback is + # invoked with None for regular groups, or an empty list + # for chained groups. with ctx: - Command.invoke(self, ctx) - return _process_result([]) - ctx.fail("Missing command.") + super().invoke(ctx) + return _process_result([] if self.chain else None) + ctx.fail(_("Missing command.")) # Fetch args back out - args = ctx.protected_args + ctx.args + args = [*ctx.protected_args, *ctx.args] ctx.args = [] ctx.protected_args = [] @@ -1252,8 +1660,9 @@ class MultiCommand(Command): # resources until the result processor has worked. with ctx: cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None ctx.invoked_subcommand = cmd_name - Command.invoke(self, ctx) + super().invoke(ctx) sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) with sub_ctx: return _process_result(sub_ctx.command.invoke(sub_ctx)) @@ -1265,7 +1674,7 @@ class MultiCommand(Command): # but nothing else. with ctx: ctx.invoked_subcommand = "*" if args else None - Command.invoke(self, ctx) + super().invoke(ctx) # Otherwise we make every single context and invoke them in a # chain. In that case the return value to the result processor @@ -1273,6 +1682,7 @@ class MultiCommand(Command): contexts = [] while args: cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None sub_ctx = cmd.make_context( cmd_name, args, @@ -1289,7 +1699,9 @@ class MultiCommand(Command): rv.append(sub_ctx.command.invoke(sub_ctx)) return _process_result(rv) - def resolve_command(self, ctx, args): + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: cmd_name = make_str(args[0]) original_cmd_name = cmd_name @@ -1311,36 +1723,94 @@ class MultiCommand(Command): if cmd is None and not ctx.resilient_parsing: if split_opt(cmd_name)[0]: self.parse_args(ctx, ctx.args) - ctx.fail("No such command '{}'.".format(original_cmd_name)) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] - return cmd_name, cmd, args[1:] - - def get_command(self, ctx, cmd_name): + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: """Given a context and a command name, this returns a :class:`Command` object if it exists or returns `None`. """ - raise NotImplementedError() + raise NotImplementedError - def list_commands(self, ctx): + def list_commands(self, ctx: Context) -> t.List[str]: """Returns a list of subcommand names in the order they should appear. """ return [] + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + class Group(MultiCommand): - """A group allows a command to have subcommands attached. This is the - most common way to implement nesting in Click. + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. - :param commands: a dictionary of commands. + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commmands`` argument can be a list of command objects. """ - def __init__(self, name=None, commands=None, **attrs): - MultiCommand.__init__(self, name, **attrs) - #: the registered subcommands by their exported names. - self.commands = commands or {} + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None - def add_command(self, cmd, name=None): + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[t.Union[t.Dict[str, Command], t.Sequence[Command]]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.Dict[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: """Registers another :class:`Command` with this group. If the name is not provided, the name of the command is used. """ @@ -1350,40 +1820,65 @@ class Group(MultiCommand): _check_multicommand(self, name, cmd, register=True) self.commands[name] = cmd - def command(self, *args, **kwargs): + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: """A shortcut decorator for declaring and attaching a command to - the group. This takes the same arguments as :func:`command` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. """ from .decorators import command - def decorator(f): + if self.command_class is not None and "cls" not in kwargs: + kwargs["cls"] = self.command_class + + def decorator(f: t.Callable[..., t.Any]) -> Command: cmd = command(*args, **kwargs)(f) self.add_command(cmd) return cmd return decorator - def group(self, *args, **kwargs): + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: """A shortcut decorator for declaring and attaching a group to - the group. This takes the same arguments as :func:`group` but - immediately registers the created command with this instance by - calling into :meth:`add_command`. + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. """ from .decorators import group - def decorator(f): + if self.group_class is not None and "cls" not in kwargs: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": cmd = group(*args, **kwargs)(f) self.add_command(cmd) return cmd return decorator - def get_command(self, ctx, cmd_name): + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: return self.commands.get(cmd_name) - def list_commands(self, ctx): + def list_commands(self, ctx: Context) -> t.List[str]: return sorted(self.commands) @@ -1394,31 +1889,52 @@ class CommandCollection(MultiCommand): provides all the commands for each of them. """ - def __init__(self, name=None, sources=None, **attrs): - MultiCommand.__init__(self, name, **attrs) + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) #: The list of registered multi commands. - self.sources = sources or [] + self.sources: t.List[MultiCommand] = sources or [] - def add_source(self, multi_cmd): + def add_source(self, multi_cmd: MultiCommand) -> None: """Adds a new multi command to the chain dispatcher.""" self.sources.append(multi_cmd) - def get_command(self, ctx, cmd_name): + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: for source in self.sources: rv = source.get_command(ctx, cmd_name) + if rv is not None: if self.chain: _check_multicommand(self, cmd_name, rv) + return rv - def list_commands(self, ctx): - rv = set() + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + for source in self.sources: rv.update(source.list_commands(ctx)) + return sorted(rv) -class Parameter(object): +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: r"""A parameter to a command comes in two versions: they are either :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently not supported by design as some of the internals for parsing are @@ -1436,13 +1952,15 @@ class Parameter(object): :param default: the default value if omitted. This can also be a callable, in which case it's invoked when the default is needed without any arguments. - :param callback: a callback that should be executed after the parameter - was matched. This is called as ``fn(ctx, param, - value)`` and needs to return the value. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. :param nargs: the number of arguments to match. If not ``1`` the return value is a tuple instead of single value. The default for nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. :param metavar: how the value is represented in the help page. :param expose_value: if this is `True` then the value is passed onwards to the command callback and stored on the context, @@ -1452,6 +1970,32 @@ class Parameter(object): order of processing. :param envvar: a string or list of strings that are environment variables that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. .. versionchanged:: 7.1 Empty environment variables are ignored rather than taking the @@ -1463,27 +2007,38 @@ class Parameter(object): parameter. The old callback format will still work, but it will raise a warning to give you a chance to migrate the code easier. """ + param_type_name = "parameter" def __init__( self, - param_decls=None, - type=None, - required=False, - default=None, - callback=None, - nargs=None, - metavar=None, - expose_value=True, - is_eager=False, - envvar=None, - autocompletion=None, - ): + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + autocompletion: t.Optional[ + t.Callable[ + [Context, t.List[str], str], t.List[t.Union[t.Tuple[str, str], str]] + ] + ] = None, + ) -> None: self.name, self.opts, self.secondary_opts = self._parse_decls( param_decls or (), expose_value ) - - self.type = convert_type(type, default) + self.type = types.convert_type(type, default) # Default nargs to what the type tells us if we have that # information available. @@ -1496,158 +2051,363 @@ class Parameter(object): self.required = required self.callback = callback self.nargs = nargs - self.multiple = False + self.multiple = multiple self.expose_value = expose_value self.default = default self.is_eager = is_eager self.metavar = metavar self.envvar = envvar - self.autocompletion = autocompletion - def __repr__(self): - return "<{} {}>".format(self.__class__.__name__, self.name) + if autocompletion is not None: + import warnings + + warnings.warn( + "'autocompletion' is renamed to 'shell_complete'. The old name is" + " deprecated and will be removed in Click 8.1. See the docs about" + " 'Parameter' for information about new behavior.", + DeprecationWarning, + stacklevel=2, + ) + + def shell_complete( + ctx: Context, param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + from click.shell_completion import CompletionItem + + out = [] + + for c in autocompletion(ctx, [], incomplete): # type: ignore + if isinstance(c, tuple): + c = CompletionItem(c[0], help=c[1]) + elif isinstance(c, str): + c = CompletionItem(c) + + if c.value.startswith(incomplete): + out.append(c) + + return out + + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() @property - def human_readable_name(self): + def human_readable_name(self) -> str: """Returns the human readable name of this parameter. This is the same as the name for options, but the metavar for arguments. """ - return self.name + return self.name # type: ignore - def make_metavar(self): + def make_metavar(self) -> str: if self.metavar is not None: return self.metavar + metavar = self.type.get_metavar(self) + if metavar is None: metavar = self.type.name.upper() + if self.nargs != 1: metavar += "..." + return metavar - def get_default(self, ctx): - """Given a context variable this calculates the default value.""" - # Otherwise go with the regular default. - if callable(self.default): - rv = self.default() - else: - rv = self.default - return self.type_cast_value(ctx, rv) + @typing.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... - def add_to_parser(self, parser, ctx): - pass + @typing.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_value` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if callable(value): + if not call: + # Don't type cast the callable. + return value + + value = value() + + try: + return self.type_cast_value(ctx, value) + except BadParameter: + if ctx.resilient_parsing: + return value + + raise + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE - def consume_value(self, ctx, opts): - value = opts.get(self.name) if value is None: value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + if value is None: - value = ctx.lookup_default(self.name) - return value + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP - def type_cast_value(self, ctx, value): - """Given a value this runs it properly through the type system. - This automatically handles things like `nargs` and `multiple` as - well as composite types. + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. """ - if self.type.is_composite: - if self.nargs <= 1: - raise TypeError( - "Attempted to invoke composite type but nargs has" - " been set to {}. This is not supported; nargs" - " needs to be set to a fixed value > 1.".format(self.nargs) - ) - if self.multiple: - return tuple(self.type(x or (), self, ctx) for x in value or ()) - return self.type(value or (), self, ctx) + if value is None: + return () if self.multiple or self.nargs == -1 else None - def _convert(value, level): - if level == 0: - return self.type(value, self, ctx) - return tuple(_convert(x, level - 1) for x in value or ()) + def check_iter(value: t.Any) -> t.Iterator: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None - return _convert(value, (self.nargs != 1) + bool(self.multiple)) + if self.nargs == 1 or self.type.is_composite: + convert: t.Callable[[t.Any], t.Any] = partial( + self.type, param=self, ctx=ctx + ) + elif self.nargs == -1: - def process_value(self, ctx, value): - """Given a value and context this runs the logic to convert the - value as necessary. - """ - # If the value we were given is None we do nothing. This way - # code that calls this can easily figure out if something was - # not provided. Otherwise it would be converted into an empty - # tuple for multiple invocations which is inconvenient. - if value is not None: - return self.type_cast_value(ctx, value) + def convert(value: t.Any) -> t.Tuple: + return tuple(self.type(x, self, ctx) for x in check_iter(value)) - def value_is_missing(self, value): + else: # nargs > 1 + + def convert(value: t.Any) -> t.Tuple: + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: if value is None: return True + if (self.nargs != 1 or self.multiple) and value == (): return True + return False - def full_process_value(self, ctx, value): - value = self.process_value(ctx, value) - - if value is None and not ctx.resilient_parsing: - value = self.get_default(ctx) + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + if value is not None: + value = self.type_cast_value(ctx, value) if self.required and self.value_is_missing(value): raise MissingParameter(ctx=ctx, param=self) + if self.callback is not None: + value = self.callback(ctx, self, value) + return value - def resolve_envvar_value(self, ctx): + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: if self.envvar is None: - return - if isinstance(self.envvar, (tuple, list)): - for envvar in self.envvar: - rv = os.environ.get(envvar) - if rv is not None: - return rv - else: + return None + + if isinstance(self.envvar, str): rv = os.environ.get(self.envvar) - if rv != "": + if rv: return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) if rv is not None and self.nargs != 1: rv = self.type.split_envvar_value(rv) + return rv - def handle_parse_result(self, ctx, opts, args): + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: with augment_usage_errors(ctx, param=self): - value = self.consume_value(ctx, opts) + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + try: - value = self.full_process_value(ctx, value) + value = self.process_value(ctx, value) except Exception: if not ctx.resilient_parsing: raise + value = None - if self.callback is not None: - try: - value = invoke_param_callback(self.callback, ctx, self, value) - except Exception: - if not ctx.resilient_parsing: - raise if self.expose_value: - ctx.params[self.name] = value + ctx.params[self.name] = value # type: ignore + return value, args - def get_help_record(self, ctx): + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: pass - def get_usage_pieces(self, ctx): + def get_usage_pieces(self, ctx: Context) -> t.List[str]: return [] - def get_error_hint(self, ctx): + def get_error_hint(self, ctx: Context) -> str: """Get a stringified version of the param for use in error messages to indicate which param caused the error. """ hint_list = self.opts or [self.human_readable_name] - return " / ".join(repr(x) for x in hint_list) + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) class Option(Parameter): @@ -1666,8 +2426,12 @@ class Option(Parameter): :param prompt: if set to `True` or a non empty string then the user will be prompted for input. If set to `True` the prompt will be the option name capitalized. - :param confirmation_prompt: if set then the value will need to be confirmed - if it was prompted for. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. :param hide_input: if this is `True` then the input on the prompt will be hidden from the user. This is useful for password input. @@ -1687,104 +2451,144 @@ class Option(Parameter): context. :param help: the help string. :param hidden: hide this option from help outputs. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. """ param_type_name = "option" def __init__( self, - param_decls=None, - show_default=False, - prompt=False, - confirmation_prompt=False, - hide_input=False, - is_flag=None, - flag_value=None, - multiple=False, - count=False, - allow_from_autoenv=True, - type=None, - help=None, - hidden=False, - show_choices=True, - show_envvar=False, - **attrs - ): - default_is_missing = attrs.get("default", _missing) is _missing - Parameter.__init__(self, param_decls, type=type, **attrs) + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: bool = False, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) if prompt is True: - prompt_text = self.name.replace("_", " ").capitalize() + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() elif prompt is False: prompt_text = None else: - prompt_text = prompt + prompt_text = t.cast(str, prompt) + self.prompt = prompt_text self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required self.hide_input = hide_input self.hidden = hidden - # Flags + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + if is_flag is None: if flag_value is not None: + # Implicitly a flag because flag_value was set. is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False else: + # Implicitly a flag because flag options were given. is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + if is_flag and default_is_missing: - self.default = False + self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False + if flag_value is None: flag_value = not self.default - self.is_flag = is_flag - self.flag_value = flag_value - if self.is_flag and isinstance(self.flag_value, bool) and type in [None, bool]: - self.type = BOOL - self.is_bool_flag = True - else: - self.is_bool_flag = False + + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag = isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value # Counting self.count = count if count: if type is None: - self.type = IntRange(min=0) + self.type = types.IntRange(min=0) if default_is_missing: self.default = 0 - self.multiple = multiple self.allow_from_autoenv = allow_from_autoenv self.help = help self.show_default = show_default self.show_choices = show_choices self.show_envvar = show_envvar - # Sanity check for stuff we don't support if __debug__: - if self.nargs < 0: - raise TypeError("Options cannot have nargs < 0") + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + if self.prompt and self.is_flag and not self.is_bool_flag: - raise TypeError("Cannot prompt for flags that are not bools.") + raise TypeError("'prompt' is not valid for non-boolean flag.") + if not self.is_bool_flag and self.secondary_opts: - raise TypeError("Got secondary option for non boolean flag.") + raise TypeError("Secondary flag is not valid for non-boolean flag.") + if self.is_bool_flag and self.hide_input and self.prompt is not None: - raise TypeError("Hidden input does not work with boolean flag prompts.") + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + if self.count: if self.multiple: - raise TypeError( - "Options cannot be multiple and count at the same time." - ) - elif self.is_flag: - raise TypeError( - "Options cannot be count and flags at the same time." - ) + raise TypeError("'count' is not valid with 'multiple'.") - def _parse_decls(self, decls, expose_value): + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: opts = [] secondary_opts = [] name = None possible_names = [] for decl in decls: - if isidentifier(decl): + if decl.isidentifier(): if name is not None: raise TypeError("Name defined twice") name = decl @@ -1799,6 +2603,11 @@ class Option(Parameter): second = second.lstrip() if second: secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) else: possible_names.append(split_opt(decl)) opts.append(decl) @@ -1806,7 +2615,7 @@ class Option(Parameter): if name is None and possible_names: possible_names.sort(key=lambda x: -len(x[0])) # group long options first name = possible_names[0][1].replace("-", "_").lower() - if not isidentifier(name): + if not name.isidentifier(): name = None if name is None: @@ -1816,19 +2625,14 @@ class Option(Parameter): if not opts and not secondary_opts: raise TypeError( - "No options defined but a name was passed ({}). Did you" - " mean to declare an argument instead of an option?".format(name) + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" ) return name, opts, secondary_opts - def add_to_parser(self, parser, ctx): - kwargs = { - "dest": self.name, - "nargs": self.nargs, - "obj": self, - } - + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: if self.multiple: action = "append" elif self.count: @@ -1837,74 +2641,145 @@ class Option(Parameter): action = "store" if self.is_flag: - kwargs.pop("nargs", None) - action_const = "{}_const".format(action) + action = f"{action}_const" + if self.is_bool_flag and self.secondary_opts: - parser.add_option(self.opts, action=action_const, const=True, **kwargs) parser.add_option( - self.secondary_opts, action=action_const, const=False, **kwargs + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, ) else: parser.add_option( - self.opts, action=action_const, const=self.flag_value, **kwargs + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, ) else: - kwargs["action"] = action - parser.add_option(self.opts, **kwargs) + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) - def get_help_record(self, ctx): + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: if self.hidden: - return - any_prefix_is_slash = [] + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash - def _write_opts(opts): rv, any_slashes = join_options(opts) + if any_slashes: - any_prefix_is_slash[:] = [True] + any_prefix_is_slash = True + if not self.is_flag and not self.count: - rv += " {}".format(self.make_metavar()) + rv += f" {self.make_metavar()}" + return rv rv = [_write_opts(self.opts)] + if self.secondary_opts: rv.append(_write_opts(self.secondary_opts)) help = self.help or "" extra = [] + if self.show_envvar: envvar = self.envvar + if envvar is None: - if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None: - envvar = "{}_{}".format(ctx.auto_envvar_prefix, self.name.upper()) + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + if envvar is not None: - extra.append( - "env var: {}".format( - ", ".join(str(d) for d in envvar) - if isinstance(envvar, (list, tuple)) - else envvar - ) + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) ) - if self.default is not None and (self.show_default or ctx.show_default): - if isinstance(self.show_default, string_types): - default_string = "({})".format(self.show_default) - elif isinstance(self.default, (list, tuple)): - default_string = ", ".join(str(d) for d in self.default) - elif inspect.isfunction(self.default): - default_string = "(dynamic)" + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default_is_str = isinstance(self.show_default, str) + + if show_default_is_str or ( + default_value is not None and (self.show_default or ctx.show_default) + ): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif callable(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if self.default else self.secondary_opts)[0] + )[1] else: - default_string = self.default - extra.append("default: {}".format(default_string)) + default_string = str(default_value) + + extra.append(_("default: {default}").format(default=default_string)) + + if isinstance(self.type, types._NumberRangeBase): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) if self.required: - extra.append("required") + extra.append(_("required")) + if extra: - help = "{}[{}]".format( - "{} ".format(help) if help else "", "; ".join(extra) - ) + extra_str = ";".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" return ("; " if any_prefix_is_slash else " / ").join(rv), help - def get_default(self, ctx): + @typing.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @typing.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: # If we're a non boolean flag our default is more complex because # we need to look at all flags in the same group to figure out # if we're the the default one in which case we return the flag @@ -1912,16 +2787,20 @@ class Option(Parameter): if self.is_flag and not self.is_bool_flag: for param in ctx.command.params: if param.name == self.name and param.default: - return param.flag_value - return None - return Parameter.get_default(self, ctx) + return param.flag_value # type: ignore - def prompt_for_value(self, ctx): + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: """This is an alternative flow that can be activated in the full value processing if a value does not exist. It will prompt the user until a valid value exists and then returns the processed value as result. """ + assert self.prompt is not None + # Calculate the default before prompting anything to be stable. default = self.get_default(ctx) @@ -1940,29 +2819,66 @@ class Option(Parameter): value_proc=lambda x: self.process_value(ctx, x), ) - def resolve_envvar_value(self, ctx): - rv = Parameter.resolve_envvar_value(self, ctx) + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + if rv is not None: return rv - if self.allow_from_autoenv and ctx.auto_envvar_prefix is not None: - envvar = "{}_{}".format(ctx.auto_envvar_prefix, self.name.upper()) - return os.environ.get(envvar) - def value_from_envvar(self, ctx): - rv = self.resolve_envvar_value(ctx) - if rv is None: - return None - value_depth = (self.nargs != 1) + bool(self.multiple) - if value_depth > 0 and rv is not None: - rv = self.type.split_envvar_value(rv) - if self.multiple and self.nargs != 1: - rv = batch(rv, self.nargs) + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + return rv - def full_process_value(self, ctx, value): - if value is None and self.prompt is not None and not ctx.resilient_parsing: - return self.prompt_for_value(ctx) - return Parameter.full_process_value(self, ctx, value) + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source class Argument(Parameter): @@ -1975,37 +2891,48 @@ class Argument(Parameter): param_type_name = "argument" - def __init__(self, param_decls, required=None, **attrs): + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: if required is None: if attrs.get("default") is not None: required = False else: required = attrs.get("nargs", 1) > 0 - Parameter.__init__(self, param_decls, required=required, **attrs) - if self.default is not None and self.nargs < 0: - raise TypeError( - "nargs=-1 in combination with a default value is not supported." - ) + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") @property - def human_readable_name(self): + def human_readable_name(self) -> str: if self.metavar is not None: return self.metavar - return self.name.upper() + return self.name.upper() # type: ignore - def make_metavar(self): + def make_metavar(self) -> str: if self.metavar is not None: return self.metavar var = self.type.get_metavar(self) if not var: - var = self.name.upper() + var = self.name.upper() # type: ignore if not self.required: - var = "[{}]".format(var) + var = f"[{var}]" if self.nargs != 1: var += "..." return var - def _parse_decls(self, decls, expose_value): + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: if not decls: if not expose_value: return None, [], [] @@ -2016,15 +2943,15 @@ class Argument(Parameter): else: raise TypeError( "Arguments take exactly one parameter declaration, got" - " {}".format(len(decls)) + f" {len(decls)}." ) return name, [arg], [] - def get_usage_pieces(self, ctx): + def get_usage_pieces(self, ctx: Context) -> t.List[str]: return [self.make_metavar()] - def get_error_hint(self, ctx): - return repr(self.make_metavar()) + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" - def add_to_parser(self, parser, ctx): + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/pipenv/vendor/click/decorators.py b/pipenv/vendor/click/decorators.py index c7b5af6c..5940e69f 100644 --- a/pipenv/vendor/click/decorators.py +++ b/pipenv/vendor/click/decorators.py @@ -1,41 +1,48 @@ import inspect -import sys +import types +import typing as t from functools import update_wrapper +from gettext import gettext as _ -from ._compat import iteritems -from ._unicodefun import _check_for_unicode_literals from .core import Argument from .core import Command +from .core import Context from .core import Group from .core import Option +from .core import Parameter from .globals import get_current_context from .utils import echo +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +FC = t.TypeVar("FC", t.Callable[..., t.Any], Command) -def pass_context(f): + +def pass_context(f: F) -> F: """Marks a callback as wanting to receive the current context object as first argument. """ - def new_func(*args, **kwargs): + def new_func(*args, **kwargs): # type: ignore return f(get_current_context(), *args, **kwargs) - return update_wrapper(new_func, f) + return update_wrapper(t.cast(F, new_func), f) -def pass_obj(f): +def pass_obj(f: F) -> F: """Similar to :func:`pass_context`, but only pass the object on the context onwards (:attr:`Context.obj`). This is useful if that object represents the state of a nested system. """ - def new_func(*args, **kwargs): + def new_func(*args, **kwargs): # type: ignore return f(get_current_context().obj, *args, **kwargs) - return update_wrapper(new_func, f) + return update_wrapper(t.cast(F, new_func), f) -def make_pass_decorator(object_type, ensure=False): +def make_pass_decorator( + object_type: t.Type, ensure: bool = False +) -> "t.Callable[[F], F]": """Given an object type this creates a decorator that will work similar to :func:`pass_obj` but instead of passing the object of the current context, it will find the innermost context of type @@ -58,52 +65,99 @@ def make_pass_decorator(object_type, ensure=False): remembered on the context if it's not there yet. """ - def decorator(f): - def new_func(*args, **kwargs): + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore ctx = get_current_context() + if ensure: obj = ctx.ensure_object(object_type) else: obj = ctx.find_object(object_type) + if obj is None: raise RuntimeError( "Managed to invoke callback without a context" - " object of type '{}' existing".format(object_type.__name__) + f" object of type {object_type.__name__!r}" + " existing." ) + return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) + return update_wrapper(t.cast(F, new_func), f) return decorator -def _make_command(f, name, attrs, cls): +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[F], F]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +def _make_command( + f: F, + name: t.Optional[str], + attrs: t.MutableMapping[str, t.Any], + cls: t.Type[Command], +) -> Command: if isinstance(f, Command): raise TypeError("Attempted to convert a callback into a command twice.") + try: - params = f.__click_params__ + params = f.__click_params__ # type: ignore params.reverse() - del f.__click_params__ + del f.__click_params__ # type: ignore except AttributeError: params = [] + help = attrs.get("help") + if help is None: help = inspect.getdoc(f) - if isinstance(help, bytes): - help = help.decode("utf-8") else: help = inspect.cleandoc(help) + attrs["help"] = help - _check_for_unicode_literals() return cls( name=name or f.__name__.lower().replace("_", "-"), callback=f, params=params, - **attrs + **attrs, ) -def command(name=None, cls=None, **attrs): +def command( + name: t.Optional[str] = None, + cls: t.Optional[t.Type[Command]] = None, + **attrs: t.Any, +) -> t.Callable[[F], Command]: r"""Creates a new :class:`Command` and uses the decorated function as callback. This will also automatically attach all decorated :func:`option`\s and :func:`argument`\s as parameters to the command. @@ -126,33 +180,34 @@ def command(name=None, cls=None, **attrs): if cls is None: cls = Command - def decorator(f): - cmd = _make_command(f, name, attrs, cls) + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd = _make_command(f, name, attrs, cls) # type: ignore cmd.__doc__ = f.__doc__ return cmd return decorator -def group(name=None, **attrs): +def group(name: t.Optional[str] = None, **attrs: t.Any) -> t.Callable[[F], Group]: """Creates a new :class:`Group` with a function as callback. This works otherwise the same as :func:`command` just that the `cls` parameter is set to :class:`Group`. """ attrs.setdefault("cls", Group) - return command(name, **attrs) + return t.cast(Group, command(name, **attrs)) -def _param_memo(f, param): +def _param_memo(f: FC, param: Parameter) -> None: if isinstance(f, Command): f.params.append(param) else: if not hasattr(f, "__click_params__"): - f.__click_params__ = [] - f.__click_params__.append(param) + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore -def argument(*param_decls, **attrs): +def argument(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: """Attaches an argument to the command. All positional arguments are passed as parameter declarations to :class:`Argument`; all keyword arguments are forwarded unchanged (except ``cls``). @@ -163,7 +218,7 @@ def argument(*param_decls, **attrs): :class:`Argument`. """ - def decorator(f): + def decorator(f: FC) -> FC: ArgumentClass = attrs.pop("cls", Argument) _param_memo(f, ArgumentClass(param_decls, **attrs)) return f @@ -171,7 +226,7 @@ def argument(*param_decls, **attrs): return decorator -def option(*param_decls, **attrs): +def option(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: """Attaches an option to the command. All positional arguments are passed as parameter declarations to :class:`Option`; all keyword arguments are forwarded unchanged (except ``cls``). @@ -182,7 +237,7 @@ def option(*param_decls, **attrs): :class:`Option`. """ - def decorator(f): + def decorator(f: FC) -> FC: # Issue 926, copy attrs, so pre-defined options can re-use the same cls= option_attrs = attrs.copy() @@ -195,139 +250,188 @@ def option(*param_decls, **attrs): return decorator -def confirmation_option(*param_decls, **attrs): - """Shortcut for confirmation prompts that can be ignored by passing - ``--yes`` as parameter. +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. - This is equivalent to decorating a function with :func:`option` with - the following parameters:: - - def callback(ctx, param, value): - if not value: - ctx.abort() - - @click.command() - @click.option('--yes', is_flag=True, callback=callback, - expose_value=False, prompt='Do you want to continue?') - def dropdb(): - pass + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. """ - def decorator(f): - def callback(ctx, param, value): - if not value: - ctx.abort() + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() - attrs.setdefault("is_flag", True) - attrs.setdefault("callback", callback) - attrs.setdefault("expose_value", False) - attrs.setdefault("prompt", "Do you want to continue?") - attrs.setdefault("help", "Confirm the action without prompting.") - return option(*(param_decls or ("--yes",)), **attrs)(f) + if not param_decls: + param_decls = ("--yes",) - return decorator + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) -def password_option(*param_decls, **attrs): - """Shortcut for password prompts. +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. - This is equivalent to decorating a function with :func:`option` with - the following parameters:: + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) - @click.command() - @click.option('--password', prompt=True, confirmation_prompt=True, - hide_input=True) - def changeadmin(password): - pass + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + assert frame is not None + assert frame.f_back is not None + f_globals = frame.f_back.f_globals if frame is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + t.cast(str, message) + % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. """ - def decorator(f): - attrs.setdefault("prompt", True) - attrs.setdefault("confirmation_prompt", True) - attrs.setdefault("hide_input", True) - return option(*(param_decls or ("--password",)), **attrs)(f) + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return - return decorator + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + if not param_decls: + param_decls = ("--help",) -def version_option(version=None, *param_decls, **attrs): - """Adds a ``--version`` option which immediately ends the program - printing out the version number. This is implemented as an eager - option that prints the version and exits the program in the callback. - - :param version: the version number to show. If not provided Click - attempts an auto discovery via setuptools. - :param prog_name: the name of the program (defaults to autodetection) - :param message: custom message to show instead of the default - (``'%(prog)s, version %(version)s'``) - :param others: everything else is forwarded to :func:`option`. - """ - if version is None: - if hasattr(sys, "_getframe"): - module = sys._getframe(1).f_globals.get("__name__") - else: - module = "" - - def decorator(f): - prog_name = attrs.pop("prog_name", None) - message = attrs.pop("message", "%(prog)s, version %(version)s") - - def callback(ctx, param, value): - if not value or ctx.resilient_parsing: - return - prog = prog_name - if prog is None: - prog = ctx.find_root().info_name - ver = version - if ver is None: - try: - import pkg_resources - except ImportError: - pass - else: - for dist in pkg_resources.working_set: - scripts = dist.get_entry_map().get("console_scripts") or {} - for _, entry_point in iteritems(scripts): - if entry_point.module_name == module: - ver = dist.version - break - if ver is None: - raise RuntimeError("Could not determine version") - echo(message % {"prog": prog, "version": ver}, color=ctx.color) - ctx.exit() - - attrs.setdefault("is_flag", True) - attrs.setdefault("expose_value", False) - attrs.setdefault("is_eager", True) - attrs.setdefault("help", "Show the version and exit.") - attrs["callback"] = callback - return option(*(param_decls or ("--version",)), **attrs)(f) - - return decorator - - -def help_option(*param_decls, **attrs): - """Adds a ``--help`` option which immediately ends the program - printing out the help page. This is usually unnecessary to add as - this is added by default to all commands unless suppressed. - - Like :func:`version_option`, this is implemented as eager option that - prints in the callback and exits. - - All arguments are forwarded to :func:`option`. - """ - - def decorator(f): - def callback(ctx, param, value): - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - attrs.setdefault("is_flag", True) - attrs.setdefault("expose_value", False) - attrs.setdefault("help", "Show this message and exit.") - attrs.setdefault("is_eager", True) - attrs["callback"] = callback - return option(*(param_decls or ("--help",)), **attrs)(f) - - return decorator + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/pipenv/vendor/click/exceptions.py b/pipenv/vendor/click/exceptions.py index 592ee38f..9e20b3eb 100644 --- a/pipenv/vendor/click/exceptions.py +++ b/pipenv/vendor/click/exceptions.py @@ -1,45 +1,46 @@ -from ._compat import filename_to_ui +import os +import typing as t +from gettext import gettext as _ +from gettext import ngettext + from ._compat import get_text_stderr -from ._compat import PY2 from .utils import echo +if t.TYPE_CHECKING: + from .core import Context + from .core import Parameter -def _join_param_hints(param_hint): - if isinstance(param_hint, (tuple, list)): + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): return " / ".join(repr(x) for x in param_hint) + return param_hint class ClickException(Exception): """An exception that Click can handle and show to the user.""" - #: The exit code for this exception + #: The exit code for this exception. exit_code = 1 - def __init__(self, message): - ctor_msg = message - if PY2: - if ctor_msg is not None: - ctor_msg = ctor_msg.encode("utf-8") - Exception.__init__(self, ctor_msg) + def __init__(self, message: str) -> None: + super().__init__(message) self.message = message - def format_message(self): + def format_message(self) -> str: return self.message - def __str__(self): + def __str__(self) -> str: return self.message - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.message.encode("utf-8") - - def show(self, file=None): + def show(self, file: t.Optional[t.IO] = None) -> None: if file is None: file = get_text_stderr() - echo("Error: {}".format(self.format_message()), file=file) + + echo(_("Error: {message}").format(message=self.format_message()), file=file) class UsageError(ClickException): @@ -53,24 +54,32 @@ class UsageError(ClickException): exit_code = 2 - def __init__(self, message, ctx=None): - ClickException.__init__(self, message) + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) self.ctx = ctx self.cmd = self.ctx.command if self.ctx else None - def show(self, file=None): + def show(self, file: t.Optional[t.IO] = None) -> None: if file is None: file = get_text_stderr() color = None hint = "" - if self.cmd is not None and self.cmd.get_help_option(self.ctx) is not None: - hint = "Try '{} {}' for help.\n".format( - self.ctx.command_path, self.ctx.help_option_names[0] + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] ) + hint = f"{hint}\n" if self.ctx is not None: color = self.ctx.color - echo("{}\n{}".format(self.ctx.get_usage(), hint), file=file, color=color) - echo("Error: {}".format(self.format_message()), file=file, color=color) + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) class BadParameter(UsageError): @@ -91,21 +100,28 @@ class BadParameter(UsageError): each item is quoted and separated. """ - def __init__(self, message, ctx=None, param=None, param_hint=None): - UsageError.__init__(self, message, ctx) + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) self.param = param self.param_hint = param_hint - def format_message(self): + def format_message(self) -> str: if self.param_hint is not None: param_hint = self.param_hint elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) + param_hint = self.param.get_error_hint(self.ctx) # type: ignore else: - return "Invalid value: {}".format(self.message) - param_hint = _join_param_hints(param_hint) + return _("Invalid value: {message}").format(message=self.message) - return "Invalid value for {}: {}".format(param_hint, self.message) + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) class MissingParameter(BadParameter): @@ -121,19 +137,26 @@ class MissingParameter(BadParameter): """ def __init__( - self, message=None, ctx=None, param=None, param_hint=None, param_type=None - ): - BadParameter.__init__(self, message, ctx, param, param_hint) + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) self.param_type = param_type - def format_message(self): + def format_message(self) -> str: if self.param_hint is not None: - param_hint = self.param_hint + param_hint: t.Optional[str] = self.param_hint elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) + param_hint = self.param.get_error_hint(self.ctx) # type: ignore else: param_hint = None + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" param_type = self.param_type if param_type is None and self.param is not None: @@ -144,30 +167,31 @@ class MissingParameter(BadParameter): msg_extra = self.param.type.get_missing_message(self.param) if msg_extra: if msg: - msg += ". {}".format(msg_extra) + msg += f". {msg_extra}" else: msg = msg_extra - return "Missing {}{}{}{}".format( - param_type, - " {}".format(param_hint) if param_hint else "", - ". " if msg else ".", - msg or "", - ) + msg = f" {msg}" if msg else "" - def __str__(self): - if self.message is None: + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: param_name = self.param.name if self.param else None - return "missing parameter: {}".format(param_name) + return _("Missing parameter: {param_name}").format(param_name=param_name) else: return self.message - if PY2: - __unicode__ = __str__ - - def __str__(self): - return self.__unicode__().encode("utf-8") - class NoSuchOption(UsageError): """Raised if click attempted to handle an option that does not @@ -176,22 +200,31 @@ class NoSuchOption(UsageError): .. versionadded:: 4.0 """ - def __init__(self, option_name, message=None, possibilities=None, ctx=None): + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: if message is None: - message = "no such option: {}".format(option_name) - UsageError.__init__(self, message, ctx) + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) self.option_name = option_name self.possibilities = possibilities - def format_message(self): - bits = [self.message] - if self.possibilities: - if len(self.possibilities) == 1: - bits.append("Did you mean {}?".format(self.possibilities[0])) - else: - possibilities = sorted(self.possibilities) - bits.append("(Possible options: {})".format(", ".join(possibilities))) - return " ".join(bits) + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" class BadOptionUsage(UsageError): @@ -204,8 +237,10 @@ class BadOptionUsage(UsageError): :param option_name: the name of the option being used incorrectly. """ - def __init__(self, option_name, message, ctx=None): - UsageError.__init__(self, message, ctx) + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) self.option_name = option_name @@ -217,23 +252,22 @@ class BadArgumentUsage(UsageError): .. versionadded:: 6.0 """ - def __init__(self, message, ctx=None): - UsageError.__init__(self, message, ctx) - class FileError(ClickException): """Raised if a file cannot be opened.""" - def __init__(self, filename, hint=None): - ui_filename = filename_to_ui(filename) + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: if hint is None: - hint = "unknown error" - ClickException.__init__(self, hint) - self.ui_filename = ui_filename + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename = os.fsdecode(filename) self.filename = filename - def format_message(self): - return "Could not open file {}: {}".format(self.ui_filename, self.message) + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) class Abort(RuntimeError): @@ -249,5 +283,5 @@ class Exit(RuntimeError): __slots__ = ("exit_code",) - def __init__(self, code=0): + def __init__(self, code: int = 0) -> None: self.exit_code = code diff --git a/pipenv/vendor/click/formatting.py b/pipenv/vendor/click/formatting.py index 319c7f61..ddd2a2f8 100644 --- a/pipenv/vendor/click/formatting.py +++ b/pipenv/vendor/click/formatting.py @@ -1,30 +1,38 @@ +import typing as t from contextlib import contextmanager +from gettext import gettext as _ from ._compat import term_len from .parser import split_opt -from .termui import get_terminal_size # Can force a width. This is used by the test system -FORCED_WIDTH = None +FORCED_WIDTH: t.Optional[int] = None -def measure_table(rows): - widths = {} +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + for row in rows: for idx, col in enumerate(row): widths[idx] = max(widths.get(idx, 0), term_len(col)) + return tuple(y for x, y in sorted(widths.items())) -def iter_rows(rows, col_count): +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: for row in rows: - row = tuple(row) yield row + ("",) * (col_count - len(row)) def wrap_text( - text, width=78, initial_indent="", subsequent_indent="", preserve_paragraphs=False -): + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: """A helper function that intelligently wraps text. By default, it assumes that it operates on a single paragraph of text but if the `preserve_paragraphs` parameter is provided it will intelligently @@ -55,11 +63,11 @@ def wrap_text( if not preserve_paragraphs: return wrapper.fill(text) - p = [] - buf = [] + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] indent = None - def _flush_par(): + def _flush_par() -> None: if not buf: return if buf[0].strip() == "\b": @@ -91,7 +99,7 @@ def wrap_text( return "\n\n".join(rv) -class HelpFormatter(object): +class HelpFormatter: """This class helps with formatting text-based help pages. It's usually just needed for very special internal cases, but it's also exposed so that developers can write their own fancy outputs. @@ -103,38 +111,51 @@ class HelpFormatter(object): width clamped to a maximum of 78. """ - def __init__(self, indent_increment=2, width=None, max_width=None): + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + self.indent_increment = indent_increment if max_width is None: max_width = 80 if width is None: width = FORCED_WIDTH if width is None: - width = max(min(get_terminal_size()[0], max_width) - 2, 50) + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) self.width = width self.current_indent = 0 - self.buffer = [] + self.buffer: t.List[str] = [] - def write(self, string): + def write(self, string: str) -> None: """Writes a unicode string into the internal buffer.""" self.buffer.append(string) - def indent(self): + def indent(self) -> None: """Increases the indentation.""" self.current_indent += self.indent_increment - def dedent(self): + def dedent(self) -> None: """Decreases the indentation.""" self.current_indent -= self.indent_increment - def write_usage(self, prog, args="", prefix="Usage: "): + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: """Writes a usage line into the buffer. :param prog: the program name. :param args: whitespace separated list of arguments. - :param prefix: the prefix for the first line. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. """ - usage_prefix = "{:>{w}}{} ".format(prefix, prog, w=self.current_indent) + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " text_width = self.width - self.current_indent if text_width >= (term_len(usage_prefix) + 20): @@ -161,25 +182,24 @@ class HelpFormatter(object): self.write("\n") - def write_heading(self, heading): + def write_heading(self, heading: str) -> None: """Writes a heading into the buffer.""" - self.write("{:>{w}}{}:\n".format("", heading, w=self.current_indent)) + self.write(f"{'':>{self.current_indent}}{heading}:\n") - def write_paragraph(self): + def write_paragraph(self) -> None: """Writes a paragraph into the buffer.""" if self.buffer: self.write("\n") - def write_text(self, text): + def write_text(self, text: str) -> None: """Writes re-indented text into the buffer. This rewraps and preserves paragraphs. """ - text_width = max(self.width - self.current_indent, 11) indent = " " * self.current_indent self.write( wrap_text( text, - text_width, + self.width, initial_indent=indent, subsequent_indent=indent, preserve_paragraphs=True, @@ -187,7 +207,12 @@ class HelpFormatter(object): ) self.write("\n") - def write_dl(self, rows, col_max=30, col_spacing=2): + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: """Writes a definition list into the buffer. This is how options and commands are usually formatted. @@ -204,7 +229,7 @@ class HelpFormatter(object): first_col = min(widths[0], col_max) + col_spacing for first, second in iter_rows(rows, len(widths)): - self.write("{:>{w}}{}".format("", first, w=self.current_indent)) + self.write(f"{'':>{self.current_indent}}{first}") if not second: self.write("\n") continue @@ -219,23 +244,15 @@ class HelpFormatter(object): lines = wrapped_text.splitlines() if lines: - self.write("{}\n".format(lines[0])) + self.write(f"{lines[0]}\n") for line in lines[1:]: - self.write( - "{:>{w}}{}\n".format( - "", line, w=first_col + self.current_indent - ) - ) - - if len(lines) > 1: - # separate long help from next option - self.write("\n") + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") else: self.write("\n") @contextmanager - def section(self, name): + def section(self, name: str) -> t.Iterator[None]: """Helpful context manager that writes a paragraph, a heading, and the indents. @@ -250,7 +267,7 @@ class HelpFormatter(object): self.dedent() @contextmanager - def indentation(self): + def indentation(self) -> t.Iterator[None]: """A context manager that increases the indentation.""" self.indent() try: @@ -258,12 +275,12 @@ class HelpFormatter(object): finally: self.dedent() - def getvalue(self): + def getvalue(self) -> str: """Returns the buffer contents.""" return "".join(self.buffer) -def join_options(options): +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: """Given a list of option strings this joins them in the most appropriate way and returns them in the form ``(formatted_string, any_prefix_is_slash)`` where the second item in the tuple is a flag that @@ -271,13 +288,14 @@ def join_options(options): """ rv = [] any_prefix_is_slash = False + for opt in options: prefix = split_opt(opt)[0] + if prefix == "/": any_prefix_is_slash = True + rv.append((len(prefix), opt)) rv.sort(key=lambda x: x[0]) - - rv = ", ".join(x[1] for x in rv) - return rv, any_prefix_is_slash + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/pipenv/vendor/click/globals.py b/pipenv/vendor/click/globals.py index 1649f9a0..cfcade14 100644 --- a/pipenv/vendor/click/globals.py +++ b/pipenv/vendor/click/globals.py @@ -1,9 +1,25 @@ +import typing +import typing as t from threading import local +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + _local = local() -def get_current_context(silent=False): +@typing.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@typing.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: """Returns the current click context. This can be used as a way to access the current context object from anywhere. This is a more implicit alternative to the :func:`pass_context` decorator. This function is @@ -19,29 +35,35 @@ def get_current_context(silent=False): :exc:`RuntimeError`. """ try: - return _local.stack[-1] + return t.cast("Context", _local.stack[-1]) except (AttributeError, IndexError): if not silent: raise RuntimeError("There is no active click context.") + return None -def push_context(ctx): + +def push_context(ctx: "Context") -> None: """Pushes a new context to the current stack.""" _local.__dict__.setdefault("stack", []).append(ctx) -def pop_context(): +def pop_context() -> None: """Removes the top level from the stack.""" _local.stack.pop() -def resolve_color_default(color=None): - """"Internal helper to get the default value of the color flag. If a +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a value is passed it's returned unchanged, otherwise it's looked up from the current context. """ if color is not None: return color + ctx = get_current_context(silent=True) + if ctx is not None: return ctx.color + + return None diff --git a/pipenv/vendor/click/parser.py b/pipenv/vendor/click/parser.py index f43ebfe9..7d995f77 100644 --- a/pipenv/vendor/click/parser.py +++ b/pipenv/vendor/click/parser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ This module started out as largely a copy paste from the stdlib's optparse module with the features removed that we do not need from @@ -18,16 +17,38 @@ by the Python Software Foundation. This is limited to code in parser.py. Copyright 2001-2006 Gregory P. Ward. All rights reserved. Copyright 2002-2006 Python Software Foundation. All rights reserved. """ -import re +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t from collections import deque +from gettext import gettext as _ +from gettext import ngettext from .exceptions import BadArgumentUsage from .exceptions import BadOptionUsage from .exceptions import NoSuchOption from .exceptions import UsageError +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter -def _unpack_args(args, nargs_spec): +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: """Given an iterable of arguments and an iterable of nargs specifications, it returns a tuple with all the unpacked arguments at the first index and all remaining arguments as the second. @@ -39,10 +60,10 @@ def _unpack_args(args, nargs_spec): """ args = deque(args) nargs_spec = deque(nargs_spec) - rv = [] - spos = None + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None - def _fetch(c): + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: try: if spos is None: return c.popleft() @@ -53,18 +74,25 @@ def _unpack_args(args, nargs_spec): while nargs_spec: nargs = _fetch(nargs_spec) + + if nargs is None: + continue + if nargs == 1: rv.append(_fetch(args)) elif nargs > 1: x = [_fetch(args) for _ in range(nargs)] + # If we're reversed, we're pulling in the arguments in reverse, # so we need to turn them around. if spos is not None: x.reverse() + rv.append(tuple(x)) elif nargs < 0: if spos is not None: raise TypeError("Cannot have two nargs < 0") + spos = len(rv) rv.append(None) @@ -78,13 +106,7 @@ def _unpack_args(args, nargs_spec): return tuple(rv), list(args) -def _error_opt_args(nargs, opt): - if nargs == 1: - raise BadOptionUsage(opt, "{} option requires an argument".format(opt)) - raise BadOptionUsage(opt, "{} option requires {} arguments".format(opt, nargs)) - - -def split_opt(opt): +def split_opt(opt: str) -> t.Tuple[str, str]: first = opt[:1] if first.isalnum(): return "", opt @@ -93,34 +115,57 @@ def split_opt(opt): return first, opt[1:] -def normalize_opt(opt, ctx): +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: if ctx is None or ctx.token_normalize_func is None: return opt prefix, opt = split_opt(opt) - return prefix + ctx.token_normalize_func(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" -def split_arg_string(string): - """Given an argument string this attempts to split it into small parts.""" - rv = [] - for match in re.finditer( - r"('([^'\\]*(?:\\.[^'\\]*)*)'|\"([^\"\\]*(?:\\.[^\"\\]*)*)\"|\S+)\s*", - string, - re.S, +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, ): - arg = match.group().strip() - if arg[:1] == arg[-1:] and arg[:1] in "\"'": - arg = arg[1:-1].encode("ascii", "backslashreplace").decode("unicode-escape") - try: - arg = type(string)(arg) - except UnicodeError: - pass - rv.append(arg) - return rv - - -class Option(object): - def __init__(self, opts, dest, action=None, nargs=1, const=None, obj=None): self._short_opts = [] self._long_opts = [] self.prefixes = set() @@ -128,7 +173,7 @@ class Option(object): for opt in opts: prefix, value = split_opt(opt) if not prefix: - raise ValueError("Invalid start character for option ({})".format(opt)) + raise ValueError(f"Invalid start character for option ({opt})") self.prefixes.add(prefix[0]) if len(prefix) == 1 and len(value) == 1: self._short_opts.append(opt) @@ -146,53 +191,66 @@ class Option(object): self.obj = obj @property - def takes_value(self): + def takes_value(self) -> bool: return self.action in ("store", "append") - def process(self, value, state): + def process(self, value: str, state: "ParsingState") -> None: if self.action == "store": - state.opts[self.dest] = value + state.opts[self.dest] = value # type: ignore elif self.action == "store_const": - state.opts[self.dest] = self.const + state.opts[self.dest] = self.const # type: ignore elif self.action == "append": - state.opts.setdefault(self.dest, []).append(value) + state.opts.setdefault(self.dest, []).append(value) # type: ignore elif self.action == "append_const": - state.opts.setdefault(self.dest, []).append(self.const) + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore elif self.action == "count": - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore else: - raise ValueError("unknown action '{}'".format(self.action)) + raise ValueError(f"unknown action '{self.action}'") state.order.append(self.obj) -class Argument(object): - def __init__(self, dest, nargs=1, obj=None): +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): self.dest = dest self.nargs = nargs self.obj = obj - def process(self, value, state): + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: if self.nargs > 1: + assert value is not None holes = sum(1 for x in value if x is None) if holes == len(value): value = None elif holes != 0: raise BadArgumentUsage( - "argument {} takes {} values".format(self.dest, self.nargs) + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) ) - state.opts[self.dest] = value + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore state.order.append(self.obj) -class ParsingState(object): - def __init__(self, rargs): - self.opts = {} - self.largs = [] +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] self.rargs = rargs - self.order = [] + self.order: t.List["CoreParameter"] = [] -class OptionParser(object): +class OptionParser: """The option parser is an internal class that is ultimately used to parse options and arguments. It's modelled after optparse and brings a similar but vastly simplified API. It should generally not be used @@ -206,7 +264,7 @@ class OptionParser(object): should go with. """ - def __init__(self, ctx=None): + def __init__(self, ctx: t.Optional["Context"] = None) -> None: #: The :class:`~click.Context` for this parser. This might be #: `None` for some advanced use cases. self.ctx = ctx @@ -220,15 +278,25 @@ class OptionParser(object): #: second mode where it will ignore it and continue processing #: after shifting all the unknown options into the resulting args. self.ignore_unknown_options = False + if ctx is not None: self.allow_interspersed_args = ctx.allow_interspersed_args self.ignore_unknown_options = ctx.ignore_unknown_options - self._short_opt = {} - self._long_opt = {} - self._opt_prefixes = {"-", "--"} - self._args = [] - def add_option(self, opts, dest, action=None, nargs=1, const=None, obj=None): + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: """Adds a new option named `dest` to the parser. The destination is not inferred (unlike with optparse) and needs to be explicitly provided. Action can be any of ``store``, ``store_const``, @@ -237,27 +305,27 @@ class OptionParser(object): The `obj` can be used to identify the option in the order list that is returned from the parser. """ - if obj is None: - obj = dest opts = [normalize_opt(opt, self.ctx) for opt in opts] - option = Option(opts, dest, action=action, nargs=nargs, const=const, obj=obj) + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) self._opt_prefixes.update(option.prefixes) for opt in option._short_opts: self._short_opt[opt] = option for opt in option._long_opts: self._long_opt[opt] = option - def add_argument(self, dest, nargs=1, obj=None): + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: """Adds a positional argument named `dest` to the parser. The `obj` can be used to identify the option in the order list that is returned from the parser. """ - if obj is None: - obj = dest - self._args.append(Argument(dest=dest, nargs=nargs, obj=obj)) + self._args.append(Argument(obj, dest=dest, nargs=nargs)) - def parse_args(self, args): + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: """Parses positional arguments and returns ``(values, args, order)`` for the parsed options and arguments as well as the leftover arguments if there are any. The order is a list of objects as they @@ -273,7 +341,7 @@ class OptionParser(object): raise return state.opts, state.largs, state.order - def _process_args_for_args(self, state): + def _process_args_for_args(self, state: ParsingState) -> None: pargs, args = _unpack_args( state.largs + state.rargs, [x.nargs for x in self._args] ) @@ -284,7 +352,7 @@ class OptionParser(object): state.largs = args state.rargs = [] - def _process_args_for_options(self, state): + def _process_args_for_options(self, state: ParsingState) -> None: while state.rargs: arg = state.rargs.pop(0) arglen = len(arg) @@ -320,9 +388,13 @@ class OptionParser(object): # *empty* -- still a subset of [arg0, ..., arg(i-1)], but # not a very interesting subset! - def _match_long_opt(self, opt, explicit_value, state): + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: if opt not in self._long_opt: - possibilities = [word for word in self._long_opt if word.startswith(opt)] + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) option = self._long_opt[opt] @@ -334,31 +406,26 @@ class OptionParser(object): if explicit_value is not None: state.rargs.insert(0, explicit_value) - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] + value = self._get_value_from_state(opt, option, state) elif explicit_value is not None: - raise BadOptionUsage(opt, "{} option does not take a value".format(opt)) + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) else: value = None option.process(value, state) - def _match_short_opt(self, arg, state): + def _match_short_opt(self, arg: str, state: ParsingState) -> None: stop = False i = 1 prefix = arg[0] unknown_options = [] for ch in arg[1:]: - opt = normalize_opt(prefix + ch, self.ctx) + opt = normalize_opt(f"{prefix}{ch}", self.ctx) option = self._short_opt.get(opt) i += 1 @@ -374,14 +441,7 @@ class OptionParser(object): state.rargs.insert(0, arg[i:]) stop = True - nargs = option.nargs - if len(state.rargs) < nargs: - _error_opt_args(nargs, opt) - elif nargs == 1: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] + value = self._get_value_from_state(opt, option, state) else: value = None @@ -396,9 +456,47 @@ class OptionParser(object): # to the state as new larg. This way there is basic combinatorics # that can be achieved while still ignoring unknown arguments. if self.ignore_unknown_options and unknown_options: - state.largs.append("{}{}".format(prefix, "".join(unknown_options))) + state.largs.append(f"{prefix}{''.join(unknown_options)}") - def _process_opts(self, arg, state): + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: explicit_value = None # Long option handling happens in two parts. The first part is # supporting explicitly attached values. In any case, we will try @@ -422,7 +520,10 @@ class OptionParser(object): # short option code and will instead raise the no option # error. if arg[:2] not in self._opt_prefixes: - return self._match_short_opt(arg, state) + self._match_short_opt(arg, state) + return + if not self.ignore_unknown_options: raise + state.largs.append(arg) diff --git a/pipenv/vendor/importlib_resources/tests/data03/__init__.py b/pipenv/vendor/click/py.typed similarity index 100% rename from pipenv/vendor/importlib_resources/tests/data03/__init__.py rename to pipenv/vendor/click/py.typed diff --git a/pipenv/vendor/click/shell_completion.py b/pipenv/vendor/click/shell_completion.py new file mode 100644 index 00000000..706fb693 --- /dev/null +++ b/pipenv/vendor/click/shell_completion.py @@ -0,0 +1,574 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value = value + self.type = type + self.help = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +compdef %(complete_func)s %(prog_name)s; +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response; + + for value in (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + set response $response $value; + end; + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + def _check_version(self) -> None: + import subprocess + + output = subprocess.run(["bash", "--version"], stdout=subprocess.PIPE) + match = re.search(r"version (\d)\.(\d)\.\d", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + raise RuntimeError( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ) + ) + else: + raise RuntimeError( + _("Couldn't detect Bash version, shell completion is not supported.") + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: t.Type[ShellComplete], name: t.Optional[str] = None +) -> None: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + value = ctx.params[param.name] + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(value: str) -> bool: + """Check if the value looks like the start of an option.""" + return not value[0].isalnum() if value else False + + +def _is_incomplete_option(args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, ctx_args: t.Dict[str, t.Any], prog_name: str, args: t.List[str] +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/pipenv/vendor/click/termui.py b/pipenv/vendor/click/termui.py index 02ef9e9f..034fe6ed 100644 --- a/pipenv/vendor/click/termui.py +++ b/pipenv/vendor/click/termui.py @@ -2,29 +2,31 @@ import inspect import io import itertools import os -import struct import sys +import typing +import typing as t +from gettext import gettext as _ -from ._compat import DEFAULT_COLUMNS -from ._compat import get_winterm_size from ._compat import isatty -from ._compat import raw_input -from ._compat import string_types from ._compat import strip_ansi -from ._compat import text_type from ._compat import WIN from .exceptions import Abort from .exceptions import UsageError from .globals import resolve_color_default from .types import Choice from .types import convert_type -from .types import Path +from .types import ParamType from .utils import echo from .utils import LazyFile +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + # The prompt functions to use. The doc tools currently override these # functions to customize how they work. -visible_prompt_func = raw_input +visible_prompt_func: t.Callable[[str], str] = input _ansi_colors = { "black": 30, @@ -48,63 +50,61 @@ _ansi_colors = { _ansi_reset_all = "\033[0m" -def hidden_prompt_func(prompt): +def hidden_prompt_func(prompt: str) -> str: import getpass return getpass.getpass(prompt) def _build_prompt( - text, suffix, show_default=False, default=None, show_choices=True, type=None -): + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: prompt = text if type is not None and show_choices and isinstance(type, Choice): - prompt += " ({})".format(", ".join(map(str, type.choices))) + prompt += f" ({', '.join(map(str, type.choices))})" if default is not None and show_default: - prompt = "{} [{}]".format(prompt, _format_default(default)) - return prompt + suffix + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" -def _format_default(default): +def _format_default(default: t.Any) -> t.Any: if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): - return default.name + return default.name # type: ignore return default def prompt( - text, - default=None, - hide_input=False, - confirmation_prompt=False, - type=None, - value_proc=None, - prompt_suffix=": ", - show_default=True, - err=False, - show_choices=True, -): + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[ParamType] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: """Prompts a user for input. This is a convenience function that can be used to prompt a user for input later. If the user aborts the input by sending a interrupt signal, this function will catch it and raise a :exc:`Abort` exception. - .. versionadded:: 7.0 - Added the show_choices parameter. - - .. versionadded:: 6.0 - Added unicode support for cmd.exe on Windows. - - .. versionadded:: 4.0 - Added the `err` parameter. - :param text: the text to show for the prompt. :param default: the default value to use if no input happens. If this is not given it will prompt until it's aborted. :param hide_input: if this is set to true then the input value will be hidden. - :param confirmation_prompt: asks for confirmation for the value. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. :param type: the type to use to check the value against. :param value_proc: if this parameter is provided it's a function that is invoked instead of the type conversion to @@ -117,16 +117,30 @@ def prompt( For example if type is a Choice of either day or week, show_choices is true and text is "Group by" then the prompt will be "Group by (day, week): ". - """ - result = None - def prompt_func(text): + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: f = hidden_prompt_func if hide_input else visible_prompt_func try: # Write the prompt separately so that we get nice # coloring through colorama on Windows - echo(text, nl=False, err=err) - return f("") + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") except (KeyboardInterrupt, EOFError): # getpass doesn't print a newline if the user aborts input with ^C. # Allegedly this behavior is inherited from getpass(3). @@ -142,57 +156,78 @@ def prompt( text, prompt_suffix, show_default, default, show_choices, type ) - while 1: - while 1: + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = t.cast(str, confirmation_prompt) + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: value = prompt_func(prompt) if value: break elif default is not None: - if isinstance(value_proc, Path): - # validate Path default value(exists, dir_okay etc.) - value = default - break - return default + value = default + break try: result = value_proc(value) except UsageError as e: - echo("Error: {}".format(e.message), err=err) # noqa: B306 + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 continue if not confirmation_prompt: return result - while 1: - value2 = prompt_func("Repeat for confirmation: ") + while True: + confirmation_prompt = t.cast(str, confirmation_prompt) + value2 = prompt_func(confirmation_prompt) if value2: break if value == value2: return result - echo("Error: the two entered values do not match", err=err) + echo(_("Error: The two entered values do not match."), err=err) def confirm( - text, default=False, abort=False, prompt_suffix=": ", show_default=True, err=False -): + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: """Prompts for confirmation (yes/no question). If the user aborts the input by sending a interrupt signal this function will catch it and raise a :exc:`Abort` exception. - .. versionadded:: 4.0 - Added the `err` parameter. - :param text: the question to ask. - :param default: the default for the prompt. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. :param abort: if this is set to `True` a negative answer aborts the exception by raising :exc:`Abort`. :param prompt_suffix: a suffix that should be added to the prompt. :param show_default: shows or hides the default value in the prompt. :param err: if set to true the file defaults to ``stderr`` instead of ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. """ prompt = _build_prompt( - text, prompt_suffix, show_default, "Y/n" if default else "y/N" + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), ) - while 1: + + while True: try: # Write the prompt separately so that we get nice # coloring through colorama on Windows @@ -204,10 +239,10 @@ def confirm( rv = True elif value in ("n", "no"): rv = False - elif value == "": + elif default is not None and value == "": rv = default else: - echo("Error: invalid input", err=err) + echo(_("Error: invalid input"), err=err) continue break if abort and not rv: @@ -215,54 +250,30 @@ def confirm( return rv -def get_terminal_size(): +def get_terminal_size() -> os.terminal_size: """Returns the current size of the terminal as tuple in the form ``(width, height)`` in columns and rows. + + .. deprecated:: 8.0 + Will be removed in Click 8.1. Use + :func:`shutil.get_terminal_size` instead. """ - # If shutil has get_terminal_size() (Python 3.3 and later) use that - if sys.version_info >= (3, 3): - import shutil + import shutil + import warnings - shutil_get_terminal_size = getattr(shutil, "get_terminal_size", None) - if shutil_get_terminal_size: - sz = shutil_get_terminal_size() - return sz.columns, sz.lines - - # We provide a sensible default for get_winterm_size() when being invoked - # inside a subprocess. Without this, it would not provide a useful input. - if get_winterm_size is not None: - size = get_winterm_size() - if size == (0, 0): - return (79, 24) - else: - return size - - def ioctl_gwinsz(fd): - try: - import fcntl - import termios - - cr = struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234")) - except Exception: - return - return cr - - cr = ioctl_gwinsz(0) or ioctl_gwinsz(1) or ioctl_gwinsz(2) - if not cr: - try: - fd = os.open(os.ctermid(), os.O_RDONLY) - try: - cr = ioctl_gwinsz(fd) - finally: - os.close(fd) - except Exception: - pass - if not cr or not cr[0] or not cr[1]: - cr = (os.environ.get("LINES", 25), os.environ.get("COLUMNS", DEFAULT_COLUMNS)) - return int(cr[1]), int(cr[0]) + warnings.warn( + "'click.get_terminal_size()' is deprecated and will be removed" + " in Click 8.1. Use 'shutil.get_terminal_size()' instead.", + DeprecationWarning, + stacklevel=2, + ) + return shutil.get_terminal_size() -def echo_via_pager(text_or_generator, color=None): +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: """This function takes a text and shows it via an environment specific pager on stdout. @@ -277,14 +288,14 @@ def echo_via_pager(text_or_generator, color=None): color = resolve_color_default(color) if inspect.isgeneratorfunction(text_or_generator): - i = text_or_generator() - elif isinstance(text_or_generator, string_types): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): i = [text_or_generator] else: - i = iter(text_or_generator) + i = iter(t.cast(t.Iterable[str], text_or_generator)) # convert every element of i to a text type if necessary - text_generator = (el if isinstance(el, string_types) else text_type(el) for el in i) + text_generator = (el if isinstance(el, str) else str(el) for el in i) from ._termui_impl import pager @@ -292,21 +303,22 @@ def echo_via_pager(text_or_generator, color=None): def progressbar( - iterable=None, - length=None, - label=None, - show_eta=True, - show_percent=None, - show_pos=False, - item_show_func=None, - fill_char="#", - empty_char="-", - bar_template="%(label)s [%(bar)s] %(info)s", - info_sep=" ", - width=36, - file=None, - color=None, -): + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": """This function creates an iterable context manager that can be used to iterate over something while showing a progress bar. It will either iterate over the `iterable` or `length` items (that are counted @@ -346,11 +358,19 @@ def progressbar( process_chunk(chunk) bar.update(chunks.bytes) - .. versionadded:: 2.0 + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: - .. versionadded:: 4.0 - Added the `color` parameter. Added a `update` method to the - progressbar object. + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) :param iterable: an iterable to iterate over. If not provided the length is required. @@ -369,10 +389,10 @@ def progressbar( `False` if not. :param show_pos: enables or disables the absolute position display. The default is `False`. - :param item_show_func: a function called with the current item which - can return a string to show the current item - next to the progress bar. Note that the current - item can be `None`! + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. :param fill_char: the character to use to show the filled part of the progress bar. :param empty_char: the character to use to show the non-filled part of @@ -384,12 +404,33 @@ def progressbar( :param info_sep: the separator between multiple info items (eta etc.) :param width: the width of the progress bar in characters, 0 means full terminal width - :param file: the file to write to. If this is not a terminal then - only the label is printed. + :param file: The file to write to. If this is not a terminal then + only the label is printed. :param color: controls if the terminal supports ANSI colors or not. The default is autodetection. This is only needed if ANSI codes are included anywhere in the progress bar output which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 """ from ._termui_impl import ProgressBar @@ -409,10 +450,11 @@ def progressbar( label=label, width=width, color=color, + update_min_steps=update_min_steps, ) -def clear(): +def clear() -> None: """Clears the terminal screen. This will have the effect of clearing the whole visible space of the terminal and moving the cursor to the top left. This does not do anything if not connected to a terminal. @@ -421,26 +463,39 @@ def clear(): """ if not isatty(sys.stdout): return - # If we're on Windows and we don't have colorama available, then we - # clear the screen by shelling out. Otherwise we can use an escape - # sequence. if WIN: os.system("cls") else: sys.stdout.write("\033[2J\033[1;1H") +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + def style( - text, - fg=None, - bg=None, - bold=None, - dim=None, - underline=None, - blink=None, - reverse=None, - reset=True, -): + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: """Styles a text with ANSI styles and returns the new string. By default the styling is self contained which means that at the end of the string a reset code is issued. This can be prevented by @@ -451,6 +506,7 @@ def style( click.echo(click.style('Hello World!', fg='green')) click.echo(click.style('ATTENTION!', blink=True)) click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) Supported color names: @@ -472,10 +528,15 @@ def style( * ``bright_white`` * ``reset`` (reset the color code only) - .. versionadded:: 2.0 + If the terminal supports it, color may also be specified as: - .. versionadded:: 7.0 - Added support for bright colors. + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. :param text: the string to style with ansi codes. :param fg: if provided this will become the foreground color. @@ -484,42 +545,73 @@ def style( :param dim: if provided this will enable or disable dim mode. This is badly supported. :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. :param blink: if provided this will enable or disable blinking. :param reverse: if provided this will enable or disable inverse rendering (foreground becomes background and the other way round). + :param strikethrough: if provided this will enable or disable + striking through text. :param reset: by default a reset-all code is added at the end of the string which means that styles do not carry over. This can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 """ + if not isinstance(text, str): + text = str(text) + bits = [] + if fg: try: - bits.append("\033[{}m".format(_ansi_colors[fg])) + bits.append(f"\033[{_interpret_color(fg)}m") except KeyError: - raise TypeError("Unknown color '{}'".format(fg)) + raise TypeError(f"Unknown color {fg!r}") + if bg: try: - bits.append("\033[{}m".format(_ansi_colors[bg] + 10)) + bits.append(f"\033[{_interpret_color(bg, 10)}m") except KeyError: - raise TypeError("Unknown color '{}'".format(bg)) + raise TypeError(f"Unknown color {bg!r}") + if bold is not None: - bits.append("\033[{}m".format(1 if bold else 22)) + bits.append(f"\033[{1 if bold else 22}m") if dim is not None: - bits.append("\033[{}m".format(2 if dim else 22)) + bits.append(f"\033[{2 if dim else 22}m") if underline is not None: - bits.append("\033[{}m".format(4 if underline else 24)) + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if underline else 55}m") + if italic is not None: + bits.append(f"\033[{5 if underline else 23}m") if blink is not None: - bits.append("\033[{}m".format(5 if blink else 25)) + bits.append(f"\033[{5 if blink else 25}m") if reverse is not None: - bits.append("\033[{}m".format(7 if reverse else 27)) + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") bits.append(text) if reset: bits.append(_ansi_reset_all) return "".join(bits) -def unstyle(text): +def unstyle(text: str) -> str: """Removes ANSI styling information from a string. Usually it's not necessary to use this function as Click's echo function will automatically remove styling if necessary. @@ -531,7 +623,14 @@ def unstyle(text): return strip_ansi(text) -def secho(message=None, file=None, nl=True, err=False, color=None, **styles): +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: """This function combines :func:`echo` and :func:`style` into one call. As such the following two calls are the same:: @@ -541,16 +640,31 @@ def secho(message=None, file=None, nl=True, err=False, color=None, **styles): All keyword arguments are forwarded to the underlying functions depending on which one they go with. + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + .. versionadded:: 2.0 """ - if message is not None: + if message is not None and not isinstance(message, (bytes, bytearray)): message = style(message, **styles) + return echo(message, file=file, nl=nl, err=err, color=color) def edit( - text=None, editor=None, env=None, require_save=True, extension=".txt", filename=None -): + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: r"""Edits the given text in the defined editor. If an editor is given (should be the full path to the executable but the regular operating system search path is used for finding the executable) it overrides @@ -580,15 +694,16 @@ def edit( """ from ._termui_impl import Editor - editor = Editor( - editor=editor, env=env, require_save=require_save, extension=extension - ) + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + if filename is None: - return editor.edit(text) - editor.edit_file(filename) + return ed.edit(text) + + ed.edit_file(filename) + return None -def launch(url, wait=False, locate=False): +def launch(url: str, wait: bool = False, locate: bool = False) -> int: """This function launches the given URL (or filename) in the default viewer application for this file type. If this is an executable, it might launch the executable in a new session. The return value is @@ -603,7 +718,9 @@ def launch(url, wait=False, locate=False): .. versionadded:: 2.0 :param url: URL or filename of the thing to launch. - :param wait: waits for the program to stop. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. :param locate: if this is set to `True` then instead of launching the application associated with the URL it will attempt to launch a file manager with the file located. This @@ -617,10 +734,10 @@ def launch(url, wait=False, locate=False): # If this is provided, getchar() calls into this instead. This is used # for unittesting purposes. -_getchar = None +_getchar: t.Optional[t.Callable[[bool], str]] = None -def getchar(echo=False): +def getchar(echo: bool = False) -> str: """Fetches a single character from the terminal and returns it. This will always return a unicode character and under certain rare circumstances this might return more than one character. The @@ -640,19 +757,23 @@ def getchar(echo=False): :param echo: if set to `True`, the character read will also show up on the terminal. The default is to not show it. """ - f = _getchar - if f is None: + global _getchar + + if _getchar is None: from ._termui_impl import getchar as f - return f(echo) + + _getchar = f + + return _getchar(echo) -def raw_terminal(): +def raw_terminal() -> t.ContextManager[int]: from ._termui_impl import raw_terminal as f return f() -def pause(info="Press any key to continue ...", err=False): +def pause(info: t.Optional[str] = None, err: bool = False) -> None: """This command stops execution and waits for the user to press any key to continue. This is similar to the Windows batch "pause" command. If the program is not run through a terminal, this command @@ -663,12 +784,17 @@ def pause(info="Press any key to continue ...", err=False): .. versionadded:: 4.0 Added the `err` parameter. - :param info: the info string to print before pausing. + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. :param err: if set to message goes to ``stderr`` instead of ``stdout``, the same as with echo. """ if not isatty(sys.stdin) or not isatty(sys.stdout): return + + if info is None: + info = _("Press any key to continue...") + try: if info: echo(info, nl=False, err=err) diff --git a/pipenv/vendor/click/testing.py b/pipenv/vendor/click/testing.py index a3dba3b3..d19b850f 100644 --- a/pipenv/vendor/click/testing.py +++ b/pipenv/vendor/click/testing.py @@ -1,77 +1,117 @@ import contextlib +import io import os import shlex import shutil import sys import tempfile +import typing as t +from types import TracebackType from . import formatting from . import termui from . import utils -from ._compat import iteritems -from ._compat import PY2 -from ._compat import string_types +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand -if PY2: - from cStringIO import StringIO -else: - import io - from ._compat import _find_binary_reader - - -class EchoingStdin(object): - def __init__(self, input, output): +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: self._input = input self._output = output + self._paused = False - def __getattr__(self, x): + def __getattr__(self, x: str) -> t.Any: return getattr(self._input, x) - def _echo(self, rv): - self._output.write(rv) + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + return rv - def read(self, n=-1): + def read(self, n: int = -1) -> bytes: return self._echo(self._input.read(n)) - def readline(self, n=-1): + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: return self._echo(self._input.readline(n)) - def readlines(self): + def readlines(self) -> t.List[bytes]: return [self._echo(x) for x in self._input.readlines()] - def __iter__(self): + def __iter__(self) -> t.Iterator[bytes]: return iter(self._echo(x) for x in self._input) - def __repr__(self): + def __repr__(self) -> str: return repr(self._input) -def make_input_stream(input, charset): +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO]], charset: str +) -> t.BinaryIO: # Is already an input stream. if hasattr(input, "read"): - if PY2: - return input - rv = _find_binary_reader(input) + rv = _find_binary_reader(t.cast(t.IO, input)) + if rv is not None: return rv + raise TypeError("Could not find binary reader for input stream.") if input is None: input = b"" - elif not isinstance(input, bytes): + elif isinstance(input, str): input = input.encode(charset) - if PY2: - return StringIO(input) - return io.BytesIO(input) + + return io.BytesIO(t.cast(bytes, input)) -class Result(object): +class Result: """Holds the captured result of an invoked CLI script.""" def __init__( - self, runner, stdout_bytes, stderr_bytes, exit_code, exception, exc_info=None + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, ): #: The runner that created the result self.runner = runner @@ -79,6 +119,10 @@ class Result(object): self.stdout_bytes = stdout_bytes #: The standard error as bytes, or None if not available self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value #: The exit code as integer. self.exit_code = exit_code #: The exception that happened if one did. @@ -87,19 +131,19 @@ class Result(object): self.exc_info = exc_info @property - def output(self): + def output(self) -> str: """The (standard) output as unicode string.""" return self.stdout @property - def stdout(self): + def stdout(self) -> str: """The standard output as unicode string.""" return self.stdout_bytes.decode(self.runner.charset, "replace").replace( "\r\n", "\n" ) @property - def stderr(self): + def stderr(self) -> str: """The standard error as unicode string.""" if self.stderr_bytes is None: raise ValueError("stderr not separately captured") @@ -107,21 +151,18 @@ class Result(object): "\r\n", "\n" ) - def __repr__(self): - return "<{} {}>".format( - type(self).__name__, repr(self.exception) if self.exception else "okay" - ) + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" -class CliRunner(object): +class CliRunner: """The CLI runner provides functionality to invoke a Click command line script for unittesting purposes in a isolated environment. This only works in single-threaded systems without any concurrency as it changes the global interpreter state. - :param charset: the character set for the input and output data. This is - UTF-8 by default and should not be changed currently as - the reporting to Click only works in Python 2 properly. + :param charset: the character set for the input and output data. :param env: a dictionary with environment variables for overriding. :param echo_stdin: if this is set to `True`, then reading from stdin writes to stdout. This is useful for showing examples in @@ -134,22 +175,28 @@ class CliRunner(object): independently """ - def __init__(self, charset=None, env=None, echo_stdin=False, mix_stderr=True): - if charset is None: - charset = "utf-8" + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: self.charset = charset self.env = env or {} self.echo_stdin = echo_stdin self.mix_stderr = mix_stderr - def get_default_prog_name(self, cli): + def get_default_prog_name(self, cli: "BaseCommand") -> str: """Given a command object it will return the default program name for it. The default is the `name` attribute or ``"root"`` if not set. """ return cli.name or "root" - def make_env(self, overrides=None): + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: """Returns the environment overrides for invoking a script.""" rv = dict(self.env) if overrides: @@ -157,7 +204,12 @@ class CliRunner(object): return rv @contextlib.contextmanager - def isolation(self, input=None, env=None, color=False): + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: """A context manager that sets up the isolation for invoking of a command line tool. This sets up stdin with the given input data and `os.environ` with the overrides from the given dictionary. @@ -166,15 +218,20 @@ class CliRunner(object): This is automatically done in the :meth:`invoke` method. - .. versionadded:: 4.0 - The ``color`` parameter was added. - :param input: the input stream to put into sys.stdin. :param env: the environment overrides as dictionary. :param color: whether the output should contain color codes. The application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. """ - input = make_input_stream(input, self.charset) + bytes_input = make_input_stream(input, self.charset) + echo_input = None old_stdin = sys.stdin old_stdout = sys.stdout @@ -184,51 +241,68 @@ class CliRunner(object): env = self.make_env(env) - if PY2: - bytes_output = StringIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - sys.stdout = bytes_output - if not self.mix_stderr: - bytes_error = StringIO() - sys.stderr = bytes_error - else: - bytes_output = io.BytesIO() - if self.echo_stdin: - input = EchoingStdin(input, bytes_output) - input = io.TextIOWrapper(input, encoding=self.charset) - sys.stdout = io.TextIOWrapper(bytes_output, encoding=self.charset) - if not self.mix_stderr: - bytes_error = io.BytesIO() - sys.stderr = io.TextIOWrapper(bytes_error, encoding=self.charset) + bytes_output = io.BytesIO() + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None if self.mix_stderr: sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) - sys.stdin = input - - def visible_input(prompt=None): + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: sys.stdout.write(prompt or "") - val = input.readline().rstrip("\r\n") - sys.stdout.write("{}\n".format(val)) + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") sys.stdout.flush() return val - def hidden_input(prompt=None): - sys.stdout.write("{}\n".format(prompt or "")) + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") sys.stdout.flush() - return input.readline().rstrip("\r\n") + return text_input.readline().rstrip("\r\n") - def _getchar(echo): + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: char = sys.stdin.read(1) + if echo: sys.stdout.write(char) - sys.stdout.flush() + + sys.stdout.flush() return char default_color = color - def should_strip_ansi(stream=None, color=None): + def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None + ) -> bool: if color is None: return not default_color return not color @@ -236,15 +310,15 @@ class CliRunner(object): old_visible_prompt_func = termui.visible_prompt_func old_hidden_prompt_func = termui.hidden_prompt_func old__getchar_func = termui._getchar - old_should_strip_ansi = utils.should_strip_ansi + old_should_strip_ansi = utils.should_strip_ansi # type: ignore termui.visible_prompt_func = visible_input termui.hidden_prompt_func = hidden_input termui._getchar = _getchar - utils.should_strip_ansi = should_strip_ansi + utils.should_strip_ansi = should_strip_ansi # type: ignore old_env = {} try: - for key, value in iteritems(env): + for key, value in env.items(): old_env[key] = os.environ.get(key) if value is None: try: @@ -253,9 +327,9 @@ class CliRunner(object): pass else: os.environ[key] = value - yield (bytes_output, not self.mix_stderr and bytes_error) + yield (bytes_output, bytes_error) finally: - for key, value in iteritems(old_env): + for key, value in old_env.items(): if value is None: try: del os.environ[key] @@ -269,19 +343,19 @@ class CliRunner(object): termui.visible_prompt_func = old_visible_prompt_func termui.hidden_prompt_func = old_hidden_prompt_func termui._getchar = old__getchar_func - utils.should_strip_ansi = old_should_strip_ansi + utils.should_strip_ansi = old_should_strip_ansi # type: ignore formatting.FORCED_WIDTH = old_forced_width def invoke( self, - cli, - args=None, - input=None, - env=None, - catch_exceptions=True, - color=False, - **extra - ): + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: """Invokes a command in an isolated environment. The arguments are forwarded directly to the command line script, the `extra` keyword arguments are passed to the :meth:`~clickpkg.Command.main` function of @@ -289,16 +363,6 @@ class CliRunner(object): This returns a :class:`Result` object. - .. versionadded:: 3.0 - The ``catch_exceptions`` parameter was added. - - .. versionchanged:: 3.0 - The result object now has an `exc_info` attribute with the - traceback if available. - - .. versionadded:: 4.0 - The ``color`` parameter was added. - :param cli: the command to invoke :param args: the arguments to invoke. It may be given as an iterable or a string. When given as string it will be interpreted @@ -311,13 +375,28 @@ class CliRunner(object): :param extra: the keyword arguments to pass to :meth:`main`. :param color: whether the output should contain color codes. The application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. """ exc_info = None with self.isolation(input=input, env=env, color=color) as outstreams: - exception = None + return_value = None + exception: t.Optional[BaseException] = None exit_code = 0 - if isinstance(args, string_types): + if isinstance(args, str): args = shlex.split(args) try: @@ -326,20 +405,23 @@ class CliRunner(object): prog_name = self.get_default_prog_name(cli) try: - cli.main(args=args or (), prog_name=prog_name, **extra) + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) except SystemExit as e: exc_info = sys.exc_info() - exit_code = e.code - if exit_code is None: - exit_code = 0 + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) - if exit_code != 0: + if e_code is None: + e_code = 0 + + if e_code != 0: exception = e - if not isinstance(exit_code, int): - sys.stdout.write(str(exit_code)) + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) sys.stdout.write("\n") - exit_code = 1 + e_code = 1 + + exit_code = e_code except Exception as e: if not catch_exceptions: @@ -353,30 +435,45 @@ class CliRunner(object): if self.mix_stderr: stderr = None else: - stderr = outstreams[1].getvalue() + stderr = outstreams[1].getvalue() # type: ignore return Result( runner=self, stdout_bytes=stdout, stderr_bytes=stderr, + return_value=return_value, exit_code=exit_code, exception=exception, - exc_info=exc_info, + exc_info=exc_info, # type: ignore ) @contextlib.contextmanager - def isolated_filesystem(self): - """A context manager that creates a temporary folder and changes - the current working directory to it for isolated filesystem tests. + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. """ cwd = os.getcwd() - t = tempfile.mkdtemp() + t = tempfile.mkdtemp(dir=temp_dir) os.chdir(t) + try: yield t finally: os.chdir(cwd) - try: - shutil.rmtree(t) - except (OSError, IOError): # noqa: B014 - pass + + if temp_dir is None: + try: + shutil.rmtree(t) + except OSError: # noqa: B014 + pass diff --git a/pipenv/vendor/click/types.py b/pipenv/vendor/click/types.py index 505c39f8..21f0e4f7 100644 --- a/pipenv/vendor/click/types.py +++ b/pipenv/vendor/click/types.py @@ -1,37 +1,47 @@ import os import stat +import typing as t from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext from ._compat import _get_argv_encoding -from ._compat import filename_to_ui from ._compat import get_filesystem_encoding -from ._compat import get_streerror from ._compat import open_stream -from ._compat import PY2 -from ._compat import text_type from .exceptions import BadParameter from .utils import LazyFile from .utils import safecall +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem -class ParamType(object): - """Helper for converting values through types. The following is - necessary for a valid type: - * it needs a name - * it needs to pass through None unchanged - * it needs to convert from a string - * it needs to convert its result type through unchanged - (eg: needs to be idempotent) - * it needs to be able to deal with param and context being `None`. - This can be the case when the object is used with prompt - inputs. +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. """ - is_composite = False + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 #: the descriptive name of this type - name = None + name: str #: if a list of this type is expected and the value is pulled from a #: string environment variable, this is what splits it up. `None` @@ -39,29 +49,66 @@ class ParamType(object): #: whitespace splits them up. The exception are paths and files which #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on #: Windows). - envvar_list_splitter = None + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None - def __call__(self, value, param=None, ctx=None): + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + return {"param_type": param_type, "name": self.name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: if value is not None: return self.convert(value, param, ctx) - def get_metavar(self, param): + def get_metavar(self, param: "Parameter") -> t.Optional[str]: """Returns the metavar default for this param if it provides one.""" - def get_missing_message(self, param): + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: """Optionally might return extra information about a missing parameter. .. versionadded:: 2.0 """ - def convert(self, value, param, ctx): - """Converts the value. This is not invoked for values that are - `None` (the missing value). + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. """ return value - def split_envvar_value(self, rv): + def split_envvar_value(self, rv: str) -> t.Sequence[str]: """Given a value from an environment variable this splits it up into small chunks depending on the defined envvar list splitter. @@ -71,49 +118,83 @@ class ParamType(object): """ return (rv or "").split(self.envvar_list_splitter) - def fail(self, message, param=None, ctx=None): + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": """Helper method to fail with an invalid value message.""" raise BadParameter(message, ctx=ctx, param=param) + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + class CompositeParamType(ParamType): is_composite = True @property - def arity(self): + def arity(self) -> int: # type: ignore raise NotImplementedError() class FuncParamType(ParamType): - def __init__(self, func): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: self.name = func.__name__ self.func = func - def convert(self, value, param, ctx): + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: try: return self.func(value) except ValueError: try: - value = text_type(value) + value = str(value) except UnicodeError: - value = str(value).decode("utf-8", "replace") + value = value.decode("utf-8", "replace") + self.fail(value, param, ctx) class UnprocessedParamType(ParamType): name = "text" - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: return value - def __repr__(self): + def __repr__(self) -> str: return "UNPROCESSED" class StringParamType(ParamType): name = "text" - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: if isinstance(value, bytes): enc = _get_argv_encoding() try: @@ -128,9 +209,9 @@ class StringParamType(ParamType): else: value = value.decode("utf-8", "replace") return value - return value + return str(value) - def __repr__(self): + def __repr__(self) -> str: return "STRING" @@ -153,17 +234,32 @@ class Choice(ParamType): name = "choice" - def __init__(self, choices, case_sensitive=True): + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: self.choices = choices self.case_sensitive = case_sensitive - def get_metavar(self, param): - return "[{}]".format("|".join(self.choices)) + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict - def get_missing_message(self, param): - return "Choose from:\n\t{}.".format(",\n\t".join(self.choices)) + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) - def convert(self, value, param, ctx): + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: # Match through normalization and case sensitivity # first do token_normalize_func, then lowercase # preserve original `value` to produce an accurate message in @@ -179,30 +275,51 @@ class Choice(ParamType): } if not self.case_sensitive: - if PY2: - lower = str.lower - else: - lower = str.casefold - - normed_value = lower(normed_value) + normed_value = normed_value.casefold() normed_choices = { - lower(normed_choice): original + normed_choice.casefold(): original for normed_choice, original in normed_choices.items() } if normed_value in normed_choices: return normed_choices[normed_value] + choices_str = ", ".join(map(repr, self.choices)) self.fail( - "invalid choice: {}. (choose from {})".format( - value, ", ".join(self.choices) - ), + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), param, ctx, ) - def __repr__(self): - return "Choice('{}')".format(list(self.choices)) + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] class DateTime(ParamType): @@ -228,212 +345,285 @@ class DateTime(ParamType): name = "datetime" - def __init__(self, formats=None): + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] - def get_metavar(self, param): - return "[{}]".format("|".join(self.formats)) + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict - def _try_to_convert_date(self, value, format): + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: try: return datetime.strptime(value, format) except ValueError: return None - def convert(self, value, param, ctx): - # Exact match - for format in self.formats: - dtime = self._try_to_convert_date(value, format) - if dtime: - return dtime + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) self.fail( - "invalid datetime format: {}. (choose from {})".format( - value, ", ".join(self.formats) - ) + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, ) - def __repr__(self): + def __repr__(self) -> str: return "DateTime" -class IntParamType(ParamType): - name = "integer" +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type] - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: try: - return int(value) + return self._number_class(value) except ValueError: - self.fail("{} is not a valid integer".format(value), param, ctx) + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) - def __repr__(self): + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: return "INT" -class IntRange(IntParamType): - """A parameter that works similar to :data:`click.INT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. - See :ref:`ranges` for an example. + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. """ name = "integer range" - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound - def convert(self, value, param, ctx): - rv = IntParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if ( - self.min is not None - and rv < self.min - or self.max is not None - and rv > self.max - ): - if self.min is None: - self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), - param, - ctx, - ) - elif self.max is None: - self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), - param, - ctx, - ) - else: - self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), - param, - ctx, - ) - return rv - - def __repr__(self): - return "IntRange({}, {})".format(self.min, self.max) + return bound + dir -class FloatParamType(ParamType): +class FloatParamType(_NumberParamTypeBase): name = "float" + _number_class = float - def convert(self, value, param, ctx): - try: - return float(value) - except ValueError: - self.fail( - "{} is not a valid floating point value".format(value), param, ctx - ) - - def __repr__(self): + def __repr__(self) -> str: return "FLOAT" -class FloatRange(FloatParamType): - """A parameter that works similar to :data:`click.FLOAT` but restricts - the value to fit into a range. The default behavior is to fail if the - value falls outside the range, but it can also be silently clamped - between the two edges. +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. - See :ref:`ranges` for an example. + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. """ name = "float range" - def __init__(self, min=None, max=None, clamp=False): - self.min = min - self.max = max - self.clamp = clamp + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) - def convert(self, value, param, ctx): - rv = FloatParamType.convert(self, value, param, ctx) - if self.clamp: - if self.min is not None and rv < self.min: - return self.min - if self.max is not None and rv > self.max: - return self.max - if ( - self.min is not None - and rv < self.min - or self.max is not None - and rv > self.max - ): - if self.min is None: - self.fail( - "{} is bigger than the maximum valid value {}.".format( - rv, self.max - ), - param, - ctx, - ) - elif self.max is None: - self.fail( - "{} is smaller than the minimum valid value {}.".format( - rv, self.min - ), - param, - ctx, - ) - else: - self.fail( - "{} is not in the valid range of {} to {}.".format( - rv, self.min, self.max - ), - param, - ctx, - ) - return rv + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") - def __repr__(self): - return "FloatRange({}, {})".format(self.min, self.max) + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") class BoolParamType(ParamType): name = "boolean" - def convert(self, value, param, ctx): - if isinstance(value, bool): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: return bool(value) - value = value.lower() - if value in ("true", "t", "1", "yes", "y"): - return True - elif value in ("false", "f", "0", "no", "n"): - return False - self.fail("{} is not a valid boolean".format(value), param, ctx) - def __repr__(self): + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: return "BOOL" class UUIDParameterType(ParamType): name = "uuid" - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: import uuid + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + try: - if PY2 and isinstance(value, text_type): - value = value.encode("ascii") return uuid.UUID(value) except ValueError: - self.fail("{} is not a valid UUID value".format(value), param, ctx) + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) - def __repr__(self): + def __repr__(self) -> str: return "UUID" @@ -468,15 +658,25 @@ class File(ParamType): envvar_list_splitter = os.path.pathsep def __init__( - self, mode="r", encoding=None, errors="strict", lazy=None, atomic=False - ): + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: self.mode = mode self.encoding = encoding self.errors = errors self.lazy = lazy self.atomic = atomic - def resolve_lazy_flag(self, value): + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: t.Any) -> bool: if self.lazy is not None: return self.lazy if value == "-": @@ -485,7 +685,9 @@ class File(ParamType): return True return False - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: try: if hasattr(value, "read") or hasattr(value, "write"): return value @@ -493,16 +695,22 @@ class File(ParamType): lazy = self.resolve_lazy_flag(value) if lazy: - f = LazyFile( - value, self.mode, self.encoding, self.errors, atomic=self.atomic + f: t.IO = t.cast( + t.IO, + LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ), ) + if ctx is not None: - ctx.call_on_close(f.close_intelligently) + ctx.call_on_close(f.close_intelligently) # type: ignore + return f f, should_close = open_stream( value, self.mode, self.encoding, self.errors, atomic=self.atomic ) + # If a context is provided, we automatically close the file # at the end of the context execution (or flush out). If a # context does not exist, it's the caller's responsibility to @@ -513,15 +721,26 @@ class File(ParamType): ctx.call_on_close(safecall(f.close)) else: ctx.call_on_close(safecall(f.flush)) + return f - except (IOError, OSError) as e: # noqa: B014 - self.fail( - "Could not open file: {}: {}".format( - filename_to_ui(value), get_streerror(e) - ), - param, - ctx, - ) + except OSError as e: # noqa: B014 + self.fail(f"{os.fsdecode(value)!r}: {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] class Path(ParamType): @@ -530,9 +749,6 @@ class Path(ParamType): handle it returns just the filename. Secondly, it can perform various basic checks about what the file or directory should be. - .. versionchanged:: 6.0 - `allow_dash` was added. - :param exists: if set to true, the file or directory needs to exist for this value to be valid. If this is not required and a file does indeed not exist, then all further checks are @@ -548,25 +764,29 @@ class Path(ParamType): supposed to be done by the shell only. :param allow_dash: If this is set to `True`, a single dash to indicate standard streams is permitted. - :param path_type: optionally a string type that should be used to - represent the path. The default is `None` which - means the return value will be either bytes or - unicode depending on what makes most sense given the - input data Click deals with. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.0 + Allow passing ``type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. """ envvar_list_splitter = os.path.pathsep def __init__( self, - exists=False, - file_okay=True, - dir_okay=True, - writable=False, - readable=True, - resolve_path=False, - allow_dash=False, - path_type=None, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type] = None, ): self.exists = exists self.file_okay = file_okay @@ -578,30 +798,48 @@ class Path(ParamType): self.type = path_type if self.file_okay and not self.dir_okay: - self.name = "file" - self.path_type = "File" + self.name = _("file") elif self.dir_okay and not self.file_okay: - self.name = "directory" - self.path_type = "Directory" + self.name = _("directory") else: - self.name = "path" - self.path_type = "Path" + self.name = _("path") - def coerce_path_result(self, rv): + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result(self, rv: t.Any) -> t.Any: if self.type is not None and not isinstance(rv, self.type): - if self.type is text_type: - rv = rv.decode(get_filesystem_encoding()) + if self.type is str: + rv = os.fsdecode(rv) + elif self.type is bytes: + rv = os.fsencode(rv) else: - rv = rv.encode(get_filesystem_encoding()) + rv = self.type(rv) + return rv - def convert(self, value, param, ctx): + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: rv = value is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") if not is_dash: if self.resolve_path: + # realpath on Windows Python < 3.8 doesn't resolve symlinks + if os.path.islink(rv): + rv = os.readlink(rv) + rv = os.path.realpath(rv) try: @@ -610,8 +848,8 @@ class Path(ParamType): if not self.exists: return self.coerce_path_result(rv) self.fail( - "{} '{}' does not exist.".format( - self.path_type, filename_to_ui(value) + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=os.fsdecode(value) ), param, ctx, @@ -619,30 +857,32 @@ class Path(ParamType): if not self.file_okay and stat.S_ISREG(st.st_mode): self.fail( - "{} '{}' is a file.".format(self.path_type, filename_to_ui(value)), + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), param, ctx, ) if not self.dir_okay and stat.S_ISDIR(st.st_mode): self.fail( - "{} '{}' is a directory.".format( - self.path_type, filename_to_ui(value) + _("{name} {filename!r} is a directory.").format( + name=self.name.title(), filename=os.fsdecode(value) ), param, ctx, ) if self.writable and not os.access(value, os.W_OK): self.fail( - "{} '{}' is not writable.".format( - self.path_type, filename_to_ui(value) + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=os.fsdecode(value) ), param, ctx, ) if self.readable and not os.access(value, os.R_OK): self.fail( - "{} '{}' is not readable.".format( - self.path_type, filename_to_ui(value) + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=os.fsdecode(value) ), param, ctx, @@ -650,6 +890,24 @@ class Path(ParamType): return self.coerce_path_result(rv) + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + class Tuple(CompositeParamType): """The default behavior of Click is to apply a type on a value directly. @@ -665,75 +923,107 @@ class Tuple(CompositeParamType): :param types: a list of types that should be used for the tuple items. """ - def __init__(self, types): + def __init__(self, types: t.Sequence[t.Union[t.Type, ParamType]]) -> None: self.types = [convert_type(ty) for ty in types] - @property - def name(self): - return "<{}>".format(" ".join(ty.name for ty in self.types)) + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict @property - def arity(self): + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore return len(self.types) - def convert(self, value, param, ctx): - if len(value) != len(self.types): - raise TypeError( - "It would appear that nargs is set to conflict with the" - " composite type arity." + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, ) + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) -def convert_type(ty, default=None): - """Converts a callable or python type into the most appropriate - param type. +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. """ guessed_type = False + if ty is None and default is not None: - if isinstance(default, tuple): - ty = tuple(map(type, default)) + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) else: ty = type(default) + guessed_type = True if isinstance(ty, tuple): return Tuple(ty) + if isinstance(ty, ParamType): return ty - if ty is text_type or ty is str or ty is None: + + if ty is str or ty is None: return STRING + if ty is int: return INT - # Booleans are only okay if not guessed. This is done because for - # flags the default value is actually a bit of a lie in that it - # indicates which of the flags is the one we want. See get_default() - # for more information. - if ty is bool and not guessed_type: - return BOOL + if ty is float: return FLOAT + + if ty is bool: + return BOOL + if guessed_type: return STRING - # Catch a common mistake if __debug__: try: if issubclass(ty, ParamType): raise AssertionError( - "Attempted to use an uninstantiated parameter type ({}).".format(ty) + f"Attempted to use an uninstantiated parameter type ({ty})." ) except TypeError: + # ty is an instance (correct), so issubclass fails. pass + return FuncParamType(ty) #: A dummy parameter type that just does nothing. From a user's -#: perspective this appears to just be the same as `STRING` but internally -#: no string conversion takes place. This is necessary to achieve the -#: same bytes/unicode behavior on Python 2/3 in situations where you want -#: to not convert argument types. This is usually useful when working -#: with file paths as they can appear in bytes and unicode. +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. #: #: For path related uses the :class:`Path` type is a better choice but #: there are situations where an unprocessed type is useful which is why diff --git a/pipenv/vendor/click/utils.py b/pipenv/vendor/click/utils.py index 79265e73..91a372d3 100644 --- a/pipenv/vendor/click/utils.py +++ b/pipenv/vendor/click/utils.py @@ -1,86 +1,105 @@ import os import sys +import typing as t +from functools import update_wrapper +from types import ModuleType from ._compat import _default_text_stderr from ._compat import _default_text_stdout +from ._compat import _find_binary_writer from ._compat import auto_wrap_for_ansi from ._compat import binary_streams -from ._compat import filename_to_ui from ._compat import get_filesystem_encoding -from ._compat import get_streerror -from ._compat import is_bytes from ._compat import open_stream -from ._compat import PY2 from ._compat import should_strip_ansi -from ._compat import string_types from ._compat import strip_ansi from ._compat import text_streams -from ._compat import text_type from ._compat import WIN from .globals import resolve_color_default -if not PY2: - from ._compat import _find_binary_writer -elif WIN: - from ._winconsole import _get_windows_argv - from ._winconsole import _hash_py_argv - from ._winconsole import _initial_argv_hash +if t.TYPE_CHECKING: + import typing_extensions as te -echo_native_types = string_types + (bytes, bytearray) +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) -def _posixify(name): +def _posixify(name: str) -> str: return "-".join(name.split()).lower() -def safecall(func): +def safecall(func: F) -> F: """Wraps a function so that it swallows exceptions.""" - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs): # type: ignore try: return func(*args, **kwargs) except Exception: pass - return wrapper + return update_wrapper(t.cast(F, wrapper), func) -def make_str(value): +def make_str(value: t.Any) -> str: """Converts a value into a valid string.""" if isinstance(value, bytes): try: return value.decode(get_filesystem_encoding()) except UnicodeError: return value.decode("utf-8", "replace") - return text_type(value) + return str(value) -def make_default_short_help(help, max_length=45): - """Return a condensed version of help string.""" +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + total_length = 0 - result = [] - done = False + last_index = len(words) - 1 - for word in words: - if word[-1:] == ".": - done = True - new_length = 1 + len(word) if result else len(word) - if total_length + new_length > max_length: - result.append("...") - done = True - else: - if result: - result.append(" ") - result.append(word) - if done: + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate break - total_length += new_length - return "".join(result) + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." -class LazyFile(object): +class LazyFile: """A lazy file works like a regular file but it does not fully open the file but it does perform some basic checks early to see if the filename parameter does make sense. This is useful for safely opening @@ -88,13 +107,19 @@ class LazyFile(object): """ def __init__( - self, filename, mode="r", encoding=None, errors="strict", atomic=False + self, + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, ): self.name = filename self.mode = mode self.encoding = encoding self.errors = errors self.atomic = atomic + self._f: t.Optional[t.IO] if filename == "-": self._f, self.should_close = open_stream(filename, mode, encoding, errors) @@ -107,15 +132,15 @@ class LazyFile(object): self._f = None self.should_close = True - def __getattr__(self, name): + def __getattr__(self, name: str) -> t.Any: return getattr(self.open(), name) - def __repr__(self): + def __repr__(self) -> str: if self._f is not None: return repr(self._f) - return "".format(self.name, self.mode) + return f"" - def open(self): + def open(self) -> t.IO: """Opens the file if it's not yet open. This call might fail with a :exc:`FileError`. Not handling this error will produce an error that Click shows. @@ -126,102 +151,100 @@ class LazyFile(object): rv, self.should_close = open_stream( self.name, self.mode, self.encoding, self.errors, atomic=self.atomic ) - except (IOError, OSError) as e: # noqa: E402 + except OSError as e: # noqa: E402 from .exceptions import FileError - raise FileError(self.name, hint=get_streerror(e)) + raise FileError(self.name, hint=e.strerror) self._f = rv return rv - def close(self): + def close(self) -> None: """Closes the underlying file, no matter what.""" if self._f is not None: self._f.close() - def close_intelligently(self): + def close_intelligently(self) -> None: """This function only closes the file if it was opened by the lazy file wrapper. For instance this will never close stdin. """ if self.should_close: self.close() - def __enter__(self): + def __enter__(self) -> "LazyFile": return self - def __exit__(self, exc_type, exc_value, tb): + def __exit__(self, exc_type, exc_value, tb): # type: ignore self.close_intelligently() - def __iter__(self): + def __iter__(self) -> t.Iterator[t.AnyStr]: self.open() - return iter(self._f) + return iter(self._f) # type: ignore -class KeepOpenFile(object): - def __init__(self, file): +class KeepOpenFile: + def __init__(self, file: t.IO) -> None: self._file = file - def __getattr__(self, name): + def __getattr__(self, name: str) -> t.Any: return getattr(self._file, name) - def __enter__(self): + def __enter__(self) -> "KeepOpenFile": return self - def __exit__(self, exc_type, exc_value, tb): + def __exit__(self, exc_type, exc_value, tb): # type: ignore pass - def __repr__(self): + def __repr__(self) -> str: return repr(self._file) - def __iter__(self): + def __iter__(self) -> t.Iterator[t.AnyStr]: return iter(self._file) -def echo(message=None, file=None, nl=True, err=False, color=None): - """Prints a message plus a newline to the given file or stdout. On - first sight, this looks like the print function, but it has improved - support for handling Unicode and binary data that does not fail no - matter how badly configured the system is. +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. - Primarily it means that you can print binary data as well as Unicode - data on both 2.x and 3.x to the given file in the most appropriate way - possible. This is a very carefree function in that it will try its - best to not fail. As of Click 6.0 this includes support for unicode - output on the Windows console. + Compared to :func:`print`, this does the following: - In addition to that, if `colorama`_ is installed, the echo function will - also support clever handling of ANSI codes. Essentially it will then - do the following: + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. - - add transparent handling of ANSI color codes on Windows. - - hide ANSI codes automatically if the destination file is not a - terminal. - - .. _colorama: https://pypi.org/project/colorama/ + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. .. versionchanged:: 6.0 - As of Click 6.0 the echo function will properly support unicode - output on the windows console. Not that click does not modify - the interpreter in any way which means that `sys.stdout` or the - print statement or function will still not provide unicode support. - - .. versionchanged:: 2.0 - Starting with version 2.0 of Click, the echo function will work - with colorama if it's installed. - - .. versionadded:: 3.0 - The `err` parameter was added. + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. .. versionchanged:: 4.0 - Added the `color` flag. + Added the ``color`` parameter. - :param message: the message to print - :param file: the file to write to (defaults to ``stdout``) - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``. This is faster and easier than calling - :func:`get_text_stderr` yourself. - :param nl: if set to `True` (the default) a newline is printed afterwards. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. """ if file is None: if err: @@ -230,70 +253,73 @@ def echo(message=None, file=None, nl=True, err=False, color=None): file = _default_text_stdout() # Convert non bytes/text into the native string type. - if message is not None and not isinstance(message, echo_native_types): - message = text_type(message) + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message if nl: - message = message or u"" - if isinstance(message, text_type): - message += u"\n" + out = out or "" + if isinstance(out, str): + out += "\n" else: - message += b"\n" + out += b"\n" - # If there is a message, and we're in Python 3, and the value looks - # like bytes, we manually need to find the binary stream and write the - # message in there. This is done separately so that most stream - # types will work as you would expect. Eg: you can write to StringIO - # for other cases. - if message and not PY2 and is_bytes(message): + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): binary_file = _find_binary_writer(file) + if binary_file is not None: file.flush() - binary_file.write(message) + binary_file.write(out) binary_file.flush() return - # ANSI-style support. If there is no message or we are dealing with - # bytes nothing is happening. If we are connected to a file we want - # to strip colors. If we are on windows we either wrap the stream - # to strip the color or we use the colorama support to translate the - # ansi codes to API calls. - if message and not is_bytes(message): + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: color = resolve_color_default(color) + if should_strip_ansi(file, color): - message = strip_ansi(message) + out = strip_ansi(out) elif WIN: if auto_wrap_for_ansi is not None: - file = auto_wrap_for_ansi(file) + file = auto_wrap_for_ansi(file) # type: ignore elif not color: - message = strip_ansi(message) + out = strip_ansi(out) - if message: - file.write(message) + file.write(out) # type: ignore file.flush() -def get_binary_stream(name): - """Returns a system stream for byte processing. This essentially - returns the stream from the sys module with the given name but it - solves some compatibility issues between different Python versions. - Primarily this function is necessary for getting binary streams on - Python 3. +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. :param name: the name of the stream to open. Valid names are ``'stdin'``, ``'stdout'`` and ``'stderr'`` """ opener = binary_streams.get(name) if opener is None: - raise TypeError("Unknown standard stream '{}'".format(name)) + raise TypeError(f"Unknown standard stream '{name}'") return opener() -def get_text_stream(name, encoding=None, errors="strict"): +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: """Returns a system stream for text processing. This usually returns a wrapped stream around a binary stream returned from - :func:`get_binary_stream` but it also can take shortcuts on Python 3 - for already correctly configured streams. + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. :param name: the name of the stream to open. Valid names are ``'stdin'``, ``'stdout'`` and ``'stderr'`` @@ -302,13 +328,18 @@ def get_text_stream(name, encoding=None, errors="strict"): """ opener = text_streams.get(name) if opener is None: - raise TypeError("Unknown standard stream '{}'".format(name)) + raise TypeError(f"Unknown standard stream '{name}'") return opener(encoding, errors) def open_file( - filename, mode="r", encoding=None, errors="strict", lazy=False, atomic=False -): + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO: """This is similar to how the :class:`File` works but for manual usage. Files are opened non lazy by default. This can open regular files as well as stdin/stdout if ``'-'`` is passed. @@ -332,35 +363,35 @@ def open_file( moved on close. """ if lazy: - return LazyFile(filename, mode, encoding, errors, atomic=atomic) + return t.cast(t.IO, LazyFile(filename, mode, encoding, errors, atomic=atomic)) f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) if not should_close: - f = KeepOpenFile(f) + f = t.cast(t.IO, KeepOpenFile(f)) return f -def get_os_args(): - """This returns the argument part of sys.argv in the most appropriate - form for processing. What this means is that this return value is in - a format that works for Click to process but does not necessarily - correspond well to what's actually standard for the interpreter. +def get_os_args() -> t.Sequence[str]: + """Returns the argument part of ``sys.argv``, removing the first + value which is the name of the script. - On most environments the return value is ``sys.argv[:1]`` unchanged. - However if you are on Windows and running Python 2 the return value - will actually be a list of unicode strings instead because the - default behavior on that platform otherwise will not be able to - carry all possible values that sys.argv can have. - - .. versionadded:: 6.0 + .. deprecated:: 8.0 + Will be removed in Click 8.1. Access ``sys.argv[1:]`` directly + instead. """ - # We can only extract the unicode argv if sys.argv has not been - # changed since the startup of the application. - if PY2 and WIN and _initial_argv_hash == _hash_py_argv(): - return _get_windows_argv() + import warnings + + warnings.warn( + "'get_os_args' is deprecated and will be removed in Click 8.1." + " Access 'sys.argv[1:]' directly instead.", + DeprecationWarning, + stacklevel=2, + ) return sys.argv[1:] -def format_filename(filename, shorten=False): +def format_filename( + filename: t.Union[str, bytes, os.PathLike], shorten: bool = False +) -> str: """Formats a filename for user display. The main purpose of this function is to ensure that the filename can be displayed at all. This will decode the filename to unicode if necessary in a way that it will @@ -374,10 +405,11 @@ def format_filename(filename, shorten=False): """ if shorten: filename = os.path.basename(filename) - return filename_to_ui(filename) + + return os.fsdecode(filename) -def get_app_dir(app_name, roaming=True, force_posix=False): +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: r"""Returns the config folder for the application. The default behavior is to return whatever is most appropriate for the operating system. @@ -392,13 +424,9 @@ def get_app_dir(app_name, roaming=True, force_posix=False): ``~/.config/foo-bar`` Unix (POSIX): ``~/.foo-bar`` - Win XP (roaming): - ``C:\Documents and Settings\\Local Settings\Application Data\Foo Bar`` - Win XP (not roaming): - ``C:\Documents and Settings\\Application Data\Foo Bar`` - Win 7 (roaming): + Windows (roaming): ``C:\Users\\AppData\Roaming\Foo Bar`` - Win 7 (not roaming): + Windows (not roaming): ``C:\Users\\AppData\Local\Foo Bar`` .. versionadded:: 2.0 @@ -419,7 +447,7 @@ def get_app_dir(app_name, roaming=True, force_posix=False): folder = os.path.expanduser("~") return os.path.join(folder, app_name) if force_posix: - return os.path.join(os.path.expanduser("~/.{}".format(_posixify(app_name)))) + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) if sys.platform == "darwin": return os.path.join( os.path.expanduser("~/Library/Application Support"), app_name @@ -430,7 +458,7 @@ def get_app_dir(app_name, roaming=True, force_posix=False): ) -class PacifyFlushWrapper(object): +class PacifyFlushWrapper: """This wrapper is used to catch and suppress BrokenPipeErrors resulting from ``.flush()`` being called on broken pipe during the shutdown/final-GC of the Python interpreter. Notably ``.flush()`` is always called on @@ -439,17 +467,113 @@ class PacifyFlushWrapper(object): pipe, all calls and attributes are proxied. """ - def __init__(self, wrapped): + def __init__(self, wrapped: t.IO) -> None: self.wrapped = wrapped - def flush(self): + def flush(self) -> None: try: self.wrapped.flush() - except IOError as e: + except OSError as e: import errno if e.errno != errno.EPIPE: raise - def __getattr__(self, attr): + def __getattr__(self, attr: str) -> t.Any: return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: ModuleType = sys.modules["__main__"] +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + if getattr(_main, "__package__", None) is None or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + matches = glob(arg, recursive=glob_recursive) + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/pipenv/vendor/contextlib2.py b/pipenv/vendor/contextlib2.py deleted file mode 100644 index 3aae8f41..00000000 --- a/pipenv/vendor/contextlib2.py +++ /dev/null @@ -1,518 +0,0 @@ -"""contextlib2 - backports and enhancements to the contextlib module""" - -import abc -import sys -import warnings -from collections import deque -from functools import wraps - -__all__ = ["contextmanager", "closing", "nullcontext", - "AbstractContextManager", - "ContextDecorator", "ExitStack", - "redirect_stdout", "redirect_stderr", "suppress"] - -# Backwards compatibility -__all__ += ["ContextStack"] - - -# Backport abc.ABC -if sys.version_info[:2] >= (3, 4): - _abc_ABC = abc.ABC -else: - _abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) - - -# Backport classic class MRO -def _classic_mro(C, result): - if C in result: - return - result.append(C) - for B in C.__bases__: - _classic_mro(B, result) - return result - - -# Backport _collections_abc._check_methods -def _check_methods(C, *methods): - try: - mro = C.__mro__ - except AttributeError: - mro = tuple(_classic_mro(C, [])) - - for method in methods: - for B in mro: - if method in B.__dict__: - if B.__dict__[method] is None: - return NotImplemented - break - else: - return NotImplemented - return True - - -class AbstractContextManager(_abc_ABC): - """An abstract base class for context managers.""" - - def __enter__(self): - """Return `self` upon entering the runtime context.""" - return self - - @abc.abstractmethod - def __exit__(self, exc_type, exc_value, traceback): - """Raise any exception triggered within the runtime context.""" - return None - - @classmethod - def __subclasshook__(cls, C): - """Check whether subclass is considered a subclass of this ABC.""" - if cls is AbstractContextManager: - return _check_methods(C, "__enter__", "__exit__") - return NotImplemented - - -class ContextDecorator(object): - """A base class or mixin that enables context managers to work as decorators.""" - - def refresh_cm(self): - """Returns the context manager used to actually wrap the call to the - decorated function. - - The default implementation just returns *self*. - - Overriding this method allows otherwise one-shot context managers - like _GeneratorContextManager to support use as decorators via - implicit recreation. - - DEPRECATED: refresh_cm was never added to the standard library's - ContextDecorator API - """ - warnings.warn("refresh_cm was never added to the standard library", - DeprecationWarning) - return self._recreate_cm() - - def _recreate_cm(self): - """Return a recreated instance of self. - - Allows an otherwise one-shot context manager like - _GeneratorContextManager to support use as - a decorator via implicit recreation. - - This is a private interface just for _GeneratorContextManager. - See issue #11647 for details. - """ - return self - - def __call__(self, func): - @wraps(func) - def inner(*args, **kwds): - with self._recreate_cm(): - return func(*args, **kwds) - return inner - - -class _GeneratorContextManager(ContextDecorator): - """Helper for @contextmanager decorator.""" - - def __init__(self, func, args, kwds): - self.gen = func(*args, **kwds) - self.func, self.args, self.kwds = func, args, kwds - # Issue 19330: ensure context manager instances have good docstrings - doc = getattr(func, "__doc__", None) - if doc is None: - doc = type(self).__doc__ - self.__doc__ = doc - # Unfortunately, this still doesn't provide good help output when - # inspecting the created context manager instances, since pydoc - # currently bypasses the instance docstring and shows the docstring - # for the class instead. - # See http://bugs.python.org/issue19404 for more details. - - def _recreate_cm(self): - # _GCM instances are one-shot context managers, so the - # CM must be recreated each time a decorated function is - # called - return self.__class__(self.func, self.args, self.kwds) - - def __enter__(self): - try: - return next(self.gen) - except StopIteration: - raise RuntimeError("generator didn't yield") - - def __exit__(self, type, value, traceback): - if type is None: - try: - next(self.gen) - except StopIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - if value is None: - # Need to force instantiation so we can reliably - # tell if we get the same exception back - value = type() - try: - self.gen.throw(type, value, traceback) - raise RuntimeError("generator didn't stop after throw()") - except StopIteration as exc: - # Suppress StopIteration *unless* it's the same exception that - # was passed to throw(). This prevents a StopIteration - # raised inside the "with" statement from being suppressed. - return exc is not value - except RuntimeError as exc: - # Don't re-raise the passed in exception - if exc is value: - return False - # Likewise, avoid suppressing if a StopIteration exception - # was passed to throw() and later wrapped into a RuntimeError - # (see PEP 479). - if _HAVE_EXCEPTION_CHAINING and exc.__cause__ is value: - return False - raise - except: - # only re-raise if it's *not* the exception that was - # passed to throw(), because __exit__() must not raise - # an exception unless __exit__() itself failed. But throw() - # has to raise the exception to signal propagation, so this - # fixes the impedance mismatch between the throw() protocol - # and the __exit__() protocol. - # - if sys.exc_info()[1] is not value: - raise - - -def contextmanager(func): - """@contextmanager decorator. - - Typical usage: - - @contextmanager - def some_generator(): - - try: - yield - finally: - - - This makes this: - - with some_generator() as : - - - equivalent to this: - - - try: - = - - finally: - - - """ - @wraps(func) - def helper(*args, **kwds): - return _GeneratorContextManager(func, args, kwds) - return helper - - -class closing(object): - """Context to automatically close something at the end of a block. - - Code like this: - - with closing(.open()) as f: - - - is equivalent to this: - - f = .open() - try: - - finally: - f.close() - - """ - def __init__(self, thing): - self.thing = thing - - def __enter__(self): - return self.thing - - def __exit__(self, *exc_info): - self.thing.close() - - -class _RedirectStream(object): - - _stream = None - - def __init__(self, new_target): - self._new_target = new_target - # We use a list of old targets to make this CM re-entrant - self._old_targets = [] - - def __enter__(self): - self._old_targets.append(getattr(sys, self._stream)) - setattr(sys, self._stream, self._new_target) - return self._new_target - - def __exit__(self, exctype, excinst, exctb): - setattr(sys, self._stream, self._old_targets.pop()) - - -class redirect_stdout(_RedirectStream): - """Context manager for temporarily redirecting stdout to another file. - - # How to send help() to stderr - with redirect_stdout(sys.stderr): - help(dir) - - # How to write help() to a file - with open('help.txt', 'w') as f: - with redirect_stdout(f): - help(pow) - """ - - _stream = "stdout" - - -class redirect_stderr(_RedirectStream): - """Context manager for temporarily redirecting stderr to another file.""" - - _stream = "stderr" - - -class suppress(object): - """Context manager to suppress specified exceptions - - After the exception is suppressed, execution proceeds with the next - statement following the with statement. - - with suppress(FileNotFoundError): - os.remove(somefile) - # Execution still resumes here if the file was already removed - """ - - def __init__(self, *exceptions): - self._exceptions = exceptions - - def __enter__(self): - pass - - def __exit__(self, exctype, excinst, exctb): - # Unlike isinstance and issubclass, CPython exception handling - # currently only looks at the concrete type hierarchy (ignoring - # the instance and subclass checking hooks). While Guido considers - # that a bug rather than a feature, it's a fairly hard one to fix - # due to various internal implementation details. suppress provides - # the simpler issubclass based semantics, rather than trying to - # exactly reproduce the limitations of the CPython interpreter. - # - # See http://bugs.python.org/issue12029 for more details - return exctype is not None and issubclass(exctype, self._exceptions) - - -# Context manipulation is Python 3 only -_HAVE_EXCEPTION_CHAINING = sys.version_info[0] >= 3 -if _HAVE_EXCEPTION_CHAINING: - def _make_context_fixer(frame_exc): - def _fix_exception_context(new_exc, old_exc): - # Context may not be correct, so find the end of the chain - while 1: - exc_context = new_exc.__context__ - if exc_context is old_exc: - # Context is already set correctly (see issue 20317) - return - if exc_context is None or exc_context is frame_exc: - break - new_exc = exc_context - # Change the end of the chain to point to the exception - # we expect it to reference - new_exc.__context__ = old_exc - return _fix_exception_context - - def _reraise_with_existing_context(exc_details): - try: - # bare "raise exc_details[1]" replaces our carefully - # set-up context - fixed_ctx = exc_details[1].__context__ - raise exc_details[1] - except BaseException: - exc_details[1].__context__ = fixed_ctx - raise -else: - # No exception context in Python 2 - def _make_context_fixer(frame_exc): - return lambda new_exc, old_exc: None - - # Use 3 argument raise in Python 2, - # but use exec to avoid SyntaxError in Python 3 - def _reraise_with_existing_context(exc_details): - exc_type, exc_value, exc_tb = exc_details - exec("raise exc_type, exc_value, exc_tb") - -# Handle old-style classes if they exist -try: - from types import InstanceType -except ImportError: - # Python 3 doesn't have old-style classes - _get_type = type -else: - # Need to handle old-style context managers on Python 2 - def _get_type(obj): - obj_type = type(obj) - if obj_type is InstanceType: - return obj.__class__ # Old-style class - return obj_type # New-style class - - -# Inspired by discussions on http://bugs.python.org/issue13585 -class ExitStack(object): - """Context manager for dynamic management of a stack of exit callbacks - - For example: - - with ExitStack() as stack: - files = [stack.enter_context(open(fname)) for fname in filenames] - # All opened files will automatically be closed at the end of - # the with statement, even if attempts to open files later - # in the list raise an exception - - """ - def __init__(self): - self._exit_callbacks = deque() - - def pop_all(self): - """Preserve the context stack by transferring it to a new instance""" - new_stack = type(self)() - new_stack._exit_callbacks = self._exit_callbacks - self._exit_callbacks = deque() - return new_stack - - def _push_cm_exit(self, cm, cm_exit): - """Helper to correctly register callbacks to __exit__ methods""" - def _exit_wrapper(*exc_details): - return cm_exit(cm, *exc_details) - _exit_wrapper.__self__ = cm - self.push(_exit_wrapper) - - def push(self, exit): - """Registers a callback with the standard __exit__ method signature - - Can suppress exceptions the same way __exit__ methods can. - - Also accepts any object with an __exit__ method (registering a call - to the method instead of the object itself) - """ - # We use an unbound method rather than a bound method to follow - # the standard lookup behaviour for special methods - _cb_type = _get_type(exit) - try: - exit_method = _cb_type.__exit__ - except AttributeError: - # Not a context manager, so assume its a callable - self._exit_callbacks.append(exit) - else: - self._push_cm_exit(exit, exit_method) - return exit # Allow use as a decorator - - def callback(self, callback, *args, **kwds): - """Registers an arbitrary callback and arguments. - - Cannot suppress exceptions. - """ - def _exit_wrapper(exc_type, exc, tb): - callback(*args, **kwds) - # We changed the signature, so using @wraps is not appropriate, but - # setting __wrapped__ may still help with introspection - _exit_wrapper.__wrapped__ = callback - self.push(_exit_wrapper) - return callback # Allow use as a decorator - - def enter_context(self, cm): - """Enters the supplied context manager - - If successful, also pushes its __exit__ method as a callback and - returns the result of the __enter__ method. - """ - # We look up the special methods on the type to match the with statement - _cm_type = _get_type(cm) - _exit = _cm_type.__exit__ - result = _cm_type.__enter__(cm) - self._push_cm_exit(cm, _exit) - return result - - def close(self): - """Immediately unwind the context stack""" - self.__exit__(None, None, None) - - def __enter__(self): - return self - - def __exit__(self, *exc_details): - received_exc = exc_details[0] is not None - - # We manipulate the exception state so it behaves as though - # we were actually nesting multiple with statements - frame_exc = sys.exc_info()[1] - _fix_exception_context = _make_context_fixer(frame_exc) - - # Callbacks are invoked in LIFO order to match the behaviour of - # nested context managers - suppressed_exc = False - pending_raise = False - while self._exit_callbacks: - cb = self._exit_callbacks.pop() - try: - if cb(*exc_details): - suppressed_exc = True - pending_raise = False - exc_details = (None, None, None) - except: - new_exc_details = sys.exc_info() - # simulate the stack of exceptions by setting the context - _fix_exception_context(new_exc_details[1], exc_details[1]) - pending_raise = True - exc_details = new_exc_details - if pending_raise: - _reraise_with_existing_context(exc_details) - return received_exc and suppressed_exc - - -# Preserve backwards compatibility -class ContextStack(ExitStack): - """Backwards compatibility alias for ExitStack""" - - def __init__(self): - warnings.warn("ContextStack has been renamed to ExitStack", - DeprecationWarning) - super(ContextStack, self).__init__() - - def register_exit(self, callback): - return self.push(callback) - - def register(self, callback, *args, **kwds): - return self.callback(callback, *args, **kwds) - - def preserve(self): - return self.pop_all() - - -class nullcontext(AbstractContextManager): - """Context manager that does no additional processing. - Used as a stand-in for a normal context manager, when a particular - block of code is only sometimes used with a normal context manager: - cm = optional_cm if condition else nullcontext() - with cm: - # Perform operation, using optional_cm if condition is True - """ - - def __init__(self, enter_result=None): - self.enter_result = enter_result - - def __enter__(self): - return self.enter_result - - def __exit__(self, *excinfo): - pass diff --git a/pipenv/vendor/contextlib2/LICENSE.txt b/pipenv/vendor/contextlib2/LICENSE.txt new file mode 100644 index 00000000..e40caa18 --- /dev/null +++ b/pipenv/vendor/contextlib2/LICENSE.txt @@ -0,0 +1,124 @@ +Note: The type hints included in this package come from the typeshed project, +and are hence distributed under the Apache License 2.0 rather than under the +Python Software License that covers the module implementation and test suite. + +A. HISTORY OF THE SOFTWARE +========================== + +contextlib2 is a derivative of the contextlib module distributed by the PSF +as part of the Python standard library. According, it is itself redistributed +under the PSF license (reproduced in full below). As the contextlib module +was added only in Python 2.5, the licenses for earlier Python versions are +not applicable and have not been included. + +Python was created in the early 1990s by Guido van Rossum at Stichting +Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands +as a successor of a language called ABC. Guido remains Python's +principal author, although it includes many contributions from others. + +In 1995, Guido continued his work on Python at the Corporation for +National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) +in Reston, Virginia where he released several versions of the +software. + +In May 2000, Guido and the Python core development team moved to +BeOpen.com to form the BeOpen PythonLabs team. In October of the same +year, the PythonLabs team moved to Digital Creations (now Zope +Corporation, see http://www.zope.com). In 2001, the Python Software +Foundation (PSF, see http://www.python.org/psf/) was formed, a +non-profit organization created specifically to own Python-related +Intellectual Property. Zope Corporation is a sponsoring member of +the PSF. + +All Python releases are Open Source (see http://www.opensource.org for +the Open Source Definition). Historically, most, but not all, Python +releases have also been GPL-compatible; the table below summarizes +the various releases that included the contextlib module. + + Release Derived Year Owner GPL- + from compatible? (1) + + 2.5 2.4 2006 PSF yes + 2.5.1 2.5 2007 PSF yes + 2.5.2 2.5.1 2008 PSF yes + 2.5.3 2.5.2 2008 PSF yes + 2.6 2.5 2008 PSF yes + 2.6.1 2.6 2008 PSF yes + 2.6.2 2.6.1 2009 PSF yes + 2.6.3 2.6.2 2009 PSF yes + 2.6.4 2.6.3 2009 PSF yes + 2.6.5 2.6.4 2010 PSF yes + 3.0 2.6 2008 PSF yes + 3.0.1 3.0 2009 PSF yes + 3.1 3.0.1 2009 PSF yes + 3.1.1 3.1 2009 PSF yes + 3.1.2 3.1.1 2010 PSF yes + 3.1.3 3.1.2 2010 PSF yes + 3.1.4 3.1.3 2011 PSF yes + 3.2 3.1 2011 PSF yes + 3.2.1 3.2 2011 PSF yes + 3.2.2 3.2.1 2011 PSF yes + 3.3 3.2 2012 PSF yes + +Footnotes: + +(1) GPL-compatible doesn't mean that we're distributing Python under + the GPL. All Python licenses, unlike the GPL, let you distribute + a modified version without making your changes open source. The + GPL-compatible licenses make it possible to combine Python with + other software that is released under the GPL; the others don't. + +Thanks to the many outside volunteers who have worked under Guido's +direction to make these releases possible. + + +B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON +=============================================================== + +PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 +-------------------------------------------- + +1. This LICENSE AGREEMENT is between the Python Software Foundation +("PSF"), and the Individual or Organization ("Licensee") accessing and +otherwise using this software ("Python") in source or binary form and +its associated documentation. + +2. Subject to the terms and conditions of this License Agreement, PSF hereby +grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, +analyze, test, perform and/or display publicly, prepare derivative works, +distribute, and otherwise use Python alone or in any derivative version, +provided, however, that PSF's License Agreement and PSF's notice of copyright, +i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +2011 Python Software Foundation; All Rights Reserved" are retained in Python +alone or in any derivative version prepared by Licensee. + +3. In the event Licensee prepares a derivative work that is based on +or incorporates Python or any part thereof, and wants to make +the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to Python. + +4. PSF is making Python available to Licensee on an "AS IS" +basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT +INFRINGE ANY THIRD PARTY RIGHTS. + +5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON +FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS +A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, +OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between PSF and +Licensee. This License Agreement does not grant permission to use PSF +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using Python, Licensee +agrees to be bound by the terms and conditions of this License +Agreement. diff --git a/pipenv/vendor/contextlib2/__init__.py b/pipenv/vendor/contextlib2/__init__.py new file mode 100644 index 00000000..d6c0c4ac --- /dev/null +++ b/pipenv/vendor/contextlib2/__init__.py @@ -0,0 +1,798 @@ +"""contextlib2 - backports and enhancements to the contextlib module""" + +import abc +import sys +import warnings +import _collections_abc +from collections import deque +from functools import wraps +from types import MethodType + +# Python 3.6/3.7/3.8 compatibility: GenericAlias may not be defined +try: + from types import GenericAlias +except ImportError: + # If the real GenericAlias type doesn't exist, __class_getitem__ won't be used, + # so the fallback placeholder doesn't need to provide any meaningful behaviour + class GenericAlias: + pass + + +__all__ = ["asynccontextmanager", "contextmanager", "closing", "nullcontext", + "AbstractContextManager", "AbstractAsyncContextManager", + "AsyncExitStack", "ContextDecorator", "ExitStack", + "redirect_stdout", "redirect_stderr", "suppress", "aclosing"] + +# Backwards compatibility +__all__ += ["ContextStack"] + +class AbstractContextManager(abc.ABC): + """An abstract base class for context managers.""" + + __class_getitem__ = classmethod(GenericAlias) + + def __enter__(self): + """Return `self` upon entering the runtime context.""" + return self + + @abc.abstractmethod + def __exit__(self, exc_type, exc_value, traceback): + """Raise any exception triggered within the runtime context.""" + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is AbstractContextManager: + return _collections_abc._check_methods(C, "__enter__", "__exit__") + return NotImplemented + + +class AbstractAsyncContextManager(abc.ABC): + + """An abstract base class for asynchronous context managers.""" + + __class_getitem__ = classmethod(GenericAlias) + + async def __aenter__(self): + """Return `self` upon entering the runtime context.""" + return self + + @abc.abstractmethod + async def __aexit__(self, exc_type, exc_value, traceback): + """Raise any exception triggered within the runtime context.""" + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is AbstractAsyncContextManager: + return _collections_abc._check_methods(C, "__aenter__", + "__aexit__") + return NotImplemented + + +class ContextDecorator(object): + "A base class or mixin that enables context managers to work as decorators." + + def refresh_cm(self): + """Returns the context manager used to actually wrap the call to the + decorated function. + + The default implementation just returns *self*. + + Overriding this method allows otherwise one-shot context managers + like _GeneratorContextManager to support use as decorators via + implicit recreation. + + DEPRECATED: refresh_cm was never added to the standard library's + ContextDecorator API + """ + warnings.warn("refresh_cm was never added to the standard library", + DeprecationWarning) + return self._recreate_cm() + + def _recreate_cm(self): + """Return a recreated instance of self. + + Allows an otherwise one-shot context manager like + _GeneratorContextManager to support use as + a decorator via implicit recreation. + + This is a private interface just for _GeneratorContextManager. + See issue #11647 for details. + """ + return self + + def __call__(self, func): + @wraps(func) + def inner(*args, **kwds): + with self._recreate_cm(): + return func(*args, **kwds) + return inner + + +class AsyncContextDecorator(object): + "A base class or mixin that enables async context managers to work as decorators." + + def _recreate_cm(self): + """Return a recreated instance of self. + """ + return self + + def __call__(self, func): + @wraps(func) + async def inner(*args, **kwds): + async with self._recreate_cm(): + return await func(*args, **kwds) + return inner + + +class _GeneratorContextManagerBase: + """Shared functionality for @contextmanager and @asynccontextmanager.""" + + def __init__(self, func, args, kwds): + self.gen = func(*args, **kwds) + self.func, self.args, self.kwds = func, args, kwds + # Issue 19330: ensure context manager instances have good docstrings + doc = getattr(func, "__doc__", None) + if doc is None: + doc = type(self).__doc__ + self.__doc__ = doc + # Unfortunately, this still doesn't provide good help output when + # inspecting the created context manager instances, since pydoc + # currently bypasses the instance docstring and shows the docstring + # for the class instead. + # See http://bugs.python.org/issue19404 for more details. + + +class _GeneratorContextManager(_GeneratorContextManagerBase, + AbstractContextManager, + ContextDecorator): + """Helper for @contextmanager decorator.""" + + def _recreate_cm(self): + # _GCM instances are one-shot context managers, so the + # CM must be recreated each time a decorated function is + # called + return self.__class__(self.func, self.args, self.kwds) + + def __enter__(self): + # do not keep args and kwds alive unnecessarily + # they are only needed for recreation, which is not possible anymore + del self.args, self.kwds, self.func + try: + return next(self.gen) + except StopIteration: + raise RuntimeError("generator didn't yield") from None + + def __exit__(self, type, value, traceback): + if type is None: + try: + next(self.gen) + except StopIteration: + return False + else: + raise RuntimeError("generator didn't stop") + else: + if value is None: + # Need to force instantiation so we can reliably + # tell if we get the same exception back + value = type() + try: + self.gen.throw(type, value, traceback) + except StopIteration as exc: + # Suppress StopIteration *unless* it's the same exception that + # was passed to throw(). This prevents a StopIteration + # raised inside the "with" statement from being suppressed. + return exc is not value + except RuntimeError as exc: + # Don't re-raise the passed in exception. (issue27122) + if exc is value: + return False + # Likewise, avoid suppressing if a StopIteration exception + # was passed to throw() and later wrapped into a RuntimeError + # (see PEP 479). + if type is StopIteration and exc.__cause__ is value: + return False + raise + except: + # only re-raise if it's *not* the exception that was + # passed to throw(), because __exit__() must not raise + # an exception unless __exit__() itself failed. But throw() + # has to raise the exception to signal propagation, so this + # fixes the impedance mismatch between the throw() protocol + # and the __exit__() protocol. + # + # This cannot use 'except BaseException as exc' (as in the + # async implementation) to maintain compatibility with + # Python 2, where old-style class exceptions are not caught + # by 'except BaseException'. + if sys.exc_info()[1] is value: + return False + raise + raise RuntimeError("generator didn't stop after throw()") + + +class _AsyncGeneratorContextManager(_GeneratorContextManagerBase, + AbstractAsyncContextManager, + AsyncContextDecorator): + """Helper for @asynccontextmanager.""" + + def _recreate_cm(self): + # _AGCM instances are one-shot context managers, so the + # ACM must be recreated each time a decorated function is + # called + return self.__class__(self.func, self.args, self.kwds) + + async def __aenter__(self): + try: + return await self.gen.__anext__() + except StopAsyncIteration: + raise RuntimeError("generator didn't yield") from None + + async def __aexit__(self, typ, value, traceback): + if typ is None: + try: + await self.gen.__anext__() + except StopAsyncIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + if value is None: + value = typ() + # See _GeneratorContextManager.__exit__ for comments on subtleties + # in this implementation + try: + await self.gen.athrow(typ, value, traceback) + raise RuntimeError("generator didn't stop after athrow()") + except StopAsyncIteration as exc: + return exc is not value + except RuntimeError as exc: + if exc is value: + return False + # Avoid suppressing if a StopIteration exception + # was passed to throw() and later wrapped into a RuntimeError + # (see PEP 479 for sync generators; async generators also + # have this behavior). But do this only if the exception wrapped + # by the RuntimeError is actually Stop(Async)Iteration (see + # issue29692). + if isinstance(value, (StopIteration, StopAsyncIteration)): + if exc.__cause__ is value: + return False + raise + except BaseException as exc: + if exc is not value: + raise + + +def contextmanager(func): + """@contextmanager decorator. + + Typical usage: + + @contextmanager + def some_generator(): + + try: + yield + finally: + + + This makes this: + + with some_generator() as : + + + equivalent to this: + + + try: + = + + finally: + + """ + @wraps(func) + def helper(*args, **kwds): + return _GeneratorContextManager(func, args, kwds) + return helper + + +def asynccontextmanager(func): + """@asynccontextmanager decorator. + + Typical usage: + + @asynccontextmanager + async def some_async_generator(): + + try: + yield + finally: + + + This makes this: + + async with some_async_generator() as : + + + equivalent to this: + + + try: + = + + finally: + + """ + @wraps(func) + def helper(*args, **kwds): + return _AsyncGeneratorContextManager(func, args, kwds) + return helper + + +class closing(AbstractContextManager): + """Context to automatically close something at the end of a block. + + Code like this: + + with closing(.open()) as f: + + + is equivalent to this: + + f = .open() + try: + + finally: + f.close() + + """ + def __init__(self, thing): + self.thing = thing + def __enter__(self): + return self.thing + def __exit__(self, *exc_info): + self.thing.close() + + +class aclosing(AbstractAsyncContextManager): + """Async context manager for safely finalizing an asynchronously cleaned-up + resource such as an async generator, calling its ``aclose()`` method. + + Code like this: + + async with aclosing(.fetch()) as agen: + + + is equivalent to this: + + agen = .fetch() + try: + + finally: + await agen.aclose() + + """ + def __init__(self, thing): + self.thing = thing + async def __aenter__(self): + return self.thing + async def __aexit__(self, *exc_info): + await self.thing.aclose() + + +class _RedirectStream(AbstractContextManager): + + _stream = None + + def __init__(self, new_target): + self._new_target = new_target + # We use a list of old targets to make this CM re-entrant + self._old_targets = [] + + def __enter__(self): + self._old_targets.append(getattr(sys, self._stream)) + setattr(sys, self._stream, self._new_target) + return self._new_target + + def __exit__(self, exctype, excinst, exctb): + setattr(sys, self._stream, self._old_targets.pop()) + + +class redirect_stdout(_RedirectStream): + """Context manager for temporarily redirecting stdout to another file. + + # How to send help() to stderr + with redirect_stdout(sys.stderr): + help(dir) + + # How to write help() to a file + with open('help.txt', 'w') as f: + with redirect_stdout(f): + help(pow) + """ + + _stream = "stdout" + + +class redirect_stderr(_RedirectStream): + """Context manager for temporarily redirecting stderr to another file.""" + + _stream = "stderr" + + +class suppress(AbstractContextManager): + """Context manager to suppress specified exceptions + + After the exception is suppressed, execution proceeds with the next + statement following the with statement. + + with suppress(FileNotFoundError): + os.remove(somefile) + # Execution still resumes here if the file was already removed + """ + + def __init__(self, *exceptions): + self._exceptions = exceptions + + def __enter__(self): + pass + + def __exit__(self, exctype, excinst, exctb): + # Unlike isinstance and issubclass, CPython exception handling + # currently only looks at the concrete type hierarchy (ignoring + # the instance and subclass checking hooks). While Guido considers + # that a bug rather than a feature, it's a fairly hard one to fix + # due to various internal implementation details. suppress provides + # the simpler issubclass based semantics, rather than trying to + # exactly reproduce the limitations of the CPython interpreter. + # + # See http://bugs.python.org/issue12029 for more details + return exctype is not None and issubclass(exctype, self._exceptions) + + +class _BaseExitStack: + """A base class for ExitStack and AsyncExitStack.""" + + @staticmethod + def _create_exit_wrapper(cm, cm_exit): + return MethodType(cm_exit, cm) + + @staticmethod + def _create_cb_wrapper(*args, **kwds): + # Python 3.6/3.7 compatibility: no native positional-only args syntax + callback, *args = args + def _exit_wrapper(exc_type, exc, tb): + callback(*args, **kwds) + return _exit_wrapper + + def __init__(self): + self._exit_callbacks = deque() + + def pop_all(self): + """Preserve the context stack by transferring it to a new instance.""" + new_stack = type(self)() + new_stack._exit_callbacks = self._exit_callbacks + self._exit_callbacks = deque() + return new_stack + + def push(self, exit): + """Registers a callback with the standard __exit__ method signature. + + Can suppress exceptions the same way __exit__ method can. + Also accepts any object with an __exit__ method (registering a call + to the method instead of the object itself). + """ + # We use an unbound method rather than a bound method to follow + # the standard lookup behaviour for special methods. + _cb_type = type(exit) + + try: + exit_method = _cb_type.__exit__ + except AttributeError: + # Not a context manager, so assume it's a callable. + self._push_exit_callback(exit) + else: + self._push_cm_exit(exit, exit_method) + return exit # Allow use as a decorator. + + def enter_context(self, cm): + """Enters the supplied context manager. + + If successful, also pushes its __exit__ method as a callback and + returns the result of the __enter__ method. + """ + # We look up the special methods on the type to match the with + # statement. + _cm_type = type(cm) + _exit = _cm_type.__exit__ + result = _cm_type.__enter__(cm) + self._push_cm_exit(cm, _exit) + return result + + def callback(*args, **kwds): + """Registers an arbitrary callback and arguments. + + Cannot suppress exceptions. + """ + # Python 3.6/3.7 compatibility: no native positional-only args syntax + try: + self, callback, *args = args + except ValueError as exc: + exc_details = str(exc).partition("(")[2] + msg = "Not enough positional arguments {}".format(exc_details) + raise TypeError(msg) from None + _exit_wrapper = self._create_cb_wrapper(callback, *args, **kwds) + + # We changed the signature, so using @wraps is not appropriate, but + # setting __wrapped__ may still help with introspection. + _exit_wrapper.__wrapped__ = callback + self._push_exit_callback(_exit_wrapper) + return callback # Allow use as a decorator + + def _push_cm_exit(self, cm, cm_exit): + """Helper to correctly register callbacks to __exit__ methods.""" + _exit_wrapper = self._create_exit_wrapper(cm, cm_exit) + self._push_exit_callback(_exit_wrapper, True) + + def _push_exit_callback(self, callback, is_sync=True): + self._exit_callbacks.append((is_sync, callback)) + + +# Inspired by discussions on http://bugs.python.org/issue13585 +class ExitStack(_BaseExitStack, AbstractContextManager): + """Context manager for dynamic management of a stack of exit callbacks. + + For example: + with ExitStack() as stack: + files = [stack.enter_context(open(fname)) for fname in filenames] + # All opened files will automatically be closed at the end of + # the with statement, even if attempts to open files later + # in the list raise an exception. + """ + + def __enter__(self): + return self + + def __exit__(self, *exc_details): + received_exc = exc_details[0] is not None + + # We manipulate the exception state so it behaves as though + # we were actually nesting multiple with statements + frame_exc = sys.exc_info()[1] + def _fix_exception_context(new_exc, old_exc): + # Context may not be correct, so find the end of the chain + while 1: + exc_context = new_exc.__context__ + if exc_context is old_exc: + # Context is already set correctly (see issue 20317) + return + if exc_context is None or exc_context is frame_exc: + break + new_exc = exc_context + # Change the end of the chain to point to the exception + # we expect it to reference + new_exc.__context__ = old_exc + + # Callbacks are invoked in LIFO order to match the behaviour of + # nested context managers + suppressed_exc = False + pending_raise = False + while self._exit_callbacks: + is_sync, cb = self._exit_callbacks.pop() + assert is_sync + try: + if cb(*exc_details): + suppressed_exc = True + pending_raise = False + exc_details = (None, None, None) + except: + new_exc_details = sys.exc_info() + # simulate the stack of exceptions by setting the context + _fix_exception_context(new_exc_details[1], exc_details[1]) + pending_raise = True + exc_details = new_exc_details + if pending_raise: + try: + # bare "raise exc_details[1]" replaces our carefully + # set-up context + fixed_ctx = exc_details[1].__context__ + raise exc_details[1] + except BaseException: + exc_details[1].__context__ = fixed_ctx + raise + return received_exc and suppressed_exc + + def close(self): + """Immediately unwind the context stack.""" + self.__exit__(None, None, None) + + +# Inspired by discussions on https://bugs.python.org/issue29302 +class AsyncExitStack(_BaseExitStack, AbstractAsyncContextManager): + """Async context manager for dynamic management of a stack of exit + callbacks. + + For example: + async with AsyncExitStack() as stack: + connections = [await stack.enter_async_context(get_connection()) + for i in range(5)] + # All opened connections will automatically be released at the + # end of the async with statement, even if attempts to open a + # connection later in the list raise an exception. + """ + + @staticmethod + def _create_async_exit_wrapper(cm, cm_exit): + return MethodType(cm_exit, cm) + + @staticmethod + def _create_async_cb_wrapper(*args, **kwds): + # Python 3.6/3.7 compatibility: no native positional-only args syntax + callback, *args = args + async def _exit_wrapper(exc_type, exc, tb): + await callback(*args, **kwds) + return _exit_wrapper + + async def enter_async_context(self, cm): + """Enters the supplied async context manager. + + If successful, also pushes its __aexit__ method as a callback and + returns the result of the __aenter__ method. + """ + _cm_type = type(cm) + _exit = _cm_type.__aexit__ + result = await _cm_type.__aenter__(cm) + self._push_async_cm_exit(cm, _exit) + return result + + def push_async_exit(self, exit): + """Registers a coroutine function with the standard __aexit__ method + signature. + + Can suppress exceptions the same way __aexit__ method can. + Also accepts any object with an __aexit__ method (registering a call + to the method instead of the object itself). + """ + _cb_type = type(exit) + try: + exit_method = _cb_type.__aexit__ + except AttributeError: + # Not an async context manager, so assume it's a coroutine function + self._push_exit_callback(exit, False) + else: + self._push_async_cm_exit(exit, exit_method) + return exit # Allow use as a decorator + + def push_async_callback(*args, **kwds): + """Registers an arbitrary coroutine function and arguments. + + Cannot suppress exceptions. + """ + # Python 3.6/3.7 compatibility: no native positional-only args syntax + try: + self, callback, *args = args + except ValueError as exc: + exc_details = str(exc).partition("(")[2] + msg = "Not enough positional arguments {}".format(exc_details) + raise TypeError(msg) from None + _exit_wrapper = self._create_async_cb_wrapper(callback, *args, **kwds) + + # We changed the signature, so using @wraps is not appropriate, but + # setting __wrapped__ may still help with introspection. + _exit_wrapper.__wrapped__ = callback + self._push_exit_callback(_exit_wrapper, False) + return callback # Allow use as a decorator + + async def aclose(self): + """Immediately unwind the context stack.""" + await self.__aexit__(None, None, None) + + def _push_async_cm_exit(self, cm, cm_exit): + """Helper to correctly register coroutine function to __aexit__ + method.""" + _exit_wrapper = self._create_async_exit_wrapper(cm, cm_exit) + self._push_exit_callback(_exit_wrapper, False) + + async def __aenter__(self): + return self + + async def __aexit__(self, *exc_details): + received_exc = exc_details[0] is not None + + # We manipulate the exception state so it behaves as though + # we were actually nesting multiple with statements + frame_exc = sys.exc_info()[1] + def _fix_exception_context(new_exc, old_exc): + # Context may not be correct, so find the end of the chain + while 1: + exc_context = new_exc.__context__ + if exc_context is old_exc: + # Context is already set correctly (see issue 20317) + return + if exc_context is None or exc_context is frame_exc: + break + new_exc = exc_context + # Change the end of the chain to point to the exception + # we expect it to reference + new_exc.__context__ = old_exc + + # Callbacks are invoked in LIFO order to match the behaviour of + # nested context managers + suppressed_exc = False + pending_raise = False + while self._exit_callbacks: + is_sync, cb = self._exit_callbacks.pop() + try: + if is_sync: + cb_suppress = cb(*exc_details) + else: + cb_suppress = await cb(*exc_details) + + if cb_suppress: + suppressed_exc = True + pending_raise = False + exc_details = (None, None, None) + except: + new_exc_details = sys.exc_info() + # simulate the stack of exceptions by setting the context + _fix_exception_context(new_exc_details[1], exc_details[1]) + pending_raise = True + exc_details = new_exc_details + if pending_raise: + try: + # bare "raise exc_details[1]" replaces our carefully + # set-up context + fixed_ctx = exc_details[1].__context__ + raise exc_details[1] + except BaseException: + exc_details[1].__context__ = fixed_ctx + raise + return received_exc and suppressed_exc + + +class nullcontext(AbstractContextManager, AbstractAsyncContextManager): + """Context manager that does no additional processing. + + Used as a stand-in for a normal context manager, when a particular + block of code is only sometimes used with a normal context manager: + + cm = optional_cm if condition else nullcontext() + with cm: + # Perform operation, using optional_cm if condition is True + """ + + def __init__(self, enter_result=None): + self.enter_result = enter_result + + def __enter__(self): + return self.enter_result + + def __exit__(self, *excinfo): + pass + + async def __aenter__(self): + return self.enter_result + + async def __aexit__(self, *excinfo): + pass + + +# Preserve backwards compatibility +class ContextStack(ExitStack): + """Backwards compatibility alias for ExitStack""" + + def __init__(self): + warnings.warn("ContextStack has been renamed to ExitStack", + DeprecationWarning) + super(ContextStack, self).__init__() + + def register_exit(self, callback): + return self.push(callback) + + def register(self, callback, *args, **kwds): + return self.callback(callback, *args, **kwds) + + def preserve(self): + return self.pop_all() diff --git a/pipenv/vendor/contextlib2/__init__.pyi b/pipenv/vendor/contextlib2/__init__.pyi new file mode 100644 index 00000000..d42c6b05 --- /dev/null +++ b/pipenv/vendor/contextlib2/__init__.pyi @@ -0,0 +1,132 @@ +# Type hints copied from the typeshed project under the Apache License 2.0 +# https://github.com/python/typeshed/blob/64c85cdd449ccaff90b546676220c9ecfa6e697f/LICENSE + +import sys +from types import TracebackType +from typing import ( + IO, + Any, + AsyncContextManager, + AsyncIterator, + Awaitable, + Callable, + ContextManager, + Iterator, + Optional, + Type, + TypeVar, + overload, +) +from typing_extensions import ParamSpec, Protocol + +# contextlib2 API adaptation notes: +# * the various 'if True:' guards replace sys.version checks in the original +# typeshed file (those APIs are available on all supported versions) +# * deliberately omitted APIs are listed in `dev/mypy.allowlist` +# (e.g. deprecated experimental APIs that never graduated to the stdlib) + +AbstractContextManager = ContextManager +if True: + AbstractAsyncContextManager = AsyncContextManager + +_T = TypeVar("_T") +_T_co = TypeVar("_T_co", covariant=True) +_T_io = TypeVar("_T_io", bound=Optional[IO[str]]) +_F = TypeVar("_F", bound=Callable[..., Any]) +_P = ParamSpec("_P") + +_ExitFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], bool] +_CM_EF = TypeVar("_CM_EF", ContextManager[Any], _ExitFunc) + +class _GeneratorContextManager(ContextManager[_T_co]): + def __call__(self, func: _F) -> _F: ... + +# type ignore to deal with incomplete ParamSpec support in mypy +def contextmanager(func: Callable[_P, Iterator[_T]]) -> Callable[_P, _GeneratorContextManager[_T]]: ... # type: ignore + +if True: + def asynccontextmanager(func: Callable[_P, AsyncIterator[_T]]) -> Callable[_P, AsyncContextManager[_T]]: ... # type: ignore + +class _SupportsClose(Protocol): + def close(self) -> object: ... + +_SupportsCloseT = TypeVar("_SupportsCloseT", bound=_SupportsClose) + +class closing(ContextManager[_SupportsCloseT]): + def __init__(self, thing: _SupportsCloseT) -> None: ... + +if True: + class _SupportsAclose(Protocol): + async def aclose(self) -> object: ... + _SupportsAcloseT = TypeVar("_SupportsAcloseT", bound=_SupportsAclose) + class aclosing(AsyncContextManager[_SupportsAcloseT]): + def __init__(self, thing: _SupportsAcloseT) -> None: ... + _AF = TypeVar("_AF", bound=Callable[..., Awaitable[Any]]) + class AsyncContextDecorator: + def __call__(self, func: _AF) -> _AF: ... + +class suppress(ContextManager[None]): + def __init__(self, *exceptions: Type[BaseException]) -> None: ... + def __exit__( + self, exctype: Optional[Type[BaseException]], excinst: Optional[BaseException], exctb: Optional[TracebackType] + ) -> bool: ... + +class redirect_stdout(ContextManager[_T_io]): + def __init__(self, new_target: _T_io) -> None: ... + +class redirect_stderr(ContextManager[_T_io]): + def __init__(self, new_target: _T_io) -> None: ... + +class ContextDecorator: + def __call__(self, func: _F) -> _F: ... + +_U = TypeVar("_U", bound=ExitStack) + +class ExitStack(ContextManager[ExitStack]): + def __init__(self) -> None: ... + def enter_context(self, cm: ContextManager[_T]) -> _T: ... + def push(self, exit: _CM_EF) -> _CM_EF: ... + def callback(self, callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... + def pop_all(self: _U) -> _U: ... + def close(self) -> None: ... + def __enter__(self: _U) -> _U: ... + def __exit__( + self, + __exc_type: Optional[Type[BaseException]], + __exc_value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> bool: ... + +if True: + _S = TypeVar("_S", bound=AsyncExitStack) + + _ExitCoroFunc = Callable[[Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]], Awaitable[bool]] + _CallbackCoroFunc = Callable[..., Awaitable[Any]] + _ACM_EF = TypeVar("_ACM_EF", AsyncContextManager[Any], _ExitCoroFunc) + class AsyncExitStack(AsyncContextManager[AsyncExitStack]): + def __init__(self) -> None: ... + def enter_context(self, cm: ContextManager[_T]) -> _T: ... + def enter_async_context(self, cm: AsyncContextManager[_T]) -> Awaitable[_T]: ... + def push(self, exit: _CM_EF) -> _CM_EF: ... + def push_async_exit(self, exit: _ACM_EF) -> _ACM_EF: ... + def callback(self, callback: Callable[..., Any], *args: Any, **kwds: Any) -> Callable[..., Any]: ... + def push_async_callback(self, callback: _CallbackCoroFunc, *args: Any, **kwds: Any) -> _CallbackCoroFunc: ... + def pop_all(self: _S) -> _S: ... + def aclose(self) -> Awaitable[None]: ... + def __aenter__(self: _S) -> Awaitable[_S]: ... + def __aexit__( + self, + __exc_type: Optional[Type[BaseException]], + __exc_value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> Awaitable[bool]: ... + +if True: + class nullcontext(AbstractContextManager[_T]): + enter_result: _T + @overload + def __init__(self: nullcontext[None], enter_result: None = ...) -> None: ... + @overload + def __init__(self: nullcontext[_T], enter_result: _T) -> None: ... + def __enter__(self) -> _T: ... + def __exit__(self, *exctype: Any) -> bool: ... diff --git a/pipenv/vendor/importlib_resources/tests/data03/namespace/resource1.txt b/pipenv/vendor/contextlib2/py.typed similarity index 100% rename from pipenv/vendor/importlib_resources/tests/data03/namespace/resource1.txt rename to pipenv/vendor/contextlib2/py.typed diff --git a/pipenv/vendor/dateutil/LICENSE b/pipenv/vendor/dateutil/LICENSE deleted file mode 100644 index 1e65815c..00000000 --- a/pipenv/vendor/dateutil/LICENSE +++ /dev/null @@ -1,54 +0,0 @@ -Copyright 2017- Paul Ganssle -Copyright 2017- dateutil contributors (see AUTHORS file) - - 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 above license applies to all contributions after 2017-12-01, as well as -all contributions that have been re-licensed (see AUTHORS file for the list of -contributors who have re-licensed their code). --------------------------------------------------------------------------------- -dateutil - Extensions to the standard Python datetime module. - -Copyright (c) 2003-2011 - Gustavo Niemeyer -Copyright (c) 2012-2014 - Tomi Pieviläinen -Copyright (c) 2014-2016 - Yaron de Leeuw -Copyright (c) 2015- - Paul Ganssle -Copyright (c) 2015- - dateutil contributors (see AUTHORS file) - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The above BSD License Applies to all code, even that also covered by Apache 2.0. \ No newline at end of file diff --git a/pipenv/vendor/dateutil/_version.py b/pipenv/vendor/dateutil/_version.py index eac12096..b723056a 100644 --- a/pipenv/vendor/dateutil/_version.py +++ b/pipenv/vendor/dateutil/_version.py @@ -1,4 +1,5 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '2.8.1' +version = '2.8.2' +version_tuple = (2, 8, 2) diff --git a/pipenv/vendor/dateutil/easter.py b/pipenv/vendor/dateutil/easter.py index 53b7c789..f74d1f74 100644 --- a/pipenv/vendor/dateutil/easter.py +++ b/pipenv/vendor/dateutil/easter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -This module offers a generic easter computing method for any given year, using +This module offers a generic Easter computing method for any given year, using Western, Orthodox or Julian algorithms. """ @@ -21,15 +21,15 @@ def easter(year, method=EASTER_WESTERN): quoted in "Explanatory Supplement to the Astronomical Almanac", P. Kenneth Seidelmann, editor. - This algorithm implements three different easter + This algorithm implements three different Easter calculation methods: - 1 - Original calculation in Julian calendar, valid in - dates after 326 AD - 2 - Original method, with date converted to Gregorian - calendar, valid in years 1583 to 4099 - 3 - Revised method, in Gregorian calendar, valid in - years 1583 to 4099 as well + 1. Original calculation in Julian calendar, valid in + dates after 326 AD + 2. Original method, with date converted to Gregorian + calendar, valid in years 1583 to 4099 + 3. Revised method, in Gregorian calendar, valid in + years 1583 to 4099 as well These methods are represented by the constants: diff --git a/pipenv/vendor/dateutil/parser/_parser.py b/pipenv/vendor/dateutil/parser/_parser.py index 458aa6a3..37d1663b 100644 --- a/pipenv/vendor/dateutil/parser/_parser.py +++ b/pipenv/vendor/dateutil/parser/_parser.py @@ -20,11 +20,11 @@ value falls back to the end of the month. Additional resources about date/time string formats can be found below: - `A summary of the international standard date and time notation - `_ -- `W3C Date and Time Formats `_ + `_ +- `W3C Date and Time Formats `_ - `Time Formats (Planetary Rings Node) `_ - `CPAN ParseDate module - `_ + `_ - `Java SimpleDateFormat Class `_ """ @@ -60,14 +60,8 @@ class _timelex(object): _split_decimal = re.compile("([.,])") def __init__(self, instream): - if six.PY2: - # In Python 2, we can't duck type properly because unicode has - # a 'decode' function, and we'd be double-decoding - if isinstance(instream, (bytes, bytearray)): - instream = instream.decode() - else: - if getattr(instream, 'decode', None) is not None: - instream = instream.decode() + if isinstance(instream, (bytes, bytearray)): + instream = instream.decode() if isinstance(instream, text_type): instream = StringIO(instream) @@ -654,7 +648,7 @@ class parser(object): try: ret = self._build_naive(res, default) except ValueError as e: - six.raise_from(ParserError(e.args[0] + ": %s", timestr), e) + six.raise_from(ParserError(str(e) + ": %s", timestr), e) if not ignoretz: ret = self._build_tzaware(ret, res, tzinfos) @@ -1359,10 +1353,10 @@ def parse(timestr, parserinfo=None, **kwargs): first element being a :class:`datetime.datetime` object, the second a tuple containing the fuzzy tokens. - :raises ValueError: - Raised for invalid or unknown string format, if the provided - :class:`tzinfo` is not in a valid format, or if an invalid date - would be created. + :raises ParserError: + Raised for invalid or unknown string formats, if the provided + :class:`tzinfo` is not in a valid format, or if an invalid date would + be created. :raises OverflowError: Raised if the parsed date exceeds the largest valid C integer on @@ -1593,17 +1587,27 @@ def _parsetz(tzstr): class ParserError(ValueError): - """Error class for representing failure to parse a datetime string.""" + """Exception subclass used for any failure to parse a datetime string. + + This is a subclass of :py:exc:`ValueError`, and should be raised any time + earlier versions of ``dateutil`` would have raised ``ValueError``. + + .. versionadded:: 2.8.1 + """ def __str__(self): try: return self.args[0] % self.args[1:] except (TypeError, IndexError): return super(ParserError, self).__str__() - def __repr__(self): - return "%s(%s)" % (self.__class__.__name__, str(self)) + def __repr__(self): + args = ", ".join("'%s'" % arg for arg in self.args) + return "%s(%s)" % (self.__class__.__name__, args) class UnknownTimezoneWarning(RuntimeWarning): - """Raised when the parser finds a timezone it cannot parse into a tzinfo""" + """Raised when the parser finds a timezone it cannot parse into a tzinfo. + + .. versionadded:: 2.7.0 + """ # vim:ts=4:sw=4:et diff --git a/pipenv/vendor/dateutil/parser/isoparser.py b/pipenv/vendor/dateutil/parser/isoparser.py index 48f86a33..5d7bee38 100644 --- a/pipenv/vendor/dateutil/parser/isoparser.py +++ b/pipenv/vendor/dateutil/parser/isoparser.py @@ -159,7 +159,7 @@ class isoparser(object): components, pos = self._parse_isodate(datestr) if pos < len(datestr): raise ValueError('String contains unknown ISO ' + - 'components: {}'.format(datestr)) + 'components: {!r}'.format(datestr.decode('ascii'))) return date(*components) @_takes_ascii @@ -333,10 +333,10 @@ class isoparser(object): pos = 0 comp = -1 - if len(timestr) < 2: + if len_str < 2: raise ValueError('ISO time too short') - has_sep = len_str >= 3 and timestr[2:3] == self._TIME_SEP + has_sep = False while pos < len_str and comp < 5: comp += 1 @@ -347,13 +347,18 @@ class isoparser(object): pos = len_str break + if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: + has_sep = True + pos += 1 + elif comp == 2 and has_sep: + if timestr[pos:pos+1] != self._TIME_SEP: + raise ValueError('Inconsistent use of colon separator') + pos += 1 + if comp < 3: # Hour, minute, second components[comp] = int(timestr[pos:pos + 2]) pos += 2 - if (has_sep and pos < len_str and - timestr[pos:pos + 1] == self._TIME_SEP): - pos += 1 if comp == 3: # Fraction of a second diff --git a/pipenv/vendor/dateutil/rrule.py b/pipenv/vendor/dateutil/rrule.py index 6bf0ea9c..b3203393 100644 --- a/pipenv/vendor/dateutil/rrule.py +++ b/pipenv/vendor/dateutil/rrule.py @@ -5,26 +5,27 @@ the recurrence rules documented in the `iCalendar RFC `_, including support for caching of results. """ -import itertools -import datetime import calendar +import datetime +import heapq +import itertools import re import sys +from functools import wraps +# For warning about deprecation of until and count +from warnings import warn + +from six import advance_iterator, integer_types + +from six.moves import _thread, range + +from ._common import weekday as weekdaybase try: from math import gcd except ImportError: from fractions import gcd -from six import advance_iterator, integer_types -from six.moves import _thread, range -import heapq - -from ._common import weekday as weekdaybase - -# For warning about deprecation of until and count -from warnings import warn - __all__ = ["rrule", "rruleset", "rrulestr", "YEARLY", "MONTHLY", "WEEKLY", "DAILY", "HOURLY", "MINUTELY", "SECONDLY", @@ -81,6 +82,7 @@ def _invalidates_cache(f): Decorator for rruleset methods which may invalidate the cached length. """ + @wraps(f) def inner_func(self, *args, **kwargs): rv = f(self, *args, **kwargs) self._invalidate_cache() diff --git a/pipenv/vendor/dateutil/tz/tz.py b/pipenv/vendor/dateutil/tz/tz.py index af81e88e..c67f56d4 100644 --- a/pipenv/vendor/dateutil/tz/tz.py +++ b/pipenv/vendor/dateutil/tz/tz.py @@ -1596,7 +1596,7 @@ def __get_gettz(): name = os.environ["TZ"] except KeyError: pass - if name is None or name == ":": + if name is None or name in ("", ":"): for filepath in TZFILES: if not os.path.isabs(filepath): filename = filepath diff --git a/pipenv/vendor/dateutil/utils.py b/pipenv/vendor/dateutil/utils.py index 44d9c994..dd2d245a 100644 --- a/pipenv/vendor/dateutil/utils.py +++ b/pipenv/vendor/dateutil/utils.py @@ -63,7 +63,7 @@ def default_tzinfo(dt, tzinfo): def within_delta(dt1, dt2, delta): """ - Useful for comparing two datetimes that may a negilible difference + Useful for comparing two datetimes that may have a negligible difference to be considered equal. """ delta = abs(delta) diff --git a/pipenv/vendor/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz b/pipenv/vendor/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz index 89e83517b562451622cea7cbe1dbfac5c3d2513e..524c48e12db7dfe159f282e4664f71ce249e1970 100644 GIT binary patch literal 174394 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 z zK@$OwOkfjTQHun~g(Ow{Yf+gd;sF5djTjwXB5<*F3&+$$r2VWhb^+9`*R*7>2a^m< z5bYm)PbT%I8xZX3?kG(}-R`(q_W|{^q0iDYtHvi^KJHT&JiS@c-Q%ZxB`)AIIPO$F zA#!e8(z@DV?|Cbce-=T3fH}d?0nMV$q@) zuEkMiL^NY*45xgFG_Lx3eN*L_n+oUSarE<&YeBBco(wJM)D8?+6ngYj#N^fr<{Rt{ z>$h`?Oy0hq%*9lfn+zfpOT@2Zw|~O!FaAP9NSDpIs&LKtW8-#vL6i300CmmfF`Ir^ zh2KQ%A&NEOntm=mZr3^wIB(a_H=x}v3bC=7{b8ojr244FH?La%!RCjWUxROoVg=_* zPgj-n*KG#}St%LHb}+Qcc*jkO+b!z#q#`Em#@lr=zof8FQq9VhO?ER*9vo&(6^(0^ z%=?z?s9ObTR?InCv~gux6XqrjU?XZLC}<3ddG)!Kk8h6~XDYF2};g zSiqlQG@@fIP#XH&YD_*yEAxH%rty|pt;5pbWd2Ew?8k3HU+P79bILepi1h_CiJR+d zUknIa*ZSDD}S* z?o8gapr*K3D3vnHOm(xmb*XvOb&qfN4b?|<1ruEn{#c~O`7^iik4C0xu)@(#2C**O zq}#_#hR1J9KmJxb`h^xeL<{)Pg1tLI2U-9^3*^v(mriIwCtC10ZY5mFFPx3BiyYl# zhHgqjH&u0`n<#rZLkXQiqfDdKM7wBVPe0fOtbA1y?t&QHe;jQ`_(r*!LEH%s!u#!U zrXAj!$k!~YvlQQT&C#fYGK_G&dTeF~v|wi4i>HeNt%DBZEUn2wQv#>5{=^y zIbq+%MGF{&r=N?wM+-icVT_U0W6K-NkbwO#vN)B;p4DT?+a~Aop>MT;=4kGix@S#< zRuMxBu&a2)1v}9KVzfXGEnq|on(qXp!!q)j=-xz`#;OL6urh9wp%Hp$gaaBe*M;r} zc^r47f?#)^nDw)`(@2GsZb6A=MkF6zs?feC%F=Pj;4D)M(8~loog1c%o@44agn7oF zWr~pnTueemwSk^h4WKRQOkXv1T0Zq^_ORH+SHXTNRIC`$o>8=4;-<1lt~Jr>^<2Bz zjd!3motSY^!O_a1+?ILK=*_SAB@VhKmBtSnK1Z?fz^4_Pz(P}fi5{7{HzN*$g@)<>?2*U)j!ID7noIa_=S@uz7Jmwe|jRFuBu0^lF#ZsECK3+>UqQ zGGodL3Z3NImnl2y<1L=v%1F6bYc5u^D_#>Sh3$}&uv~cv6wHaFC}6Y;P5$_$mB*+x zl%k?)si@-UXU04KUVixYvS`+K+rF&pbHkt|LZG-Vtvp2{EVWL1bx9+0_q1wCP*B}| zl}DApVO)=}y;&Roh|1>k9w3hYV)XYzgR9tygP`bH|8DNGj-Ov_E(?kEdw7;?3Pjs@ zdL~}mY;LgCva?K2lxx{q5idR}CT>`)Jveu>xp+I7*SmxG7BkOKWVu06Go7}oahP+M z>ep=_mx16P+oKdw+ew=0(fkFU$YzXubK^5Kirsmxoud>vZ7Qi>$VrZET}8t)F=Mn} z+xW}DW?@Bk?$0>W1l`+?+)ELU!K@;}ypX(}fzAU4`m^-14T5te4UH8;7u}{d4d((p z3+IgoY<0h>c+R$H>^-}VcK$~7*Aeq!7d;~QEwFn?F1c5Iv!7TThUgdz- zenn!cKep)Nb{am196o365-}h@e9qq`GEdeT4JNy=EBGrKlz=AEWglR+LTmh3{}mae zvrwb5;fGb#XgP1>>m3sG4GpkD0}Af|8$pplsfUvq0WK1<5$<`9 zM&AYZ@cAX0UZs_Y7<6H0c_i8yK)^+U#XcbaxKm{QTPu+hTHJFiDlNHCL;d3hM3B)M z_wM6++3cU6p5ft;ThP-8|7OHk{uL=5LJGmdLkk#%@t#ZE31k*(M0##OqI}&C7Tsuh!+R(d(kWt)a6u=FZZx<(l!`}#rI$kao!-l0 zcG1VI_|(yBDwDim@0G7irq?%2j`@ggS?T)p6z?gbhJkq1r=I?U?{H#gAA?3|VHeGe>RuB*Gi+#C9N2G-9Ra!cO7dRR&ua7)?XB zhNk(9rooCq(=Z>SX=Lv}y=V~l4n&UzWqpX%Jw}r#GlnsuIhQ}gdfoxwpn;G+G*I44 zRl@YH^5!bT-h;RTq}^_5OMZkOxQ-^TMw5pmeq&i73+ksIT}S__R%H?sv?}Jnh26Mx zt0e3yW8Vs`^Z_l)9{6$yguiOBRB?2Qn@AFSxiUUeP}QKdqIWj$&mO+}RH+wyoX?Nq*XiguMYL8n|?lYX$ zY;Ot3FFDkSS!Dd6vF#)`1W1~fiEA>neP6BDX5LCPp1CR1zGQ1L)?6wjGio(-=M$R> ze^zt463VO2a#U>WjC{#TmsWlIvqV#{6_WIfSc*Za*0A0ZHv!*%{a9u9ZP**Na$PRn z63q#t^0Z;865qUX<8@EjMSuJVZ7hKe@!)t6A?HWbwwg^OPk|bMir3*U|%#S(B46 zYNneM66wEN#zx1Crt=sr!~0bnsk4hNWv;%_^2rY-HSMzT z`bxh&Jn`<|HnZw$GjQZ_Xg)VAF!$cwN~+^EKHT|fe{KC!r=g!NBgaZn#N^S7(WLw_ z(sg(8AS-+kox_in(N9Eef|i^HYxE05otn*xRdyFz+m;x3GN$581Zu~a@O^@(sbj6a@<_n}Q!dyDWpKA~h9i}y%a;IPM4aWnFs2*J~b4wGF6 z%<$b!I7R9mnx}vnoiQFO^ zGCe;_S{3!fUWKp{E1T=Mv;}Kc6$QubA{A|`BDv_Tju)zoXA&BMEI5*cVpat-)YLS7I zvr!er5!Zm_lH9xXQs6~6WzFLc*{JAvX(U4G$r+SOVFFMwR|g^liGMQfK-HNbxac{k zM|uWjFq#0eRi)pAUz<#X;i~=vkzoA?qAP=hE0CPQx7uX>gkK|A(EM6xo{HXV6nUnA z^s9(#G3kY5LejPdTsyShk^vU~G$12$$cBmLbdwq8eIPsyJU-1v0Wzd_ET8VduHpLH z!{-_*6MzT09WSU5h&Dg72{zo;&c?*C>$2S zGyr=k^b&RrJV*C^v&Or=M?M>cNS~|`F(N$!s!KEWlkVxJKmv3!C{D_7OcQZO0%%b%2kgZI0eE z8^wVhF_WhlATf1dI0;RyhVC>7J_?f$jo6dbFHU3IUl4;SdeIq3>s zyo!H;y8i$>{{c!oxdQ^3#11<9=+ma}DZ-?+P*9 zv)O)oxVme<4#*_~1m=EbKD@g;P~C$Lo42=?_QrXG&CX+K`(lFvH{xjm4GRtRO}3&M zo5;lNG_gT*_TImBY*gyv$hDffdYLw+;!IVsO~Zv-7nk4tllDp_-*&3o)6@G8re5n{ zQM;D&*Z(lo8egp6>F?M{xn)bU-H3lZo#Fel{-ADZ=b9QmD;lAq!}qfA@K*RV@v5tH z)1H#jvnUmNcWAKdI@RD;zd(Z_znOzQmBoB>L3nf91oP&(IrSj*#_M^VIAis3zi=VA zDtoE_TgKjV`v!}R2GSJUn=kvcsMS(h`_N1S&7 zxI?BfvIkCDUQV3N)vb+Bjf{*9?V5ET6X<*+C(n5?7!ff#xzW|N70$I?e6nIHVOqs* z=!Yhey%#5o!ND&3JWwGgko=ht%ag8Og@3xbtUml*G36HYbmF9-L(@f(++p$2z?@Iy zSJ#C~|FUbjv*^C`OTYt_2}ibXLa)3Hb^+nO zE9lSCL!X*~pofX-c`ceQ0mD@3LT%euVsoVb zPW~%IA8=IV#Hr9h69#Oql3(_qh*}osn}G}F6KG7Sqa6=A8Z&%J-!*FO-TTqy`XXxL zS*DtX*c_EjzRG~6r66Ups(HD9(hCRwg~mt$pAR@LU;Ii1ERE>gdKM*jbYe2CbyLza zNv}WCAGt^hO=-hzO>{--eBiEi!>_pzf7vWhQ`;6{A_yf0@&-;N!b67N!QOr58U`h5 zgubdT<{je=%ioIqE))OqDIWjtY8U?FY!8A}nPp6FonDWpp&7$+tY7Vy7fCMswdauM~KOwJVrc-N*gDh^Y^UwpsG*@_cJQ=FNSo^zx92sD451}LS1rVxIX&kN^|9e z;mUqjh+aL%bXC18jPDAE*`GNl{m}&9T?QV}q+9wM-b=UL5Ufh19BR^i0&ub2R9`}& zU)LyC8c`^)Li3YWJAa>LtL2ox`p$lxayL%);)b-MVXje?%YuQ8+A|;9#0|MX(}bOM z_nnY5+YcVAeXSu$;{j?mpi{TQDS-JP@R=~Gua5EubOTtJ26lJtFCKlh6ZLwps)vLp zq71Gbw*k@$fHOJ)b#tkYzJligXt4p!7T}^TmGhZil>PdU^yyZT5#Vyt!Sb&L8l%>X zV(QHA6oDWwE{?8Nkz!(D^q?Mnx+=O(OxGPD0(qN>DXu%MDcm%Gfwg#T;fT3*+T-0sr=kGwAh|-WejN6galL zGuKpSh?WA&Eg7?%55L(Ei!Dhx>Ip`?H8#8lzfMlii3u7Sm!U)_!<&X6i_f}Vmp`Ei zXDpikx#QHi&N0+iQ}P&=n=BU#_#NKd7KngHhWmi%R{+p|hA_5nK~fyspYa{ZY1y0R z)lZe7pu2G74RkWy_%@W*$KGBW)o=_?0LpGN6M(pE*)NfbQ4!J6ztbFT(JTLfG@JqolfZj*q;-l2m^EnyK!^Y$KREu1A}?wTE}+Mz zJ^=}Q38m8u0B7CFA(#6CTZtdpRnhfi7QtM*Ui(J$xxiR7xyXQlTWpYnpO*sL>knz# zA9~)@%*?K692J6UI;Yv{VjWG?mG%!yf78@V_StSKOuk@D$tqK|&7!m^-nY?8oNIFv zw}*PxOf6r%wYjWy)0YGI235JzROMm_RYQkEdFA$eEjQIG_=PNeclR`24bC$7C)e2i zk++;?P!npQaj=cp8X24|lccq5Q2$&upN%D%F6-h1kEY0kzk_ZhJa=nKdRhH}Ns@UhhUX%-j z&Kb;n?jEjWcp|i|Y^ObuPqVYt<|Q5jVC*V>&)?JXqixZ z{<9p7^Or{Tao#c8(*3+e6CpXW;!R(#1A_Xb3-~5goa+SdM%)wL?ab13)V&w&n;d@w z&|dx$e;9$W#*jXNv9EiONd!YZh4;-L(#J%6{_YEuVzY;r@2SGv`uf7pep?B1S}PxU zf8Z|nT=%6gP^K`s-EyHYQ>L)=g>g?Mb1#WU3fMjM0C&>>e5055Ik6=or9fuHl-j3_z^d>~TZ5j~fVfzs!Xw|OtA~@7K-Z@hB*!ARuP%raJ!{`FF!Y}qwXy_0+qDi$G`pog~%{W2WY8vN-;NdVoB=HZ~x0q~RG>|{;X)-G(hr`X_ z{6nX?&ssCv-%xGxy|=$aI&wRu3EAHMIy~HC{^BzINqz}oWI(lB%Vo$E`>B~mJ(%L!HK&kqMW&<{Vf zCvyeaK{>zX-QJ&C0gu&MOdapC{>d|t8|8gAZS1prj7NB)Bf$x z#@mZB%I`b3q5X}~-mxAaWVXhrmA|F(Mf$gjW8ThSyA_+*iCONFud!HL*Jq3CnpJ~s zwgR2WVC<kYio9us9oPE_7`%Oo#*8l#hq4#~u__{lj zMgM-1FT`V}Nr4D@qtdimP;;t^hgZEisB<Uq(pNjE+elfu320g9(bM<$pY&=vOfGSTv$UA!Aut4X)?K`TMB8TVHTbt!_5a%WD1Tvi#jD%YyCT1Nv>J?dPXIj;QU3bPY&cp1?i%rQncddkx_*=5|0 z9S~j@617j57$3)odUsO!4a}Rla^9>|*u5>oM5mVwl9SzDOnvHYr{RYWRnd5cJz6%! z_)Bx~ZxSfF*_<6BI-n zEFbtYS|az)pB`F`fWNCY%<`83bodR|*fs zaWUhh167`rVDm=FQ_XNg0^g0pq=V1`e6--@3_axMI~SO=RI(&z^Q%uQZtpQaZT-U9 zDI^##Xa|Rdz4Dst`?bcBL-4kM=1|HoBy4r)2J{Rh*|9+wMu_|K{mEx(oRGh`q?T-l zQUNoqbi}47pF?1SlqAo2?d88F(<_2Q!q8VtAj~eb#$(*9l?6r92a=U&=;$3Z0^P`g zhW-$TJx%4M|B%+9Ffda~Ct(&_SY<8stDD}*?Bp}n7c@%X{gT}uKNvL{pNhd{aKn}ed_R%U>81nzw`|L@A?XA+fRv9+ac#FHJL8FEG*1wA_j=~fC904gJGcR ze;1U{kA^^J{92=71Q0p_J*3(dyIUszXJK5v4K>AALDJF!Oh2aef#3fw%o^%jM}R+< z{$<%K8YIqaD8LA4fM+73k%;pj_euaEj(X@Qz5(+tr9ngKbhWIQC=pMTsZY{2P@FV> zt$ZQnpFhtAZO1{f>i)riA1t-)-1e-Jpq99L2Rj_PnhgFP61`~zIxLB}nRyo|AJ5+8 zaPt49xF2%$71=ixT2V%1!u6j&1KM^A(QqP@O*8v{&!W{P%k_JxQ7L2laQExK2uW&A9O)`1x=1fbnv7OWs+eBtY||6 z(JtSoYGd+AdSSq8_uwqpfp@aCRS4b7usehbGwhdq`QB<6qnXg zPx69TWUJz(@1c&xA^X#7jS}!t<(5b=+C_j#VL0)FA1QeEnmP9@#a%{P|JPAa+s?G@ z2T*#bi=&gHE2-NX9BglcD}ZnSVqOV7&I%gy)5iq z4HZy?`^&PB3Jsr4e6L8T-lu5p`^2u%$G5jx_~wu;&-BQ{C?TAlHGzHaqh|XpUru;Q zTh7i>mTcX6j*&|3yHt&=YN_jSON_N)CWXn3KVmC~O>k!8h)<+>*~vJy-NN79N^n^k zwK`3NIcF_de1j@S6)-<$i>JK=F+~;#xsF}Z=92c*ycF~jKFcD-U7-)+j}ey2iu;{Q ziocQ@#9swgWrvYIT%ix<9|f!O!bl&j15v^bbG~$BUv0xEDa|tk4vI81l zf!QCy2(VTlfldBd3)^K(P8$}3KBGFFfE}-}CJ2{nzbB&;5 z<#p0^Kz@N&qDt8lBJ_Vfb3vw%dv?0?M3!8SZ4_I74VY!E>1{l7PQ&#Ax?9fi8_ z#Ia}rQcEJn|7(TBman6`$XvFMpimjWuNsQ_pKjkh1vP-wEGK*QGoj+|vP-Bu^5X2Q z?%zn~KmM}XsTds#C(prXDInExfI5RB%g&%DXs1cPT3F^9De;9>b-$zo9?Qq$e*`eYkdaxXQL%R+HBK78_>Jv z2H_U}#6PbPb0}-n;Zw4t_!%+wixuE~CP4D8VMpxFmA#uW$C5w}jvQf>f~WLZCg68w z65tr11&I8*=73IJwEcQmq4XW)b5Z-m$l?#d&Re%=R!vxwg2wOSOC<*LFxvU$ZU)_G z?Mu|n$t3MY(uWGv-~PW8aFB1I$&TtxMq;eqzj1?xda>VtQ#?vezKI+ly1Al-i|?L@ z{U?%9xBdymlrK&A>=iSoz?IVoR2UE#(FaEVXC9y}n<|TXmHKEHOH~+46X`z$wEy`5 zcSex_=|RuPz~t?&tgJGShj#3*;P7?eKhJ(Dk?9)2!&+q`?I3c0ZTJ*{5c-R{0otdK zK5!Pp=|?o=%EHLJHz)eIv9T!e2~Z?hSa0OahNip{TmH8(nt)4O;cCv zS2@`l$1czxtz!6ZwoMD9{Ji0Xud>ZyE_G+g^FIRhK#-HcUcXv8%Ki;Niyd8wK^&}r zc)H&#O-}$KJ>cpJ{iUn^pD!JHDzK=kL_)bUfup0drV3QejUEyaU5)BT{ah$OFP3FT zd3O5}=j3=_CPh!_mr_x-tBJZZcJr@KYKYW*EI3l?p|-g4$b8HCxT##badxE8vpi65 zyT@N~JzZ&#)g(=`xSYaTJ5}#zp=eXG{%S%*xQcy&C^gSq;jDSIeu;{IPCZn#Mm1eL z&tXJ=ykXV6t3oAU$C1{KU-VjhhssHQm!v^4?zrhl2lW!Q8nN^fD74rM&Ov7mlTMnb zwPii5)@$?3&=7;!SZ3J z-hHPH@iY;Ttzss9C(Nk#)ZF9dMq*i?SYfKMB00h<+ILj*iQ8Vq$AI8oTenw zyg-(;l;!u5g>-(Vy9@i3wVM6cXtibldGwux{bh(F%M&rN!vL`%z}FA`CLaeOo?(EI<%_CNN}Gc(*|&V(Gc%Rd)K%i{hKSXHbj!K^mM7XH9)5bpb9FA?T5rr+ zYB!Cbvph#3ReVLQtrccod7V09-x!$uixdCJ?RrtdW68&5%Tr-F<)Hby^zGzg=|4GH zBT|0sO(C<*O^kI#F0w=pesT^5e{Dr_r_`K#yT+Y$QEb%)7%3KynJ+Im=59KY=*j#@ z(Q(erB^)d-5{;FmVISIOt{*bL$j7G6OQj|1U#KdbE4&}BS2Mcrlp>zS3MzX&ED#Z2q)Cnc?W4 z$Ni;*)u-*YW{o<9<)-t=gzxUNYLj`c6zKMRbKAjm3i4Q8q;dqp_VLi7?e}&=ZGOMl zRO-I`M8-F6Rmb*Im7*?!`)8I2g|GVO-dc|oUFFMCx_XD*juZ5C9>vUiCM3))lyWq% zU8PQ(hnhO~M!nYG(k2qwyRp@8nUy&^w5J_iMG9pdKwg*b4N9HnwTX&n`u@4kn$h(4fj#((|SDq zB zTEb8XG)>yc^T5eS!qC93u^n8_$!ll{noi+?mGi0b3We1K?heJNG@mOsql9O3Ie+9j z{fJYcAOLsYR}-{W4tPoq?#6~4VVFh+JY@oR;|ry68_z7~a&|moilPLWg;tP8(Spoi z3ahxCx~5~En4I~Q?+q2Ao!>Q$QxaL_>z|0(qC60{!^g{+$z{k0_28TpvlSBOBad4> zAbN2a6?%C=RCxf1@}9td=~cXd=s7gK^YHTkcsiD+AVT)a2+uHyh~vbwv-?qNURuZ@Cg z)c-9fZbAv6UII5*C{7ge7PIUYU_OBxOnICmF+C3ba}kuBM1O&ni{>9~SZwA1&H`Rw z;*jn?Unr!beYDN)On;4=Rmnp7{aXdp#l<XL;stWswmP(@{z??4UXZe+4hfE#% zgcK8N2J}TCx4$iHh37JIMTFb%$oisgWnN_HuWhCL5s{VS%pyVqv(JYDLx-Fq5T5Wl zWe-RlJ^f*xGuxNd&6TRiI>_YlT0i$&UrmQ^WMa+*i-eybYuRiPV*fJ||iIylleHJ`aHsXhNx zuX4Z>m9Cq2xO+%}B+vC{Rm9Bi|f1*rf_twSD zM=r=C8`~1%f7)I=l}cRHSSeuR`@AC;A41MV8MebHqm{_Qae6x{kMFJXZ0eNY`D|io zu4amLuHs_C1fqw6gF+>KITZWpb6y>7*>WOYWBsS^BCi|a$H$%F-CH_y%x2h&+%vmZ zOzFa2*9mH|PZqmJZfglkQ`r1IhJG-|N#?#}QKqN`@tz)?^r)FY7dl&~c~9?|p(cII zL|d9BZ0u8=7VKm=11>-~%Ha=q{h4XRJF#Gm_lPOMEBB=%17M_}Dolv6c;`b{<9m(0 z02nP}7YN30s_`-q#>Ck57}khMYye&%kd6$5ae=C^Axq+&RItYT#6I8^BI$=gFe%0^ z2+R|UI1ao*B5hZ_EqjCqk@Y%IaKeXZ3#h$m4T9-qq`p}Qf*FC12q2#&IyvJ^pGgY` z!>mD0gphiPPCnRE9O6x|DYbNKFw6_&L#9^VkXr1X4JNXrg8^bf`Xdv zKwm6nCbQ8C|Ke)sL7Dso_C>Xkz|0i@rR9W90>daGT{ZLifA^HoR>RenIsrsRy`Hdp zB{t#!g`xL)Z)W@$QWyLFap*HIt`G0__ws?V*wq}8*i~%d@N14A4sb_g=)IP+E4Z8< zU=AmDXWezvi}JThA{P)7_HsQr4Oa6iDDzSIb~Q`f(?hF;o3h`w;4{>FAmLIn@i$|7 zvdL>{pS}MHHvqBv`5rLO)J%VN`n%j>DZ(L|@Y;2p{;-RjD=4w`+jiUO$)E4$X3bt4 zCa<4c$@sX<_BF`ilohxA^l=L!sm)*5Ft-&FC9f@)|75;v3$%J6zaf(Bng8x@5c>4{ zK=>SoIv5$|D#+W1<%H$NTy;>O14?F9?D;mzAe6o?1=PSjiVL;O|-2iHretQa~K zcWPF?KK>86jgM&k6a=bY%{sZRp7g1awg^SmCiYb|GJaXj$<$U2(Q;3FRP;WL z>Uhet6+?KEP3gkRu_d-=Tj_wW~ph?~gU z;%(;dh8p;S=K}Z-_OlJa@)^{X2cX@j6*?vh`Z0E8e%vdkBH!+*Az9=qnXu2Sb z#^z*?9+*`0y8!7RbH?MbH+Nbn9H_Fm=MYoN-=++#TdOlVY+VVue5zYInCc6bQ(c#q z$&VwK5#|jY2kL{ke~mV9U%F0PX_yz3{N6T`9XC)i9CWwi$+%MY;4!gbX5*!A%JAD% z%3D9h)p@f*l{eW)PBrXCQBnKlV8?2eM;_0?%md2=If8q%w}(F~)`$CIc@y7YcG}7# zE3E_>nH2vB$B%kBCqqZDoMm@wq9AX@^N>$&b3^Tgk;ZE(qmm6BNVDGttkF$z+aYs# z%fD|BR@y#9*0dio%5@^8Qz0-PwInCkbRC)MC=9QvC~-WM&N0#ds)UzWAg$uLG>SNJ zGZ(j0l5-9Fsi@pL{w0}!I$k&W_REY>R6?U<0hLpPx%uDi3M#35-q$M^X&(ty*sSSa zE*>cESy1cV_5sZ`a9oIv8!qPmd2)-9WDwZm z0iSzGwmjW+#e~?lnf%<|GUh>a?Jj-02#sB!k^NJR*b5yA1POtHa3oK~acOan?$ZT; zr9mN}AdnOz9t2nYL+q;{kQ^f(J#GvZT|BsxB;;KXNCor@Pf}O{ml>D%0bMS*^Kr=c zAdnX57rvz7H~LDjbfSVJfu!9x`bMxcdC1=&kO``j5bqT(F*aQ%xbtZU_#~X4zOR+! z5gr$=lSQofNgqG`m@R{|!0D`6R17z}bZ zZjb3qPjaLW#GyL|hh!u<(O2QnU4o@)L;ePXpdh>e1%-Rkkarrd|CrOV{QsYp0+Zmt z)_&$pMn&yrL&jCvp(F1EC zA%s{5%P$BA=B*9pVm*R{ak0b%%Wo(vZh>P3VV#d4O~LYi!Lh2)BRutAr z1i1=Mz88>;^~xG@&-C?=Ts#bz0!ADoHkc6y%!mtS#4~gpk;dr!fYBL((V2_U*@@A) zhS7!UgMZ;1J6#b;w0CvTdFa;3WIPvovQ{gn^RXha27gsR`@M57HIlABY3 zXUyBSX9Y5`nqy$a^b2z$&d=7WU`Iz&EtETHDE^3V*jqDc$e6`3BPU0o;o|dE|Mu$G zRq*@(fl$2yIg_7*u}WHw(aE+W%D6b)y+*#+^+dMRb=NM}Rp_~L^S_zWZ<<@a7t^BT$vP>lEGN>$y^tv@E;hB;QP={hR>W^$*d2iwA329{F5jhS9g~vjTe`l zU?>)$nB-Ap=arzC_<>c&v`}+f)m#xbfmtONohGeBwxg3@O^;5KUaQv>$PCrKQj{s{ zJIdCdY~!o5G4LNP<`65LOs-R^$xF<3HY?JunKx(Ua@Po}%Iu3^(9|!@ua+!`HLcJ_ zh=eJICFlpc5Nk@d7Vykf*ko99*hJ~LkG9HQOtdoH*osya#U553rgXlOx9Dp_%^7WS55`S#EF`~&CM-0c1mY`cV9Din7yAP$?iE*w9NoJ zQ6?fTbnig#^tbuj8J_1&?_xjTUf3lvF4Q1q2LpX84WvmR3mM96q4QGCzZ{4Z@LNRa zU;Nq^0OK`SCb2AJ)Wv@ENlf{*e-THgmEF0UaL{8 zjb|ApUHA)WorQP76mUVOa{GoTmTCF_{$>0CfUx2tq3#ee77lk9(PpLAgI;o5=(6q|&Kf!T~`)~_Vwx(`uf{THVcaBM;1 zw8LcFF@oz?CV;iM$N!;vQ5@&vQpRG6y(fz~kZTE$Yb5Pb#wcJ&K#LK4(`Z%$sEPoY z3g`OONR0pDc?I=Sh9?&Z9s)BLT;7OrGf88jprP^B_oa=XPrQMf%qxUj2-Iu@>n%hZX z(90xFvG>L}6aEdg_ns~8zAR<|>;iCa8J_M-ZR0m{J5AJjnb(Tzch<4~2UO%GKRE$i zxWL}KeHtJa!>br4RcsP&QwQ>x1M+w>yaxvx>L{STY~J17Yl*#e9t zmg~Oc>${gR>%RPB`DRYKhgl`n-unu$CL8{zrrUcj}u{) z9Fr}H(;maST;Ev)`gR1c;SP@ky2Z?UkuK$5F~%`Cj;v2V!fN_H!goX{;mnAg>RrSg zpC>|d0XDclGVY_ChD%&HerNAK(XaX@xweJ*Z3+k6-O09XeW=xsdGxkdfEaB-*oKAo z*v3oc(&{o6d3`8n5jqXh^rVMkcI30TSJu^BoJ+X;F$WpnhK=oq&VL^oQuf&|iIN)H z7v7rYBBzP3AJ@~I!()%Xbje_!%Umh6{&-T_{B>M%<2-gX)qu%`h@`Qcho`N!dtT5C z)=c9Ndb-t=I9i^r5^gj3IC7{T-4}79ysw#`LbR9RJ!5CUqds};GCZH@`1^rnH`pO- zk*?xr!=KcS#*V$ADE&pRBE266uR5l)DA;#OgEHkbFeuWC$hB`m9i2C@E(=2@L!DbNKMJtqMZy z!yUf%Tb}lzgKhGw%j@sD4k|BE}+-MEi9S43;*JC$f@^OZfds$(`3DrY9k0= zmFLp5!{4)5YQ?r#;lB@a5Xen-r)x`zZmuYCcZGw+QxYs-ioD-8Jtse%mnO?0ZAIuz zeEk^k!$$?p6H@%H+C~{VFiY9P zC`|jCMA505Ua)q98FH?kmUpe!)L*H9yWWvdt^>ySP`yu#JB$Tt?SCsY_`ZKGhF!Pn z*bI~B-<>U6hHDSw>6VxX3w^IqsaM_@824&}YcpwQ~QTUbg#|#Sx%Z+%X(7D~KlIzXTP>^-mUaGU|DHZy>zqO#%hh1^dmXKkf(68qP z7Lm{O-4pC}u_+@9Z9 zK6#A(vAYt!3!F4tvOK>HKb2bDwfNRi7ZHflE*GBiNn-DqPn`^lq(UN*u%gf3jh>Cb zqqv$pKYkuOI@2Vk8Q;`9Gt*Uw`4RYb!?AI##~oOp!G)V}#DmjfnzAoY8cy&pFgcEQ zlu+YHo}+o{H5K1E9asIJ8qMV{zKdJ$`p`*u?F=@L2R+r4zN*2Hc|{m8S!sJ~1&keL zm&CvAE$iOoehOK)`2!i*)dY2g!AnPznkx+giGWoJngl=vMR(hOSgn1==HvIH2;_UwvCgY2U-KU9(CJAV~s_K)TU}2)6iA zUv#6V6}{m(!INzA6IWYDkz(vdf2$clGOvMco0Z70)aemwk1P+BewZaFRivVS%~Mse zi<YzeXNOqt- zuDHTFE%zt?R4oHR$7Gx|dt7KTK#fNA;SVa0GE0Mz>9N z8nJa+xdMA!I>v5AL6(df=@8|nki{O=tB;@G@Hk}9FZF!Q31U(ebiqUg@^(^Rr$r&| zR!qx!!^0+qZEKXqu+;NRvMJ;caA>IcrxG%f?A_Hw4uQAM|=cO6;+JzFVinP!51eyn%w++5dp>%GT{utV)=_C z*%bV@I3nrGYl7+$dcB^8DhJ?+M z6RfEq;Sc@z7Y`TbKbJ&P@K<1B8p)b(A2C0PI}|n^cDb*y>A*9$5Zdrn++#!lT>&+< z^ww`xU%2(70i@;laU4?j(9z$ENKIHqcs}mhQrRr4cy9-Gr<^~^!kkvE7W(bdX3QcP zsYi((!iDGB)l=s#!vs5)^lbcA=gxkNu;%~o5UQP)#^D)gfz$JOfqurQRfQ<5M@=UO#< zb6}q?Z{Uz-DtQ%Tk0jk`R^rbbL&$U}lc-yxLSYlGIiCtS_OWP#~1KTO7EdROx@ zagJ+B>N@(1J|iZQiG6)PpGZLMQ+@@Alnrwp zW;QFlW?N@x-ZJZ=nw~e!u{Ty3s2-O1+RuU;K;EM8&gUPy^6O9#dB(cgFRFKcz&Z9N zDl#=KVqcSM=Sp&@m*Q}1>{T)3b9jnkGHQ8t6P~(Ypfits>i(yy3z^wPsgC_2xd=_G z<@u-splJ=DQv;1nl1Si0)$$ZoWaRP$Q-3hCo8SY2zi{yZ2>jHsJ#`vS9mr#BC5!o~ z`}5SzU8J>ru6{xejzH)4)O`Wsz992S+hNHn11i)pVI0T8!y33M$_-SEY~w$D*4 z%A?n~ZJ(*X=A=;2c>I(ZlHgj^yg-T03$YZI!I^o`1FM~Tb1IL5CM3BKWwa%?ynumQ zQSJQDouY=W#2o~vbdta{Sw-8f!N4S9%A=WB0AWZ@3c={-C@JMp;N&J(2MB-WK|)sT zywpT_6xwer&MwIX9NnCGcms?Fj&5!j?&hS}u>uLmNpc<215!m2^o1TM%5R2}+hHKU z^W^yFNT_9dF;j^<%WrK*Nq`f`k4zijq*fk9P(v+!N_NqQ-krYT!=Gsl)*PrQ+Lmk; z%aG(^{fo!WT;h&h8D*tB+7C>G$c(e``J{YUwWWQ5=4%v7U&rB` zKa*BhN>Arx>mJ1QXTj;UF<2i z>94OyO5$E_;JjOzjv@h{t+Cm4sazW%xx6bx=nqkyeT(MaZDOmlFBH#=J_j1$@7elOVZJY5WX*dNb+8CM(ql58~)|IHn3P1W_^3Cac#6?Ev> zA0}@n4NGP9$LE+H_#3n$$6DPiZ!&lpvX_rfYcfFLti&ob8Lj-y-{4Nwp`FOoGeMq} zK!ZEiEB0UyZ~rktx%%6m2{~sShL%Tso!hg@X!QtFe~smPZZ6@nd$F59#;v~6Y{q_N%xs=LdWerbG?Sop<<(-~ z_fo6fjIfgP|Gqy({rhw!e`0KuQTn^=ACiUop~Hb-TSjpzTe9$fwh-33`@vMA=$XVq zXf@;&cdgTdXzSxzu&CJ_-=wx>B{ygC}$DAivo zkr0arSA~yrTg=|XdU-LsxlxUL?j1gmvQgc5c8PK(Yy4Fv|B|J%h>AdVrh|ZQhf)}-IH)T>4+w5Qhs*D za4-5_RL;}8EYYl$jKut~O2}rCMTfueL|wBeoYWxT4SYQuF`~JycdO~-^GM;T`TUFI zpZZrwpGC=Bd-Lg4mrPrHO`GkSl~atM`Y+UQzCP!)Ne_F_DU&KM<0Omc9ObHKPgGE3 zj?SU-J4-`*k7@A42DxVk9x4<7~{DGM&ur8Vs_ z9KCI$N|Ou5lAfeYsF^?CG-09Vzu*lK^et6Wc`+|%gt^8D6+%o{^=RXGKC_bjhtx__ z{pwSq1bHX8F1Sri?!}FKzJza=2~tpT-s`F)xzJ~k0Qi&)fW#-u6UcnBqyV7s$?^m$ zpDd{WXneAy%7r}Zn4}C;rN>_5)$Vj;pnon{7(?0V3;;bkw0Wg`N#A2Nofm{40GtCr z>j_)~An6I*17Q9MAOOJTi}FjHG>cmm3vED5P!!76)wa3Y!nEQ$&lMyW@m?xQ2F2lr z1bZ-^n&XSpAAsfCmqF|v^cpMy^NkNZm^E19O`9Ku0_7w6E;eIwKeOpMPIu5Hl1ld4 z4=T%mSoq$At;ggNUl4D+jVJwF24EPUo}*eg+$T(6DPq5oiG`0p;TH)O<~N7I$v{$D z>C3P9iKIk8OkFlWQy#eZVsq?#P?16!O7wbJx6Eu zK*=F8A?>^eK>*MIK#%kn8-ASqL6xoSI05+sIu@4?E!fk01USd zfO8H2e6jk*X{OPRZi3J_Mjx|i6`@Ybt-4k1ygCSw!aM-}J)lG5RHwA_S}#fP>8Ait zb^};`{?^X3CLO0VRpW=ot(-Ecp!~K9n_*IsdKjaTUfckp?ggN6$CFlJt4u2G5|wNb zwKB~oBrJRjCxD&R=ND!EDFBSyf!bZ}F{xZ3fR+9MK%f^e@zj$AY8K7Tk}f&4=7vw- zl3y#MEtDZSBn>24Gs?rHf^nNJDR&E`WLG$sL{cR~6gx&~Is=5-$paCN!1{7`@4M3c zB!@bIE4CnC$p$fub~FWE68zY}3|1G!=cxGfnkK+?uO`K(FEp)|Y5ou-IaIC9q(Tgo z5@XCL+R+Fo@?niuUK$xNBrAhSMHm34Y5@6$kyhT@e}j~!JRaeEsL;5lSDteY9W*W; za4gNoN)A0;dS@o6q+BLI&jZYZeb2bf!lY8uVT1v&#Q@fgTCF@2NN-x8q}-L}h|T{L z(xCq-F8_IegzP=SnfJYEORL2`{ZaHQi@ z?h(V+h&T0ky9hjThKp546-51K$3;Z*N>W=xLi@(8=uazH%Funkx;lpQSv=;-J=9T# zj~ViHv2s&JVCz@C24m1@{#i7dXLv4&%k6wfeBUXsb%INx&(ZD$H(gG<3_e|zP)FEe&FyiSVHg-IisX1w?v$Bv`fiAaBR1DVTv4#Ta(2DM(>k;Mt2pwBmZd zhbN%U?)3vQ?Hx}MCU<7L3|cU~(H?ezI3;7-yCv$mZ@kMLN-=eu36RIT9i?}y-*L&m z^XF`qGAdDV8fbGY*GGq* zlM4gRu}rzR`zLX+}B#*DIo21Ve^RA0!+KM$zYP(U~&WZis%XB z;EWU1KsNT>@7|jg*itzlaUlm;&_?z#%YLo_=u1ou$$)X+<(HU5aFi+vm*%vl!tMHN z2o0BMY?{Ua9ZeggAkC*bhKdbC2`Dy`M_Q7hmA-U3)Drr zfcPr(Hsdto+)a<4^7EE^dXD(!O^In-`6?U|SSoYC2GEN`f&lpmrQz0WyN+&>yYE8) zsP8^(OLzjTk8Q#1WfkR|T43F>TG&-e*Z#sVf2ma@VOd2nAjRKm%pFa-i?1G{*zKat zX@jB4THqGlZFKKO`lS^{h3zYS^j)r;ccoSY?=0T?f|6|y2f0_j5c`qlNLCYu@=VNZRo-*4h$d)n5oBRFSSB_Q)(q- zsxjyBafv)kz84E=4-FClNK{!cGUp~v=lh@SH!aO-Z=<7UxLEMS{Y_lL0WZBacteFv zLP2Bh`(RmxA{($E+FDqH+E*8w(2@O=iYizFpeK}6!M<0H>@SE0$UmbpWkCx2q6H?& zazZr(0|p!Z#Aksdde60_cW^ovP)e;Jdu0`m7QhfSz>omsb+E@p38W}(qA@r25vW_N zHh8hL3dRkUM?xyr22TO@E1-1fiP~V@r-kPM3+Mbf!_@*vt)KGG1P*}Q)SF(MXr#~7 zJ9~uhj?wu31S+SrulJl#vJ(5S`NgL%UtJD8lV|E7fW2WD$Y##acYz>gSz{0!peX-oNz>BQ4u}v$s8S_RB^%%s0*TDMVp~}%S^_)O8b$5SAb+bi=2S?!<~K|h#(tHN%a@> zhs(K9b2qC!AaL$LGA3^3es>*MsS}W)FNoq@w=XJtO$8V&v11^swIxI&e|E>^XM523 zFWV2Z(vE1c9xmEQ+Y1a`443Y+b@2fpV@E}n-Afr>m$MOw+me{79Ewa!f%**MgrX~FLICDC9&U{ zzfpYGp!l`}ucXJ%E|9@tZ82Mp^d@jA<-U_g5|8)9rkU&7&n_Hrq~^XMxw$IpMrr?C zQsrkC&0xKjng^J;ivg4JlPUhmM1!`IwBl7L^8-h7RlQ;|gROzHbH?L^Ka{)iljDYKaw>3UXs}KC9z63%kVPt$ zP0MzkqM2#5Tl>q$84a3F&3M7+d!q_{PZDa0-gaj3R=RX|%pFB|d$ zf%-sj1K~PZr9DAN@!fqVnJ=~~^h+PYLWqk|Ql8yH++>1_5FHHt#y)RI8^dH}BEusU zBgwc~K5#L!(cC61zGE`~OHn{eP193AlZQ@{n({)VDRU)1GfWPoIc00Lhz~dKp1_5 z@dlHGjdBE^nBeQrj_*Au69a1>bvNyGWdyyL9Nn7G;oDUc>&l0JDW&Ra127|Pc#I@u z)U@VL*1x(VT--b6b$3NpZ)2rZV{oMk3c}Q+SjnO%mC?p;RTa9Xb}m6~ zTTVD+2(dy{U3?l*IeU!i*FuTFy)|eaMRZHRU2{p7Nhxi$&k#`q4{!>66#DD|L`Ao9 zPf1$PX3l{?g?n)LMg)Cdrjx!WpXNFBT!%01((5$rQ-dBzHX=B840RIqP8 znunr(!~N*sFk;H_EEF%Cwxjautrp*9hOhc0^K*?tA%WYUYrejiuPRV)iuT8mtoS1` zTelUycP_v%LHeoZ8=EeWHry(B?s6;->0t81AjvSDogQLs6Vwk%Z?))(7)*^2y6N0b za&{S3)tw&CK`GWfglH|=D%ID(+9}%3?^l3-^Wt)`?9?*gSr9n<2RC)VQ`Ktt{?28Z zv5~h@V=Qc{w3YCq=ICz0@E*2D{muKfyH1!#csqD2w4yQdhQ;Za0W|S>H8^!DyY`h@)$YZ;z*j}&h zzm)emYKb$ef^>6P5|f{#g6F;=WaYuormfdZ*kf27vR}>)+AB8@%4r;&&u&ySD16n= zIw?*r$P`pi5%cRvi!o^R9A<5G(?E*NuOGpSh$B@;s0;18l`S1D@jfkV_|$yDD_^@-ZXtg}10ljBphQ z^Kpg$@#1rN%E3?g>sez1`qorf_$J3GaKAWF&EYhV0&mdSA3$ zAIR!bB=ifq24x6BeAC$XX~F3xu@vnsZE5^D5o!3pWt5Ju5(OJls3Wa(zwUB}cZMSm^-D$I+q91%`E~~&rGe>8k6ZeqL)DR~{uatKpZ56OvVRm` zGzzKR+d?z6g{FQ%E4-I0+Y;nYlJ`l3N(3@X2UNhamRW9`_K@xC)8qvR2H{7S=ZiQh zHHL0|U8G z5Lg~EyRxRUC|!;3m#2tOST3@Pva7Qw<5PqrKvVxjL-0hC1JD@O(Q$+$^d;CAVo}Yd zJlT;Z%~@%)h_ywz7oe!SQutUAS0>MgCNmU7`S(LH%%#DTNT)@N{8{8KlCL&%g;ITe zOpuT)j%l;rA1=S3-fT<#IRM;HRz}rog2Sd?l1*SUQ&Q_l$kqkNnPW3gQW~k03uV#z z6b7f6APMcEJbNJt{TPZL{f;?@e!0`P$Q)aJlCma8(peJv8j7!+!1SJ3M?$wQxXB#b zWs>qNNAd!2gyAa_GE=hYNEp`z513=ePg1hyN;*qHUx(u>6EjnCX^UFb1<#vf*H2P9 z=1N`wjtG3^w0ZpZd^!?NLt)P*Cn-x*xif}xx3QKdDZ6teSkmASHuP?75i=Bq=Xi{aFs)mL z#<#)@s6%ugGqb!jqt3v%1IkK7@mdIi2T&OTy0P#V(qv(NQ8d5#`wSs}(lPNxw+r~~ z3sI_Yn`xz4Fcx7&bi0}ZTmG$Sb|*de#>2_@5Z3bZ;O1ywYsW5f%LOD)azIx9^3{>o zcjHGF)ln2^CL76^0uPCz(kD9)uc%_`%TIPb?}u9RK~A*}_oC;s8t`wiC_Wmh2q%pw z*C=A=hKhxU&d4i#U7s(y75oJaLreJ$J}y5OXpNH>xR<~D+$b#ifLT#1rdp``)pew% z`#9O~53!|&#O|X;&+WQ~+T*F^^l61gi_>*+W4WE>vQJ&xf{zcuWkh}Wv;ZBKvcO2x zbOe>xv=R||+1RpDG59YF@V)onmlhYc@}m{`Y4UI$Z6Ti(+sm_&I*&u2aoE9utj2LZ ztG4&|G1dF_G$ZtXQxn3wktzGCqI}et<8Qn?+y#{W)o!S_eizgi){ok$!+3v&6~+g; zHpd)r&*9IZ933BX{e<>+eC^&_#uejd5IXsKjH=z$jpk|rV{*4${4D)?YW^k9&3B7O z^!Behu0QRPnY^az;3%uyz;cYO#a!9JI03&as19KL$;#qXtdNf(A{P zhD_LJmrU64&Dn|0d6L6!wI%x2SiZ93=dlx&%Htms-U)Sse^LKS8ltvN1lmuaB@a=L zd`b3KR8ICUuTAn-Y)tYWtpQ|JlD`FhY}Ngr?({xt>((LaveI7af5P#yTB=Z4El)ra z0F4T0xbd<{dF-g?00UQ+NRTUS^rt3)WdB2eH5p)_VTi3#1mq#m6dLSz*ilnW*ibzO zjc~X@rZ@>kY{i!5W;p7xE3B)o^#-19h_Trm#^M2lB%JjO;t(eW&lG0(z^BL{gy@if zQ;_3p7(UVoO8i4G4Fk{AIPKhc+3)gx8^KYRTF(`k$v$TdPH20a<2`q}1y|&Qr~4O# z8Y`O3baL)Y!?mwiMJ}Kf7aLz%Aj_+V@RkHQqysbgc#h+l5(S?xr776OgP4z0no!6{ ziO)D?snm7IRm#`Y97)APmzpDgS?cXbL$ccsGzk$US*32ze_DV93xvLPE`Gh#4o?XoPpO zd}ImNx;4G|PZHO;jq%lm=r6Y`W7DxFNLVu}N4$HaDN*vHF#F1$y;AaOPX*KKg_73A zocOaNOb9VF@3AlEXMNnYlJ?MF8`+_l!~3{=v^)CYFx0*?#0y5of^Q_prQTuj#m6M2 zIg5m)p38+^SWF}ofe{?SC3mIO1s-A5+apLD8>%ri+&cuO%adJ0cac|&BpQ03gx!tn zYaFD!x28^~;uRw^G`af~zBDYQTX^BSbktlnfZ}b~g2HU18Hh6HY)c@*-ofq0c2wRw zRE-BM8Zvjbo?)%h2)S`3@{)~;hPEBCE$RB;e6h+@7Bgj9pqB_cSca^G{Q%-SZj~Fm+t0e?~WRBeoR`P+7K-3 zM*Hy{;u<;J_n%?@SsWycVYrl0okIBQfL#My$#UCdk??13OaBor%f1K8C}G_C_={wi z%c`mO_Ber7=I!zGSusv2%aXC% zA{&1hX6C$bgivHg2RWn6P9ocA=24KdkhFxZT>cA9?+~b-Qa?xas``!b+v}P9;PZ^% z6=t1kE0?XwOh$~y9vGV;n!eSo2e%X+;ac)78Ax^(a~y^&haMCS-tO<6i`<#Ih1zG5Zzf&1LKb4~DV>!SOQ?pR9>^p!&| zk+wcU(U$ZN7*PRQq6@@5$Te8F<}rjlFMlt*=Z>01IrXdK4#v)_|D2Wup1@+%bNy^Q zlC?a6#p9M^<8*h=<})Fo8~nlKLj*8h4A=HUMpQu3ldOmem=}w+`OqE}KqwCAV-xLT`ru@T{u@q1p&8Zq3nU^dUMm_rOFEtWskKAvC5Bf3R-mt|2o>ai|@5w`FQGg}B z3|R6jQt12Cct$VA36{82gR5;*=zDZ{M&B7#q<(u-J*UVKK=`j9S&ZrXl)?wv7Rv&{ z)TdFCPhplkqt5G=uA>+3v$LOk&<@qi3%9%zTV#Ua{r&@(J~&H!pb&HihH5bo&RyjM zMDj6_cc>CBz>bHN#dNV+6@2n=FJc|tWdv8%-tQ2Oc$KdjaWGVb@X_!3hCeI7c5jF2 za-23eEmCdU__d^H875`b*lLdE`|6>RQ)Mg%lr^ZF7RKLzYtB9_&&Ye$wG57dySmNAo*}!oTTuvJJX3z8CTul4(X74OO9`xC z-~aahCUXq}Y%swSqf+9MnBp@K29^kr+t+)D1fsEK6H+12SIApYs`>~LCA$y%DP5Kv zl(=taRxxW|4)Z|ra(eZ?>)>~L68b_r-{Y3I^sn+qhs#UkHj;x^i-+nM z5fAzzH?}FxMYjyMPz^svrTn?AUwFbZn3=?^nyW&~IFDDAJ3jX-Nwx0o8W&lKcwSzW zaC%v!acn$QL0eORScQFz1%zg zoS0wp(q6Y_4QA5iUF?OVN5~9gi)Zy^%$0Pd^$eB$0OMkYLJN+6D4?->Gjn=(R5;uP z9#MU~=~x3cV9?;1#Hkrc3GW108sZ)hF%KewoDf9EL@-ttVmJ!XGFt_T*1JYLkibP; z^SxK?Dcn0|MMWm8GQA8J7`6-p)V2&WKmG~7_AFwLd2w6lrarRRf_)>h9lH|2!|<+h zaw%SzrudBJTy6ksnSIE7F03Xg2<=?csTxwXP+zH9P&G3N;47u(-mj=6($V~ zQ-7!h|7z0eLL=vPt=go^idFWy3ku#7_TbQAJ6D{5d`47eD^WJvh_DSaZ>hjte}BHN&OfhC=8?I|4z6;80q`|w;d*2bCl{ULB_o z?IlFW@*m_ErS8|Dy^kB+bV?0<#k0JV#D&@$)K=NbdX-M+TCpe0ei5C+CQK%3XN;w) zF|E(Z^mPZA%3G}zVs1Ge(yo)oZg*_Z$4FpX>nrY+AM>d?Pdkm%Hx|lw_OdYBA21G+ zVzn=b*#ht)X)R^nVfK*hLy?liz1g0*7O|ojVqW&T#d+pYq9_}@?fh^A{aV|^+V>WE zZ{!vwsYi)6F98H*J_WwJ?%g$UFbI2zf8A?t4FEX9b?*sqqW~l14c_)}H?|Y{I@kiy z2TONG&$huez?dvufVBJXMX#tAQ$o&*ByBB`w>==0xM$+&FR3Ng|94BvkyMa`Hpzuz z83|Tc1%JUEXQJ=CAaj|!i1bPP| z!g}rFuA}K4f9BGXEf6=uiT|vw1uYB`>nHROle*i1t_GYU?i&tH8&1X}pngm)p74D; z+lW1L+dU#9AAA>RbG6w{+t+L}RCM zOJ})q$NcgNH1nKCBzMN3@$H#2vf~APR3^xONf7<)%xz%sIKZn_VDoQuR1nWk(pK`# zRi7x&#k#CQjpWZ}kN-y7`OJ2bWBL!7H4hsahaP%X?lgW`KkhqvriNKe+DsKL{M_i5 z3KDFZeyixsq`OO}DI;=Pv9{-9^dk`=BuHk*pFkv^+my>fgMIQ(eY(l-A@>!3O9c7a z*NsHxBYT%bf_yO@AKF7U?~whU_gM9>2#i8SVwqq#%3k(#1vhAl1vhrll5<9(2wrVx zwt^dR!0-q(vca5Tw%(2aCK$Q0r@ctd?Ai~B@-FmboqIEm`mqL%df^JT`jv9FdbmGx z6P@Y-AF=8|G0@C73ucF@3uXg*raeM|meVtxl1MlakgT)H$X0*E!d4#X!uRWH=-g!2r(_hhWc1Lgc1t4Pn}k z01Fhf(KlZp7^@IeyizW+5JEef=$#(W#7>FdS!;Xc@FGOlhP6g>Ep=nmo7GzLT6%mA z^P(c3%(^l8`p2|qfBCB(O{dlR_V#tOR z8q2`+FIHSDxw943%HaX2IU0{^~Vgib{k#NdC4>6iLCGPtA4|`0=;%K{u+<7o2>Q$X+;(fhvE2- zC~H1_?OHLS;0 zH({y>t0RQL&WFA8O7ev750lah%@)4YSAu%d=b~VK4!wNU7zQ}ld4Hx^6y`#Y51u^D zdNJd0*zg)s>XM?h_v;mdQjRUco;5b$K6zWXTS$?K@W|?0WKO$Ym2?;Ru%h(y#*7!5 zd(QY*&y?`~xOO&|9fqn$NFJUky?u$meE^+wkYpfSh~i(r`1IX6xeOuY|4t8q4#j$? ze0!Vu5BOSGvjL+&>(I_Md!-jbd{X8z^)FN8Ov2gka@_~krZMs3--1h|OWB4eCv0q0 zoo7}EOw+P5$wG$gsx(~DF;+#)lwrh`#y4rn$u|nyJ9U$nh0Vck{f=gty(!E44pX%o z8%oT$EY{4pE=A0^4uALOrJU3%)_+@_olIE-@mqFZOE@Xsgzn}XbR~)&-IH#%Rf+=7 z6y9vX6t57Fh4KqOb6iqhusN`aT3pGm&xAC7?_bbZNRREV!{8_}CzGE3&2L&4$M1SC zet=^@bT<1-r;)|%y#cuN(!7=6Y?^dHSyRmCj%~A`^0PiauH$b!oz=ule?8}vS&=^& ze7jnQM_rLt*VO2jDj2d1I>x1I?c!jTc8 z!h5LAo2Ua+9RZ|{RGX2D?_C88(2uLI9Q)999u!%{D$LEPya>#xNR+0fGQ9LjT!i)I zM~KUXoLgJC@0Qzje$Vm_ATL@Dp0|94YbvVJz5Ki~hvL{S7j--sb@2E;JRTB2IxbCO zM&`S86vr)mk36vV-8_;7g6!B#v#?=T@jFB7F7#^Cf3Chz-$(1bXe~YST0IZ^V~orV zDgJycbRMUQbIWJVEN=28JOUNGe44ac|N1J6%twW5hob{|5X>xhvCo&8%kRP2ohjGI zo0)#hi$Kw#8Zg*NY9XsS_N_SCJygIV3%fG7-C|Vga9-8Tlw3xh1P#k~@g35ZRU$42*eEQqmK@cJdN&e6xSoQ545)Ze3xOq zy*c*d0&j9;P+ljvUBXC7X?fyxYErC75B{f6zFX>WK0Yg=V9k+18yu&z7S8QWSF4dh zU5k;yUjSAIT0PL1_r^aIu+bITTKU_I435i;49;1O3|`BP3_4M7Z!-Qlf@>Km!BcwD zyb6F8(3kcg8^U+X32;C1zs5|C6{%pOqbLJf2^*bVAsgLs5gT3QIDS{8K#NEn7I>tr$Rv0!S#1lcTt?QoE?Jl5jM$ zA&b+Q8(=jL=W}-jngP&A3(0(YM+RGDM+PlO68xJ+(ptlN($Z3)lu{gY2)`+kPRs30 zVPdB-|OiIAx@3UJ7q(ysKPDq_7* z0F)2-48EM$)i>$tJ?Q`*{*5cYU?h95qxJi{uFVxwD(c6#X(wrR0gEo_i{AAu@?A5w ziHb`+XQFLZ|F9l_r(QjO5K(K|L+?YhM380t-*>1Vh!$hNT!gNPf1bayyn-SSxCZ=Y zn~ey~{(CY#PkrHE8i{Ba2o}48gx*$eNg|f_n=q&!8~1RG`##v2Zf6*79FC0k zl_lGe)E2%X?yIF>bn1IF9#Kpx9`R%v9{6`1eX11XH1t6G-SqQ>#?~@^d7LZcW=f0t zkO!ZvEWg!tNCn?cUM0bLwU7xs0n+}a@F@X7r=`utwb(Shl*lz>>~=IvAF|USV!ZdOJe8lq5DKmtKP9vSWT~9}s&0yK$fv3Lk zbY|Ci>%dcoaP{qUxScq1*zu88j+a44vt!M+sQB*cT-Qo5PWt~gd^S1sHFZTg+)nKn z{E8_(H@|m{r=$H6$Fn-+vT-HstbHfo3jAr)3qSTKwHRBv#kBdq3&2&FSlTlT2|f{lEie7$V}I%HP9S16w*ZGeHs4%?mY^&9P%ADOqwQt)-wh3d?5Ca*OZZu5r3#B9#>!arn+nd!u|xg^fS6Rh=X1w5<-N z#8>X2l>75N9=oeCYE5@Uk}w&N_>}Fni^%S3z#`d4L~L`S%2FB0 z7xR=)AYQ`J9tiFb=n)7Z+?d}uvC?!2FX2IdC?ycbjs=L8D;46Mrh;&@WDELB*MIGc z?M@qw0V9Vvcb8mzmBXf?BQw@zszIRwYkv+@&W$`^0F>na$t+F|n^~_M)Zu?I4%I$%t^XYcXZfSu~@`8x9q<#BADe`Pd_xu}` z!qKg?R`{}5eHv0c34a{tR-KQC*N^=+BGGavRi4O#ru^lS@0EJ!A)Qz$PxP_(i<`Ls z+uPGicqD4;lJ{aIG$Tw@s5l!5*o6<2CkrbgK3yj6JKL427cFmC=N(eTtr)%20LY%y z`2VJw9!R;g*4XA!DY1~W)&NS$4dB;X)~%+4!#6ADdXMVTD=9{BRU#(ez3vl|eI%%- z_4(p6L+y1y`}F@i3U>OeMDfq-+Rsf{*uBas@2K@HgY%W@yN;91gIBmat9YkMVPm&t zu(RJ~g*O}1g&PKCZac?n_IfK*O-L*6TI3z)K9vn+k-L(0wp%i75tYnUVcKg7?X>1J z)#h#kP)PVU%k98KcWD`ym#aj%%}Jk2JtK1d#m;`b`v}y>=_H+RT-l(-WBhlugxpBn zvC74HnfmHEhP*+>pXON_jTl4IS_O5PQa2W_R35F)b0>xsj<3I0A;%5oXKr-dOk95q zL`OW6b`J8BzmmhfF0Z{8XV69b+1@irI|mn8?BGvo{M9$6FmnptQ#+>+`O5Brqwzg3 z^n(BnO;TFbwuePBk49UiC!nfL0dpWs6>17dnC10(!$>)ly?s+Nmu-e!G5*yM4 z22DBhuxS}^8yzVi`6Nyo-B{aXDXXg6dcsEXCmXaD1DYUfjg`x)ZjCkNl%NY~m4ya* zt2DiOF;pRPcQ-PlCCCegcu&N#fTfc=czMv&L^0}C3*kr0rvfnDe*q-`(%$I~V7XE* ztUs)uPR(?qLJ$=yEgiD60?<&iZu=$Xp|qw?UsP>3pvx<~HnI>|BZ$u}18x8(~dmGE0qiAW8wJh2cM2bH7XKeB+snO~Yif3O;%Pr}o zl5e6|%)44q_sx%<%2|OdpO&hTy>fjZ?C)CK&NEY_1YQcM7$T@U1*g5DT#NH44%Dl8 zXNt5d-f=ySU19`*Rr)tI!8*Zx|OU0va=c9(l@f>i#mX94TV&sx3+4=qU# zAb8Xd2kORf$AM|;N{<3Q5V{Vmo+t& z%PM*ft0R{DGe-Q=w!f~PRj&=XRF7{yILq(FNs(72I@`v{9@4wv;is%8;<5j{Wxrif zVOb7W)dTji5!O>P?w5wy7gjC(`=@7aB}ta~(>9mhGX_S=RbE^^{rlC<>GPLck8M6? zgt%Q=PcAO4Yt!#*wCJjG(a_*F@)%QA@%NoI$(X8GsmqLPp8UNgyzuQF{m9sxki}O{ zh;Wz+@%ny8;9_2KCG}bX5p8jCy)A8#(fl>V=h%cC--xqX`4e5Wvfj(;QA_^Ux2e{z zZ@>I8yGXHnef$1piVxxI6rT(5RXSxz^ykkZQA|aP43vfOA-A8L8}%)F_G3yr3X6N5ls_+D1={S*9o zeket($ll&hIt`&-Ea*LsllaOuQ*ftea(_`NblS6@#oA&6?H~>1Tqd<_IVIKJZp-nv ztwXmdv$A$*w}KOhuCHCc9-q10=hz>Z+L_WAH{1`+@|lV*wkV?j@arqKg`)TUy%yzQxOd{d(zNJd%%*=veeO(W`W<3>3b?JCq za|soZ?Tearu<70RE~OG1;dZxf9Zu`r)@?Q}E|;K2_+QH@E- ztmB+)hl#hYZlC=LYc!4GD){ztDD11}%;O z%f!fM6|KBFMcI1h^LfhfFVQAxqDi;6R5mYs$tvzVPuFQ2ak(3Fh*%qq_&*4w^-XiD&tmL1H{JKm6*!3^uIy$Q(2AqCx*rUte!dAg;)^i8fQyN`>~5 z-Jh>48Pg$NfILON*ftY=vMOaw2Kx7yIo z%`&#&1n3z!BxQ^d9it0-{INY~9SeKhOW4H5FEfwMh>1OJzhDzR59|=f41Muttb-Pp z*bcNlG(379=)cD2fQu2j0Kyk$w6M$`@j&vgc)AZkrCDKSPY1X`p!*P1n)Quc_~PDErjZ{YjpRh2HlQUfSA>;iOP6?i-9anv~RJG=^d^;_*v{WX&a}*o<_5L{9tpD@h zs1f5pN?k#jdx+cE4u7Q%K_Iytyzb-|`ArK0*PVdA!MRV>x#5Vu>uH@;m<^@`L;0gZ z7Vz=2zy8#se~z4PJysLNO^hOX*ZYh{137)QyFUBp2RBY+G*N3|>F~9bP7)%a3YCK# z2>ClonbA_I`}a*w+rPc5y@7m{QI?;kjLdq1HN2t`O-6sc777OHlHdKQqf3Y^9qE)0 zNS9(6EV3ML^QA%{)dUA{y!dDSf7HflGxN7@2?RzqPpXM4`fD%nsi$!Av)zpgqV0_f z#P~vKUo}gJZ&e90^m`L{*{Cd86!#HIH8-85tn^RUvNa0}p}y;7r0A#UIoUlQYIps$ z+d3KC6?PCV*o9w~i&@ja>x%(f`=e}M9L(!0(U+Cr>QAMsgR^^Y(0~SRHfYd-2J`x# zL%s;gYOZWQ8e=>T2~r(@CS6Y)Shn;Ln%Yz$Rpx*XgQ&WbQCI~_V?{TP%`w~Q=iPRq zwTB!M6ct0!+#cpAtvWROme+p%>|M`wg9HtW0Qt3q8zg?kl$iaAJkr`L>ZF$qF-c}v zE5r<%2=}r#{3OZD zK;R(Hk1fus8>CT#TV@3@+~adCe~dYl&4H4yOdb!@EPWi2U^3vO;GCx&Gz2i1-E=bP zg}U_X5sxg{`te#d{5MvWL1_r=QBr37c*=Dj*p>(ISQ-GjhdX}w$bzABn%REsv*)ul zfay$chE8>qTU^#`{kCvg?)Wm{3pp&rPnkSnWPVfKr`u@oo`RFdAtI!$_h*V<%qGch z#qA6^UsuhgCp41&3;yNEc=@OCbM?z1o6n;&qUx8TYSV3_sQf0sE3OMnDjGE+{(U=Y zQP=h@JN{N?Y%hjmadV|yySr_jt*$m5m)31FA8EY1~#v>mtuJ#5m=lsc^ z23tu?bei!}a7G<0;Z!rS6Q?+hj>#oH`Zs2=gM%-k<%0)bOz-h#V+@iIP3#a;^u+@n1OxKb3{U(~{UdaLYI+5%hYCYOjOHK`tr8j#-YlEw^K@rC* z31eaJ{$8d}OZZ<;gV=h*#Er75m+dDcWzw`?Ai=I!R#rCPr?W2x3L~fqsAdyXfD{O# zKyYJK$$8sSsI*?}`(br@d*%oqMY8^7b+_ncfUK)whPbz8+^|zg*?9Xzb$sZ)y56K^ zMlCQxj1;f%`PUiZR~Y(3xt;#63pFYjMxmqf|nJFr}p~lltI zCmXFbW$?3G94f$2af@&DZ!S)Ndo}e`hYMG=j)a(ueZgzW6A#uWa_dz;po3CqSh7jz z^bTxK&?R3OV1Edpe0i9238890|Lt-kko|!Fqeq(WH>K%7iGBqO@Y7_>N3%Is~#ZXh`Xn9?5=pX& z_9Xqqb4k(hAx4<=&@|jJ*g35@{X{5Q0@&CL>VrEL1_I_RB0L}2-FI8EG)17dlTbwew{Hm_DRb{U4FJ{~{#|7xr}8yLo&z8B zw5`yQD~uNaIDdo-9@aF2Q6+iRh<%Rm?CbV-(}x(|mPppQim8XIjMWp_j++F-Xrj9% zwR8WHW}K!!m1%6Nlp#ulYWbcW)Yk1O)UICr)$RK#lsh(ctvW}gkbB~t9&h`|C>AO~ z69*j;W0#uF$d#g^c~L9GFW>yRRj~=VYoL33?QY{<`Z;e&faU$c%bf5TM@fz{HED$+ z=X$Xk&eMdvaz#R$rKZ%_Chv-AFP>#K#Fc=|{#K*ve(kO4UU`L4ycbs*3*v91#KG;q zcpjymSKJfLFl*>Oe_R?3$Z1w#LBPxkjmDLdZZ&)as_ zTDTTNSACZwLsvP&ohSndE)^>INV-HMcBazy_Q;5+12=U3%!Y$SB9OJo>-haT*M zPQsR&!=w4;Gx+NMsnlT^?DJRNG?@FnX>fJ;AACy=uuSg%xjxAQwkF$1|rUN}r7ij;C7L?Xo&9i~gs1IVBDwTnj z{UeKzAIohq9XAQnEOKOilJ;f9&~cOU(2Dq9r@Wi()2Z+`&2tI}gNj#YQEi)UXwi!; zvyP8#djIw+-8pQ9^-o*0hm)TMvBsdO^<)KcApFJsv z-da8>sN7#ZvBcKthT2`71%bfwX{)sDdWcwBdEYKo_e<+5%r}~;D#EbOizk*Pt{T#3 zZzxbNIRD9}2dJwAUum;16DFs$qZ2RT`e%4-9(^Z`^3$dvCi_rI1jA>pnKi@uj+@9p zkht|LM1EK7K34!tu2r2_SEXj5L^3_RYhAtD!3E_VStzyP(@gatN5zA7?hxMji;J{& zrR3@LopuZ4IH#lApVjur)Lb>^T(|kui!&jM0aHGUWk}Oqnr=>FyL0HyAFQY*sSS$N z1l=cg`+g(%{|Hr`XG41ZvU$Z$>gP=ciL3`TdZ#o~nx|$e>^>}*v8yfQQ(8ORJ?7o) zbk(%lcVRpHrlWZ!Ldvf9Za5sbbtU|b*kX9Gm|>LQ^0c-4u_&Srp;)#MU8l7$3eR4y ztc&&9$z`+-eHJ(G7!*Cvk`pl9xWH1Yu!vP+6HjGb&zV2H{v~_YvveZ#`!y86EMoUP)3b4e+6u7kPPFv>NP#@r6~hc=va~!fQ?OEt7J04RkBJ z_uui;Y2ERziMH9IXgUuFCq+DTN+>wYr=1MlqyGe#V~0*T+H5^%pt4;_25|L1(`x?S-~zpNrWcA|r^l z=x(;QydmB3b&q%XYc5WQk1YAI)CBsfFFnB}{T{l5QCzTh{5e{KSlYqVmgCYhxchd} zTkEWYQ3oI%i)PhzmqvX%r57yCV4(!dAXq{Mgq_2|lGY>a+ys_Humtu9t5qjkI)y$z zr`k^0(AZ8f;Mh)S`HJro=4s)b;A!y$EOcNYP4LXmeLZ@vl48mC%Y*9XajUeSX?o*3 z^Yl-;L)=M)L)@UVfg5x-aC83+qXqml;LT|>0GGUK)?M`UMxa}`M71G??q&Bjyr?O|W@!r- zs!`7i!FI*)@>@jph1ac&6pkJBr;2t?y5`Px%b^f%88iMLsUMfmJw|OAib6flFgdF1 z_a+x@7e!y({wJyAM$D2Q0rWrocM(k}cwlLNF|0g3Omt^uUumxFGN{pfRQ6g+vfkIV zu~qR;&2HVE+EM4JX%6UBw+^{Ti=%Q2wF{|N8m!}e&)YM91qf0WJg}_X>3sr!Kt3J+ zM(HJ7cbjVHDiVIachKkAyv4i7*f{|3wfy8hu_3<#lkI{M0 zx6bN3Tvp#|xYvgIEV`~E`-7Y%`AA0|#N%0x+A^k!yk|`1s7i6*<4Af4d z!cSLKz6ePPn4sK)9^HxMs#)uMnLHe0c^6iGfx|4+w z`{Tk*jsDTuQL)TYrDD^>@Nx?`L(>FB%$}UYLFdfdTMvWGDgk#K;eJ$KTJ81yFF015Zt z7nzvQAdWZtQ;zGtT%` z{88!7R@CUlBpP;9yag=Fu1ACaKI1ZanSOxEtu$Q^W>^87pf)-!$g?%PajY3NCcfBe z#LhHZ^<{hd6ifC3qgtOJ?Iq*b>9;0Y&}XD){|YYsu8X-EXPWHn$cJ(aN^`Bi8*CFAJVGU`K>^N~AdymfnqzDdTdc&=cDa;6Ad zei4kap!+FEo;@ce83j=Gltip{nb zF}udG-H3fVu7(MdnA6q@ZR#aN zS2AU7-c1bqjTKz2T|NbT$kCiY(+byM&qH# z2F>`L_Bogcg7%U5eU*63i+&9MuCnZ>XqX&<*t!o0YjD9yhjy^;$Lz6A0b1~9mb%$nNq87BUZnXqvLV} z5@#`^L445Bq|MM{#-PlxSRW-KRwZY2XpxWj1tc?}kMKJ1IWWj|A8^#*>YKScPfDw> zaIoeDPpKK^QO~kkaoOJ(VJY|WJW#f;$W~Ie6q_jV6#NYlc0M`HTUGmeJp|uug{yn( zW2zaNv1a5Db<^I9U+)9tVtAi%y1#`fa+Kl641!ZuLV#HT$<%S0$v)#~ zK#HI_tY{aU6l>BP`$=gtyF{hm>#o%+=;zH|;jKHb4KL()<@bIO5lqGXJ)JpWoKHWyeMF)c8Y^~~+>Q?fdPjUjGAh-KMyGZZ_YXWrt>SOJ zE_mrihY6qTEO#^Q${=qM;f=T z|L7QxY#yj(?Xr(7Y~>insMcPm!IWO+YpGDh#<@ptZ=aOUQn!taZq^0Gr@=RvULAEg zZh~RjBDnY9>WBT~unnX16Fnd+XcHW=wBa^Wj|ZuYw9(D-#xRAMaVI9#KXBiz|z6&h?(^fj}ugpz#Z+=((2ap^Ccu}~c3xHa2#H0xjeLua$0PJ1vl%sr@jrHY=uKnaL{X&Am zkpK5}zE`6QIREYl-VBl^fOns<&H)&)3gD^n4XVB-4_>9xsAj7e4Oo!vC!Qmvw@E7k zBd-i@ib_Ma6C5|Kv&ei}!nJhQq^zwJZt|)p{))_J*&&fpVva+&eV?bl z=f3U(bN}9*UHeIDJLL8OgD(O1Bi->?M<0T1AY$K~^*-$A?$P=^t$k%M{jbV)!X9GX zk~bxReCa%oPt%y&SI>U_#}ebl-*2BMxwF4+$hbZ99P1-gOydf+^LyQVcbG;|Y@E2I z(pe29^SC|P(_^_jFI^2~YJ0@Rxl+|sRpIQ=rO2pduAt8j5$BzIJ#9McBKq!!#^|-$ zPOWLZ@4KCht(u2oU*+cf+maTF;JYSAhURbKi%LT zR=oJ9oSlzfhORkw8lsy27F;j6%O#8N*<`k7^xT})GTnuC-EN+9o)<7NkQvIKfklp% zCYCuF{Lv^&Ep9&=nkK#G_?g6=2G_w5GpBs}j>TxFb#kz?$oabFtAfyi(zfF+G_`XD z%&Ps=>zdgdUVE!qQ}naFTrWGZW%bSC%C;sJ!0Ga$W>?Z`Ja#ObJ9YqzP>S`*8?qw3 zRc*7*M%gV49J&O8)JSzs2OiDFM7dI@XCx*1YV?|ojPj*Ur-$|~;+l=e3EErxoRtG) zER_S(?@ba)U^A`Cr<&X@sx`ZX3@Yto0XhgLyH-ld;o>CcgC$dmqc};UB&V6Kq^1y0 zt-?Og{oXctjVb8teQQ`r`f=^4z;&VUTN3eC{%ERhhM3Q12IARH1>sbWsUtA@F_>BA z{~2n9{-1;xFZsn?6&5*D`9XlI6ZmZ#3%NcJlj!;lCc(Z#!H+<-Gi>9>Ex`A~HpB4* zwwvIM9KJX`Z@OX1Er>dy{z^YxBChqe0=*os=)2I{R+x8P_Qu*HV2) zp;i}A{^%f0W0tdLrqNjgKa#PVhU~Xlqs(kjaI%G)QHJ-Z`MyYypGU>?dlk@dwH zNem15x1O7dRbVRv2*o$LPgpjwwsm@T1mF>UWBve8QIkNg`~-A>w9O{e?M?QHijFBN zN3ao99<8+3HaxG>W_et5>ls~tS4G2zR7PlFY9ea1migz4|5+1wPj3N*PG0`4KYS(1 zL{}}nAGzk}o?Y->=!(o1*4nh#SCBf56`zgTRi~d9>%w=I+~X8p)3|A5YfPEA$61qsr;2m;Cz#8YGN!pD$sEMU=lKU&Q2S!qssgt=VO@ z8aEir9vlPk94Kpc1#?;bZ!@KyNJQ94D$KBI1?C7r_HdHc84fP@c$>&|9Jrvjt0wPn zLjR_mb5(c8)oNFfn}`>&>ll^%V$OHP2i3X2qd_1zeg$?XR_4+KAe*m=%8_DCk@D{q z-hZQFyZVpc6$6av^_&9BxpNP83pVX#1fqI7E@NA5HzItcq^`)=(a?`{aP2h+dU-&VCX>i<|AY;S(9E1956JSJ6N7qf$N0pOU> zbO7qLfo4`2hz-^Kx*+Sup zWgKvy;-4*WtA<*!@;2X0cT?oY=HY)?+a;S^x>y7Efs_BH*_ba#8J!-Oa*S909XIdI z*_g-)bnhwgkyo8=KK*8w>EXb&A}?id>3HN!-}t_R#mRMS+SJg^EAn9fGiZ*%<(-ev&PvEE%y3BNrjz@M6$C ze_ykkb_HOGJm&CX(H&CduX%VqGrAD05a#RtVAXkM36ycXA zQj|y6o_A@}Hgi~(Tve#q!O4Xu^_HGm>yx7^j@arWeqI_yx>6U#j7DLk+8cuF$%B=P zWf#n|I(5ms^|*=FP4DZ=4!(Tb?^6svz1K+nO!EsD+dy4u+yCZ3++pIvgj4rE1we%lbcne?(@#xLQLT+oywU%@804!FMn>ngRw!y*w*H!F^ShEtu=Wq-bSyy^)n8LXo)n$_ z>kqiijc+fVP(of(9i1=F*3#ItaU!oy<@XAtQYJ?2TN%>?95T#AZeZtw#TOG5mycq7 zy=!C7Z$H;7SY|XRf?vN7)h+U!{|ayoAI21e0$e9A?lRpkB4sz?Vr9}RxJ4Fo(Yj@S zdTZx--E3Ti#m4vV>hw!)5zot(QAN6|+m7el1eG2cI4=Ax&hB6REyc5^-I>|;F1<|^(S+ZR@BNACmocy=YhI-M4vd@4}U_2 z{g?-ZZ)*qrpQ|@N+`Ttm*nxlOrKUj%xfw0Neb6t2J@cWiBt;F3&kEw$hq0e2wFyQ8 zzmh|6IkJg$C80GiX)8$V7?d?j%1k0+HwXv%SVx?t2Bz-uLN`mQTOy)RN@2iX-(?5Q zYb^j*`a9K!NM@lI&s1EMk6j{Q_uEn6Hl>Q2IDh^jn7nux(*4~h94y)0-_sNVi4n+a%CQ=P2WX6zh;kYu{`QVa%{|Q&T8HhkR8y)sd1+AIq0FP$?yriJB z8!-m@wFwuAq8m`?O?xj)=>RCnfa&j3-(_SJWtka(_9;|G%qn0B*Il(`UI7|75BU0* zO!TYl1`ns3XzFK71hj1oOcD)jmfYrQnP=3YNLIRRRf_s-{Xb>0j>LOVrUi4Ag%7k+ z@tk}$w|<-@iFff`tlT@!BktRUB0EF3qANR|ZSb=;IL*Fa;MX*S7``gdK5+veKD_oS z+E?|QtSTN5;-YFd8yUT||59pLQ47XCNe>6r>@1PMPf?)2W84H(_@CrR_J1K->AGuB zQ7}@V7gI1ygg!7ThOj8Se&-qYoYmmVBX_c5-%}&5^e4rxr(}RpIXfPH+*v}Aj8T@l zh&|$tlEjcWf55CTtdfl$FazvkzV4N{Un zN-d7y>Z(^_FTbC!bifLC(XJW){->GH-RK?7CirxCr}Kb5ie41>bTCW(DBw5eB~}2f zahCDO)ynW2R9Eh4oaas)HWxSb7ppy+FcFt%c+!9nWt-}98h37Y0H^7pyt6NB04dDz z8T}&1v<&h3aVJ1&7=hpQfeet$4pQ?YWzbh+{zOuoyw~(WidbFo zHZR-i{4K9muGib1w0oe|QqF&gDnL#{U#v&J?WU3Z&2y4Nd>T5gj(O#H1*{WEw!Bfe z*}jucy?egQ_u?)DQndk40RRp_vwH$mzReJe) zTbiO)5z0jM$H@sFlQI^2nz&iI%E#JcHC|O^85BuXsn*D501^>F+dtlB%zs z^KqPv-SKwU)9_B4@x?`s{0~t6OAh6%iKVl|jC__qY1tK9N$PD^3jc7tDIY^ zU!Kgy9%8k}5c@I&3!Z=wvZr9!gAASKkX@EF;n~u7wccMxt_!SU%4uE&D z&(00ElA+CKdDvL1z`MZToHPJl?7P(Km3ny;u-Q}UIZj{@xl^w>74O` z_|1n)8HBjL&#C^!*NJP=-#r8=coP-g%`kzVbh(RUQIcy#A*xxS3K79f331_(HknVN z&iKO-|E44AxjtR>t?Y|NyYk3~!w(p=?32EHR^u`+dVXU!>V$!TWtYW}Dm-L8xsbbpWC|0Ya7Lx5CjDmgeXL59=FqN2#dPyz*! zA#FeAUfQ&e?{0pmJgsw;j*oN^`8ckhvxhBZpD5ZHv*R{~NtzK8sJg$`2`N&Q%~(%GVTAd!NYJ_>^(V??+b8vK6`KEHz z#iZ6gm6sj2;2%I4J~i}G(48X39Yy;t9M?lKvTu%FD)AYIw4L?~SCQ#=hZl#~Ik&xZ zh(Z=+3K7G-^2_Hu;|`~wb9@i${=(XZGYv#E_N!eWWX zjg;T;F3FzT=P?~q+RVa$)jik9U*}MwArz=*;%yNm9*KNv~lBW0U@C{ zPicJQUW$kR?!<+R6YmiOzJg}Ig=VY7J-`m>SJjsJn)mC{HL8Tv7tpYncMqU%C0}Q~c!-Myk;8(7VL|$_Ab8jiIc!K+ z2yq`a1P=!yhXV=2f%M}*@Ngk=xR5YhNIxzF4-X=T2MNQ2^y5MB!ii<^Az|UfefSW( z2x8d?Y%>1_;@B4A*bd^@ZsOQJ;@BZ(Ty%+dlB(|{P2Nd5(J^5?kin%7g-OcbnuWrG zWN>psVcnsy%~03_7>phUlZ3&{V6Y$3=6ss7d9@}uMPYhIX-6S3&Ffwx+H9zGOUM{p@=+m~Knch?!fwHIhch1YbN z2IgN~)RGF(d|8~I-uO#uPpDS5q&TU3xQ9yqr>V2mz0BA@uw1Ps^Zd}!^-Xg>Z)U_=5AIomhqd0K{`~u)XicDO>OFhj)a#aTmrItsx;n!m zx}=(Y##Z}jw#z72tw{-aWET}X@Y;wOC3B$jNa;wE;+Wlzcm6Va;%ci&K7P9TyFWmt z_Cu6U{uAH7255AcDn@f#*@GT>oz5sjO^L21ovgNK7UKkr(qA;1y2E~)mcf>Hqt>V6 zmzsl*OiMKv23gB?E^6l4s}ky10yLY?F~e;>5al6PqvS(pswOIrzU0LldFD9}%gOJY ziLtuxJp2G15jAt|w=R?Pjk9uH(p1~Ku+E+KiOrPcu(CxYd#UdUR7P%5r<)>FDOg(J zb)}-^6Y?&|G|d&=f`sJt!O~>?iV67KL$-@EgghWZSBk!{!-6?0n)^`KSod;BNgZ44 zE{K<2KvhLLSJzR5lI>k{xAyNJ2`cN9L3()R?P?(_<66(s4F=@z+8ST4$E#^h;AkYo zRvgz$r|cw*6U^wCo{xU7B;C>N-*=PJcyF!`{GRccC6$+t;4f8Y(Mb7#@MKejsZ97b zuKchHW{W2ztY-8sX1TQ6vt6oxJ@li>tnjs~CK($tKxv=`vQyfnRqmD}a|+lqCHy=m z4$4chdTw*Mz6tC3>6mzkPn6!i&Y?~|s&d?;#ol%B3S2B`Os8N)YyNhS@oG_ubjYY- z4mEwuMm$ar8E1!#^FYRhA>)#tXjNaTN%Ck&f{F?r9f_BEk~{`Ko)K(Ez!)Q87Ll<0 zNZ58Hj8T!>sKw8^4H%O6p>f|yvu7>{CZ z9;%D)bC01Hjf&&tiehqrVCo)Vf&h{$TE7*jn2WEPVdK=vsETb&_{0|KN{rzHwt6gq z%Og?D{Q-}53=eF}k}Ep83AQCy%?L1*^}!COMLe?#nX-(!)RS%kZRXG^%S!3xe}|@EiorAeg>yAp-(x5O{+Cao<7)Jop#1 zV=thpv_+$qjRvtKaz3b_1+t>psU0nF6DsFp*l`rDE(h+8A+JL`C0CSfv0OGSSG2jo zAXWkrD=p`W&B`#ee+?&396l^Z;~QSk7j;%^@ED1yh!E5#!|3j%Wx z)F|#(cM)7beL(xM64>EQ(TMogV*&KE`2C09m2hjm!KUu95ID#w*k>4Qr>+bF5fEI1 z;0Od$T#Jm0@Cbl{_-PO@MPG~s4<-wwKq$`R5B_I5H|}S@l4B&E(T0@@7`+7^#sB07 zA3h%?ukF$cInuD)UDx%r?d<01s5gRS5iYVYdDi(eZxKfqx!JGn zHGnimC<|LAm@HQ}su{G`>}?{qB1F@jL-jmI+u!_lHNKRGS8&TTIPnoIFFt8M0oVTb zA{bsgVi7)7w1*%HOA4L34cKb}3mR;a77A3KXyJWoZ0`PhE8N!gzP>_aLSsPQDM|DV zn0zuhY~VJCtK5iCSX`e9E*J7jJ5QuR74M96T(*!M`_8L5u3|3BBj9K1c4Y7})jMkC z>3w(a5^9^BBDc1H`Ww_+&i3DJ%M>;XP1ef`y#_XQn{n7dO*TwV+@|;D2KDNDlghnZ zzqY#bE^QPWokA-7wsNR})F(@iMyOBthJI|>o%c)IZ+y;KR5VP3Khl1@W!LmEu3pEB zyI$DQpZ{g$PyRw98+!*yfBx?26)N2gI(O}uJ;GarhPwyivSqFJbqmKx#cADQb^pTt zuj9|H7yiw|GpEaS)%;Bh9FZ4IAw=hH$B*}q?|$bj!@LrfAQ|N@GUV4iRE?cSM>jpj z?)8?v4bAQDGn9xicKhffkrojqUBky<;D$*)Of8IL5@>F_GOOZhH;-@vD=E`COId;M?g^W!L;}n129{BE0^KiwJL(5CeFpd`-Qu zc354{V|k-5J?<}W;ZA?!1fHk??H}Do4QiSdEKB(3B4KW_*<5qbu(prU^yz_$B!LDK zP9YzE27Sz^xqUpxOgqN{ooD6JIwv*A8J=*G`dAOMY7Y9?4zv0l^s!ex?qS_~hW?ME zpuwjI8ngOw>|?xt`Kdo{xX^TrK*nbvCRYse!$tAzmnWDYfPg?51p045fCYkQ^w^m8FQD!*PxUjzhy;SVKdwR~ zH%TN`NlAhO)MOuH8`7#gZ3vb$UVQ=rQxK%zgAfoba!J%M)T+ z2M9Q_47e+%SmuWB4H^IkX>7?vVj9sGjl#zhJph`fFp8&;J55U zY-+j(oOG`m1XuVsc|bG^?!=Bx<>^%v*yargc0f>m559pwn8aJ?)aUInUFDOjXyP|9 z-G-}gB~~R!eA-tHCSpkC&an*X$DcIBN*b-oko#~*Y|4@N1h9d)4a9Ha4@o`Zi5ud< zUdj@yA4t3dWbgtMz*kgqyaY91A*^7NCbfn2yE{A--9F&7=XYV1Sp0Fgp8F> zJd%kUlELvzC05PAnk2Bsj&c0SRZ7>>RVxq_$ekYzUckO6X4^9_(EZ~JYwK8|zrpY$ z-Toy4jV86I6oF=t+L?Mw8ZwQ$L%j8_;iA`gqWo^M>qWhK;+lphDaz!FMxpqLq_n+}a9ISKFXt`)|Har_heh>;ZKDbzB{3o?IUpU<-9w3jiqud_ z!_XbVsMOFUprjy(NW+Yjh(U@p3?(7mox?Eu+y377JLkW1oj;hhpL;#)eqwX&nZ5S2 z)`s6XU(J=hjZ+bo{*C+X=Jz;*#dF$2rYC5W%nUu@*8HquNcd9SD1TFih>l90|4uhq zQji+;y3u#Chz$N}l22O>62V}A{cv5sN&eOQsl7Ojz! z9)C4@GM*2+sa_ht*Bm(gowRRwJ1@IZTrseDU=9BhA`hJx5P;fcv6`<~3;6u>Y1%AP zf85{{_+~~m-yZhB-1Q{L;l+^epyr3raKwAlO;~*({K5NVn_^}*Zl)ndmK^ayoy0fQ z&E2)qz9kbgiAw}|o#Ly#`n|;U0eTT13Nm*mKU=b}?q64zlDvrEV>fF_^Fq;(b_XLMzklq|hj zsZ+Q>ONmx|Qc{@|DtV$LR(fJ7R8oO668j>TO>xf3*-Cie=$<6+{3|I z&*?w?O<2^BUjHJ>d%n%p9sj-ioHGlbRKrsMUM- z^c9Me2iZasaxPU*SBsloRsI7EKtKruPC;P%A7BU<^19+u`HeX88%g9h(&APkzLXP+ zFKSalUc@fd-)KNU2LzPVL4X7V7(u}4pT<9c6j5C;BJD$ls9s&)<;to#!7*ELm)4v# z=T)Uzn1x#1AMX~gXjRc2@0PA;WjQ)c^)(9(dr_4dsvAl|c(#4))U3@8?W1o*?a4KW z`P>BQ^($J#HO9LQD_T7Y5laGCYsO*e1A3?r1N49)5kefu1x41%gcf|C+JfLNx*a0F zITiO1mDb9%r4rIu_NkZ{SyCxhkG285HC)y zJx)Zu&N|C^3TDz0r?jMnbxatYpA~px!20m>Ww4&g$Ln1>FlT#?bngcggXMw1mVUN1#EKjHYQGg^`)2;e zqUe#=oASNlhk>cyt;$-9A;Iy-6#KV4Ikt|;E0*?y-4Ys#-)svs;SdegVckZ*6xKw- z_A1H~oXQ)vG9#*dgd}GcMl7rXe~0v0g&+7Q9o35$$8H-EIfHTdx_0(R>U;|5+%5~3nmAIVT`H@sF9QFSNenAHoE`{>{4l;CL^$TXiLPqq zMrLkCW%$gDNgGw!?7!}98$#3}J@gDU=bVfKIlz(M-L>m9f}0OO;EC) zVU-5L$DKVJm3ZCXAS%os7$mK4J$AB5>54jU>Ev_j5y-gL{5UjZY4lHvlFQ$MY?p$I zAYS81M}w&ojFZpjXR|G9Rs&&gY2FwOn}&YyNRk~P9XPoky5Vt%?FC40bWDhUPpq|z zdsWN*CG$fdOrcuM+nzp-8!;GcoIMg{)XW*Mb+y)xRBm@rKrDJ|c%6fnfT_+sqhb0T ztIB9|nSa(|m3ww7Ex*sPy3(#X)d8Zn3!nKc3}{I^zso)It%a}%@)0cEBCq$x0!(6j zgh}BmFZO*FkljCH0d-Jz0>^tEgTUawv19L^`TjR{9vu6Kiba8su60brrLqQ;qfrYhvS03^oH0e)}kfH07!KwN&`X7g`5GOi~UV5Q+B{39N3 zl-mz{n|rn?YJlH-lY5q2is0cez&C}ZM#}B4o@hxdw712@(*f1?|AD#xfoTiv1=EZ@ zadb!z8y*n@yv?cCf@(a;70$ch@zbkUPziKEjQN!-8jJ17;@`1AIA~1rK4>ghZl428 zo$C0{Sfpt>9Y7Acl>=HmJ@i_z$pi`14Djv@S6+|_{3VrGYFGW!5eo!L@Dawqc#)jG z3&`&va2z(=?=16^2dZzBN{QUT^q zR(`*2t|J!N2)c9^Bp3r@GOy7bUIw$R$YXO4|MG?W{%OsXl-^ftY2sY8py6qd!gi&7 z?ymg4(|2mUY&s;vR!W8Ze!=$NcEID%h?$5GnQ$le%pm^Q} zUdU$8fwSUJa7y$W(TnmvfQpLz%X7S{@b5{Wh4T==>yKyMJlF;r*P=3UhZbQ{cF_f2 z&)!yJ0-Z9jr>2BIp1@YMN$_spWkp@r^; z{I&rTiKr}vrRS42#8h`J+AAuNm6TD${a^zp;%{v=r?WVAeCcOx1t1dZKMwmP+T_rF zRe*+vSvw$Kb(e2-Q2S9@ zyk%I=;9O8SI#%JHju~)DG_BMk#&GKmZ44dBOfjZD+sKMQxY!&c+&SW%MOZzpM^ygW z7@alOJuQfA2{>4Ne}GTW53^3(p4kUpu~-RK!S*WR|P)h>e7^ zN*G<1t=`yP4ba<|bmT^FU8k9Bd%gK7Pbk&7px5A5e*p?DX0J`rw&U)$>gFN5RK;&c zX_x__=)?DmD(x#4b~g^Y4mCc8i=Vn+8aH3BaEBTfbm1{+3n7@LjgnW@%7!8iePj1H zq_!pU$>EbCh7;gZST2-d=~UqFd-T5ylWKSG$3X;-Xc~mHqbW1sPwItaD|nxjjaXK~ z7hXNA^fJawy%mHXbFUh=(e%4W2R#3PwLC2|LF@+@-xJ~+{fexGm+qcw%%plw9BW8M zwlu4Fj#oG8?RomOZ5JHA#14YL%I_i~uxs{CE&HGOFucr~V=uJmFduF!l=Tf?AP)ZE zT%X!z)4qPJL6wA}*9a+iqIqdS@l1WUtS<~7xwpZ$wPz=<5r4QlA#!S_QU0@h3yTnQ zcK@v6(U6x{g0c8GRb`)y4aeEJ#^mdxllFUDOC3ir{dpl}dB`AR6d9A9j=hoyEOXsO z$D`43Ektl|=VXhh@}f(5^rJvJhP}GmbwHh1`V@cQT8(u_&(eiIxi}jeF1iS>(6-?( z?uhg-vHSW-pdE`JOqxj?UJyEY;h+=s(%f(|;zOIjpZaaz$-46?p; z3Q|ws$_RVEW3h3J&ZHgEejq2Up?_3e!n?Ei>CXAB$LS`rL)z>Y8f?<4kC|Fk$Jx`d zW=t(7s6199?T1dgbzM>6d%M9sa%Cz5}ZDuz!6|a1WJVza!C!vvBQp3QEL&PjiF|m`FPqPj(=@Bzuxt>_8y<2Z#_Q6eHO!7 z6kqOG+2zFW+@@6GAt%H|^Yqq4y__rJ(%Z9A;xUIWbM-uCq0)QB@g77R?1Sb9f^>&% z7P)$k1!?p|m+f!kZ`0`YkAWaMSl8!Or)HYrgc8qrH z7X+d~Gv<9OTs^KtG~Y0+_0&}LG*jn=T=;L|?@(#I8dxgq-WH_M z%A^b8_Yt>xPqSRuExUF&n04@Q=}?A7%j0Gc|3P@O_S`Sc)SqtbaevDJrMV6L-g>~RSth@&p0Ta#&3Lt=*yi#e>`BYCfJ zJOHhig4Ul)(`Z!{A&w@MZk@|nz299a)Exu=k~=k1lgpHDHNh4OyX`Y#prr_qLLc zN}T#{q3&nX1RZC7iPzioi#J)~A}1n2j$!FeelW%af=Z_#=&mM6=MT~)Jq+eg1N9i$ zN+HadWRCo*rbh%hZLdPkbm$L;y! zKU6H&zQz%5-(cH4!0isIl@cyYhLADKc^6iCKv=0w-tAB2`Eo|Fextd4;Q>4GO_?>E zU7}KlsIfBh?5QRrof7c9Ra>YRTqdwi?g0C@CnihLLjmJP{*@jB{f}FaTaSxABs>oN z@>pkGp8uZzfY_%a*O~j<%75PsckNP3H}6{C!Qp9K@2~0K`)#_sHIW@!F(KR5aIsoZ zb6vQ%hSX8nmMZ&e&sV2uXM`7?D73qXJ@Y2!QDTn#J!Y1>Hf)(pCGA;ni+N#EMmG(p z9@1UzKD>E~F-eaD-tkmcl_e>iq)NDk>xUi@b}PkQ!cQhJ%qBi_tQL8#JuHl_lZ)w$ zW&-qqQ)SA07G?4UA6KCNwM-F;Tm2gwlU!sn2W4_{)H%hObeTA9LZd8W>XUo~qW z%UU{YwmgtJCO>!1JTqU`w5(2UHe=~eAz_0UNjHNSj#@dkS$kgvrKttKpqG8?UNrF|e-i~u ze|{;2WOMyb!(IBb@0LLf=|8fbbuR?y3{0M_s?0|Lp9&h&&l!0(J3`i%Ir8^Lv-aV# zUr>6-dX0mx!k2F#CtvCJr^C6_$bJ_uxm}mYmA>`6VB^^TU$gQ*jpM-oNCWFN@5q41 z)O%44nu>~VKc)ln=W~^B0r_Lq1`9&gT|(yrpcPJF#44Rp9Jlp@t32NV^u6HBl>2Nj zNk8EFX`t;S(e^j(Xve^oQ6>+oahA#%2IIEG;vc*g|BEtgw$`RXPTw5z<(GA8{hyHa z{;ut;I!Cw|@NTO7^BwbY$&hITgMU5NgRHji=n7({zIF6C)+&R_=+#&vMR9rCoSyskR0jO@XF*wE2h*~Vhh^}E*H)EY0wq(-HW*y0QQREq+$ZUPEmPO3 zP@76jP#&~|JYf4`RnQ;Dj@eAIM2vyYp}v-HvX+N;FuDQS0-4BuQB0wyP5Cpd4`!%m z#bnW4a*UUG=-#&?9?W|5-4gQt>QE%N*K(Gi^mMz6S`+bOdJf`x>{?V5M)_k0T^ z0)mb;P0ng}w-{D!8sIzU-#q+-QpZBJT`+wneXfer<)1C&Mt$y7n@$@ReDGV7H{538 zD3xRR4!-Q>jUL`2y4TtwGM1tkswE&IpuYO$ZVRf1oEQ2!Ma^e;GEYoE;D}LfZ&Zu= z%ahkN{tS0qKMCJ^{=SBv>!a|!t@nr}-KyjBY#BA}s$w|DynfYjFu2oYfjPxEuA;69 z>(tbNQAzggquJvh$9!G^C3{ zgb9AK+%(DrXE>X%T_%m#RnBqz6&j;N8ZYs2oZAx+pvysoeE})lYC$8)R@^#9l{9-& zh8JXlnm0_Eu%!h*Fe;)9p)Ur^mukoKVeIn(48dQ~ z=1b?lZBw0+`=A2>@ml%xGVx0BA`HRo&uU2<3$*eXjTwS(3Nr*dmI)syy{qY#yyuY0 zXZ=>dZZQP!JOoXYfe~K?jiW%Duiqn%*m#Iu0`u?!8j-5wo|-1? zDt$a6OlHz@GriEOa^NZ$xr~72X8j}3O%gC`zfHk_>OeQspHzWW44}#tP=yza?kU7o(3|+ z2Q9LJ!RAmX0t6Dq1I6jVjxtbdVvr#xXwe+l5sM}z!#*u&uXM%)@{}r$Lt5E<7%#bii zD9#CXG=y3!g$$W;7qw}_3KCJ_w;^E-+#U)GALzc|qvn@6K9waAR@aaQmtF3afPZWb zQ`T!gVz7GP5Qun1Xe1!tya(vt5wegR_X@uF4g;SVHYXeq+upUi{jT*{o669isv*K9 zl#R7eElT>{J~k^R<;gWO%Z$}oNTVPPI0I*znzdeHHGGgcy-q}^&<{tR0EVqSK*l{w z{Jry${U`b}okouoh9%a|q=UaAb6T^oS76ab3S>4GjY)GkS>(8^N2UJ?xxu>G=_z0} zBmDZ&RZXT0uft1#{sb8lsKNTLidz+_J}dd7;5RT}a~jOOGGtQ$D4naH6!gFEI*$i3 zf)A8D{Bs5@+CJqT%6jl=@|2Mz=xgU6+7M-Yj zPx#v<^3}5H7BKy#$p{E72bayQ<{6>R25tslybKT;#H#{-8nk}gIYf%h08V-uNnia!yq}pn>D$O$kWA5_ zHm`mnbIK`MpQKtLZ+jg-Hjtr9C%QxB$5mf&wmF-r(Z9lAyF;O>9`vc%%-J#NVbDUg zZL0Sey2#u3*mj2!?mZqnqtie9oSkw^KaRa}X~Vy$x)mnmAcEEB_(RRy8xb-o63=BM z4%=TR<+UcJVVud{>Jr!9%j<`arG2%<{2;(FlE=pzI{L2R zr1#dqnTYpemVu9}F+l~qC1bRRxi*vX5n0m;#RKJT{v=eOzZLP@cG01>RBGn-)ez0O z{S^7F!P|KW(FxDWW_dKnh!~WMWoHI05SjTOdwn(0-`dx0AKtqoB4^vkG^}VrdAtja zCSe=SzL2{4v%G-*M{*W}MXo9t1aPSx`&+4j7%}y%KbA-BwT(@S5ir^HYz zKWMeXKdCgT=R4}pi+0XKPKan>L?6X#=_sz4wpg+bck!|Y$V7GsyC(g7TiKNsZ8`!J&hUc%3Aihj_ zRdXrS+K|$wy2K&ugW)F$!yL4Gi;BGBgO{Bx^GZT|pm;>obQe z>_oU9If-z?>_qGoF2n3auoBVn6%O`@3I{)kd9Pe?ZRU`!y~v_)7`p^$kdy=~VF32K zl_2cpuoC%nX1!-7P9k>Mpv?;f1T&>HR^omhCZP<}HC(H3xG`kbJ0Vh+DIT?X?FGok z^xL24TSA3HBbbNGO|XC1toKbB=!XgDhn|y&CMd6Ik9X%+I9vmVKkot6iz^(q{wiF3 z`UETSbslU@z#tx8Va~)PFoNDtqbeMJ-vq7jgI4Z=87;5R6gL8+Y3+w=r**wOBBYRw^N*?V60e!q${rP4gIgIIMeE{DeQ;d4-Y{nz68!hXf^(LA};Chr(OSEVSF zKjo{Yq`dm>Y-VbtS=pof?9#0|+;NKfGG^%*m#mq&p?aKK3jEpO$~%s}1Kp$=>F}MT zxwmR~gHg<$SGR3v8@l3_l;UHmwuF14SvL5yq~k~WJw2^X>B0EU^V=OE=Nlc8Qfb700(O>2(MFsLE zW(gkc3YjD%WC~)OMNK@Ic#X?ObgJQXaZf6}K3Z?zM?Jc9c9_{!yYs#?$>u0~vn~-H zPqXAB`_`%BkfhyCUzI9WL}cI;mp-a*3yXvf2VTqA8wn+I-hFmuj+J|8E7 zrWM}nX*aXiI9Cn%MHI>E7d-9uRa|=+YpAO(aC|h6dLmG4=&d}es!c(uP$+v!p7rB0 zF7|I%xt>Tr2cyMK6DLLi|9N7n!WKP=tD6Wok$*q)qYGwwP^x{gE_6(-+`!DX2$Tl8 zIx^)cg0q=G3YXS3C8)N&TN<=Cfq`3AIHfs%gDW63AY$lpF*RiLHD4lowcj}SB-FWa zRdy^Cv*USWKzFPXUYW4=)#+%BQaa(yAkFccYWTfc={82Yzze-gUy1gsy*|Y+&2!q- zM?}{1-6`9@?<n#^Tuid9_xLt%0M=XURBCB^$aiXE@xN{dJHd)r6< zq-nz&bqsrPoo}8v#HzSVtJwLR_+8FwArdbnVm6J2SDB1t1BXUPOPNOUU5kOxtaNZy zhY?4_(5l}JZ6^d%!jE8=kdmjPRNp_|e)UN9+WQ^E81%EXdHlzfXCg)M-{CN=JPb%{ zR~lCv3$9X^1%)FlcyNVFf@(l|?H-bmIcAkb>e;oGzfIR2m|wmOs(SeVb-&%0ikcS6 zy>A&Yauk^Q76eUKjk5yQzHAJK?e)?p9cwZnV8 zQZbp=VlkPbP=pBNCPE}Pox9~xgvxJu`8rmF2$dfej;C^+um<7HTI>%H<@isBvhF{D z3n6j=!@^gXDlirF<_L4{TC9YQeWg~G8A1?t{>ie4V0-tK11CK%;<C`5D^{$s*=D54hYbI-QYff*s%3$`*nw(%(GlJIpiE^S@>O^uTvhi-sxK3W!vT5 zu`oABBK35<0XnXt)0ZvnG@Yh5X^yB7CWXQqGSD=b>jUk0vR@?$?0|v4jDJIs-QT=&5swrts>d84bj%WIvGdWEn!EU zx9g92d%t3dSJ;Mg43MUtnYd=ru4*jtt~~$s#5w-!4U>Y=NBLsW*dT)&l-WGdmkJMV zRI3=$0Kx`t-YO3~&$V^HU(05#$CR2!G8Psa?oR0OX_2E5tDl=2+ocV(ihr!`?=sm~ zZTXFRxB7P3bhN~`R_csiS|-Sa-A@p%(@c1dte!ZIFR^Wq7K@#ko37GPCVZT*8?$X) zov1Ck7$QBkzGNQ?O*R<3km9J+2}~ZmFxe^Wl5+Xjm78%q5f>O=Tkv}P0vJ_e-TRe{ z`pxR?o1a za5I*VVU0VSt(tE;uOb;Q4ClbuzEcSqkn{fi)BUJc>zYB^$1++3gtrBuIE^(Qmaux^NPH3*nvdY z)Z&O=uD_p<(zWk~8qZ2AQ19v63UvN1L3zJuL{(u9?abn?tC4BHKt;bmb*gD{KBbkq zMx?EN+vLSF&LVHlqL-XSshmZHoJF;qMc)Sp$(X40HlNDzR7UKlpsBCJh836~AfO8Z z;;A5@1p@RSUe#tph5tgG$dq;A$EO=z;(g1QI|% z{U4wQ0=yuQ3j#0GimA2lkwwR$I`4t7FbJbT_%Eo}sSg5oNh+VVg8)~0#8o?97q%PO zud??o4Pv4nfSt0S_PlVVq3tzIKD}0jtdYX+_2~X(Kj$;yN?&=ln^*KVK~>nd;bso5 zn?(N!?cat$JudZ>;@Q;R^%Q>H$JM>de!5INWyCJDMBZT7OX|Z4v}AglyWSuJx!z`Z zV=gs$RPnJ+Q!aHZ*bae|*EBELb)(aeoGfXhFWtyqdVw_E%hkF{Je5E@*sAeVBLB58 zo=Re7Fe#B>DpPLiZK~bpsWeLner zYhcb(I6=M0e-41TjQj_HCqWH73Bc{1Ax2RmqJ8(*9h!O!S&$t0Xz2D=Ju8$WY8*e)T zN7$5s}N1fqv81 z^$d=B1;~>GH!V_qRncx~q@au$Zjw%{K*VCCduI&RAC747>py)F?4kA9n=rj_5CuGt zcKveMXz4r5r!B%g`uf%BZOpD=+UDyi#AqUYU$c(!dew^4?-rHk`e~RRpQnlZ+#d_< zuQPH8L`CZKa!o20-!02z{fvwp!mlbjo~^_bGZY}X8gggaoiVcGZh4ki=ff4&CU=@? zFV#1kr)hAe5zfO~gwDsrQNF%3LE?`tfBe8)S2;K!BwzKRRf+&Q6Z;A%7OAw`bMBML zvOqj#ptD|ZUQ!PQu0KKlS`{v-D(8>tGEJbW?)4slnV}FgIP8+kKeZLzvqW4QDf$ zo27>HQz(_QJwrIQ6zx|+<YM;DW5{TdD23yK z|4Q<~vVHIL^R}Onk>Dm+np1p< z?Bs#a>2W|SeB0gEw{NnlkK@w;BBM0KdKx|YC%d)(7>74plBEt`pOont|ML|S*DLw- zbJJqes->dEc3NObsIn*S(rw2it~p>;Ds9en?$2Q+#$+}WP#RZ!6yFzUFtGQ9BSWao zGylL|>V~xH7Srx|?E~`ju2tj-{)rnJ@0+rQJD)goJjr8Ip7eC+Zo|tB`HOP@R%#O( z_5FLSa!_3!(&Cd(mEp@l<$W%^?V9;9%WX8Tp{IhcUs6}GX5uTg6rSlJ^qie7&s>ng^e}@zrYs{z#McUe!ls8vfBWXh@;#uCWvxMH@I%2sg z`EIr5W2!okq>O@5t!eSNsu@Bb5r@!K*0#j$G9C*my>t58+A$l2Qci%~SaU#4jEF)c z-*s`>R&z(@$Dmr1X+t=nCmOJ=*en#|AUCAe^rprDtbH~XrFT;(>TD&qAkmcBjdpGH!;B) zZ}Wz@{0FPqc7kZ*8Pc7OkI+WH2w09|+JOln@U&jUnQyKu~?h3epHXEQxeX(u4B}W05Ob00Lw}BsBZF1nt zH=Zp;_KeRE0AWH_4yiReK-z0?xmtM>XdoDN0ExI@d@{St?cDGs!$qKt?(}C*#|w&> zk(1fTk8OP!?+Ma5c^?4=6t1uuqJh)|-{@jk1V*}Svum*4e)fMuV+DrJ+Cu-N%O)x{v`uNFig@tCG6WLv<=`Qp!{-^hqTUJQQlFx<$ zjktnit-L{if$XyU0Ekge)u^t49%P*-e;6_q7LhjT`AN}5xm+;DKDWlu}pG5Ar z`Qqaj0WdsG=z?~#f$n|LZ^v^Qxi}6!g4m1WxvJz7WZCQHnd&QxKoB1RIIRW(B6xt! znFpZP|G5r+EZVRFr?I#5SORCZ0hUc5LL>Kh&LiUtXfp-?##MmuGq}ynwe{1LO+eMJ zhycu1%pnzePn-Sj@pT3+Ao&R3$LiTYCtw%jmq#mmveE&VegZsq)_{h4c;v+x(01}= z@+)eqx#}30o)d1w0shsB>)((c2^`IQk7WIZHsA7E?h-caDgNKn)_m4>5n23t69FJu zfS5}zf+suEN;^Qp1Y9gBi**7jKK6rU{!{f_Eha}PLI>7#GrYTv@C zS8RIrU!6CLoBeVAde=%Me<84n!T7R-*VoFe4!lX7TwA(I@`hCH^!*ud&~s&wzFMF^ zM)V%p%q>WZAT+=fwpE8zq-lJ4iR~f%e@?T<`k89Tj~a5js!}|_xB#e*0+A#NVEsTG zVfUs-!zIVu% z3IF#T$b0OcwR!$Rk$dZrd?h5m2j&F#fo*9ZP(OK76_9P2UjeE@Ct`5`@gcI%^yci~ zdE2Bx0(f!wFJFa8By-{WKxCo!kHmUFbsA8X<6n}vprNAnIRQkv&%oVE4#D%oGq^x}TZmlb&T0K=QGq??bX< zaQ3m1`!BoR7NVcp-RhUwA+LHXWi_+o^Ha7ieauQE^J}>0-t-{}gLGf*3MLm8O_f9# ztEDa62fQ%W7jb_ab9Y=6F9e!qUW|#F9<=&gc$ZqSy)u2v78-1oxAXkZ7Hi||*g5G~ z!pD=ZF|JVqZ`nW5s~km^PA8f8oHF_v&tLlXJ_BV6*t){4;pYQlwz1GI=n2-@$6IQZHpUU_7xP1OCz)}+PD9-5zTewfQr;TBD9=D;= z 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

oF5%wc?0lVIdiCvTMwKQ}m1M4pzSU2C#ISwFq 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
oHJaZa%&cRgbKqQScY`o5It4F}rqGD>-kDeG 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 literal 153315 zcmcG#Ra9Hu*T(y{v`~r_cPT-O6)5h-y+CnyhvE*U6nA$h6o=rh#e;irDDE!7LeB2@ zALCq|+jH^Dnrl8&*4hIylI*=GBj3D9&{nAs{SvBP(Jxs}{}<6y*=A{JiS53d<1*2)&ciwOqvw#Pf>OiKJDLY+ z^~u+lNC@tS@v=kcLb&Vp@-|hl!_N=hzti8qzyPOXYiEm*5&6Ke8H4N{B}FlVs$H(c zdH|vY()=Reoc7=r?OCJ+!%b~pqtVgK*E9C~?%V4Y&o2Vid*25Ge@PggXMq;oJMz+u)r63Y}_x=eX6jVFs56>&{ zO!ohoW83$0Fl2t8kWexA((_hcaCkFOf7-w4?%qL#-H-Y}vzW!3SP+TYX41bLTd3f8 zgz}jCmt}KRF=4@ah5(;7A4gb|>m1h-$cp=|*YQc`*t)bH1#6n2Ey}f>* zc4`plcMlw6?S=m;=;ag0+Z7AzY-5k|-3B4{2KmOp)+%UaA0He0bb0mf4y9-yiShX* zH?josPw9K_$Ja!@?NI}7l)W#HD0WV^k>MdQrgN=_0qlz|KM&E-$Pv6rrwu>9X(7cFqvG29@a2XzLor`>&ryJy_?>N zVG<@sRkr4+YRNQVOpl~;dW4yXHR~l+RmXm^V2lYpl48F{z&1n8P*JKLzbqS8tumIi8ZwxGv+j}` zF7r@qlF$6VmRIr>YGgJ^gP$)58V1tv%cR>CxvtX+yxkWIeEJpVI*vwX{d6#(e)8IG zB2`MQ>szO-H4^zYf~#M!JQq~JEiL&5M`rd7w?9N1#s{WtR%`HQy=Q3V@RAk5B1Hvj zRQt6gL>Cf{TE?j)c>A-Y=GsNbsgF`vot@%XZrR15r~3Ik!aN#|wNFSL2d6DIb>Z;q z>Y_qs*2;7}PRrpeTHD6s#oAp+hT_Vqv#`fR@?&s+fZv4pgEs4T4>X~~M(-GxA*Cvm ziz9C}eP`K(sqN1`Enks5*0|!6*EW?ou(FQZZaoF+5cLWS~KE z&>#h9kTT9BE`IBsObrBb@uncnY`fWPdtqDT$5vvzX;S4W&1m?^PyR1u}?Mvbyb?Gk~mqT*WyAikz%w$**hGM_eCdlS=U4ve$JnCIM?oyhz3<%xAoRY63|<~C&xVllPY0}i`Ld=EsPDS_CE0ynyq!*3$q-5y!LC+b(4(cxuj#;W+T0usLHuXxdxa5wJI7 z-4dZyM839}hD*GWCE%LmW#Ce7?%%-`^BVsHUsuVe>6(Sr)!Mtz!5CWDpg^ksk+qUn zTaHVp{EMrY0S{&Yn9f+6J4+MUes-_#H>K}8UySIkHi}xZr9WV~k%7H?y_ls52QL)V zSO(eVU9#?+8m_hj$9L62$x>#@4>KH}>$@-2V5GYOLUlU+tfsDJ(QuhDg7cP)lMPWu z=^A4j%t6+n6Ms#vyP9~ z*>)^-9IDedFuaTUyCLOdZARxNd{&3F31X}m)W9v7VQYUhKD)HWWp#2p_c69$DHMLj zw8CjQbo?+%gGl$eC1YFVOeAI9h-odQ7cg~hUEFYW>0R9onqj$Kh8aGg3;dn5u$D?C zcT^AJ5%SHsA=pFx6gArS98itIXy?2h3hQr6w~27XhYEaB(F$OT?0Lv% zetT5)I^l0vk9Q?t_SZ60boETs{Fj$0PTdFj+y^n~gZ$`&%=I4l8`_YU<|fMRYK31@P_1XXB^1 zc^~h4?D`Y0>eaPnHy!Kwb=TUeHXWmUemD%KUme1Xuy7s&-jq`87HJsU(GZ`6a2;FA zpA03KR^CKv(0IqlCSA%;zft_~LAFf&!w|FeYShri1Qr{Th|iVFe?n1J*P+gxBpdVI ztRO^p)RQ#lC1uQ$T!7#uli!PN%?BK-|7Hm9B^?dsQ;lOtk2H9S5Jpzz1d7vb&#>$3 zo2QezTsHe=^ye<(C$@gpSc=O>>6^YGLbP>(cUrO{B=>pV*AM6;H9lCgTRvq1%4B}Z zA}!2SSF`myL4mwQ!jU zO2<1I12}cdUV~pSZdL4Kd-3VAh)TNc)LKL|bU4Q0SF$ZdS&P~5afZ9c(B%sGnaniR zH@C?)1^IkR7R73ImIJPitMTHejCJGB+kBr`FdhY{qcA+=WjZK&RBBf%QCmv+V?MBd*ob19mj48=_0(Ua2=tW)5F zSf5!&cwDawh$GhD!K)NvnVEkcBRcJIZG_%IyS>lhc~EhTl!MTqVL9mx|3XSIJlU1m zHp#nvmgVR|KKFn=M;zc|^Erx<#QVK40JXoX81J82<7k*63g z_&F0-CKK=eCpXh2s=dxOZt-1!7cS?eg~hhw7$h?@o`>%e!`@wL?HVFbe;@B*MM!lv z=^(n6ryuAm-i9R8_A}lC?Gp2ZWSe|R2ndOc^RVK1e>PcZvb`GoB;JO;O1)(7yQPmZ zqSS^3*uiOppWEUuxK8DGbUbmhV3|&wu*gVCBDhW{0wIHdKMDE;2t04?rRE_HN)av7 z6utt9x2>-@T`v2>q1K8IWivT;O-i}`irF=$_53boS^Tya{HstFg>3jUzMB$!>u_bk z|FGS;<@%mwcR#Xj*M@@<<6F8{SM|s zjo)JH8ZHr?9dK2*$BVN$a#o7Nn9PXQD?1Or`6Z2q%5sY1@ zG}P_(NRz7d&xg(1?x3d2g*eH{vswMgv!Q&+BbpS9no4?V{wrQmEe|`wJ4+^Q&hV?` z;b_<{!$VwbQf9{hLld>eftLJi)eVCbUv-HF)p=gSFBlT|OABQ~&ub-XNj;dAq=VyBM9#7ullx>5 zKEgdg!(_&yWqW$Zx%8lJdm8ss%V>3zd7*OFlg8eg7Q2~`EqW(ZExueLEuV+vocr}8 zcjUBRHpqGSeuAOl*AIuH*{U~M%#>BO6su=?XqP`|qSJ zYA#bll~Xc#<}emDj`Y)T{_9(Y_dFHfWYOOGG9xyK7Wz;x&td}aVN?FZNaY&DrbZ`d zTnWpRV^wa=TdW>>utexVb>_-qit=ggZrO_4wtdU;ppUtHQ?K*gIg<{|`)DVOwXK1| zTsRSQ#5|v0TQ!$2Z>{5c_!Ydj#mhoxUJX5RO@sOv(}O1(pPkn|j;w0XbVlIbDO0mG zoz94qhMndT>dXHork#B!{k)8XWtGku3TXE&clrc98YBiiF8>}4HoTWb+s^ahvFR0l zlp^i)4dFI97qs8*i_b_(CRGWz%-P|I6>*!ml|}^U2&}Li83qJATsyo%{%MvvID_gHmAfst9;17F^5d>sTO^FqgrBVSxT|rg|40*C#GPILX!`?g z>wmZ#Hd=22X+oly!_w;I^23J8Xrj_8z zIB7OsC3tewe&?tSRj{l!sR!ckkzQQOQ>`-h_z@>14{Slf=tHX7G^3IX2up~PRI$Oku^$Kfjq%SW;If5DX&On^2Z=O z7=pBoC}_NK5?S%VWHKh>kRO;dDwbx(C<)D+wSSOgw>O4m_XE$u;Qc?aJe2YQde{au zx?VWHd}msI^-7f*7)%4R-t}o65|OU((jqrI$zgumN}~EZz$p7CS}p%OX|dT09wk&H zhpdEOnV6WxKm_REPrad!UEcBaBSwn`{DAC8L; zqGys)(%SDN|*dtI>I4?#sY?M><<;)^%7i%B3J2xH94bCZ@;jKa39B?9^D5}5Wm z0Y*$*Kao=!^FUaT8N1XmeI)y)oT!qoNfhrFT+=?`3?fkFf7=pa>?U#{CQ)}ebOT{* zNPO%O?3?<4v{n$#zG)5^!mL0Z7f@}D0WcT=Bj-I}NCYN{_7hzU0uh+0K${;xI+8iN z)QSO6d-W5$l%5)3+;9PgDq!pY9dU1B?V4d0{2YhKX2;_SfapD>l+L5Fwu$+sIGt-Pw|~YOQ^-9;W!(|;-E-EyFfzma z1Cjb3KlWc7`U_CzODS&TC_7A|MXHarvPNdV|3EAP<1vulYI9&j*^v<~3Vy5&{PPo^ z1G_{PBJ;5}{lA1fBQv!ZG^X8<-5>E7$e>JgDQ=P|J8q)IZ$`&Vy{_%TGaFKrT;~&C zZFlv1n?kyK>vTAkk-D7aQy;pNJ?&y$PY@5@-j5xh5Q!i5qaF}rX$U@%6E~;vxm=ct z&39KK%KJ01Z1WbQy5(alzpU#96z1%5s}e1w9a0F;DJ^7Wc|m8Lvl44{C1H&oO2672 zYh#azt_tfBi9?5hFm4@8_kc1A8&xHN6}NQXf=iNntA@?X8Zx!*t@KW4jGbjuXzqtvLAhaNN+nAUy*}az_h29|CPCON&ecWH{y<|8bNVD!US4Fb zf_9bIVCKQ)LN(3e*4h5pf@N|v_INqZ6$ zEa{lcysgFIuEkD-e2$`i{P?{>9IF7tTSs(}$v+n>Lh*?wmx&8N~-(1#*1(G=3J3N(BrX)^9# z*yFE%nNZ)0^?z+oy6&-?7pVwa`Od7IPu*&Rk3VHyUJ`bzBPmIP`DiwTgC9@CW_*By zKV=2DHDvOsYr}`oY0UGfNod0(WVSg{xKyyi>;5zQDnX2|A|-kK2)vfvuYTQ<$}K%5 zzOxm(s>r%HA15;NyBZA8Ekry~2Bn^jTm^6(cJY`$W5HbYTSi94sSCw5k7CGRbL1#I z@@=*4#b+cI37E5G<%s2b(VNhN!Y;eQr1112M$o{*+FSC< zUX5yj>V<~pqL6O&rvD!rOXvGkkKvcnd1E9V#$U^m$khZ%BCIK@E`$37Fa8XFE4%Lh zNGE29>G_3M`#C}MA^%&^wK<|ZU9g`0Z=Y4rpYSQEK-}LLNc2*qC`wV>@3OSaH?%y( zyThjjegJ;tf@owEDN@Y4b-VVc7Is9v?$!Cva|8IaI>Hb5Y-n(bFwa783EhauF9kVr z0zV>{!E;-F6>-~|a+llN$=cuUrGj0kbFEwk&60Ot^EG%;vR0pxXs90XIGHU%OojI!2ui@j+%$dx2{9?F@T^du4?le^$9<5j=LKaom zB)PSp?dp>ppBVTMe`QKV6|h>2LXAqlSb|N z%O>aeR;jy3CVt4h*C}_VRVZsUuhcmCWdjzzA_or~YG}k_Pi1U?D9bIci56`|jmtg0 zB^}Qk=FByzh8^#@^&IAcBkY)+G&u~0X;B0PS?5;V^()<+e}5GiQY^1?3i%4_E!XL= z2GOc@b?Cs^XDTpsXsiQ;LUc*J6`(&z-0P56*FKu*cZ(whiY9rS8lIT$5W-D5}DX4M^#*Y~N2ZyP&i(azwjKX=-ySS_!brp`C5 z5ONNvkVNLGkus2<%x6+>k~*`l>Ngv)jn>vsJ94`yYJerVJ5x$ilsbO?PS*B0^`U{~ zeK{pX+{2@A%GLuo9vSb!AjXkhG9uvei~PsRTDmMgFf9RmA)|SR$^N|K)lpn}T|?gB zl5S`;5g0?c(wcmVOO^EATK0%-XoTykYsl`vE#Sd*U=XM9ftEXU^jasecFT=baD>-T zt+)P)tKoMjA2_CGro0*p_Y22fkM?LJ0C6;g@;lq(#^q%iz^?NEo#Cr zie7_f5t8UElp9u?yGc|q@jRu*MBa%3MC~DL~>SKoEs7#mvv}8&MPCfyFSmsOoM1G#lEr?`#rUnC^_QAx=7wJH_y z!=1GBt-_id;C2ff0tEvk0~7)@0Q3XQ1-5{8#4^EepGg_sE!h=(7FDILU#<)*F_HY- z7X1|!Xha8e&z^K3eUJHQoD4XV-U3c0z*!^Fc0!S&-2x1+Qnb5)fz_XqDc!1xe2{}F z!>Y-?kAo@Gs%h*G2UC_+Q#3HkwrW!BMNCA{FWL9jj1Gqa>!XarduPwBDn`Zl9%vsT zswx3g#-DNknM<@q&te0uWSS{dWdSFn%4_BBZZHlL-I9F)P(I$7T0X)1rL5SL1qlCj zLPGwSl+9ZjNl9SY_&}NlkfION3I69GIBBHF9~-iXbSGtG1=3rA^vnEJsl!NjU5BY% zGkjzNTze%A)4vqJL>-y+-^3CqkOveVFBlDEXdi7nMyjc>6T%B^rWV{>x5bM7Drdw0P=PRwgWad?X?#=4HeSppw zoP+IpM9|i=XyUwUw%zpRPuzp?!65>}fbBj&`3E{8w-cUgiD~wA$+jR2iN45gSmnBg zb8z}zsfqN8h0jvhd6)mTffE+SIW9QllI_*Dlzmxz#(OoFy)~Lkbi(|_JF3p;@rz|Q zy~=pcK-qXts+4X-C%y?|tI)LSN?}Cd9btD0j>vXx5}D?r>ahQ+DnEa5Vbqwh3W%uN-5r^3pev`FQGw;goh|!WxS_1>{=6=QAjnx@ zOhq}1g+-kiOv0B9R%~H5#_w`!WOP}b<~|a%TrS3xZ;Ld|KIt+vKd1&5*KKK1>hgm< z2dBM^6Y54nr&21IN^A}&rlG_e@ypY_tNT%-F1l+1}#)8liBUi+cB+J5B;A$QYtO;{p6_jhuLQ@bx+ zq^HNGM^%oz$jIqE6v#=RDP=aWKyrBBv1v*EgyG;DNrYp5%$GnVQptZE#h`*Dm9+l? zkOQ%4GXPory96PipvPGuf#hai;P@GdhJO~##|9!%fyh@NxuhT1v^w2kI1NA{1E3H) z5Kaup7=Vln$U)e&OWogbZoW&1xRQqd03yVJ2 z86aZesK*p+Kz()hF9nBa>a5@2To$-A+5pyp*!m3PmHjxt zmEizT1#kvP0H_6+2Dn5*lEeAwWSH=tN*1_gL)Zg;vI#~Ku*ey^x=-C<34#C;015zK z0rUXO0PFx<0eri^C;WUbkQfDwNiSr_iL|GUBxIogO8{#Cn*h52hXAJlm*0UqI}>1T zfk$!>IuPI|$oUlD z{fMx$<`p_|dvS}9wbdxBwBxIUm-V3uX`&cZS6Fv->@7Jjvm8Z5dRKbro5`|1_)lz? z>t>Ul-kjX;oU&z+#sXh64)n@gt}b)cnta=4?&tbUOK)4`vkeFR(;vq6!^a&nm6hSF zpWPh5?9^_$Gg!>aS6ZrSWjA#NE97fef5Imei5mt)nxKEzCc0WJ{TfO&1Mc+`b}3Aq zD`YmDt`~=Ve?dMAbQ$b@8|tm%lf2?A-q|JBy}~u%^5u>{Om3!+h%Z8OYNmI37wUt9 z_0PZ#^+AqMTVkhovd7(|1-amc2H=P|EzmpR$q4putB4AO z8`xv3sq|?RHvP8B(5CX5xj93UZb0Jt%JbxTeSIF5T#48?Vq@$ieny-vAuxJ;f_cse z2`TSeZxLPP2wz`+pQqy3V#k4d!iH2I=8961cwp2z1MCkLbErt zW{is`DV;~dC>o>p56AL1R^gb_HL|wXb)XEZz0bPVduB*mfKli#5vV ziq|evs?0_}hJ0USo-guQ4fVY=I~z~F`}$2g@fEuSv&>%zIXgVk=;mNBZMR3JFkMogFvwxc244r!^W)=6b`@ujWO12SZ%C z<~-$k_oKqP$xN#|Wx5(mW#nXe>bdvv-~pS+U3QaSW9KSJW1QZ#n_R!zcge}B?&`?c?lY;z4e$rHkn~1MbInN2w;_O)x z_&H5dCx}4TE>LJ~p2T~>P7LGGCi*g__I0Xb-s| zEB}E!hb&28+$Z0azfR*+aG=z6kwg7-X^XUQd9=H>aFJN|u35SMbnc`vY+p<#cE!am zzMH%rVryzQm26`@<&$s6z9?tSKJwYFgH?FWTRHse1Fzh$AMTIj1$^age|sjT!%(G` zE<+{S%5|R0@1N(B?g*~7?~3{CP^H>ZzU@lunoRNOY^De`cEbjReTF@y*TF-X~m zxCQwnNT=Ms+iw@Ee?mY1ce_4Yx14P)S2%km2?b_prMg?JEK+~@_ZdAJ1$Ll4;L=@W zO}N2%6?EC&LM}8qVd#BksC4$A@4V42BJuAA;`o`kg!l_W+VNe;Pw@?@g5FQ8)N5!n z&0*iud<;I5WkV$Tyez_^cqh=YarV;Rt8NN%N+@JmhCmp{9~M-}xMXQwv?Sw!Xkgug}3wCI4AIW$I3DnnV-b>*H_4Lv$NO+12Y!QK44axmQu)Qq67U; zTVW(Z4e)RS9{i#(Ywc&i*eM1KFc&*Zc?orqdH8_|^Gg#Q4Qxe)kq>sbGqtC-K&DV; zT8f+MXb14tF;mMO*#e`%0lcVAcr@X`X(wYQ5vr&FLo z!!%uydGtGJv4j$!)27`hGb<3nOUfA;m6oDz0QA_b8T|n&GH*}^GQI+hIZV=D%K-f= zf%sH2c9x@fU}Yz9z|Qjj?JOMFnNW4OwKgRLSOp`nwgwrXO5*~M4g)qaVgbw^Ow#+& zUX!2_#Yvz8194m*dN2uU1`xXhEawIXSWYugLa|>Zj>Z|-Fvh>lWT&OjM*gOfy#^}j zns^h0=K}kdQJA2{#+#{i__wvwp15imeY}IC->?+jm78|XeT;6q0s8YRPO#4}N;^?(&*dIV& zREOA^nL7)s1AU`IWgYSDV8;*Y}5^*Pk_MJYaRoGQ=&zZAP zFQLjefbYG8!H-4R|6zAh~-_jY%?p&th#E+8k|8hfT5| zL35Xnv@0am(a({HJ|!j*#CGV(cyjzMsAjYvh?06!tT&QP zRzTntYsgES9;_YwI;ylNptKB-O6!Y_joWEedEVCBKcp_IdY8|WT+%iENxJ;rL+Mj$ z3L*$(3feN5*Zzyxf9OK)O07biW;(%}cxVwGsnao{kDB)ZN9i;pjiti7O2O%pA*{E zs=Vmy8lbI?*Go(k+DCR-CG+s}sD`yq>O41fx<|41qV|&}F zt3dx=uGyS-Owp7E&rX`gt8Te?%+U>X)8xIrw#d~;$zbdF-6S(Ao8a};k=S5pscZtd z!wpUbtuC6m<{plPHqM0{ofHT`Z-a$3mjyJn1XhTP-0PKV-T7D4Pui{cWOHRt_zgfq zOyxQzn=*%ohpXbfGMjiE(&i!wjSAjhpEaQSs(Uy4y28+$*ro$^l()J**#;#r1FwlC z%Vmv*vjSY`!fV44_=96@ndx9TT!4Z;{1A*;(h^@#n$BN+hn`SCB(%{jlaNp6y&3*3 z;n(3q92=6X_vK;lu6rG(p}!g>duylLc3+V9k}DHY8_UMZm4%E2mLq!npkN7QIPZhFmh|`A(af|Y5%ypx5Qw^=q@YZU~%{Njp zhQ{Q5*imGIJ^W!HBEFnpHzHGfXkH-@oK%gDxBfr(c(B_$aW1m6|IJQ;ne<2JC$uA~ z@y7wdcTh2)yzl>p_Wun}{~H9c|EFO?jT6+hP@EPGcVmFIwOym{jmd}0fN~~@_cRqj zC4K3dzyvpsz3b<{+8h)A8`gm#CC&@ws9II)^KNc6W)BVrR__TkIHu@DYEaY)WZ)9_4w2&hIEY>M`arHjQ42Z@#z> zm5(1sqqvzxi*y$Vukv(h%pxD{+=@wms}Kz^(K?RCGC zKFY&ob0w1fe|m%ORib<@LjHJ?*rQX~zl%!bA{+|mK_39uMw*S0zS+{OkN@Z|N&0q6 zqpja*p}qTD((1SIN(49A0N85Fc*Q0uEp31ldrPDKJ-dS>DK21$u{-R566hVZqI9PQ zf>HA^&~YV5iRr?)KaIYyw@X7>`uh4+*8ZFiEv~W8+caIjF`p0Ukrj{ROYG_C2a4yrPS(8r__|TF)X7Xrq zx2}KV+HI;vt(4eUZf?yIEEWFPB<=hDcD@sw~p zf6{yC_(}Zx^qRiM2Ei3T7gM+eI(VipsBmf~p?J&)7^J*hpMaSoQrVwVbDk!$ZvX1W z)X(!G_NH3XXMfN0?{BuAHC!hy(!jTCRa=`+AJtZG=5ZBcc3tc)X}fdV7|MB9&9*`| zohz)7&RDB1r9akyy3*-)`KBn53Pkq%%d6&bH1#Lw3ibUulAbr`<`KOjv)~KFQo|@| zC=4Su{Ef2a^W&o@JOy#hAB1p}d1lL!64FCF{%*I;F?;-#mLZ;FIaG6Ox~fQNJ9OYH zJ?7>c!`URHGgfCD#d(%L)%v8J#JPSaBZT<-&N48~sKY4q!}#aCi7sHY*%?H1 zpZP~^vMI1%jWTROwdZ>!hV19QD+?077>FneSmK2>f){Q%V zj61Ux--93VBYSMa;l*@x7X9{DcwcOJHvRmaOffgZ_{=y~0jKS)PFF50dG6l-$F=zK z#`GdfG|S$TFWFx4dNL~>>v1ztz@!)B`U_i|!eUh$8#L)#<1>Le5hdsCyZeZK`@p8( zqK77yVzi-kcW_V3a4b1~d54xgX0GR=-`A(bDI6&iqr)Z1DNUc}`G?)J515Nx*;CJ~ zs=vk^rZerf?^bwj=l`CLeat#_*L2wt*JM#ANOtcX$}hjG@F-p7DAS6AlfG{WS+mrLLe|Gayn&jvru9KlXU>P0OJawuqG5L#T zlJxcNuuCd2l6ftVu|S$($kxhspdS6&l8=V9@p=pic(AFNMoFkkPH#7bH#m|8yXsp! z%_hOyC9HmPn{?A=8Jr6RJsRuKW;>P(jN*Ly@or4qe@{Ixm~2wou{*sp{oN-{<%E5k zcE`YKSZ%V!~a28qjheO#(>xC13DE>Rce+I#c@+J!=6V>Tv^~=pF z-ip7a%|y5tX*_RTh-G}Gc4?JBS2$JieBsNGtO#C*48E9Kh6^$l=}rEn-+dnS(&1ND zu{dWnpzudvL`+f8Vu<=Ax&C)D6|;F~3Pq}yc8S=s(k3L*CMD9QB+>>EY10#FGff&% zbr_kA8JVpbnVpE*P{IEYeX@SDR8;`7>PkrY1();w!EQB;M|JRa;FqlK_X0Mepl9u< z_qF3j=o$6MrjrFcL_u_8-9+_@WT~S|LG1g+o6Y)AswlC{;2C3<9->bN*g#_9M`Xp; zpFklxssr4CUsVz4L;SDLM0J8meq6upkeFtUVvKh%Mt{I9Ko7q`1F9NZaVExeOj^(h z^#be3APTCCFo$xpBWIJ2R5+QS>+mu_`Pq?K$nb0_27Y0oqVz9?0@X#L#1fHB&@)`$ z0VRTgg$eZ$xsp45#XO=07D396toRTHgvqcYlgFAv<=Bx|2}UZ?P0*LZ%%MtvGh}^` zYJ(EOb7A%M zdQx_jgRg_Y7Y3JC!o6ykS);iLmRnhI?H6;3mlBC$ofewi1ON?n8-scu0lDI#k<9_J`IC zcvO8qpex+6XtDOO9Z~;Y&u(OVPF12Mjcq5ysTSvkuEg;aKogXs8blo9R4qTtIj`oS zzQ1`8=E&e@lPg{C0kw#AkT3@3*d_!`oW4QjTj?QcZSa!Wx(SU^Bxui`zOJ(y8XEv( zSPK`V)JRUu;<*$rY^Nwb6xElx2(-90EWS53|3JLFEu1v1ahSGpD|H*^E~4B&Fyl&#m04gKLPy*JzGg1_LTu zj(N+Wc&s4t{K^w{soXX4>6xivqPiVxxvJzd8d#%O=yiH~_X6ysBx&J=X5yn8LQul~ zH_;M{GOPj7YK9qzH_aK_1ei>Gu_cQn-fi+6>+p zzRO&)YiA}qk?hU1^zoyT(+pA+R4TZ!bhssZd7@$d#d9&cT?Kgbce!=)K z>5}(GVj?*I-FQ4T_IP|gHf9Vpj*JQ_y>vXl6ae;HdTAAacz`JY>`1Vv3K}p6m;%5? z2Xu54>G)B|6na5eNaF7j00_W7z?;y--wXgU09F8D03`qrfc?-!5b~cPY_z|#VW{71 z`jATm**f5+2a#ZLyR>uo|clkWB%(0g&|onGKMM06EG`OaU1u6Hun2 zMr{Cr8>mRC6itL#EX5qE1}f?;#a;%~3n0&1%66nu%U|GJFh$x+v1dkGa`{52(1_#&8tzNE3Kp zCuhxbFDqwtMf!-bm#RLBu*hN^i!dTSf%r&d96VN^dI zc<>7&79U>uK3~1wsrFwgj;!{7Xm-~UF+I1g$R&1pJ5tB*F<1+hHSqO!&sILa=bL+3 zwf|Vqh*sCFj!1=} z2S35c5e)uwXPc$&;vR#EY2(UpoImP@l-{G~LDA82@L>#z&IFzkhE@HfzWh?Fk>`md z7qKKll#3|pQPx7(PrcVd=yQ8iAWom1E7rZeh*O%fF9$Afvz2^>&0X+>yG*UcD%Sa~ zTq@RY#6CjLC|XdCVAsphI~}XK#$JZ z3;sx`+E%siwiU7O^M1_z-BZmrR4c&u!l^>!Vo|F?gzr5eG?yd=ccj>q-uPZ2)%)%V z#?tuAqJ4SRg5YXd0CTT_bywSpn)0~U%5}jt0pCMYl^X^O{MUXGt51s*KSzcg<5Dbx zgpNem*d|g31Ay-&nWs1Fb!xMp6nt2^9Et5Sg-h!{nIhVjMw?Th+M)X9xW;afpT ziG&dgO7{D|veu4%XQgva-oh_?B3!--EMrlwsExa0Rc9aheCAvK_4DL&o#JqR6U8#? zJ$YT>E_0r>&$WwP{ea&GbR|2?JcZT9oz-&5Lt+5PTY9efeOg@Gp)RqVsy_|>Fk zuzh20>zwAPXKXE8uPV#ANfc|jgF`#Xr-^j&RHUUqkayp~C+*P2r=C&9%b&l(b{Daq zvvV**DVeCcdGuy=){8kcw_iXj&}p>{PjwC>NA(*gJ86Iaj`}UxylOj)$P0_((x8vw z)rqX0e9SFfC9Sj%USf`Q)noN0xjk#lt}Iu~iH^a49zbC7=)k%Ko2VcgD}(^7JEcqMW}J z7$pVezm~xcn!<=6p_0Uu;$!gcV~|E+cEK}F3Zh2+O@^mPwDT*hhXF+r9}sIl4vS3% zt6)Za1d@~fgxCl;0!h<=q-jCY zbRcPZkTe5Gnh_-Z0VK^-xdFUm+uo_nzGQTEViAcj(Cdw**3#>pz)yRQKbB(SUzBi8qXjO_G@xDTZv5(PWkBK+IW2=shy4k)*`azHOiM@Af6Hlie zN$LZ+K>^NPy2d{*4D!Cg9<`YV9z9;JQtDY5`Fa*D_elG+(TS|725cnm6m1uCj<6)r zr6{@+$D11$EsPFT>a((pt{j^IaQ*9di`}~vl+EA!CHoBxPdp~Z!x-aknK-ylbj^&Gx*&h*W8(v@MLR(@c4K2UI8P3$!lN) zFhK@JWSN?vQTYp`0;12zMZ5r70Ggyg2G9(!Aii682SD^n zm5drmjTt}?KwId~$$ zx^f){o)MY10dqXg2p`M;JJQKhLV<@%n4a^vzJ9fH)aB`APKHR$d1hO75em|^u44D{ z)af^Gw3e=An1K=7aqjxrX7c%k*h6PGxt9eDKh)t;EbdAuY3^bw){NQa*ku}?<<He2?tdZp{UrrU^dzr4)7!fW<;SzBNy=&rWtTAN+VcmJ!_ zdllW5Wz7cM;)0T2&ryHG}WY5*5(byznvg}VCYHzs_u{2&v zUa$WsZ`+14H+@@?RNs+udntTUu^V<$b`s0Pd={`zOBv>sPZm{TCxCbO6*JX;#J#!O z^yD0-bT4yNI2=!3*=Wi|_n|9F8SbebrF^nfp7ng%c`};8Wa4|cwc1Fz`Pt6WXOL-6 zN4+K+YsQYS-FcA}s$Hb_K}B1Zg~&qQFHNoGskzH}r;lrAa0Z-QZg{Fz3HCQ?d%l<3 z8Cag;_Je-gvG6Rx*iwuBjTfcdk*ph~EX&h(m*mn#lv`Uxu%#xRx-e#+aw2jwN@+d`!LN2(s+l6blbLXEVmsobBDwt{ zr*P-)*W=|M--N8cDl+nu6T{(Nr#9g+XWQNLv9{s~1Q2nU!)%D(Z8W#Fl@o)39GogIIGd-uJ-@T%1;xkmh5IwPwIW~(MCs-U+&w1mgWO{BuF6kExozOf3 z`^h*TWmZ;J-xo~*%O-IBmTgRfi~onIuMCK)Yr9suQBu0Qn~^l=?q=vlkZus9bCB-t zPC-ISx(AR3>F$pC4)^o^_wB-%uXc_O3`Kd6?rS}>YkhLvWRl}3(@W|%FGHW^}0C_Obia6UYMGcv$E zGN2kY?G#VCp_)%S_!G)F$j#0tI~64t9WVT1ntUu+3U($4?vWgO&> zDSHBkC`dlo|S3suJ(4Z<9bv28`(Rw-`zUglb-WLkbSC`36gKUhRC&7UE2Ls3Oe4oM)z^R^dl7JeV0#hpaZ~WRn+ent)Wy8t z2tb8s4FgODVVZZQkEF$z4I@mhud>6sv=pg2g{&0zHiJLd%CcCcs@VWPQD@-!bs}vF zLw7sDW`eueB`670ND2fT<(Mm$BC|QmidiM9p>^l*6;e?aQUe2Ix#o&YsK9{SOM;KX z8B@4GY#tEH8w|uU11<*boK_0f2QO8?92mN4#NNh0iFx#(*@RiccMV0CA%LS`LpRfC zF1}(ZR;8n?yH)Vc8?C_g2IMx@DukXr>=bICv3>zQEHy*JxTKv~ae7#JvpK&EMQ zx7hj;jRY0AoyyEMT?Pl3en6(_X^Isk6|==rv+eSbYPD}nkfS^Ef}W?qA7NkRNRZom?Z)=@;G@}ZsLs(SZ6`h zL}-e=B^B?YGOoF3LR7{6bTK~h)FFx!edd29tr-A0dKJg|nr0DBvI%(Y2m9STHD{fI zky-ig0k>}uHh7vvB*`YMnq@PJck>@P>!M%9CmNXvy%tUrJHmK6{x>9H#`bRBkh8AO z$Sl2UKr;w(ghZo5Q><(pZSmJ%>vNa=n$_}Bo4w+#wzo!-Cr9Ku zEmj=T?Z?w>EB1&+8>6;$C7s#wTaqUAAH36Si3~S8FQ^4AQyH4)vl?gp_8Qw~$@P>k zjrc@;4}c3JvXf(A=OZPs>BeWNR;3<@b+xneQ}+2JvE@)uZVXxM7eV(gO0I_sjZ1Y8 z4?{5`a{i7TKJ07e+v=Sta{Ed%qgqa1YV<*NUmrcLzWKS@gZCCXAoo|L%>^VfeVx8%rQrbEr(tIrnURT zr9F9J4YJAQ9XC}s@$D4$dsQWZ^_)*m)i2~bXtoTNJ|%A~SKh6_)JIo~>eVTm5_BhE z$fe5Y^@cySKiIxql=6ZgQ>k*fRv8{{D%+lA+Z@m}NzcZIYBWMwDM~L}TfB&D8#GeA z)O}fe($w9gEgSVeNieUr$Lr>Pw6*P9SS?Gei}|r6_f+u)E3a*IRfF$H?6u?M5!1GDY2&lJzI;?NT^!M~uICUmJ#L@av-%X)2fG$^ z7QZ%=``wkeomQHyXH)q+pf6;eQaC0BKk7>8)(9n;7_&>`?bYeLcqJ9|oSFHpaZ!-C zsp0@*2=;erKC@4eqK!qN^f7OvFCr7W zcI_^0`B&izNj2yBBh{iF=L{$QF2ndd3N+-D>kSGlSd;#DGAO=7dfGPkT0LB2U05}Hl3;-(^iIV(vxZLS;F9YRQG`?470KTFF zEr72W{RLd(jw+e1CM-CsHC^G(Q6oZ7v|bTAyMGimi2o=7P}v~-qn6AFi~W6&2emMS z3r{b>56cFS51_aNpFYw#jT;Pc3$F+I%_aB?Yc^(U96%r^04|$g6Dw2M5z96B3`UeT zB%EdymN%UM`T>jsm{Vb?z|FQC%h#k_0dNf9IbYK%YzpapfbO@3SB-FcuWb;f5ISnv zU&)ZX*)6~ppF)A672uZOCxy}WdVSOV#tRQPAx*upMz%qm!Uo2uO7Nwnlv(1Eax^JL zK17SBbq}<{(b@y*9*#EpL#6opARsjo5QPaukOC1xK!i6C@eD*@egqu80}d#F!`nw> zYaGCdj?x;J<^VU27Y#7t0S0CuN(+dp4=B(RpJIo?6@bO3I4SquoiD>^*dBzcQV0cW z9u7JlcPI>DT{ndXViWsO2mVFPFmE@4)IIC!uTRN^%bm4V!nd`a8a{+-vc-&2LtRNl znT;Pwg#@k|PuMA}S47%_ePQmPQDopoB8m*}QJ<1tl?MYkg8t>=9)+6&UY8}YxrOI7 zGq(O7jz4MS_6D0C!d1n4GIg6C_kEyWyjK-H=1ZF1MITl{`ZM)KBS{n^IzH$N^=Tb^ zmMo+uLscUJmYqV-WBO>GUwiHHpiHi9{r>(1=f(7t3%gzG@n1GEI^?3G3DsNpQqLt< z*Kk?C$Ph_0b8f=ub7B;sm+%v`O^Q5QR$}6~dM4fVyAi27DND6%QXe>WE#i}|!<#OeGNP2Gv zyf4rFAY$mipY->L(@=O9#pCCaiu0nbROOGf{Obt#?e`=bq^@H6rd0xLBgPT?nTR&}?Op2n?DQ>v5Sl59T|EO`Imw-a_Cu)>uy0Vm}X zxe{~Bu$qP&b&`fVHX^`4aAdBy#62c_Yp8Y+m&&!B+i#N+8f|4lp2eCjTyJ6$wNYs4yK8YszV%8AYMRi+rJ!2M9)9Pc3o+SeuEkq+ zF<~a9uGJ9iTfc>+G>V(BXHeG?Dnj026ic&)sL|5*Fmb1I`Fx1lCaEP}%}Bv4mOdmf z*s7-&lrRBhP;-%yeEW-4EFBg4iFOt~{LV3~*KbneIQXgp&M~3@0RR#J6aZ)dF!IWM z5IeK+Ke{Bko2DkhDMFxdinV#Sz7@o~^go<_Q^k9|lKHTPCnEts27m$p6#yClbO0Ct zFa}@_zzgccLs$-DS2F*W{bji0R=jPv2z@1%1|P z!HrAAlC}x`!o@^>n(#9XiG?B#s^k)_gvKDv%-H(J{Yx8<~&>Zp|C2h zQX0Sz=NM8DKk&UEL0nbNB~pg#TS3|`!4D@m8IegodPIr26m>iUQ&m-$Xc+~-An{_r z2Mn5k!C;b)oT2JtH*;jw*M^^HsO4-xzMtZ%1}>2-;pK5P_j!8qXc)Bkl5;5u?|>Ln zAO->?(U6?;2!8SB0sJR+i678J>s0e?7IcgR7}WZQ2a!T& z5~xOXJ1`UjOk8N_6s8mGo}b+D?cX`@0s{v5($rPO`rU$e3k(7~A)02G+PHe~_Xn?P zrNVah{_kZ0hXvTTCzB0R6B^Tvo`<%gC)mlpm_Nn%>Y+b{Lub^6KdkBg#J$QON#v+Y zKySg8cTAKQK_G4RF3@wfrhd^v?&(Oz0NGv-R1#yY;X7E{+HM0@o9%DoH_Eckv~4i; zJnSw!`V*ZSE!p)KQ?U%r`AZLf`{^Hp*zsA% zE2hc+6zN(pco%t6KmO2P^qA*i(fCmZwKpDO-clS&a{j@zcq0&BC&pwnbT;!$+dSfVc&(+`xo6MUMf8KJs?&*l z3ZqTtJiG$2bA^l5m9QZt2MQ5-kA zxBdD%Q3{T4zsTDyU_a|QH0TedcSS$2Y3@~5K)d0Z{}sBe7{RDLyVCO{sT!Njy_kQ# z!~HqaZy3+_qBVENLQ8GLFEn@V61`}JMT_VjWAV$r(4OfhyB&!lzfbY;(1nxqd-seC zJgs%~hk&#*nKPX~i^v2H>Aa^O9lX2YO{a1yM-RgpA{a2UPK+teD?5#Mh3*b}wh4GJ zVk?b_x%P97&746;#24&U?41_gL(e+9XObA07a|AK#p#`9{o>=}2FZM*EE5;Tp^=Y= zsjHSZ6KUi#m>rj=xuG}J@ZIAYk^V{9dAh8P(GbrFkWH_~hy+cC2^R5J0_QH^-&yqG zze?y2BFmydQ7uNjrXz?n?56DR&WN15A|ja~p3xxVUVFgkmp?=s10TLq!XAE**Shqr z9)V})Td%izbg!>^^oalC8o3HzJeCo996^o^t%&%HbXq_e#O1XHjdc)Xrn6}(ADs02 zZp6=x8_fY* z953Mv%^rJP1EB`(9!Ht$bXu$E<)J~dZvCq=?x)+2Ofhm){31c)b*N{v5F6$Ie*r zpU3RWOW1h!gvrMR+gljsqQZ&A?G;AnbMfPS=dZZKRc~5e>l4fHiuOzSg8~-N{=BIzA z)KjL<*%U{2t68wQY}xLpdyc1Vn7NGi>5M)P7(GMQst7x|o z@H>}mp*pyDlka+O)YGa&Kq7X;qEo*rD^TU{6lvV^dGhDvyv0+6KZmK}5&f)!l3|1W zdsvXGT(n3N+XD$nlhZhH^Ydtbnzw2D8TwX9m!{)Nll|usy(0Y+pxLbv~Bop-9JxxLB{PZO>u0q>x3y}Eq8hOSvFPW3it3N@b|;YN4ii!yox>@>R? z7I-$q4&N}YQhL1)+4d%2!&?NOkDSD%)4Q>H{5ebn$sZ;xj~!;NeBvE(=6&duvh9%3 z8u80r=7oJ*O@kLsvu!9Zajrzee2Qb>yZm%KF@aqgz8kv4UgtN^i*GU>C9`e#mZxt8 zc!XBzMI1+=%c+3wd_IglOrCqilU$g)fnu2+hE!EOhS@M6C%cz zCstQDa8I*Ljyp-=scH5Eu`IXVjTNrU6>~}sc^<&#y_6c8ouFuu{p`P4PJK_)AF&&I z$N)tB2z!<`{OoTgh4}=z;=7dEC%&h_w%U!=uLeRp!=4B1-abJtBrc^C@h2&WUh1Sv z|FR_S5NrQ)GJF5*-L9p6h{secoB)n?T~|huFLi9o`d#ApOCP=WNl9Mf3c6$#4h3$47+_6r@q(De&FzYtPAKv)39 zuemD=TV$3Y`~VUWMb@RwbM;wXSKxP9&F0EFrbQ!^>m*5^rkRH$)a!&uJEm7Yh}XQ( zX?o?2IA=x-UjMvwO-AK~_~{FAW&-5+LNzaR`a+ypFSZw|$*MdMKYbz2Y>{CJ$Lwf? zhxvMa1lYW^%`5MsNa*WpdBRe}!&Ej^?3ynQ~B3uvriQ)Ll$K~HX@%yinwK4~2@4ve8 zy#HDqZWoyH(#N<+#Mu2?a20YVTd)sKjxTFp^6i4j#`Z7>t{+y(K|5XhrDK!G7 z<_o`*D`4mH4~Nokb3pEUfg1TKouBvdE)u0HO)`HL7;=Hbp{(01kk&q*LK}~euvrek zk@yeb*bg|`5M3loiRwEQ|N7=D zruzW2ab(lPz{GgnmjaVNtUgUF^A04s36w{`SqhA#rZC>>Cs-KPdOd3JOt z^Cv?iKtc@wrD?a|y8qHH#Z884y%ZY;idm*ghDjjvR5m9HxvrY7X3rY($KMb8&@s4h zPQM=k93m%6AK)Ht8t8d|Ihq4u3oq7e7We%oJQmmecrSw%wVMj0ASC96u5kf!!vW~rWJ_^5Mi-!afDA_FvfsOMf&KTP2GttJ z&_181QZ>ShtK$EEGp75B#vzvS(4 z@Eq(l@8MJGGj_!SYzwjvL$0qF#oq2b(fU>1-f3D7;;}4kGrPc^a%)U)qoMw^dSTNt z;^Hb#*1k5g^D`*u^V7uIrzKSu%BmKmADQ?Y`b!(@}&`~3sWLP-Mp9IU#G6ySVm zi5Bbg@Ohc|B#^vl>Kmp^*%PX4EcAr2C@ZS$D;LOEu-nd<*l{)Z)NzM>$*KZO-8owL zM0daCT>O(I)P2A2m%EeJj$hTPygt?HIZ+{OA}3Z~S16c;Eqv$Lu*T8+n)BGuP^(I~ z7+$M(A$o%V^cG89@phc=xK^ghDLSRqNx?Z)e^{GU=v~C-LbqrOmctLS7T3D`4*9C` z(H{q7cY&v=OioV5eJMsQxnaOLQ@(NsQe(A5p=m|A^hsHq$&>abj?&1u6~x zv}oSM894kL7*(8sEMF%NjW!!3EzjW(u_YZR1}7kW_cj}>L;^EpY>;#dprOp&em{-E z{BFwl9ekK9LiPitdLU^L96{@2(y>%49^cMgJd|07JhZYmS!bNpd5D|ceW&<^^&wan zMT-#vFAP+5R6jmkll<95){Q=d${_ghHbC;{Z-Q?4p-pnVXUTnk$m8Y1w9Inzpa{=O zvbO~55AXgCMr3cx0je(eg1Gc-$b#qxY&MT%=p~8>>jR?duj=Sm)?ENHz1_B3YXqBLZ z%_+67#~(#i@9a6L-YRN7_n+(`4#}n#g);eVngjV8p)$3KJX=2}$W`^voSoXF(3$)k zC_r7gX$dt=`NG#r*49gboT@@Bm#9o+(xbwq43Z#-Zp)`^JjZD0K;pgG&Qk&Z*wl~V z$gPANd{x;=QP7NeQ9{};MMV}*MK4k3tjECiSY9^Yh({AeDJI|EH=g%-_frnlMzB4U zt<`EHmZ}M~ra|4xKk%M%A_eT&e(kI9N|l%NGZiW;GvruAB?Dn1roN%27J+Z< zXc=E$wW)`AJ%1|&MZA+|!+{1Yuq3mTiUd;1AHBshwuz-gg|1Lx**H{VHQo>*HzpT; zI%*&Oa5QS(k7xc@Iu2>yAs6GSSX$ZNni~p^N4OG@54n#_$a(e}Q1<_Jn3DHaZ!4A( z2WsSwWitT|C3dmw$IDGYb6FEC>B1qiImHty3hUFnr7U@&0Ytu^fxi9`M#|p4W+m-- z6%!vOFl@%VKO6;rRrWRjm9%5onW0Fnq6~dFN_1BCp8G5PHWrwxm$J7xH`K5eqfv|Y z)6vn7+-o~-=*s&jgtxiZ+k?v9U`J(dH6URjDRgBKz%VJ4d^R;N47HK456JDL>}@w~ z9g_31;@|~zNbdE}UoHuCejIgkVErsm!%~b!cb$+0mW15v>pDmt8`Llfuw(`;JcI-- zu&m`=i>~Kf|6RDl2nQU7mAz$1p@vNujiITZCW&m6;&ZQyhLpYG%}d&?h-}8eAq#TG zuo!9qXjU)~4OD9dCLlG>CE;AsF7$4Ey;apLbivdlfJzujUd1BeRU)FV6>+QV{j&=1 zF8A8ez#1`NVK^@L8cAB&I~&*+T$hq|cVKT&$ZSp!v24brLKpNHKOJ2q=Uh*jm52l( zGzvtKO%J_pock2A@Qd!lQ6mtHRd1@RkaO)sTOtCS%n9X#XG5#_kv%l`S`kPY38c&f zHtOO%bcGo>{GV8j%?7}{f8<Cph>!at+E{4LV&Oa@_9pzxi#QN>+N@ zAU*99BK~WvfRFDm3-a(C^V<7!8T@aw7jdc*V*T&tZRyleacH=ETc|AEQIU-p?=E}d zY|N~z9P9lu`f>xex7L%Pp>w5hze4qG&c_Xcq=OlYOlXOpQ*DTcQknH^ukIh* z_#oq7+IoNKXV$gCVwRi+RkE38XAB|xWI9El`G1A?>D&!SwuZBJ?)_Gnmi>FN#ieTu_)DAADJvSdKpY!h2%pI&1!d>U=dKCMbSy$d(zwplN-h7m)N1t#sh<3O$Msi8 z0uA+;Eo4c*GSn*?`Vrl5x+lZS#&~|?O0=)Cu_Mw_?g@*e@6>vu;F&}({B2JU-9;er zzkuVFsozXHy&t|{77lcI0=IjotE&GFHG$3}wf6ZoTg-bJ#Il1cF%495uvxqmNU~}_ z`18BB@l(6yigMR?(uY(hn^;8SN_n!yN%n^Vcl4I3>X$UX(-KyXxUpjVb8^H^2W@4d zuW(KNlO;qOqc@>J(RtF!Pt~W8ouZLLhs8cu2qI~ad7YM(@KZVcu+2azMtVAaSV@}c z1A1>lp1o?BTvrZ)`_PC&Wl{!p;V*s2y z0Pk0ff$N{$%oiRZc*>c@bQIpyVl45+_m>3no)@wCLh|ZAE~A8}}k?2vBfqLg;ej65)-s z(eT>dzM_~jLiI_(mNRO>O!`f7SA$?!+l7-d5W`ec4+#*eheP?@gOkG6h2tUfosLs6 zknRmjHx5d&5vnjvH_mC25o!ajF)D9@5vpKB4MLlXHk|!ij30Tw2_6}OU%x(c)rKz+ z|Bb`=J1@IH`8Uqr00}XfE~7}l_`Gkxx9)_Y#LdZ}#1Tf+U=SEhDyd4pp)585TIDyC z*oki_m1c~XT#}8LKHJvdv1(ubz$4a1GpOBVU=pmsTXI1dKq0n1`&Jl`10kS77}%nQ z+w|7HoQ?vzblPaZ*w?`S#+d%=)CLyT$Ojd^i3KLG9$0wFP4GmEh>`R$152)}pi32H z#+a#L&WOq5rTkwbCMeMNh^WDfaMeb0mC#0u!GYT}d7IRY&w4L|M!_2F0F*fRtc?bQ z8)u=&y^eI63Ph1J2CjEAu0oPCP6S%+z)dGsI9YT$*5E`O*5EN>)?l5NMJQ^cp#pvJ zw@Dwts7Zm5C~{PWQUUtR-Kr?l#!PrX(f7MGcuqi3#rLei`6%%+wZVm_EkM>zEIBH* zph8EDz(Pu3OU{8g`pON^P?kXXLq z*=eI~086Rl(?+WY!X$yE2%;u^WC14e6G1LF1Vye(FR;*2@q6LK8%;Q-Qr&8K7&tb@ckNh_1JhA~wiie~9Ws}N0 z8qix(a!xY1y4yWBD6rdmtjWWcZh8M(EL|u)q4er;VB~9o@D>YKy~SXDo2Z6lKf^$+ z;tAu|T;Hvq|M2KmdgNkOZB=kci3d<^e=(Z^PhI-i-gU>0S1S$46Z)AXjnPT+Z4`o# zrFB~R8R)7Qwl)#6NoxZVAirc~CyJe9C%@9oY>|QZZqVr}X(jwbolDOHm#LNH{B=CJ zipw)ZsTET@1{9v1uQ4^$N3@t?{0me`Vd)>gX0%z1*S_xWL5&H;CBzj-P32utnpBF&}i0#~qTVXw(q%m=N)Za!2ENbSpVVh@1+`l7+Lyr7Upc%f8+Lvvh$Q50*C%D$Zkw)3<MiEq~S5KHj9xl2R~dvqlF?3V;b z4NJhF&dv!KK<5qxEz;8T9v?97G&r_=LqCaeMfti?rd>yJTNRWP?LPpG& zJkLUt3lN_c=UadGu^X1hPX8q+*JrriXLj^gPiU}{L(|w%csyH@!a0Gjv}m-67;-Zl}_zL6e5( z_r~s^xwRiV*fvXl_M~UKA5E+bGI^5kt%oiq%2Twuupx&gHV<61rlV(xr#tt@ul|e1 z_NmgU&vyD@>iOvv?t*W<@kq%!Ne@})-C^q5I*6>=r@qvFaXp=6Zm+rULv=UXD){*3 zu8{$~nS5c9Lx9J}=eR?+yz_6|mdWrL>Ozv6{nfRE62ei~N~hNj^d!j5bbFA4x=Jpwu1h1ckF4%-H08djYRFy)mk=ay@h1JPlYmCA)`KZtE> zQsYb>hl;}74r}dF%5(gl#XpSUN=R+d35}%Q7qO?Py%_hf!h+?JHVR@7ZCP97oy4Te zrq%Wd{_2sHKYkq5Zib#QLGAy7+_VU4-7OAg#VBQ+vC1lb z@h_cC#cEL*BtzHj_cBMKb04ZAI>gey>t| zRlrnej=2pVYB!piN?T8>;8z| z!Lenb?cL*vAI=Ipze%5+@)lj9WYtMSjF{DY5VUe{fzM$2w2E#~{&4q6IVLfQ1~$s? zy=^O`>C-2m!&x#{q3$x|$9Xh|PFTw^8 zZ7;&^C5?smcick@73wYrejE%-!1@&!W_=OP{5bNKlhj?V1Z+5VFTx!VQ7^(15EU;1 zcnF3w@*;czacKE)|Mt;xJT0F1x1=iaUmX1c0`(Zu@vU5R(BCm?DOHjbRr;%MOy;UI z+MCk*2$7^Rl|~SnQbIdgz93hMAFW-IszPr-^m=bVikwtVQFW9~Q9z3Uw3l2|PA-j< zPCkLaql<1JmFXK$>)*E^ely@>c@p6tUOdVAD( z>i$ZC&oO1FkPRGk>i%T;Fj7nHH=sXhZ$L3kK*m4c2e^6z2fnJ4Q%hk34r{`nW7?0x zNEf%Moa{`cHnoMYA^AaMz&x#4o!YFVHg6TksryCTKF1I$gpqP+uc;q$b(P*Oz!jTR zqAK?F6A0ov%R4f!)cr0^F$+|q(pgh)OGPd=$w5?`koovuXRxI_>t|Jmssvjw}GhI_rOz{f@}BS+5q7`{Qln=?+#RNzqX^<304GcU?Age0kQ&4`RE>)cTQS%MXlbz( z`{aPlH2^l1wf1*u7?M8!T`!1z~K5FaoO|7XlVQbgQl+2VI(2L4yk z|4r@NooowM2AV&5mQLkAVVL#UhV*j`SWD~^45m=N**Op6>W@-BUy zyITzy3t@)sD8<9JHIHE{W$g3+Dh^YR%Bbh;hY1UK-(X!=j8YK$7zncJ|La6&d~>)Y z@c4EIv-|B4?z7dM-&KmjI(lT?%!aL~W`xsDIfF%KA@IJ=%n#IfCuR{{5i)*d5KmsZ z*X%SHL}>GNOiVPOb8S-Nr(;iS=jIx{{`<8Nu&5ThzK(k+$4Vut)(-i4wRvLceF59! z6-Z(~dT%iyJ)Hk)c3^Ah=ItU;>1<3{Zh>vX--=U`tunJKIjN0xshu-~qrM;Y z=3L&#Q?W$3wpC=D?HsSHT{pHmOIORoPF1K-GAdNpIUrxP+>&gj%Tc0~O<(iibd@<~ z$#6!cnc20GwQ&W~-uA=3O4nbF0ChO<<@n-{Z0dM67^-oP~WqpU+@=--Tl_e}*&2)!{4`0Drc}?10@^4k&qp(@pY3NFT zP%Hb%x3V#Q(l_i~fL3QcfqfADal^==DMDtxQg4;L@I1xX@#*+|qv?m%e~BQaqXahQ zl|41}o;Je>rN_m=q4 zV|@GEn_EjnntXc2_=?qi@1F!bO-*tacub?GSg5s*$R1j84lB#3x^NTX(h)zF%-Q-_ zbsD&utFF+$69C=BVh=>{aUD{Rd;<0`rX^w#b8LPb=y0` zf>VUaAwn>wL8oSU(x@4KfC+# z_&q_{*hCYQ{cej%+L_l+)yRN~>8p^~e2cbpjCL1;7F0zo&`wr%(wuL`JT*S;mzDy{ zpmNsuh$^@yR;8$LTmwA9#k5C5Up`IPsP&vyuJf1>)z)RzwTdT;xII9sm)JU=mpEYlpzT&!zLrAAhpLlBAk1SSOV zZ*oG9GAH+jgdDS-1VMP?0W~&c<>~N2)#Y33m}YL3m}XAZPPy`&1C#QcnnsDO%(vDU zz>LgnwR=>Qmpcdk*4l)kJO}T=d+COM8dXgZYw5ELJn&#BIdFQte~*RjT8ZlM=LQAa z)!pp{ChtcB$olF z0IVRG8G1#Gxc?qln4iJ7R!v}nsJqCN_;CC8e3$TXvael5$e&&nnB-vRhyh>3T=~%; zR^xwX_ynw@lo?nsaF&xm>jA898JHr;OE}X0J>~st>B4WV9Wj2dRKMm_p?myyhF7pFfL6nAegSBJ^(d!`3v4|T)cOY) z!rmvoNYwmLVhapl=2kJ3@50}Lt0H1Hhd*q?u-^KBVVDuA!tC^(m(E|+OzEE|@5hVl zPdM)V;h*5kE>~%w{*6Dg-SV-2!WPW8+daRCUBkYFMNSA1%P&|`iF#qJ8k&yp?O!#p zU18#QE8gsHOwB5|_8rMIUXgJnH)g`K@BIqg4*%ubG1+OCTDa9>n9$+$DEV0C5_@@7 zsML%6@Eu*Uvx|Z>;r7OF{RGbK%yT-@jd$QAPeWee31GfM3*~$`PY|LXYiT%&v9hc{!b+{^z zo7c}^o%SmF*Wo-c|N6IjhB=dBHlX_lg2@{(v5~>zifF?Ce<-~y2NL@F0HQG!X$vFk zcN)T?DQDkJxZ2Zb{Q}wXD@bJDM?t49?VpnD#OQMa!KUlPEgr1;G=y=%wwu&-j?wzk z1XYm8!EQdM5A)LO%r8DqmiEP$A5Fuvd%+F4fzK!ZKERx78?akmi^DXqF8xE{?qN8{ z_noS*pT-kDz$}?^V09Sxzy}r2vGE^Z56n5RF7DmVWVriPO{Axjo}lNOKU1QcNN`UM zJ>QNGgtJyz*2Hfp&M^BlD;ysQPsO~3e)fiU68?EyxS&9Sfp7i&{4~b>g=HW89sTF` zZotjoVa@%mW^%R~qt%uMt%m_^mTp2Uj*H-*8<}~^=3dQr1I*Zmo#XJPl$!PTH1k6B zc_xyqhyx&Q!~r54MCtQZ@`n+gsgJfXjdF#KK5L)XXGrhUv0O0Cp^3E-3OM$_iQaI_3s}M1wl+hL5f(JJQ^`li5n_g z9*?DDu`nBqM~8F1vK7BYz3PIL9o#>#yKDdaaewtA*mbA@EGz%VKfk#H*!ZJZHn<9Q zjH|o_6OnzoSxa{mTd!q(VW4C2xsYhQ0tm>b<5m54aAnwZsyu;;~4degZwQVIeZ&PWJJf(%$#r>vU0|SzKnR z95Ju%w6%Sn3AMO^rZ*An2l#ZI)I}c&Xx>DP(kcpIXBhTK-n@U>c~DTVHdHbG;n#AG z7C1Jy@emH#ab&N8lfeh^xX<57_EY9d<9h#_-<)mtt@j<$)F z`xu^mZYfCT#JHHg{&VJvg@Zl$O~Q7-!7zXFM+YgAj{&f+wIIyat(~O{4SoX$7CUz0 z9tup=;QZujlwbvPXt#pz-G)2a_q>~nJKX-&Hw^>)kCnl5GbgrbcZ*Go>x#aHOhjw! z2|jm3;QgO!YzDqEE#57k8NEeRte+EEe-`@{HYkgzcR8d_IsM_x)mR>twUu*iyed`k zNguO>@*@kJWjgGXd;qE4u`^(y8nA1swQd<`{bFz$s-~V%IzgyaWG@PHH7E{q)qQwd z=ra&{@+tEzG~}l?G~~-&31$bH%_qIrjj!7UFXd|?8NhXtaQKb69I*>)lsWvH7bTbu zC?%Nof4M|{lwewrH&US~;(*FaFpuGEdMtMlsV!5YH(Bc!#K(ATK2gthQ(BTXuCr7G z=jP3YX8A%xi~%}g8*;TB7E z0fQR>J9b%u7$jd4L9Z65^54sXMn|;<$H%Jr+}$VY_1?1^4BdikM_Vhho*OL=X;}f0%Yh`EYec^O_pL3m|W3oH5nKt45+wIed&_i(C>4(`jmD-s0 zg41vA=Y6`=TSthS9LpwltU?;Ag_Vw)J)`*aGxDze$IYTqy!ALcNiE+|x~L$>VDVx6 zODl!6i(o8Ca@?3A7`PZo?&cL1wVO}*9 z63}U43FxOgG3qjoyHoFyUvPY!)*?1WDIvsG>MHP0m?hr^OMExKe86Po%R$O&$U~Au zFZnix1pQ6@n(tHu-X@1asK_1HW)0;vALncU@or3qwv&4<(lL%QJhrw9yqx-OzAoTR z2#JXMg~fL&R6xCX{0Z}O#D|lQ(BHyPQ73^sBw1;R0fTVjTRPRZPVRM(rCe4_Dt9K5 z!ORHt-tZ@1ul_pq?@NuW_*CxfauNf}!+;wyk1~}z7tqTb0eS-UfWzdA10N7I`jVy| zvb0_@_^YyHusVm}$FIyn>dhD_g{qo7`Z+1)kH>yV5phJnRo`->YcqeefCCcQ8ENFB zs#3jY`RjpP`X-ai4jP9xsnadVt(MY3TOV9VZT6=|{rd=UQpA9C@a~~;X;_$g*cf$E z#CIzEy!vopT#_qO)&d_$HDY2VX+cQBK@AKj@Z~m@nyH z#;;pV?EJ~svLQiFH>}715+Oj^xwxQx`HbHazEK{nYo^pwDWTYOVjCl{)I>)F{IPDu zMl>;_eQy3O7phX9SXFA??p+9}J-nK$9PQM#b5Rnpwa>k7LiOvfWV4j#Ybx{pyD-_* zv&**~ur4t2nLEAXvF-f1GDX1;xH&Kd#$>Z_X#{PcvMQp1*+O{_ixgouCDz$J4>Xpq z`Hs>s`Pfzh(qb$aC82O&^I3s~GpER!-@~u5 zqQp8ns>HflPi2~bL}hwRS7q93QF%HB=ob;I{6F&EGAzm`{1+ENN(lv|8%0D!KtMVr z1q7r8q?J@cnx&MGZbU$&yF(CGl$H`H30Jzi7Fc%9;P?Fg*LAMz|LVLwFLpjN_sku0 z&olSVKF`dvzetTVgI?2U29eVEu`izWq~KwEwgK}z{JQtU zSKlU53xAjPK+tU8MF$PMn@O1F&qAJpkRJ$N46bkSE=p?o$j_gOdXv! zFB#dj?bnSk42~KW+t8;4X*d*rPh)p*L#vL8+C|ec9ypb_)k@TPDc+^~U~lJeAiTkM zUw^MQ7U5o+HM1Ta8J*w9Cmy?ms*E4_g&UPgoJHzf%V%_3tmDE{3!wWo4R&z z^fZoi@z}UHf6ge-=I1NBQ`NXZ)}zaIoq@tn%6oH1)qhjyZ0#qPzV);o;WQCM zs~_r|$(r(`$!v4*J=*9l`Z^V-GiLDNeU@OwOLwwac0TgXT1$?4>)6>s(P%Vj=xzU- zLp*o5PVx+U8pyX3S8LN@V_P2TRMKpL(g|vos(g!w{P=cC`~~5GAxH4_^?Si061>4y z<@fiwnC|Wyf9adpdRas#>F~K0bY$7KZR?dRUYZ`knVu`f)t(xWaWot4x}_d@XYE-e z@q=82bV1rXn^b{Tdfsxb$I52QJzj6k9*PCe(CU#4ES6C!v@OyrSodFR+vXlkG59f} zX@W9T>_mR*5H%=$m9=C0bZ2tZBl@18pHr1!YgW+v3ZWj+!!Ploj;)s8(U`+;!3nKz z!$!Si&7ar=-CruY$5m0t%Ef1zvhFh$!?05r^Ymxi`)m89@3r=W1V`G7@)nt@^Af+5 zN@ji@ISG_7NKa~MJ26*JcrR)G*6rjIOReESXVFN(@xULuk=JNkl!&7ZkyT~d~-*z^m&zE`(*Qb83jV7!dGRRB5jUf{_zV{RN*O@|7hHuacr+BjFi-Qlq zy-ef}_~_)ag|xOCl4w5r<2Pz2UYt+V+!j#R)7;klk+4g=?bmd6q(|c^?O(Fg`1SmF zPh~|>;T5GNPR136T=w*Q*BqC`DA$&%*j@vCe9J!&jSnx!AFC>ghQL;Qj4My`*wY7K ztM^f^Cck3)9YlwY)f7cLVWkMH%x6#Ef|VIju76;qFRUC;2*k1Hcp$A9e#te*<7)zW zD_&kO;oW;T5bWz0;~~2f6y~;#q{SXyBUD(Ed~+ z(Ab^>-Cl#+dQa#YgGCurE5Fb+aSJHnK9unEJR<}%KIfSSF!SL&BMLKL&NJdLGi9+C z@{F0D2+OAz{fvd4h?E~9D?JetzkBpEHkTv9yWgfKTcfxnhhoh+7`fCT++gG~fpC+N z%Mk)6BbOh9Tl7Rx5V+`xG9cWhCn|%$&B)aP;SM8LKLj2|u0Ig&GIDJ~;AP~(LbwN2 z{)#o{gBl_5(-Yl=Ai&5a3E@7}2SE_(6X3j%VmzlO6>2s@C??t;cPtTbxWU-OLoKs@3=EyqyzFXVm||+<|K0 zg}uaK-Awn_#ttFh^|y8X?F!L{X(UWkZuS{b??^HpCOd5K=F*GKZ`Qiq@fcW5Oto4| zkmy@YmmITB5&pJH0m6Q|SN&Y2E}}UjsI9{H;Go4lv(*<9lcx)sGNcRaC!lLekg#4p z$$eKjSy}ydQx{b_1e`fO{!fwi@|lvTK# zR<2o>R`&8C{r3+hg27fc^rw{3f-w9IjBaf|vP0Ln)xoVA)e2WKZ3K9iEf@!V!yTTf zD6X;8v(|MLoQ!r=-K{IQFiqzs)bsqsjAg|-F~35xslXNE6|V6JW1X42 zee5gCMV}xV6We#Gwf&+!#e+hkei?$JTw~X%Mce80N+xC{-s;aCwOFdYTsBwJr?;c` zZb@~U3Z(7WIhJ`##FZUMQCjx4t$;lHetz#guEFmq3Hp{PQw>pkBHyf)%AQ-O65X!J z`|z?Nw{hN3+l6;xNae}eUaGe}@3?7|x~i$2Hy`IH41iG%C!cIe5RzE%lgm(kwznqq z(e)QsSu@uv%eU9v*mWO2)t7nEZz61U*_yNw`S>OmTXWZ%N$b(OFfKHT1Ixor0kYVo zF+qFW6bOL{L^mGZPNpUPPW1giG#P&ont)CQgWJo3#dTo8KF7_Ypln0&GPfc5@Ghj5 zuwZYHU$7hsL^Ib0pqaY~c90f$JE%CaSwtJ*tdnpM+KDd^?IaY027QFH$nh()QqzR9 znT}96q`$K!2h>n#GZaqF;kp}yPJ<;sU2=peeJHY;stp-S(gsM)eJ@^N!74&s84BcJ z@=68QV}JA{2@7_-JTwrWp6I1NnpdI3G+4-%n2iPN4Ml7j$Y84NS+Kt#j|(ibL(HU+ z!9<205DogH>#G9MoRt>DqAb{k7D^v!%qw3m!T@v=Y%xIhuXHN_4a3~ai#weMxh$7v zqt{ehiQ9k+eJHReym0X;3$~c$0-=8Z8cB>J?SG{WQG(Nk$Rue)+=RA5y#uVHoEHdY zQJuuIQtkM&sGktq@Mle#FZy3#4n>mUNMDG#>US}a1uFx4WCyKc2}ExR`=gU-q2aJ+ z4s1Mc5O9L<6xOq~)p_-q~ zY)Uci(-_%0w2mNZ8u|vPYdlj--|z?-;;QltnidY_rOxYFsNRb)-D({PSuXEZ*exE4 z#Ww2ShxdP;p~w6j>byV9nR;N4qS8`6PzqpU`@q-!bkK?^9|F z_fN+sio*FW%uDJcW7peWW?Cw&8T@V*vGWr4ot}-|&EL7sHA#o#rN&eT?I1X zmFi8wg%5@cLwVLq3u;UEU#RxcO(jiF<_-*en5(mX^^=K0B&Js4$pk!ebOn5hGP$>K(|ypx zKAa@^hDDmv7Rtx#D@2k542U)k0o3r!}Xt;o`kx zOW7RP+sz?9qIVvP3VeFw^IFOM?CEp&O&=Tgv%nBB_e!FCQ#PB8p$+Z-^T-kM0hjTQ zAxqzG(v_1B8@rJ!+_`CC-1A24Hp(c)-UKJ9be8EIKlQsWj>55WL6XidHawbZI5L{N zSs(FMhrBx46`dvD^qD#*66sw`-}+9TMfmuuKz{<}4XSLDkI z>)4D`;%bSpdd{Snma#*|)2&b)_bRp6H7744r;0@fwx4kaZ>!_O?!Oz#R0?H_yQAbz zdYMhDSI22~MTJA(rtrlEKU?#Al``R{^VXbODvqbB3yYIcs+()X3)fYVF~JG=@>)EJ zh9oWOIm5bV-ToKZvXYh^(uK)a?#scmti0Z$QKJ&?sum8DW%o%x?=3`K%H}BVEp*Ob zf7UG~VJOsV$9>$EPtNtkX!mmMODrz0G7gjRXK9pEPCu#R)5q19y#_x!m;IP7KPYPw zWP2q!+GLa1Em8L+7d{13@;mWW7QQ(#pF!)S(#)3B-E2XT`)uoq2#1G1rSqNuo59WH ztV>(h3a@2_SRti3!lVDV@5p{e&0w|AHTORQg&;~kpA>tO?S}gwy~#ZPCKwH|)L(a= z|NC9b(m+t;Hj84o=vu$Q)cN_OC+7D5&L`!x|2v<=#+C8!e3F*=|IPU%M@$Q`udE7z zqxq<^1Yb{>l0V}~j=x>-N%=6R*cN93A}Qmk$(?+>(ipAq!|uYn0=dIeZqA0?E<<~% zd-K%mzBw;ewCAZ^L{(PU-*)|?9!d7oCfl_j+kB(7$NME?Z6c_~(5Y(3_AFMV_~0h@ z#ykgHqc16-MN3i5L6xsf2#=T5Y(1P@7S7a*Bq;Cl^Y7|^CgvZ~?C^7xQet60u!@Pb zSWlU~F*y+V?B?VE58j%*=6W0HAH@gjf14kFBmH9pGw@&SKFq=uUtZPO6k*wUQg@!T zoF^SHsj75kZ8xmTq;EAkPoAD9#^;GiT>?j|>3Q<(JTV(RQ>jRCL&A+E?5&n{!5pnt zLf7oARh8ks5|~6-pEg|maGsQ$CtuE!UTak~xU~c(>*opPJh@^66NdBT&Uqqk!`|vz z*T&K628G#JM*sD;DlQ>Cb*EhWtrd^ARXIG*N~)^1IRY~_3`y^MhhU~j-#Km==Z@fK znGUV^csH1N3^U=uxi^1V-VsdYFe~gf<4<}Ykx(&gNk*%xhOeS;TXjh+&ka{q?X`_m z^eEXK!Il1~7mTecdkkWE2Y9L)8M77p^XiPM8k_SK(UZzV+HV-%WzW~L^DvZN$X)U3N~cSvxh=|pFO;5)miiU zTliE_HbItu5Y=b-5US4sK~y4gie%sXXm#hGGwNE_UE$`3bP?0HR3a*YR3bWWsc7%C zhDRisJ*-Q7_Au{d1)H5}1>0{S!xGZ(;p;tF1T*wRx;gaF%c+q$LfHf}cJQ3-{gSTe z-+ZMb6>KQ;&Km3Q;R&w#u|iNq+O?7{EB=x$c_LlQw^z8G{qeYW1xR)0@fdaIn;1&E z2q9i(C{bdDC`+qriGc0iU*R5NX$@z%`90j{X&}|_AVzJb3*6@e>vKWZQV_O^!s8xF zmm~Wo!>G#o`_e4v&bfEAVh#OG(eIng?Vra}gh>svU8AKOI zzYdL)glG#f3T`(c(T_D-U()=8!(D|dmWRRB<$&8hSbM{-z?~sJcoKxCBKon_<9rJ@ zE7+0$m zm1eRd^QMF6&RB7uXyGOAd?nV_=JuGh;)BQKv4+oE?YvU7HF)lLfBBQ&P&?|rV_%3e z%chZZ_%MvH;N~;;Xs|SSEXOc7ZAABA;lqQj(kx1m2O1GyytTuL(T^iUC#CBfwnp!W zm9PC=D6Y-oCf+xDSpMR>fY9>5V$_&I+udPB>%+0O?E|gel2^00$}bHqqhIoka_NL$ zKDa&?9s-|1k+h?mr*nf1h1-K`H;2YuLfT$kZd{!^G9J5`)38EOOFASZJiMVb&4@l9fQB!eKrqXsvR()|pu6;?sG}ffTojO0aQ#C=;8POvq(1N^SViZQ6Gotp`-WUQas)AW8&xJsTV)W70U#5J-NW>MRGs% z5z%1Qj_C4ZI}+FDb$FtdlrkY5${*!QoOkX8Tu$UDIL@`jL&FzH-MCc3hIuP4rzo6cCIbQG!cqY z-V7i;v&wHdKh&T!vRZ{`#Dwf38*)(PXM1CN%qY`EDM|PUQ$huM^p`YRuYuqQVZ3mc z=eLi+6C3BDp`*j_AG7MpKTKN+;DLs)8vehyuSPzWACP^pc~^WUIjWajJ}l`o%X9Yq zlfi_d@Qt&%DLe;9+;XJZyyLK6!0R`< z5tX2=N-ZoX#^xaEEiJBy?1r#N0z) zMfvbLf!8@LKPEqIkY?WW{r#~xX-QDFhntqoZ^JU7rOy58(U&6Ci2QK(+CVOw{h*Gy ziLBP9gYVy{C){z0-Nfpjh|OZ&`^kG7h{3akuD#dusjl}WMU{Ih-|1oGOiy9twoRQG z>JGMP(_Z;Av{LbUHuWk=Znd1~i+^Ve(>*r=6>;JF%jhR^4aW{t>&a}B2dI|yNS%hm z-JJ%@{WMujeu%QHs0xLSEtMoYJ~F-a=h0J^X}Z*#e$27Ar~SNAJUYD#o(wq_9m)l5 zYQ5NaURu-k3GQ50zga`zqijSqO5RmqIn z_VS}Hv8CY;`Qof3@Hk@+d`j8ZQhC_cj`bBstF`1t_pb9Z2WED8aWEQa1ime?`50A_ zU;ehF(^PSEE|+zUmW6d~g`I6}CqCxDl`{6=fohl6YPCi9=PobTs|EvCEhX^~1|4$u zXbc9tVA)-?D#M4wVBjXB!9f0cin+iKFG5N7HP5S);a5K>j0#+X_ywYx?C38lm|ur^ zdHGR`;Boc`q_O#`iSkUXuAyH9MCJdyB4Kl?CyhONgCARO7}8}_Bs1TPU#WPHnQaS~ zh>cf0s4I;Jk~n1NBjZ_i%^!w-c}c{!MSGQPz$mcGj#GACFaer86m#IQ(&gnrVxWNw zzozji0&*N#)yOHqAwGvH)fn{l<2*n@`VLo}eP%1DP| zK10;$@=)54AFY;?9Tm`*gM$ryZXh=*pej2`!Ns){xW=5 z!ubelyT!J)@{xV5n=1Bz<$JaujR6_IxZ%6lgY~i4154X3ub7#i6A>i@v`nQx{}l`) z{}q1gEGi^^)@(QMORvV{Pf>mXYJA!j*RC}v<^d8MNlD~WkXr;!HR1a=>OZ<#?v6zE#=S{I03 zs$GdZn{%PQ>1>hKOV-T2i9+1y5see%qApcx{>@LjKPHEAkN(m_E3HqS9Rz-xQb&hj zbQ~V>gDpj*Nl=$O4fRpy00Q{;Bga8&vb5|72Dr>4x6Z1uTLdmBRCe@9C+27f8;6)s zR68BV8lB|K7@b8Q@qpXqr_^3Pw%F5%jreke1of$>dwLr!y=<%}{zey1auNSBXufiSeY=8) zItmZhnEV^-x5-RXw(i1?zY=tNvMe#}cag+!PL_R~I)ms?_ufF@k4%DiSFJNd>!cG= z|8h<-aeq-@b5f;jNa7zok$;t(1Sb zyzxB~;d24en$3=wdCQFG&XPo|_zNJ8KlGda+r;bZj}$#3MDVN?ebSitW||paK9$m< z_Bj<@=xjIdyl@)op77r;UUf~Cf4g{}X{y-SZ0FwKz3k2#G4o^n)wgDG3eyaV+fPay z2VCBXzp*VJoh!~CrD94ORxi9dmo>`pw_teHK+)~qQ%#0H>!qVJNS)P^GufBJr7Ffe zs-^ChyjzxO#qf1p?ZWzdVPBDA$xaW9t}J(4wZ*L7g}a|nj@&Cx zo}~bFf5ncK+j;LBY%@PmCE5J z{$jtnj4o6u`Nc1I_r75mcmLx#iAJs+@6G}u(!Rvt+M90cpNXxe0w0+9w9rej-guId zqSMc*;7L5h5SdA-ucxFk)vxjT?)5l!-R*8Fx8Veqv^XtS12s2;yqv{NonI>a2}=Ui z!_?~*2`^S$MyOpLshos%ukJtGNJKiCYCdeAs!MP`Q_JdKU`XA)`)`k$Xn1e1St`*S zKShU?-}v3-zQo3lb`29T4^yAqK`xcByt6H5d)Ju#k>tBh>4%54RzEg0Yo3`Wv*1_d zF%nnZe4{v8qa`!CUl~~PA}O$Bh3Aric3@zMvQ~`XfliDd$&(mC&&pV~D^+=taEot_ z%;@k{b{PgswFACu^D?73)v;{kRe8AfIZDALE4NQuC}U#;7r2)jr}I9p9co|t{mc21 zasAe<yXhm|N{XlSAn9T&)ulxlC#uEPdg7`gUc3|nU06;c-h0MN zw)d=zc#q{>i05|Lg}rBY$@ZkLK4W^cXvV}rbdL;w?;aW3r4)j6&lG}yi@iZI@VDiD zuqXM)uj1SA?gSf`02$%?Z{lc~0MEytzKK7``zpT7@>P7iCyJ{F7JI&ne`V^Rd}YS; zjLahZ%RRD+5Wa`cQV7N=-m~%b2D#nt4RXD-h;w)^uj|U*1#cSd;J2Rs5)oWl-^G=z zJ1Hy8nB<`mcW?d2_);jN6H4p;Pug;?I7` zytpT=W5)F8@iQh$!h2*Ub7oBTBWo?RCvgLH}J6?+tRsS!~5;S`4`PRb0R8 zyZHFsui{Ej3ngS*G>XzKQEY954PR z-UWG|wG0sx>|KB?qA3LNIw=I8m}(%_N2Cjb+_;O$0bfo!)y}Gy!3EUUet7_{&eo^^ zvhdUxw6`NTE*?V(f7}~5Kq91dz*6=wAZyWCs^Io=C<05PUyPdQj(bGw&PKc9n8#-G zmBgMuo|p5LQZeB??6R0E_cc}A?e5I)L7!v;QbA&iN*b|2PF);)t zz%Ptq?$@k&oI-B98pgN`NNs`RhX7%NDmp+h-M~tX2VfS@#?&bR>gYjVGh+J^-&Xa@ zowPmQ<7T_}w@`Q2`nJ3$GY1fbBuJ@3KE$>!e_~rE;mx zy)m8eag_;N~5j543NVnUPIR?i^$-f4t4&S_dA z7*S=xg6ilCaxxltb5!u#Xb1hr^o4s}wZS(`{xCCsF3%b;cXZ9#>Ecj^RUYc1|sm zeD8*QN0f3qlgfIu1-x%-Ah+^pI%{;jtX*fkCA76y7$+mh99>L^R(zuod5d}~&(|n? zmPcHC#w{k%6;69-$^7I!Ul85QjbmTbGr=Wh<$ddxYQP0suE$D8RUv(K(yY<}frRCQ zTEw}&HM#z}9#Mp|4|XZ>^a#ryWM7l72sMAK$?%Z7Ac#=#Z`T9Dla~)~Z6I1)hy&5l zT3nInA?21F_4nJG$1SJRE(6U+sYq_QKYqWJzU+}&Eo&D?ni&{`uSFR}%vd-ID_G{y zvRm*+=CHo%DBupE%N7fv$ws`S=~gS(i34t_e1}b>Jq?j4x-nn!f(UnE-7>^x1-}_q zxTno(>(*);Swcb@DQ*0Tc=@9itOI*(pRbBxxlII@n-I-P=@s^~J*tl3coBt;!_OTx zzRDf@f@8F)72A zDvq$P`+D<(XcfV5#c#UX4@Ms|EeK1UWpL(u>h%RUf25zboTqsy84*z3eY{)rh$ZE_ z()x@sNvMo;1tH;0oYtF?dBHU8oeAW{{?D#2X@nVn$mDqY$}dj8<5=08ZizF@0TMdS z37yB?^A{8qS;P;bCklS@X#?TS79XDC}k=%&I7`rRn3ZLH!q{+Gyhg|E} z3i_smExUnyJM{8T)G$6_`^*={LQ-}vvZW0rUmE2AsP1+fRL2I@(Y?Y(QHJfg=cs%@ zvRln!7z-(&MOo)f+F_I1o0>|c9+t}C?Ve&gj-7!cg$H^CnTSi7RYUd)|Zzsz305ED1%N@Woxcm=y?XZp=fKtdRLC^hi+` zWLAL8qR_{ba3FHxV3XYQCO2RcKIp=tZv4Q6_`TOT84)=jKh(2RS#jKegH*@`>ow0s z^gt21P(o;p+sv`)?`GFO;EoG^qr)@#I$6sVzgOk5sC$CmLM$M@ z_3wb0*q=X>z)?JApfK2z#FI`1G=w*ES8&2z9z{o(6`_0Oaq&`AJs^fn-sm{<-3azo zn6ge0Kt2X5p%E3ozt6&3V^!8Rk1}j)5jW})oFRx>g#M$N5iE7}*>}tj@bIy_*|C(= z9>U5>zl>s)u=sD&U+~S#DBi=b8=J||1q1n z4$h)Mq7n#?1Uz6X1OtXcVtqU=q2BBuJe=NPp-e)=9C87i#lSa32XtROm&yEdvIw=U zh*dnH1=;_&5Z^D~RMg!z{)@2OQhEpcy1*^SRf`=UJ4SZn-c-~%uX?g|>tEG##2lib z9RcQm)YLO)*Gs5NSjD5LIyBTCy(5e@T0)+(g34Wv;j7xM?g4!g#m`crqKDv~t(!i~Ypy^=KdIts2%&RtQQr}keMo*&O zjbnA1u)XY`3mBe%NRxAM0-JM9?_7wgL)5kVRq>Z=Q4M}Jm5J!chxp@6}(jD5sCyU44UWe_@A2n|EVdVcobCv zl_7RP(%F$5R`J|V7-_k+JEAujZFw#n$YI_01hAd@Yv;b&yK?Wd z(RtV0*Zx&XVfAdk=+0xxU#?;5-;H4teNqRIXW4AuEJ_ZM`WsS3NMt&onF+-KoqatY ztPVgT3aflpdI$vS5xNSJXLDNoXZaxdii`dRqH+RR#p`kj&3u)@q879_d{(&G-iZI? z1z=Vt0ed@$6hUnH&<>(+SIqG!K}t_ol4;AN_H*Hk$@tIa6D)H?{q_2nTlS!|PGEs< z0bOad&MBGsDPdi`I&+GtJmGrB?;oSCPwbE0j^jEOmp@6<9x(B>CdgJ$sc2fqyeCFqv_){{il$Vc^!ZDR1Qw8m*R_pP$+^wurdZoXp^UH=0=qN7~&6$C_xAR)I z%5ELY>G+UwPlKZB#u$~;;||{K-{q((+0>YmaNpUU&*AU&*VPSNqxrao*D^jxPAWNU zSBUXAmc+ic3=orO2#Ia62p7wK&CNcy;&D_HWYw|1@Zzxd6N{CC-v_wOyf98ew5^P1 zhf5%P?YB#nsit!pQ{@tg_mgh!;L z!G8)l&HLtI@hAA{5yo4L4yW#dQSEBo1?0&L&t=a!E%E$LQH;K+AK7P)-!-2*2B#BU zZ~uHqwj`Iw-x%;%I)<3g97pCZ3n4yUH%-`c=@=5iZ#XidETIIJyEFI~XB9Z+os{J9 z0wbi!uMukPQr|GYD5K6o*rUX8DX<_yUYCXNGTw^-mb>Khmjb^^$IuY6;mTOE5R%{( z2CxW`&*KOFm5yN`{Ddp>nuTycDTg2sEgi#5h;u;}&!7AvOWOrPnG3R%{^a;9Z8(Gh z7i2m7$%z%NU1q@xij~JDoVg$??oUq6B9BMNiX;1|VSq&jNA`(7`E{1ION0S9vX=hj zbS!Q7gso;AKXGI|{K=VF@CXU7UX%^>Cue8DBO=tiD4XI>&dGvDOc-lktt8v7WPU05 z8DHFU9M-219469)G~{gf!7(_j*3yJ@|wm*7kic1 zt^||gvUW%l@{@nM5_}Jrwg0QC`bXR!8;(nDp?7DD8PX}fe`^eOI~LedOnAW0b@M0L z+4=Vz^BKb3Vq|fm(c3Jh@&pT3op{QeLV=UDn4f);^X#6bQTHZaPxr>OL++dDgepN9 zO9{i=k=N6Z2$$Ym`>UI9>d5+In|h(@^9xHVt;Cxab6spti=Y1F2`-T#$TesR@Y-t( zPh-R?oX?P{pqOBz#G+>6$=CNi7CM8!}pAF}n+!q)wXxe->{_?2(&WLR{;Wvtf9&W`n}7jC3U8uO>S zM-@Mp0*;4AS}gXBxBdS(rF1T5dc{kAT$}FribHV_fU?(~mAzcR?JKMN{9ZugV0+I; zcJ)r@qyxuQG{5SBgMX;ruiTC*x6r0PU zu_e`UQzzQ17wK~~nF7J7ME!lhiPVv5DiZolWo$HwH z_GUw6=FMhjwp^WazBM+p{YsNOk)I)7rL$@3F*uoaL`1rD@gKt$i>}vIA<} zc7V)VGyto!V2$496j%%GfNIJe&<)W7;4wGWq$*2tc|(u{3|I!-e0iCu~7DOa3g2f0sLh_+o1qxT?I&J|2dKEACV;tB)?(|R>mMB)>t0T zg01T)4cQx5L>k)f+MOMs5xT`Wa}6N%uY#=_XiqOWkTRhL$S!h#GNJ~VW}%>d4R(=! z78I|*F1H`W4~79Jj+RV34Gh9&=ZwQ=7SKay)cGMqf4ptrjOY`_ml{oa#ztG)Y5Ss?7uJLtu^dt_i|8-)jf4; z^)g;CDBb)O9h0t~H?qewvWA%FqxY~`ArYQ-5c1k}tRnHWo@@8Cq*h2vwu!izMs6ph z7J9>b@Y@&uoJ+q0X-YlQuT|mp)m}Fh{$;c&m367v{i#!}Tjr?Ov`KT{YO$=}*R=BJ>knh+Sb^U7cqv<_Xp4$y#Za*Tj;kJYP>;>?=|aNn==9Xebc z>H3zoeob;!AtaS(%_(P7pqByjm)N%}M6R|i@bk%FB&owVdd+og_eaf)g!c-&wQq6c z729mi$dkvaw}}Q76{&2qrR>zE|DIa!3b`Wa`(8yeeRSM1alr(R6*M)qeuz1F;N~)? zCb&Z-VfFK=gVu8P$^8CW%`pDugPH~t!-?2JFRz#MJieVQ64|f)lXhHfd?#8pYFB-SSqC-)^*qpqiV<|^)E#uaNZv+f5Xeb;SW z>PmhsF{KqvS2!2?&27pUwtg`q*hEytn00aQxzEm#m)QY53Bx-cM>17|Rt`=IW>XvEMF^k0ZNg36@Y%UNZiocrzIM+0df z$G>=W^IyD@4g;nvEt$b87_bN9LPZ-ual)c121LTJYnF!wRM0S4J1#)&oU!pETmh_A4@i8cnF7K@g`Wo@k9L6MhH*|G^UuO3Y8d1;Rp1@0DVo^qI*?MJ28b{s*Jq!nYcXKu zq&!v`p5y%qjMe~V5Y&(AHgCUKHF^F^7loAbT@%u_0Oc9mj8aMV8R#z|<(BU5d-I37 zEkoZ}s@KE#GaVil(pEf2mQUDc8W?ly*cEWrzQ3Dk_~STCcXB7(@YJcVwy`JMb~-;f zHDFP;He*Y-6st&fO6T#b_HEjAG@XR!yTU2q_A!rF?>&D{d7u_(Us=ajGWx1f$o6tK zjvN`&Y7N+r-j#PSSqlCA$xx!UeJsH6$C={r$0Jg^(z=%7I+LTQQR@TIkqjq+$vT}EAA-&p|ubM3}vz;|jA?7~mb$5nDw^X#` z^sJv7k17@$FOiHgsHPQ~t*lsk^uH2hyW1MUP^lM5ylJTr;-qO|D}2wwXmh8X3DdLw zdiJ5|(HKg=+vm&Bn9D}8VR>I;`B5BO=>TrLPyf12ZOi4w;OR?#Q728JC)Enp&TC`7-Q|pe@J9Jgq_=Cbr}554%g$w? zlrg97eKjRxGxet;!}&KQ^Klz2c%n_;`*UcvvFL?j$BUKL$dP?UiP{K5 zQ~|9<{b(K|MmoLaOH=CcrY0%^!y;g}ao6;)Kug=Gs#RE^$7a#8e0xF2x4oBMXe?Rp zBrJ)!>1iMDpQ64OLW=3t3s)UBD_^aWa664SPEBj`q$HP3KN&Yn7iN`7LzJr>{MxjN zCz$?0Z}NZq4kO9gwE7E|R;BRTHZ7P14sbRx7NHT^Vm|=IPZ+h}MedDmgWu5Ypnf+D zkj;)glAa0;hL`_o8#qM^5_V%VmAJ5|{BQu|eWb2F!64E0K-?;t z1t@4$xpq64e6#~pb#?#&L^~+o6!M`K;6!ftFLIUJ&H}|_7;y5!Ks3~63Zs&SRy(kH zJ`1uTUl5en2j#9{j#%%&&u>14^^+n7c*EF}DEW^_{%=u*_ur!G z(JZifN)T`jWb*zOx9DK-(1(4bhM@;OVfqE1E&budA}ViUQH9|kvkb1EprbT~VK*Pc zWzPrk@R;qU|@1z@%e2PhbW%VvQv z9M{XHtToVgS5X>)+~@IWh6*5cpnwWAP`tkb=Ab8FbgM!mX1Ie5Fo-}HMXymTe|2uM zI|kbI=vd`MEG@DHD>Z9_mAZ4gw+Ec>#62#>a4bF5Vaqe$BF-UL+m=EWgFReqNalC& z((Wu8-g#q{JFlGm?GA6QCV@RwY={8{-kOVVS_~~5ZyNVC!WIwmi zPoMfN&fGmLuN(t-|CGA)>@+X$QTgpN@a7EhExQtYFNifhwa)A7`JvQZHGzzql(O3$ zUjLA=e;+&tDP0xX8<}xp6792yg?hwENkngNLeXD@hsV6gDe|Gg8WPhETHAH9z0-5~ zu4-ILNNiST$Imfx5PZvV^Y;l>NX+9T`kCP>IFk$5f5u3rEr=QTp_Hj3BI}JkVV;x5 z3a^`o#^(a(u)?j(#JJc*=bcIDjT45mXu|4#uuXl|`Saz-iV5Nvwa4%#@|w>Z&h$++ zMRrDB%B9~&ZIW~2d+o0}|16$Lcne3?Zi)RI*2G9xp2hnfiTNmBJ#^Ab@N6j-X~i}R zkL<{OAKkS0E+!V$T-oO*{xW|F{oZ1eBE(Ka1?v^xG?L~nYB+G5+!QI+V-f8!Hhs8w zMX||ia(W}4O5+sw{n=_txr81Pyq(S(a0{+gaSe&C^k%bFt5)o|DZ&=*P^&mO`QQ^O zeKqPB>!x8pQ+nu_>9e}rl2hH(dC0FZu>N+_qs6a-3Hy?h<;mPdS#+V!N^*6i(D@;w(JhM9(5@9l{Ovg9Bz`f z5tx#;=@88J;J!Ktc#gwjh!dK0;gg{M^Q$a|Z(IMpO8vVKCS*?6O)x?sl}a z9nMd4=^8q69s>C_oS%WxHEis)9OR|lN<2ODS-O`#Sp_^dW-(0RH7r?w9Fc_osg|~| zJ>a<;iy>3!C;{6=|ImvpY&fCMFR-!shZ3`};p&V0ygDAwHd*NToFZpi$&KrH{$i1=bk?j<5M1nHxJWNX#0jUiWdjq`GUMS@| zE??$EW~ZsHEqEdkMMsk+ZVafhlRu}%eUCbiX2SPQgNnsF?`~~L9CqC8j7IgpWL`;{V1}s+R5W{HmBojV~wdl$A{=SGVg09k1De{2@7=3gt5aVuR1i` z{7MXT53M;)g7x0zm=nqUB@2ICEZ-dbty$i8|JvE-{LuLfw*C6_O20;{LE$Cw25Ulc z9z1z&oS$0jJO#Bhh3(@;kBj-Ve&GD{lCEJPFC~;$z4-IJbj>aDQeycZ7k@TN*W4p7 z?N#C-k+&1jdWZXSRk}u;y;hR^>Q^Pr3-TNnu9B=<-D0ERy5086a@S6tfc+t%H*NT} zo%>B_B)j4Gug7f_`B?>K8gjAU+p9IY4`vC!MSdcrrj5muzh4=W6?&1asDGEA(pXxa zhW#Ned2EN$Pki|{oU3j&p48!zENn5cpU6X%@Yv`yJmZVPlo0#8qZ_hE;7og0%Q|QN zQOnCze`0uvklJCK;2rx3kSu~I1n!QKt1tZ?4|w+wJbC0$95$g#QR{nSWp*Ffi5Z3Gsebd#=VcrjCH7OQcE=mb=$+7%OYg1SS;`DxAPslh$PUojNSS+k0?qPoPaOcpG70{C6d7D+$plB z8$1mSt-+u&TLH;?L5I<)%aY(o>J)^!tV*%7mmDx-hrrR7oD&db@uihO^3WB%dkB65 zJ$b8@Zmz_38gK6#2PYB(n+KU(HD10_%LiO#G+cH5q2;JwYkE2u17A#LGhmM6e41|dIwO|D%%p$>A9@ui}js))ZFWnm!>6U;Vu5-YmzimdMGs@5)UfQ?64wuR9 zT32S=1xj0cf?HD@v@iYISrYHly0Xgtawbl;2AL^IiSK>obe6#P>{2WWe%r_bl=u+s zmpL7ckhzsVpgN&9h1 zZZ&nFoui!0ycK&Ff!ss9KBf#P>7{%_eNW&e4%^V`4!CkAMS|t*$hEZ2%eB#)K8aqY zu{#SH0eY<`(U%1drM!I(oChDS0&O@{(MW8z^IHrx+xfT+41(xK-Mvi}P0~-EVWrq6 z=z!54(9s7+V#Ou*z{&8#_W*%fJ>YFFLKcNf6-U>ffReBvYvV3PVQzllv;iFZfZlHm zxLhpmTP*g0+7$~H#_slGKqEDe*h`{5pna?Ak@f@K2@InBpJyC_l%=l1=EHUH{nNk- zU@zUv#1w*ZU*&zk$$a_(D^-?zM16XidtkLqjPmmNBINr*RW z#q|g^%LQTN_e;ar?n@=U{mwW#%NK7A`c+c;2X21x@+4MJAXZ`tycYTuj}1P*R{r|t z^5Y+upNgI#hDy4tt)C9!3j5UpGN~g>2q8Dv;ypwDI<%PtE2T%U1I+%m`J=|js`|LN z3;mgWMB=t?AbC*zF=aIJJ{tK^3>VW+Q_Ju*7aqy&Nf+h5kzKR~O5uOU{sQ3hDi9)R z-abHd-c>(CHBOe8fNKRHo6xeP_XKI7%j`7WzX@#Aib^c5BM$x-XKxu)R})2v1}7nS zf(EzX!Citw2m}xAZo!=k1a}A$Jh($}cY?dSySrTAo;lxpQ#JErs-|jwEP8kE)w`Qh z#XXnq)w`cNerJsX(h^dd$G}TI&|l@lTUE3%Q) zxn7TbWKv3hx6T@JS^ITy*M_IMzVOA*WM3^#=!3@n>1JzzWfEQE-0;}OIhpGKsorH~ z^m+TvX>D;u?zISP^X=@BSM!R}$tnNIml&#JcJuEys?ra?S=K_O#yu&G-`Vd}xsgn2 zc%MeC0YP+oPxozA+HUU6K8=&hKDSzmG0ARxUKOhc2VBz^cY2PMx#Nw68Dl5JAAHPx z4^Qwf6AFO~%6-4#^P9JCz2^8Xh(~efw@6sW-;>_EdsO@wUtR0c_Tmi|RNDKhvpU4) zJn4J>scmF)N-m=(#Ef66(R(aTH<&;ELnW^?mou*vV+_AE@Tr%hPv<}$rhz}ckW)P7 zFwU5H%*}ietq-f)hdvd!(}5!E6keXSQU$>y8N%gBf#PwN{vEs9wqjdu-l^3m zn=+N^<0-H~o&K2@>2yL?{r%tdx4Qc`Ts1-|rSp8|E8KIxT&|VP?`B9zZI`spM;_EO z(?7d;IQ<+J^dNC+t06++yF!rmxE@vRKM`kJlIm8qDQ%R2OZW?|zJM^X?* zm6O?z@a|DmLImsWs{ka?PhEYhrXK;I3zhsk93qFG0SeYzxBwc_Pe`csueu1NjL@-0 z-~xn1KcS-H!F5rSFCZf3`Wd{(8i5bc75x<1&xK&ZjxE1^`L+rjweQkB_>t6`O|qG{sFDa`vwq*W z$!E|}gAl}a{l4*&n*UnL;9G-j)06fc$F)&;%&hUTjZD&%MdX&|IvGhM%Lu*}90qnx z<;OEKmEXh0v0cWV?M=QXxWE+EpdDJfZf6%mSv)@hZOuk4{oC%Cr8{HenFc$?S+{yX zeK|#WzW1?k)_R7C@kxM{d3C1?t_b)+C4cDQNuK%d<* zJG>56QaZHnG`#x7(FHRKLRtj8czDGMTg}e5^fnJXPq#as(jT(#`@Mo`R%|ObWH-z+ zUc)XsAoF3Dg_RxY1R_EM{A{pDP44iZ8neZZwCl{TPaqOHtkz2ZfdQ$ff#ipl+DzpC#*!20NBxg!H;E$pb*X5ELaXO zpPY7T7GwLYqy6NPWWSv-d362aRuXiZJKOyWZL|SnRMl<$_Cu5+mk^VWKTf7s5Ggi~ zWY`A>`ItA+8aX}p2W)i$3{}jKzyDx`?Ng_{()DNSx@I>E51HkKbQ1@4j}+SHG$B#K zm?I5*HS26p7I)Eeo)P04#Wq>8iCa744ZkpGUDQ=%V=45=q5n)7$EtQ7*L9!aCrnp` zOovyFuzK5(<8lpad7`kLBV@GL+-dca)yZA%uP~+4FTQGfT_MW>guRbX_|Stfo)lvn zft#Izd+WjWI_Sdrn_7ppmYZYY-+!VYSA@&A#OX_c|AK9|giblRsQQ!GD;xOeDF(Sc z0#@bG!|L;IE6fy{Yyvaaj@Hef^KsCbUzKTu0+kbmr`pB}`fl>$-acvE+Z95dbK8m* ziyZnhbwLqzDci!;yYeX&yRPdt!!6uOX|r1t+P?E|Ie-W6<#ef^qkLYFfv^H$$29)VQ8bWbm?MZ31Q`f&svwGC&LBz|>;lBnTVB6$0zF0lc``uH73leE?x}L{UqjZfAPG1HJREdhO&L`KYW^Qn zu^+o+#dDD8(8Gw*IjKE=7~@FtS~mU$_~hR!5aHQnBSV9Es zkEA)OEz=SZ9@(F-`&qV6h@AkQi_cQ#W+#tADdAUe4CpIK=WLZ+y2TV-6opE13LT~s zgawk*A?G&pmOb8x+&)7(64GVqix-;`F9|!6fH1*ASV%A^O3H$50e{|dee!?YSt%7} zY<0OZN4M2~B4TODEt-6jrZ_mvV3iK(bkmG4J-7-pwZfIQ*XTUF>Zz_iWzJT=88D9Z z;}=xvnhkpSr2X0RhWI#00fM#w=Z#zc`o`A1BC#Et%7-!2Dc_#fsY3IaXgzjc=TQ49 zozX`n)2V!-p)KJkM&Vk7nZs6Ub_eM0_N4&u4R?X(AfOyF1nlnWo;K5gB0 z+nv|S%FrJke&X1f_dR#1v+82ydl_$}D7U&1fu`T;V^7A-L0KV_z;DNWm&K{q;N|S) zN1INVAKJZcpViw#T1;p}*t19OEyOjhjN9&?NT1jRAHz13Z^PVDsYNuG3xywV?gt^j zIOCCsx=#I5F%PL)))?S=&!NbqIv)-D(O^EQ>Z0qsd1hXR)PAe6((%MM|8CuB9sgwQ zAoSk$d8d6xEI$`qX(j%}lXC0BTGlM=aV<@86mk7T-BDYd*=%aGypwz`l;ioNs<_6# zuX~$_Ve8tF+N$7FuF!dATlHnu7I<{NC$^o3uDKg8pYb4^U9~;-;(2*pJ;U*2zt8%3fayI=e1j&i8LZuLMC)~`TaMplfsL+d#xI9$O@}mRon(1 z+q+ zJZ(ca0dHyQe-!T-%QWt35vZbka{n{#^*pGRi5rr}`vnHoP%PykbFR<4PAQCP>6j<2 z8lS$~TO4z}6;9yd5Bfr~D$I9ua<{IYxvq-;*+x2XAjKxRoio5XcYJ@HiO>JhNb_Kw zh0i~mbnx|!lbpf^YdqQ?>n@pjaYuN44;s4Iv)FV|ufiQf3;}AozkT$4{_WK{85Ogd zj7x{9vI>7{$}9@4-S)y=b;PBbqvLTcwi41i^-YmbbyWsmd+)`ii$W@Q5bp-xU^Vx} z<33!RynpZ9=HZx7!M6>`hX=%To~}}z8SOXRpjnw28nQ@#I`)7c3&Z36z}$1p`T=BA zg@g41a!(sG#jif@;s zjLA73E7}e&6a6O|TI>_D`cE}vNZesi==hTKul{xMI6bb0LPK%b|BG&Df}5%%ExvB9 z)-=Yh*y4-pl9^P7s$+Fl%`W$g#2|6~N|J_W_dtw~`Z(*F`G{q`Jm@hsKCAM62~I4H zB6g!YM!L3Rvtu}^7*C5e8|mPYF+cxa;~AA&_k2`XW@AZ3-w=?Zn?q%Lf$7$H=vW%^ zmN;1(iBnu-o9LUK6<6>X3w?*!;_RU+e9z;zXs<3J=7qhVp6Ms#PzR~s9|s5xb11M> zcc@V(FHh?1Mr{P;$*rzF`5z4SAm)6u_mVh*i-P7JGW^luiOz(;-K zl>C)*?=8Ag3P2%YE|tTHRcl6Vh49&){38b9r~|^R{~rOnKZ01b{pd3&0kFo;@P4sy zE96L`18{b+h+`x1Os^==MF$Y5WD&90;R01J{#usK$ceGLFVt#T(NK`E+r(?h%AjJg z2N35WqVjd2$HNDfeTuJrMZp?L&30miAsZ-aG1CmLqB)wIjZC z^?=M2YM>x{yaYVOuSn`d(E%E}Sb1_2Tpk%ZtgA3$>UXGw|In4+1g67N6pIcpU`@RV zY-Nw{g{P>Aq^=VkV5X8~!Ky|Jyn(0aX#5=DA8WWm{!es(%`Vo2+=P%vh6C$refZ;6>{Dd*Swo=cx*W|3iC z&p=si*~vf;8DQvsYpVk6~lN%vJk+OV*#fO%-Px&Kl z1KT1W?yhTY^`i-_fy$B(z${}&&04ZZhv)6Qzzs*gr-(C2A<6NN(!+b>s-O8LjxbBt z%1ixZF48C4?W&{ST;+P#4KFhlYK5+&NBBq5IngbKEFq%oG5mYe#Euj8saMx~I!u${ zDn7P~FQmZux2^TXj61)qxsE?cVs~e#5A`o`9EkMHu;FR!niD&Uj0n^ z$xeWj|xOO0*UO4or-?3MaNj)(kQQsEBkMW5*C5G_xEuWp|F zUivP<3X6vaTfQTUw@dpUFnr=T%4S_i*Pa^YK1iFKP}7~iSYx_Kb)-Smb(QXER)vJt zY&K3)NOlfyml({?v-2~B-R9l+TOI^`@Mj(GTCVaCTKw;TP2B#@-goDs>#r4cwoS(x z_sJYC);bvNT)>}DtMOR;tJbh1=FIH-m^+LwKLm6dcKAbFD-z1n?%)+%?N8dG_ zq|$pXa;YHJ6n%SFV_hI)Ht%f}qZ4ic`eq{w?*{6IGkZdRxQ+vglK7OFtL&0OEvDh# zuEXzMPLjglKp=s5y`qgpyugf0wZNQw9*1W3_Y1A-Cmitw8lEJf=&pAgheD2FY$r*I zr*U6K3>%&UPKw_mS83DYfuIG!4MGZpIta6>RO}XlFvFAh<>AaB1ELlaBVsDH=vDSA z5NwJoj(8AK0{4>6yrb{#Y*xFzM?ekjcuAfv9;6(`!+wH))KPY;53b$2F|iI?T`lwp z9lb{r`PMTvJ$jM8Z6%=-K*(oQN%VeYFw%3hKq{o8{ND^lP8D>2?=XGYjq8S#Sf9sqVd)UngYShGB0rX=*&B|nGA59Oj$0~EimEYJoaOtGyfb+55byX6#Y zd)(z|cPFJHTTB=H>Ww5>6Q1XSmO6{7mv3X5yv~DWfb@hx`X;q(AbQ}h(;XxeDlP3(00Yw2+MAk;}aV`F6wZX>;6g0`iQQ*fJ_?`Q_H zeXw<7J|z2rIo(lCbw9IEA;zuApMfACb?zDB@ihK*c&H@(&4s=$u=&sg#Pq(ey;&Ez>3|l?kL#|xvj4CuIbcH9 zTi>LTmH9rtM83yE)}Z<_@(u^~P;9IT!MWCd#InXuMH>JJ>D4%3Zh^oQl-2sBqvHaY zk1Yl6xp?%(Lr=Q5`b{5F$Qv)Sq^yXX_&k8^pE9{JjMG#4c&I~uXxMLj;m$JQ5krb^FMpw;`d*tJqT4dxYGbWvi`)F{&crc|99XdtT&t|S05*t4)$k;VYDc-f2M82H4`lP!hI;^6kKp*JzRV&s%sb>9k&u70R z4XH3YkQ-{1Sk4QS9ol)VYg*qOGJ>`d_36Q`j}ePhkb|Zl^BLGCbhhRm)h_E*X%< zUO36SoG!FDv{LE0WanT;?teU`xcA{PU<}j;0+9*JoIMY^agt77W&> z@}wbN(}}Zr_?%|albc5ro14?T>#g`EoJlptE>lo1R=nu(cfS6FBZ?IIFxMP!M?1c z8(#neR`>+iIBMc=IJ(DTC6663h!a{y&!Om5m3e6Nt($NhVCSXbz;93RH zwxK_51zg<~9)AM&15M>$JwqQc_a7kEfE#cL6e{RhL{{9zjaSOpe8~92?JGR&^7uYu zW>}+9r;E|sDx@q*lA=amNnG!-=wJl*{hZ{VkX-4pUBsDP-wHU-y11WXysG!!?ZJ7G z{IpkR4L2?qWS5Bqht_bHvjm67aF_4>AO2fe?F;u=MeD${PP`VOW9DIPam4BD;0K(} z9@nFPSi{z{_8?a2LxAwbrh)BljL=5-@X(p>Dcuu8#Nl{tS;cza@iat_+jUkCam(0! z{MR~6=_I^-i(^{14%_V3v;FxEM?G4*4wt+dv$r84w?GkaoBX(baPj+h&6P+E!*JU7N3y0~ z1m)`gc9X|5QsW_2;{Ym}$o}*AN9jNpnAiVYm_{DXV#GXnT|bPArt_6Dn)vH7#8AiK zQEz+bNFb82W6_B7$+>*eJ9*jS@<>-|7++sGAk$OI@^*tE|CS_ps$j$HUuH^fEs2Px zB@eZ%<+{@!N40&6-J?GSyQ$F8gpJgfsEu>VD2yy!+d%IhL6Z*Jwz<CJ4dz_ywTNJFB)tRG&%BJjSsTU5u?mBBgRzj5hA^&p&MN^QTEK-a^S$@zA% z>Koc$<7{<k6TquD5T#^V@lj-EWgj78CRbgN< z){%rn4Rbi2eC>-?PNk(@tUSQW)gi>OwV$)gn{2h?@QScfl8UILT4l!6u|zy=?OwGy zj*&Wc>0hx`huAD!3oI_LJ;zVlIU{&IS$ZXu=CoJq3mr)ArWTwp{uHQC4fqn%C=TyJ zllP$O)-V1mK|y=2N#H!yJg`FN=&V|gt9dMK*OlqiJTQOV7IVC9C^U4qMmoC8R01ic zUOEI~*E$`MH1G&M7KN%Uhw=&X`5el z>-r_tVW_?Gq5@uZb#Ua0`QcL!!NVwvm(Ibd+)4%dT_AFbTsQRn-Dl}whM#0Q=cHGg zoK#gCr1uk1;*o~i<}JFzEd)JY(JnCq8j*3Ig;r#9+qvWAw3?))+w3D@Wi3KYw@Ne~ z+Oa-1hb*Qmx%qd;;XEI=@gGj+?KQLIWqke#JM8L6er0kkWNPmJ{qD#`Q6bAVkK27A z1CM7;MxeSggLI`wW}WR{hEhvn+@*7?*HRa|G4zVl%StLahoy1v}{eI7==PlM1r&J-Ek;UpBq5B2+?chY~Ri3jmq*`3(42tpMs4x47ATr15+((wgHKl?GVVA9IOJ2&cIC?L@K(HVZpd z{Nx>#Y28cje_c!f-@&(kS*7~ce?R?tfe8#LfR&CCaKFNebI*q&_PoD>V)+V-zq2U@ z4(uwl0aoFu4&nEOWrzu6$#_x3h`RW&re2Tv$EyFp2)qe!BF`gCN1#~U_<(AOvM(wl z@*kxeq+rk4PT@#R;g0#l7JQ1Y_;L2LHYn~U2;{SY{EWB{1IWJUZE#{veiJ0*wJ4}B zaAH6GCMd{jQBj59#eNaUCi_j$N=?y`bB4z`zd+qZSMDF|+ zl^H>7+;4(YYKn`zHY)B09W~0BIs-xM*l$9BoD&mu6+!IDZ$g9?$Pz_BI27q^E_+#r zwZb4qKzeQMA-)%E++pldB#v!z4yp(l1e{qRYx2*)7jM|Oc7%50zkB^$?@vcXFXB%W zyZTBkCoQ)2jAUG^2Ef35WOd<<(0#w2_@Z{}THE2k4=J6L1O1eg=%%X%|S>t5#7(XR)xpVzf zLZYh$8@U#GXc9ust)InbDJ#j$rradN94?Q&XsrbEvm&+sj3m%-`OhE-RY%Ur_qVVm z*ZL5uj*_$MZ{b5u=@*ytDpbZG?|;enLJwY1iur}&kW(UsTEI~nxtqo11e@d0JN{=# zuROxv)4O3vP+vw;O8)wg?-ZdMJ(ZF(pu}(K$|pys7nke2b>f&1U8W+M=P@+L+S4P}E z>vac)bYvOub>z1o7gbxeEA8JU!1)Q3Zw-_r90B3A5c%&rn%98lVGTPwhf3L9W$hi= zZ+j1w>nJz!RZhLMIV-`eP|tgJO5k|_d6T!0bs)l^T_)-qTCe=nSlL3K|# zGzMI?$np@+N4VoC?|43MI1Gv^Sa_oteQ(Eqga7uJ;+?JYV|*}QM_YsGq#Kw058v}yT@lWcGa+ulHJ6j9m$7YseLNCKb=ZCH zrfWrf$J)N_?cTa>`M&qI?KY{NNz6m{^4*@c?&;CX^77(SCZlusIAP_OThwp;o+o0f z+mhTpy9kyRDWrsR3MVU+VwI=C^!~V=Lf}RD+B1!Xt5U^A`I>)?k*ks=d8U;}`B-jV z(n_!LhwSL_AZ4*f#%@CD{3p;u>LxdOECm`EPI9Bx!=S6Ji=L~p`HPiai&y?0*BT91 z`;zP?il8PkuWM1_G=a88Yh-|m;fc^_#|KvQU@E>zad-d=K^B9 zFB(^U0X_ZYOU%Zl)xZDd+xNe+n0ab0sxVlz58{4nkL!xP)?W62Qn`Pn^LhIP*XJFG z4F=sa3bU+2L^AZEs2Fi$H%eb#i)Nx_1dwdX!z1spmg~dWDwl z{s>MbuT)`nrL>NL)S@;-TC0%ZV8_@u8^u>&WstF|;R2mMrB-KuphiR`gcFnVi^V0U zMnctu6VvjG#s8y5YLyrQKVB$!gOjLNDz_Q%1hCONF>a%VhDQSKFv!e61%is>wHR)- zGKX@tG83TR1S+soT*cp?03Yx!(Vj%4r8KuiL z;nyc#Mp+Igk6Vq#_SY|&ZE1Z=_Zb#PAASEUzy{l&NZRvIpBfm41lMQN4S=<@qlaum z>-(zB43hq}1v3%S#%U+-QMUWAp1Kb-kha0qqfr5p^8M%G)jpElD(Ti^J1?i;T-~goMJ zUf%+hO)d z(jWjTT_$5H!gMsEQF1Og)hxc4rn+0>z zDhC(-r zmy$Uwn){q?d-^M#KP@S0>pH8=NUhKQw4-k>IBaX*h_;mM$|s(Q?QG16-Fk1;FHRwu zQ9q(4aNa!kzWIv3ZWxMDQE}~A9G&l9@%N^x{UW`mBD9gTeE|EsF(*L#F{ekU;qVvT^op4GO{_88}5ojcO?;1)wlPAb?J{rCtuK%I>8i6e0p3A?}^Fza^>-K0O z>Z?vq-@TIVz4tlMT1`2>(VX4T1fed>(4FON-pNgXVve7<)kPH z`0y=8L^!4i?++7mw|%U<5#kcL?JK2zE!CEjW_+_kywTh-M;y6!9C zdCyScf$Ldx4QdIm3jNJB7l}m#EYq^)_oaog>sh0Co~8(D{wtct2&|FQF{LMZ0_fs* zS`rocUg`4=N~iNN4oa`YQR|SY#s8=hoP14siGr2PJ1F5DPd)9#BFkQ`K{HspLL*z? zr7Ful>L43$SGnlU)& zf6=7CXm<3V(Iza*p8p;k`6oCs@8U|bJBw^VEG0M{HJU-^@|jw!b1;4vI7ht_>J)fg zaB9O4GA(l10@7!qRIpG719&`e-S}r3=UfY4*M~gI_2zMHeS}s^AAV7N%%*wKO#86R6N=ELn*a* z`AzUy=~l|c7l(meeIB@K!3Sge$i*oeFFy+gYU`}bRur{(M|JoPOY5JECsLppT(-8T z1wIxODKHo=+gQ|s5X%!eumCRGTGWCV3yK`r#}+>Zm+can=O$`FN_9wzwS*D~gUj|8 zJs`)@LJcH^&khqkpu}224HSmYj*HCi*07*4uDW=iI@l=r@a7azOvHcU8@cm4RAwYG z#YHxKu~Z_Nj_4EXa;`gKAS)x4hs#ts-@C8!0SGO+a2kU|hJliH{82#q+1~z_KKNxD z0XoC54ltiUV-haX_Y*?((h>)-hZBp`G3h5aoe~ayT_-Li4M#5c(91R8K1$suLm7pH z6}UZxg(nZ{np!5k4E1xz5k3by$$90T2iVDh_aqa&sAw}FRKQ}`{sOYQOR4rm4yPhY zTkV2H)T-+x)U7qTgg1v&LmTF>inkt5rc{?>0twlQ<=nxhrt}p8c5J~hO{)ZPDQ1z8 zgPiffy@a_HAFLwJJ{U#9z~mo1ZR)bHdDFgybN-Lp+`iU2_n-f;udRM>f;IIF1wO8S z#7%C?Ey5M~rfkP=B7bz<%Kiv#h??QPr?+g&WGk3iG{|dUkGvVzAW%`Y;SR3PVIuwnIE) z+-?B~ej~>{gmL|enS7%)N9}GmZK&h9=6o1sE;QFC8v6uWx+NW(2}fE$I(C6N+Lf?_ ztPDpwZM?FJ#i4fanTQEjdN~8z23MN67j-Ty_q6XE;i-4BerMi*LO|1q63fPf?n|Tz zwR-h08Z&krfyGH2aS&fXsDRK0VGP0=gcAra5I;dgXrhOK($tg;CbrbL@1qJyzegV` zhlj>Bj>%h&u!cd#G>Byo+aQiXT!VO8oQ#M6n@jWFK>CYZXLQnxUj`FBs8sD#NJ{XJ zn}I_O0v!xp(MbsbB+SJ~0$R#%U2F4*PAp{k7AE68!JbHlAfX#11cHRu0-DP2&Yoq| ze(U5hMdq=bn8+Fu$eM!GDUezRQp0A$cOg~<2=*G?)DG! zMJ&-3*_(yYhQ~xicn{Jyki{mo1Rx3nQ@|WZzOX2Tbue6a+zy>Lw&}uJy@7rYw=&Po zo&fO1HIB9*!z%54-@3g-FV+|zmlH2*y|fqIlX|=3`PR&-#*3)E`?AHe=Yoq-t8v$d z!k3@j5Yq2+o3_i>LGc{IjXv|X2(BF>MV`+nDwT^bh6Co8KzL=1m)k1OmdG37+NWGV zm=JK-UK%7jU#a)8chI|Pr!()xwNCJ1+NUtomy>!0b|T z{HWU5L+%%K8i)|Udbw`0p8kB=JM(ZJ{8a(gK3;bTZovNbF6+rV?Z1;(gjFfw-@0dX zN%qH}Uu8T9))tw#nXeC?Mup3v5krSEd9_Tm4WaOOrwk?BUWJv-X6lBpr=IwF9&?j= zVzuv}tm33iLvmH$@%GP6&papd$Jb}SfABWmvCVlMpYT`O`fs1Ha`a4jB?j)lGnMMCqYwLVX=A4PLsZuJp?c)ER#sAP{mqAH zp~mvO<**h^H^@s^JSo{e$yw7~U4UMiG}&3(&SiiwW-qC$*}D3KTUXJDZ%@Jd8^x%> z4-+mjU7c{F94NjVmDDVpM?Y3r>Zr535<_t3?imT4ANqTKlBIwDw9~`Lj*AAx(+Ph( z_p^eVwNAfODc#d#1?Ckqmi8}I?ptB&@1N)yy^IB+gKkOLAuCTGJqO(Cudi3#6=H55 zl{QZlamP@&w)Hq=e1En(AILOg{%MIgGaehjME|%ReRkvPT$q&^BPttYJ6=ltD143~ z+Yb5uD$oFqLQ51CA8QLK&<~EnNEDS2%LqB}4;+P+C@L}5R-X(!O5i|7#*RoM32GOD z*iB<~a$pRjm+UiWAjX0QVpC3XU~F7(ETg9^7NP9B{AwOnO$IOX-Y=%-2PVZQBzUa9 z-c${;7h~bECbluh=U3l5`l4^{4C&!07N6MGYcqHeU$2M6vd8~+lw^I)KowS^dS|!D zoY*#QpFE_;(-Ax%XL|kxJi1%2yx773h6ZrJKs|#aZ;fSi!e2KY5Dxp&F(5Y>s@2x1|bbm~)t3(fpAJE*S>L z*qz29Eb+t`-Wje3jWwU|wECGJVzFnKS9{gJ&AoNW#mDME|#7pn#-I5ppAB9csy%LGyw|NDjP{ka~m z`hR;@@!z0LWNUMX`0~NVWe4RleseOKLxX@w{WLIX4qqXRk$tHIxJriV+q}_;IPN$w zw9MU?BW6|LU`-=FZxN&#vth5#t+W&i^^k0Uwlj(!rHn2G6^$N$VAEDDEv$dw|7P6; zgc9AX8J5q^xy{ZUuT3tM=@l+r+nOz>C6|CHO+GCvY9F^S9C2MAeRg}Su!J@euCUGH z>p)BJaCnFCm7jmlU4DzKoKBL|+Siq}Iv9FeJ`A;}J8tbtHMZp7ViH~0w;irDeszU3*F%0Tu789cZ^{jYNKCaWeztvODyY(=L zA5VEHn{(^(u3P_Wss+rva}k~Qw%zc99d+8z{dUO4^>Jvi z9(vmGFyo8FaExxn9=`qT9%owa*y2?v_x%FzZE#|P70=mOG2Y0Rc{>K1^0BnoKcgM< z1;{#$5>`>`P=JZiYcR;J@NepAB#Gg~?6>=z=UUbggJ#UUXcGgE5JzDL29&^tJuCCx z(uEUF6&u%9MH|<2dhV87ute>U`cN}k@EtFWBqw}SxVsX2KJwkNQB6#dQ4OZGQO&yA zKeLY9uu;AKO6+T+n&c9&`L|KcJha!W!z_HXeVC5>$pMU6F~g5d*J~DY6*lTCkDEra zjhogcgPWF-7d|>R(Q77MYE*+_t-L)W|2{3l4jiZgM&`8+Pu8>eBI1BX5!uWc`h6aC zN}eSx5cvxZcHrmU3|*Wm33f+Z#9WtR7<8^yE%~UlwA^YPGW>3~D9Kj0MC~-^T{%H* zNjQeja!KrSmXpHP8jii4vzthZIbGYy*vPfe_`O%=b-FmGfEHcqOGb)?t5=4_9iAYv zJoc!tSd+qAZHXF@nNYLy*)X%piBPkwRE`z28$tx|#8Lpyn5mvG$sNsdo}nJZ@zjXGzMmSgfH3}^BL&kRfl?*8_H zCiRpK9L$t9Rab*DwJqX+yN7e~1o#~$bv_>^B~p$Z<*P_Xl#z!WrI&*nbykWUwMLE| zm1#js)b^c{h{TwdD1!z&>W+$k)EjQ{pjo0YMUkB7g>lkyk2q9{>=W1}4>zj)4@jB$ zFJ!3H{;@>v`gEw2HUH!R4bkL*qI1rqN|*wNz8I$`8`w=HRLUGX!>m2X;^q^_npPptkH6cOy?q1~K4tm}vS_rHBcnu+`_@Qe%+c!P6 z6fwBe=isn+-*cbhWQCOGR53Q~mX%^7e6xa_u}!@w;($RGJNFGElBgdAy^)%@&FiWQ zPI^b|RCh7|jWF7qB%K^eKb>sEer3P94JSkFPKHl$;*%m+yWdbh(Nflb7r~c7d^Y)e zQKKaLHwy#LR~XOQs8CcgZSU}Vj(^4*GsCUJPI36zo-RxOAQc3(LKHj&Y^HSD1suWI z>SFuvfj~Eomv8)OfEZ&wwdVAYEe!JlKmC?$cprAJpfJdQ z{*3SRLP!0{?+mheenm2HHr0!`|H69uL}o1eRYpOce)x%u0L$?hCSv?&auFyOe9W@m zL?aCg$`bNFEOXEO`83?;h%3<=O!<~#DZ$W{=@wWYe3W1~UglC#yw=j66R(NIjUML@f90kuHBW7#emsh(-VbI+#VLEGv7B55D7H3Blcb>iqUKJZ(-7>U~ z#%RH<0XY@lO$NmZ8nvpKgwpW+e5(Sd>e7u^9blIkSK2%3Yd}O^>Jpk`c~8li-FU3E zy{8`C*n)oe^Q{l}YlW$d^vmF|%`q;r((YqO8pYg05`w=xt1SHM?N%mKN`s&EV-U*e zxkoh|+YE?qLHYGH%@V(eB50_G)sMv_TSj>2C}{8C@-0!4l~3b6T13|mG|Y#E*6$a+ z#yh=yrGt%~FGT9cN}co8SVn?yEHreA6tj~UTWM(2Rcq&f|;u5`R)60`71zV`eHtR@3#nd#>iK(zlduAp?VeGAs z?$F4K+}PD`I#XK@jZ9C=R!-Z0XjeDlZFwgtgjbR27*iukKX*01Sbu?>Qgw;vBmr5B zUX>olYl2()rjtOF8`JZ*^tk&^HT5mk)g7pqYZ)}m+o3eKRQ0_RpP2^r>5^(CXp?3% zD3dtVXp^XAdgFtKd*eytLTOx*!f0N=_8EEFBn;5SFq#+OX3ezdD#3_d5R`RvMMx2vXx-8;4i)LdxO34{J7diMbt?% zkzg>oYO3IGMzSOzjSi$ug5BUVzAJlyVH^aJZ*aaW72tlMRDUZ&n^c>ehb+!nMQ!xY z&&Ehr9}KjIt!?y?E{Ri*GD)J0085c6>^mEI*7qrclxh|! z&HJ^X0cfarcB^1A&VY=|j&K~{7*csD@?EB78Cvd?ktFE$nyLO>n8vIs23#GChVUDs zmj8>shC~Kq`dFt@5VHEeh&QX;fcCF`T53AFyu{UK@YC3R`I&6%d;}-~UrgO?W55%K z?`}KyOPMue@Nj>5)%g zR#SRdH?XcYjn6k}&{~fIkdW6if%E@f-4E-%TUQ+jKQVrwpnKieN1i){G}b{kk%t?5 zmYkq*&-Xj_rDc`!_KSQ z0K$~Hu>5Nhw^ab!SsS?Dz%qYHzS;qJg#VDfN-(wgqjtLT2LQi z@ot{H8D;%%F6MoaqV`&@WZp_qF!6e0e8b9v5pn)t7*X|p`;pvq3?!*-O(>UByGfec zgnKt_T#vDVK((_W{Q_xz$UWVD)f#=ipo@F0C8OJ8pG?JjMVT*aB_`3;+^FeJTTg}m zB-v#By;EZU9A@l`87)IM+GmKSHEnMl3E9#PCd*B~mUn+^k4|C6{$qc~>PS$ro!tH? zu-D8aSn8}R9Kn(AUF@7zqjR>VsMfu0K7j2z&KQTCyE~xocA?b17`almm%A#>rd;E9 z?lRUpFv5^O-i7Tbf9IWl-pAtDfvqm7V-x!na;uJPq8^Xp31z7I*`91%Iis`{DX`l} z#(yE+s^BQ@I*%b>WP=MNZ#5Fo)5+#x`K;4VRf6WpCeLvRT$iwAdt z1`itCA-F6q!QI^<)6eIKk)?Akp@ybSJE{sl!9$z;^qzNi6OBlg?8UFsFTm6v%@vH>m7NxNf;Zk!? z=7ib?Tg^hFp`@a6oe~96ZppE%`vOjyqC_DVjX+MDlA@?7Ujd=7sV2giA9P5Izz>rX ztYiAx0`fNZCmun6^R1xRTqw(>9q%`XWfDXQA`14Xu5J|+^d4dg_JXeNs!&u6yDIiS zUEMg~SWL!3dI<3JRgdCI}VQA$owA+yx=O@<%4}M`rLx=I=zJLL`77V*8`$_@nBf zys1LKt;6^LL1aBg81P4)_eb9MN51n%ew90C%Kkz>^FbPdXbM5Jv?8AFe6hTa7>9&j z6@)7G-!M*rAYO$a;emkXBxvgR5gDv-?ptz4=Q`?)jIx4(XKv+CiKz z*+E0ou5sNr}LU55V=_T!H1+8H3-m_6^(1m3i<0M-FO%m2?9V(J4;= z{S4|HNSAML3RO|50_-lJdvL&c2FiEZZKQM8j45g9#%5)k?~~2z0BA6D%(DTg*b;rE4y?{uX|oNcy9!ud1v{9^>( zzuHK?2$_I?H;UMM%R1T3Wj>l%!JT@lH0y&mnwKzWb~6d3?R71P@Xv6hD^nfVVVRmN zSH`u`7tdf1&ilrjZ3WZai}`@Vik$p2}g zwo65=TW%p6j{c?~WDheji1c*{BbJ0-kPvm-nxKSNSH897eoDj0vgiym_RNp^9evls zUwd{_T0R9zqDl6{S@#iwH1uP2}Hf0q`E$9r;|Y@32p_>^%mVt?nuUtwR;vU%eq+dsrf!k5L~-lu|>9g^I(P%`ahElR?GjAp_>LICZh z7RYn)CJZov{2)k`OKIb!Naf5k#L8F@|Kry=_(>85E?&rOui4SYdxI(#9LB%e}*{jhDLXp(82TcT+%nLdDcAm+jc zIrDGRnjbXVwrWXq=SXIT&vmy;zU(FEb+jvrw|0phyaL7~vP86c0dKB=WDd7YjSjU< zpzj!Xi?exl45+c*b|}k-@~}*SVH%aZTfpI8Hph9xgF{zNE18sMnnbSshNkzK~jid9j^j2Zj(zdTLT6^X6u6_&r<)?u!pW{n}>mxe)?;}?^ z&Ll>g`*ow*INU$mcQA^s{OT>0Uv@WqP8l+Z9Oc<2{1S=j@zS;p_UDDpIfhl5``sf8 z|JwSkKa639g{RSezun?9rblK*!!-N2%hV5&-2k|oL?hv|$ho}6cx8ze#feB~S-cKZ zlcrkf$aH-}_P1zBq7G$IypHmO-0$1z%%gd_>KMhD+Agk-bJagVuAS$IQZz`w-6J^= z9w`@~b@ZBU;nlmp>45 z9mZi0Qd9vRl70L;OOU?+(Vnq0}KwUNyQv-RTGqOEd{G zIC^)5m*$8m0Wp-;4G6x#f16a`_O*m0KwiL#ysKjb{gl4U)8=o2sJKg3@a z_rzc7Fvedtb;e)b$$MY>Ag)({i4F7!ogu zXyPwZ-+_FbtS3gYoM&CUtf#qiosf>$zJ_2qw$i z6NY%4``(C3=^JbTgN(ZQ`HxyrPs#v9hxOYHlx_Gi+geT@GUwIZ8{r5@tSj^F0+vyX z<;;$I&#=$SFiyQXg{>iEAfR9W44T6+p9aPw9)NzCMYuf1i zDW)Q07bRnU@~CorVYMI! z@%R7vO3#gxhyg+$9Pq+Tjp!AGUOK?vRwxu#a#-myJ+UPl7umt$*z_9{>Qhlc^y!bx z)VQQLt=+p0Bmn#Er!XM$NA;}JY_-x;%EL3;MP0{Z2Y?8t77yS%2mUH3eOm>(A4Tb? zUF%ZOPK^H!kptA?)Y9N|AQ&1oBhG**GX6Yk8h*a*2!f;ExF2>zbOVdkgm^ur^>?CM zwJwK}HUip;4T^+;!Pw4Im@=Q{Udi~iGyBZ#H$AKr=7#2bVg@hoG>4kW7{9HX7wdth z;1zdhl3U!ZP_R9zE)BbtKv6gT7JbA>S-B}mS^Hx?{83-A=@QCit0?NNbw2daKRaTn zff-=DkUrjk#$tV1Q%}}i#-c16I!jGBGiwaB#@Q|jgiaCZ51f6RnaFGoje#klk+a=! z3bmJsVSX;LLppRF7vGmhMs9ZTkN!FBA5HFvS6z*8gT_2tkNEIv4z>P6tF+aE>kITb zG-d;~5nJ;)43<{=)P;cxay_?a_MUh{i4jNhxi?&73-!GiGH$}vbQrCL^KU~9wW}QM zs^4O^w(Eq48k*G|3kHSQME@{!IOZRz5U9YdIl`hxoTE5kZH3FaF9?gZ44)$DG!a5J z{QN__18-j1L4&-5eymUizi5?#Y={Jecq0>>66!R4v0Cs&LchggUha7JV4!x3L*xoc z0YmlR*2>Baw3bQA&)B;+;Etoz)ML+-_Q4YI=x>4Q|EPbb(c_H#Bbu7|b5#nAS@uqsv*}OJ)H*fP}GP<33 zmtNFH`SrTJPUBWZ`4YZsQcQR*e(OND7hm7~C?3|nf3@V@$vO7MZBU3y=RD#^?7Cxv z&hGmhi@lcwW9UDHKk`*M`aw3xy1G3BLtK#2_s|ptKysd#L&q$%B#7{*6f43np@F!)rPycG!I+_6{v+W+1 zi%u-XaXIO6eMh6*<09c?fg$vx&fTZXsD+e3mK(y>YV5J=j@B*F6;4JlC7+w2)9{=U z@+TTVMec?}>ETQ-;i!at{91NGrmRD`9eW0MYo!CR4o{NU`rcBff9`eLhPw@#kDTTB ze$DULyTIvO&u&Y}D6-#4-HpcQ4(h}TZfzH91*lE`qHo^+fLX9F@!Fs=5h~keZ1nC{ zU|u_7FzdtZ3WMykG)78aU##qNkKiy8C!7iMpY3}XmLNl)kyHFulz`eYw$U<9<$uvq zsxy~-k>hLJ<@4qL3zs&>>lYs6Z?3INR}$rBn2E%*TouWi`533b-eaX~uIvrIR{i-a z*kx-+^2}0gGs~!EW=5)}eM&sb@vwl~$%#AVpJspvW36z?pPQzvw|ir9=#2-7(H)K@ zjAj4oP`sP}`CVQAdvbBM+&@yYJk@so0TW`h8E(Ct{=D_;E0a-N5#=GB#rR0vm+fzH zmN6vE<9d4f&LtWj#sdSj6*YRYdUm7<@d!6=Sqo6sh}HuU{R49J-xhopGD*WE!N9O9 z=+z<;f|wu#gowW+KzXY}q_96S@Bc}>9|a$clebDGuDUBE@OM=tIR|7Ya6! zqZRfW^uPdA0u)LeB7cYpPGCsDD*_Z69iljhi3-TPCP1MNjK)-{vyB6}h##0*9-aPD zpA~5w*8@Yk(6Na+!A3nuD4aS(Bj^5zm;@+1Iz;mj6UU$sL@WXn0Ue@!s|5%uIuZp7 z=|70cdcH*vB{Kp7vp)g_!pkZI6b}Td&KC^ph@A-N>;9++FPZ&cQXt^f-Pd&?fZIC+ zpfDq#vLIpWAmHdAywO2;tAl{6gMg=lfRFNa7+t4$wudtKc;n~_;Qs8DK-X-#-?0v% znFgZe25MpyFOKZfAjGNhhnc|VD>ywZtVp4Z>N*?grI~Ce`4RBrX&n5<&U?(}98AxQ zQvoOP7}y!sdEt~q$J@Zp0N}8k(NuNLWnbEw0$+p99?%(AWQ9HYm+b!S`7@`zMFHHL zc+c`p$ND5t)I*60Pga#2F#$dG6=J$0Y!ntoPS%*r3DQ)SV;#${HWn8os;MvyEY`@5sTKj;YXK;@6bfk+SUzRR+9nf~GSaq} zNXI`$Khv4|F2^k|1PnBDS6>G4!(3zRfn3%NcB*(}mR}%ck4LWV3TF<(R52GPFkN9+ ziAQ$L2j!5i?i{I`9u!tX^TW4TNJQn*hTSGqH0Y*5#JV`769a*(d0?$75G4nso$<)J zj2>u6H>xR)2rp}L+)F<5BOvKc zxJ=WLAp|mq1-#Uq5c=@+0wPYp9fQ_^U={cLFQ=Ogfx=uAL(Gaz9c=Y>k%n6xF((e0 zLxmdsAp)$_6o*`%3s&MZ7sp4onroKFam4G_42DJRbZb_O0|#v}NN*L1%;DLKe*0p+9!mnkq~e}?bS27MAB)vksLXP74=CNQ z1&E8!%>nsu6L8g7=`FXzZ+o_A z6yNyu^bWjoP~WZ`=g;%$IZ=H~B%eGjKbbs|lBsm5xLIXWe)~vfYY{PcN`JGWGdk@M z+`-W9u{bUIJBy!c%VnzbeMfk8&?;}=t}jhLaW+q%FHmL{HU~YHXrOe&7=`wOBiAi? zk4xeS%`US`)bhJUnLcIrD5EzJJ{U7T%hh9A|D6&p?EOQ==88<%Yt?Io*Ly8t;dXvp zbf+9)v({^=zt1$@(q}H3r#Hphf%i}iJb^U-|EO~!iYo3~yN zAKAgP^y1W2V|ZHbltNl_Subs35Jo?vuLil;a%y_E|T*4P5fN?mg=w{C2r_<>&RBlW4}Gpg*N)pg)wci2QZk z+R6p^?c*0jVv>aynlaJb)DwfiP$Hno6(2TRN2z$@;6hG`{WS7#(6ZG`e;wemGlrL%$+SV!+~iZpvRlqLP7Xc0s*jfS zruHyp1Vluemf9anaKS&c>Ei-7U&yB0d3|^I*%@R$T6xS}L|@RI;M@joIR@FDRQ=fC zPv{tVD)+70YF$3q&3E_}*{m;}9?KGjTaRxz3M zoxo&-$coww>#|Aw&iK_&3fy*Yf5v1hpG=HV_)Iz3?^&Nb&601j*)(QcYimUk611DN z^V6gu;ul`gJhFCH%x#garTe$;j&W}mOAYmb);reF1bf18!tRBdniBA!cm zPbAstP44bu1}C}e>d?fUg#?)^A;v64+Tx(<_@Zi===9ViRZI9RJNMd!)lylyOyqmh z{6kn>KdW|MKVd~`2ASx4uhUT;zUMo$$s@zo=7pg-Nr`@`^84dv(@1e+8y5QC-|9H+ zr}b{V{!SKlsg1T82KIaegll8#MXRrp{WWCNAR4ty;z+Y}#BGKZFHxE0!Eez^c`Mv&+x-%9ZNXh(Xv5Ulj5Y

yja~WxFc`yfrj%BE^ zgT@-#KyX5_A7&&ff8<&bkbgToHR_9n62`GWGwRDXOZXVQZ%ttQWOz(DyDUVt6~{kO zTO;5$fof{IioMIfHEgCF20xs(mb*8>s9d6j?ar=5VxOmsJyIEvc@@&X-GYd8{Yb_c!>+W$Ctey={ zrn^rhvqb~i2C;Y3Cpd3k5*Xm=II2UsGy{;`kqHb4v@k5}(V0Ry=R)u$(jL1baz{c; zeyQyCcLp*^3@;P&Hk-3zvbfkJb$E9BsIzA_^AD{F6|2H`wLLISv6!2Ls@88h1CNl< zPqA5C0;b7a($dn+u-sH!Mh+~kW71gFTt?!-0x>;UsQ9n&0W9o-g$130-PGg@B7^rl zFx${I)QZG(vzB#^CKcO=!DR*>*z!TnZt6#F>zMn(pmei}*@dl(?vq*JwS z*%erZjDAY+S)U^%@>hB4Qr};#k!#bhOuK&71^6yqNoNnKX_toHTO3Vh%yxYSob{at zIjZQHf>?S!#pSA3ifU%-g-!@#^gJl1B!rZy!~K1zyA4hk;P z;`ma(nySAiYS9|5FG_59qvJ|roa0K3Oy6ssY*A?nb7p9`w$iH27}m;Z&dI;iToKC9 zxV{GkKP%%(-Du-W?cG8&u3JC>tG28r8(72l60OAgnz`hV92AH`e`s7EG8L3gjVF|@ zW+|2mf=LmFd^K{K-?Qj6pEY<(4#njPO6koLOR?lYbb8QSJ_yG4wV?DdvBh$Vxa3ew zZO&GYMsuZ8yws~DO~ch+w$!Ttq`vVQuG(BBhig)5GozygrPv!B3ebX5Q7YHbLU9n{ zzvk2>hh+aXr`3E;2-3L50(;p2QtN1qYX;PkLu8T?>qL+zwN#s-0b!KWY5~z<4p8GUy;D4)0R*Q*Pzv05vS2qOinUsq0?;Z5idZrqrIJ~-(LOcZESpF3*<B!fY`%-VM73 z*T+(3OD^$k(=IO9B=F*tQn*ud_=db6;l|;a>ymRM*UQrh1c~G>19X9kQNl9^H3X+qAQ2 zS#A8Zuxh^auE*~fm~GL{TYP}A2f1Gf1~!_7funBQVZK{U{nQQm3BIy^qeut(iuc_@ zk9YfSSn+L*aE-15$K_nwP4QuPO!2d&_xRLg%>MPtNt;`}`#(R=x{~pX)0os_`@;4s zsM9~v$-lHp6?8Y)W!5BAS%j#(_mg-`{Jryk#?h{LOEucJaNqhGE+np&B{t7}nF$PB z;aD%6|EMWvZhAIs7-D+%#-PUHY>nLcYZ!WC7Bcb|rBEI=c~i23SeWAtpH{<|&xGQO7li z-{TE=_t|TPQ7EL{7S{h$`x7l#1mV!M+ESTm4V50RX-#I^k!ltLaF%?4-BgOSNiTkC{?P#cHFz72>T4(vzW1n zK6oZJ;V^_x5mlOfW(YJpeOdgLzeIiitGTqPo9Jijb(^UlJ8gA7ACZa>= zcl`vG3xW>W&w5^;tZQ80Y!-0X82e0u(VJ7~tH<@nZj!HU~(F9e&HK(};80=2J)DIY1csNsKM{8}y;kPxtSc;r9&SobweBsEy_5|SO2&v zR#sfe4~cD7y>{{1lIIzXW^0jCjLGKmJ{4x-dA?(+ooh9gAJuBN;Wc;mx>{gM)yELb zZOp9FvawjMXgs~noGt7kZErwxJWkG%0qQ!|%r61be>yJlFM z)SHGEU0dDS>-~G6ZJTTUp?8)-DC>)rKEknp`>UN)KlL#>EWWo-bL6?_sQ{6wsFi?^y#oW)*t=v`%|}8Y72rHL|wX@P1N$-4P7>~*a!7av}>=)*}is{Ank@n zemsyfHk^2G;dMA@b8EvGbm{ta!+X&@zp$u~dGarbPhQb&M(M9T%0x~H!VE4K(H}KJ zH6yzEMu~++B$inXrWM@JDyahAmU-MXuwgJmtd84;@k_2 zuM86mMbyTiW{YHp+e&bUdpm=%Xrok80F#8mxDxXwJk6O*q%a+V5tFoao-QeXbv2T- z#jc%4_FbE2$VoPd0cH{-Er6wb2uhV`EaG$2V;_=WT0TVJ_oH4RV#dCvuS~=ww(#w-3jgpVGjMYNl6%$bn|+reyj;k)jBsQv_!{vt!|W@=I&a>|*(b}UQU67xX5 zl^4JY)^@D@KgRv@|1quq(}2vR$CH1H3Ez!n)VE#ABpg6FmD9^g{;(G<4?qT}4gtf` z#kE18at&H$uE?DIOeqeBH=Y6ha0f7#!TzDr8eD8~g)V9a!0-jwWGj8nYdzHXbSn{`(NqdI99b=^u%r zpr8m|b$~H|IR>9D3C5>olsn)Q`3+Vnz>v;*Mq04Dr$B(d8pY%E88w1c89C#F1##a{ zBIX$=Q&y#On5?D|3}eq`-eB)iYHb1vm2rcr#GW9iy2rM zhksmUw^QtRXAI8+?gplz8Hc*Y1V`9EEv#{b)ote|O}(aJ%wBb=CJq|;t@BNPt-QBx zuJ8K^Tgw!c>KZ&xZGQ1S_s;CrSEMi6?kMw0SjyzyAFnhJI4K7Iz*QpEBd$a%_x827 znp#g?Upci4a`($R+`9SQMSokocp7DH)nQS#XaaEYuHiGyz-H-}o-9R5(AdIw0m%%U zI06WIl-H+MBsy!B|6&LOk^CA%nr?7D2_F%Eg4!~D8+ja^I8f)?xNzv;2rjXk9?Re( zZef_2sTfWnRbc!wZSS($2+n$ikWh4t5NtF`M@OaFM?PIQ;q0_dCZ=-%3U(AgeGihT0i+}maUcw@n3 zX3Wd=A925F{+Pk?oj~)krvHkR&E1g-*cT`8g;DzL7BbUaeGmgZ2R#c8}o6d0|4XiKZodk+W?F?VmXxbKnVw5Sa-A2Pum#9M56Rs25flRhEh3az@;(Yu^X^C5+J^N2o4 z&OYV@g|vV*)B*Z5PB6a-DbC;^=Jl8L*D4k44*t#|o-dP_MwsFZ?gyovf8~ogTkuf? zrBF3HFN!(ul!BKF(qOV#(t5uT>R_^vyrUUK@b-{u@^*wdRdbCdUGrsB^!AW^^0s^p zNE1H{;!jFD_k{w`b8cGgtWL9Yep>BK2>I>q4A8ac73X= zCeVOZZ4-THamVbuaIyD!(#iOCIVAgoO55z;Eue&PaEnP6PzG?Q+2gqG+?DGUYTw^W z(I#zz!Ds+)1^9Q7Ps0q(8ngKQ0`o?q`c0Ri`3TR@Xz<%b%H2{KmNx+U9P2_+}9J=2~UseI1$@JDsOS3}8m_j={N zGXa4gRwxiWjp`NeYT)w;iYBDh{s$p}1kbL+L&b1+t^C|hEzuTS?SS`7^Kx5uX)tU&j^-&#`yGw+aD2z!&m$@{Kat=9K=kT6vBlc%UX!XVP5zpN2@xs~ z3ojF8TYbczcRL6*ClwJyR2Jh1l1(#3vB#q+mL$FG;!^qjpZ0ssFU7?;?5sdjWYD}2 zN*@{s;DHr^@6)CFd!1jo`o(|R;QwjS{--5~z@HdEz?P_fAy=r=Wf1Z|CD#9x6reKH z=Ul9=P7bt!tNMRdWb%HEit(HGOgTnO z>wOGb=YKx^PaAEDtRsvrOxlMg?S#jq)2aU3|C84G0fQF%r$U{8+BRkuI}x1|3rc%7 zIJ;|l8x4T1>~E^FGX(s+hbqC1;ZJ}RF-eESl)Kd(*63>PWwey4$-RpJ81?{I-LCV_iE zG!zhp7(M0g0ae7dIdqIBYRwnWFVCp-05oh10KF{*A=3qH_cEWrpCLcNgVq0&o^1mb zctB;9(UZwG@cdpUktKX50U*S2CIzrDUOU}D8I$9KJo>j&t0QT5{&P(ZOSJBFL@#pc2Nlm?>$?t#fjMlW1 zEBAUvv>)t`-`$d$X!iD@G(&Y9EW|A7JadXF-+tWp7PyforyFZhk9o{R674;ry}GHt z&%OVcnlg94(Oj11z6Oh3uJQN0#(dhx$4%pNXZUe{wZqYVlvEwAC9vunpMW!?uf(5H zLhJQ76z(0$pfx90bNy3kC|I3vJ3JEgN-kz`gvot7aqe)0lyBo#$YUyD`%qD#EoAkU zD0|g`%-Jl!mi6<)Z1RIiq%x%`(DIR) zqll{5tvkC1#D}HF+xmDS2W{qMC5&pF97?u%ItL_0rXol%J6}nO^hh)6@v6noRZV*B z{RzECyGUo{ydWw2^rxQ+xAGtw#-1KNclV*!rk&oeN1FE{{b#Sk{407RmxMb^(t}=` zu=UO`dZXHO8l&1+koto(fZj*~*&pF`ug&gougxrDug!1Hi*zXvd9~Mp=u_C--P;Zm zS!yHo?{}CI7#Hd2ptkGI*PmjOhum|Mho1~buGi+qsnL}kI3 zD$;*;i$DFbd~-n>%D>5z20Hqe+FxXor$7QBq}S#x-X;(Jn`rxEY-$d=9?^(h=wyOz znug#M@H`Dgd&RM;0`M(!x+e7L0?pj_l&wJc;Oz9jsO{dGc0j!QP*puGiHKKS1cxM*gNF8r;yz40{@w6&_~6aB7drdiSL zGeaoc<>31UB_N9Jq4P1Nl`7Mzvuh?4Cp4_QG-6Q$fA4buPZyzCEZ@z}K2{jeG^P^0DHv-*h0*%|I|Dzp zvdM}q|EKSl^Dmq6kD7gD8uxx+w2u;vozRa+e1*=?I)~q}z!7}q*Qq2cYTtRXouCWgF^D~r_FFtFr}Dg!|}>J-o%<9sMeWA9PC<2 zsY)H>{lB>D=i^J%XXN9@+VDv;K_F`XsQyY$2ANFvBw_wdP7i!lg6byr{kMEw}X`Xqi5kCYLfj zCbQiBp<T)2hs|= z&Jp;gdM3d^aU5-wd4+_Az89AE^;n2eqMYrt)Bg%ga>O7QBW3yMUgZe4THrxIpF?Ce zK(BHX?(F74M4v;>2&}OQQWRgf?h5(j7VVfDXGmXnthb?r<<>S)V-xyOaNf0tocwr^ zI@xj#TRGHFqTuhb;Jak3g2UdqV(!*L@N5KNr{&W&bMfam7pZlVaKM7L^Cf$yV8h6B z2M&>s{!_NE^8?`g570z2=JVU7hSxscB6zF9u@lu;k&&~T)aZ#%7Zd2bE0Nn@q)?c= zc6OYU&;MNAj{US$r_N^I-HUe9*7#m)dHlAuT2!!Y_UCzarakcr3lH@|f>!?>Huvfe z;0xXp_zPes8~{^kgs!^B=K-f&oEfwGFv?!-8s%eyLB)o${K8`&clj?J+0L)(fwn=7FHeF2+3uZ2jeGAl;+@Wxj_OD84sUfV9aL^T>rFBa zZbAwFYQ|dAoKSdgO-mQGERuGRmh#?P2M=B~_ghcZ8!8z6#jjuZ6g0?QRx=^=E1^UR zCX{QjcBWWPLXNNZ-T7t~YLCBY@W=dCyv9hz^x)|D&V=Pvb2ch@(k0S;vw!p3zn)81Oq|BSyx zJZY-sAF^^vJ*&y>ds0u~J)1;K*qq_0pOGn@T-npBk0@#9R^A1-tqt2~R6m+{1GZA+ z6L9yb&Nn62wxbe-UDQRvT{h#3--E~1zb;Jws`;EOFQtrOsadX7s;oU17#O?jKLy`M zIt{%sGbqn{Z$1)mB?T2&U$3HG5TnhOrp*@ngr5Ip&ejQqv+s9?5h6MgxQy9)*>n_z z*S_2`h?E(_v5I{FoGw5`4NOi|{D*g#utV`Vzf{5;qh@R86FeP@vfgpre;=CTGcvpXJ8M=ATje}WzMHv zb=JS$6?3!;6nJBh0f~7z_db zEZ?%QCPW%TofAw&>aNGy4R$OK5_p&Ck;?S~9qToVi+s~;7nypzn6Fi)dfzA)<0ce| zd3L)*0dDaFvNGR$jP>+p*w>Byb!pRzfZ=7C%GAt*seZnv@6s@t@mdzjR(Q~ zNfJnJD~=1<60EJ+2I{fOT3UrAD%uV_+rYIqE>AVz+D-$%oyM0qc?sK)X+y34Z}pAM ze04RvSlMhWUn*?6_yNDd>6f(HRwRXU;+AK^-s-UPRBWug(U~7TpMJ9@r}^wg`nVBe zJ<+!S8-Wd)wqz&Kxt2L5uMCtkr`41Hza=;;x;?eW)^{3V{S9T`{jXLFT9#{mCA8(2 zv3@wf5lL->!{BRIOKRYJBj+^$SI>j51&!7b(i*onGbm#k?4T4=U2T5Fej$cZuH=n_ zAUM!TVqqAYIrQwDIHOChh~Y&K#f;g4bMB*p;-mF*sl=l=Vq zF(8p%FHuH@o}R8C#q)`eVZY(75}a|;Rhulh}O$YCN&=7WB1Q`IbE6@QwX_c0l7C6ywHy7W$jvsglK=1>oYK zFH)-e;WA^s^o?5fj*4%^k@j1(nYAZd1 zbC+CxZ(BBzx67(OO#Nr^GT7XT+*#G``MM}HZq2b64?#hxu2- zNyU8>p9L>Pk6|}G&xcx-qy-|!%8bNH!#6`jiX*vElUC6LUW&X!M3`?G%(z#?i1Te2 zT#^h~hKPhK)cW^TkSwBjaX`%+s9}4Z#6c1UbEIQ5`<4{IDZPa}M08!F+HZvlGVVkS zX5T2`kB-TVW_9UcZ7$mZm3e%b(C!LBPCU1r_}r>8WsJTEfb8@I$kR{Mv<6^=th}i^ zuAt(AxT6pwwtgIVHBX)wG9q}l*7Ng|bmyto)qg_K`}v6<5$l!URupgCtfGBYC*AClT6&+%E@;G-tmvGUQqG6OPV%3aor%Uid! zpObf}9B^#-nzft)BPsxe-9cYX189^Eit><5>?TSY{~xqPz<)btaSFb(NZ@JiMeSNS zg@yqq*T&IfcTlM`;E14KHA4)t8)UXJno@S_W?%%w=gZX|piQCm^d25nPog zFRKW|k8%aPn7w5fJ7ZhEF(jvVaHHT4uW=Da-$TOYr^gUeT0=$| z!({m=TICpHwea8S8mZwiLgq{^J-1cJ#xkSG12u~D=Pi;aHXg-_Em4a)t3g@$5*)ZF z5n7#bBp|8x_b<3Tm<1rpOUFZPH!@upwSC9g4lb&TTe<|Ef8HDKfb%uz#zcSFo<`VG z9zCWb<#=bX|37rSV|1L|_dgsoO{2zYY+DT{c4J%9pivt(n%HP;+qTs-wr$&*`Op3P zzIa|eYt5d0ZGHAR*Q}X2>zwQCV*_-Ux>45e_t<2J(b~utdO5`#+}+bFoc2kdabI)(a#>jz8SR0@2!trYHj=4}*mzbxAh ze{>L&UnSFH5<&dJc<$Q5c+O{_CeQ(n-)TPzy;;gw4>x`Z3CDm$?*MMt$^NwYp`Uf6 zqJODL;p2VhBP0GZh-jQS7{aSt5J=j1MRLoTs6-ZY8v_!QMDjFmnECBQS2)^X51p#a z3b!^;C|u2m_If1MOuTxc^^!a#OZ<0L?iEv(&7jH>bFF%)d_A2AILPl_8+;Ua{<7&g z4tf$Xw$(Jt@(#XyeUL9S{>8~Aa$7J1x|$vFE%*R5k&VMzrIRPTvofZs3W&ja49P*Y zo(dql8K)YV+FZHm=LKsM`t(GRnU;^ntT`r;@tkV=+~u+TzCD8P0RANeDlR@g*HU$> z?4+~oVhdEO{?!C2%h{IEhZQH&?^YKvE*PpOBFUI1hBRWkZG@=Q5wAX%9-=eN&hb4R8{2Eu zC41+M>D)R159SsVbtfm(ko7G!+SM8M)V%A$E)K5~W)b2y5J(u^aJ`G-SXdj6-aV?4 z0gI%$`#Wkn2HVvr-D^KTnCIg2hHuBP$MyDEeMF)9!W?N+!(KOCH;slT{Z)rx-^8>a zAZYqCp0v=21Mi8dPkn66O?s41!X_##eK#SpiVqjHF9NqOf}}5khA)DJFM@Lp@DnTw zJuHeWEQ%E@N+>K!2`tJ#Sd=4JluzO^gDM~J{(Qij`hbUlfTx0h_Xh!QDkzBpl{p8M zMdAww(aAeXC_G9DJjy?Klp}bQPaja|KcL7C5L$h{2O~&QUWXTNbo(mS_$t--s?_+Z zHK3N7z*brjn)Slj^uqn>h4biz^Y4WV?}dx&g-h#&%j<xHYEmf&;_KnM&#NXQ4u zBBEHyyrSJ_e4GnF*b6|o3qU}J!Rvt0x%yzzOXQ0X0~P+;>}=92=!<|3i`Vf%=L*N9 zS3d_x3eW70Rs*PN^rHA7D1X4~z|^^tB?vY%Dy1jBH}Rwm4SaUHMmL8P zpj03ckzv1?XzKJRgY9v{AyLipr3~hDT9HpN92hr{w^uz*7HqYQw`%5#ZXRzlYZu)% z{r7D0hv%esvI(%m{wTzOIlUQr&KgI^>NuhH_%(a;2guVP+45DDp_YJ8c$V&|^1(D>3^ zJ;~R#WN7y*uW{VTn5prYu8OzXWq$5E6R3`mQxJLF^0KKh^ao`_hU3cAh`XlM`l*vd z`p2OUm#z*(9k;g{WX+anBCRs>u9nmiuPplWpI@_UpR06AMVdsG5BP57G~LA-p6ONs zeH&o(P3Ex0r+Qv^^W8cyh_BjN1{y;!PIMn5>GVQ4ShAJy+1 z?D=D6zS60KqEVa?utfW~@O&do9~~34QTOPp38tnwYx04&ObiThL_~G=<*Px{~FraerfAYr!{W1QWHM7rfKs+ZbtJHka)WHmd6$3qCgknFa z{WH}5`#<}KeLN>h`sNg>-rs)w*idaQRI7vl)iOi1PGYTt#HhoSo7V)yXd}!Awo{xT z62DIQggy>I8IjOOM9E)2ut@``C|eteV|poK*F4A|kgXJ1dzOB4M-?bSy!a?FE;O(df`%A80VVWb0rC`A8+d#t=>h#Ym-lnK`l&Ce#@DU)!NZVrnQd zwW>XbOc)edq2aJ3n&IoW2G9SPa>JzxiMnGR)RjsKio*bPRe`z|heKVppp9tFgWexJ zC|VtT^Oyfzo2*j%rJ(nbRqwzZ`hgurB=MU-{gCq4^u$~gdkOQ`(&V6=A%E?Ql#3!t zrcp z56>W)q>tU&BTst`Gf&a4{~(`uUyL^)%Y3FIEeX)U5w*f_^*8=YNaO3~YFd_&>P0sw zbZY=axCt$xZ(f-c{tE&x4&9#|c?mjuN{~xx2>%IzhmV|iHU9eu_$<&(SF9cS>VT60 z?zX*z;GDMHO>YyHmeK$|Tr@!>K6Tl>)AelXLh6NfA@eP#l^bL%Z)Y5rCuT9Y{67-4 zdD}_^m~sVkDlsGo?S(A7Q?`DpxGYHJJtvSxpg+<1uVeIsaqt3XwV^_Sd!{ijM}&Q{?p2K*C<7e5lVCm8;r z6|d{I1;1J32uwhGZJyE>W4Z#6F0gA|obOVoRl@c!cP!Ib^{(`9Twi8T*Jw)m<)pCy zKPulx1A~$bJBn7L0E@?psMA7ivR&sJq!5r~NLu3<*3$=sLrI42rf02j9EJ+;D9N9h z4Mf6kl3r*A*2gCdNzkp|=y)k&ry-IGaT+)EXNIpJ=oBL%j;-?pgh?3!+J)yltXWw< z_4bf?13grIATKL>1z=c6PW_ZoA>tWaHw`vrP{+aiHYN8{*_(>T7h;32N>Cf%bIKgo@S);JSi!nGfNfbLof z^EwFgdJyv(t)>yh9UHa$MH+{d$r6%^u*{=rk&E@ZD0Mn|0V(C9e+79&y(>GX?fv@s z7qHzu87JV)v$64fx2~4#_OjG|kv8lm$ltRB-4oO`#FQB+e7M&8gAAQp+9ER6If*Rt zWni`NpQ%h#@YRA^f_(%>+XW2+?OBcR!Rchd5=#16^EpVr?Y&}t<466#W^KRO<@=IR z*W?Y3r-41krrQO#d3WyZ^Han2U$8LOb0GMmd7s0iY}oo`9bHxi3mWpmDq<(6SljK; z_lI7li|zQ0MZ$Q?n8T2cg}JYH7a|?k!w{~G`EnLO#g@eGm6pp>0;U6jI;+=U40i>4 z^xKHcm-X-I-gjMW1swReGKSAhbM;&p!Ny@|TFt zg>6Tj>xE#}zxe7n%r5E}KzmKN?Gi~S<8gJ+W=uFvH2;=RjZRRXbwUdyd+if(@qlNr zycK*{!>pqgYMKxkcNDMNV{JI(S!LWuAFn$!7Mf6wVc=AP?BRB?TZGp-F2=u&0pcU; zwI;SMpKC&XK4fsbb*|3+<;S)^ywrawul>vSVOhBO?fa$oYq18;uuUG5gSkvEU2Q$N zS%}zxQa~sPBBmfZr7OAQnPlivEJiIC$EyG5pwLWYOhG(KS60b0lhCDMjM{t(GfRnq z&qEjjB$Tc~l4o9_OR$)=*py~6k^|5xtRz^Nf;3d$j#5IG_%Uk(>aGz57${vef~Ryb zYx_9^l_Ek(k|~^xB+q(6m%=b>si@2>r3XGog=T)i6y&9JwU<2Gf~HATm5{Oglu3dq zC?s)o7rJy!D1Im-2`?&1B`PT)Drqh%86YZ|ZxV$T>=*jiFZ82-sI-4*uz%=Z|Im;9 z7?B?_(LyK)&?&!QNU&2%a#Krk(@JvFOL8+xax+VEvr2NaOLB8ca&t>^^Gb4m4K{HO zwQ@)8eZrWAA@s+j%%h;p9Sl??1Zz|u+o%KW5wlSwh`5*X1z z2C3e1NN`U)V9CvDOF`dTK=!-w>gwWF{`6uMh0{SNVO8T@HFp(+2)v(-FO)`^-T%vl zDF1CN?AI)ZVZrwRfzfgEfC9YC(@~0Zfm;?$z({V_{qvMDd{E7#&z?RBM9k`afun0& zK_*CFt9#%_k<+i$SF*#^s3!w^0I=S<+%$V_dty*+==g3*Qz%HMT==NB?vdc5NY~~RUEmWp z_Gb5?Ges^)DEn&FgTMAwlHqz!;wERSYbHm#ZeI{&%Z6rDt0L%i&As_7~ZVJ0np`ZI0VagkfDR>sw@ofN_g74I~*3hLX4>M(v_n}&GX?H4- zU0JqXgGauNj@l^p{nJ^m1@-3P}2vIO#TpW%<7R8aK3Wn~84+N~*@&qD_4_J*C^6F>Gxq(_$B zrxA&8oAVCm<3XG>7^n5A#Sq>*p#Jkq4HCOEDo3q=Db8ACf|cPo|3HZ0AqERTcq;0g z{WGn^tJsMD>Ka8FI;n~H87|%*0Wo!PNhdQWPZPCJE3Hr~y-+KoP%AT3pc<8xO{kT9 zsMW7fE7wpfk5DV0P%HmXtKd+p@KCGhP^-95t0dbz97Sx*acs*?lxeJ#X>7L_y@9E2=-jC^!d2&>Fx>R}ATrNll;~0t=r3&m$!6qk) zK>ybG5d-o+BZ}K{z%&H4R8^tUv0k{+F^nvY@4kv2jr<52mDZ38_HQ92pIe| z4hYrKMR5x_Nf;oagaw@1@&%kAELmVUR;gmUD5F!HBxC#of|LM7qTH)LW#yld45dO9 zKO!!A)l$!C)KXEPnSVkvGy7?L7ldZw^o(?tWUMb1WxV|X z6{#45knbcJZ~35{TZ*xsB2nB!kFK8=>};`a+W^ z_Ym$Z&*+5V=@l?zL;g1PC+Cdrc>5V}n*gVdW(V^V_Y|U60m+#IRSZ5%HtrqldCI*n zhSEzEba8{RPrD2Bf7u+MsH|)*gP&WMH_Ra)X~4x=t03wmFl$Pd{dL^KqIA+q_jH0y zmaUTJSvT$KrtL8MBF3N*0z^jY80WQm{DCaddO~?}tZ}cNyOzK$DqC(^7bBSksLZm4$+a zcd0AP7b*#MSv@gXE2DjNJ7)D@Uy%ekQ!YS4?vA65u* zb2G?lWx-m1XsxXg7{nx)WZxSb{4LC?LxR6C$!bJMmOkgsz2ziQ7aky1Qvc372ytN1 zwxE>mT0H!6U8m1ql-@NVQ}_Z978G=o){6dp)0hoYQUT`s2d;Yo=;7xcfzVGti#bWq z5+X_MZGnzezd@ioVy3rc>#Vhbj3RphTFl^Q*pq|WOjGyEg3s2;L!R+Gm?iVLZ7INsjGix4E!&%YOD2C1HAZI8+eIyc?JRv46v9 zq2TcnFW!=^=JW5$=C615_47{&(jDcCCZ{#WT{~A=>y->tT{!AsYbz4#CAR3dvUCsU zbT*SGn;cT7YZ80g+6vOgVF7|FrIMjby-)pfTK5Bqy6i&Bl|=|B19I!eO-0{R1{=2M zDvrYf2Jgs<^||`mBM4=r^~Yh+q;CJNR;YJ@rN%sL5(HK^V1iS1TqeE~1}C#OUM(Tn zr)?WI(zr39(q)(3hKLOA8+VvwlHS&ReUFc+45CmD4QhAQw*>PWW;Fh4yw5_HiKssm zvg&kOwcE)+I$n59YQ#F-TJn8Wn|qNXnMf`F^jNWn{V~yDQ@k}CI zY#T0Rn-)oqB;mPF7052n=!6wXjc8%WEl>RC^S!{9s{|TL#IV|`Aw)bDop5d;bA1Jn zQfq=I8SI}7EwF9>8Xf}ajjcobg@X9){JR|I(x2kOQ+N=@x@^zRAj#{)|#R2D7OGZ$VV3dO!%i@(BPi zG|sQGfF1hEsN;{M;|pp1e8hl3>b$r;JK=47NAubx=`o*RUUztJ zT+p=kW*n#n>8*c>aUztB$bdh-$-#TOnYG-*C9|s&(SIv**>^2>nO`eh2)HlOMF(-| zc<%+_E#&{$nIB4$EIUVcRv~NV*3Krtveb0m9nT~3K6UR$;#7{}UYD2n5cT+^$T`D} zxdFtr2qMXzZ}6R%#6X3?jDo>L^V1B6H#bS#=^@9MrpK6O$C&<#F)fNQEsHU&f-$YL z6iG!8nWuw0SVq44t1%LtfE{w*YL*P-nR z{p;ILmAu^H=P`QX9BGDYvhXymxrV%=&g?9>Z9mrpg(sOnbxF_kKqdN`J>+BI9|jO9 zBGma3Nbamm0GNyZrMhXQ`%;6sHu-zn3GBNAd%`M&Mh(Ao0OY9#K@_xiw{F+Y_T7K4-pH|Lf9I%cgA-Ha}zm- zf|2?StZ$W4r*vMmM?t=g5k^newo}0l2P_^OZ?`%4=oZW?PrG|L-%dZWta#lWOX=e| z8{W+**x_|DqoR5Mhih^w|FVizAB^kYrSZ}q-6x!jt$qRHGzeEYPCsOyiwTMsv8-Hg zqer-c?+vEXSEE^1Tn_rB+LP^c8xF^>BQ_Wf>Z~r?BqAQNh(M34`L{vdkLTDMVT26- z?dV2tX#9ux+HI?`z=Q(`u}jezLpGzBLlcr{_1{M?d!ed z-q@X8`n@SS9#k{jrFHT6Bt$!n4tqX>UsJACKHKO0VQtrdJRQe^%U>kNd#QV7w~kaN zXu$9EOIOt8NRdkdDPT%q11YF7AEuO?vX-2(m7KDdoN~BEc*oZY zBi0rp))6DtS!WoBoK%vUELc=DR8~AxRua`O5+n8xMr;B`Yzjtf21aZSMr;8_Yzane z1x9QQMr;E{Yzszg2S#iU0bCdbWh}=BP6S;tV>U!k(jsD5V{ zu~!(ecNnox7_n~{u`tUoIDc~LL<-&K!euJm=SD=I0H}eBj~=PBkWsnOMje}?H@Cu5 zz)R?_SCI6N#3wf87Z5m_$eex1h3XEXbT2&003LU#i&l5hf@CY3^qtK}5#(s#=0nd; zkoF)+{G%4ERJ|vou>`9Mnh5jQN0K}X4gaj+oRbG%y*)B=FG?WqrS|QpyTdDjfoV2j z7xuk)R*GO`9CDiY0?L{LWpFvd$si9kdPvBMgUbi+qsIHPH)e(QN}7UBWDO#^y_*8P zhR&^jFXW&J3ppq+P0*;7I+0yiJU7b_0~?FVH7FO<))JjT|U@5Y*uRvHGy2c9zP zCh9a6HfzN=<8rDkew|+7G zI_s}i%DnF%?M5(G5}}IK{}jf&Xoz--vyKYXamMKK)ZI5UamL43!_~1+k__9^j+DG9 zua~@G(x80SG^TvU{l^$)noa(U%lhXHId@z*7gSS?_VQ`C%Bi80?hZH3u-!^s`G||U z-S$73B+gKfB;8}?AZ{r})^$8V&NVFhoA3~(csJ#;RJwv0S)5|zSQnn!0F{_|28?PI5~W)_~uYxq-_r#!YDn1Tnt|WrhfMCQVhA!>qGEY z!&fb{lbbF#Z9$KV8pp!-9(oF!f2hd}u_;MB*Ox>9Fw&dxvcYh$p^ZOeP!cItGox(hO!Ac&i@%5(SQK zY&upEbjtD_z!Yf@%rgr~tT zB{%2Qnh&7s63Ag2WEXYFg&ld|(F;v2sCKp-zjn!b(6U|0n-?&Ykpp76>|de|Zl$mp zV$31KMq+&Q^djB&i=d>B>Tj#K)HEfNCbJf2`%QjZnZu^d^a1as<;SOron3m7=$+lU zxELpr+ju@1=7b}FLKA;+uu=ZZGsMcU^%>NO1+AU;u008Sf8rQ&G3SMVaCu;2x*u@d z%sUq6JDq`n=8mN*)*71 zUHN`hWp<-)ECL^WV9Qnj{H!IRa@uI}CWqd~w*%MxnUdLOs0vJ(scjVm zl~Xw?iU(C3@4D&t2-5_qp$GvMpQOV=gNJu)dcR^$ixT?Ba(ID__8 z+w}Yi1UnvXj&4v3+99P9W#KMOrqOB=T@-3=N`W`B79 zGPuGGAtn%F1uRjwMe@x5dDj|p;Yt{``^aKi2Y6j_Yh;8>cy-^p^dPyQQiEV`{-EgiJjN56n{A!0i> zIiJO)M0(2dK{j@8PB$m~f`L53Uq*je(hLsHsEJnn*3P|VoP3hyN)&f)S~UP zT`X(b&xgGa@iIv;7MjxDc)AeyJ=^wh^L*NgFY0 zzN1KU)oAfsv)zxUa=X<+HrrK@2+(u)J%mS4Os{dO$#c0pO?b4Q z+X0t#{%o9irbF1H=(}-tR+F3AU+ag>hopm^qenZ$iMe``j{3r)jLA5z-jfP=_g_CV zz7$I&die4wbfW%}*OfT)<_BrguFW_qyraISy)HHZ5+gdA6YaCbhAa_&|CKo&8cPK>KRx6IP? zWEVkjGiX!0KTKnGw2B^XD#+I_YagKM#SyuM-gA_RNagk=a)rudfD|U*g*$RC(*;z~g8p8?}u473nAFLu(nCpKB?>ul4|U`Z?xuLL)J+!Ho++>-=N+|y6g=^oh~ zXlb9|zXiesMDZ&oj*2z`)3I|^4s@k)4R;SB&F~8Ntp;g7P-5LTxB-n0f+|mK`w8_{x#+mdAI}=QURPJegMOMQ zeeWS`Vq{_3S%JZhmi=xWQq{^%0dIMIQ2a$)XYkf+< zg&VZHo=J!!O6Ydj!>Gf0&$gTxmYuu~1TSjiKoF4ipnndtkgC<{F-HUS_iQ}%mPe87 zza%eIVS*iQUyF|}iKIb`2Nz_8?Y>hVJOW`oF_b+t@rW@2< z4(rp-yddR|xpX+v?_u}nls{4I zVBFrNM}kOCb(695kGtz$90$AG>=VH7=1yzh>vJXOVR~+1Zf8fd4_VdtugnhQf4|w& zK4h*Yo+e*~5M<+_nlH+jiN8&*K_ke{3aqt8h*V$;8;+Uq zyFU8))9N$&u8N=gV#)GO&6(=X)e(}JyjsQAJgJPYb^0k^Z(>|`j-b!p{Cx^D_dyS; z-T(1(trTRUSPH*8Ovj$&g|PdNltAKh&(lw(jJZPu0zTI;>t-R;-Jow76?$~v8+=5^ zo?LTNo*mMxL{ey!p51*@8bx%+HnNe;#gsV?pFa@5e+lb*bKC-x_PpNv-p=erebhObYL=g|$ zC!r0OgjhV{i06>Ut=~$;t?yNllf<4C!J=A+Sv(q24qw<)4%>IiLLWPaQYw^~UO}?D z)a|-WH2JJ?>i{R}cDGRK_82G!?8&-zi+@Uxu6vb>ws=H_k^&TfpLqCU2#S1mYT_(Y z=h-A%=a~Q{f7v=gE$U?wy128?R38|rm&fI~IpwLBzb&)NMk%_&3&)*R^~aup1F4qZ zab@b#UAUxEsoN*RsN0RVWL+<@hbhkE&MtbPy+ekR?WJz-rjvrxP^=RarC#<9_cG1_#;sTXq;5xt z!X-mFUpRGpGnB}%p{Z!%&a|xBksAzIv-aCEa9vM8Eu+KS^JA!vz!v~q)#%ZGgY0dd zYqHz59l#3nPIC4J5I_KsZ?Wyn)}LR9=Q=D^4zg>=%BoTIeo>cu7u#uHKzF^=Jn`7@ zz5Q#y8;FSaeDcfSy&q^9Yj_w}&7E(cn-Kit&!g8Oxx?+7x&Cs+uc^scW_ft#fIJ@8 zT9S?_@v1U$bRG1FE*KQEX?znY<`+2TFbW-Ps3OAbla|ypraZWSGoo_L%=4VNY4tbVR*H3byG$Z#a6YJ)I%XbHZ3SUl!_vW4-AxBEylhT` z!w%%|)Oo$INv%K<4HR`=;OaW?E(>_mXNcz9<&cvRSRWS(yI){Sman>quuuq{KJ- zcGywz`&zW=`))fOclrX_v~AOPgPm^9d`H88eY@Iv@p+Vt`g-v#@w~TyVEBnhr}K2@ z#cTzr^kUX*M%HEA!NP;KIa`+ z*jTQXip3o`r#CgtzJnX{UVK3RBGMk&7HYkhc2&niK*FW`v!YWO&tSyyMID(^bnPzoyCh8y;iSQ?pmjL7P{3e2dqY=%_S@K7k)yc4=nn zURy-uu4Q_bnQ`%?npc88jpvfaZFhX>bPhQW3=D~?Y7}J_ms%a)f1>x7Zkct1`wbt3 zZ%PlkY-!f~v(8F({d~p(K1Q2<66(Jp_5DGAxosExkDvJx);(lj80N92196K?3lsTk zsAeD>sTpprZ-kB%{T5Z(r@4 zdURy?2Hh&DsnV=)ZCpLtW@uk%VZ+wfg<$U5^4PAXn(B8U1(c^cE1z{yZ9)g-@BTXY z44t;WKy@}hm=M)2LYN&XGhw(fihT_4sP1gYK8=p6>i(kr`JIoRP0-uyVlQmCC_`@% zgnJAM5Gy`{=-ENM)F%r3ZL6;#c~m*?>d4HxJbUqs=a&m$x4w|_T89_L1xP+6E~J}x z6;#8pnqfXM44p`@>3nyYZu@l)K#d&%S7+TpuC0zl^LNvLs|MrX>LJU?KhXgGWWe>5 z^zJZ6wcH|Y_iW=vGgb3#gZx?DC0p(3!sUSdpyl9&GBKX#n78^_YPZ~6Q6(1DUotq$ z!`~Cwt(gpRh6sw%K4qRCLs8?KU#pg%x^ws2 z8nh$yZ!SrWP2ET?V@P$`3})NVVyp_77JsNLz}b999}sYPe|taqFjZQn?eXztMwi63 z;sq&kh@R*|_ZJ+^^REV+s_&62bHC9umS>*T4;z(#914StEhc)0mAZ(}vc}W5>Kx)% z?R&Kiv`eO_OGx|uxbav&7WMYE_Xz1M;iUXaY(P$nbhD1(yhrc(u+A;hcuGQliZ zqJTVVy@yM0```P6t~Mn;%sg+R7&d2Nx8aguwgGAtjyT-vr?@t0 zt!D91Fn8TX1V+_#K|}KVzm^o2r}Pr?ouS9nfar!fOoPP7hTiv=P|Sl?H_qrceVUS| zPM_Vkqe<)nH*N(#c_%rEukFF)Uao2V>JGdW_d1bk1%*h6i+50?Uv1J;H*GS}f$yq> zN|b7aj*dWkg54=>=o@#T8P4vNf8MOBGUDday3s$RJE^WLvP3k8mv;ET!jebnAds3k zZoR-t8>mHxQSlCW9&!;t!ny-&qm_KLD`D+pMQ5V#^s`TzNk(IQAE^BFHf8&6kA+4)f)Yut2L(hD=%%@ZC%Ar-U)$+Ua5hHR8WvcD2PESv|`0W z=Wp{(v@-<2`MTjS_G9!lU^s)1VbSxZ8%+Sd3i8E?q` za!ytmwO|hJHg^iYvo%Oj(q8F4SOM_SjYpgTIOVGcKyx;)_&7z%nF;zP!zJ$ze3E|k z+C}eFXqe%ULorCT-)`{GY4quV)1vK~+&yICA5)h;ov{8}1N1aB9h!4&+y9%QGG1P| zvtq8!1Zv?ET_k6xPYu0zAqI4?LQ5icMZ~;`_i&xy`-J20dd2s@ANKR~MIc75{dHR$ zPG2}~8E?w%OG5b8nvC~-m<>hm8do7!MHMa7F1ah`3&tftk%#=Vj}i~L7K?K=Y^<&% z5BbX-vo`#W381pbphNxwugv%>^@Im>qUmLB>tW&lXVq4#FnSxU74mKHcN%P2_{0kV zQ;#^3LB#gL#qdw?YZZ>?l<2v{53Q)o$2-)w29DQpljPTM8|vu32-U*X%crM=O#ZI7 zaNQtke{2j{>I)idl4*b_BhLG6gNo`MdK@a#6O3d(Ew`_&PA?)kvDOu=YzXiP=DNlo zT~tKls+U~7Hw29s*XznOCN`1)j-nPx8N~MG?7Kf8MGMMkV9uG zEod-kBZ}Z=psThYXXT0F=uSV0<}l-+%Hm*#;b0CYxG0coNEQYb)`^!@{PFnNivaZP zXoH>cL;(uCbz7*X4Q6ObRI8>!ilZ3YA@LhI5gKm*^cT=Q37^mc^ryCph-uSZ#t0a( zZ@a+$`~H1-=OZLLl}&piBz-XP#W8BI^Ab$nE$kuG>|jFndvlKcICIGhEV}x0$8VD? z5&a#E1bP~_zKLx{yp^#l4l@7Ie(QSevi%f*_Kf{D+czxNeO0`3fhl6cCHivo_Ei_x zOH%FKEllNdXk2Zp)GHSpt)(^v>f77e(dp`yfQ*D!yPCh+_~6bxTvs}pAgd$}I4_?3 zKAr(Yq+Gcy+?O5_OUYL)%l0?6tnoy1&`6Aye0XFWqru!vd^N%S!fA8IuUgHyiGY^& ztYtDc)(qGGy$hFs?>4Nb$Iv@}#5-5lV6aQY{DC0M*DL;-_?&S*L|9tQLqfM5e+uC`gjuoMN3UYRl{F5 zC9lbbb>2FQjPlhWY;Cshe4Qflx{%uf$e~{TGs1)mq&fuVn_m_{$}uU#x&UXqq4XDZ<;=pL9+ zj8t9CZuHJ|wQ}$C>Zv+@#}$_3;?DN1njU<}<*5(itFb!3@z;!3Uy}c2?6~^RCt7O) zZ>?u$xlfgsrN+>8`-n5KHx?7%VEZm;qbsbvpx#SI@jyo3p&)-w?S9Hy>61v>&| z9fE`js-y*)q{U~+zohQu0b8)leO+QESdtdlk`_3U7PyiYc#;~xqq!4&Lh z>LxwBW4ddjvT+g%rW2Ix=uUWk-YH)2AI&BxYcQZfSW5jT+kp%z6Y2wII3^BD%oMqw zc(|6TKk+(;bURw52?kL*MwS&DeE0&YGyiO5XnJsHWr)8NfEhYeI|(_?ax-Mr{*{@X?4 zYfrcT2&~_Ix$8#+KS#^`3O&+}7fKi!NI6OL!LT+n+*S#(CRX*1dZv*mjq=8+B#kof zKue;KpOI=IjQA15SoL+?4BbSedg0g#MC<$c-`YqbVdZ&#@ZmvrsJFAKv1_27>v>v>=}WQ*RisZ(!2D<}z& zdIKXsTmF@JPbcR-L@@z!>!<2-Eoz)}3D5GDL^Yf5PsG7<4>h)w=`NQ%1C z?HFxLL$`>Yb`v;6M6dh|vLgrC-27>taM|+N$6h+!j`{Fpm*(LGR4gaf{y@ZVc*5n` z-)h>?W>V6rdeZH+yB$|6_e-I))Tg>u_qF-y;9GbU%Spw){u}QmbkRYmYkyeL{AiWX zYiXj@wG5YkS*ei{aivtt0$*@G9JQ`qFV+;WEVuwsMSiSyK!phZxxCwt`8&E8^#83a zwCxSLzLRJ%)OlvDPpwcg_*_GD$npi+D_;#~u>)U3X^R_iT18b+qt|(KYQ+}c36_sM zbvGOOy2ibvk2aapMpIwl-!q;$rxsJ$;NLU72rW-0EnRPbeM{zNkg;S~B9kuECD><9 z7MdI2gWCGH8l)RwxOF4EZGczmv-Az{;CgS=;>&RI@YZm0>JK{Ozq)Qtb^pPvkNZJk zu%KaWOT)=O7uHeh;@Ngf+L2rby$EYqZh$4M^eY6nz@CW|HudwqO9l5EAadm1sI3`@ z>^#iAi8z)7Sirt=G^)tays&#A2W41(bY&aQ(l+@m^C0;-(XA{dIrL!lA&t&Km5N_wSrIyQ<@6X0e&1@|#HW&H$ zc2e*MOP_@uf9~>id;M~B`U2S~a5is!PCyhWIbR4`v@*U*B5#2gvn3k1+7t}eoIq39 z7&f%`kxa!eJ;~a#-KO#_OnfapVh$@~WUBQiGFZhX?&29c*AIw0Ur1(9iOBapm{SZ@ zMOF#D6`_rG9UROSsPOti>WVH1_&O zK;QCFr?UwBzts+ZtYJEc46v(hF{r6#vYFeZ+ouqY&a$ys*aWnOF&tJ{p+^O-a#TXG53L7rVez zFYr9N5RSv26gfVA74j|rkEO4Ui{ktK20=nWO1irwC8fK&q!lD3q@-CwUw}@AX^;mLYfPxKY4-h%0Z!xDkY#WKmcbnDW6!;D0?( z{!4m!eCbMDj?sD%(!=b-kYhD`Wrj`sI%M+ave60>wTY25FnuZ+z8c_EOrwgb`(3P=lS0GRz-XrIYv|08>F59sNJ%h>t<)4=-OQY-cwUM2LQ(v zAoUMuoj>_|&|+M@YtwHMdqABXDbrc(Kd9&WbS|-l407*+d;4{H=Db3VI>2u&wTGV6l6&VYT(yIa5b&l#2+uZZJj~6Km%~{1A zUD*C<3l63nwH;k=O^J7|SiwT)B2|I628fLKpJ3sh+Jmcmlq#4u)pHZD)*a!v9ysCN zbK}2jBF&5B>pEG%(uaMj4+<)KadmRamPZJYr&@=_=(xa))E}Ipg-XT^rt^PJsQZTK zap13c=cWAr;q_sOvoTvCEu}H(dZ7QXFDpcbVVw@JOHz$}M?(_585BCjUUJwNKYS~Z zLM=bBe!?JSn^RY{q}oEcc+4aHRZS$X-1#-zzwaKUDfFyiZ<%L)_2}{N(9nE;jOqBn zOliIg##8Kz>x5Ygro>rqw$dF97U3Kc+e_*3+izUj2MB@B zvqmOdiLzjtB(5j;=I;#GGf_{jux_xsK=1PlE+VBlC)Jbbd(!mHu5W96b2sp(1t$}@ z1t;-11t-4XQ557|AN{-U2V0KdzxzV4rGhO}@L!-FTd>akBU^0dU~7(qt`olGuHwQ+ zhaU<~0zt*C$I~~inA113m|6O}V0%WW3U5wQgXfW}!mU%(;Pk|*@ELvdkGj)0fp*h3 zC&L9NvAExRle+RiI}pVxRk$s?y+QY6qQ+%c^GACn_`)^99n3VLt@5mw;zy}a;@KU* zdcMa2bTokFmI<~*)$)eqNK{%s)ymOE0-Sm08W3yZQf@Q8hj<4SL|f>6sXh+8Sq>b{ zAzye2snW|%BO(`AvoA)(fFD?c*$KYE8EhrpLC`j@lsSQq zhqY%=Y5nBwyX&H;CjELhnWb#eKg>TmQmnFwU?}kC}v@nUrFp0Dt6OBcdn(Irq3^WIdjFi?iEn$df^6 z(D+7Kb1s}Sv21lTv8>Ufz?s~uz?ptsb&lBm`{%^6!XNvN&IQgt#q}F=#Pl1}HRj5{ z*VVkKiWxQvm+0j7iD$(^+|8J}UC+RqFTKyis;2&Jch-#Rt6(njL2L7}JS^+=u^(4! zccQA6GCq{+ZJz&YkA>&)z=!gO5$(?8Ww0KkIJcI0(}}2$`H8K!+U?pj)^CQf=Glty))|Eroqc zeS{Z`IL1e`UbXBP{p&<(j4VJ#WLW$guBl_6F5+yxCW?C-?@@K9I~9@oS55~0N*d*Z z@!`6;DrS5njW_&dOBm2tW`QZsoitQAI8s>d>C%<{e)qv?$j0U6P5yUIBwm7sf`#uT8JK+@&XBy3ZPPlK1oI zxiDR62eI=8lc*)9BHded=;d9=G=#XDpG zO{$rv4i3+R_O=3nds?dh)EHX!xUJ=$?h9qm4>}!T^v81{sov);keBMroqzspl>*j3V9&09;Ncrc+*fmazi8$hv ziRE;a8}FHkjPPVvyc!EuFpP}g?I&y_trX)hVjlcgVl{_zc&)i@1+%m+<@6{#gBaT@ zSFwtYy}W=;I@|pQpg1{#sK6nF_1_k^2+e?+HKF&dV)1j_gqZ@7oqMz}t+g`{$=be-hBg1xUtj{OrCr&|JxNQxKI-~hN<+)V*+(gy7Hemg+r$??2Koy5e8nC9_> z%owq?S@cXEhU;knMm*1u8qnYIYfI}KDxm<@!h+;~W1*%zY2skZ3 zxgWNOo5-AI?R==B2#EE#>X1mUyj9|^&aoJz4?4>@UCZFzaqd}e^!3v_Zf;LA5xTcq z03P-cv4V;nhT!3G~B)e!akg#(8S%2!zb=yP=n3r&-|Rq@(Ne z;?MlM_Sv4(DQB?VWk>~QZ<6%T`z0AJeej)$Rr?X&wwb4c-MD5o@;ZK2Iei599A|tE zkt_uwXhlWzHe0$#i&sS&EXw;`CE&}aUzWcCQ=)M4DpOSad#h8@n+JUxUuQ>JwC350 zH!5QRWwJ|#GtK8nq3T^sNZ3(#X|04v7w)@9b?DiZ&ZG8KSrR95R#D=R{f_I_e*btN z9kW=wxbnO!yXxZgTrFM}9I{;7dSq64u-oLwX_7UdGICaRd#|ovULA1H$2zT?c>;6W zy(h&o+&y!r10XJ8{ok_wNrB(|a)Wb-^A>-W{#f!@snq*(;nRDl2u0Zxs!eqT7|TaM z8s|~LkK>Pk%2+6rgBmD~)t?6>J5hU*0Ujv}gfS?<27t7@On$IQGLCdtvsyBu@;upl zNPy5c;pY&&pk%jBIo@nP?Zr}^K5b!;F5I$m>f@0)V?H3$VCMUCt7kott_-;ol(B~t z34OdFd1x8CK(sHoC;pa6>(SvbW6~O>?YqdlO>%NH37PIr)OVhEBVB0_m$J6*5aRih z=wVytK!Xydc#%o}z>yi>yj|Q8qB*?e88%^cmn1ZICy@7Y%Y)NoaqQ^>S;$gGeG;o1 zZXWr4QA+jD-cz%xq#`fo+kcQ%zOe)w#IJb$!puPVThnEdfAoj~+;;TkHTAVHlHAuue^7s=j+PyjBZ*V)jIai?pN5T?it-(n;UbBv? z%uJVNEd%D53&QdQ&4bR3_yI}cz8xcsHq?wZ5&{I6OELZolUAb`VIsCTN53VB93_4~ zo(vf!*(fCzXkxxl+$;f)>=%k|-_`pTtMK^rs&Jb4E)=B;L3VtUB&^9k7pFn=LNR|V zll{@rxMU)enMU8WL#`@YC993ho7_QJkVkb(CW6blLXqMAOp~G%D7F5cns|O4%sX6A zvHCyaDM(EGN8p3R$$ta^NDv6c294Q;-&naQccB~5`)~kX7<9w7%#b231 zwawWUow@AX#)p<~F|KGf+DE?O;kBk(&FLl-fwh<&EvolQcK)n?@Oc3HQ@bGc(~$kz z8fgRr3p-o;R~lRh7YlC6V-Ac=T3qwAs% zXp_It@;fQ9(Tb7m8RzFSJZpjgJ#E-6jOZ+L_t1O5oI1tilVE4=}=d4 zrvu=~7vhHxh(?>!zT0MnovbdM_t9TZb~;>t%E@$bZ?xabogV=v7I(u^1KnEp6n?V3 zSFu?3aHm+t4-u(C9&yJtf9&L|Qdp$19k?rM`AY6*i?})S$m#m#dJ+U!dRUGVH24bt z+e)bAUf~}~-^#Va>&+35CKVy)fIePPUvo zGl=ge)HIqkxoSo)Ly-sgJDW0BSW19@Eb_kf4)~&Scl7TceS81+hJA}RA&~^nHFd40P}muDnytxR zQi7-h=7yaE7{?WTXFuvdY(TF8U<9O(YJyK|*vNk1hM(OEY#E5B#g{ps`dDB)^7|P# zqg&_CPICJb^|w`LBD0G#-tP-@#R6#UeD8sP8isz<`yteo2`W{rI8%CNyHHB6xjEs7 zG$K2`RX8c$A4wzAq9^KfS`-yDy>^0lr(x|hnAQ6*IT@UE7N*s4cCuIa*7QWJcYL(2 zxFD#vxI;jRit?6M<~)h zzpRm8|KbjSE>y5@mXt;484V~exD62zNqJX@F^6_JxKs!(u7z$v?c>$ds;mr&nG zhX+6^iHgH^leu`w6>aU=4Uoh<@G8YYu?0GxlD5 zU+4Ch=hyZ{_Mj=&Jdu^cv!8ZuPNL%uvSI5IKhaH!w>TJOUk^W~k>sI-VAtPcdj`-`h zKA_T99m*Jl4@DU9f2zhHf)Oh|m=XRfFWovY*}e1)5q;WZd_n!B?>+{@BIjC$UzA<6 zouR#(60ZtmbRNKz7VB&?)AKnd# zDQZ^z&RDF~is*6}e`=uBQ0y+}&oJFelV|V54_28|SgyDiA#S<-h6=c7sefQ{^p?ip z>N{YHocSRvS3y!#$;)E?ubPCtb?4R3p5syUb|INjimMOG-(J!$E({Q`UlJ#Od)BG3 zYeZ#0V<=FxwxP8}-z$17 z&)pT`6ND5vOjtwK^_pBzR{i`OOMIXAHp^yMTXfH_8^v7$VBw+NRkOiUYyh{TJeMr} zH$zu=fQoWzHt_b&dIM6u4oS5|70aV!KC1i(HQfJ&luZ>mJ8$q$EwDc4g&tK3 zA6pEfAc5(kHj?V4Nb@4ng1t;hBH;T=is3y7_;cd9KCx)T4f>TKG}&qv=#F=1RWGPv z{Qhdm8OdXYu1)pYCN=#w+Xer1^$~4gwpDqHyRaj$+dx^ADSSZ%ejwywDEe^#UsP*M znDg3t>qw^0@D1m>Zt1GMVOay?k!|*6TjmX(3vr9>KDRYCbAY)e@cSoX=r48G&nuy zq_IDwYjX{a;Ugyhj|4B^{` z?tQY@fHGtNDaBvJ`OL9$5-)5BhHi6whadBZ4$mA^rW6BL8IoHa9ONNFTDiB!EdKM? z8|PAdaQ0CvW}F*d0bDOS3bqx8&*U@@>n1zrixXs5QL-1T z4I%M5B?_9lL$p%a&uwmqG+%#c$Z_@Q(#slg*6VxytjqL)F{B-DgIc-IostOVr1;PT zZZW3P=T1um^H+ShCaQf*SW8M+%Su=)OjxT#Az#j5Gs0kVz+m%~(T1DRMuXAjJ)=!5 zqfI%Z%?P8-0eAyrvf*a3(GXM!pI7W7v%{&3f%3#c!I2kF9JDeH%JT(U`31`J6u>tde1K`R(}!nN*wJ=18bJJ`p@OnWE~PXRRgiulBuYmY^s5W{&SDK*{to z^%l0|3b-T}?*iU>;L0E$RKaIqi3i}xIlyPRe~md~WvqgxId=|xdkiyt-s1Hl`_g@u zps;PMd0R)6=l+rGucgJc)zqMFs#=IwNZF9fnd(Ec^bZT<1dbgbT3rh%o)eM17ri_w z=Bk~&l@mi68$xH?<3Bg7y7;={X}3DrmR%J)wN+zlp!cPJVE)7n!>b}3xcsX3dIM4q ztc=nycG?s3a9sg-Q($!7V8-%)KMEBrW1#s50zO^BMTmve-T*l14UP0FTu6Jn_z|zQ zlHLZ2CgEj~ms1@a2(o^v?d%%&MJTGz!T0dLK`opCakd_XGl29Mh&zKd%4vi7nTQyk zTasiio`3$y_VXX_4}SRUTtf`5A*c30{1zGNvyA7edNGwJUxtV;b-Ab8@h;QNH%OZ| zwrI2EvfKVxfb%3OI`c*AZL2t?u)u=xpF8(YB0nr1s%-!(TcA=b9YJsv`!V3pbbXMR~VeNNHi4KEXXX|G~D>CE91Y zb|lC?*uwe3Of0bBNk)T_l^8Rv|Agz=8KR-vF zI09Mb4((Y;YY%|k4q1J@B-5YbG%gxgg!D-SXOE!M+_%LW)? zndnz7F?V^)O{pbGPkFu>N&#`rmrAr>%YF2l=1P6du~7F+#tv7-paUr4n&^y~|5Lo4y!OKGPrp5@NY-n2 z&cU+Mg_g3ryebqV$X@PCr$j$sYkkIHkT!5G!#xQJs061Q%z(-ktUJCwEud2OGEe15 zMq>Hfp71rjo$fr)v4pawLBf_{&QiYpu#!c{(I0?9z37q*Nlsa5aB1yI6TER@uKCB_ zK&MK1S!U@?iSqqHV+LTWi-3_W!`y>n91dmli}~_^LNL4N>MEQBfR^H@Ws1I+1jyD(oG%>>s=w+ zU8rmSPn-6Tk=EG?@tG(7rqvLdt(-e+FpyjfY?@WS8Z^pyXRq<-pT$^ z;w)pa^HiyJU}UB*_a{ARqefIL(bhoBt5~^N_>@K*&Ahx&gB!E5(gUk9a^$nX+p*RR zue{jWgYnqrqZRhGkX^imgVu=_iM7R{tK1urg}uyF3yV813ph5M@SgR>`lf*i6d71S zO0u~J#dyH>`h4Usa27AT((O*ShZW49-hLsAE{eDsvY2kuvpAm)TS<6ayD~{>DfW|J zz9W{N;n_>&*xs#IpE;M(HgUA_#p*U5du$id_vy(%UVKGemWb^xx_KNP^K7=b?zOZp z&~NtV z0_G^~Mp)c2r#Bi<8kx~)#;V$pKezre)yp96)}p>(ccApn9f_6d-SL&~BW+k2 z(yDGw%tkG!yZyc$X!#Yd=(gKF(_*^J?s3!c02K=yqd8k+ZQcBa?RO?UVretfwdM2B zvA*4+a{abB#6C8jxqJ4Cs?h=d3FRj$8EJo9X3NCka*+jJcuJ%d$(ZqU*#Sp0iZKJf z+zG2F0=gRkW$TNX52xIqSNh-LqkLFw{e+`Wh_qrEGsu~;C=~c#DhdgU$UWJO!p@?h zbNuL+|8FB~HyS&OfzC0?FQ0QWY!`~1#iGEkAvq~@CVQc%NMeU$9|J8KCLARt(jp@o zBO}rxCmJIs(xM;`vQ-qaQxtNLoGdt#t^bXomCcwTO6RzV7hmiD*nS_cXXQ*bc>rUK zj!281XpEkS6OG6zRN$2^I@2^dll~*7=|@cZ7);X`O!}A#`M4r`c!oWMe;*NXMvO^e zxYo2fM_*=95)5 zUkOdN$ycm)++9qz0Z4GnqlOSA^pj?uvW3%w9|6^KoKGHZ-{>KYsEj6~txLmCE{ud1 zKg!O1_?6CeRYz_J{=b+A^9H@1D;Ntfnwc^%(&CdYaHe}{IQNjf7c0MHPZ~+X!S&=y zjrWPAXd%a8eXdd^84GD+NV%R~cINw7H`6xDLduubC6#_{C6+MZvg=)IqvodU@_qil zDP=!T-WmDrEf{VLXqUZOFfZB<;;1Ycxiu}T8u?1@BXMS^cM~l^dga$zQ{oU3uHOF6 zMX%4#AaQ)UTos}cq_HzC$5+BVyNJO;5E!sFO>n3` zY(1XqcF)zrzgvGhmxFCzjs=r8N^Nip=koujJD2d-qwM=jCPU?o;~(va?H_M{uPOCz z1&|dw3M(-SeTh*n3yxK`x~p`YovA2FwXXslkQ%D6nq@DZp zW5JN*=|U-D)Q)TBZ)BMohC`{oZJnW0&arV}G)p;~DA$YOQvq_j2f-$ei~1g=-L1}; zqK>&vj)OuGr9b7=WLlP^NSQ#BN90DGNItGtKmIuKGW^(j0$q2(D|zuV6dJlVYoUMf zRbG~1h0xog%)eFd)h04c4{o z7NElRzDTxW(aaq7uNQEg{7hDV#GdMn{{UZ&IBhxTiUs%3UREt?F5%OsIh}qIgCRe{ z`E0QwUu>Q3Wk0&@2*)%2EY4>cMfqa+$(fsIwv_$oIi%0Ay}5phF%Yq4Q1qkIf-;CS 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 a$1xo%1ox9%9ceNF__ldZ2ky8&yz@WAsp(Gu diff --git a/pipenv/vendor/dateutil/zoneinfo/rebuild.py b/pipenv/vendor/dateutil/zoneinfo/rebuild.py index 78f0d1a0..684c6586 100644 --- a/pipenv/vendor/dateutil/zoneinfo/rebuild.py +++ b/pipenv/vendor/dateutil/zoneinfo/rebuild.py @@ -3,7 +3,7 @@ import os import tempfile import shutil import json -from subprocess import check_call +from subprocess import check_call, check_output from tarfile import TarFile from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME @@ -23,11 +23,9 @@ def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): for name in zonegroups: tf.extract(name, tmpdir) filepaths = [os.path.join(tmpdir, n) for n in zonegroups] - try: - check_call(["zic", "-d", zonedir] + filepaths) - except OSError as e: - _print_on_nosuchfile(e) - raise + + _run_zic(zonedir, filepaths) + # write metadata file with open(os.path.join(zonedir, METADATA_FN), 'w') as f: json.dump(metadata, f, indent=4, sort_keys=True) @@ -40,6 +38,30 @@ def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None): shutil.rmtree(tmpdir) +def _run_zic(zonedir, filepaths): + """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. + + Recent versions of ``zic`` default to ``-b slim``, while older versions + don't even have the ``-b`` option (but default to "fat" binaries). The + current version of dateutil does not support Version 2+ TZif files, which + causes problems when used in conjunction with "slim" binaries, so this + function is used to ensure that we always get a "fat" binary. + """ + + try: + help_text = check_output(["zic", "--help"]) + except OSError as e: + _print_on_nosuchfile(e) + raise + + if b"-b " in help_text: + bloat_args = ["-b", "fat"] + else: + bloat_args = [] + + check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) + + def _print_on_nosuchfile(e): """Print helpful troubleshooting message diff --git a/pipenv/vendor/delegator.py b/pipenv/vendor/delegator.py index 19f27070..367f52b0 100644 --- a/pipenv/vendor/delegator.py +++ b/pipenv/vendor/delegator.py @@ -6,8 +6,8 @@ import sys import locale import errno -from pipenv.vendor.pexpect.popen_spawn import PopenSpawn -from pipenv.vendor import pexpect +from pexpect.popen_spawn import PopenSpawn +import pexpect pexpect.EOF.__module__ = "pexpect.exceptions" # Include `unicode` in STR_TYPES for Python 2.X diff --git a/pipenv/vendor/distlib/__init__.py b/pipenv/vendor/distlib/__init__.py index 63d916e3..492c2c70 100644 --- a/pipenv/vendor/distlib/__init__.py +++ b/pipenv/vendor/distlib/__init__.py @@ -6,7 +6,7 @@ # import logging -__version__ = '0.3.1' +__version__ = '0.3.2' class DistlibException(Exception): pass diff --git a/pipenv/vendor/distlib/index.py b/pipenv/vendor/distlib/index.py index 7a87cdcf..b1fbbf8e 100644 --- a/pipenv/vendor/distlib/index.py +++ b/pipenv/vendor/distlib/index.py @@ -18,7 +18,7 @@ except ImportError: from . import DistlibException from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, urlparse, build_opener, string_types) -from .util import cached_property, zip_dir, ServerProxy +from .util import zip_dir, ServerProxy logger = logging.getLogger(__name__) @@ -67,21 +67,17 @@ class PackageIndex(object): Get the distutils command for interacting with PyPI configurations. :return: the command. """ - from distutils.core import Distribution - from distutils.config import PyPIRCCommand - d = Distribution() - return PyPIRCCommand(d) + from .util import _get_pypirc_command as cmd + return cmd() def read_configuration(self): """ - Read the PyPI access configuration as supported by distutils, getting - PyPI to do the actual work. This populates ``username``, ``password``, - ``realm`` and ``url`` attributes from the configuration. + Read the PyPI access configuration as supported by distutils. This populates + ``username``, ``password``, ``realm`` and ``url`` attributes from the + configuration. """ - # get distutils to do the work - c = self._get_pypirc_command() - c.repository = self.url - cfg = c._read_pypirc() + from .util import _load_pypirc + cfg = _load_pypirc(self) self.username = cfg.get('username') self.password = cfg.get('password') self.realm = cfg.get('realm', 'pypi') @@ -91,13 +87,10 @@ class PackageIndex(object): """ Save the PyPI access configuration. You must have set ``username`` and ``password`` attributes before calling this method. - - Again, distutils is used to do the actual work. """ self.check_credentials() - # get distutils to do the work - c = self._get_pypirc_command() - c._store_pypirc(self.username, self.password) + from .util import _store_pypirc + _store_pypirc(self) def check_credentials(self): """ diff --git a/pipenv/vendor/distlib/locators.py b/pipenv/vendor/distlib/locators.py index 12a1d063..0c7d6391 100644 --- a/pipenv/vendor/distlib/locators.py +++ b/pipenv/vendor/distlib/locators.py @@ -20,14 +20,14 @@ import zlib from . import DistlibException from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, - queue, quote, unescape, string_types, build_opener, + queue, quote, unescape, build_opener, HTTPRedirectHandler as BaseRedirectHandler, text_type, Request, HTTPError, URLError) from .database import Distribution, DistributionPath, make_dist from .metadata import Metadata, MetadataInvalidError -from .util import (cached_property, parse_credentials, ensure_slash, - split_filename, get_project_data, parse_requirement, - parse_name_and_version, ServerProxy, normalize_name) +from .util import (cached_property, ensure_slash, split_filename, get_project_data, + parse_requirement, parse_name_and_version, ServerProxy, + normalize_name) from .version import get_scheme, UnsupportedVersionError from .wheel import Wheel, is_compatible @@ -378,13 +378,13 @@ class Locator(object): continue try: if not matcher.match(k): - logger.debug('%s did not match %r', matcher, k) + pass # logger.debug('%s did not match %r', matcher, k) else: if prereleases or not vcls(k).is_prerelease: slist.append(k) - else: - logger.debug('skipping pre-release ' - 'version %s of %s', k, matcher.name) + # else: + # logger.debug('skipping pre-release ' + # 'version %s of %s', k, matcher.name) except Exception: # pragma: no cover logger.warning('error matching %s with %r', matcher, k) pass # slist.append(k) @@ -593,7 +593,7 @@ class SimpleScrapingLocator(Locator): # These are used to deal with various Content-Encoding schemes. decoders = { 'deflate': zlib.decompress, - 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(d)).read(), + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(b)).read(), 'none': lambda b: b, } @@ -1062,8 +1062,6 @@ default_locator = AggregatingLocator( locate = default_locator.locate -NAME_VERSION_RE = re.compile(r'(?P[\w-]+)\s*' - r'\(\s*(==\s*)?(?P[^)]+)\)$') class DependencyFinder(object): """ diff --git a/pipenv/vendor/distlib/markers.py b/pipenv/vendor/distlib/markers.py index ee1f3e23..923a832b 100644 --- a/pipenv/vendor/distlib/markers.py +++ b/pipenv/vendor/distlib/markers.py @@ -15,9 +15,8 @@ Parser for the environment markers micro-language defined in PEP 508. import os import sys import platform -import re -from .compat import python_implementation, urlparse, string_types +from .compat import string_types from .util import in_venv, parse_marker __all__ = ['interpret'] diff --git a/pipenv/vendor/distlib/metadata.py b/pipenv/vendor/distlib/metadata.py index 6d5e2360..6a26b0ab 100644 --- a/pipenv/vendor/distlib/metadata.py +++ b/pipenv/vendor/distlib/metadata.py @@ -94,8 +94,9 @@ _426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', # See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in # the metadata. Include them in the tuple literal below to allow them # (for now). +# Ditto for Obsoletes - see issue #140. _566_FIELDS = _426_FIELDS + ('Description-Content-Type', - 'Requires', 'Provides') + 'Requires', 'Provides', 'Obsoletes') _566_MARKERS = ('Description-Content-Type',) @@ -117,7 +118,8 @@ def _version2fieldlist(version): elif version == '1.2': return _345_FIELDS elif version in ('1.3', '2.1'): - return _345_FIELDS + _566_FIELDS + # avoid adding field names if already there + return _345_FIELDS + tuple(f for f in _566_FIELDS if f not in _345_FIELDS) elif version == '2.0': return _426_FIELDS raise MetadataUnrecognizedVersionError(version) diff --git a/pipenv/vendor/distlib/resources.py b/pipenv/vendor/distlib/resources.py index 18840167..fef52aa1 100644 --- a/pipenv/vendor/distlib/resources.py +++ b/pipenv/vendor/distlib/resources.py @@ -11,13 +11,12 @@ import io import logging import os import pkgutil -import shutil import sys import types import zipimport from . import DistlibException -from .util import cached_property, get_cache_base, path_to_cache_dir, Cache +from .util import cached_property, get_cache_base, Cache logger = logging.getLogger(__name__) @@ -283,6 +282,7 @@ class ZipResourceFinder(ResourceFinder): result = False return result + _finder_registry = { type(None): ResourceFinder, zipimport.zipimporter: ZipResourceFinder @@ -296,6 +296,8 @@ try: import _frozen_importlib as _fi _finder_registry[_fi.SourceFileLoader] = ResourceFinder _finder_registry[_fi.FileFinder] = ResourceFinder + # See issue #146 + _finder_registry[_fi.SourcelessFileLoader] = ResourceFinder del _fi except (ImportError, AttributeError): pass @@ -304,6 +306,7 @@ except (ImportError, AttributeError): def register_finder(loader, finder_maker): _finder_registry[type(loader)] = finder_maker + _finder_cache = {} diff --git a/pipenv/vendor/distlib/scripts.py b/pipenv/vendor/distlib/scripts.py index 03f8f21e..1ac01dde 100644 --- a/pipenv/vendor/distlib/scripts.py +++ b/pipenv/vendor/distlib/scripts.py @@ -282,6 +282,19 @@ class ScriptMaker(object): self._fileop.set_executable_mode([outname]) filenames.append(outname) + variant_separator = '-' + + def get_script_filenames(self, name): + result = set() + if '' in self.variants: + result.add(name) + if 'X' in self.variants: + result.add('%s%s' % (name, self.version_info[0])) + if 'X.Y' in self.variants: + result.add('%s%s%s.%s' % (name, self.variant_separator, + self.version_info[0], self.version_info[1])) + return result + def _make_script(self, entry, filenames, options=None): post_interp = b'' if options: @@ -291,15 +304,7 @@ class ScriptMaker(object): post_interp = args.encode('utf-8') shebang = self._get_shebang('utf-8', post_interp, options=options) script = self._get_script_text(entry).encode('utf-8') - name = entry.name - scriptnames = set() - if '' in self.variants: - scriptnames.add(name) - if 'X' in self.variants: - scriptnames.add('%s%s' % (name, self.version_info[0])) - if 'X.Y' in self.variants: - scriptnames.add('%s-%s.%s' % (name, self.version_info[0], - self.version_info[1])) + scriptnames = self.get_script_filenames(entry.name) if options and options.get('gui', False): ext = 'pyw' else: @@ -326,8 +331,7 @@ class ScriptMaker(object): else: first_line = f.readline() if not first_line: # pragma: no cover - logger.warning('%s: %s is an empty file (skipping)', - self.get_command_name(), script) + logger.warning('%s is an empty file (skipping)', script) return match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) diff --git a/pipenv/vendor/distlib/util.py b/pipenv/vendor/distlib/util.py index 01324eae..b9e2c695 100644 --- a/pipenv/vendor/distlib/util.py +++ b/pipenv/vendor/distlib/util.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2012-2017 The Python Software Foundation. +# Copyright (C) 2012-2021 The Python Software Foundation. # See LICENSE.txt and CONTRIBUTORS.txt. # import codecs @@ -309,7 +309,9 @@ def get_executable(): # else: # result = sys.executable # return result - result = os.path.normcase(sys.executable) + # Avoid normcasing: see issue #143 + # result = os.path.normcase(sys.executable) + result = sys.executable if not isinstance(result, text_type): result = fsdecode(result) return result @@ -1570,7 +1572,8 @@ class ServerProxy(xmlrpclib.ServerProxy): # The above classes only come into play if a timeout # is specified if timeout is not None: - scheme, _ = splittype(uri) + # scheme = splittype(uri) # deprecated as of Python 3.8 + scheme = urlparse(uri)[0] use_datetime = kwargs.get('use_datetime', 0) if scheme == 'https': tcls = SafeTransport @@ -1759,3 +1762,204 @@ def normalize_name(name): """Normalize a python package name a la PEP 503""" # https://www.python.org/dev/peps/pep-0503/#normalized-names return re.sub('[-_.]+', '-', name).lower() + +# def _get_pypirc_command(): + # """ + # Get the distutils command for interacting with PyPI configurations. + # :return: the command. + # """ + # from distutils.core import Distribution + # from distutils.config import PyPIRCCommand + # d = Distribution() + # return PyPIRCCommand(d) + +class PyPIRCFile(object): + + DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' + DEFAULT_REALM = 'pypi' + + def __init__(self, fn=None, url=None): + if fn is None: + fn = os.path.join(os.path.expanduser('~'), '.pypirc') + self.filename = fn + self.url = url + + def read(self): + result = {} + + if os.path.exists(self.filename): + repository = self.url or self.DEFAULT_REPOSITORY + + config = configparser.RawConfigParser() + config.read(self.filename) + sections = config.sections() + if 'distutils' in sections: + # let's get the list of servers + index_servers = config.get('distutils', 'index-servers') + _servers = [server.strip() for server in + index_servers.split('\n') + if server.strip() != ''] + if _servers == []: + # nothing set, let's try to get the default pypi + if 'pypi' in sections: + _servers = ['pypi'] + else: + for server in _servers: + result = {'server': server} + result['username'] = config.get(server, 'username') + + # optional params + for key, default in (('repository', self.DEFAULT_REPOSITORY), + ('realm', self.DEFAULT_REALM), + ('password', None)): + if config.has_option(server, key): + result[key] = config.get(server, key) + else: + result[key] = default + + # work around people having "repository" for the "pypi" + # section of their config set to the HTTP (rather than + # HTTPS) URL + if (server == 'pypi' and + repository in (self.DEFAULT_REPOSITORY, 'pypi')): + result['repository'] = self.DEFAULT_REPOSITORY + elif (result['server'] != repository and + result['repository'] != repository): + result = {} + elif 'server-login' in sections: + # old format + server = 'server-login' + if config.has_option(server, 'repository'): + repository = config.get(server, 'repository') + else: + repository = self.DEFAULT_REPOSITORY + result = { + 'username': config.get(server, 'username'), + 'password': config.get(server, 'password'), + 'repository': repository, + 'server': server, + 'realm': self.DEFAULT_REALM + } + return result + + def update(self, username, password): + # import pdb; pdb.set_trace() + config = configparser.RawConfigParser() + fn = self.filename + config.read(fn) + if not config.has_section('pypi'): + config.add_section('pypi') + config.set('pypi', 'username', username) + config.set('pypi', 'password', password) + with open(fn, 'w') as f: + config.write(f) + +def _load_pypirc(index): + """ + Read the PyPI access configuration as supported by distutils. + """ + return PyPIRCFile(url=index.url).read() + +def _store_pypirc(index): + PyPIRCFile().update(index.username, index.password) + +# +# get_platform()/get_host_platform() copied from Python 3.10.a0 source, with some minor +# tweaks +# + +def get_host_platform(): + """Return a string that identifies the current platform. This is used mainly to + distinguish platform-specific build directories and platform-specific built + distributions. Typically includes the OS name and version and the + architecture (as supplied by 'os.uname()'), although the exact information + included depends on the OS; eg. on Linux, the kernel version isn't + particularly important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + + """ + if os.name == 'nt': + if 'amd64' in sys.version.lower(): + return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + return sys.platform + + # Set for cross builds explicitly + if "_PYTHON_HOST_PLATFORM" in os.environ: + return os.environ["_PYTHON_HOST_PLATFORM"] + + if os.name != 'posix' or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + + (osname, host, release, version, machine) = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_').replace('/', '-') + + if osname[:5] == 'linux': + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + + elif osname[:5] == 'sunos': + if release[0] >= '5': # SunOS 5 == Solaris 2 + osname = 'solaris' + release = '%d.%s' % (int(release[0]) - 3, release[2:]) + # We can't use 'platform.architecture()[0]' because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647:'32bit', 9223372036854775807:'64bit'} + machine += '.%s' % bitness[sys.maxsize] + # fall through to standard osname-release-machine representation + elif osname[:3] == 'aix': + from _aix_support import aix_platform + return aix_platform() + elif osname[:6] == 'cygwin': + osname = 'cygwin' + rel_re = re.compile (r'[\d.]+', re.ASCII) + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == 'darwin': + import _osx_support, distutils.sysconfig + osname, release, machine = _osx_support.get_platform_osx( + distutils.sysconfig.get_config_vars(), + osname, release, machine) + + return '%s-%s-%s' % (osname, release, machine) + + +_TARGET_TO_PLAT = { + 'x86' : 'win32', + 'x64' : 'win-amd64', + 'arm' : 'win-arm32', +} + + +def get_platform(): + if os.name != 'nt': + return get_host_platform() + cross_compilation_target = os.environ.get('VSCMD_ARG_TGT_ARCH') + if cross_compilation_target not in _TARGET_TO_PLAT: + return get_host_platform() + return _TARGET_TO_PLAT[cross_compilation_target] diff --git a/pipenv/vendor/distlib/version.py b/pipenv/vendor/distlib/version.py index 3eebe18e..86c069a7 100644 --- a/pipenv/vendor/distlib/version.py +++ b/pipenv/vendor/distlib/version.py @@ -710,6 +710,9 @@ class VersionScheme(object): """ Used for processing some metadata fields """ + # See issue #140. Be tolerant of a single trailing comma. + if s.endswith(','): + s = s[:-1] return self.is_valid_matcher('dummy_name (%s)' % s) def suggest(self, s): diff --git a/pipenv/vendor/distlib/wheel.py b/pipenv/vendor/distlib/wheel.py index 1e2c7a02..5262c832 100644 --- a/pipenv/vendor/distlib/wheel.py +++ b/pipenv/vendor/distlib/wheel.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2013-2017 Vinay Sajip. +# Copyright (C) 2013-2020 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # @@ -9,7 +9,6 @@ from __future__ import unicode_literals import base64 import codecs import datetime -import distutils.util from email import message_from_file import hashlib import imp @@ -29,7 +28,8 @@ from .database import InstalledDistribution from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME) from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, - cached_property, get_cache_base, read_exports, tempdir) + cached_property, get_cache_base, read_exports, tempdir, + get_platform) from .version import NormalizedVersion, UnsupportedVersionError logger = logging.getLogger(__name__) @@ -47,15 +47,18 @@ else: VER_SUFFIX = sysconfig.get_config_var('py_version_nodot') if not VER_SUFFIX: # pragma: no cover - VER_SUFFIX = '%s%s' % sys.version_info[:2] + if sys.version_info[1] >= 10: + VER_SUFFIX = '%s_%s' % sys.version_info[:2] # PEP 641 (draft) + else: + VER_SUFFIX = '%s%s' % sys.version_info[:2] PYVER = 'py' + VER_SUFFIX IMPVER = IMP_PREFIX + VER_SUFFIX -ARCH = distutils.util.get_platform().replace('-', '_').replace('.', '_') +ARCH = get_platform().replace('-', '_').replace('.', '_') ABI = sysconfig.get_config_var('SOABI') if ABI and ABI.startswith('cpython-'): - ABI = ABI.replace('cpython-', 'cp') + ABI = ABI.replace('cpython-', 'cp').split('-')[0] else: def _derive_abi(): parts = ['cp', VER_SUFFIX] @@ -576,6 +579,13 @@ class Wheel(object): if not is_script: with zf.open(arcname) as bf: fileop.copy_stream(bf, outfile) + # Issue #147: permission bits aren't preserved. Using + # zf.extract(zinfo, libdir) should have worked, but didn't, + # see https://www.thetopsites.net/article/53834422.shtml + # So ... manually preserve permission bits as given in zinfo + if os.name == 'posix': + # just set the normal permission bits + os.chmod(outfile, (zinfo.external_attr >> 16) & 0x1FF) outfiles.append(outfile) # Double check the digest of the written file if not dry_run and row[1]: @@ -938,6 +948,16 @@ class Wheel(object): shutil.copyfile(newpath, pathname) return modified +def _get_glibc_version(): + import platform + ver = platform.libc_ver() + result = [] + if ver[0] == 'glibc': + for s in ver[1].split('.'): + result.append(int(s) if s.isdigit() else 0) + result = tuple(result) + return result + def compatible_tags(): """ Return (pyver, abi, arch) tuples compatible with this Python. @@ -985,6 +1005,23 @@ def compatible_tags(): for abi in abis: for arch in arches: result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) + # manylinux + if abi != 'none' and sys.platform.startswith('linux'): + arch = arch.replace('linux_', '') + parts = _get_glibc_version() + if len(parts) == 2: + if parts >= (2, 5): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux1_%s' % arch)) + if parts >= (2, 12): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux2010_%s' % arch)) + if parts >= (2, 17): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux2014_%s' % arch)) + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux_%s_%s_%s' % (parts[0], parts[1], + arch))) # where no ABI / arch dependency, but IMP_PREFIX dependency for i, version in enumerate(versions): @@ -997,6 +1034,7 @@ def compatible_tags(): result.append((''.join(('py', version)), 'none', 'any')) if i == 0: result.append((''.join(('py', version[0])), 'none', 'any')) + return set(result) diff --git a/pipenv/vendor/dotenv/__init__.py b/pipenv/vendor/dotenv/__init__.py index b88d9bc2..3512d101 100644 --- a/pipenv/vendor/dotenv/__init__.py +++ b/pipenv/vendor/dotenv/__init__.py @@ -1,18 +1,21 @@ -from .compat import IS_TYPE_CHECKING -from .main import load_dotenv, get_key, set_key, unset_key, find_dotenv, dotenv_values +from typing import Any, Optional -if IS_TYPE_CHECKING: - from typing import Any, Optional +from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key, + unset_key) -def load_ipython_extension(ipython): - # type: (Any) -> None +def load_ipython_extension(ipython: Any) -> None: from .ipython import load_ipython_extension load_ipython_extension(ipython) -def get_cli_string(path=None, action=None, key=None, value=None, quote=None): - # type: (Optional[str], Optional[str], Optional[str], Optional[str], Optional[str]) -> str +def get_cli_string( + path: Optional[str] = None, + action: Optional[str] = None, + key: Optional[str] = None, + value: Optional[str] = None, + quote: Optional[str] = None, +): """Returns a string suitable for running as a shell script. Useful for converting a arguments passed to a fabric task diff --git a/pipenv/vendor/dotenv/cli.py b/pipenv/vendor/dotenv/cli.py index e17d248f..b7ae24af 100644 --- a/pipenv/vendor/dotenv/cli.py +++ b/pipenv/vendor/dotenv/cli.py @@ -1,6 +1,7 @@ import os import sys from subprocess import Popen +from typing import Any, Dict, List try: import click @@ -9,13 +10,9 @@ except ImportError: 'Run pip install "python-dotenv[cli]" to fix this.') sys.exit(1) -from .compat import IS_TYPE_CHECKING, to_env from .main import dotenv_values, get_key, set_key, unset_key from .version import __version__ -if IS_TYPE_CHECKING: - from typing import Any, List, Dict - @click.group() @click.option('-f', '--file', default=os.path.join(os.getcwd(), '.env'), @@ -29,8 +26,7 @@ if IS_TYPE_CHECKING: help="Whether to write the dot file as an executable bash script.") @click.version_option(version=__version__) @click.pass_context -def cli(ctx, file, quote, export): - # type: (click.Context, Any, Any, Any) -> None +def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None: '''This script is used to set, get or unset values from a .env file.''' ctx.obj = {} ctx.obj['QUOTE'] = quote @@ -40,8 +36,7 @@ def cli(ctx, file, quote, export): @cli.command() @click.pass_context -def list(ctx): - # type: (click.Context) -> None +def list(ctx: click.Context) -> None: '''Display all the stored key/value.''' file = ctx.obj['FILE'] if not os.path.isfile(file): @@ -58,8 +53,7 @@ def list(ctx): @click.pass_context @click.argument('key', required=True) @click.argument('value', required=True) -def set(ctx, key, value): - # type: (click.Context, Any, Any) -> None +def set(ctx: click.Context, key: Any, value: Any) -> None: '''Store the given key/value.''' file = ctx.obj['FILE'] quote = ctx.obj['QUOTE'] @@ -74,8 +68,7 @@ def set(ctx, key, value): @cli.command() @click.pass_context @click.argument('key', required=True) -def get(ctx, key): - # type: (click.Context, Any) -> None +def get(ctx: click.Context, key: Any) -> None: '''Retrieve the value for the given key.''' file = ctx.obj['FILE'] if not os.path.isfile(file): @@ -85,7 +78,7 @@ def get(ctx, key): ) stored_value = get_key(file, key) if stored_value: - click.echo('%s=%s' % (key, stored_value)) + click.echo(stored_value) else: exit(1) @@ -93,8 +86,7 @@ def get(ctx, key): @cli.command() @click.pass_context @click.argument('key', required=True) -def unset(ctx, key): - # type: (click.Context, Any) -> None +def unset(ctx: click.Context, key: Any) -> None: '''Removes the given key.''' file = ctx.obj['FILE'] quote = ctx.obj['QUOTE'] @@ -107,9 +99,13 @@ def unset(ctx, key): @cli.command(context_settings={'ignore_unknown_options': True}) @click.pass_context +@click.option( + "--override/--no-override", + default=True, + help="Override variables from the environment file with those from the .env file.", +) @click.argument('commandline', nargs=-1, type=click.UNPROCESSED) -def run(ctx, commandline): - # type: (click.Context, List[str]) -> None +def run(ctx: click.Context, override: bool, commandline: List[str]) -> None: """Run command with environment variables present.""" file = ctx.obj['FILE'] if not os.path.isfile(file): @@ -117,7 +113,11 @@ def run(ctx, commandline): 'Invalid value for \'-f\' "%s" does not exist.' % (file), ctx=ctx ) - dotenv_as_dict = {to_env(k): to_env(v) for (k, v) in dotenv_values(file).items() if v is not None} + dotenv_as_dict = { + k: v + for (k, v) in dotenv_values(file).items() + if v is not None and (override or k not in os.environ) + } if not commandline: click.echo('No command given.') @@ -126,8 +126,7 @@ def run(ctx, commandline): exit(ret) -def run_command(command, env): - # type: (List[str], Dict[str, str]) -> int +def run_command(command: List[str], env: Dict[str, str]) -> int: """Run command in sub process. Runs the command in a sub process with the variables from `env` diff --git a/pipenv/vendor/dotenv/compat.py b/pipenv/vendor/dotenv/compat.py deleted file mode 100644 index f8089bf4..00000000 --- a/pipenv/vendor/dotenv/compat.py +++ /dev/null @@ -1,49 +0,0 @@ -import sys - -PY2 = sys.version_info[0] == 2 # type: bool - -if PY2: - from StringIO import StringIO # noqa -else: - from io import StringIO # noqa - - -def is_type_checking(): - # type: () -> bool - try: - from typing import TYPE_CHECKING - except ImportError: - return False - return TYPE_CHECKING - - -IS_TYPE_CHECKING = is_type_checking() - - -if IS_TYPE_CHECKING: - from typing import Text - - -def to_env(text): - # type: (Text) -> str - """ - Encode a string the same way whether it comes from the environment or a `.env` file. - """ - if PY2: - return text.encode(sys.getfilesystemencoding() or "utf-8") - else: - return text - - -def to_text(string): - # type: (str) -> Text - """ - Make a string Unicode if it isn't already. - - This is useful for defining raw unicode strings because `ur"foo"` isn't valid in - Python 3. - """ - if PY2: - return string.decode("utf-8") - else: - return string diff --git a/pipenv/vendor/dotenv/ipython.py b/pipenv/vendor/dotenv/ipython.py index 7f1b13d6..7df727cd 100644 --- a/pipenv/vendor/dotenv/ipython.py +++ b/pipenv/vendor/dotenv/ipython.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from IPython.core.magic import Magics, line_magic, magics_class # type: ignore from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore parse_argstring) # type: ignore diff --git a/pipenv/vendor/dotenv/main.py b/pipenv/vendor/dotenv/main.py index 58a23f3d..b8d0a4e0 100644 --- a/pipenv/vendor/dotenv/main.py +++ b/pipenv/vendor/dotenv/main.py @@ -1,50 +1,26 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, print_function, unicode_literals - import io import logging import os -import re import shutil import sys import tempfile from collections import OrderedDict from contextlib import contextmanager +from typing import (IO, Dict, Iterable, Iterator, Mapping, Optional, Tuple, + Union) -from .compat import IS_TYPE_CHECKING, PY2, StringIO, to_env from .parser import Binding, parse_stream +from .variables import parse_variables logger = logging.getLogger(__name__) -if IS_TYPE_CHECKING: - from typing import ( - Dict, Iterable, Iterator, Match, Optional, Pattern, Union, Text, IO, Tuple - ) - if sys.version_info >= (3, 6): - _PathLike = os.PathLike - else: - _PathLike = Text - - if sys.version_info >= (3, 0): - _StringIO = StringIO - else: - _StringIO = StringIO[Text] - -__posix_variable = re.compile( - r""" - \$\{ - (?P[^\}:]*) - (?::- - (?P[^\}]*) - )? - \} - """, - re.VERBOSE, -) # type: Pattern[Text] +if sys.version_info >= (3, 6): + _PathLike = os.PathLike +else: + _PathLike = str -def with_warn_for_invalid_lines(mappings): - # type: (Iterator[Binding]) -> Iterator[Binding] +def with_warn_for_invalid_lines(mappings: Iterator[Binding]) -> Iterator[Binding]: for mapping in mappings: if mapping.error: logger.warning( @@ -55,64 +31,71 @@ def with_warn_for_invalid_lines(mappings): class DotEnv(): - - def __init__(self, dotenv_path, verbose=False, encoding=None, interpolate=True): - # type: (Union[Text, _PathLike, _StringIO], bool, Union[None, Text], bool) -> None - self.dotenv_path = dotenv_path # type: Union[Text,_PathLike, _StringIO] - self._dict = None # type: Optional[Dict[Text, Optional[Text]]] + def __init__( + self, + dotenv_path: Optional[Union[str, _PathLike]], + stream: Optional[IO[str]] = None, + verbose: bool = False, + encoding: Union[None, str] = None, + interpolate: bool = True, + override: bool = True, + ) -> None: + self.dotenv_path = dotenv_path # type: Optional[Union[str, _PathLike]] + self.stream = stream # type: Optional[IO[str]] + self._dict = None # type: Optional[Dict[str, Optional[str]]] self.verbose = verbose # type: bool - self.encoding = encoding # type: Union[None, Text] + self.encoding = encoding # type: Union[None, str] self.interpolate = interpolate # type: bool + self.override = override # type: bool @contextmanager - def _get_stream(self): - # type: () -> Iterator[IO[Text]] - if isinstance(self.dotenv_path, StringIO): - yield self.dotenv_path - elif os.path.isfile(self.dotenv_path): + def _get_stream(self) -> Iterator[IO[str]]: + if self.dotenv_path and os.path.isfile(self.dotenv_path): with io.open(self.dotenv_path, encoding=self.encoding) as stream: yield stream + elif self.stream is not None: + yield self.stream else: if self.verbose: - logger.info("Python-dotenv could not find configuration file %s.", self.dotenv_path or '.env') - yield StringIO('') + logger.info( + "Python-dotenv could not find configuration file %s.", + self.dotenv_path or '.env', + ) + yield io.StringIO('') - def dict(self): - # type: () -> Dict[Text, Optional[Text]] + def dict(self) -> Dict[str, Optional[str]]: """Return dotenv as dict""" if self._dict: return self._dict + raw_values = self.parse() + if self.interpolate: - values = resolve_nested_variables(self.parse()) + self._dict = OrderedDict(resolve_variables(raw_values, override=self.override)) else: - values = OrderedDict(self.parse()) + self._dict = OrderedDict(raw_values) - self._dict = values - return values + return self._dict - def parse(self): - # type: () -> Iterator[Tuple[Text, Optional[Text]]] + def parse(self) -> Iterator[Tuple[str, Optional[str]]]: with self._get_stream() as stream: for mapping in with_warn_for_invalid_lines(parse_stream(stream)): if mapping.key is not None: yield mapping.key, mapping.value - def set_as_environment_variables(self, override=False): - # type: (bool) -> bool + def set_as_environment_variables(self) -> bool: """ - Load the current dotenv as system environemt variable. + Load the current dotenv as system environment variable. """ for k, v in self.dict().items(): - if k in os.environ and not override: + if k in os.environ and not self.override: continue if v is not None: - os.environ[to_env(k)] = to_env(v) + os.environ[k] = v return True - def get(self, key): - # type: (Text) -> Optional[Text] + def get(self, key: str) -> Optional[str]: """ """ data = self.dict() @@ -126,8 +109,7 @@ class DotEnv(): return None -def get_key(dotenv_path, key_to_get): - # type: (Union[Text, _PathLike], Text) -> Optional[Text] +def get_key(dotenv_path: Union[str, _PathLike], key_to_get: str) -> Optional[str]: """ Gets the value of a given key from the given .env @@ -137,8 +119,7 @@ def get_key(dotenv_path, key_to_get): @contextmanager -def rewrite(path): - # type: (_PathLike) -> Iterator[Tuple[IO[Text], IO[Text]]] +def rewrite(path: Union[str, _PathLike]) -> Iterator[Tuple[IO[str], IO[str]]]: try: if not os.path.isfile(path): with io.open(path, "w+") as source: @@ -154,21 +135,29 @@ def rewrite(path): shutil.move(dest.name, path) -def set_key(dotenv_path, key_to_set, value_to_set, quote_mode="always", export=False): - # type: (_PathLike, Text, Text, Text, bool) -> Tuple[Optional[bool], Text, Text] +def set_key( + dotenv_path: Union[str, _PathLike], + key_to_set: str, + value_to_set: str, + quote_mode: str = "always", + export: bool = False, +) -> Tuple[Optional[bool], str, str]: """ Adds or Updates a key/value to the given .env If the .env path given doesn't exist, fails instead of risking creating an orphan .env somewhere in the filesystem """ - value_to_set = value_to_set.strip("'").strip('"') + if quote_mode not in ("always", "auto", "never"): + raise ValueError("Unknown quote_mode: {}".format(quote_mode)) - if " " in value_to_set: - quote_mode = "always" + quote = ( + quote_mode == "always" + or (quote_mode == "auto" and not value_to_set.isalnum()) + ) - if quote_mode == "always": - value_out = '"{}"'.format(value_to_set.replace('"', '\\"')) + if quote: + value_out = "'{}'".format(value_to_set.replace("'", "\\'")) else: value_out = value_to_set if export: @@ -190,8 +179,11 @@ def set_key(dotenv_path, key_to_set, value_to_set, quote_mode="always", export=F return True, key_to_set, value_to_set -def unset_key(dotenv_path, key_to_unset, quote_mode="always"): - # type: (_PathLike, Text, Text) -> Tuple[Optional[bool], Text] +def unset_key( + dotenv_path: Union[str, _PathLike], + key_to_unset: str, + quote_mode: str = "always", +) -> Tuple[Optional[bool], str]: """ Removes a given key from the given .env @@ -217,33 +209,32 @@ def unset_key(dotenv_path, key_to_unset, quote_mode="always"): return removed, key_to_unset -def resolve_nested_variables(values): - # type: (Iterable[Tuple[Text, Optional[Text]]]) -> Dict[Text, Optional[Text]] - def _replacement(name, default): - # type: (Text, Optional[Text]) -> Text - default = default if default is not None else "" - ret = new_values.get(name, os.getenv(name, default)) - return ret # type: ignore +def resolve_variables( + values: Iterable[Tuple[str, Optional[str]]], + override: bool, +) -> Mapping[str, Optional[str]]: + new_values = {} # type: Dict[str, Optional[str]] - def _re_sub_callback(match): - # type: (Match[Text]) -> Text - """ - From a match object gets the variable name and returns - the correct replacement - """ - matches = match.groupdict() - return _replacement(name=matches["name"], default=matches["default"]) # type: ignore + for (name, value) in values: + if value is None: + result = None + else: + atoms = parse_variables(value) + env = {} # type: Dict[str, Optional[str]] + if override: + env.update(os.environ) # type: ignore + env.update(new_values) + else: + env.update(new_values) + env.update(os.environ) # type: ignore + result = "".join(atom.resolve(env) for atom in atoms) - new_values = {} - - for (k, v) in values: - new_values[k] = __posix_variable.sub(_re_sub_callback, v) if v is not None else None + new_values[name] = result return new_values -def _walk_to_root(path): - # type: (Text) -> Iterator[Text] +def _walk_to_root(path: str) -> Iterator[str]: """ Yield directories starting from the given directory up to the root """ @@ -261,8 +252,11 @@ def _walk_to_root(path): last_dir, current_dir = current_dir, parent_dir -def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False): - # type: (Text, bool, bool) -> Text +def find_dotenv( + filename: str = '.env', + raise_error_if_not_found: bool = False, + usecwd: bool = False, +) -> str: """ Search in increasingly higher folders for the given file @@ -280,13 +274,7 @@ def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False): else: # will work for .py files frame = sys._getframe() - # find first frame that is outside of this file - if PY2 and not __file__.endswith('.py'): - # in Python2 __file__ extension could be .pyc or .pyo (this doesn't account - # for edge case of Python compiled for non-standard extension) - current_file = __file__.rsplit('.', 1)[0] + '.py' - else: - current_file = __file__ + current_file = __file__ while frame.f_code.co_filename == current_file: assert frame.f_back is not None @@ -305,21 +293,68 @@ def find_dotenv(filename='.env', raise_error_if_not_found=False, usecwd=False): return '' -def load_dotenv(dotenv_path=None, stream=None, verbose=False, override=False, interpolate=True, **kwargs): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, bool, Union[None, Text]) -> bool +def load_dotenv( + dotenv_path: Union[str, _PathLike, None] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + override: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> bool: """Parse a .env file and then load all the variables found as environment variables. - *dotenv_path*: absolute or relative path to .env file. - - *stream*: `StringIO` object with .env content. - - *verbose*: whether to output the warnings related to missing .env file etc. Defaults to `False`. - - *override*: where to override the system environment variables with the variables in `.env` file. - Defaults to `False`. + - *stream*: Text stream (such as `io.StringIO`) with .env content, used if + `dotenv_path` is `None`. + - *verbose*: whether to output a warning the .env file is missing. Defaults to + `False`. + - *override*: whether to override the system environment variables with the variables + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. """ - f = dotenv_path or stream or find_dotenv() - return DotEnv(f, verbose=verbose, interpolate=interpolate, **kwargs).set_as_environment_variables(override=override) + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + dotenv = DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=override, + encoding=encoding, + ) + return dotenv.set_as_environment_variables() -def dotenv_values(dotenv_path=None, stream=None, verbose=False, interpolate=True, **kwargs): - # type: (Union[Text, _PathLike, None], Optional[_StringIO], bool, bool, Union[None, Text]) -> Dict[Text, Optional[Text]] # noqa: E501 - f = dotenv_path or stream or find_dotenv() - return DotEnv(f, verbose=verbose, interpolate=interpolate, **kwargs).dict() +def dotenv_values( + dotenv_path: Union[str, _PathLike, None] = None, + stream: Optional[IO[str]] = None, + verbose: bool = False, + interpolate: bool = True, + encoding: Optional[str] = "utf-8", +) -> Dict[str, Optional[str]]: + """ + Parse a .env file and return its content as a dict. + + - *dotenv_path*: absolute or relative path to .env file. + - *stream*: `StringIO` object with .env content, used if `dotenv_path` is `None`. + - *verbose*: whether to output a warning the .env file is missing. Defaults to + `False`. + in `.env` file. Defaults to `False`. + - *encoding*: encoding to be used to read the file. + + If both `dotenv_path` and `stream`, `find_dotenv()` is used to find the .env file. + """ + if dotenv_path is None and stream is None: + dotenv_path = find_dotenv() + + return DotEnv( + dotenv_path=dotenv_path, + stream=stream, + verbose=verbose, + interpolate=interpolate, + override=True, + encoding=encoding, + ).dict() diff --git a/pipenv/vendor/dotenv/parser.py b/pipenv/vendor/dotenv/parser.py index 5cb1cdfa..398bd49a 100644 --- a/pipenv/vendor/dotenv/parser.py +++ b/pipenv/vendor/dotenv/parser.py @@ -1,18 +1,11 @@ import codecs import re - -from .compat import IS_TYPE_CHECKING, to_text - -if IS_TYPE_CHECKING: - from typing import ( # noqa:F401 - IO, Iterator, Match, NamedTuple, Optional, Pattern, Sequence, Text, - Tuple - ) +from typing import (IO, Iterator, Match, NamedTuple, Optional, # noqa:F401 + Pattern, Sequence, Tuple) -def make_regex(string, extra_flags=0): - # type: (str, int) -> Pattern[Text] - return re.compile(to_text(string), re.UNICODE | extra_flags) +def make_regex(string: str, extra_flags: int = 0) -> Pattern[str]: + return re.compile(string, re.UNICODE | extra_flags) _newline = make_regex(r"(\r\n|\n|\r)") @@ -32,67 +25,39 @@ _double_quote_escapes = make_regex(r"\\[\\'\"abfnrtv]") _single_quote_escapes = make_regex(r"\\[\\']") -try: - # this is necessary because we only import these from typing - # when we are type checking, and the linter is upset if we - # re-import - import typing +Original = NamedTuple( + "Original", + [ + ("string", str), + ("line", int), + ], +) - Original = typing.NamedTuple( - "Original", - [ - ("string", typing.Text), - ("line", int), - ], - ) - - Binding = typing.NamedTuple( - "Binding", - [ - ("key", typing.Optional[typing.Text]), - ("value", typing.Optional[typing.Text]), - ("original", Original), - ("error", bool), - ], - ) -except (ImportError, AttributeError): - from collections import namedtuple - Original = namedtuple( # type: ignore - "Original", - [ - "string", - "line", - ], - ) - Binding = namedtuple( # type: ignore - "Binding", - [ - "key", - "value", - "original", - "error", - ], - ) +Binding = NamedTuple( + "Binding", + [ + ("key", Optional[str]), + ("value", Optional[str]), + ("original", Original), + ("error", bool), + ], +) class Position: - def __init__(self, chars, line): - # type: (int, int) -> None + def __init__(self, chars: int, line: int) -> None: self.chars = chars self.line = line @classmethod - def start(cls): - # type: () -> Position + def start(cls) -> "Position": return cls(chars=0, line=1) - def set(self, other): - # type: (Position) -> None + def set(self, other: "Position") -> None: self.chars = other.chars self.line = other.line - def advance(self, string): - # type: (Text) -> None + def advance(self, string: str) -> None: self.chars += len(string) self.line += len(re.findall(_newline, string)) @@ -102,41 +67,34 @@ class Error(Exception): class Reader: - def __init__(self, stream): - # type: (IO[Text]) -> None + def __init__(self, stream: IO[str]) -> None: self.string = stream.read() self.position = Position.start() self.mark = Position.start() - def has_next(self): - # type: () -> bool + def has_next(self) -> bool: return self.position.chars < len(self.string) - def set_mark(self): - # type: () -> None + def set_mark(self) -> None: self.mark.set(self.position) - def get_marked(self): - # type: () -> Original + def get_marked(self) -> Original: return Original( string=self.string[self.mark.chars:self.position.chars], line=self.mark.line, ) - def peek(self, count): - # type: (int) -> Text + def peek(self, count: int) -> str: return self.string[self.position.chars:self.position.chars + count] - def read(self, count): - # type: (int) -> Text + def read(self, count: int) -> str: result = self.string[self.position.chars:self.position.chars + count] if len(result) < count: raise Error("read: End of string") self.position.advance(result) return result - def read_regex(self, regex): - # type: (Pattern[Text]) -> Sequence[Text] + def read_regex(self, regex: Pattern[str]) -> Sequence[str]: match = regex.match(self.string, self.position.chars) if match is None: raise Error("read_regex: Pattern not found") @@ -144,17 +102,14 @@ class Reader: return match.groups() -def decode_escapes(regex, string): - # type: (Pattern[Text], Text) -> Text - def decode_match(match): - # type: (Match[Text]) -> Text +def decode_escapes(regex: Pattern[str], string: str) -> str: + def decode_match(match: Match[str]) -> str: return codecs.decode(match.group(0), 'unicode-escape') # type: ignore return regex.sub(decode_match, string) -def parse_key(reader): - # type: (Reader) -> Optional[Text] +def parse_key(reader: Reader) -> Optional[str]: char = reader.peek(1) if char == "#": return None @@ -165,14 +120,12 @@ def parse_key(reader): return key -def parse_unquoted_value(reader): - # type: (Reader) -> Text +def parse_unquoted_value(reader: Reader) -> str: (part,) = reader.read_regex(_unquoted_value) return re.sub(r"\s+#.*", "", part).rstrip() -def parse_value(reader): - # type: (Reader) -> Text +def parse_value(reader: Reader) -> str: char = reader.peek(1) if char == u"'": (value,) = reader.read_regex(_single_quoted_value) @@ -186,8 +139,7 @@ def parse_value(reader): return parse_unquoted_value(reader) -def parse_binding(reader): - # type: (Reader) -> Binding +def parse_binding(reader: Reader) -> Binding: reader.set_mark() try: reader.read_regex(_multiline_whitespace) @@ -203,7 +155,7 @@ def parse_binding(reader): reader.read_regex(_whitespace) if reader.peek(1) == "=": reader.read_regex(_equal_sign) - value = parse_value(reader) # type: Optional[Text] + value = parse_value(reader) # type: Optional[str] else: value = None reader.read_regex(_comment) @@ -224,8 +176,7 @@ def parse_binding(reader): ) -def parse_stream(stream): - # type: (IO[Text]) -> Iterator[Binding] +def parse_stream(stream: IO[str]) -> Iterator[Binding]: reader = Reader(stream) while reader.has_next(): yield parse_binding(reader) diff --git a/pipenv/vendor/dotenv/variables.py b/pipenv/vendor/dotenv/variables.py new file mode 100644 index 00000000..d77b700c --- /dev/null +++ b/pipenv/vendor/dotenv/variables.py @@ -0,0 +1,88 @@ +import re +from abc import ABCMeta +from typing import Iterator, Mapping, Optional, Pattern + +_posix_variable = re.compile( + r""" + \$\{ + (?P[^\}:]*) + (?::- + (?P[^\}]*) + )? + \} + """, + re.VERBOSE, +) # type: Pattern[str] + + +class Atom(): + __metaclass__ = ABCMeta + + def __ne__(self, other: object) -> bool: + result = self.__eq__(other) + if result is NotImplemented: + return NotImplemented + return not result + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + raise NotImplementedError + + +class Literal(Atom): + def __init__(self, value: str) -> None: + self.value = value + + def __repr__(self) -> str: + return "Literal(value={})".format(self.value) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return self.value == other.value + + def __hash__(self) -> int: + return hash((self.__class__, self.value)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + return self.value + + +class Variable(Atom): + def __init__(self, name: str, default: Optional[str]) -> None: + self.name = name + self.default = default + + def __repr__(self) -> str: + return "Variable(name={}, default={})".format(self.name, self.default) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + return (self.name, self.default) == (other.name, other.default) + + def __hash__(self) -> int: + return hash((self.__class__, self.name, self.default)) + + def resolve(self, env: Mapping[str, Optional[str]]) -> str: + default = self.default if self.default is not None else "" + result = env.get(self.name, default) + return result if result is not None else "" + + +def parse_variables(value: str) -> Iterator[Atom]: + cursor = 0 + + for match in _posix_variable.finditer(value): + (start, end) = match.span() + name = match.groupdict()["name"] + default = match.groupdict()["default"] + + if start > cursor: + yield Literal(value=value[cursor:start]) + + yield Variable(name=name, default=default) + cursor = end + + length = len(value) + if cursor < length: + yield Literal(value=value[cursor:length]) diff --git a/pipenv/vendor/dotenv/version.py b/pipenv/vendor/dotenv/version.py index 9da2f8fc..11ac8e1a 100644 --- a/pipenv/vendor/dotenv/version.py +++ b/pipenv/vendor/dotenv/version.py @@ -1 +1 @@ -__version__ = "0.15.0" +__version__ = "0.19.0" diff --git a/pipenv/vendor/dparse/__init__.py b/pipenv/vendor/dparse/__init__.py index 295f38ee..afe8f63f 100644 --- a/pipenv/vendor/dparse/__init__.py +++ b/pipenv/vendor/dparse/__init__.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals, absolute_import """Top-level package for Dependency Parser.""" __author__ = """Jannis Gebauer""" -__email__ = 'jay@pyup.io' -__version__ = '0.5.0' +__email__ = 'support@pyup.io' +__version__ = '0.5.1' -from .parser import parse +from .parser import parse # noqa diff --git a/pipenv/vendor/idna/LICENSE.md b/pipenv/vendor/idna/LICENSE.md new file mode 100644 index 00000000..b6f87326 --- /dev/null +++ b/pipenv/vendor/idna/LICENSE.md @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2013-2021, Kim Davies +All rights reserved. + +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/pipenv/vendor/idna/LICENSE.rst b/pipenv/vendor/idna/LICENSE.rst deleted file mode 100644 index 63664b82..00000000 --- a/pipenv/vendor/idna/LICENSE.rst +++ /dev/null @@ -1,34 +0,0 @@ -License -------- - -License: bsd-3-clause - -Copyright (c) 2013-2020, Kim Davies. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -#. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -#. Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided with - the distribution. - -#. Neither the name of the copyright holder nor the names of the - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -#. THIS SOFTWARE IS PROVIDED BY THE 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 HOLDERS 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/pipenv/vendor/idna/__init__.py b/pipenv/vendor/idna/__init__.py index 847bf935..a40eeafc 100644 --- a/pipenv/vendor/idna/__init__.py +++ b/pipenv/vendor/idna/__init__.py @@ -1,2 +1,44 @@ from .package_data import __version__ -from .core import * +from .core import ( + IDNABidiError, + IDNAError, + InvalidCodepoint, + InvalidCodepointContext, + alabel, + check_bidi, + check_hyphen_ok, + check_initial_combiner, + check_label, + check_nfc, + decode, + encode, + ulabel, + uts46_remap, + valid_contextj, + valid_contexto, + valid_label_length, + valid_string_length, +) +from .intranges import intranges_contain + +__all__ = [ + "IDNABidiError", + "IDNAError", + "InvalidCodepoint", + "InvalidCodepointContext", + "alabel", + "check_bidi", + "check_hyphen_ok", + "check_initial_combiner", + "check_label", + "check_nfc", + "decode", + "encode", + "intranges_contain", + "ulabel", + "uts46_remap", + "valid_contextj", + "valid_contexto", + "valid_label_length", + "valid_string_length", +] diff --git a/pipenv/vendor/idna/codec.py b/pipenv/vendor/idna/codec.py index 98c65ead..080f22a3 100644 --- a/pipenv/vendor/idna/codec.py +++ b/pipenv/vendor/idna/codec.py @@ -1,41 +1,43 @@ from .core import encode, decode, alabel, ulabel, IDNAError import codecs import re +from typing import Tuple, Optional -_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') +_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') class Codec(codecs.Codec): def encode(self, data, errors='strict'): - + # type: (str, str) -> Tuple[bytes, int] if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return "", 0 + return b"", 0 return encode(data), len(data) def decode(self, data, errors='strict'): - + # type: (bytes, str) -> Tuple[str, int] if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return u"", 0 + return '', 0 return decode(data), len(data) class IncrementalEncoder(codecs.BufferedIncrementalEncoder): - def _buffer_encode(self, data, errors, final): + def _buffer_encode(self, data, errors, final): # type: ignore + # type: (str, str, bool) -> Tuple[str, int] if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return ("", 0) + return "", 0 labels = _unicode_dots_re.split(data) - trailing_dot = u'' + trailing_dot = '' if labels: if not labels[-1]: trailing_dot = '.' @@ -55,37 +57,30 @@ class IncrementalEncoder(codecs.BufferedIncrementalEncoder): size += len(label) # Join with U+002E - result = ".".join(result) + trailing_dot + result_str = '.'.join(result) + trailing_dot # type: ignore size += len(trailing_dot) - return (result, size) + return result_str, size class IncrementalDecoder(codecs.BufferedIncrementalDecoder): - def _buffer_decode(self, data, errors, final): + def _buffer_decode(self, data, errors, final): # type: ignore + # type: (str, str, bool) -> Tuple[str, int] if errors != 'strict': - raise IDNAError("Unsupported error handling \"{0}\"".format(errors)) + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return (u"", 0) + return ('', 0) - # IDNA allows decoding to operate on Unicode strings, too. - if isinstance(data, unicode): - labels = _unicode_dots_re.split(data) - else: - # Must be ASCII string - data = str(data) - unicode(data, "ascii") - labels = data.split(".") - - trailing_dot = u'' + labels = _unicode_dots_re.split(data) + trailing_dot = '' if labels: if not labels[-1]: - trailing_dot = u'.' + trailing_dot = '.' del labels[-1] elif not final: # Keep potentially unfinished label until the next call del labels[-1] if labels: - trailing_dot = u'.' + trailing_dot = '.' result = [] size = 0 @@ -95,22 +90,26 @@ class IncrementalDecoder(codecs.BufferedIncrementalDecoder): size += 1 size += len(label) - result = u".".join(result) + trailing_dot + result_str = '.'.join(result) + trailing_dot size += len(trailing_dot) - return (result, size) + return (result_str, size) class StreamWriter(Codec, codecs.StreamWriter): pass + class StreamReader(Codec, codecs.StreamReader): pass + def getregentry(): + # type: () -> codecs.CodecInfo + # Compatibility as a search_function for codecs.register() return codecs.CodecInfo( name='idna', - encode=Codec().encode, - decode=Codec().decode, + encode=Codec().encode, # type: ignore + decode=Codec().decode, # type: ignore incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, diff --git a/pipenv/vendor/idna/compat.py b/pipenv/vendor/idna/compat.py index 4d47f336..dc896c76 100644 --- a/pipenv/vendor/idna/compat.py +++ b/pipenv/vendor/idna/compat.py @@ -1,12 +1,16 @@ from .core import * from .codec import * +from typing import Any, Union def ToASCII(label): + # type: (str) -> bytes return encode(label) def ToUnicode(label): + # type: (Union[bytes, bytearray]) -> str return decode(label) def nameprep(s): - raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") + # type: (Any) -> None + raise NotImplementedError('IDNA 2008 does not utilise nameprep protocol') diff --git a/pipenv/vendor/idna/core.py b/pipenv/vendor/idna/core.py index 41ec5c71..d6051297 100644 --- a/pipenv/vendor/idna/core.py +++ b/pipenv/vendor/idna/core.py @@ -2,16 +2,12 @@ from . import idnadata import bisect import unicodedata import re -import sys +from typing import Union, Optional from .intranges import intranges_contain _virama_combining_class = 9 _alabel_prefix = b'xn--' -_unicode_dots_re = re.compile(u'[\u002e\u3002\uff0e\uff61]') - -if sys.version_info[0] >= 3: - unicode = str - unichr = chr +_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') class IDNAError(UnicodeError): """ Base exception for all IDNA-encoding related problems """ @@ -34,45 +30,49 @@ class InvalidCodepointContext(IDNAError): def _combining_class(cp): - v = unicodedata.combining(unichr(cp)) + # type: (int) -> int + v = unicodedata.combining(chr(cp)) if v == 0: - if not unicodedata.name(unichr(cp)): - raise ValueError("Unknown character in unicodedata") + if not unicodedata.name(chr(cp)): + raise ValueError('Unknown character in unicodedata') return v def _is_script(cp, script): + # type: (str, str) -> bool return intranges_contain(ord(cp), idnadata.scripts[script]) def _punycode(s): + # type: (str) -> bytes return s.encode('punycode') def _unot(s): - return 'U+{0:04X}'.format(s) + # type: (int) -> str + return 'U+{:04X}'.format(s) def valid_label_length(label): - + # type: (Union[bytes, str]) -> bool if len(label) > 63: return False return True def valid_string_length(label, trailing_dot): - + # type: (Union[bytes, str], bool) -> bool if len(label) > (254 if trailing_dot else 253): return False return True def check_bidi(label, check_ltr=False): - + # type: (str, bool) -> bool # Bidi rules should only be applied if string contains RTL characters bidi_label = False for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) if direction == '': # String likely comes from a newer version of Unicode - raise IDNABidiError('Unknown directionality in label {0} at position {1}'.format(repr(label), idx)) + raise IDNABidiError('Unknown directionality in label {} at position {}'.format(repr(label), idx)) if direction in ['R', 'AL', 'AN']: bidi_label = True if not bidi_label and not check_ltr: @@ -85,17 +85,17 @@ def check_bidi(label, check_ltr=False): elif direction == 'L': rtl = False else: - raise IDNABidiError('First codepoint in label {0} must be directionality L, R or AL'.format(repr(label))) + raise IDNABidiError('First codepoint in label {} must be directionality L, R or AL'.format(repr(label))) valid_ending = False - number_type = False + number_type = None # type: Optional[str] for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) if rtl: # Bidi rule 2 if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: - raise IDNABidiError('Invalid direction for codepoint at position {0} in a right-to-left label'.format(idx)) + raise IDNABidiError('Invalid direction for codepoint at position {} in a right-to-left label'.format(idx)) # Bidi rule 3 if direction in ['R', 'AL', 'EN', 'AN']: valid_ending = True @@ -111,7 +111,7 @@ def check_bidi(label, check_ltr=False): else: # Bidi rule 5 if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: - raise IDNABidiError('Invalid direction for codepoint at position {0} in a left-to-right label'.format(idx)) + raise IDNABidiError('Invalid direction for codepoint at position {} in a left-to-right label'.format(idx)) # Bidi rule 6 if direction in ['L', 'EN']: valid_ending = True @@ -125,14 +125,14 @@ def check_bidi(label, check_ltr=False): def check_initial_combiner(label): - + # type: (str) -> bool if unicodedata.category(label[0])[0] == 'M': raise IDNAError('Label begins with an illegal combining character') return True def check_hyphen_ok(label): - + # type: (str) -> bool if label[2:4] == '--': raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') if label[0] == '-' or label[-1] == '-': @@ -141,13 +141,13 @@ def check_hyphen_ok(label): def check_nfc(label): - + # type: (str) -> None if unicodedata.normalize('NFC', label) != label: raise IDNAError('Label must be in Normalization Form C') def valid_contextj(label, pos): - + # type: (str, int) -> bool cp_value = ord(label[pos]) if cp_value == 0x200c: @@ -191,7 +191,7 @@ def valid_contextj(label, pos): def valid_contexto(label, pos, exception=False): - + # type: (str, int, bool) -> bool cp_value = ord(label[pos]) if cp_value == 0x00b7: @@ -212,7 +212,7 @@ def valid_contexto(label, pos, exception=False): elif cp_value == 0x30fb: for cp in label: - if cp == u'\u30fb': + if cp == '\u30fb': continue if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): return True @@ -230,9 +230,11 @@ def valid_contexto(label, pos, exception=False): return False return True + return False + def check_label(label): - + # type: (Union[str, bytes, bytearray]) -> None if isinstance(label, (bytes, bytearray)): label = label.decode('utf-8') if len(label) == 0: @@ -249,102 +251,109 @@ def check_label(label): elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): try: if not valid_contextj(label, pos): - raise InvalidCodepointContext('Joiner {0} not allowed at position {1} in {2}'.format( + raise InvalidCodepointContext('Joiner {} not allowed at position {} in {}'.format( _unot(cp_value), pos+1, repr(label))) except ValueError: - raise IDNAError('Unknown codepoint adjacent to joiner {0} at position {1} in {2}'.format( + raise IDNAError('Unknown codepoint adjacent to joiner {} at position {} in {}'.format( _unot(cp_value), pos+1, repr(label))) elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): if not valid_contexto(label, pos): - raise InvalidCodepointContext('Codepoint {0} not allowed at position {1} in {2}'.format(_unot(cp_value), pos+1, repr(label))) + raise InvalidCodepointContext('Codepoint {} not allowed at position {} in {}'.format(_unot(cp_value), pos+1, repr(label))) else: - raise InvalidCodepoint('Codepoint {0} at position {1} of {2} not allowed'.format(_unot(cp_value), pos+1, repr(label))) + raise InvalidCodepoint('Codepoint {} at position {} of {} not allowed'.format(_unot(cp_value), pos+1, repr(label))) check_bidi(label) def alabel(label): - + # type: (str) -> bytes try: - label = label.encode('ascii') - ulabel(label) - if not valid_label_length(label): + label_bytes = label.encode('ascii') + ulabel(label_bytes) + if not valid_label_length(label_bytes): raise IDNAError('Label too long') - return label + return label_bytes except UnicodeEncodeError: pass if not label: raise IDNAError('No Input') - label = unicode(label) + label = str(label) check_label(label) - label = _punycode(label) - label = _alabel_prefix + label + label_bytes = _punycode(label) + label_bytes = _alabel_prefix + label_bytes - if not valid_label_length(label): + if not valid_label_length(label_bytes): raise IDNAError('Label too long') - return label + return label_bytes def ulabel(label): - + # type: (Union[str, bytes, bytearray]) -> str if not isinstance(label, (bytes, bytearray)): try: - label = label.encode('ascii') + label_bytes = label.encode('ascii') except UnicodeEncodeError: check_label(label) return label + else: + label_bytes = label - label = label.lower() - if label.startswith(_alabel_prefix): - label = label[len(_alabel_prefix):] - if not label: + label_bytes = label_bytes.lower() + if label_bytes.startswith(_alabel_prefix): + label_bytes = label_bytes[len(_alabel_prefix):] + if not label_bytes: raise IDNAError('Malformed A-label, no Punycode eligible content found') - if label.decode('ascii')[-1] == '-': + if label_bytes.decode('ascii')[-1] == '-': raise IDNAError('A-label must not end with a hyphen') else: - check_label(label) - return label.decode('ascii') + check_label(label_bytes) + return label_bytes.decode('ascii') - label = label.decode('punycode') + label = label_bytes.decode('punycode') check_label(label) return label def uts46_remap(domain, std3_rules=True, transitional=False): + # type: (str, bool, bool) -> str """Re-map the characters in the string according to UTS46 processing.""" from .uts46data import uts46data - output = u"" - try: - for pos, char in enumerate(domain): - code_point = ord(char) + output = '' + + for pos, char in enumerate(domain): + code_point = ord(char) + try: uts46row = uts46data[code_point if code_point < 256 else - bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + bisect.bisect_left(uts46data, (code_point, 'Z')) - 1] status = uts46row[1] - replacement = uts46row[2] if len(uts46row) == 3 else None - if (status == "V" or - (status == "D" and not transitional) or - (status == "3" and not std3_rules and replacement is None)): + replacement = None # type: Optional[str] + if len(uts46row) == 3: + replacement = uts46row[2] # type: ignore + if (status == 'V' or + (status == 'D' and not transitional) or + (status == '3' and not std3_rules and replacement is None)): output += char - elif replacement is not None and (status == "M" or - (status == "3" and not std3_rules) or - (status == "D" and transitional)): + elif replacement is not None and (status == 'M' or + (status == '3' and not std3_rules) or + (status == 'D' and transitional)): output += replacement - elif status != "I": + elif status != 'I': raise IndexError() - return unicodedata.normalize("NFC", output) - except IndexError: - raise InvalidCodepoint( - "Codepoint {0} not allowed at position {1} in {2}".format( - _unot(code_point), pos + 1, repr(domain))) + except IndexError: + raise InvalidCodepoint( + 'Codepoint {} not allowed at position {} in {}'.format( + _unot(code_point), pos + 1, repr(domain))) + + return unicodedata.normalize('NFC', output) def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): - + # type: (Union[str, bytes, bytearray], bool, bool, bool, bool) -> bytes if isinstance(s, (bytes, bytearray)): - s = s.decode("ascii") + s = s.decode('ascii') if uts46: s = uts46_remap(s, std3_rules, transitional) trailing_dot = False @@ -373,9 +382,9 @@ def encode(s, strict=False, uts46=False, std3_rules=False, transitional=False): def decode(s, strict=False, uts46=False, std3_rules=False): - + # type: (Union[str, bytes, bytearray], bool, bool, bool) -> str if isinstance(s, (bytes, bytearray)): - s = s.decode("ascii") + s = s.decode('ascii') if uts46: s = uts46_remap(s, std3_rules, False) trailing_dot = False @@ -383,7 +392,7 @@ def decode(s, strict=False, uts46=False, std3_rules=False): if not strict: labels = _unicode_dots_re.split(s) else: - labels = s.split(u'.') + labels = s.split('.') if not labels or labels == ['']: raise IDNAError('Empty domain') if not labels[-1]: @@ -396,5 +405,5 @@ def decode(s, strict=False, uts46=False, std3_rules=False): else: raise IDNAError('Empty label') if trailing_dot: - result.append(u'') - return u'.'.join(result) + result.append('') + return '.'.join(result) diff --git a/pipenv/vendor/idna/idnadata.py b/pipenv/vendor/idna/idnadata.py index a284e4c8..b86a3e06 100644 --- a/pipenv/vendor/idna/idnadata.py +++ b/pipenv/vendor/idna/idnadata.py @@ -1,6 +1,6 @@ # This file is automatically generated by tools/idna-data -__version__ = "13.0.0" +__version__ = '13.0.0' scripts = { 'Greek': ( 0x37000000374, diff --git a/pipenv/vendor/idna/intranges.py b/pipenv/vendor/idna/intranges.py index fa8a7356..ee364a90 100644 --- a/pipenv/vendor/idna/intranges.py +++ b/pipenv/vendor/idna/intranges.py @@ -6,8 +6,10 @@ in the original list?" in time O(log(# runs)). """ import bisect +from typing import List, Tuple def intranges_from_list(list_): + # type: (List[int]) -> Tuple[int, ...] """Represent a list of integers as a sequence of ranges: ((start_0, end_0), (start_1, end_1), ...), such that the original integers are exactly those x such that start_i <= x < end_i for some i. @@ -29,13 +31,16 @@ def intranges_from_list(list_): return tuple(ranges) def _encode_range(start, end): + # type: (int, int) -> int return (start << 32) | end def _decode_range(r): + # type: (int) -> Tuple[int, int] return (r >> 32), (r & ((1 << 32) - 1)) def intranges_contain(int_, ranges): + # type: (int, Tuple[int, ...]) -> bool """Determine if `int_` falls into one of the ranges in `ranges`.""" tuple_ = _encode_range(int_, 0) pos = bisect.bisect_left(ranges, tuple_) diff --git a/pipenv/vendor/idna/package_data.py b/pipenv/vendor/idna/package_data.py index ce1c521d..e096d1d5 100644 --- a/pipenv/vendor/idna/package_data.py +++ b/pipenv/vendor/idna/package_data.py @@ -1,2 +1,2 @@ -__version__ = '2.10' +__version__ = '3.2' diff --git a/pipenv/vendor/more_itertools/tests/__init__.py b/pipenv/vendor/idna/py.typed similarity index 100% rename from pipenv/vendor/more_itertools/tests/__init__.py rename to pipenv/vendor/idna/py.typed diff --git a/pipenv/vendor/idna/uts46data.py b/pipenv/vendor/idna/uts46data.py index 3766dd49..f382ce38 100644 --- a/pipenv/vendor/idna/uts46data.py +++ b/pipenv/vendor/idna/uts46data.py @@ -1,11 +1,13 @@ # This file is automatically generated by tools/idna-data -# vim: set fileencoding=utf-8 : + +from typing import List, Tuple, Union """IDNA Mapping Table from UTS46.""" -__version__ = "13.0.0" +__version__ = '13.0.0' def _seg_0(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x0, '3'), (0x1, '3'), @@ -72,32 +74,32 @@ def _seg_0(): (0x3E, '3'), (0x3F, '3'), (0x40, '3'), - (0x41, 'M', u'a'), - (0x42, 'M', u'b'), - (0x43, 'M', u'c'), - (0x44, 'M', u'd'), - (0x45, 'M', u'e'), - (0x46, 'M', u'f'), - (0x47, 'M', u'g'), - (0x48, 'M', u'h'), - (0x49, 'M', u'i'), - (0x4A, 'M', u'j'), - (0x4B, 'M', u'k'), - (0x4C, 'M', u'l'), - (0x4D, 'M', u'm'), - (0x4E, 'M', u'n'), - (0x4F, 'M', u'o'), - (0x50, 'M', u'p'), - (0x51, 'M', u'q'), - (0x52, 'M', u'r'), - (0x53, 'M', u's'), - (0x54, 'M', u't'), - (0x55, 'M', u'u'), - (0x56, 'M', u'v'), - (0x57, 'M', u'w'), - (0x58, 'M', u'x'), - (0x59, 'M', u'y'), - (0x5A, 'M', u'z'), + (0x41, 'M', 'a'), + (0x42, 'M', 'b'), + (0x43, 'M', 'c'), + (0x44, 'M', 'd'), + (0x45, 'M', 'e'), + (0x46, 'M', 'f'), + (0x47, 'M', 'g'), + (0x48, 'M', 'h'), + (0x49, 'M', 'i'), + (0x4A, 'M', 'j'), + (0x4B, 'M', 'k'), + (0x4C, 'M', 'l'), + (0x4D, 'M', 'm'), + (0x4E, 'M', 'n'), + (0x4F, 'M', 'o'), + (0x50, 'M', 'p'), + (0x51, 'M', 'q'), + (0x52, 'M', 'r'), + (0x53, 'M', 's'), + (0x54, 'M', 't'), + (0x55, 'M', 'u'), + (0x56, 'M', 'v'), + (0x57, 'M', 'w'), + (0x58, 'M', 'x'), + (0x59, 'M', 'y'), + (0x5A, 'M', 'z'), (0x5B, '3'), (0x5C, '3'), (0x5D, '3'), @@ -110,6 +112,7 @@ def _seg_0(): ] def _seg_1(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x64, 'V'), (0x65, 'V'), @@ -171,7 +174,7 @@ def _seg_1(): (0x9D, 'X'), (0x9E, 'X'), (0x9F, 'X'), - (0xA0, '3', u' '), + (0xA0, '3', ' '), (0xA1, 'V'), (0xA2, 'V'), (0xA3, 'V'), @@ -179,66 +182,67 @@ def _seg_1(): (0xA5, 'V'), (0xA6, 'V'), (0xA7, 'V'), - (0xA8, '3', u' ̈'), + (0xA8, '3', ' ̈'), (0xA9, 'V'), - (0xAA, 'M', u'a'), + (0xAA, 'M', 'a'), (0xAB, 'V'), (0xAC, 'V'), (0xAD, 'I'), (0xAE, 'V'), - (0xAF, '3', u' ̄'), + (0xAF, '3', ' ̄'), (0xB0, 'V'), (0xB1, 'V'), - (0xB2, 'M', u'2'), - (0xB3, 'M', u'3'), - (0xB4, '3', u' ́'), - (0xB5, 'M', u'μ'), + (0xB2, 'M', '2'), + (0xB3, 'M', '3'), + (0xB4, '3', ' ́'), + (0xB5, 'M', 'μ'), (0xB6, 'V'), (0xB7, 'V'), - (0xB8, '3', u' ̧'), - (0xB9, 'M', u'1'), - (0xBA, 'M', u'o'), + (0xB8, '3', ' ̧'), + (0xB9, 'M', '1'), + (0xBA, 'M', 'o'), (0xBB, 'V'), - (0xBC, 'M', u'1⁄4'), - (0xBD, 'M', u'1⁄2'), - (0xBE, 'M', u'3⁄4'), + (0xBC, 'M', '1⁄4'), + (0xBD, 'M', '1⁄2'), + (0xBE, 'M', '3⁄4'), (0xBF, 'V'), - (0xC0, 'M', u'à'), - (0xC1, 'M', u'á'), - (0xC2, 'M', u'â'), - (0xC3, 'M', u'ã'), - (0xC4, 'M', u'ä'), - (0xC5, 'M', u'å'), - (0xC6, 'M', u'æ'), - (0xC7, 'M', u'ç'), + (0xC0, 'M', 'à'), + (0xC1, 'M', 'á'), + (0xC2, 'M', 'â'), + (0xC3, 'M', 'ã'), + (0xC4, 'M', 'ä'), + (0xC5, 'M', 'å'), + (0xC6, 'M', 'æ'), + (0xC7, 'M', 'ç'), ] def _seg_2(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xC8, 'M', u'è'), - (0xC9, 'M', u'é'), - (0xCA, 'M', u'ê'), - (0xCB, 'M', u'ë'), - (0xCC, 'M', u'ì'), - (0xCD, 'M', u'í'), - (0xCE, 'M', u'î'), - (0xCF, 'M', u'ï'), - (0xD0, 'M', u'ð'), - (0xD1, 'M', u'ñ'), - (0xD2, 'M', u'ò'), - (0xD3, 'M', u'ó'), - (0xD4, 'M', u'ô'), - (0xD5, 'M', u'õ'), - (0xD6, 'M', u'ö'), + (0xC8, 'M', 'è'), + (0xC9, 'M', 'é'), + (0xCA, 'M', 'ê'), + (0xCB, 'M', 'ë'), + (0xCC, 'M', 'ì'), + (0xCD, 'M', 'í'), + (0xCE, 'M', 'î'), + (0xCF, 'M', 'ï'), + (0xD0, 'M', 'ð'), + (0xD1, 'M', 'ñ'), + (0xD2, 'M', 'ò'), + (0xD3, 'M', 'ó'), + (0xD4, 'M', 'ô'), + (0xD5, 'M', 'õ'), + (0xD6, 'M', 'ö'), (0xD7, 'V'), - (0xD8, 'M', u'ø'), - (0xD9, 'M', u'ù'), - (0xDA, 'M', u'ú'), - (0xDB, 'M', u'û'), - (0xDC, 'M', u'ü'), - (0xDD, 'M', u'ý'), - (0xDE, 'M', u'þ'), - (0xDF, 'D', u'ss'), + (0xD8, 'M', 'ø'), + (0xD9, 'M', 'ù'), + (0xDA, 'M', 'ú'), + (0xDB, 'M', 'û'), + (0xDC, 'M', 'ü'), + (0xDD, 'M', 'ý'), + (0xDE, 'M', 'þ'), + (0xDF, 'D', 'ss'), (0xE0, 'V'), (0xE1, 'V'), (0xE2, 'V'), @@ -271,765 +275,772 @@ def _seg_2(): (0xFD, 'V'), (0xFE, 'V'), (0xFF, 'V'), - (0x100, 'M', u'ā'), + (0x100, 'M', 'ā'), (0x101, 'V'), - (0x102, 'M', u'ă'), + (0x102, 'M', 'ă'), (0x103, 'V'), - (0x104, 'M', u'ą'), + (0x104, 'M', 'ą'), (0x105, 'V'), - (0x106, 'M', u'ć'), + (0x106, 'M', 'ć'), (0x107, 'V'), - (0x108, 'M', u'ĉ'), + (0x108, 'M', 'ĉ'), (0x109, 'V'), - (0x10A, 'M', u'ċ'), + (0x10A, 'M', 'ċ'), (0x10B, 'V'), - (0x10C, 'M', u'č'), + (0x10C, 'M', 'č'), (0x10D, 'V'), - (0x10E, 'M', u'ď'), + (0x10E, 'M', 'ď'), (0x10F, 'V'), - (0x110, 'M', u'đ'), + (0x110, 'M', 'đ'), (0x111, 'V'), - (0x112, 'M', u'ē'), + (0x112, 'M', 'ē'), (0x113, 'V'), - (0x114, 'M', u'ĕ'), + (0x114, 'M', 'ĕ'), (0x115, 'V'), - (0x116, 'M', u'ė'), + (0x116, 'M', 'ė'), (0x117, 'V'), - (0x118, 'M', u'ę'), + (0x118, 'M', 'ę'), (0x119, 'V'), - (0x11A, 'M', u'ě'), + (0x11A, 'M', 'ě'), (0x11B, 'V'), - (0x11C, 'M', u'ĝ'), + (0x11C, 'M', 'ĝ'), (0x11D, 'V'), - (0x11E, 'M', u'ğ'), + (0x11E, 'M', 'ğ'), (0x11F, 'V'), - (0x120, 'M', u'ġ'), + (0x120, 'M', 'ġ'), (0x121, 'V'), - (0x122, 'M', u'ģ'), + (0x122, 'M', 'ģ'), (0x123, 'V'), - (0x124, 'M', u'ĥ'), + (0x124, 'M', 'ĥ'), (0x125, 'V'), - (0x126, 'M', u'ħ'), + (0x126, 'M', 'ħ'), (0x127, 'V'), - (0x128, 'M', u'ĩ'), + (0x128, 'M', 'ĩ'), (0x129, 'V'), - (0x12A, 'M', u'ī'), + (0x12A, 'M', 'ī'), (0x12B, 'V'), ] def _seg_3(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x12C, 'M', u'ĭ'), + (0x12C, 'M', 'ĭ'), (0x12D, 'V'), - (0x12E, 'M', u'į'), + (0x12E, 'M', 'į'), (0x12F, 'V'), - (0x130, 'M', u'i̇'), + (0x130, 'M', 'i̇'), (0x131, 'V'), - (0x132, 'M', u'ij'), - (0x134, 'M', u'ĵ'), + (0x132, 'M', 'ij'), + (0x134, 'M', 'ĵ'), (0x135, 'V'), - (0x136, 'M', u'ķ'), + (0x136, 'M', 'ķ'), (0x137, 'V'), - (0x139, 'M', u'ĺ'), + (0x139, 'M', 'ĺ'), (0x13A, 'V'), - (0x13B, 'M', u'ļ'), + (0x13B, 'M', 'ļ'), (0x13C, 'V'), - (0x13D, 'M', u'ľ'), + (0x13D, 'M', 'ľ'), (0x13E, 'V'), - (0x13F, 'M', u'l·'), - (0x141, 'M', u'ł'), + (0x13F, 'M', 'l·'), + (0x141, 'M', 'ł'), (0x142, 'V'), - (0x143, 'M', u'ń'), + (0x143, 'M', 'ń'), (0x144, 'V'), - (0x145, 'M', u'ņ'), + (0x145, 'M', 'ņ'), (0x146, 'V'), - (0x147, 'M', u'ň'), + (0x147, 'M', 'ň'), (0x148, 'V'), - (0x149, 'M', u'ʼn'), - (0x14A, 'M', u'ŋ'), + (0x149, 'M', 'ʼn'), + (0x14A, 'M', 'ŋ'), (0x14B, 'V'), - (0x14C, 'M', u'ō'), + (0x14C, 'M', 'ō'), (0x14D, 'V'), - (0x14E, 'M', u'ŏ'), + (0x14E, 'M', 'ŏ'), (0x14F, 'V'), - (0x150, 'M', u'ő'), + (0x150, 'M', 'ő'), (0x151, 'V'), - (0x152, 'M', u'œ'), + (0x152, 'M', 'œ'), (0x153, 'V'), - (0x154, 'M', u'ŕ'), + (0x154, 'M', 'ŕ'), (0x155, 'V'), - (0x156, 'M', u'ŗ'), + (0x156, 'M', 'ŗ'), (0x157, 'V'), - (0x158, 'M', u'ř'), + (0x158, 'M', 'ř'), (0x159, 'V'), - (0x15A, 'M', u'ś'), + (0x15A, 'M', 'ś'), (0x15B, 'V'), - (0x15C, 'M', u'ŝ'), + (0x15C, 'M', 'ŝ'), (0x15D, 'V'), - (0x15E, 'M', u'ş'), + (0x15E, 'M', 'ş'), (0x15F, 'V'), - (0x160, 'M', u'š'), + (0x160, 'M', 'š'), (0x161, 'V'), - (0x162, 'M', u'ţ'), + (0x162, 'M', 'ţ'), (0x163, 'V'), - (0x164, 'M', u'ť'), + (0x164, 'M', 'ť'), (0x165, 'V'), - (0x166, 'M', u'ŧ'), + (0x166, 'M', 'ŧ'), (0x167, 'V'), - (0x168, 'M', u'ũ'), + (0x168, 'M', 'ũ'), (0x169, 'V'), - (0x16A, 'M', u'ū'), + (0x16A, 'M', 'ū'), (0x16B, 'V'), - (0x16C, 'M', u'ŭ'), + (0x16C, 'M', 'ŭ'), (0x16D, 'V'), - (0x16E, 'M', u'ů'), + (0x16E, 'M', 'ů'), (0x16F, 'V'), - (0x170, 'M', u'ű'), + (0x170, 'M', 'ű'), (0x171, 'V'), - (0x172, 'M', u'ų'), + (0x172, 'M', 'ų'), (0x173, 'V'), - (0x174, 'M', u'ŵ'), + (0x174, 'M', 'ŵ'), (0x175, 'V'), - (0x176, 'M', u'ŷ'), + (0x176, 'M', 'ŷ'), (0x177, 'V'), - (0x178, 'M', u'ÿ'), - (0x179, 'M', u'ź'), + (0x178, 'M', 'ÿ'), + (0x179, 'M', 'ź'), (0x17A, 'V'), - (0x17B, 'M', u'ż'), + (0x17B, 'M', 'ż'), (0x17C, 'V'), - (0x17D, 'M', u'ž'), + (0x17D, 'M', 'ž'), (0x17E, 'V'), - (0x17F, 'M', u's'), + (0x17F, 'M', 's'), (0x180, 'V'), - (0x181, 'M', u'ɓ'), - (0x182, 'M', u'ƃ'), + (0x181, 'M', 'ɓ'), + (0x182, 'M', 'ƃ'), (0x183, 'V'), - (0x184, 'M', u'ƅ'), + (0x184, 'M', 'ƅ'), (0x185, 'V'), - (0x186, 'M', u'ɔ'), - (0x187, 'M', u'ƈ'), + (0x186, 'M', 'ɔ'), + (0x187, 'M', 'ƈ'), (0x188, 'V'), - (0x189, 'M', u'ɖ'), - (0x18A, 'M', u'ɗ'), - (0x18B, 'M', u'ƌ'), + (0x189, 'M', 'ɖ'), + (0x18A, 'M', 'ɗ'), + (0x18B, 'M', 'ƌ'), (0x18C, 'V'), - (0x18E, 'M', u'ǝ'), - (0x18F, 'M', u'ə'), - (0x190, 'M', u'ɛ'), - (0x191, 'M', u'ƒ'), + (0x18E, 'M', 'ǝ'), + (0x18F, 'M', 'ə'), + (0x190, 'M', 'ɛ'), + (0x191, 'M', 'ƒ'), (0x192, 'V'), - (0x193, 'M', u'ɠ'), + (0x193, 'M', 'ɠ'), ] def _seg_4(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x194, 'M', u'ɣ'), + (0x194, 'M', 'ɣ'), (0x195, 'V'), - (0x196, 'M', u'ɩ'), - (0x197, 'M', u'ɨ'), - (0x198, 'M', u'ƙ'), + (0x196, 'M', 'ɩ'), + (0x197, 'M', 'ɨ'), + (0x198, 'M', 'ƙ'), (0x199, 'V'), - (0x19C, 'M', u'ɯ'), - (0x19D, 'M', u'ɲ'), + (0x19C, 'M', 'ɯ'), + (0x19D, 'M', 'ɲ'), (0x19E, 'V'), - (0x19F, 'M', u'ɵ'), - (0x1A0, 'M', u'ơ'), + (0x19F, 'M', 'ɵ'), + (0x1A0, 'M', 'ơ'), (0x1A1, 'V'), - (0x1A2, 'M', u'ƣ'), + (0x1A2, 'M', 'ƣ'), (0x1A3, 'V'), - (0x1A4, 'M', u'ƥ'), + (0x1A4, 'M', 'ƥ'), (0x1A5, 'V'), - (0x1A6, 'M', u'ʀ'), - (0x1A7, 'M', u'ƨ'), + (0x1A6, 'M', 'ʀ'), + (0x1A7, 'M', 'ƨ'), (0x1A8, 'V'), - (0x1A9, 'M', u'ʃ'), + (0x1A9, 'M', 'ʃ'), (0x1AA, 'V'), - (0x1AC, 'M', u'ƭ'), + (0x1AC, 'M', 'ƭ'), (0x1AD, 'V'), - (0x1AE, 'M', u'ʈ'), - (0x1AF, 'M', u'ư'), + (0x1AE, 'M', 'ʈ'), + (0x1AF, 'M', 'ư'), (0x1B0, 'V'), - (0x1B1, 'M', u'ʊ'), - (0x1B2, 'M', u'ʋ'), - (0x1B3, 'M', u'ƴ'), + (0x1B1, 'M', 'ʊ'), + (0x1B2, 'M', 'ʋ'), + (0x1B3, 'M', 'ƴ'), (0x1B4, 'V'), - (0x1B5, 'M', u'ƶ'), + (0x1B5, 'M', 'ƶ'), (0x1B6, 'V'), - (0x1B7, 'M', u'ʒ'), - (0x1B8, 'M', u'ƹ'), + (0x1B7, 'M', 'ʒ'), + (0x1B8, 'M', 'ƹ'), (0x1B9, 'V'), - (0x1BC, 'M', u'ƽ'), + (0x1BC, 'M', 'ƽ'), (0x1BD, 'V'), - (0x1C4, 'M', u'dž'), - (0x1C7, 'M', u'lj'), - (0x1CA, 'M', u'nj'), - (0x1CD, 'M', u'ǎ'), + (0x1C4, 'M', 'dž'), + (0x1C7, 'M', 'lj'), + (0x1CA, 'M', 'nj'), + (0x1CD, 'M', 'ǎ'), (0x1CE, 'V'), - (0x1CF, 'M', u'ǐ'), + (0x1CF, 'M', 'ǐ'), (0x1D0, 'V'), - (0x1D1, 'M', u'ǒ'), + (0x1D1, 'M', 'ǒ'), (0x1D2, 'V'), - (0x1D3, 'M', u'ǔ'), + (0x1D3, 'M', 'ǔ'), (0x1D4, 'V'), - (0x1D5, 'M', u'ǖ'), + (0x1D5, 'M', 'ǖ'), (0x1D6, 'V'), - (0x1D7, 'M', u'ǘ'), + (0x1D7, 'M', 'ǘ'), (0x1D8, 'V'), - (0x1D9, 'M', u'ǚ'), + (0x1D9, 'M', 'ǚ'), (0x1DA, 'V'), - (0x1DB, 'M', u'ǜ'), + (0x1DB, 'M', 'ǜ'), (0x1DC, 'V'), - (0x1DE, 'M', u'ǟ'), + (0x1DE, 'M', 'ǟ'), (0x1DF, 'V'), - (0x1E0, 'M', u'ǡ'), + (0x1E0, 'M', 'ǡ'), (0x1E1, 'V'), - (0x1E2, 'M', u'ǣ'), + (0x1E2, 'M', 'ǣ'), (0x1E3, 'V'), - (0x1E4, 'M', u'ǥ'), + (0x1E4, 'M', 'ǥ'), (0x1E5, 'V'), - (0x1E6, 'M', u'ǧ'), + (0x1E6, 'M', 'ǧ'), (0x1E7, 'V'), - (0x1E8, 'M', u'ǩ'), + (0x1E8, 'M', 'ǩ'), (0x1E9, 'V'), - (0x1EA, 'M', u'ǫ'), + (0x1EA, 'M', 'ǫ'), (0x1EB, 'V'), - (0x1EC, 'M', u'ǭ'), + (0x1EC, 'M', 'ǭ'), (0x1ED, 'V'), - (0x1EE, 'M', u'ǯ'), + (0x1EE, 'M', 'ǯ'), (0x1EF, 'V'), - (0x1F1, 'M', u'dz'), - (0x1F4, 'M', u'ǵ'), + (0x1F1, 'M', 'dz'), + (0x1F4, 'M', 'ǵ'), (0x1F5, 'V'), - (0x1F6, 'M', u'ƕ'), - (0x1F7, 'M', u'ƿ'), - (0x1F8, 'M', u'ǹ'), + (0x1F6, 'M', 'ƕ'), + (0x1F7, 'M', 'ƿ'), + (0x1F8, 'M', 'ǹ'), (0x1F9, 'V'), - (0x1FA, 'M', u'ǻ'), + (0x1FA, 'M', 'ǻ'), (0x1FB, 'V'), - (0x1FC, 'M', u'ǽ'), + (0x1FC, 'M', 'ǽ'), (0x1FD, 'V'), - (0x1FE, 'M', u'ǿ'), + (0x1FE, 'M', 'ǿ'), (0x1FF, 'V'), - (0x200, 'M', u'ȁ'), + (0x200, 'M', 'ȁ'), (0x201, 'V'), - (0x202, 'M', u'ȃ'), + (0x202, 'M', 'ȃ'), (0x203, 'V'), - (0x204, 'M', u'ȅ'), + (0x204, 'M', 'ȅ'), (0x205, 'V'), - (0x206, 'M', u'ȇ'), + (0x206, 'M', 'ȇ'), (0x207, 'V'), - (0x208, 'M', u'ȉ'), + (0x208, 'M', 'ȉ'), (0x209, 'V'), - (0x20A, 'M', u'ȋ'), + (0x20A, 'M', 'ȋ'), (0x20B, 'V'), - (0x20C, 'M', u'ȍ'), + (0x20C, 'M', 'ȍ'), ] def _seg_5(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x20D, 'V'), - (0x20E, 'M', u'ȏ'), + (0x20E, 'M', 'ȏ'), (0x20F, 'V'), - (0x210, 'M', u'ȑ'), + (0x210, 'M', 'ȑ'), (0x211, 'V'), - (0x212, 'M', u'ȓ'), + (0x212, 'M', 'ȓ'), (0x213, 'V'), - (0x214, 'M', u'ȕ'), + (0x214, 'M', 'ȕ'), (0x215, 'V'), - (0x216, 'M', u'ȗ'), + (0x216, 'M', 'ȗ'), (0x217, 'V'), - (0x218, 'M', u'ș'), + (0x218, 'M', 'ș'), (0x219, 'V'), - (0x21A, 'M', u'ț'), + (0x21A, 'M', 'ț'), (0x21B, 'V'), - (0x21C, 'M', u'ȝ'), + (0x21C, 'M', 'ȝ'), (0x21D, 'V'), - (0x21E, 'M', u'ȟ'), + (0x21E, 'M', 'ȟ'), (0x21F, 'V'), - (0x220, 'M', u'ƞ'), + (0x220, 'M', 'ƞ'), (0x221, 'V'), - (0x222, 'M', u'ȣ'), + (0x222, 'M', 'ȣ'), (0x223, 'V'), - (0x224, 'M', u'ȥ'), + (0x224, 'M', 'ȥ'), (0x225, 'V'), - (0x226, 'M', u'ȧ'), + (0x226, 'M', 'ȧ'), (0x227, 'V'), - (0x228, 'M', u'ȩ'), + (0x228, 'M', 'ȩ'), (0x229, 'V'), - (0x22A, 'M', u'ȫ'), + (0x22A, 'M', 'ȫ'), (0x22B, 'V'), - (0x22C, 'M', u'ȭ'), + (0x22C, 'M', 'ȭ'), (0x22D, 'V'), - (0x22E, 'M', u'ȯ'), + (0x22E, 'M', 'ȯ'), (0x22F, 'V'), - (0x230, 'M', u'ȱ'), + (0x230, 'M', 'ȱ'), (0x231, 'V'), - (0x232, 'M', u'ȳ'), + (0x232, 'M', 'ȳ'), (0x233, 'V'), - (0x23A, 'M', u'ⱥ'), - (0x23B, 'M', u'ȼ'), + (0x23A, 'M', 'ⱥ'), + (0x23B, 'M', 'ȼ'), (0x23C, 'V'), - (0x23D, 'M', u'ƚ'), - (0x23E, 'M', u'ⱦ'), + (0x23D, 'M', 'ƚ'), + (0x23E, 'M', 'ⱦ'), (0x23F, 'V'), - (0x241, 'M', u'ɂ'), + (0x241, 'M', 'ɂ'), (0x242, 'V'), - (0x243, 'M', u'ƀ'), - (0x244, 'M', u'ʉ'), - (0x245, 'M', u'ʌ'), - (0x246, 'M', u'ɇ'), + (0x243, 'M', 'ƀ'), + (0x244, 'M', 'ʉ'), + (0x245, 'M', 'ʌ'), + (0x246, 'M', 'ɇ'), (0x247, 'V'), - (0x248, 'M', u'ɉ'), + (0x248, 'M', 'ɉ'), (0x249, 'V'), - (0x24A, 'M', u'ɋ'), + (0x24A, 'M', 'ɋ'), (0x24B, 'V'), - (0x24C, 'M', u'ɍ'), + (0x24C, 'M', 'ɍ'), (0x24D, 'V'), - (0x24E, 'M', u'ɏ'), + (0x24E, 'M', 'ɏ'), (0x24F, 'V'), - (0x2B0, 'M', u'h'), - (0x2B1, 'M', u'ɦ'), - (0x2B2, 'M', u'j'), - (0x2B3, 'M', u'r'), - (0x2B4, 'M', u'ɹ'), - (0x2B5, 'M', u'ɻ'), - (0x2B6, 'M', u'ʁ'), - (0x2B7, 'M', u'w'), - (0x2B8, 'M', u'y'), + (0x2B0, 'M', 'h'), + (0x2B1, 'M', 'ɦ'), + (0x2B2, 'M', 'j'), + (0x2B3, 'M', 'r'), + (0x2B4, 'M', 'ɹ'), + (0x2B5, 'M', 'ɻ'), + (0x2B6, 'M', 'ʁ'), + (0x2B7, 'M', 'w'), + (0x2B8, 'M', 'y'), (0x2B9, 'V'), - (0x2D8, '3', u' ̆'), - (0x2D9, '3', u' ̇'), - (0x2DA, '3', u' ̊'), - (0x2DB, '3', u' ̨'), - (0x2DC, '3', u' ̃'), - (0x2DD, '3', u' ̋'), + (0x2D8, '3', ' ̆'), + (0x2D9, '3', ' ̇'), + (0x2DA, '3', ' ̊'), + (0x2DB, '3', ' ̨'), + (0x2DC, '3', ' ̃'), + (0x2DD, '3', ' ̋'), (0x2DE, 'V'), - (0x2E0, 'M', u'ɣ'), - (0x2E1, 'M', u'l'), - (0x2E2, 'M', u's'), - (0x2E3, 'M', u'x'), - (0x2E4, 'M', u'ʕ'), + (0x2E0, 'M', 'ɣ'), + (0x2E1, 'M', 'l'), + (0x2E2, 'M', 's'), + (0x2E3, 'M', 'x'), + (0x2E4, 'M', 'ʕ'), (0x2E5, 'V'), - (0x340, 'M', u'̀'), - (0x341, 'M', u'́'), + (0x340, 'M', '̀'), + (0x341, 'M', '́'), (0x342, 'V'), - (0x343, 'M', u'̓'), - (0x344, 'M', u'̈́'), - (0x345, 'M', u'ι'), + (0x343, 'M', '̓'), + (0x344, 'M', '̈́'), + (0x345, 'M', 'ι'), (0x346, 'V'), (0x34F, 'I'), (0x350, 'V'), - (0x370, 'M', u'ͱ'), + (0x370, 'M', 'ͱ'), (0x371, 'V'), - (0x372, 'M', u'ͳ'), + (0x372, 'M', 'ͳ'), (0x373, 'V'), - (0x374, 'M', u'ʹ'), + (0x374, 'M', 'ʹ'), (0x375, 'V'), - (0x376, 'M', u'ͷ'), + (0x376, 'M', 'ͷ'), (0x377, 'V'), ] def _seg_6(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x378, 'X'), - (0x37A, '3', u' ι'), + (0x37A, '3', ' ι'), (0x37B, 'V'), - (0x37E, '3', u';'), - (0x37F, 'M', u'ϳ'), + (0x37E, '3', ';'), + (0x37F, 'M', 'ϳ'), (0x380, 'X'), - (0x384, '3', u' ́'), - (0x385, '3', u' ̈́'), - (0x386, 'M', u'ά'), - (0x387, 'M', u'·'), - (0x388, 'M', u'έ'), - (0x389, 'M', u'ή'), - (0x38A, 'M', u'ί'), + (0x384, '3', ' ́'), + (0x385, '3', ' ̈́'), + (0x386, 'M', 'ά'), + (0x387, 'M', '·'), + (0x388, 'M', 'έ'), + (0x389, 'M', 'ή'), + (0x38A, 'M', 'ί'), (0x38B, 'X'), - (0x38C, 'M', u'ό'), + (0x38C, 'M', 'ό'), (0x38D, 'X'), - (0x38E, 'M', u'ύ'), - (0x38F, 'M', u'ώ'), + (0x38E, 'M', 'ύ'), + (0x38F, 'M', 'ώ'), (0x390, 'V'), - (0x391, 'M', u'α'), - (0x392, 'M', u'β'), - (0x393, 'M', u'γ'), - (0x394, 'M', u'δ'), - (0x395, 'M', u'ε'), - (0x396, 'M', u'ζ'), - (0x397, 'M', u'η'), - (0x398, 'M', u'θ'), - (0x399, 'M', u'ι'), - (0x39A, 'M', u'κ'), - (0x39B, 'M', u'λ'), - (0x39C, 'M', u'μ'), - (0x39D, 'M', u'ν'), - (0x39E, 'M', u'ξ'), - (0x39F, 'M', u'ο'), - (0x3A0, 'M', u'π'), - (0x3A1, 'M', u'ρ'), + (0x391, 'M', 'α'), + (0x392, 'M', 'β'), + (0x393, 'M', 'γ'), + (0x394, 'M', 'δ'), + (0x395, 'M', 'ε'), + (0x396, 'M', 'ζ'), + (0x397, 'M', 'η'), + (0x398, 'M', 'θ'), + (0x399, 'M', 'ι'), + (0x39A, 'M', 'κ'), + (0x39B, 'M', 'λ'), + (0x39C, 'M', 'μ'), + (0x39D, 'M', 'ν'), + (0x39E, 'M', 'ξ'), + (0x39F, 'M', 'ο'), + (0x3A0, 'M', 'π'), + (0x3A1, 'M', 'ρ'), (0x3A2, 'X'), - (0x3A3, 'M', u'σ'), - (0x3A4, 'M', u'τ'), - (0x3A5, 'M', u'υ'), - (0x3A6, 'M', u'φ'), - (0x3A7, 'M', u'χ'), - (0x3A8, 'M', u'ψ'), - (0x3A9, 'M', u'ω'), - (0x3AA, 'M', u'ϊ'), - (0x3AB, 'M', u'ϋ'), + (0x3A3, 'M', 'σ'), + (0x3A4, 'M', 'τ'), + (0x3A5, 'M', 'υ'), + (0x3A6, 'M', 'φ'), + (0x3A7, 'M', 'χ'), + (0x3A8, 'M', 'ψ'), + (0x3A9, 'M', 'ω'), + (0x3AA, 'M', 'ϊ'), + (0x3AB, 'M', 'ϋ'), (0x3AC, 'V'), - (0x3C2, 'D', u'σ'), + (0x3C2, 'D', 'σ'), (0x3C3, 'V'), - (0x3CF, 'M', u'ϗ'), - (0x3D0, 'M', u'β'), - (0x3D1, 'M', u'θ'), - (0x3D2, 'M', u'υ'), - (0x3D3, 'M', u'ύ'), - (0x3D4, 'M', u'ϋ'), - (0x3D5, 'M', u'φ'), - (0x3D6, 'M', u'π'), + (0x3CF, 'M', 'ϗ'), + (0x3D0, 'M', 'β'), + (0x3D1, 'M', 'θ'), + (0x3D2, 'M', 'υ'), + (0x3D3, 'M', 'ύ'), + (0x3D4, 'M', 'ϋ'), + (0x3D5, 'M', 'φ'), + (0x3D6, 'M', 'π'), (0x3D7, 'V'), - (0x3D8, 'M', u'ϙ'), + (0x3D8, 'M', 'ϙ'), (0x3D9, 'V'), - (0x3DA, 'M', u'ϛ'), + (0x3DA, 'M', 'ϛ'), (0x3DB, 'V'), - (0x3DC, 'M', u'ϝ'), + (0x3DC, 'M', 'ϝ'), (0x3DD, 'V'), - (0x3DE, 'M', u'ϟ'), + (0x3DE, 'M', 'ϟ'), (0x3DF, 'V'), - (0x3E0, 'M', u'ϡ'), + (0x3E0, 'M', 'ϡ'), (0x3E1, 'V'), - (0x3E2, 'M', u'ϣ'), + (0x3E2, 'M', 'ϣ'), (0x3E3, 'V'), - (0x3E4, 'M', u'ϥ'), + (0x3E4, 'M', 'ϥ'), (0x3E5, 'V'), - (0x3E6, 'M', u'ϧ'), + (0x3E6, 'M', 'ϧ'), (0x3E7, 'V'), - (0x3E8, 'M', u'ϩ'), + (0x3E8, 'M', 'ϩ'), (0x3E9, 'V'), - (0x3EA, 'M', u'ϫ'), + (0x3EA, 'M', 'ϫ'), (0x3EB, 'V'), - (0x3EC, 'M', u'ϭ'), + (0x3EC, 'M', 'ϭ'), (0x3ED, 'V'), - (0x3EE, 'M', u'ϯ'), + (0x3EE, 'M', 'ϯ'), (0x3EF, 'V'), - (0x3F0, 'M', u'κ'), - (0x3F1, 'M', u'ρ'), - (0x3F2, 'M', u'σ'), + (0x3F0, 'M', 'κ'), + (0x3F1, 'M', 'ρ'), + (0x3F2, 'M', 'σ'), (0x3F3, 'V'), - (0x3F4, 'M', u'θ'), - (0x3F5, 'M', u'ε'), + (0x3F4, 'M', 'θ'), + (0x3F5, 'M', 'ε'), (0x3F6, 'V'), - (0x3F7, 'M', u'ϸ'), + (0x3F7, 'M', 'ϸ'), (0x3F8, 'V'), - (0x3F9, 'M', u'σ'), - (0x3FA, 'M', u'ϻ'), + (0x3F9, 'M', 'σ'), + (0x3FA, 'M', 'ϻ'), (0x3FB, 'V'), - (0x3FD, 'M', u'ͻ'), - (0x3FE, 'M', u'ͼ'), - (0x3FF, 'M', u'ͽ'), - (0x400, 'M', u'ѐ'), - (0x401, 'M', u'ё'), - (0x402, 'M', u'ђ'), + (0x3FD, 'M', 'ͻ'), + (0x3FE, 'M', 'ͼ'), + (0x3FF, 'M', 'ͽ'), + (0x400, 'M', 'ѐ'), + (0x401, 'M', 'ё'), + (0x402, 'M', 'ђ'), ] def _seg_7(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x403, 'M', u'ѓ'), - (0x404, 'M', u'є'), - (0x405, 'M', u'ѕ'), - (0x406, 'M', u'і'), - (0x407, 'M', u'ї'), - (0x408, 'M', u'ј'), - (0x409, 'M', u'љ'), - (0x40A, 'M', u'њ'), - (0x40B, 'M', u'ћ'), - (0x40C, 'M', u'ќ'), - (0x40D, 'M', u'ѝ'), - (0x40E, 'M', u'ў'), - (0x40F, 'M', u'џ'), - (0x410, 'M', u'а'), - (0x411, 'M', u'б'), - (0x412, 'M', u'в'), - (0x413, 'M', u'г'), - (0x414, 'M', u'д'), - (0x415, 'M', u'е'), - (0x416, 'M', u'ж'), - (0x417, 'M', u'з'), - (0x418, 'M', u'и'), - (0x419, 'M', u'й'), - (0x41A, 'M', u'к'), - (0x41B, 'M', u'л'), - (0x41C, 'M', u'м'), - (0x41D, 'M', u'н'), - (0x41E, 'M', u'о'), - (0x41F, 'M', u'п'), - (0x420, 'M', u'р'), - (0x421, 'M', u'с'), - (0x422, 'M', u'т'), - (0x423, 'M', u'у'), - (0x424, 'M', u'ф'), - (0x425, 'M', u'х'), - (0x426, 'M', u'ц'), - (0x427, 'M', u'ч'), - (0x428, 'M', u'ш'), - (0x429, 'M', u'щ'), - (0x42A, 'M', u'ъ'), - (0x42B, 'M', u'ы'), - (0x42C, 'M', u'ь'), - (0x42D, 'M', u'э'), - (0x42E, 'M', u'ю'), - (0x42F, 'M', u'я'), + (0x403, 'M', 'ѓ'), + (0x404, 'M', 'є'), + (0x405, 'M', 'ѕ'), + (0x406, 'M', 'і'), + (0x407, 'M', 'ї'), + (0x408, 'M', 'ј'), + (0x409, 'M', 'љ'), + (0x40A, 'M', 'њ'), + (0x40B, 'M', 'ћ'), + (0x40C, 'M', 'ќ'), + (0x40D, 'M', 'ѝ'), + (0x40E, 'M', 'ў'), + (0x40F, 'M', 'џ'), + (0x410, 'M', 'а'), + (0x411, 'M', 'б'), + (0x412, 'M', 'в'), + (0x413, 'M', 'г'), + (0x414, 'M', 'д'), + (0x415, 'M', 'е'), + (0x416, 'M', 'ж'), + (0x417, 'M', 'з'), + (0x418, 'M', 'и'), + (0x419, 'M', 'й'), + (0x41A, 'M', 'к'), + (0x41B, 'M', 'л'), + (0x41C, 'M', 'м'), + (0x41D, 'M', 'н'), + (0x41E, 'M', 'о'), + (0x41F, 'M', 'п'), + (0x420, 'M', 'р'), + (0x421, 'M', 'с'), + (0x422, 'M', 'т'), + (0x423, 'M', 'у'), + (0x424, 'M', 'ф'), + (0x425, 'M', 'х'), + (0x426, 'M', 'ц'), + (0x427, 'M', 'ч'), + (0x428, 'M', 'ш'), + (0x429, 'M', 'щ'), + (0x42A, 'M', 'ъ'), + (0x42B, 'M', 'ы'), + (0x42C, 'M', 'ь'), + (0x42D, 'M', 'э'), + (0x42E, 'M', 'ю'), + (0x42F, 'M', 'я'), (0x430, 'V'), - (0x460, 'M', u'ѡ'), + (0x460, 'M', 'ѡ'), (0x461, 'V'), - (0x462, 'M', u'ѣ'), + (0x462, 'M', 'ѣ'), (0x463, 'V'), - (0x464, 'M', u'ѥ'), + (0x464, 'M', 'ѥ'), (0x465, 'V'), - (0x466, 'M', u'ѧ'), + (0x466, 'M', 'ѧ'), (0x467, 'V'), - (0x468, 'M', u'ѩ'), + (0x468, 'M', 'ѩ'), (0x469, 'V'), - (0x46A, 'M', u'ѫ'), + (0x46A, 'M', 'ѫ'), (0x46B, 'V'), - (0x46C, 'M', u'ѭ'), + (0x46C, 'M', 'ѭ'), (0x46D, 'V'), - (0x46E, 'M', u'ѯ'), + (0x46E, 'M', 'ѯ'), (0x46F, 'V'), - (0x470, 'M', u'ѱ'), + (0x470, 'M', 'ѱ'), (0x471, 'V'), - (0x472, 'M', u'ѳ'), + (0x472, 'M', 'ѳ'), (0x473, 'V'), - (0x474, 'M', u'ѵ'), + (0x474, 'M', 'ѵ'), (0x475, 'V'), - (0x476, 'M', u'ѷ'), + (0x476, 'M', 'ѷ'), (0x477, 'V'), - (0x478, 'M', u'ѹ'), + (0x478, 'M', 'ѹ'), (0x479, 'V'), - (0x47A, 'M', u'ѻ'), + (0x47A, 'M', 'ѻ'), (0x47B, 'V'), - (0x47C, 'M', u'ѽ'), + (0x47C, 'M', 'ѽ'), (0x47D, 'V'), - (0x47E, 'M', u'ѿ'), + (0x47E, 'M', 'ѿ'), (0x47F, 'V'), - (0x480, 'M', u'ҁ'), + (0x480, 'M', 'ҁ'), (0x481, 'V'), - (0x48A, 'M', u'ҋ'), + (0x48A, 'M', 'ҋ'), (0x48B, 'V'), - (0x48C, 'M', u'ҍ'), + (0x48C, 'M', 'ҍ'), (0x48D, 'V'), - (0x48E, 'M', u'ҏ'), + (0x48E, 'M', 'ҏ'), (0x48F, 'V'), - (0x490, 'M', u'ґ'), + (0x490, 'M', 'ґ'), (0x491, 'V'), - (0x492, 'M', u'ғ'), + (0x492, 'M', 'ғ'), (0x493, 'V'), - (0x494, 'M', u'ҕ'), + (0x494, 'M', 'ҕ'), (0x495, 'V'), - (0x496, 'M', u'җ'), + (0x496, 'M', 'җ'), (0x497, 'V'), - (0x498, 'M', u'ҙ'), + (0x498, 'M', 'ҙ'), (0x499, 'V'), - (0x49A, 'M', u'қ'), + (0x49A, 'M', 'қ'), (0x49B, 'V'), - (0x49C, 'M', u'ҝ'), + (0x49C, 'M', 'ҝ'), (0x49D, 'V'), ] def _seg_8(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x49E, 'M', u'ҟ'), + (0x49E, 'M', 'ҟ'), (0x49F, 'V'), - (0x4A0, 'M', u'ҡ'), + (0x4A0, 'M', 'ҡ'), (0x4A1, 'V'), - (0x4A2, 'M', u'ң'), + (0x4A2, 'M', 'ң'), (0x4A3, 'V'), - (0x4A4, 'M', u'ҥ'), + (0x4A4, 'M', 'ҥ'), (0x4A5, 'V'), - (0x4A6, 'M', u'ҧ'), + (0x4A6, 'M', 'ҧ'), (0x4A7, 'V'), - (0x4A8, 'M', u'ҩ'), + (0x4A8, 'M', 'ҩ'), (0x4A9, 'V'), - (0x4AA, 'M', u'ҫ'), + (0x4AA, 'M', 'ҫ'), (0x4AB, 'V'), - (0x4AC, 'M', u'ҭ'), + (0x4AC, 'M', 'ҭ'), (0x4AD, 'V'), - (0x4AE, 'M', u'ү'), + (0x4AE, 'M', 'ү'), (0x4AF, 'V'), - (0x4B0, 'M', u'ұ'), + (0x4B0, 'M', 'ұ'), (0x4B1, 'V'), - (0x4B2, 'M', u'ҳ'), + (0x4B2, 'M', 'ҳ'), (0x4B3, 'V'), - (0x4B4, 'M', u'ҵ'), + (0x4B4, 'M', 'ҵ'), (0x4B5, 'V'), - (0x4B6, 'M', u'ҷ'), + (0x4B6, 'M', 'ҷ'), (0x4B7, 'V'), - (0x4B8, 'M', u'ҹ'), + (0x4B8, 'M', 'ҹ'), (0x4B9, 'V'), - (0x4BA, 'M', u'һ'), + (0x4BA, 'M', 'һ'), (0x4BB, 'V'), - (0x4BC, 'M', u'ҽ'), + (0x4BC, 'M', 'ҽ'), (0x4BD, 'V'), - (0x4BE, 'M', u'ҿ'), + (0x4BE, 'M', 'ҿ'), (0x4BF, 'V'), (0x4C0, 'X'), - (0x4C1, 'M', u'ӂ'), + (0x4C1, 'M', 'ӂ'), (0x4C2, 'V'), - (0x4C3, 'M', u'ӄ'), + (0x4C3, 'M', 'ӄ'), (0x4C4, 'V'), - (0x4C5, 'M', u'ӆ'), + (0x4C5, 'M', 'ӆ'), (0x4C6, 'V'), - (0x4C7, 'M', u'ӈ'), + (0x4C7, 'M', 'ӈ'), (0x4C8, 'V'), - (0x4C9, 'M', u'ӊ'), + (0x4C9, 'M', 'ӊ'), (0x4CA, 'V'), - (0x4CB, 'M', u'ӌ'), + (0x4CB, 'M', 'ӌ'), (0x4CC, 'V'), - (0x4CD, 'M', u'ӎ'), + (0x4CD, 'M', 'ӎ'), (0x4CE, 'V'), - (0x4D0, 'M', u'ӑ'), + (0x4D0, 'M', 'ӑ'), (0x4D1, 'V'), - (0x4D2, 'M', u'ӓ'), + (0x4D2, 'M', 'ӓ'), (0x4D3, 'V'), - (0x4D4, 'M', u'ӕ'), + (0x4D4, 'M', 'ӕ'), (0x4D5, 'V'), - (0x4D6, 'M', u'ӗ'), + (0x4D6, 'M', 'ӗ'), (0x4D7, 'V'), - (0x4D8, 'M', u'ә'), + (0x4D8, 'M', 'ә'), (0x4D9, 'V'), - (0x4DA, 'M', u'ӛ'), + (0x4DA, 'M', 'ӛ'), (0x4DB, 'V'), - (0x4DC, 'M', u'ӝ'), + (0x4DC, 'M', 'ӝ'), (0x4DD, 'V'), - (0x4DE, 'M', u'ӟ'), + (0x4DE, 'M', 'ӟ'), (0x4DF, 'V'), - (0x4E0, 'M', u'ӡ'), + (0x4E0, 'M', 'ӡ'), (0x4E1, 'V'), - (0x4E2, 'M', u'ӣ'), + (0x4E2, 'M', 'ӣ'), (0x4E3, 'V'), - (0x4E4, 'M', u'ӥ'), + (0x4E4, 'M', 'ӥ'), (0x4E5, 'V'), - (0x4E6, 'M', u'ӧ'), + (0x4E6, 'M', 'ӧ'), (0x4E7, 'V'), - (0x4E8, 'M', u'ө'), + (0x4E8, 'M', 'ө'), (0x4E9, 'V'), - (0x4EA, 'M', u'ӫ'), + (0x4EA, 'M', 'ӫ'), (0x4EB, 'V'), - (0x4EC, 'M', u'ӭ'), + (0x4EC, 'M', 'ӭ'), (0x4ED, 'V'), - (0x4EE, 'M', u'ӯ'), + (0x4EE, 'M', 'ӯ'), (0x4EF, 'V'), - (0x4F0, 'M', u'ӱ'), + (0x4F0, 'M', 'ӱ'), (0x4F1, 'V'), - (0x4F2, 'M', u'ӳ'), + (0x4F2, 'M', 'ӳ'), (0x4F3, 'V'), - (0x4F4, 'M', u'ӵ'), + (0x4F4, 'M', 'ӵ'), (0x4F5, 'V'), - (0x4F6, 'M', u'ӷ'), + (0x4F6, 'M', 'ӷ'), (0x4F7, 'V'), - (0x4F8, 'M', u'ӹ'), + (0x4F8, 'M', 'ӹ'), (0x4F9, 'V'), - (0x4FA, 'M', u'ӻ'), + (0x4FA, 'M', 'ӻ'), (0x4FB, 'V'), - (0x4FC, 'M', u'ӽ'), + (0x4FC, 'M', 'ӽ'), (0x4FD, 'V'), - (0x4FE, 'M', u'ӿ'), + (0x4FE, 'M', 'ӿ'), (0x4FF, 'V'), - (0x500, 'M', u'ԁ'), + (0x500, 'M', 'ԁ'), (0x501, 'V'), - (0x502, 'M', u'ԃ'), + (0x502, 'M', 'ԃ'), ] def _seg_9(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x503, 'V'), - (0x504, 'M', u'ԅ'), + (0x504, 'M', 'ԅ'), (0x505, 'V'), - (0x506, 'M', u'ԇ'), + (0x506, 'M', 'ԇ'), (0x507, 'V'), - (0x508, 'M', u'ԉ'), + (0x508, 'M', 'ԉ'), (0x509, 'V'), - (0x50A, 'M', u'ԋ'), + (0x50A, 'M', 'ԋ'), (0x50B, 'V'), - (0x50C, 'M', u'ԍ'), + (0x50C, 'M', 'ԍ'), (0x50D, 'V'), - (0x50E, 'M', u'ԏ'), + (0x50E, 'M', 'ԏ'), (0x50F, 'V'), - (0x510, 'M', u'ԑ'), + (0x510, 'M', 'ԑ'), (0x511, 'V'), - (0x512, 'M', u'ԓ'), + (0x512, 'M', 'ԓ'), (0x513, 'V'), - (0x514, 'M', u'ԕ'), + (0x514, 'M', 'ԕ'), (0x515, 'V'), - (0x516, 'M', u'ԗ'), + (0x516, 'M', 'ԗ'), (0x517, 'V'), - (0x518, 'M', u'ԙ'), + (0x518, 'M', 'ԙ'), (0x519, 'V'), - (0x51A, 'M', u'ԛ'), + (0x51A, 'M', 'ԛ'), (0x51B, 'V'), - (0x51C, 'M', u'ԝ'), + (0x51C, 'M', 'ԝ'), (0x51D, 'V'), - (0x51E, 'M', u'ԟ'), + (0x51E, 'M', 'ԟ'), (0x51F, 'V'), - (0x520, 'M', u'ԡ'), + (0x520, 'M', 'ԡ'), (0x521, 'V'), - (0x522, 'M', u'ԣ'), + (0x522, 'M', 'ԣ'), (0x523, 'V'), - (0x524, 'M', u'ԥ'), + (0x524, 'M', 'ԥ'), (0x525, 'V'), - (0x526, 'M', u'ԧ'), + (0x526, 'M', 'ԧ'), (0x527, 'V'), - (0x528, 'M', u'ԩ'), + (0x528, 'M', 'ԩ'), (0x529, 'V'), - (0x52A, 'M', u'ԫ'), + (0x52A, 'M', 'ԫ'), (0x52B, 'V'), - (0x52C, 'M', u'ԭ'), + (0x52C, 'M', 'ԭ'), (0x52D, 'V'), - (0x52E, 'M', u'ԯ'), + (0x52E, 'M', 'ԯ'), (0x52F, 'V'), (0x530, 'X'), - (0x531, 'M', u'ա'), - (0x532, 'M', u'բ'), - (0x533, 'M', u'գ'), - (0x534, 'M', u'դ'), - (0x535, 'M', u'ե'), - (0x536, 'M', u'զ'), - (0x537, 'M', u'է'), - (0x538, 'M', u'ը'), - (0x539, 'M', u'թ'), - (0x53A, 'M', u'ժ'), - (0x53B, 'M', u'ի'), - (0x53C, 'M', u'լ'), - (0x53D, 'M', u'խ'), - (0x53E, 'M', u'ծ'), - (0x53F, 'M', u'կ'), - (0x540, 'M', u'հ'), - (0x541, 'M', u'ձ'), - (0x542, 'M', u'ղ'), - (0x543, 'M', u'ճ'), - (0x544, 'M', u'մ'), - (0x545, 'M', u'յ'), - (0x546, 'M', u'ն'), - (0x547, 'M', u'շ'), - (0x548, 'M', u'ո'), - (0x549, 'M', u'չ'), - (0x54A, 'M', u'պ'), - (0x54B, 'M', u'ջ'), - (0x54C, 'M', u'ռ'), - (0x54D, 'M', u'ս'), - (0x54E, 'M', u'վ'), - (0x54F, 'M', u'տ'), - (0x550, 'M', u'ր'), - (0x551, 'M', u'ց'), - (0x552, 'M', u'ւ'), - (0x553, 'M', u'փ'), - (0x554, 'M', u'ք'), - (0x555, 'M', u'օ'), - (0x556, 'M', u'ֆ'), + (0x531, 'M', 'ա'), + (0x532, 'M', 'բ'), + (0x533, 'M', 'գ'), + (0x534, 'M', 'դ'), + (0x535, 'M', 'ե'), + (0x536, 'M', 'զ'), + (0x537, 'M', 'է'), + (0x538, 'M', 'ը'), + (0x539, 'M', 'թ'), + (0x53A, 'M', 'ժ'), + (0x53B, 'M', 'ի'), + (0x53C, 'M', 'լ'), + (0x53D, 'M', 'խ'), + (0x53E, 'M', 'ծ'), + (0x53F, 'M', 'կ'), + (0x540, 'M', 'հ'), + (0x541, 'M', 'ձ'), + (0x542, 'M', 'ղ'), + (0x543, 'M', 'ճ'), + (0x544, 'M', 'մ'), + (0x545, 'M', 'յ'), + (0x546, 'M', 'ն'), + (0x547, 'M', 'շ'), + (0x548, 'M', 'ո'), + (0x549, 'M', 'չ'), + (0x54A, 'M', 'պ'), + (0x54B, 'M', 'ջ'), + (0x54C, 'M', 'ռ'), + (0x54D, 'M', 'ս'), + (0x54E, 'M', 'վ'), + (0x54F, 'M', 'տ'), + (0x550, 'M', 'ր'), + (0x551, 'M', 'ց'), + (0x552, 'M', 'ւ'), + (0x553, 'M', 'փ'), + (0x554, 'M', 'ք'), + (0x555, 'M', 'օ'), + (0x556, 'M', 'ֆ'), (0x557, 'X'), (0x559, 'V'), - (0x587, 'M', u'եւ'), + (0x587, 'M', 'եւ'), (0x588, 'V'), (0x58B, 'X'), (0x58D, 'V'), @@ -1046,11 +1057,12 @@ def _seg_9(): ] def _seg_10(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x675, 'M', u'اٴ'), - (0x676, 'M', u'وٴ'), - (0x677, 'M', u'ۇٴ'), - (0x678, 'M', u'يٴ'), + (0x675, 'M', 'اٴ'), + (0x676, 'M', 'وٴ'), + (0x677, 'M', 'ۇٴ'), + (0x678, 'M', 'يٴ'), (0x679, 'V'), (0x6DD, 'X'), (0x6DE, 'V'), @@ -1078,14 +1090,14 @@ def _seg_10(): (0x8D3, 'V'), (0x8E2, 'X'), (0x8E3, 'V'), - (0x958, 'M', u'क़'), - (0x959, 'M', u'ख़'), - (0x95A, 'M', u'ग़'), - (0x95B, 'M', u'ज़'), - (0x95C, 'M', u'ड़'), - (0x95D, 'M', u'ढ़'), - (0x95E, 'M', u'फ़'), - (0x95F, 'M', u'य़'), + (0x958, 'M', 'क़'), + (0x959, 'M', 'ख़'), + (0x95A, 'M', 'ग़'), + (0x95B, 'M', 'ज़'), + (0x95C, 'M', 'ड़'), + (0x95D, 'M', 'ढ़'), + (0x95E, 'M', 'फ़'), + (0x95F, 'M', 'य़'), (0x960, 'V'), (0x984, 'X'), (0x985, 'V'), @@ -1108,10 +1120,10 @@ def _seg_10(): (0x9CF, 'X'), (0x9D7, 'V'), (0x9D8, 'X'), - (0x9DC, 'M', u'ড়'), - (0x9DD, 'M', u'ঢ়'), + (0x9DC, 'M', 'ড়'), + (0x9DD, 'M', 'ঢ়'), (0x9DE, 'X'), - (0x9DF, 'M', u'য়'), + (0x9DF, 'M', 'য়'), (0x9E0, 'V'), (0x9E4, 'X'), (0x9E6, 'V'), @@ -1127,10 +1139,10 @@ def _seg_10(): (0xA2A, 'V'), (0xA31, 'X'), (0xA32, 'V'), - (0xA33, 'M', u'ਲ਼'), + (0xA33, 'M', 'ਲ਼'), (0xA34, 'X'), (0xA35, 'V'), - (0xA36, 'M', u'ਸ਼'), + (0xA36, 'M', 'ਸ਼'), (0xA37, 'X'), (0xA38, 'V'), (0xA3A, 'X'), @@ -1144,16 +1156,17 @@ def _seg_10(): (0xA4E, 'X'), (0xA51, 'V'), (0xA52, 'X'), - (0xA59, 'M', u'ਖ਼'), - (0xA5A, 'M', u'ਗ਼'), - (0xA5B, 'M', u'ਜ਼'), + (0xA59, 'M', 'ਖ਼'), + (0xA5A, 'M', 'ਗ਼'), + (0xA5B, 'M', 'ਜ਼'), ] def _seg_11(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xA5C, 'V'), (0xA5D, 'X'), - (0xA5E, 'M', u'ਫ਼'), + (0xA5E, 'M', 'ਫ਼'), (0xA5F, 'X'), (0xA66, 'V'), (0xA77, 'X'), @@ -1207,8 +1220,8 @@ def _seg_11(): (0xB4E, 'X'), (0xB55, 'V'), (0xB58, 'X'), - (0xB5C, 'M', u'ଡ଼'), - (0xB5D, 'M', u'ଢ଼'), + (0xB5C, 'M', 'ଡ଼'), + (0xB5D, 'M', 'ଢ଼'), (0xB5E, 'X'), (0xB5F, 'V'), (0xB64, 'X'), @@ -1254,6 +1267,7 @@ def _seg_11(): ] def _seg_12(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xC29, 'X'), (0xC2A, 'V'), @@ -1337,7 +1351,7 @@ def _seg_12(): (0xDF2, 'V'), (0xDF5, 'X'), (0xE01, 'V'), - (0xE33, 'M', u'ํา'), + (0xE33, 'M', 'ํา'), (0xE34, 'V'), (0xE3B, 'X'), (0xE3F, 'V'), @@ -1353,11 +1367,12 @@ def _seg_12(): (0xEA5, 'V'), (0xEA6, 'X'), (0xEA7, 'V'), - (0xEB3, 'M', u'ໍາ'), + (0xEB3, 'M', 'ໍາ'), (0xEB4, 'V'), ] def _seg_13(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xEBE, 'X'), (0xEC0, 'V'), @@ -1368,52 +1383,52 @@ def _seg_13(): (0xECE, 'X'), (0xED0, 'V'), (0xEDA, 'X'), - (0xEDC, 'M', u'ຫນ'), - (0xEDD, 'M', u'ຫມ'), + (0xEDC, 'M', 'ຫນ'), + (0xEDD, 'M', 'ຫມ'), (0xEDE, 'V'), (0xEE0, 'X'), (0xF00, 'V'), - (0xF0C, 'M', u'་'), + (0xF0C, 'M', '་'), (0xF0D, 'V'), - (0xF43, 'M', u'གྷ'), + (0xF43, 'M', 'གྷ'), (0xF44, 'V'), (0xF48, 'X'), (0xF49, 'V'), - (0xF4D, 'M', u'ཌྷ'), + (0xF4D, 'M', 'ཌྷ'), (0xF4E, 'V'), - (0xF52, 'M', u'དྷ'), + (0xF52, 'M', 'དྷ'), (0xF53, 'V'), - (0xF57, 'M', u'བྷ'), + (0xF57, 'M', 'བྷ'), (0xF58, 'V'), - (0xF5C, 'M', u'ཛྷ'), + (0xF5C, 'M', 'ཛྷ'), (0xF5D, 'V'), - (0xF69, 'M', u'ཀྵ'), + (0xF69, 'M', 'ཀྵ'), (0xF6A, 'V'), (0xF6D, 'X'), (0xF71, 'V'), - (0xF73, 'M', u'ཱི'), + (0xF73, 'M', 'ཱི'), (0xF74, 'V'), - (0xF75, 'M', u'ཱུ'), - (0xF76, 'M', u'ྲྀ'), - (0xF77, 'M', u'ྲཱྀ'), - (0xF78, 'M', u'ླྀ'), - (0xF79, 'M', u'ླཱྀ'), + (0xF75, 'M', 'ཱུ'), + (0xF76, 'M', 'ྲྀ'), + (0xF77, 'M', 'ྲཱྀ'), + (0xF78, 'M', 'ླྀ'), + (0xF79, 'M', 'ླཱྀ'), (0xF7A, 'V'), - (0xF81, 'M', u'ཱྀ'), + (0xF81, 'M', 'ཱྀ'), (0xF82, 'V'), - (0xF93, 'M', u'ྒྷ'), + (0xF93, 'M', 'ྒྷ'), (0xF94, 'V'), (0xF98, 'X'), (0xF99, 'V'), - (0xF9D, 'M', u'ྜྷ'), + (0xF9D, 'M', 'ྜྷ'), (0xF9E, 'V'), - (0xFA2, 'M', u'ྡྷ'), + (0xFA2, 'M', 'ྡྷ'), (0xFA3, 'V'), - (0xFA7, 'M', u'ྦྷ'), + (0xFA7, 'M', 'ྦྷ'), (0xFA8, 'V'), - (0xFAC, 'M', u'ྫྷ'), + (0xFAC, 'M', 'ྫྷ'), (0xFAD, 'V'), - (0xFB9, 'M', u'ྐྵ'), + (0xFB9, 'M', 'ྐྵ'), (0xFBA, 'V'), (0xFBD, 'X'), (0xFBE, 'V'), @@ -1422,12 +1437,12 @@ def _seg_13(): (0xFDB, 'X'), (0x1000, 'V'), (0x10A0, 'X'), - (0x10C7, 'M', u'ⴧ'), + (0x10C7, 'M', 'ⴧ'), (0x10C8, 'X'), - (0x10CD, 'M', u'ⴭ'), + (0x10CD, 'M', 'ⴭ'), (0x10CE, 'X'), (0x10D0, 'V'), - (0x10FC, 'M', u'ნ'), + (0x10FC, 'M', 'ნ'), (0x10FD, 'V'), (0x115F, 'X'), (0x1161, 'V'), @@ -1462,6 +1477,7 @@ def _seg_13(): ] def _seg_14(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1316, 'X'), (0x1318, 'V'), @@ -1472,12 +1488,12 @@ def _seg_14(): (0x139A, 'X'), (0x13A0, 'V'), (0x13F6, 'X'), - (0x13F8, 'M', u'Ᏸ'), - (0x13F9, 'M', u'Ᏹ'), - (0x13FA, 'M', u'Ᏺ'), - (0x13FB, 'M', u'Ᏻ'), - (0x13FC, 'M', u'Ᏼ'), - (0x13FD, 'M', u'Ᏽ'), + (0x13F8, 'M', 'Ᏸ'), + (0x13F9, 'M', 'Ᏹ'), + (0x13FA, 'M', 'Ᏺ'), + (0x13FB, 'M', 'Ᏻ'), + (0x13FC, 'M', 'Ᏼ'), + (0x13FD, 'M', 'Ᏽ'), (0x13FE, 'X'), (0x1400, 'V'), (0x1680, 'X'), @@ -1566,1193 +1582,1205 @@ def _seg_14(): ] def _seg_15(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1C80, 'M', u'в'), - (0x1C81, 'M', u'д'), - (0x1C82, 'M', u'о'), - (0x1C83, 'M', u'с'), - (0x1C84, 'M', u'т'), - (0x1C86, 'M', u'ъ'), - (0x1C87, 'M', u'ѣ'), - (0x1C88, 'M', u'ꙋ'), + (0x1C80, 'M', 'в'), + (0x1C81, 'M', 'д'), + (0x1C82, 'M', 'о'), + (0x1C83, 'M', 'с'), + (0x1C84, 'M', 'т'), + (0x1C86, 'M', 'ъ'), + (0x1C87, 'M', 'ѣ'), + (0x1C88, 'M', 'ꙋ'), (0x1C89, 'X'), - (0x1C90, 'M', u'ა'), - (0x1C91, 'M', u'ბ'), - (0x1C92, 'M', u'გ'), - (0x1C93, 'M', u'დ'), - (0x1C94, 'M', u'ე'), - (0x1C95, 'M', u'ვ'), - (0x1C96, 'M', u'ზ'), - (0x1C97, 'M', u'თ'), - (0x1C98, 'M', u'ი'), - (0x1C99, 'M', u'კ'), - (0x1C9A, 'M', u'ლ'), - (0x1C9B, 'M', u'მ'), - (0x1C9C, 'M', u'ნ'), - (0x1C9D, 'M', u'ო'), - (0x1C9E, 'M', u'პ'), - (0x1C9F, 'M', u'ჟ'), - (0x1CA0, 'M', u'რ'), - (0x1CA1, 'M', u'ს'), - (0x1CA2, 'M', u'ტ'), - (0x1CA3, 'M', u'უ'), - (0x1CA4, 'M', u'ფ'), - (0x1CA5, 'M', u'ქ'), - (0x1CA6, 'M', u'ღ'), - (0x1CA7, 'M', u'ყ'), - (0x1CA8, 'M', u'შ'), - (0x1CA9, 'M', u'ჩ'), - (0x1CAA, 'M', u'ც'), - (0x1CAB, 'M', u'ძ'), - (0x1CAC, 'M', u'წ'), - (0x1CAD, 'M', u'ჭ'), - (0x1CAE, 'M', u'ხ'), - (0x1CAF, 'M', u'ჯ'), - (0x1CB0, 'M', u'ჰ'), - (0x1CB1, 'M', u'ჱ'), - (0x1CB2, 'M', u'ჲ'), - (0x1CB3, 'M', u'ჳ'), - (0x1CB4, 'M', u'ჴ'), - (0x1CB5, 'M', u'ჵ'), - (0x1CB6, 'M', u'ჶ'), - (0x1CB7, 'M', u'ჷ'), - (0x1CB8, 'M', u'ჸ'), - (0x1CB9, 'M', u'ჹ'), - (0x1CBA, 'M', u'ჺ'), + (0x1C90, 'M', 'ა'), + (0x1C91, 'M', 'ბ'), + (0x1C92, 'M', 'გ'), + (0x1C93, 'M', 'დ'), + (0x1C94, 'M', 'ე'), + (0x1C95, 'M', 'ვ'), + (0x1C96, 'M', 'ზ'), + (0x1C97, 'M', 'თ'), + (0x1C98, 'M', 'ი'), + (0x1C99, 'M', 'კ'), + (0x1C9A, 'M', 'ლ'), + (0x1C9B, 'M', 'მ'), + (0x1C9C, 'M', 'ნ'), + (0x1C9D, 'M', 'ო'), + (0x1C9E, 'M', 'პ'), + (0x1C9F, 'M', 'ჟ'), + (0x1CA0, 'M', 'რ'), + (0x1CA1, 'M', 'ს'), + (0x1CA2, 'M', 'ტ'), + (0x1CA3, 'M', 'უ'), + (0x1CA4, 'M', 'ფ'), + (0x1CA5, 'M', 'ქ'), + (0x1CA6, 'M', 'ღ'), + (0x1CA7, 'M', 'ყ'), + (0x1CA8, 'M', 'შ'), + (0x1CA9, 'M', 'ჩ'), + (0x1CAA, 'M', 'ც'), + (0x1CAB, 'M', 'ძ'), + (0x1CAC, 'M', 'წ'), + (0x1CAD, 'M', 'ჭ'), + (0x1CAE, 'M', 'ხ'), + (0x1CAF, 'M', 'ჯ'), + (0x1CB0, 'M', 'ჰ'), + (0x1CB1, 'M', 'ჱ'), + (0x1CB2, 'M', 'ჲ'), + (0x1CB3, 'M', 'ჳ'), + (0x1CB4, 'M', 'ჴ'), + (0x1CB5, 'M', 'ჵ'), + (0x1CB6, 'M', 'ჶ'), + (0x1CB7, 'M', 'ჷ'), + (0x1CB8, 'M', 'ჸ'), + (0x1CB9, 'M', 'ჹ'), + (0x1CBA, 'M', 'ჺ'), (0x1CBB, 'X'), - (0x1CBD, 'M', u'ჽ'), - (0x1CBE, 'M', u'ჾ'), - (0x1CBF, 'M', u'ჿ'), + (0x1CBD, 'M', 'ჽ'), + (0x1CBE, 'M', 'ჾ'), + (0x1CBF, 'M', 'ჿ'), (0x1CC0, 'V'), (0x1CC8, 'X'), (0x1CD0, 'V'), (0x1CFB, 'X'), (0x1D00, 'V'), - (0x1D2C, 'M', u'a'), - (0x1D2D, 'M', u'æ'), - (0x1D2E, 'M', u'b'), + (0x1D2C, 'M', 'a'), + (0x1D2D, 'M', 'æ'), + (0x1D2E, 'M', 'b'), (0x1D2F, 'V'), - (0x1D30, 'M', u'd'), - (0x1D31, 'M', u'e'), - (0x1D32, 'M', u'ǝ'), - (0x1D33, 'M', u'g'), - (0x1D34, 'M', u'h'), - (0x1D35, 'M', u'i'), - (0x1D36, 'M', u'j'), - (0x1D37, 'M', u'k'), - (0x1D38, 'M', u'l'), - (0x1D39, 'M', u'm'), - (0x1D3A, 'M', u'n'), + (0x1D30, 'M', 'd'), + (0x1D31, 'M', 'e'), + (0x1D32, 'M', 'ǝ'), + (0x1D33, 'M', 'g'), + (0x1D34, 'M', 'h'), + (0x1D35, 'M', 'i'), + (0x1D36, 'M', 'j'), + (0x1D37, 'M', 'k'), + (0x1D38, 'M', 'l'), + (0x1D39, 'M', 'm'), + (0x1D3A, 'M', 'n'), (0x1D3B, 'V'), - (0x1D3C, 'M', u'o'), - (0x1D3D, 'M', u'ȣ'), - (0x1D3E, 'M', u'p'), - (0x1D3F, 'M', u'r'), - (0x1D40, 'M', u't'), - (0x1D41, 'M', u'u'), - (0x1D42, 'M', u'w'), - (0x1D43, 'M', u'a'), - (0x1D44, 'M', u'ɐ'), - (0x1D45, 'M', u'ɑ'), - (0x1D46, 'M', u'ᴂ'), - (0x1D47, 'M', u'b'), - (0x1D48, 'M', u'd'), - (0x1D49, 'M', u'e'), - (0x1D4A, 'M', u'ə'), - (0x1D4B, 'M', u'ɛ'), - (0x1D4C, 'M', u'ɜ'), - (0x1D4D, 'M', u'g'), + (0x1D3C, 'M', 'o'), + (0x1D3D, 'M', 'ȣ'), + (0x1D3E, 'M', 'p'), + (0x1D3F, 'M', 'r'), + (0x1D40, 'M', 't'), + (0x1D41, 'M', 'u'), + (0x1D42, 'M', 'w'), + (0x1D43, 'M', 'a'), + (0x1D44, 'M', 'ɐ'), + (0x1D45, 'M', 'ɑ'), + (0x1D46, 'M', 'ᴂ'), + (0x1D47, 'M', 'b'), + (0x1D48, 'M', 'd'), + (0x1D49, 'M', 'e'), + (0x1D4A, 'M', 'ə'), + (0x1D4B, 'M', 'ɛ'), + (0x1D4C, 'M', 'ɜ'), + (0x1D4D, 'M', 'g'), (0x1D4E, 'V'), - (0x1D4F, 'M', u'k'), - (0x1D50, 'M', u'm'), - (0x1D51, 'M', u'ŋ'), - (0x1D52, 'M', u'o'), + (0x1D4F, 'M', 'k'), + (0x1D50, 'M', 'm'), + (0x1D51, 'M', 'ŋ'), + (0x1D52, 'M', 'o'), ] def _seg_16(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D53, 'M', u'ɔ'), - (0x1D54, 'M', u'ᴖ'), - (0x1D55, 'M', u'ᴗ'), - (0x1D56, 'M', u'p'), - (0x1D57, 'M', u't'), - (0x1D58, 'M', u'u'), - (0x1D59, 'M', u'ᴝ'), - (0x1D5A, 'M', u'ɯ'), - (0x1D5B, 'M', u'v'), - (0x1D5C, 'M', u'ᴥ'), - (0x1D5D, 'M', u'β'), - (0x1D5E, 'M', u'γ'), - (0x1D5F, 'M', u'δ'), - (0x1D60, 'M', u'φ'), - (0x1D61, 'M', u'χ'), - (0x1D62, 'M', u'i'), - (0x1D63, 'M', u'r'), - (0x1D64, 'M', u'u'), - (0x1D65, 'M', u'v'), - (0x1D66, 'M', u'β'), - (0x1D67, 'M', u'γ'), - (0x1D68, 'M', u'ρ'), - (0x1D69, 'M', u'φ'), - (0x1D6A, 'M', u'χ'), + (0x1D53, 'M', 'ɔ'), + (0x1D54, 'M', 'ᴖ'), + (0x1D55, 'M', 'ᴗ'), + (0x1D56, 'M', 'p'), + (0x1D57, 'M', 't'), + (0x1D58, 'M', 'u'), + (0x1D59, 'M', 'ᴝ'), + (0x1D5A, 'M', 'ɯ'), + (0x1D5B, 'M', 'v'), + (0x1D5C, 'M', 'ᴥ'), + (0x1D5D, 'M', 'β'), + (0x1D5E, 'M', 'γ'), + (0x1D5F, 'M', 'δ'), + (0x1D60, 'M', 'φ'), + (0x1D61, 'M', 'χ'), + (0x1D62, 'M', 'i'), + (0x1D63, 'M', 'r'), + (0x1D64, 'M', 'u'), + (0x1D65, 'M', 'v'), + (0x1D66, 'M', 'β'), + (0x1D67, 'M', 'γ'), + (0x1D68, 'M', 'ρ'), + (0x1D69, 'M', 'φ'), + (0x1D6A, 'M', 'χ'), (0x1D6B, 'V'), - (0x1D78, 'M', u'н'), + (0x1D78, 'M', 'н'), (0x1D79, 'V'), - (0x1D9B, 'M', u'ɒ'), - (0x1D9C, 'M', u'c'), - (0x1D9D, 'M', u'ɕ'), - (0x1D9E, 'M', u'ð'), - (0x1D9F, 'M', u'ɜ'), - (0x1DA0, 'M', u'f'), - (0x1DA1, 'M', u'ɟ'), - (0x1DA2, 'M', u'ɡ'), - (0x1DA3, 'M', u'ɥ'), - (0x1DA4, 'M', u'ɨ'), - (0x1DA5, 'M', u'ɩ'), - (0x1DA6, 'M', u'ɪ'), - (0x1DA7, 'M', u'ᵻ'), - (0x1DA8, 'M', u'ʝ'), - (0x1DA9, 'M', u'ɭ'), - (0x1DAA, 'M', u'ᶅ'), - (0x1DAB, 'M', u'ʟ'), - (0x1DAC, 'M', u'ɱ'), - (0x1DAD, 'M', u'ɰ'), - (0x1DAE, 'M', u'ɲ'), - (0x1DAF, 'M', u'ɳ'), - (0x1DB0, 'M', u'ɴ'), - (0x1DB1, 'M', u'ɵ'), - (0x1DB2, 'M', u'ɸ'), - (0x1DB3, 'M', u'ʂ'), - (0x1DB4, 'M', u'ʃ'), - (0x1DB5, 'M', u'ƫ'), - (0x1DB6, 'M', u'ʉ'), - (0x1DB7, 'M', u'ʊ'), - (0x1DB8, 'M', u'ᴜ'), - (0x1DB9, 'M', u'ʋ'), - (0x1DBA, 'M', u'ʌ'), - (0x1DBB, 'M', u'z'), - (0x1DBC, 'M', u'ʐ'), - (0x1DBD, 'M', u'ʑ'), - (0x1DBE, 'M', u'ʒ'), - (0x1DBF, 'M', u'θ'), + (0x1D9B, 'M', 'ɒ'), + (0x1D9C, 'M', 'c'), + (0x1D9D, 'M', 'ɕ'), + (0x1D9E, 'M', 'ð'), + (0x1D9F, 'M', 'ɜ'), + (0x1DA0, 'M', 'f'), + (0x1DA1, 'M', 'ɟ'), + (0x1DA2, 'M', 'ɡ'), + (0x1DA3, 'M', 'ɥ'), + (0x1DA4, 'M', 'ɨ'), + (0x1DA5, 'M', 'ɩ'), + (0x1DA6, 'M', 'ɪ'), + (0x1DA7, 'M', 'ᵻ'), + (0x1DA8, 'M', 'ʝ'), + (0x1DA9, 'M', 'ɭ'), + (0x1DAA, 'M', 'ᶅ'), + (0x1DAB, 'M', 'ʟ'), + (0x1DAC, 'M', 'ɱ'), + (0x1DAD, 'M', 'ɰ'), + (0x1DAE, 'M', 'ɲ'), + (0x1DAF, 'M', 'ɳ'), + (0x1DB0, 'M', 'ɴ'), + (0x1DB1, 'M', 'ɵ'), + (0x1DB2, 'M', 'ɸ'), + (0x1DB3, 'M', 'ʂ'), + (0x1DB4, 'M', 'ʃ'), + (0x1DB5, 'M', 'ƫ'), + (0x1DB6, 'M', 'ʉ'), + (0x1DB7, 'M', 'ʊ'), + (0x1DB8, 'M', 'ᴜ'), + (0x1DB9, 'M', 'ʋ'), + (0x1DBA, 'M', 'ʌ'), + (0x1DBB, 'M', 'z'), + (0x1DBC, 'M', 'ʐ'), + (0x1DBD, 'M', 'ʑ'), + (0x1DBE, 'M', 'ʒ'), + (0x1DBF, 'M', 'θ'), (0x1DC0, 'V'), (0x1DFA, 'X'), (0x1DFB, 'V'), - (0x1E00, 'M', u'ḁ'), + (0x1E00, 'M', 'ḁ'), (0x1E01, 'V'), - (0x1E02, 'M', u'ḃ'), + (0x1E02, 'M', 'ḃ'), (0x1E03, 'V'), - (0x1E04, 'M', u'ḅ'), + (0x1E04, 'M', 'ḅ'), (0x1E05, 'V'), - (0x1E06, 'M', u'ḇ'), + (0x1E06, 'M', 'ḇ'), (0x1E07, 'V'), - (0x1E08, 'M', u'ḉ'), + (0x1E08, 'M', 'ḉ'), (0x1E09, 'V'), - (0x1E0A, 'M', u'ḋ'), + (0x1E0A, 'M', 'ḋ'), (0x1E0B, 'V'), - (0x1E0C, 'M', u'ḍ'), + (0x1E0C, 'M', 'ḍ'), (0x1E0D, 'V'), - (0x1E0E, 'M', u'ḏ'), + (0x1E0E, 'M', 'ḏ'), (0x1E0F, 'V'), - (0x1E10, 'M', u'ḑ'), + (0x1E10, 'M', 'ḑ'), (0x1E11, 'V'), - (0x1E12, 'M', u'ḓ'), + (0x1E12, 'M', 'ḓ'), (0x1E13, 'V'), - (0x1E14, 'M', u'ḕ'), + (0x1E14, 'M', 'ḕ'), (0x1E15, 'V'), - (0x1E16, 'M', u'ḗ'), + (0x1E16, 'M', 'ḗ'), (0x1E17, 'V'), - (0x1E18, 'M', u'ḙ'), + (0x1E18, 'M', 'ḙ'), (0x1E19, 'V'), - (0x1E1A, 'M', u'ḛ'), + (0x1E1A, 'M', 'ḛ'), (0x1E1B, 'V'), - (0x1E1C, 'M', u'ḝ'), + (0x1E1C, 'M', 'ḝ'), (0x1E1D, 'V'), - (0x1E1E, 'M', u'ḟ'), + (0x1E1E, 'M', 'ḟ'), (0x1E1F, 'V'), - (0x1E20, 'M', u'ḡ'), + (0x1E20, 'M', 'ḡ'), ] def _seg_17(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1E21, 'V'), - (0x1E22, 'M', u'ḣ'), + (0x1E22, 'M', 'ḣ'), (0x1E23, 'V'), - (0x1E24, 'M', u'ḥ'), + (0x1E24, 'M', 'ḥ'), (0x1E25, 'V'), - (0x1E26, 'M', u'ḧ'), + (0x1E26, 'M', 'ḧ'), (0x1E27, 'V'), - (0x1E28, 'M', u'ḩ'), + (0x1E28, 'M', 'ḩ'), (0x1E29, 'V'), - (0x1E2A, 'M', u'ḫ'), + (0x1E2A, 'M', 'ḫ'), (0x1E2B, 'V'), - (0x1E2C, 'M', u'ḭ'), + (0x1E2C, 'M', 'ḭ'), (0x1E2D, 'V'), - (0x1E2E, 'M', u'ḯ'), + (0x1E2E, 'M', 'ḯ'), (0x1E2F, 'V'), - (0x1E30, 'M', u'ḱ'), + (0x1E30, 'M', 'ḱ'), (0x1E31, 'V'), - (0x1E32, 'M', u'ḳ'), + (0x1E32, 'M', 'ḳ'), (0x1E33, 'V'), - (0x1E34, 'M', u'ḵ'), + (0x1E34, 'M', 'ḵ'), (0x1E35, 'V'), - (0x1E36, 'M', u'ḷ'), + (0x1E36, 'M', 'ḷ'), (0x1E37, 'V'), - (0x1E38, 'M', u'ḹ'), + (0x1E38, 'M', 'ḹ'), (0x1E39, 'V'), - (0x1E3A, 'M', u'ḻ'), + (0x1E3A, 'M', 'ḻ'), (0x1E3B, 'V'), - (0x1E3C, 'M', u'ḽ'), + (0x1E3C, 'M', 'ḽ'), (0x1E3D, 'V'), - (0x1E3E, 'M', u'ḿ'), + (0x1E3E, 'M', 'ḿ'), (0x1E3F, 'V'), - (0x1E40, 'M', u'ṁ'), + (0x1E40, 'M', 'ṁ'), (0x1E41, 'V'), - (0x1E42, 'M', u'ṃ'), + (0x1E42, 'M', 'ṃ'), (0x1E43, 'V'), - (0x1E44, 'M', u'ṅ'), + (0x1E44, 'M', 'ṅ'), (0x1E45, 'V'), - (0x1E46, 'M', u'ṇ'), + (0x1E46, 'M', 'ṇ'), (0x1E47, 'V'), - (0x1E48, 'M', u'ṉ'), + (0x1E48, 'M', 'ṉ'), (0x1E49, 'V'), - (0x1E4A, 'M', u'ṋ'), + (0x1E4A, 'M', 'ṋ'), (0x1E4B, 'V'), - (0x1E4C, 'M', u'ṍ'), + (0x1E4C, 'M', 'ṍ'), (0x1E4D, 'V'), - (0x1E4E, 'M', u'ṏ'), + (0x1E4E, 'M', 'ṏ'), (0x1E4F, 'V'), - (0x1E50, 'M', u'ṑ'), + (0x1E50, 'M', 'ṑ'), (0x1E51, 'V'), - (0x1E52, 'M', u'ṓ'), + (0x1E52, 'M', 'ṓ'), (0x1E53, 'V'), - (0x1E54, 'M', u'ṕ'), + (0x1E54, 'M', 'ṕ'), (0x1E55, 'V'), - (0x1E56, 'M', u'ṗ'), + (0x1E56, 'M', 'ṗ'), (0x1E57, 'V'), - (0x1E58, 'M', u'ṙ'), + (0x1E58, 'M', 'ṙ'), (0x1E59, 'V'), - (0x1E5A, 'M', u'ṛ'), + (0x1E5A, 'M', 'ṛ'), (0x1E5B, 'V'), - (0x1E5C, 'M', u'ṝ'), + (0x1E5C, 'M', 'ṝ'), (0x1E5D, 'V'), - (0x1E5E, 'M', u'ṟ'), + (0x1E5E, 'M', 'ṟ'), (0x1E5F, 'V'), - (0x1E60, 'M', u'ṡ'), + (0x1E60, 'M', 'ṡ'), (0x1E61, 'V'), - (0x1E62, 'M', u'ṣ'), + (0x1E62, 'M', 'ṣ'), (0x1E63, 'V'), - (0x1E64, 'M', u'ṥ'), + (0x1E64, 'M', 'ṥ'), (0x1E65, 'V'), - (0x1E66, 'M', u'ṧ'), + (0x1E66, 'M', 'ṧ'), (0x1E67, 'V'), - (0x1E68, 'M', u'ṩ'), + (0x1E68, 'M', 'ṩ'), (0x1E69, 'V'), - (0x1E6A, 'M', u'ṫ'), + (0x1E6A, 'M', 'ṫ'), (0x1E6B, 'V'), - (0x1E6C, 'M', u'ṭ'), + (0x1E6C, 'M', 'ṭ'), (0x1E6D, 'V'), - (0x1E6E, 'M', u'ṯ'), + (0x1E6E, 'M', 'ṯ'), (0x1E6F, 'V'), - (0x1E70, 'M', u'ṱ'), + (0x1E70, 'M', 'ṱ'), (0x1E71, 'V'), - (0x1E72, 'M', u'ṳ'), + (0x1E72, 'M', 'ṳ'), (0x1E73, 'V'), - (0x1E74, 'M', u'ṵ'), + (0x1E74, 'M', 'ṵ'), (0x1E75, 'V'), - (0x1E76, 'M', u'ṷ'), + (0x1E76, 'M', 'ṷ'), (0x1E77, 'V'), - (0x1E78, 'M', u'ṹ'), + (0x1E78, 'M', 'ṹ'), (0x1E79, 'V'), - (0x1E7A, 'M', u'ṻ'), + (0x1E7A, 'M', 'ṻ'), (0x1E7B, 'V'), - (0x1E7C, 'M', u'ṽ'), + (0x1E7C, 'M', 'ṽ'), (0x1E7D, 'V'), - (0x1E7E, 'M', u'ṿ'), + (0x1E7E, 'M', 'ṿ'), (0x1E7F, 'V'), - (0x1E80, 'M', u'ẁ'), + (0x1E80, 'M', 'ẁ'), (0x1E81, 'V'), - (0x1E82, 'M', u'ẃ'), + (0x1E82, 'M', 'ẃ'), (0x1E83, 'V'), - (0x1E84, 'M', u'ẅ'), + (0x1E84, 'M', 'ẅ'), ] def _seg_18(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1E85, 'V'), - (0x1E86, 'M', u'ẇ'), + (0x1E86, 'M', 'ẇ'), (0x1E87, 'V'), - (0x1E88, 'M', u'ẉ'), + (0x1E88, 'M', 'ẉ'), (0x1E89, 'V'), - (0x1E8A, 'M', u'ẋ'), + (0x1E8A, 'M', 'ẋ'), (0x1E8B, 'V'), - (0x1E8C, 'M', u'ẍ'), + (0x1E8C, 'M', 'ẍ'), (0x1E8D, 'V'), - (0x1E8E, 'M', u'ẏ'), + (0x1E8E, 'M', 'ẏ'), (0x1E8F, 'V'), - (0x1E90, 'M', u'ẑ'), + (0x1E90, 'M', 'ẑ'), (0x1E91, 'V'), - (0x1E92, 'M', u'ẓ'), + (0x1E92, 'M', 'ẓ'), (0x1E93, 'V'), - (0x1E94, 'M', u'ẕ'), + (0x1E94, 'M', 'ẕ'), (0x1E95, 'V'), - (0x1E9A, 'M', u'aʾ'), - (0x1E9B, 'M', u'ṡ'), + (0x1E9A, 'M', 'aʾ'), + (0x1E9B, 'M', 'ṡ'), (0x1E9C, 'V'), - (0x1E9E, 'M', u'ss'), + (0x1E9E, 'M', 'ss'), (0x1E9F, 'V'), - (0x1EA0, 'M', u'ạ'), + (0x1EA0, 'M', 'ạ'), (0x1EA1, 'V'), - (0x1EA2, 'M', u'ả'), + (0x1EA2, 'M', 'ả'), (0x1EA3, 'V'), - (0x1EA4, 'M', u'ấ'), + (0x1EA4, 'M', 'ấ'), (0x1EA5, 'V'), - (0x1EA6, 'M', u'ầ'), + (0x1EA6, 'M', 'ầ'), (0x1EA7, 'V'), - (0x1EA8, 'M', u'ẩ'), + (0x1EA8, 'M', 'ẩ'), (0x1EA9, 'V'), - (0x1EAA, 'M', u'ẫ'), + (0x1EAA, 'M', 'ẫ'), (0x1EAB, 'V'), - (0x1EAC, 'M', u'ậ'), + (0x1EAC, 'M', 'ậ'), (0x1EAD, 'V'), - (0x1EAE, 'M', u'ắ'), + (0x1EAE, 'M', 'ắ'), (0x1EAF, 'V'), - (0x1EB0, 'M', u'ằ'), + (0x1EB0, 'M', 'ằ'), (0x1EB1, 'V'), - (0x1EB2, 'M', u'ẳ'), + (0x1EB2, 'M', 'ẳ'), (0x1EB3, 'V'), - (0x1EB4, 'M', u'ẵ'), + (0x1EB4, 'M', 'ẵ'), (0x1EB5, 'V'), - (0x1EB6, 'M', u'ặ'), + (0x1EB6, 'M', 'ặ'), (0x1EB7, 'V'), - (0x1EB8, 'M', u'ẹ'), + (0x1EB8, 'M', 'ẹ'), (0x1EB9, 'V'), - (0x1EBA, 'M', u'ẻ'), + (0x1EBA, 'M', 'ẻ'), (0x1EBB, 'V'), - (0x1EBC, 'M', u'ẽ'), + (0x1EBC, 'M', 'ẽ'), (0x1EBD, 'V'), - (0x1EBE, 'M', u'ế'), + (0x1EBE, 'M', 'ế'), (0x1EBF, 'V'), - (0x1EC0, 'M', u'ề'), + (0x1EC0, 'M', 'ề'), (0x1EC1, 'V'), - (0x1EC2, 'M', u'ể'), + (0x1EC2, 'M', 'ể'), (0x1EC3, 'V'), - (0x1EC4, 'M', u'ễ'), + (0x1EC4, 'M', 'ễ'), (0x1EC5, 'V'), - (0x1EC6, 'M', u'ệ'), + (0x1EC6, 'M', 'ệ'), (0x1EC7, 'V'), - (0x1EC8, 'M', u'ỉ'), + (0x1EC8, 'M', 'ỉ'), (0x1EC9, 'V'), - (0x1ECA, 'M', u'ị'), + (0x1ECA, 'M', 'ị'), (0x1ECB, 'V'), - (0x1ECC, 'M', u'ọ'), + (0x1ECC, 'M', 'ọ'), (0x1ECD, 'V'), - (0x1ECE, 'M', u'ỏ'), + (0x1ECE, 'M', 'ỏ'), (0x1ECF, 'V'), - (0x1ED0, 'M', u'ố'), + (0x1ED0, 'M', 'ố'), (0x1ED1, 'V'), - (0x1ED2, 'M', u'ồ'), + (0x1ED2, 'M', 'ồ'), (0x1ED3, 'V'), - (0x1ED4, 'M', u'ổ'), + (0x1ED4, 'M', 'ổ'), (0x1ED5, 'V'), - (0x1ED6, 'M', u'ỗ'), + (0x1ED6, 'M', 'ỗ'), (0x1ED7, 'V'), - (0x1ED8, 'M', u'ộ'), + (0x1ED8, 'M', 'ộ'), (0x1ED9, 'V'), - (0x1EDA, 'M', u'ớ'), + (0x1EDA, 'M', 'ớ'), (0x1EDB, 'V'), - (0x1EDC, 'M', u'ờ'), + (0x1EDC, 'M', 'ờ'), (0x1EDD, 'V'), - (0x1EDE, 'M', u'ở'), + (0x1EDE, 'M', 'ở'), (0x1EDF, 'V'), - (0x1EE0, 'M', u'ỡ'), + (0x1EE0, 'M', 'ỡ'), (0x1EE1, 'V'), - (0x1EE2, 'M', u'ợ'), + (0x1EE2, 'M', 'ợ'), (0x1EE3, 'V'), - (0x1EE4, 'M', u'ụ'), + (0x1EE4, 'M', 'ụ'), (0x1EE5, 'V'), - (0x1EE6, 'M', u'ủ'), + (0x1EE6, 'M', 'ủ'), (0x1EE7, 'V'), - (0x1EE8, 'M', u'ứ'), + (0x1EE8, 'M', 'ứ'), (0x1EE9, 'V'), - (0x1EEA, 'M', u'ừ'), + (0x1EEA, 'M', 'ừ'), (0x1EEB, 'V'), - (0x1EEC, 'M', u'ử'), + (0x1EEC, 'M', 'ử'), (0x1EED, 'V'), ] def _seg_19(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1EEE, 'M', u'ữ'), + (0x1EEE, 'M', 'ữ'), (0x1EEF, 'V'), - (0x1EF0, 'M', u'ự'), + (0x1EF0, 'M', 'ự'), (0x1EF1, 'V'), - (0x1EF2, 'M', u'ỳ'), + (0x1EF2, 'M', 'ỳ'), (0x1EF3, 'V'), - (0x1EF4, 'M', u'ỵ'), + (0x1EF4, 'M', 'ỵ'), (0x1EF5, 'V'), - (0x1EF6, 'M', u'ỷ'), + (0x1EF6, 'M', 'ỷ'), (0x1EF7, 'V'), - (0x1EF8, 'M', u'ỹ'), + (0x1EF8, 'M', 'ỹ'), (0x1EF9, 'V'), - (0x1EFA, 'M', u'ỻ'), + (0x1EFA, 'M', 'ỻ'), (0x1EFB, 'V'), - (0x1EFC, 'M', u'ỽ'), + (0x1EFC, 'M', 'ỽ'), (0x1EFD, 'V'), - (0x1EFE, 'M', u'ỿ'), + (0x1EFE, 'M', 'ỿ'), (0x1EFF, 'V'), - (0x1F08, 'M', u'ἀ'), - (0x1F09, 'M', u'ἁ'), - (0x1F0A, 'M', u'ἂ'), - (0x1F0B, 'M', u'ἃ'), - (0x1F0C, 'M', u'ἄ'), - (0x1F0D, 'M', u'ἅ'), - (0x1F0E, 'M', u'ἆ'), - (0x1F0F, 'M', u'ἇ'), + (0x1F08, 'M', 'ἀ'), + (0x1F09, 'M', 'ἁ'), + (0x1F0A, 'M', 'ἂ'), + (0x1F0B, 'M', 'ἃ'), + (0x1F0C, 'M', 'ἄ'), + (0x1F0D, 'M', 'ἅ'), + (0x1F0E, 'M', 'ἆ'), + (0x1F0F, 'M', 'ἇ'), (0x1F10, 'V'), (0x1F16, 'X'), - (0x1F18, 'M', u'ἐ'), - (0x1F19, 'M', u'ἑ'), - (0x1F1A, 'M', u'ἒ'), - (0x1F1B, 'M', u'ἓ'), - (0x1F1C, 'M', u'ἔ'), - (0x1F1D, 'M', u'ἕ'), + (0x1F18, 'M', 'ἐ'), + (0x1F19, 'M', 'ἑ'), + (0x1F1A, 'M', 'ἒ'), + (0x1F1B, 'M', 'ἓ'), + (0x1F1C, 'M', 'ἔ'), + (0x1F1D, 'M', 'ἕ'), (0x1F1E, 'X'), (0x1F20, 'V'), - (0x1F28, 'M', u'ἠ'), - (0x1F29, 'M', u'ἡ'), - (0x1F2A, 'M', u'ἢ'), - (0x1F2B, 'M', u'ἣ'), - (0x1F2C, 'M', u'ἤ'), - (0x1F2D, 'M', u'ἥ'), - (0x1F2E, 'M', u'ἦ'), - (0x1F2F, 'M', u'ἧ'), + (0x1F28, 'M', 'ἠ'), + (0x1F29, 'M', 'ἡ'), + (0x1F2A, 'M', 'ἢ'), + (0x1F2B, 'M', 'ἣ'), + (0x1F2C, 'M', 'ἤ'), + (0x1F2D, 'M', 'ἥ'), + (0x1F2E, 'M', 'ἦ'), + (0x1F2F, 'M', 'ἧ'), (0x1F30, 'V'), - (0x1F38, 'M', u'ἰ'), - (0x1F39, 'M', u'ἱ'), - (0x1F3A, 'M', u'ἲ'), - (0x1F3B, 'M', u'ἳ'), - (0x1F3C, 'M', u'ἴ'), - (0x1F3D, 'M', u'ἵ'), - (0x1F3E, 'M', u'ἶ'), - (0x1F3F, 'M', u'ἷ'), + (0x1F38, 'M', 'ἰ'), + (0x1F39, 'M', 'ἱ'), + (0x1F3A, 'M', 'ἲ'), + (0x1F3B, 'M', 'ἳ'), + (0x1F3C, 'M', 'ἴ'), + (0x1F3D, 'M', 'ἵ'), + (0x1F3E, 'M', 'ἶ'), + (0x1F3F, 'M', 'ἷ'), (0x1F40, 'V'), (0x1F46, 'X'), - (0x1F48, 'M', u'ὀ'), - (0x1F49, 'M', u'ὁ'), - (0x1F4A, 'M', u'ὂ'), - (0x1F4B, 'M', u'ὃ'), - (0x1F4C, 'M', u'ὄ'), - (0x1F4D, 'M', u'ὅ'), + (0x1F48, 'M', 'ὀ'), + (0x1F49, 'M', 'ὁ'), + (0x1F4A, 'M', 'ὂ'), + (0x1F4B, 'M', 'ὃ'), + (0x1F4C, 'M', 'ὄ'), + (0x1F4D, 'M', 'ὅ'), (0x1F4E, 'X'), (0x1F50, 'V'), (0x1F58, 'X'), - (0x1F59, 'M', u'ὑ'), + (0x1F59, 'M', 'ὑ'), (0x1F5A, 'X'), - (0x1F5B, 'M', u'ὓ'), + (0x1F5B, 'M', 'ὓ'), (0x1F5C, 'X'), - (0x1F5D, 'M', u'ὕ'), + (0x1F5D, 'M', 'ὕ'), (0x1F5E, 'X'), - (0x1F5F, 'M', u'ὗ'), + (0x1F5F, 'M', 'ὗ'), (0x1F60, 'V'), - (0x1F68, 'M', u'ὠ'), - (0x1F69, 'M', u'ὡ'), - (0x1F6A, 'M', u'ὢ'), - (0x1F6B, 'M', u'ὣ'), - (0x1F6C, 'M', u'ὤ'), - (0x1F6D, 'M', u'ὥ'), - (0x1F6E, 'M', u'ὦ'), - (0x1F6F, 'M', u'ὧ'), + (0x1F68, 'M', 'ὠ'), + (0x1F69, 'M', 'ὡ'), + (0x1F6A, 'M', 'ὢ'), + (0x1F6B, 'M', 'ὣ'), + (0x1F6C, 'M', 'ὤ'), + (0x1F6D, 'M', 'ὥ'), + (0x1F6E, 'M', 'ὦ'), + (0x1F6F, 'M', 'ὧ'), (0x1F70, 'V'), - (0x1F71, 'M', u'ά'), + (0x1F71, 'M', 'ά'), (0x1F72, 'V'), - (0x1F73, 'M', u'έ'), + (0x1F73, 'M', 'έ'), (0x1F74, 'V'), - (0x1F75, 'M', u'ή'), + (0x1F75, 'M', 'ή'), (0x1F76, 'V'), - (0x1F77, 'M', u'ί'), + (0x1F77, 'M', 'ί'), (0x1F78, 'V'), - (0x1F79, 'M', u'ό'), + (0x1F79, 'M', 'ό'), (0x1F7A, 'V'), - (0x1F7B, 'M', u'ύ'), + (0x1F7B, 'M', 'ύ'), (0x1F7C, 'V'), - (0x1F7D, 'M', u'ώ'), + (0x1F7D, 'M', 'ώ'), (0x1F7E, 'X'), - (0x1F80, 'M', u'ἀι'), - (0x1F81, 'M', u'ἁι'), - (0x1F82, 'M', u'ἂι'), - (0x1F83, 'M', u'ἃι'), - (0x1F84, 'M', u'ἄι'), + (0x1F80, 'M', 'ἀι'), + (0x1F81, 'M', 'ἁι'), + (0x1F82, 'M', 'ἂι'), + (0x1F83, 'M', 'ἃι'), + (0x1F84, 'M', 'ἄι'), ] def _seg_20(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1F85, 'M', u'ἅι'), - (0x1F86, 'M', u'ἆι'), - (0x1F87, 'M', u'ἇι'), - (0x1F88, 'M', u'ἀι'), - (0x1F89, 'M', u'ἁι'), - (0x1F8A, 'M', u'ἂι'), - (0x1F8B, 'M', u'ἃι'), - (0x1F8C, 'M', u'ἄι'), - (0x1F8D, 'M', u'ἅι'), - (0x1F8E, 'M', u'ἆι'), - (0x1F8F, 'M', u'ἇι'), - (0x1F90, 'M', u'ἠι'), - (0x1F91, 'M', u'ἡι'), - (0x1F92, 'M', u'ἢι'), - (0x1F93, 'M', u'ἣι'), - (0x1F94, 'M', u'ἤι'), - (0x1F95, 'M', u'ἥι'), - (0x1F96, 'M', u'ἦι'), - (0x1F97, 'M', u'ἧι'), - (0x1F98, 'M', u'ἠι'), - (0x1F99, 'M', u'ἡι'), - (0x1F9A, 'M', u'ἢι'), - (0x1F9B, 'M', u'ἣι'), - (0x1F9C, 'M', u'ἤι'), - (0x1F9D, 'M', u'ἥι'), - (0x1F9E, 'M', u'ἦι'), - (0x1F9F, 'M', u'ἧι'), - (0x1FA0, 'M', u'ὠι'), - (0x1FA1, 'M', u'ὡι'), - (0x1FA2, 'M', u'ὢι'), - (0x1FA3, 'M', u'ὣι'), - (0x1FA4, 'M', u'ὤι'), - (0x1FA5, 'M', u'ὥι'), - (0x1FA6, 'M', u'ὦι'), - (0x1FA7, 'M', u'ὧι'), - (0x1FA8, 'M', u'ὠι'), - (0x1FA9, 'M', u'ὡι'), - (0x1FAA, 'M', u'ὢι'), - (0x1FAB, 'M', u'ὣι'), - (0x1FAC, 'M', u'ὤι'), - (0x1FAD, 'M', u'ὥι'), - (0x1FAE, 'M', u'ὦι'), - (0x1FAF, 'M', u'ὧι'), + (0x1F85, 'M', 'ἅι'), + (0x1F86, 'M', 'ἆι'), + (0x1F87, 'M', 'ἇι'), + (0x1F88, 'M', 'ἀι'), + (0x1F89, 'M', 'ἁι'), + (0x1F8A, 'M', 'ἂι'), + (0x1F8B, 'M', 'ἃι'), + (0x1F8C, 'M', 'ἄι'), + (0x1F8D, 'M', 'ἅι'), + (0x1F8E, 'M', 'ἆι'), + (0x1F8F, 'M', 'ἇι'), + (0x1F90, 'M', 'ἠι'), + (0x1F91, 'M', 'ἡι'), + (0x1F92, 'M', 'ἢι'), + (0x1F93, 'M', 'ἣι'), + (0x1F94, 'M', 'ἤι'), + (0x1F95, 'M', 'ἥι'), + (0x1F96, 'M', 'ἦι'), + (0x1F97, 'M', 'ἧι'), + (0x1F98, 'M', 'ἠι'), + (0x1F99, 'M', 'ἡι'), + (0x1F9A, 'M', 'ἢι'), + (0x1F9B, 'M', 'ἣι'), + (0x1F9C, 'M', 'ἤι'), + (0x1F9D, 'M', 'ἥι'), + (0x1F9E, 'M', 'ἦι'), + (0x1F9F, 'M', 'ἧι'), + (0x1FA0, 'M', 'ὠι'), + (0x1FA1, 'M', 'ὡι'), + (0x1FA2, 'M', 'ὢι'), + (0x1FA3, 'M', 'ὣι'), + (0x1FA4, 'M', 'ὤι'), + (0x1FA5, 'M', 'ὥι'), + (0x1FA6, 'M', 'ὦι'), + (0x1FA7, 'M', 'ὧι'), + (0x1FA8, 'M', 'ὠι'), + (0x1FA9, 'M', 'ὡι'), + (0x1FAA, 'M', 'ὢι'), + (0x1FAB, 'M', 'ὣι'), + (0x1FAC, 'M', 'ὤι'), + (0x1FAD, 'M', 'ὥι'), + (0x1FAE, 'M', 'ὦι'), + (0x1FAF, 'M', 'ὧι'), (0x1FB0, 'V'), - (0x1FB2, 'M', u'ὰι'), - (0x1FB3, 'M', u'αι'), - (0x1FB4, 'M', u'άι'), + (0x1FB2, 'M', 'ὰι'), + (0x1FB3, 'M', 'αι'), + (0x1FB4, 'M', 'άι'), (0x1FB5, 'X'), (0x1FB6, 'V'), - (0x1FB7, 'M', u'ᾶι'), - (0x1FB8, 'M', u'ᾰ'), - (0x1FB9, 'M', u'ᾱ'), - (0x1FBA, 'M', u'ὰ'), - (0x1FBB, 'M', u'ά'), - (0x1FBC, 'M', u'αι'), - (0x1FBD, '3', u' ̓'), - (0x1FBE, 'M', u'ι'), - (0x1FBF, '3', u' ̓'), - (0x1FC0, '3', u' ͂'), - (0x1FC1, '3', u' ̈͂'), - (0x1FC2, 'M', u'ὴι'), - (0x1FC3, 'M', u'ηι'), - (0x1FC4, 'M', u'ήι'), + (0x1FB7, 'M', 'ᾶι'), + (0x1FB8, 'M', 'ᾰ'), + (0x1FB9, 'M', 'ᾱ'), + (0x1FBA, 'M', 'ὰ'), + (0x1FBB, 'M', 'ά'), + (0x1FBC, 'M', 'αι'), + (0x1FBD, '3', ' ̓'), + (0x1FBE, 'M', 'ι'), + (0x1FBF, '3', ' ̓'), + (0x1FC0, '3', ' ͂'), + (0x1FC1, '3', ' ̈͂'), + (0x1FC2, 'M', 'ὴι'), + (0x1FC3, 'M', 'ηι'), + (0x1FC4, 'M', 'ήι'), (0x1FC5, 'X'), (0x1FC6, 'V'), - (0x1FC7, 'M', u'ῆι'), - (0x1FC8, 'M', u'ὲ'), - (0x1FC9, 'M', u'έ'), - (0x1FCA, 'M', u'ὴ'), - (0x1FCB, 'M', u'ή'), - (0x1FCC, 'M', u'ηι'), - (0x1FCD, '3', u' ̓̀'), - (0x1FCE, '3', u' ̓́'), - (0x1FCF, '3', u' ̓͂'), + (0x1FC7, 'M', 'ῆι'), + (0x1FC8, 'M', 'ὲ'), + (0x1FC9, 'M', 'έ'), + (0x1FCA, 'M', 'ὴ'), + (0x1FCB, 'M', 'ή'), + (0x1FCC, 'M', 'ηι'), + (0x1FCD, '3', ' ̓̀'), + (0x1FCE, '3', ' ̓́'), + (0x1FCF, '3', ' ̓͂'), (0x1FD0, 'V'), - (0x1FD3, 'M', u'ΐ'), + (0x1FD3, 'M', 'ΐ'), (0x1FD4, 'X'), (0x1FD6, 'V'), - (0x1FD8, 'M', u'ῐ'), - (0x1FD9, 'M', u'ῑ'), - (0x1FDA, 'M', u'ὶ'), - (0x1FDB, 'M', u'ί'), + (0x1FD8, 'M', 'ῐ'), + (0x1FD9, 'M', 'ῑ'), + (0x1FDA, 'M', 'ὶ'), + (0x1FDB, 'M', 'ί'), (0x1FDC, 'X'), - (0x1FDD, '3', u' ̔̀'), - (0x1FDE, '3', u' ̔́'), - (0x1FDF, '3', u' ̔͂'), + (0x1FDD, '3', ' ̔̀'), + (0x1FDE, '3', ' ̔́'), + (0x1FDF, '3', ' ̔͂'), (0x1FE0, 'V'), - (0x1FE3, 'M', u'ΰ'), + (0x1FE3, 'M', 'ΰ'), (0x1FE4, 'V'), - (0x1FE8, 'M', u'ῠ'), - (0x1FE9, 'M', u'ῡ'), - (0x1FEA, 'M', u'ὺ'), - (0x1FEB, 'M', u'ύ'), - (0x1FEC, 'M', u'ῥ'), - (0x1FED, '3', u' ̈̀'), - (0x1FEE, '3', u' ̈́'), - (0x1FEF, '3', u'`'), + (0x1FE8, 'M', 'ῠ'), + (0x1FE9, 'M', 'ῡ'), + (0x1FEA, 'M', 'ὺ'), + (0x1FEB, 'M', 'ύ'), + (0x1FEC, 'M', 'ῥ'), + (0x1FED, '3', ' ̈̀'), + (0x1FEE, '3', ' ̈́'), + (0x1FEF, '3', '`'), (0x1FF0, 'X'), - (0x1FF2, 'M', u'ὼι'), - (0x1FF3, 'M', u'ωι'), + (0x1FF2, 'M', 'ὼι'), + (0x1FF3, 'M', 'ωι'), ] def _seg_21(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1FF4, 'M', u'ώι'), + (0x1FF4, 'M', 'ώι'), (0x1FF5, 'X'), (0x1FF6, 'V'), - (0x1FF7, 'M', u'ῶι'), - (0x1FF8, 'M', u'ὸ'), - (0x1FF9, 'M', u'ό'), - (0x1FFA, 'M', u'ὼ'), - (0x1FFB, 'M', u'ώ'), - (0x1FFC, 'M', u'ωι'), - (0x1FFD, '3', u' ́'), - (0x1FFE, '3', u' ̔'), + (0x1FF7, 'M', 'ῶι'), + (0x1FF8, 'M', 'ὸ'), + (0x1FF9, 'M', 'ό'), + (0x1FFA, 'M', 'ὼ'), + (0x1FFB, 'M', 'ώ'), + (0x1FFC, 'M', 'ωι'), + (0x1FFD, '3', ' ́'), + (0x1FFE, '3', ' ̔'), (0x1FFF, 'X'), - (0x2000, '3', u' '), + (0x2000, '3', ' '), (0x200B, 'I'), - (0x200C, 'D', u''), + (0x200C, 'D', ''), (0x200E, 'X'), (0x2010, 'V'), - (0x2011, 'M', u'‐'), + (0x2011, 'M', '‐'), (0x2012, 'V'), - (0x2017, '3', u' ̳'), + (0x2017, '3', ' ̳'), (0x2018, 'V'), (0x2024, 'X'), (0x2027, 'V'), (0x2028, 'X'), - (0x202F, '3', u' '), + (0x202F, '3', ' '), (0x2030, 'V'), - (0x2033, 'M', u'′′'), - (0x2034, 'M', u'′′′'), + (0x2033, 'M', '′′'), + (0x2034, 'M', '′′′'), (0x2035, 'V'), - (0x2036, 'M', u'‵‵'), - (0x2037, 'M', u'‵‵‵'), + (0x2036, 'M', '‵‵'), + (0x2037, 'M', '‵‵‵'), (0x2038, 'V'), - (0x203C, '3', u'!!'), + (0x203C, '3', '!!'), (0x203D, 'V'), - (0x203E, '3', u' ̅'), + (0x203E, '3', ' ̅'), (0x203F, 'V'), - (0x2047, '3', u'??'), - (0x2048, '3', u'?!'), - (0x2049, '3', u'!?'), + (0x2047, '3', '??'), + (0x2048, '3', '?!'), + (0x2049, '3', '!?'), (0x204A, 'V'), - (0x2057, 'M', u'′′′′'), + (0x2057, 'M', '′′′′'), (0x2058, 'V'), - (0x205F, '3', u' '), + (0x205F, '3', ' '), (0x2060, 'I'), (0x2061, 'X'), (0x2064, 'I'), (0x2065, 'X'), - (0x2070, 'M', u'0'), - (0x2071, 'M', u'i'), + (0x2070, 'M', '0'), + (0x2071, 'M', 'i'), (0x2072, 'X'), - (0x2074, 'M', u'4'), - (0x2075, 'M', u'5'), - (0x2076, 'M', u'6'), - (0x2077, 'M', u'7'), - (0x2078, 'M', u'8'), - (0x2079, 'M', u'9'), - (0x207A, '3', u'+'), - (0x207B, 'M', u'−'), - (0x207C, '3', u'='), - (0x207D, '3', u'('), - (0x207E, '3', u')'), - (0x207F, 'M', u'n'), - (0x2080, 'M', u'0'), - (0x2081, 'M', u'1'), - (0x2082, 'M', u'2'), - (0x2083, 'M', u'3'), - (0x2084, 'M', u'4'), - (0x2085, 'M', u'5'), - (0x2086, 'M', u'6'), - (0x2087, 'M', u'7'), - (0x2088, 'M', u'8'), - (0x2089, 'M', u'9'), - (0x208A, '3', u'+'), - (0x208B, 'M', u'−'), - (0x208C, '3', u'='), - (0x208D, '3', u'('), - (0x208E, '3', u')'), + (0x2074, 'M', '4'), + (0x2075, 'M', '5'), + (0x2076, 'M', '6'), + (0x2077, 'M', '7'), + (0x2078, 'M', '8'), + (0x2079, 'M', '9'), + (0x207A, '3', '+'), + (0x207B, 'M', '−'), + (0x207C, '3', '='), + (0x207D, '3', '('), + (0x207E, '3', ')'), + (0x207F, 'M', 'n'), + (0x2080, 'M', '0'), + (0x2081, 'M', '1'), + (0x2082, 'M', '2'), + (0x2083, 'M', '3'), + (0x2084, 'M', '4'), + (0x2085, 'M', '5'), + (0x2086, 'M', '6'), + (0x2087, 'M', '7'), + (0x2088, 'M', '8'), + (0x2089, 'M', '9'), + (0x208A, '3', '+'), + (0x208B, 'M', '−'), + (0x208C, '3', '='), + (0x208D, '3', '('), + (0x208E, '3', ')'), (0x208F, 'X'), - (0x2090, 'M', u'a'), - (0x2091, 'M', u'e'), - (0x2092, 'M', u'o'), - (0x2093, 'M', u'x'), - (0x2094, 'M', u'ə'), - (0x2095, 'M', u'h'), - (0x2096, 'M', u'k'), - (0x2097, 'M', u'l'), - (0x2098, 'M', u'm'), - (0x2099, 'M', u'n'), - (0x209A, 'M', u'p'), - (0x209B, 'M', u's'), - (0x209C, 'M', u't'), + (0x2090, 'M', 'a'), + (0x2091, 'M', 'e'), + (0x2092, 'M', 'o'), + (0x2093, 'M', 'x'), + (0x2094, 'M', 'ə'), + (0x2095, 'M', 'h'), + (0x2096, 'M', 'k'), + (0x2097, 'M', 'l'), + (0x2098, 'M', 'm'), + (0x2099, 'M', 'n'), + (0x209A, 'M', 'p'), + (0x209B, 'M', 's'), + (0x209C, 'M', 't'), (0x209D, 'X'), (0x20A0, 'V'), - (0x20A8, 'M', u'rs'), + (0x20A8, 'M', 'rs'), (0x20A9, 'V'), (0x20C0, 'X'), (0x20D0, 'V'), (0x20F1, 'X'), - (0x2100, '3', u'a/c'), - (0x2101, '3', u'a/s'), + (0x2100, '3', 'a/c'), + (0x2101, '3', 'a/s'), ] def _seg_22(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2102, 'M', u'c'), - (0x2103, 'M', u'°c'), + (0x2102, 'M', 'c'), + (0x2103, 'M', '°c'), (0x2104, 'V'), - (0x2105, '3', u'c/o'), - (0x2106, '3', u'c/u'), - (0x2107, 'M', u'ɛ'), + (0x2105, '3', 'c/o'), + (0x2106, '3', 'c/u'), + (0x2107, 'M', 'ɛ'), (0x2108, 'V'), - (0x2109, 'M', u'°f'), - (0x210A, 'M', u'g'), - (0x210B, 'M', u'h'), - (0x210F, 'M', u'ħ'), - (0x2110, 'M', u'i'), - (0x2112, 'M', u'l'), + (0x2109, 'M', '°f'), + (0x210A, 'M', 'g'), + (0x210B, 'M', 'h'), + (0x210F, 'M', 'ħ'), + (0x2110, 'M', 'i'), + (0x2112, 'M', 'l'), (0x2114, 'V'), - (0x2115, 'M', u'n'), - (0x2116, 'M', u'no'), + (0x2115, 'M', 'n'), + (0x2116, 'M', 'no'), (0x2117, 'V'), - (0x2119, 'M', u'p'), - (0x211A, 'M', u'q'), - (0x211B, 'M', u'r'), + (0x2119, 'M', 'p'), + (0x211A, 'M', 'q'), + (0x211B, 'M', 'r'), (0x211E, 'V'), - (0x2120, 'M', u'sm'), - (0x2121, 'M', u'tel'), - (0x2122, 'M', u'tm'), + (0x2120, 'M', 'sm'), + (0x2121, 'M', 'tel'), + (0x2122, 'M', 'tm'), (0x2123, 'V'), - (0x2124, 'M', u'z'), + (0x2124, 'M', 'z'), (0x2125, 'V'), - (0x2126, 'M', u'ω'), + (0x2126, 'M', 'ω'), (0x2127, 'V'), - (0x2128, 'M', u'z'), + (0x2128, 'M', 'z'), (0x2129, 'V'), - (0x212A, 'M', u'k'), - (0x212B, 'M', u'å'), - (0x212C, 'M', u'b'), - (0x212D, 'M', u'c'), + (0x212A, 'M', 'k'), + (0x212B, 'M', 'å'), + (0x212C, 'M', 'b'), + (0x212D, 'M', 'c'), (0x212E, 'V'), - (0x212F, 'M', u'e'), - (0x2131, 'M', u'f'), + (0x212F, 'M', 'e'), + (0x2131, 'M', 'f'), (0x2132, 'X'), - (0x2133, 'M', u'm'), - (0x2134, 'M', u'o'), - (0x2135, 'M', u'א'), - (0x2136, 'M', u'ב'), - (0x2137, 'M', u'ג'), - (0x2138, 'M', u'ד'), - (0x2139, 'M', u'i'), + (0x2133, 'M', 'm'), + (0x2134, 'M', 'o'), + (0x2135, 'M', 'א'), + (0x2136, 'M', 'ב'), + (0x2137, 'M', 'ג'), + (0x2138, 'M', 'ד'), + (0x2139, 'M', 'i'), (0x213A, 'V'), - (0x213B, 'M', u'fax'), - (0x213C, 'M', u'π'), - (0x213D, 'M', u'γ'), - (0x213F, 'M', u'π'), - (0x2140, 'M', u'∑'), + (0x213B, 'M', 'fax'), + (0x213C, 'M', 'π'), + (0x213D, 'M', 'γ'), + (0x213F, 'M', 'π'), + (0x2140, 'M', '∑'), (0x2141, 'V'), - (0x2145, 'M', u'd'), - (0x2147, 'M', u'e'), - (0x2148, 'M', u'i'), - (0x2149, 'M', u'j'), + (0x2145, 'M', 'd'), + (0x2147, 'M', 'e'), + (0x2148, 'M', 'i'), + (0x2149, 'M', 'j'), (0x214A, 'V'), - (0x2150, 'M', u'1⁄7'), - (0x2151, 'M', u'1⁄9'), - (0x2152, 'M', u'1⁄10'), - (0x2153, 'M', u'1⁄3'), - (0x2154, 'M', u'2⁄3'), - (0x2155, 'M', u'1⁄5'), - (0x2156, 'M', u'2⁄5'), - (0x2157, 'M', u'3⁄5'), - (0x2158, 'M', u'4⁄5'), - (0x2159, 'M', u'1⁄6'), - (0x215A, 'M', u'5⁄6'), - (0x215B, 'M', u'1⁄8'), - (0x215C, 'M', u'3⁄8'), - (0x215D, 'M', u'5⁄8'), - (0x215E, 'M', u'7⁄8'), - (0x215F, 'M', u'1⁄'), - (0x2160, 'M', u'i'), - (0x2161, 'M', u'ii'), - (0x2162, 'M', u'iii'), - (0x2163, 'M', u'iv'), - (0x2164, 'M', u'v'), - (0x2165, 'M', u'vi'), - (0x2166, 'M', u'vii'), - (0x2167, 'M', u'viii'), - (0x2168, 'M', u'ix'), - (0x2169, 'M', u'x'), - (0x216A, 'M', u'xi'), - (0x216B, 'M', u'xii'), - (0x216C, 'M', u'l'), - (0x216D, 'M', u'c'), - (0x216E, 'M', u'd'), - (0x216F, 'M', u'm'), - (0x2170, 'M', u'i'), - (0x2171, 'M', u'ii'), - (0x2172, 'M', u'iii'), - (0x2173, 'M', u'iv'), - (0x2174, 'M', u'v'), - (0x2175, 'M', u'vi'), - (0x2176, 'M', u'vii'), - (0x2177, 'M', u'viii'), - (0x2178, 'M', u'ix'), - (0x2179, 'M', u'x'), + (0x2150, 'M', '1⁄7'), + (0x2151, 'M', '1⁄9'), + (0x2152, 'M', '1⁄10'), + (0x2153, 'M', '1⁄3'), + (0x2154, 'M', '2⁄3'), + (0x2155, 'M', '1⁄5'), + (0x2156, 'M', '2⁄5'), + (0x2157, 'M', '3⁄5'), + (0x2158, 'M', '4⁄5'), + (0x2159, 'M', '1⁄6'), + (0x215A, 'M', '5⁄6'), + (0x215B, 'M', '1⁄8'), + (0x215C, 'M', '3⁄8'), + (0x215D, 'M', '5⁄8'), + (0x215E, 'M', '7⁄8'), + (0x215F, 'M', '1⁄'), + (0x2160, 'M', 'i'), + (0x2161, 'M', 'ii'), + (0x2162, 'M', 'iii'), + (0x2163, 'M', 'iv'), + (0x2164, 'M', 'v'), + (0x2165, 'M', 'vi'), + (0x2166, 'M', 'vii'), + (0x2167, 'M', 'viii'), + (0x2168, 'M', 'ix'), + (0x2169, 'M', 'x'), + (0x216A, 'M', 'xi'), + (0x216B, 'M', 'xii'), + (0x216C, 'M', 'l'), + (0x216D, 'M', 'c'), + (0x216E, 'M', 'd'), + (0x216F, 'M', 'm'), + (0x2170, 'M', 'i'), + (0x2171, 'M', 'ii'), + (0x2172, 'M', 'iii'), + (0x2173, 'M', 'iv'), + (0x2174, 'M', 'v'), + (0x2175, 'M', 'vi'), + (0x2176, 'M', 'vii'), + (0x2177, 'M', 'viii'), + (0x2178, 'M', 'ix'), + (0x2179, 'M', 'x'), ] def _seg_23(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x217A, 'M', u'xi'), - (0x217B, 'M', u'xii'), - (0x217C, 'M', u'l'), - (0x217D, 'M', u'c'), - (0x217E, 'M', u'd'), - (0x217F, 'M', u'm'), + (0x217A, 'M', 'xi'), + (0x217B, 'M', 'xii'), + (0x217C, 'M', 'l'), + (0x217D, 'M', 'c'), + (0x217E, 'M', 'd'), + (0x217F, 'M', 'm'), (0x2180, 'V'), (0x2183, 'X'), (0x2184, 'V'), - (0x2189, 'M', u'0⁄3'), + (0x2189, 'M', '0⁄3'), (0x218A, 'V'), (0x218C, 'X'), (0x2190, 'V'), - (0x222C, 'M', u'∫∫'), - (0x222D, 'M', u'∫∫∫'), + (0x222C, 'M', '∫∫'), + (0x222D, 'M', '∫∫∫'), (0x222E, 'V'), - (0x222F, 'M', u'∮∮'), - (0x2230, 'M', u'∮∮∮'), + (0x222F, 'M', '∮∮'), + (0x2230, 'M', '∮∮∮'), (0x2231, 'V'), (0x2260, '3'), (0x2261, 'V'), (0x226E, '3'), (0x2270, 'V'), - (0x2329, 'M', u'〈'), - (0x232A, 'M', u'〉'), + (0x2329, 'M', '〈'), + (0x232A, 'M', '〉'), (0x232B, 'V'), (0x2427, 'X'), (0x2440, 'V'), (0x244B, 'X'), - (0x2460, 'M', u'1'), - (0x2461, 'M', u'2'), - (0x2462, 'M', u'3'), - (0x2463, 'M', u'4'), - (0x2464, 'M', u'5'), - (0x2465, 'M', u'6'), - (0x2466, 'M', u'7'), - (0x2467, 'M', u'8'), - (0x2468, 'M', u'9'), - (0x2469, 'M', u'10'), - (0x246A, 'M', u'11'), - (0x246B, 'M', u'12'), - (0x246C, 'M', u'13'), - (0x246D, 'M', u'14'), - (0x246E, 'M', u'15'), - (0x246F, 'M', u'16'), - (0x2470, 'M', u'17'), - (0x2471, 'M', u'18'), - (0x2472, 'M', u'19'), - (0x2473, 'M', u'20'), - (0x2474, '3', u'(1)'), - (0x2475, '3', u'(2)'), - (0x2476, '3', u'(3)'), - (0x2477, '3', u'(4)'), - (0x2478, '3', u'(5)'), - (0x2479, '3', u'(6)'), - (0x247A, '3', u'(7)'), - (0x247B, '3', u'(8)'), - (0x247C, '3', u'(9)'), - (0x247D, '3', u'(10)'), - (0x247E, '3', u'(11)'), - (0x247F, '3', u'(12)'), - (0x2480, '3', u'(13)'), - (0x2481, '3', u'(14)'), - (0x2482, '3', u'(15)'), - (0x2483, '3', u'(16)'), - (0x2484, '3', u'(17)'), - (0x2485, '3', u'(18)'), - (0x2486, '3', u'(19)'), - (0x2487, '3', u'(20)'), + (0x2460, 'M', '1'), + (0x2461, 'M', '2'), + (0x2462, 'M', '3'), + (0x2463, 'M', '4'), + (0x2464, 'M', '5'), + (0x2465, 'M', '6'), + (0x2466, 'M', '7'), + (0x2467, 'M', '8'), + (0x2468, 'M', '9'), + (0x2469, 'M', '10'), + (0x246A, 'M', '11'), + (0x246B, 'M', '12'), + (0x246C, 'M', '13'), + (0x246D, 'M', '14'), + (0x246E, 'M', '15'), + (0x246F, 'M', '16'), + (0x2470, 'M', '17'), + (0x2471, 'M', '18'), + (0x2472, 'M', '19'), + (0x2473, 'M', '20'), + (0x2474, '3', '(1)'), + (0x2475, '3', '(2)'), + (0x2476, '3', '(3)'), + (0x2477, '3', '(4)'), + (0x2478, '3', '(5)'), + (0x2479, '3', '(6)'), + (0x247A, '3', '(7)'), + (0x247B, '3', '(8)'), + (0x247C, '3', '(9)'), + (0x247D, '3', '(10)'), + (0x247E, '3', '(11)'), + (0x247F, '3', '(12)'), + (0x2480, '3', '(13)'), + (0x2481, '3', '(14)'), + (0x2482, '3', '(15)'), + (0x2483, '3', '(16)'), + (0x2484, '3', '(17)'), + (0x2485, '3', '(18)'), + (0x2486, '3', '(19)'), + (0x2487, '3', '(20)'), (0x2488, 'X'), - (0x249C, '3', u'(a)'), - (0x249D, '3', u'(b)'), - (0x249E, '3', u'(c)'), - (0x249F, '3', u'(d)'), - (0x24A0, '3', u'(e)'), - (0x24A1, '3', u'(f)'), - (0x24A2, '3', u'(g)'), - (0x24A3, '3', u'(h)'), - (0x24A4, '3', u'(i)'), - (0x24A5, '3', u'(j)'), - (0x24A6, '3', u'(k)'), - (0x24A7, '3', u'(l)'), - (0x24A8, '3', u'(m)'), - (0x24A9, '3', u'(n)'), - (0x24AA, '3', u'(o)'), - (0x24AB, '3', u'(p)'), - (0x24AC, '3', u'(q)'), - (0x24AD, '3', u'(r)'), - (0x24AE, '3', u'(s)'), - (0x24AF, '3', u'(t)'), - (0x24B0, '3', u'(u)'), - (0x24B1, '3', u'(v)'), - (0x24B2, '3', u'(w)'), - (0x24B3, '3', u'(x)'), - (0x24B4, '3', u'(y)'), - (0x24B5, '3', u'(z)'), - (0x24B6, 'M', u'a'), - (0x24B7, 'M', u'b'), - (0x24B8, 'M', u'c'), - (0x24B9, 'M', u'd'), + (0x249C, '3', '(a)'), + (0x249D, '3', '(b)'), + (0x249E, '3', '(c)'), + (0x249F, '3', '(d)'), + (0x24A0, '3', '(e)'), + (0x24A1, '3', '(f)'), + (0x24A2, '3', '(g)'), + (0x24A3, '3', '(h)'), + (0x24A4, '3', '(i)'), + (0x24A5, '3', '(j)'), + (0x24A6, '3', '(k)'), + (0x24A7, '3', '(l)'), + (0x24A8, '3', '(m)'), + (0x24A9, '3', '(n)'), + (0x24AA, '3', '(o)'), + (0x24AB, '3', '(p)'), + (0x24AC, '3', '(q)'), + (0x24AD, '3', '(r)'), + (0x24AE, '3', '(s)'), + (0x24AF, '3', '(t)'), + (0x24B0, '3', '(u)'), + (0x24B1, '3', '(v)'), + (0x24B2, '3', '(w)'), + (0x24B3, '3', '(x)'), + (0x24B4, '3', '(y)'), + (0x24B5, '3', '(z)'), + (0x24B6, 'M', 'a'), + (0x24B7, 'M', 'b'), + (0x24B8, 'M', 'c'), + (0x24B9, 'M', 'd'), ] def _seg_24(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x24BA, 'M', u'e'), - (0x24BB, 'M', u'f'), - (0x24BC, 'M', u'g'), - (0x24BD, 'M', u'h'), - (0x24BE, 'M', u'i'), - (0x24BF, 'M', u'j'), - (0x24C0, 'M', u'k'), - (0x24C1, 'M', u'l'), - (0x24C2, 'M', u'm'), - (0x24C3, 'M', u'n'), - (0x24C4, 'M', u'o'), - (0x24C5, 'M', u'p'), - (0x24C6, 'M', u'q'), - (0x24C7, 'M', u'r'), - (0x24C8, 'M', u's'), - (0x24C9, 'M', u't'), - (0x24CA, 'M', u'u'), - (0x24CB, 'M', u'v'), - (0x24CC, 'M', u'w'), - (0x24CD, 'M', u'x'), - (0x24CE, 'M', u'y'), - (0x24CF, 'M', u'z'), - (0x24D0, 'M', u'a'), - (0x24D1, 'M', u'b'), - (0x24D2, 'M', u'c'), - (0x24D3, 'M', u'd'), - (0x24D4, 'M', u'e'), - (0x24D5, 'M', u'f'), - (0x24D6, 'M', u'g'), - (0x24D7, 'M', u'h'), - (0x24D8, 'M', u'i'), - (0x24D9, 'M', u'j'), - (0x24DA, 'M', u'k'), - (0x24DB, 'M', u'l'), - (0x24DC, 'M', u'm'), - (0x24DD, 'M', u'n'), - (0x24DE, 'M', u'o'), - (0x24DF, 'M', u'p'), - (0x24E0, 'M', u'q'), - (0x24E1, 'M', u'r'), - (0x24E2, 'M', u's'), - (0x24E3, 'M', u't'), - (0x24E4, 'M', u'u'), - (0x24E5, 'M', u'v'), - (0x24E6, 'M', u'w'), - (0x24E7, 'M', u'x'), - (0x24E8, 'M', u'y'), - (0x24E9, 'M', u'z'), - (0x24EA, 'M', u'0'), + (0x24BA, 'M', 'e'), + (0x24BB, 'M', 'f'), + (0x24BC, 'M', 'g'), + (0x24BD, 'M', 'h'), + (0x24BE, 'M', 'i'), + (0x24BF, 'M', 'j'), + (0x24C0, 'M', 'k'), + (0x24C1, 'M', 'l'), + (0x24C2, 'M', 'm'), + (0x24C3, 'M', 'n'), + (0x24C4, 'M', 'o'), + (0x24C5, 'M', 'p'), + (0x24C6, 'M', 'q'), + (0x24C7, 'M', 'r'), + (0x24C8, 'M', 's'), + (0x24C9, 'M', 't'), + (0x24CA, 'M', 'u'), + (0x24CB, 'M', 'v'), + (0x24CC, 'M', 'w'), + (0x24CD, 'M', 'x'), + (0x24CE, 'M', 'y'), + (0x24CF, 'M', 'z'), + (0x24D0, 'M', 'a'), + (0x24D1, 'M', 'b'), + (0x24D2, 'M', 'c'), + (0x24D3, 'M', 'd'), + (0x24D4, 'M', 'e'), + (0x24D5, 'M', 'f'), + (0x24D6, 'M', 'g'), + (0x24D7, 'M', 'h'), + (0x24D8, 'M', 'i'), + (0x24D9, 'M', 'j'), + (0x24DA, 'M', 'k'), + (0x24DB, 'M', 'l'), + (0x24DC, 'M', 'm'), + (0x24DD, 'M', 'n'), + (0x24DE, 'M', 'o'), + (0x24DF, 'M', 'p'), + (0x24E0, 'M', 'q'), + (0x24E1, 'M', 'r'), + (0x24E2, 'M', 's'), + (0x24E3, 'M', 't'), + (0x24E4, 'M', 'u'), + (0x24E5, 'M', 'v'), + (0x24E6, 'M', 'w'), + (0x24E7, 'M', 'x'), + (0x24E8, 'M', 'y'), + (0x24E9, 'M', 'z'), + (0x24EA, 'M', '0'), (0x24EB, 'V'), - (0x2A0C, 'M', u'∫∫∫∫'), + (0x2A0C, 'M', '∫∫∫∫'), (0x2A0D, 'V'), - (0x2A74, '3', u'::='), - (0x2A75, '3', u'=='), - (0x2A76, '3', u'==='), + (0x2A74, '3', '::='), + (0x2A75, '3', '=='), + (0x2A76, '3', '==='), (0x2A77, 'V'), - (0x2ADC, 'M', u'⫝̸'), + (0x2ADC, 'M', '⫝̸'), (0x2ADD, 'V'), (0x2B74, 'X'), (0x2B76, 'V'), (0x2B96, 'X'), (0x2B97, 'V'), - (0x2C00, 'M', u'ⰰ'), - (0x2C01, 'M', u'ⰱ'), - (0x2C02, 'M', u'ⰲ'), - (0x2C03, 'M', u'ⰳ'), - (0x2C04, 'M', u'ⰴ'), - (0x2C05, 'M', u'ⰵ'), - (0x2C06, 'M', u'ⰶ'), - (0x2C07, 'M', u'ⰷ'), - (0x2C08, 'M', u'ⰸ'), - (0x2C09, 'M', u'ⰹ'), - (0x2C0A, 'M', u'ⰺ'), - (0x2C0B, 'M', u'ⰻ'), - (0x2C0C, 'M', u'ⰼ'), - (0x2C0D, 'M', u'ⰽ'), - (0x2C0E, 'M', u'ⰾ'), - (0x2C0F, 'M', u'ⰿ'), - (0x2C10, 'M', u'ⱀ'), - (0x2C11, 'M', u'ⱁ'), - (0x2C12, 'M', u'ⱂ'), - (0x2C13, 'M', u'ⱃ'), - (0x2C14, 'M', u'ⱄ'), - (0x2C15, 'M', u'ⱅ'), - (0x2C16, 'M', u'ⱆ'), - (0x2C17, 'M', u'ⱇ'), - (0x2C18, 'M', u'ⱈ'), - (0x2C19, 'M', u'ⱉ'), - (0x2C1A, 'M', u'ⱊ'), - (0x2C1B, 'M', u'ⱋ'), - (0x2C1C, 'M', u'ⱌ'), - (0x2C1D, 'M', u'ⱍ'), - (0x2C1E, 'M', u'ⱎ'), - (0x2C1F, 'M', u'ⱏ'), - (0x2C20, 'M', u'ⱐ'), - (0x2C21, 'M', u'ⱑ'), - (0x2C22, 'M', u'ⱒ'), - (0x2C23, 'M', u'ⱓ'), - (0x2C24, 'M', u'ⱔ'), - (0x2C25, 'M', u'ⱕ'), + (0x2C00, 'M', 'ⰰ'), + (0x2C01, 'M', 'ⰱ'), + (0x2C02, 'M', 'ⰲ'), + (0x2C03, 'M', 'ⰳ'), + (0x2C04, 'M', 'ⰴ'), + (0x2C05, 'M', 'ⰵ'), + (0x2C06, 'M', 'ⰶ'), + (0x2C07, 'M', 'ⰷ'), + (0x2C08, 'M', 'ⰸ'), + (0x2C09, 'M', 'ⰹ'), + (0x2C0A, 'M', 'ⰺ'), + (0x2C0B, 'M', 'ⰻ'), + (0x2C0C, 'M', 'ⰼ'), + (0x2C0D, 'M', 'ⰽ'), + (0x2C0E, 'M', 'ⰾ'), + (0x2C0F, 'M', 'ⰿ'), + (0x2C10, 'M', 'ⱀ'), + (0x2C11, 'M', 'ⱁ'), + (0x2C12, 'M', 'ⱂ'), + (0x2C13, 'M', 'ⱃ'), + (0x2C14, 'M', 'ⱄ'), + (0x2C15, 'M', 'ⱅ'), + (0x2C16, 'M', 'ⱆ'), + (0x2C17, 'M', 'ⱇ'), + (0x2C18, 'M', 'ⱈ'), + (0x2C19, 'M', 'ⱉ'), + (0x2C1A, 'M', 'ⱊ'), + (0x2C1B, 'M', 'ⱋ'), + (0x2C1C, 'M', 'ⱌ'), + (0x2C1D, 'M', 'ⱍ'), + (0x2C1E, 'M', 'ⱎ'), + (0x2C1F, 'M', 'ⱏ'), + (0x2C20, 'M', 'ⱐ'), + (0x2C21, 'M', 'ⱑ'), + (0x2C22, 'M', 'ⱒ'), + (0x2C23, 'M', 'ⱓ'), + (0x2C24, 'M', 'ⱔ'), + (0x2C25, 'M', 'ⱕ'), ] def _seg_25(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2C26, 'M', u'ⱖ'), - (0x2C27, 'M', u'ⱗ'), - (0x2C28, 'M', u'ⱘ'), - (0x2C29, 'M', u'ⱙ'), - (0x2C2A, 'M', u'ⱚ'), - (0x2C2B, 'M', u'ⱛ'), - (0x2C2C, 'M', u'ⱜ'), - (0x2C2D, 'M', u'ⱝ'), - (0x2C2E, 'M', u'ⱞ'), + (0x2C26, 'M', 'ⱖ'), + (0x2C27, 'M', 'ⱗ'), + (0x2C28, 'M', 'ⱘ'), + (0x2C29, 'M', 'ⱙ'), + (0x2C2A, 'M', 'ⱚ'), + (0x2C2B, 'M', 'ⱛ'), + (0x2C2C, 'M', 'ⱜ'), + (0x2C2D, 'M', 'ⱝ'), + (0x2C2E, 'M', 'ⱞ'), (0x2C2F, 'X'), (0x2C30, 'V'), (0x2C5F, 'X'), - (0x2C60, 'M', u'ⱡ'), + (0x2C60, 'M', 'ⱡ'), (0x2C61, 'V'), - (0x2C62, 'M', u'ɫ'), - (0x2C63, 'M', u'ᵽ'), - (0x2C64, 'M', u'ɽ'), + (0x2C62, 'M', 'ɫ'), + (0x2C63, 'M', 'ᵽ'), + (0x2C64, 'M', 'ɽ'), (0x2C65, 'V'), - (0x2C67, 'M', u'ⱨ'), + (0x2C67, 'M', 'ⱨ'), (0x2C68, 'V'), - (0x2C69, 'M', u'ⱪ'), + (0x2C69, 'M', 'ⱪ'), (0x2C6A, 'V'), - (0x2C6B, 'M', u'ⱬ'), + (0x2C6B, 'M', 'ⱬ'), (0x2C6C, 'V'), - (0x2C6D, 'M', u'ɑ'), - (0x2C6E, 'M', u'ɱ'), - (0x2C6F, 'M', u'ɐ'), - (0x2C70, 'M', u'ɒ'), + (0x2C6D, 'M', 'ɑ'), + (0x2C6E, 'M', 'ɱ'), + (0x2C6F, 'M', 'ɐ'), + (0x2C70, 'M', 'ɒ'), (0x2C71, 'V'), - (0x2C72, 'M', u'ⱳ'), + (0x2C72, 'M', 'ⱳ'), (0x2C73, 'V'), - (0x2C75, 'M', u'ⱶ'), + (0x2C75, 'M', 'ⱶ'), (0x2C76, 'V'), - (0x2C7C, 'M', u'j'), - (0x2C7D, 'M', u'v'), - (0x2C7E, 'M', u'ȿ'), - (0x2C7F, 'M', u'ɀ'), - (0x2C80, 'M', u'ⲁ'), + (0x2C7C, 'M', 'j'), + (0x2C7D, 'M', 'v'), + (0x2C7E, 'M', 'ȿ'), + (0x2C7F, 'M', 'ɀ'), + (0x2C80, 'M', 'ⲁ'), (0x2C81, 'V'), - (0x2C82, 'M', u'ⲃ'), + (0x2C82, 'M', 'ⲃ'), (0x2C83, 'V'), - (0x2C84, 'M', u'ⲅ'), + (0x2C84, 'M', 'ⲅ'), (0x2C85, 'V'), - (0x2C86, 'M', u'ⲇ'), + (0x2C86, 'M', 'ⲇ'), (0x2C87, 'V'), - (0x2C88, 'M', u'ⲉ'), + (0x2C88, 'M', 'ⲉ'), (0x2C89, 'V'), - (0x2C8A, 'M', u'ⲋ'), + (0x2C8A, 'M', 'ⲋ'), (0x2C8B, 'V'), - (0x2C8C, 'M', u'ⲍ'), + (0x2C8C, 'M', 'ⲍ'), (0x2C8D, 'V'), - (0x2C8E, 'M', u'ⲏ'), + (0x2C8E, 'M', 'ⲏ'), (0x2C8F, 'V'), - (0x2C90, 'M', u'ⲑ'), + (0x2C90, 'M', 'ⲑ'), (0x2C91, 'V'), - (0x2C92, 'M', u'ⲓ'), + (0x2C92, 'M', 'ⲓ'), (0x2C93, 'V'), - (0x2C94, 'M', u'ⲕ'), + (0x2C94, 'M', 'ⲕ'), (0x2C95, 'V'), - (0x2C96, 'M', u'ⲗ'), + (0x2C96, 'M', 'ⲗ'), (0x2C97, 'V'), - (0x2C98, 'M', u'ⲙ'), + (0x2C98, 'M', 'ⲙ'), (0x2C99, 'V'), - (0x2C9A, 'M', u'ⲛ'), + (0x2C9A, 'M', 'ⲛ'), (0x2C9B, 'V'), - (0x2C9C, 'M', u'ⲝ'), + (0x2C9C, 'M', 'ⲝ'), (0x2C9D, 'V'), - (0x2C9E, 'M', u'ⲟ'), + (0x2C9E, 'M', 'ⲟ'), (0x2C9F, 'V'), - (0x2CA0, 'M', u'ⲡ'), + (0x2CA0, 'M', 'ⲡ'), (0x2CA1, 'V'), - (0x2CA2, 'M', u'ⲣ'), + (0x2CA2, 'M', 'ⲣ'), (0x2CA3, 'V'), - (0x2CA4, 'M', u'ⲥ'), + (0x2CA4, 'M', 'ⲥ'), (0x2CA5, 'V'), - (0x2CA6, 'M', u'ⲧ'), + (0x2CA6, 'M', 'ⲧ'), (0x2CA7, 'V'), - (0x2CA8, 'M', u'ⲩ'), + (0x2CA8, 'M', 'ⲩ'), (0x2CA9, 'V'), - (0x2CAA, 'M', u'ⲫ'), + (0x2CAA, 'M', 'ⲫ'), (0x2CAB, 'V'), - (0x2CAC, 'M', u'ⲭ'), + (0x2CAC, 'M', 'ⲭ'), (0x2CAD, 'V'), - (0x2CAE, 'M', u'ⲯ'), + (0x2CAE, 'M', 'ⲯ'), (0x2CAF, 'V'), - (0x2CB0, 'M', u'ⲱ'), + (0x2CB0, 'M', 'ⲱ'), (0x2CB1, 'V'), - (0x2CB2, 'M', u'ⲳ'), + (0x2CB2, 'M', 'ⲳ'), (0x2CB3, 'V'), - (0x2CB4, 'M', u'ⲵ'), + (0x2CB4, 'M', 'ⲵ'), (0x2CB5, 'V'), - (0x2CB6, 'M', u'ⲷ'), + (0x2CB6, 'M', 'ⲷ'), (0x2CB7, 'V'), - (0x2CB8, 'M', u'ⲹ'), + (0x2CB8, 'M', 'ⲹ'), (0x2CB9, 'V'), - (0x2CBA, 'M', u'ⲻ'), + (0x2CBA, 'M', 'ⲻ'), (0x2CBB, 'V'), - (0x2CBC, 'M', u'ⲽ'), + (0x2CBC, 'M', 'ⲽ'), (0x2CBD, 'V'), - (0x2CBE, 'M', u'ⲿ'), + (0x2CBE, 'M', 'ⲿ'), ] def _seg_26(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x2CBF, 'V'), - (0x2CC0, 'M', u'ⳁ'), + (0x2CC0, 'M', 'ⳁ'), (0x2CC1, 'V'), - (0x2CC2, 'M', u'ⳃ'), + (0x2CC2, 'M', 'ⳃ'), (0x2CC3, 'V'), - (0x2CC4, 'M', u'ⳅ'), + (0x2CC4, 'M', 'ⳅ'), (0x2CC5, 'V'), - (0x2CC6, 'M', u'ⳇ'), + (0x2CC6, 'M', 'ⳇ'), (0x2CC7, 'V'), - (0x2CC8, 'M', u'ⳉ'), + (0x2CC8, 'M', 'ⳉ'), (0x2CC9, 'V'), - (0x2CCA, 'M', u'ⳋ'), + (0x2CCA, 'M', 'ⳋ'), (0x2CCB, 'V'), - (0x2CCC, 'M', u'ⳍ'), + (0x2CCC, 'M', 'ⳍ'), (0x2CCD, 'V'), - (0x2CCE, 'M', u'ⳏ'), + (0x2CCE, 'M', 'ⳏ'), (0x2CCF, 'V'), - (0x2CD0, 'M', u'ⳑ'), + (0x2CD0, 'M', 'ⳑ'), (0x2CD1, 'V'), - (0x2CD2, 'M', u'ⳓ'), + (0x2CD2, 'M', 'ⳓ'), (0x2CD3, 'V'), - (0x2CD4, 'M', u'ⳕ'), + (0x2CD4, 'M', 'ⳕ'), (0x2CD5, 'V'), - (0x2CD6, 'M', u'ⳗ'), + (0x2CD6, 'M', 'ⳗ'), (0x2CD7, 'V'), - (0x2CD8, 'M', u'ⳙ'), + (0x2CD8, 'M', 'ⳙ'), (0x2CD9, 'V'), - (0x2CDA, 'M', u'ⳛ'), + (0x2CDA, 'M', 'ⳛ'), (0x2CDB, 'V'), - (0x2CDC, 'M', u'ⳝ'), + (0x2CDC, 'M', 'ⳝ'), (0x2CDD, 'V'), - (0x2CDE, 'M', u'ⳟ'), + (0x2CDE, 'M', 'ⳟ'), (0x2CDF, 'V'), - (0x2CE0, 'M', u'ⳡ'), + (0x2CE0, 'M', 'ⳡ'), (0x2CE1, 'V'), - (0x2CE2, 'M', u'ⳣ'), + (0x2CE2, 'M', 'ⳣ'), (0x2CE3, 'V'), - (0x2CEB, 'M', u'ⳬ'), + (0x2CEB, 'M', 'ⳬ'), (0x2CEC, 'V'), - (0x2CED, 'M', u'ⳮ'), + (0x2CED, 'M', 'ⳮ'), (0x2CEE, 'V'), - (0x2CF2, 'M', u'ⳳ'), + (0x2CF2, 'M', 'ⳳ'), (0x2CF3, 'V'), (0x2CF4, 'X'), (0x2CF9, 'V'), @@ -2763,7 +2791,7 @@ def _seg_26(): (0x2D2E, 'X'), (0x2D30, 'V'), (0x2D68, 'X'), - (0x2D6F, 'M', u'ⵡ'), + (0x2D6F, 'M', 'ⵡ'), (0x2D70, 'V'), (0x2D71, 'X'), (0x2D7F, 'V'), @@ -2789,902 +2817,911 @@ def _seg_26(): (0x2E80, 'V'), (0x2E9A, 'X'), (0x2E9B, 'V'), - (0x2E9F, 'M', u'母'), + (0x2E9F, 'M', '母'), (0x2EA0, 'V'), - (0x2EF3, 'M', u'龟'), + (0x2EF3, 'M', '龟'), (0x2EF4, 'X'), - (0x2F00, 'M', u'一'), - (0x2F01, 'M', u'丨'), - (0x2F02, 'M', u'丶'), - (0x2F03, 'M', u'丿'), - (0x2F04, 'M', u'乙'), - (0x2F05, 'M', u'亅'), - (0x2F06, 'M', u'二'), - (0x2F07, 'M', u'亠'), - (0x2F08, 'M', u'人'), - (0x2F09, 'M', u'儿'), - (0x2F0A, 'M', u'入'), - (0x2F0B, 'M', u'八'), - (0x2F0C, 'M', u'冂'), - (0x2F0D, 'M', u'冖'), - (0x2F0E, 'M', u'冫'), - (0x2F0F, 'M', u'几'), - (0x2F10, 'M', u'凵'), - (0x2F11, 'M', u'刀'), + (0x2F00, 'M', '一'), + (0x2F01, 'M', '丨'), + (0x2F02, 'M', '丶'), + (0x2F03, 'M', '丿'), + (0x2F04, 'M', '乙'), + (0x2F05, 'M', '亅'), + (0x2F06, 'M', '二'), + (0x2F07, 'M', '亠'), + (0x2F08, 'M', '人'), + (0x2F09, 'M', '儿'), + (0x2F0A, 'M', '入'), + (0x2F0B, 'M', '八'), + (0x2F0C, 'M', '冂'), + (0x2F0D, 'M', '冖'), + (0x2F0E, 'M', '冫'), + (0x2F0F, 'M', '几'), + (0x2F10, 'M', '凵'), + (0x2F11, 'M', '刀'), ] def _seg_27(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F12, 'M', u'力'), - (0x2F13, 'M', u'勹'), - (0x2F14, 'M', u'匕'), - (0x2F15, 'M', u'匚'), - (0x2F16, 'M', u'匸'), - (0x2F17, 'M', u'十'), - (0x2F18, 'M', u'卜'), - (0x2F19, 'M', u'卩'), - (0x2F1A, 'M', u'厂'), - (0x2F1B, 'M', u'厶'), - (0x2F1C, 'M', u'又'), - (0x2F1D, 'M', u'口'), - (0x2F1E, 'M', u'囗'), - (0x2F1F, 'M', u'土'), - (0x2F20, 'M', u'士'), - (0x2F21, 'M', u'夂'), - (0x2F22, 'M', u'夊'), - (0x2F23, 'M', u'夕'), - (0x2F24, 'M', u'大'), - (0x2F25, 'M', u'女'), - (0x2F26, 'M', u'子'), - (0x2F27, 'M', u'宀'), - (0x2F28, 'M', u'寸'), - (0x2F29, 'M', u'小'), - (0x2F2A, 'M', u'尢'), - (0x2F2B, 'M', u'尸'), - (0x2F2C, 'M', u'屮'), - (0x2F2D, 'M', u'山'), - (0x2F2E, 'M', u'巛'), - (0x2F2F, 'M', u'工'), - (0x2F30, 'M', u'己'), - (0x2F31, 'M', u'巾'), - (0x2F32, 'M', u'干'), - (0x2F33, 'M', u'幺'), - (0x2F34, 'M', u'广'), - (0x2F35, 'M', u'廴'), - (0x2F36, 'M', u'廾'), - (0x2F37, 'M', u'弋'), - (0x2F38, 'M', u'弓'), - (0x2F39, 'M', u'彐'), - (0x2F3A, 'M', u'彡'), - (0x2F3B, 'M', u'彳'), - (0x2F3C, 'M', u'心'), - (0x2F3D, 'M', u'戈'), - (0x2F3E, 'M', u'戶'), - (0x2F3F, 'M', u'手'), - (0x2F40, 'M', u'支'), - (0x2F41, 'M', u'攴'), - (0x2F42, 'M', u'文'), - (0x2F43, 'M', u'斗'), - (0x2F44, 'M', u'斤'), - (0x2F45, 'M', u'方'), - (0x2F46, 'M', u'无'), - (0x2F47, 'M', u'日'), - (0x2F48, 'M', u'曰'), - (0x2F49, 'M', u'月'), - (0x2F4A, 'M', u'木'), - (0x2F4B, 'M', u'欠'), - (0x2F4C, 'M', u'止'), - (0x2F4D, 'M', u'歹'), - (0x2F4E, 'M', u'殳'), - (0x2F4F, 'M', u'毋'), - (0x2F50, 'M', u'比'), - (0x2F51, 'M', u'毛'), - (0x2F52, 'M', u'氏'), - (0x2F53, 'M', u'气'), - (0x2F54, 'M', u'水'), - (0x2F55, 'M', u'火'), - (0x2F56, 'M', u'爪'), - (0x2F57, 'M', u'父'), - (0x2F58, 'M', u'爻'), - (0x2F59, 'M', u'爿'), - (0x2F5A, 'M', u'片'), - (0x2F5B, 'M', u'牙'), - (0x2F5C, 'M', u'牛'), - (0x2F5D, 'M', u'犬'), - (0x2F5E, 'M', u'玄'), - (0x2F5F, 'M', u'玉'), - (0x2F60, 'M', u'瓜'), - (0x2F61, 'M', u'瓦'), - (0x2F62, 'M', u'甘'), - (0x2F63, 'M', u'生'), - (0x2F64, 'M', u'用'), - (0x2F65, 'M', u'田'), - (0x2F66, 'M', u'疋'), - (0x2F67, 'M', u'疒'), - (0x2F68, 'M', u'癶'), - (0x2F69, 'M', u'白'), - (0x2F6A, 'M', u'皮'), - (0x2F6B, 'M', u'皿'), - (0x2F6C, 'M', u'目'), - (0x2F6D, 'M', u'矛'), - (0x2F6E, 'M', u'矢'), - (0x2F6F, 'M', u'石'), - (0x2F70, 'M', u'示'), - (0x2F71, 'M', u'禸'), - (0x2F72, 'M', u'禾'), - (0x2F73, 'M', u'穴'), - (0x2F74, 'M', u'立'), - (0x2F75, 'M', u'竹'), + (0x2F12, 'M', '力'), + (0x2F13, 'M', '勹'), + (0x2F14, 'M', '匕'), + (0x2F15, 'M', '匚'), + (0x2F16, 'M', '匸'), + (0x2F17, 'M', '十'), + (0x2F18, 'M', '卜'), + (0x2F19, 'M', '卩'), + (0x2F1A, 'M', '厂'), + (0x2F1B, 'M', '厶'), + (0x2F1C, 'M', '又'), + (0x2F1D, 'M', '口'), + (0x2F1E, 'M', '囗'), + (0x2F1F, 'M', '土'), + (0x2F20, 'M', '士'), + (0x2F21, 'M', '夂'), + (0x2F22, 'M', '夊'), + (0x2F23, 'M', '夕'), + (0x2F24, 'M', '大'), + (0x2F25, 'M', '女'), + (0x2F26, 'M', '子'), + (0x2F27, 'M', '宀'), + (0x2F28, 'M', '寸'), + (0x2F29, 'M', '小'), + (0x2F2A, 'M', '尢'), + (0x2F2B, 'M', '尸'), + (0x2F2C, 'M', '屮'), + (0x2F2D, 'M', '山'), + (0x2F2E, 'M', '巛'), + (0x2F2F, 'M', '工'), + (0x2F30, 'M', '己'), + (0x2F31, 'M', '巾'), + (0x2F32, 'M', '干'), + (0x2F33, 'M', '幺'), + (0x2F34, 'M', '广'), + (0x2F35, 'M', '廴'), + (0x2F36, 'M', '廾'), + (0x2F37, 'M', '弋'), + (0x2F38, 'M', '弓'), + (0x2F39, 'M', '彐'), + (0x2F3A, 'M', '彡'), + (0x2F3B, 'M', '彳'), + (0x2F3C, 'M', '心'), + (0x2F3D, 'M', '戈'), + (0x2F3E, 'M', '戶'), + (0x2F3F, 'M', '手'), + (0x2F40, 'M', '支'), + (0x2F41, 'M', '攴'), + (0x2F42, 'M', '文'), + (0x2F43, 'M', '斗'), + (0x2F44, 'M', '斤'), + (0x2F45, 'M', '方'), + (0x2F46, 'M', '无'), + (0x2F47, 'M', '日'), + (0x2F48, 'M', '曰'), + (0x2F49, 'M', '月'), + (0x2F4A, 'M', '木'), + (0x2F4B, 'M', '欠'), + (0x2F4C, 'M', '止'), + (0x2F4D, 'M', '歹'), + (0x2F4E, 'M', '殳'), + (0x2F4F, 'M', '毋'), + (0x2F50, 'M', '比'), + (0x2F51, 'M', '毛'), + (0x2F52, 'M', '氏'), + (0x2F53, 'M', '气'), + (0x2F54, 'M', '水'), + (0x2F55, 'M', '火'), + (0x2F56, 'M', '爪'), + (0x2F57, 'M', '父'), + (0x2F58, 'M', '爻'), + (0x2F59, 'M', '爿'), + (0x2F5A, 'M', '片'), + (0x2F5B, 'M', '牙'), + (0x2F5C, 'M', '牛'), + (0x2F5D, 'M', '犬'), + (0x2F5E, 'M', '玄'), + (0x2F5F, 'M', '玉'), + (0x2F60, 'M', '瓜'), + (0x2F61, 'M', '瓦'), + (0x2F62, 'M', '甘'), + (0x2F63, 'M', '生'), + (0x2F64, 'M', '用'), + (0x2F65, 'M', '田'), + (0x2F66, 'M', '疋'), + (0x2F67, 'M', '疒'), + (0x2F68, 'M', '癶'), + (0x2F69, 'M', '白'), + (0x2F6A, 'M', '皮'), + (0x2F6B, 'M', '皿'), + (0x2F6C, 'M', '目'), + (0x2F6D, 'M', '矛'), + (0x2F6E, 'M', '矢'), + (0x2F6F, 'M', '石'), + (0x2F70, 'M', '示'), + (0x2F71, 'M', '禸'), + (0x2F72, 'M', '禾'), + (0x2F73, 'M', '穴'), + (0x2F74, 'M', '立'), + (0x2F75, 'M', '竹'), ] def _seg_28(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F76, 'M', u'米'), - (0x2F77, 'M', u'糸'), - (0x2F78, 'M', u'缶'), - (0x2F79, 'M', u'网'), - (0x2F7A, 'M', u'羊'), - (0x2F7B, 'M', u'羽'), - (0x2F7C, 'M', u'老'), - (0x2F7D, 'M', u'而'), - (0x2F7E, 'M', u'耒'), - (0x2F7F, 'M', u'耳'), - (0x2F80, 'M', u'聿'), - (0x2F81, 'M', u'肉'), - (0x2F82, 'M', u'臣'), - (0x2F83, 'M', u'自'), - (0x2F84, 'M', u'至'), - (0x2F85, 'M', u'臼'), - (0x2F86, 'M', u'舌'), - (0x2F87, 'M', u'舛'), - (0x2F88, 'M', u'舟'), - (0x2F89, 'M', u'艮'), - (0x2F8A, 'M', u'色'), - (0x2F8B, 'M', u'艸'), - (0x2F8C, 'M', u'虍'), - (0x2F8D, 'M', u'虫'), - (0x2F8E, 'M', u'血'), - (0x2F8F, 'M', u'行'), - (0x2F90, 'M', u'衣'), - (0x2F91, 'M', u'襾'), - (0x2F92, 'M', u'見'), - (0x2F93, 'M', u'角'), - (0x2F94, 'M', u'言'), - (0x2F95, 'M', u'谷'), - (0x2F96, 'M', u'豆'), - (0x2F97, 'M', u'豕'), - (0x2F98, 'M', u'豸'), - (0x2F99, 'M', u'貝'), - (0x2F9A, 'M', u'赤'), - (0x2F9B, 'M', u'走'), - (0x2F9C, 'M', u'足'), - (0x2F9D, 'M', u'身'), - (0x2F9E, 'M', u'車'), - (0x2F9F, 'M', u'辛'), - (0x2FA0, 'M', u'辰'), - (0x2FA1, 'M', u'辵'), - (0x2FA2, 'M', u'邑'), - (0x2FA3, 'M', u'酉'), - (0x2FA4, 'M', u'釆'), - (0x2FA5, 'M', u'里'), - (0x2FA6, 'M', u'金'), - (0x2FA7, 'M', u'長'), - (0x2FA8, 'M', u'門'), - (0x2FA9, 'M', u'阜'), - (0x2FAA, 'M', u'隶'), - (0x2FAB, 'M', u'隹'), - (0x2FAC, 'M', u'雨'), - (0x2FAD, 'M', u'靑'), - (0x2FAE, 'M', u'非'), - (0x2FAF, 'M', u'面'), - (0x2FB0, 'M', u'革'), - (0x2FB1, 'M', u'韋'), - (0x2FB2, 'M', u'韭'), - (0x2FB3, 'M', u'音'), - (0x2FB4, 'M', u'頁'), - (0x2FB5, 'M', u'風'), - (0x2FB6, 'M', u'飛'), - (0x2FB7, 'M', u'食'), - (0x2FB8, 'M', u'首'), - (0x2FB9, 'M', u'香'), - (0x2FBA, 'M', u'馬'), - (0x2FBB, 'M', u'骨'), - (0x2FBC, 'M', u'高'), - (0x2FBD, 'M', u'髟'), - (0x2FBE, 'M', u'鬥'), - (0x2FBF, 'M', u'鬯'), - (0x2FC0, 'M', u'鬲'), - (0x2FC1, 'M', u'鬼'), - (0x2FC2, 'M', u'魚'), - (0x2FC3, 'M', u'鳥'), - (0x2FC4, 'M', u'鹵'), - (0x2FC5, 'M', u'鹿'), - (0x2FC6, 'M', u'麥'), - (0x2FC7, 'M', u'麻'), - (0x2FC8, 'M', u'黃'), - (0x2FC9, 'M', u'黍'), - (0x2FCA, 'M', u'黑'), - (0x2FCB, 'M', u'黹'), - (0x2FCC, 'M', u'黽'), - (0x2FCD, 'M', u'鼎'), - (0x2FCE, 'M', u'鼓'), - (0x2FCF, 'M', u'鼠'), - (0x2FD0, 'M', u'鼻'), - (0x2FD1, 'M', u'齊'), - (0x2FD2, 'M', u'齒'), - (0x2FD3, 'M', u'龍'), - (0x2FD4, 'M', u'龜'), - (0x2FD5, 'M', u'龠'), + (0x2F76, 'M', '米'), + (0x2F77, 'M', '糸'), + (0x2F78, 'M', '缶'), + (0x2F79, 'M', '网'), + (0x2F7A, 'M', '羊'), + (0x2F7B, 'M', '羽'), + (0x2F7C, 'M', '老'), + (0x2F7D, 'M', '而'), + (0x2F7E, 'M', '耒'), + (0x2F7F, 'M', '耳'), + (0x2F80, 'M', '聿'), + (0x2F81, 'M', '肉'), + (0x2F82, 'M', '臣'), + (0x2F83, 'M', '自'), + (0x2F84, 'M', '至'), + (0x2F85, 'M', '臼'), + (0x2F86, 'M', '舌'), + (0x2F87, 'M', '舛'), + (0x2F88, 'M', '舟'), + (0x2F89, 'M', '艮'), + (0x2F8A, 'M', '色'), + (0x2F8B, 'M', '艸'), + (0x2F8C, 'M', '虍'), + (0x2F8D, 'M', '虫'), + (0x2F8E, 'M', '血'), + (0x2F8F, 'M', '行'), + (0x2F90, 'M', '衣'), + (0x2F91, 'M', '襾'), + (0x2F92, 'M', '見'), + (0x2F93, 'M', '角'), + (0x2F94, 'M', '言'), + (0x2F95, 'M', '谷'), + (0x2F96, 'M', '豆'), + (0x2F97, 'M', '豕'), + (0x2F98, 'M', '豸'), + (0x2F99, 'M', '貝'), + (0x2F9A, 'M', '赤'), + (0x2F9B, 'M', '走'), + (0x2F9C, 'M', '足'), + (0x2F9D, 'M', '身'), + (0x2F9E, 'M', '車'), + (0x2F9F, 'M', '辛'), + (0x2FA0, 'M', '辰'), + (0x2FA1, 'M', '辵'), + (0x2FA2, 'M', '邑'), + (0x2FA3, 'M', '酉'), + (0x2FA4, 'M', '釆'), + (0x2FA5, 'M', '里'), + (0x2FA6, 'M', '金'), + (0x2FA7, 'M', '長'), + (0x2FA8, 'M', '門'), + (0x2FA9, 'M', '阜'), + (0x2FAA, 'M', '隶'), + (0x2FAB, 'M', '隹'), + (0x2FAC, 'M', '雨'), + (0x2FAD, 'M', '靑'), + (0x2FAE, 'M', '非'), + (0x2FAF, 'M', '面'), + (0x2FB0, 'M', '革'), + (0x2FB1, 'M', '韋'), + (0x2FB2, 'M', '韭'), + (0x2FB3, 'M', '音'), + (0x2FB4, 'M', '頁'), + (0x2FB5, 'M', '風'), + (0x2FB6, 'M', '飛'), + (0x2FB7, 'M', '食'), + (0x2FB8, 'M', '首'), + (0x2FB9, 'M', '香'), + (0x2FBA, 'M', '馬'), + (0x2FBB, 'M', '骨'), + (0x2FBC, 'M', '高'), + (0x2FBD, 'M', '髟'), + (0x2FBE, 'M', '鬥'), + (0x2FBF, 'M', '鬯'), + (0x2FC0, 'M', '鬲'), + (0x2FC1, 'M', '鬼'), + (0x2FC2, 'M', '魚'), + (0x2FC3, 'M', '鳥'), + (0x2FC4, 'M', '鹵'), + (0x2FC5, 'M', '鹿'), + (0x2FC6, 'M', '麥'), + (0x2FC7, 'M', '麻'), + (0x2FC8, 'M', '黃'), + (0x2FC9, 'M', '黍'), + (0x2FCA, 'M', '黑'), + (0x2FCB, 'M', '黹'), + (0x2FCC, 'M', '黽'), + (0x2FCD, 'M', '鼎'), + (0x2FCE, 'M', '鼓'), + (0x2FCF, 'M', '鼠'), + (0x2FD0, 'M', '鼻'), + (0x2FD1, 'M', '齊'), + (0x2FD2, 'M', '齒'), + (0x2FD3, 'M', '龍'), + (0x2FD4, 'M', '龜'), + (0x2FD5, 'M', '龠'), (0x2FD6, 'X'), - (0x3000, '3', u' '), + (0x3000, '3', ' '), (0x3001, 'V'), - (0x3002, 'M', u'.'), + (0x3002, 'M', '.'), ] def _seg_29(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x3003, 'V'), - (0x3036, 'M', u'〒'), + (0x3036, 'M', '〒'), (0x3037, 'V'), - (0x3038, 'M', u'十'), - (0x3039, 'M', u'卄'), - (0x303A, 'M', u'卅'), + (0x3038, 'M', '十'), + (0x3039, 'M', '卄'), + (0x303A, 'M', '卅'), (0x303B, 'V'), (0x3040, 'X'), (0x3041, 'V'), (0x3097, 'X'), (0x3099, 'V'), - (0x309B, '3', u' ゙'), - (0x309C, '3', u' ゚'), + (0x309B, '3', ' ゙'), + (0x309C, '3', ' ゚'), (0x309D, 'V'), - (0x309F, 'M', u'より'), + (0x309F, 'M', 'より'), (0x30A0, 'V'), - (0x30FF, 'M', u'コト'), + (0x30FF, 'M', 'コト'), (0x3100, 'X'), (0x3105, 'V'), (0x3130, 'X'), - (0x3131, 'M', u'ᄀ'), - (0x3132, 'M', u'ᄁ'), - (0x3133, 'M', u'ᆪ'), - (0x3134, 'M', u'ᄂ'), - (0x3135, 'M', u'ᆬ'), - (0x3136, 'M', u'ᆭ'), - (0x3137, 'M', u'ᄃ'), - (0x3138, 'M', u'ᄄ'), - (0x3139, 'M', u'ᄅ'), - (0x313A, 'M', u'ᆰ'), - (0x313B, 'M', u'ᆱ'), - (0x313C, 'M', u'ᆲ'), - (0x313D, 'M', u'ᆳ'), - (0x313E, 'M', u'ᆴ'), - (0x313F, 'M', u'ᆵ'), - (0x3140, 'M', u'ᄚ'), - (0x3141, 'M', u'ᄆ'), - (0x3142, 'M', u'ᄇ'), - (0x3143, 'M', u'ᄈ'), - (0x3144, 'M', u'ᄡ'), - (0x3145, 'M', u'ᄉ'), - (0x3146, 'M', u'ᄊ'), - (0x3147, 'M', u'ᄋ'), - (0x3148, 'M', u'ᄌ'), - (0x3149, 'M', u'ᄍ'), - (0x314A, 'M', u'ᄎ'), - (0x314B, 'M', u'ᄏ'), - (0x314C, 'M', u'ᄐ'), - (0x314D, 'M', u'ᄑ'), - (0x314E, 'M', u'ᄒ'), - (0x314F, 'M', u'ᅡ'), - (0x3150, 'M', u'ᅢ'), - (0x3151, 'M', u'ᅣ'), - (0x3152, 'M', u'ᅤ'), - (0x3153, 'M', u'ᅥ'), - (0x3154, 'M', u'ᅦ'), - (0x3155, 'M', u'ᅧ'), - (0x3156, 'M', u'ᅨ'), - (0x3157, 'M', u'ᅩ'), - (0x3158, 'M', u'ᅪ'), - (0x3159, 'M', u'ᅫ'), - (0x315A, 'M', u'ᅬ'), - (0x315B, 'M', u'ᅭ'), - (0x315C, 'M', u'ᅮ'), - (0x315D, 'M', u'ᅯ'), - (0x315E, 'M', u'ᅰ'), - (0x315F, 'M', u'ᅱ'), - (0x3160, 'M', u'ᅲ'), - (0x3161, 'M', u'ᅳ'), - (0x3162, 'M', u'ᅴ'), - (0x3163, 'M', u'ᅵ'), + (0x3131, 'M', 'ᄀ'), + (0x3132, 'M', 'ᄁ'), + (0x3133, 'M', 'ᆪ'), + (0x3134, 'M', 'ᄂ'), + (0x3135, 'M', 'ᆬ'), + (0x3136, 'M', 'ᆭ'), + (0x3137, 'M', 'ᄃ'), + (0x3138, 'M', 'ᄄ'), + (0x3139, 'M', 'ᄅ'), + (0x313A, 'M', 'ᆰ'), + (0x313B, 'M', 'ᆱ'), + (0x313C, 'M', 'ᆲ'), + (0x313D, 'M', 'ᆳ'), + (0x313E, 'M', 'ᆴ'), + (0x313F, 'M', 'ᆵ'), + (0x3140, 'M', 'ᄚ'), + (0x3141, 'M', 'ᄆ'), + (0x3142, 'M', 'ᄇ'), + (0x3143, 'M', 'ᄈ'), + (0x3144, 'M', 'ᄡ'), + (0x3145, 'M', 'ᄉ'), + (0x3146, 'M', 'ᄊ'), + (0x3147, 'M', 'ᄋ'), + (0x3148, 'M', 'ᄌ'), + (0x3149, 'M', 'ᄍ'), + (0x314A, 'M', 'ᄎ'), + (0x314B, 'M', 'ᄏ'), + (0x314C, 'M', 'ᄐ'), + (0x314D, 'M', 'ᄑ'), + (0x314E, 'M', 'ᄒ'), + (0x314F, 'M', 'ᅡ'), + (0x3150, 'M', 'ᅢ'), + (0x3151, 'M', 'ᅣ'), + (0x3152, 'M', 'ᅤ'), + (0x3153, 'M', 'ᅥ'), + (0x3154, 'M', 'ᅦ'), + (0x3155, 'M', 'ᅧ'), + (0x3156, 'M', 'ᅨ'), + (0x3157, 'M', 'ᅩ'), + (0x3158, 'M', 'ᅪ'), + (0x3159, 'M', 'ᅫ'), + (0x315A, 'M', 'ᅬ'), + (0x315B, 'M', 'ᅭ'), + (0x315C, 'M', 'ᅮ'), + (0x315D, 'M', 'ᅯ'), + (0x315E, 'M', 'ᅰ'), + (0x315F, 'M', 'ᅱ'), + (0x3160, 'M', 'ᅲ'), + (0x3161, 'M', 'ᅳ'), + (0x3162, 'M', 'ᅴ'), + (0x3163, 'M', 'ᅵ'), (0x3164, 'X'), - (0x3165, 'M', u'ᄔ'), - (0x3166, 'M', u'ᄕ'), - (0x3167, 'M', u'ᇇ'), - (0x3168, 'M', u'ᇈ'), - (0x3169, 'M', u'ᇌ'), - (0x316A, 'M', u'ᇎ'), - (0x316B, 'M', u'ᇓ'), - (0x316C, 'M', u'ᇗ'), - (0x316D, 'M', u'ᇙ'), - (0x316E, 'M', u'ᄜ'), - (0x316F, 'M', u'ᇝ'), - (0x3170, 'M', u'ᇟ'), - (0x3171, 'M', u'ᄝ'), - (0x3172, 'M', u'ᄞ'), - (0x3173, 'M', u'ᄠ'), - (0x3174, 'M', u'ᄢ'), - (0x3175, 'M', u'ᄣ'), - (0x3176, 'M', u'ᄧ'), - (0x3177, 'M', u'ᄩ'), - (0x3178, 'M', u'ᄫ'), - (0x3179, 'M', u'ᄬ'), - (0x317A, 'M', u'ᄭ'), - (0x317B, 'M', u'ᄮ'), - (0x317C, 'M', u'ᄯ'), - (0x317D, 'M', u'ᄲ'), - (0x317E, 'M', u'ᄶ'), - (0x317F, 'M', u'ᅀ'), - (0x3180, 'M', u'ᅇ'), + (0x3165, 'M', 'ᄔ'), + (0x3166, 'M', 'ᄕ'), + (0x3167, 'M', 'ᇇ'), + (0x3168, 'M', 'ᇈ'), + (0x3169, 'M', 'ᇌ'), + (0x316A, 'M', 'ᇎ'), + (0x316B, 'M', 'ᇓ'), + (0x316C, 'M', 'ᇗ'), + (0x316D, 'M', 'ᇙ'), + (0x316E, 'M', 'ᄜ'), + (0x316F, 'M', 'ᇝ'), + (0x3170, 'M', 'ᇟ'), + (0x3171, 'M', 'ᄝ'), + (0x3172, 'M', 'ᄞ'), + (0x3173, 'M', 'ᄠ'), + (0x3174, 'M', 'ᄢ'), + (0x3175, 'M', 'ᄣ'), + (0x3176, 'M', 'ᄧ'), + (0x3177, 'M', 'ᄩ'), + (0x3178, 'M', 'ᄫ'), + (0x3179, 'M', 'ᄬ'), + (0x317A, 'M', 'ᄭ'), + (0x317B, 'M', 'ᄮ'), + (0x317C, 'M', 'ᄯ'), + (0x317D, 'M', 'ᄲ'), + (0x317E, 'M', 'ᄶ'), + (0x317F, 'M', 'ᅀ'), + (0x3180, 'M', 'ᅇ'), ] def _seg_30(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x3181, 'M', u'ᅌ'), - (0x3182, 'M', u'ᇱ'), - (0x3183, 'M', u'ᇲ'), - (0x3184, 'M', u'ᅗ'), - (0x3185, 'M', u'ᅘ'), - (0x3186, 'M', u'ᅙ'), - (0x3187, 'M', u'ᆄ'), - (0x3188, 'M', u'ᆅ'), - (0x3189, 'M', u'ᆈ'), - (0x318A, 'M', u'ᆑ'), - (0x318B, 'M', u'ᆒ'), - (0x318C, 'M', u'ᆔ'), - (0x318D, 'M', u'ᆞ'), - (0x318E, 'M', u'ᆡ'), + (0x3181, 'M', 'ᅌ'), + (0x3182, 'M', 'ᇱ'), + (0x3183, 'M', 'ᇲ'), + (0x3184, 'M', 'ᅗ'), + (0x3185, 'M', 'ᅘ'), + (0x3186, 'M', 'ᅙ'), + (0x3187, 'M', 'ᆄ'), + (0x3188, 'M', 'ᆅ'), + (0x3189, 'M', 'ᆈ'), + (0x318A, 'M', 'ᆑ'), + (0x318B, 'M', 'ᆒ'), + (0x318C, 'M', 'ᆔ'), + (0x318D, 'M', 'ᆞ'), + (0x318E, 'M', 'ᆡ'), (0x318F, 'X'), (0x3190, 'V'), - (0x3192, 'M', u'一'), - (0x3193, 'M', u'二'), - (0x3194, 'M', u'三'), - (0x3195, 'M', u'四'), - (0x3196, 'M', u'上'), - (0x3197, 'M', u'中'), - (0x3198, 'M', u'下'), - (0x3199, 'M', u'甲'), - (0x319A, 'M', u'乙'), - (0x319B, 'M', u'丙'), - (0x319C, 'M', u'丁'), - (0x319D, 'M', u'天'), - (0x319E, 'M', u'地'), - (0x319F, 'M', u'人'), + (0x3192, 'M', '一'), + (0x3193, 'M', '二'), + (0x3194, 'M', '三'), + (0x3195, 'M', '四'), + (0x3196, 'M', '上'), + (0x3197, 'M', '中'), + (0x3198, 'M', '下'), + (0x3199, 'M', '甲'), + (0x319A, 'M', '乙'), + (0x319B, 'M', '丙'), + (0x319C, 'M', '丁'), + (0x319D, 'M', '天'), + (0x319E, 'M', '地'), + (0x319F, 'M', '人'), (0x31A0, 'V'), (0x31E4, 'X'), (0x31F0, 'V'), - (0x3200, '3', u'(ᄀ)'), - (0x3201, '3', u'(ᄂ)'), - (0x3202, '3', u'(ᄃ)'), - (0x3203, '3', u'(ᄅ)'), - (0x3204, '3', u'(ᄆ)'), - (0x3205, '3', u'(ᄇ)'), - (0x3206, '3', u'(ᄉ)'), - (0x3207, '3', u'(ᄋ)'), - (0x3208, '3', u'(ᄌ)'), - (0x3209, '3', u'(ᄎ)'), - (0x320A, '3', u'(ᄏ)'), - (0x320B, '3', u'(ᄐ)'), - (0x320C, '3', u'(ᄑ)'), - (0x320D, '3', u'(ᄒ)'), - (0x320E, '3', u'(가)'), - (0x320F, '3', u'(나)'), - (0x3210, '3', u'(다)'), - (0x3211, '3', u'(라)'), - (0x3212, '3', u'(마)'), - (0x3213, '3', u'(바)'), - (0x3214, '3', u'(사)'), - (0x3215, '3', u'(아)'), - (0x3216, '3', u'(자)'), - (0x3217, '3', u'(차)'), - (0x3218, '3', u'(카)'), - (0x3219, '3', u'(타)'), - (0x321A, '3', u'(파)'), - (0x321B, '3', u'(하)'), - (0x321C, '3', u'(주)'), - (0x321D, '3', u'(오전)'), - (0x321E, '3', u'(오후)'), + (0x3200, '3', '(ᄀ)'), + (0x3201, '3', '(ᄂ)'), + (0x3202, '3', '(ᄃ)'), + (0x3203, '3', '(ᄅ)'), + (0x3204, '3', '(ᄆ)'), + (0x3205, '3', '(ᄇ)'), + (0x3206, '3', '(ᄉ)'), + (0x3207, '3', '(ᄋ)'), + (0x3208, '3', '(ᄌ)'), + (0x3209, '3', '(ᄎ)'), + (0x320A, '3', '(ᄏ)'), + (0x320B, '3', '(ᄐ)'), + (0x320C, '3', '(ᄑ)'), + (0x320D, '3', '(ᄒ)'), + (0x320E, '3', '(가)'), + (0x320F, '3', '(나)'), + (0x3210, '3', '(다)'), + (0x3211, '3', '(라)'), + (0x3212, '3', '(마)'), + (0x3213, '3', '(바)'), + (0x3214, '3', '(사)'), + (0x3215, '3', '(아)'), + (0x3216, '3', '(자)'), + (0x3217, '3', '(차)'), + (0x3218, '3', '(카)'), + (0x3219, '3', '(타)'), + (0x321A, '3', '(파)'), + (0x321B, '3', '(하)'), + (0x321C, '3', '(주)'), + (0x321D, '3', '(오전)'), + (0x321E, '3', '(오후)'), (0x321F, 'X'), - (0x3220, '3', u'(一)'), - (0x3221, '3', u'(二)'), - (0x3222, '3', u'(三)'), - (0x3223, '3', u'(四)'), - (0x3224, '3', u'(五)'), - (0x3225, '3', u'(六)'), - (0x3226, '3', u'(七)'), - (0x3227, '3', u'(八)'), - (0x3228, '3', u'(九)'), - (0x3229, '3', u'(十)'), - (0x322A, '3', u'(月)'), - (0x322B, '3', u'(火)'), - (0x322C, '3', u'(水)'), - (0x322D, '3', u'(木)'), - (0x322E, '3', u'(金)'), - (0x322F, '3', u'(土)'), - (0x3230, '3', u'(日)'), - (0x3231, '3', u'(株)'), - (0x3232, '3', u'(有)'), - (0x3233, '3', u'(社)'), - (0x3234, '3', u'(名)'), - (0x3235, '3', u'(特)'), - (0x3236, '3', u'(財)'), - (0x3237, '3', u'(祝)'), - (0x3238, '3', u'(労)'), - (0x3239, '3', u'(代)'), - (0x323A, '3', u'(呼)'), - (0x323B, '3', u'(学)'), - (0x323C, '3', u'(監)'), - (0x323D, '3', u'(企)'), - (0x323E, '3', u'(資)'), - (0x323F, '3', u'(協)'), - (0x3240, '3', u'(祭)'), - (0x3241, '3', u'(休)'), - (0x3242, '3', u'(自)'), + (0x3220, '3', '(一)'), + (0x3221, '3', '(二)'), + (0x3222, '3', '(三)'), + (0x3223, '3', '(四)'), + (0x3224, '3', '(五)'), + (0x3225, '3', '(六)'), + (0x3226, '3', '(七)'), + (0x3227, '3', '(八)'), + (0x3228, '3', '(九)'), + (0x3229, '3', '(十)'), + (0x322A, '3', '(月)'), + (0x322B, '3', '(火)'), + (0x322C, '3', '(水)'), + (0x322D, '3', '(木)'), + (0x322E, '3', '(金)'), + (0x322F, '3', '(土)'), + (0x3230, '3', '(日)'), + (0x3231, '3', '(株)'), + (0x3232, '3', '(有)'), + (0x3233, '3', '(社)'), + (0x3234, '3', '(名)'), + (0x3235, '3', '(特)'), + (0x3236, '3', '(財)'), + (0x3237, '3', '(祝)'), + (0x3238, '3', '(労)'), + (0x3239, '3', '(代)'), + (0x323A, '3', '(呼)'), + (0x323B, '3', '(学)'), + (0x323C, '3', '(監)'), + (0x323D, '3', '(企)'), + (0x323E, '3', '(資)'), + (0x323F, '3', '(協)'), + (0x3240, '3', '(祭)'), + (0x3241, '3', '(休)'), + (0x3242, '3', '(自)'), ] def _seg_31(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x3243, '3', u'(至)'), - (0x3244, 'M', u'問'), - (0x3245, 'M', u'幼'), - (0x3246, 'M', u'文'), - (0x3247, 'M', u'箏'), + (0x3243, '3', '(至)'), + (0x3244, 'M', '問'), + (0x3245, 'M', '幼'), + (0x3246, 'M', '文'), + (0x3247, 'M', '箏'), (0x3248, 'V'), - (0x3250, 'M', u'pte'), - (0x3251, 'M', u'21'), - (0x3252, 'M', u'22'), - (0x3253, 'M', u'23'), - (0x3254, 'M', u'24'), - (0x3255, 'M', u'25'), - (0x3256, 'M', u'26'), - (0x3257, 'M', u'27'), - (0x3258, 'M', u'28'), - (0x3259, 'M', u'29'), - (0x325A, 'M', u'30'), - (0x325B, 'M', u'31'), - (0x325C, 'M', u'32'), - (0x325D, 'M', u'33'), - (0x325E, 'M', u'34'), - (0x325F, 'M', u'35'), - (0x3260, 'M', u'ᄀ'), - (0x3261, 'M', u'ᄂ'), - (0x3262, 'M', u'ᄃ'), - (0x3263, 'M', u'ᄅ'), - (0x3264, 'M', u'ᄆ'), - (0x3265, 'M', u'ᄇ'), - (0x3266, 'M', u'ᄉ'), - (0x3267, 'M', u'ᄋ'), - (0x3268, 'M', u'ᄌ'), - (0x3269, 'M', u'ᄎ'), - (0x326A, 'M', u'ᄏ'), - (0x326B, 'M', u'ᄐ'), - (0x326C, 'M', u'ᄑ'), - (0x326D, 'M', u'ᄒ'), - (0x326E, 'M', u'가'), - (0x326F, 'M', u'나'), - (0x3270, 'M', u'다'), - (0x3271, 'M', u'라'), - (0x3272, 'M', u'마'), - (0x3273, 'M', u'바'), - (0x3274, 'M', u'사'), - (0x3275, 'M', u'아'), - (0x3276, 'M', u'자'), - (0x3277, 'M', u'차'), - (0x3278, 'M', u'카'), - (0x3279, 'M', u'타'), - (0x327A, 'M', u'파'), - (0x327B, 'M', u'하'), - (0x327C, 'M', u'참고'), - (0x327D, 'M', u'주의'), - (0x327E, 'M', u'우'), + (0x3250, 'M', 'pte'), + (0x3251, 'M', '21'), + (0x3252, 'M', '22'), + (0x3253, 'M', '23'), + (0x3254, 'M', '24'), + (0x3255, 'M', '25'), + (0x3256, 'M', '26'), + (0x3257, 'M', '27'), + (0x3258, 'M', '28'), + (0x3259, 'M', '29'), + (0x325A, 'M', '30'), + (0x325B, 'M', '31'), + (0x325C, 'M', '32'), + (0x325D, 'M', '33'), + (0x325E, 'M', '34'), + (0x325F, 'M', '35'), + (0x3260, 'M', 'ᄀ'), + (0x3261, 'M', 'ᄂ'), + (0x3262, 'M', 'ᄃ'), + (0x3263, 'M', 'ᄅ'), + (0x3264, 'M', 'ᄆ'), + (0x3265, 'M', 'ᄇ'), + (0x3266, 'M', 'ᄉ'), + (0x3267, 'M', 'ᄋ'), + (0x3268, 'M', 'ᄌ'), + (0x3269, 'M', 'ᄎ'), + (0x326A, 'M', 'ᄏ'), + (0x326B, 'M', 'ᄐ'), + (0x326C, 'M', 'ᄑ'), + (0x326D, 'M', 'ᄒ'), + (0x326E, 'M', '가'), + (0x326F, 'M', '나'), + (0x3270, 'M', '다'), + (0x3271, 'M', '라'), + (0x3272, 'M', '마'), + (0x3273, 'M', '바'), + (0x3274, 'M', '사'), + (0x3275, 'M', '아'), + (0x3276, 'M', '자'), + (0x3277, 'M', '차'), + (0x3278, 'M', '카'), + (0x3279, 'M', '타'), + (0x327A, 'M', '파'), + (0x327B, 'M', '하'), + (0x327C, 'M', '참고'), + (0x327D, 'M', '주의'), + (0x327E, 'M', '우'), (0x327F, 'V'), - (0x3280, 'M', u'一'), - (0x3281, 'M', u'二'), - (0x3282, 'M', u'三'), - (0x3283, 'M', u'四'), - (0x3284, 'M', u'五'), - (0x3285, 'M', u'六'), - (0x3286, 'M', u'七'), - (0x3287, 'M', u'八'), - (0x3288, 'M', u'九'), - (0x3289, 'M', u'十'), - (0x328A, 'M', u'月'), - (0x328B, 'M', u'火'), - (0x328C, 'M', u'水'), - (0x328D, 'M', u'木'), - (0x328E, 'M', u'金'), - (0x328F, 'M', u'土'), - (0x3290, 'M', u'日'), - (0x3291, 'M', u'株'), - (0x3292, 'M', u'有'), - (0x3293, 'M', u'社'), - (0x3294, 'M', u'名'), - (0x3295, 'M', u'特'), - (0x3296, 'M', u'財'), - (0x3297, 'M', u'祝'), - (0x3298, 'M', u'労'), - (0x3299, 'M', u'秘'), - (0x329A, 'M', u'男'), - (0x329B, 'M', u'女'), - (0x329C, 'M', u'適'), - (0x329D, 'M', u'優'), - (0x329E, 'M', u'印'), - (0x329F, 'M', u'注'), - (0x32A0, 'M', u'項'), - (0x32A1, 'M', u'休'), - (0x32A2, 'M', u'写'), - (0x32A3, 'M', u'正'), - (0x32A4, 'M', u'上'), - (0x32A5, 'M', u'中'), - (0x32A6, 'M', u'下'), - (0x32A7, 'M', u'左'), - (0x32A8, 'M', u'右'), - (0x32A9, 'M', u'医'), - (0x32AA, 'M', u'宗'), - (0x32AB, 'M', u'学'), - (0x32AC, 'M', u'監'), - (0x32AD, 'M', u'企'), + (0x3280, 'M', '一'), + (0x3281, 'M', '二'), + (0x3282, 'M', '三'), + (0x3283, 'M', '四'), + (0x3284, 'M', '五'), + (0x3285, 'M', '六'), + (0x3286, 'M', '七'), + (0x3287, 'M', '八'), + (0x3288, 'M', '九'), + (0x3289, 'M', '十'), + (0x328A, 'M', '月'), + (0x328B, 'M', '火'), + (0x328C, 'M', '水'), + (0x328D, 'M', '木'), + (0x328E, 'M', '金'), + (0x328F, 'M', '土'), + (0x3290, 'M', '日'), + (0x3291, 'M', '株'), + (0x3292, 'M', '有'), + (0x3293, 'M', '社'), + (0x3294, 'M', '名'), + (0x3295, 'M', '特'), + (0x3296, 'M', '財'), + (0x3297, 'M', '祝'), + (0x3298, 'M', '労'), + (0x3299, 'M', '秘'), + (0x329A, 'M', '男'), + (0x329B, 'M', '女'), + (0x329C, 'M', '適'), + (0x329D, 'M', '優'), + (0x329E, 'M', '印'), + (0x329F, 'M', '注'), + (0x32A0, 'M', '項'), + (0x32A1, 'M', '休'), + (0x32A2, 'M', '写'), + (0x32A3, 'M', '正'), + (0x32A4, 'M', '上'), + (0x32A5, 'M', '中'), + (0x32A6, 'M', '下'), + (0x32A7, 'M', '左'), + (0x32A8, 'M', '右'), + (0x32A9, 'M', '医'), + (0x32AA, 'M', '宗'), + (0x32AB, 'M', '学'), + (0x32AC, 'M', '監'), + (0x32AD, 'M', '企'), ] def _seg_32(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x32AE, 'M', u'資'), - (0x32AF, 'M', u'協'), - (0x32B0, 'M', u'夜'), - (0x32B1, 'M', u'36'), - (0x32B2, 'M', u'37'), - (0x32B3, 'M', u'38'), - (0x32B4, 'M', u'39'), - (0x32B5, 'M', u'40'), - (0x32B6, 'M', u'41'), - (0x32B7, 'M', u'42'), - (0x32B8, 'M', u'43'), - (0x32B9, 'M', u'44'), - (0x32BA, 'M', u'45'), - (0x32BB, 'M', u'46'), - (0x32BC, 'M', u'47'), - (0x32BD, 'M', u'48'), - (0x32BE, 'M', u'49'), - (0x32BF, 'M', u'50'), - (0x32C0, 'M', u'1月'), - (0x32C1, 'M', u'2月'), - (0x32C2, 'M', u'3月'), - (0x32C3, 'M', u'4月'), - (0x32C4, 'M', u'5月'), - (0x32C5, 'M', u'6月'), - (0x32C6, 'M', u'7月'), - (0x32C7, 'M', u'8月'), - (0x32C8, 'M', u'9月'), - (0x32C9, 'M', u'10月'), - (0x32CA, 'M', u'11月'), - (0x32CB, 'M', u'12月'), - (0x32CC, 'M', u'hg'), - (0x32CD, 'M', u'erg'), - (0x32CE, 'M', u'ev'), - (0x32CF, 'M', u'ltd'), - (0x32D0, 'M', u'ア'), - (0x32D1, 'M', u'イ'), - (0x32D2, 'M', u'ウ'), - (0x32D3, 'M', u'エ'), - (0x32D4, 'M', u'オ'), - (0x32D5, 'M', u'カ'), - (0x32D6, 'M', u'キ'), - (0x32D7, 'M', u'ク'), - (0x32D8, 'M', u'ケ'), - (0x32D9, 'M', u'コ'), - (0x32DA, 'M', u'サ'), - (0x32DB, 'M', u'シ'), - (0x32DC, 'M', u'ス'), - (0x32DD, 'M', u'セ'), - (0x32DE, 'M', u'ソ'), - (0x32DF, 'M', u'タ'), - (0x32E0, 'M', u'チ'), - (0x32E1, 'M', u'ツ'), - (0x32E2, 'M', u'テ'), - (0x32E3, 'M', u'ト'), - (0x32E4, 'M', u'ナ'), - (0x32E5, 'M', u'ニ'), - (0x32E6, 'M', u'ヌ'), - (0x32E7, 'M', u'ネ'), - (0x32E8, 'M', u'ノ'), - (0x32E9, 'M', u'ハ'), - (0x32EA, 'M', u'ヒ'), - (0x32EB, 'M', u'フ'), - (0x32EC, 'M', u'ヘ'), - (0x32ED, 'M', u'ホ'), - (0x32EE, 'M', u'マ'), - (0x32EF, 'M', u'ミ'), - (0x32F0, 'M', u'ム'), - (0x32F1, 'M', u'メ'), - (0x32F2, 'M', u'モ'), - (0x32F3, 'M', u'ヤ'), - (0x32F4, 'M', u'ユ'), - (0x32F5, 'M', u'ヨ'), - (0x32F6, 'M', u'ラ'), - (0x32F7, 'M', u'リ'), - (0x32F8, 'M', u'ル'), - (0x32F9, 'M', u'レ'), - (0x32FA, 'M', u'ロ'), - (0x32FB, 'M', u'ワ'), - (0x32FC, 'M', u'ヰ'), - (0x32FD, 'M', u'ヱ'), - (0x32FE, 'M', u'ヲ'), - (0x32FF, 'M', u'令和'), - (0x3300, 'M', u'アパート'), - (0x3301, 'M', u'アルファ'), - (0x3302, 'M', u'アンペア'), - (0x3303, 'M', u'アール'), - (0x3304, 'M', u'イニング'), - (0x3305, 'M', u'インチ'), - (0x3306, 'M', u'ウォン'), - (0x3307, 'M', u'エスクード'), - (0x3308, 'M', u'エーカー'), - (0x3309, 'M', u'オンス'), - (0x330A, 'M', u'オーム'), - (0x330B, 'M', u'カイリ'), - (0x330C, 'M', u'カラット'), - (0x330D, 'M', u'カロリー'), - (0x330E, 'M', u'ガロン'), - (0x330F, 'M', u'ガンマ'), - (0x3310, 'M', u'ギガ'), - (0x3311, 'M', u'ギニー'), + (0x32AE, 'M', '資'), + (0x32AF, 'M', '協'), + (0x32B0, 'M', '夜'), + (0x32B1, 'M', '36'), + (0x32B2, 'M', '37'), + (0x32B3, 'M', '38'), + (0x32B4, 'M', '39'), + (0x32B5, 'M', '40'), + (0x32B6, 'M', '41'), + (0x32B7, 'M', '42'), + (0x32B8, 'M', '43'), + (0x32B9, 'M', '44'), + (0x32BA, 'M', '45'), + (0x32BB, 'M', '46'), + (0x32BC, 'M', '47'), + (0x32BD, 'M', '48'), + (0x32BE, 'M', '49'), + (0x32BF, 'M', '50'), + (0x32C0, 'M', '1月'), + (0x32C1, 'M', '2月'), + (0x32C2, 'M', '3月'), + (0x32C3, 'M', '4月'), + (0x32C4, 'M', '5月'), + (0x32C5, 'M', '6月'), + (0x32C6, 'M', '7月'), + (0x32C7, 'M', '8月'), + (0x32C8, 'M', '9月'), + (0x32C9, 'M', '10月'), + (0x32CA, 'M', '11月'), + (0x32CB, 'M', '12月'), + (0x32CC, 'M', 'hg'), + (0x32CD, 'M', 'erg'), + (0x32CE, 'M', 'ev'), + (0x32CF, 'M', 'ltd'), + (0x32D0, 'M', 'ア'), + (0x32D1, 'M', 'イ'), + (0x32D2, 'M', 'ウ'), + (0x32D3, 'M', 'エ'), + (0x32D4, 'M', 'オ'), + (0x32D5, 'M', 'カ'), + (0x32D6, 'M', 'キ'), + (0x32D7, 'M', 'ク'), + (0x32D8, 'M', 'ケ'), + (0x32D9, 'M', 'コ'), + (0x32DA, 'M', 'サ'), + (0x32DB, 'M', 'シ'), + (0x32DC, 'M', 'ス'), + (0x32DD, 'M', 'セ'), + (0x32DE, 'M', 'ソ'), + (0x32DF, 'M', 'タ'), + (0x32E0, 'M', 'チ'), + (0x32E1, 'M', 'ツ'), + (0x32E2, 'M', 'テ'), + (0x32E3, 'M', 'ト'), + (0x32E4, 'M', 'ナ'), + (0x32E5, 'M', 'ニ'), + (0x32E6, 'M', 'ヌ'), + (0x32E7, 'M', 'ネ'), + (0x32E8, 'M', 'ノ'), + (0x32E9, 'M', 'ハ'), + (0x32EA, 'M', 'ヒ'), + (0x32EB, 'M', 'フ'), + (0x32EC, 'M', 'ヘ'), + (0x32ED, 'M', 'ホ'), + (0x32EE, 'M', 'マ'), + (0x32EF, 'M', 'ミ'), + (0x32F0, 'M', 'ム'), + (0x32F1, 'M', 'メ'), + (0x32F2, 'M', 'モ'), + (0x32F3, 'M', 'ヤ'), + (0x32F4, 'M', 'ユ'), + (0x32F5, 'M', 'ヨ'), + (0x32F6, 'M', 'ラ'), + (0x32F7, 'M', 'リ'), + (0x32F8, 'M', 'ル'), + (0x32F9, 'M', 'レ'), + (0x32FA, 'M', 'ロ'), + (0x32FB, 'M', 'ワ'), + (0x32FC, 'M', 'ヰ'), + (0x32FD, 'M', 'ヱ'), + (0x32FE, 'M', 'ヲ'), + (0x32FF, 'M', '令和'), + (0x3300, 'M', 'アパート'), + (0x3301, 'M', 'アルファ'), + (0x3302, 'M', 'アンペア'), + (0x3303, 'M', 'アール'), + (0x3304, 'M', 'イニング'), + (0x3305, 'M', 'インチ'), + (0x3306, 'M', 'ウォン'), + (0x3307, 'M', 'エスクード'), + (0x3308, 'M', 'エーカー'), + (0x3309, 'M', 'オンス'), + (0x330A, 'M', 'オーム'), + (0x330B, 'M', 'カイリ'), + (0x330C, 'M', 'カラット'), + (0x330D, 'M', 'カロリー'), + (0x330E, 'M', 'ガロン'), + (0x330F, 'M', 'ガンマ'), + (0x3310, 'M', 'ギガ'), + (0x3311, 'M', 'ギニー'), ] def _seg_33(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x3312, 'M', u'キュリー'), - (0x3313, 'M', u'ギルダー'), - (0x3314, 'M', u'キロ'), - (0x3315, 'M', u'キログラム'), - (0x3316, 'M', u'キロメートル'), - (0x3317, 'M', u'キロワット'), - (0x3318, 'M', u'グラム'), - (0x3319, 'M', u'グラムトン'), - (0x331A, 'M', u'クルゼイロ'), - (0x331B, 'M', u'クローネ'), - (0x331C, 'M', u'ケース'), - (0x331D, 'M', u'コルナ'), - (0x331E, 'M', u'コーポ'), - (0x331F, 'M', u'サイクル'), - (0x3320, 'M', u'サンチーム'), - (0x3321, 'M', u'シリング'), - (0x3322, 'M', u'センチ'), - (0x3323, 'M', u'セント'), - (0x3324, 'M', u'ダース'), - (0x3325, 'M', u'デシ'), - (0x3326, 'M', u'ドル'), - (0x3327, 'M', u'トン'), - (0x3328, 'M', u'ナノ'), - (0x3329, 'M', u'ノット'), - (0x332A, 'M', u'ハイツ'), - (0x332B, 'M', u'パーセント'), - (0x332C, 'M', u'パーツ'), - (0x332D, 'M', u'バーレル'), - (0x332E, 'M', u'ピアストル'), - (0x332F, 'M', u'ピクル'), - (0x3330, 'M', u'ピコ'), - (0x3331, 'M', u'ビル'), - (0x3332, 'M', u'ファラッド'), - (0x3333, 'M', u'フィート'), - (0x3334, 'M', u'ブッシェル'), - (0x3335, 'M', u'フラン'), - (0x3336, 'M', u'ヘクタール'), - (0x3337, 'M', u'ペソ'), - (0x3338, 'M', u'ペニヒ'), - (0x3339, 'M', u'ヘルツ'), - (0x333A, 'M', u'ペンス'), - (0x333B, 'M', u'ページ'), - (0x333C, 'M', u'ベータ'), - (0x333D, 'M', u'ポイント'), - (0x333E, 'M', u'ボルト'), - (0x333F, 'M', u'ホン'), - (0x3340, 'M', u'ポンド'), - (0x3341, 'M', u'ホール'), - (0x3342, 'M', u'ホーン'), - (0x3343, 'M', u'マイクロ'), - (0x3344, 'M', u'マイル'), - (0x3345, 'M', u'マッハ'), - (0x3346, 'M', u'マルク'), - (0x3347, 'M', u'マンション'), - (0x3348, 'M', u'ミクロン'), - (0x3349, 'M', u'ミリ'), - (0x334A, 'M', u'ミリバール'), - (0x334B, 'M', u'メガ'), - (0x334C, 'M', u'メガトン'), - (0x334D, 'M', u'メートル'), - (0x334E, 'M', u'ヤード'), - (0x334F, 'M', u'ヤール'), - (0x3350, 'M', u'ユアン'), - (0x3351, 'M', u'リットル'), - (0x3352, 'M', u'リラ'), - (0x3353, 'M', u'ルピー'), - (0x3354, 'M', u'ルーブル'), - (0x3355, 'M', u'レム'), - (0x3356, 'M', u'レントゲン'), - (0x3357, 'M', u'ワット'), - (0x3358, 'M', u'0点'), - (0x3359, 'M', u'1点'), - (0x335A, 'M', u'2点'), - (0x335B, 'M', u'3点'), - (0x335C, 'M', u'4点'), - (0x335D, 'M', u'5点'), - (0x335E, 'M', u'6点'), - (0x335F, 'M', u'7点'), - (0x3360, 'M', u'8点'), - (0x3361, 'M', u'9点'), - (0x3362, 'M', u'10点'), - (0x3363, 'M', u'11点'), - (0x3364, 'M', u'12点'), - (0x3365, 'M', u'13点'), - (0x3366, 'M', u'14点'), - (0x3367, 'M', u'15点'), - (0x3368, 'M', u'16点'), - (0x3369, 'M', u'17点'), - (0x336A, 'M', u'18点'), - (0x336B, 'M', u'19点'), - (0x336C, 'M', u'20点'), - (0x336D, 'M', u'21点'), - (0x336E, 'M', u'22点'), - (0x336F, 'M', u'23点'), - (0x3370, 'M', u'24点'), - (0x3371, 'M', u'hpa'), - (0x3372, 'M', u'da'), - (0x3373, 'M', u'au'), - (0x3374, 'M', u'bar'), - (0x3375, 'M', u'ov'), + (0x3312, 'M', 'キュリー'), + (0x3313, 'M', 'ギルダー'), + (0x3314, 'M', 'キロ'), + (0x3315, 'M', 'キログラム'), + (0x3316, 'M', 'キロメートル'), + (0x3317, 'M', 'キロワット'), + (0x3318, 'M', 'グラム'), + (0x3319, 'M', 'グラムトン'), + (0x331A, 'M', 'クルゼイロ'), + (0x331B, 'M', 'クローネ'), + (0x331C, 'M', 'ケース'), + (0x331D, 'M', 'コルナ'), + (0x331E, 'M', 'コーポ'), + (0x331F, 'M', 'サイクル'), + (0x3320, 'M', 'サンチーム'), + (0x3321, 'M', 'シリング'), + (0x3322, 'M', 'センチ'), + (0x3323, 'M', 'セント'), + (0x3324, 'M', 'ダース'), + (0x3325, 'M', 'デシ'), + (0x3326, 'M', 'ドル'), + (0x3327, 'M', 'トン'), + (0x3328, 'M', 'ナノ'), + (0x3329, 'M', 'ノット'), + (0x332A, 'M', 'ハイツ'), + (0x332B, 'M', 'パーセント'), + (0x332C, 'M', 'パーツ'), + (0x332D, 'M', 'バーレル'), + (0x332E, 'M', 'ピアストル'), + (0x332F, 'M', 'ピクル'), + (0x3330, 'M', 'ピコ'), + (0x3331, 'M', 'ビル'), + (0x3332, 'M', 'ファラッド'), + (0x3333, 'M', 'フィート'), + (0x3334, 'M', 'ブッシェル'), + (0x3335, 'M', 'フラン'), + (0x3336, 'M', 'ヘクタール'), + (0x3337, 'M', 'ペソ'), + (0x3338, 'M', 'ペニヒ'), + (0x3339, 'M', 'ヘルツ'), + (0x333A, 'M', 'ペンス'), + (0x333B, 'M', 'ページ'), + (0x333C, 'M', 'ベータ'), + (0x333D, 'M', 'ポイント'), + (0x333E, 'M', 'ボルト'), + (0x333F, 'M', 'ホン'), + (0x3340, 'M', 'ポンド'), + (0x3341, 'M', 'ホール'), + (0x3342, 'M', 'ホーン'), + (0x3343, 'M', 'マイクロ'), + (0x3344, 'M', 'マイル'), + (0x3345, 'M', 'マッハ'), + (0x3346, 'M', 'マルク'), + (0x3347, 'M', 'マンション'), + (0x3348, 'M', 'ミクロン'), + (0x3349, 'M', 'ミリ'), + (0x334A, 'M', 'ミリバール'), + (0x334B, 'M', 'メガ'), + (0x334C, 'M', 'メガトン'), + (0x334D, 'M', 'メートル'), + (0x334E, 'M', 'ヤード'), + (0x334F, 'M', 'ヤール'), + (0x3350, 'M', 'ユアン'), + (0x3351, 'M', 'リットル'), + (0x3352, 'M', 'リラ'), + (0x3353, 'M', 'ルピー'), + (0x3354, 'M', 'ルーブル'), + (0x3355, 'M', 'レム'), + (0x3356, 'M', 'レントゲン'), + (0x3357, 'M', 'ワット'), + (0x3358, 'M', '0点'), + (0x3359, 'M', '1点'), + (0x335A, 'M', '2点'), + (0x335B, 'M', '3点'), + (0x335C, 'M', '4点'), + (0x335D, 'M', '5点'), + (0x335E, 'M', '6点'), + (0x335F, 'M', '7点'), + (0x3360, 'M', '8点'), + (0x3361, 'M', '9点'), + (0x3362, 'M', '10点'), + (0x3363, 'M', '11点'), + (0x3364, 'M', '12点'), + (0x3365, 'M', '13点'), + (0x3366, 'M', '14点'), + (0x3367, 'M', '15点'), + (0x3368, 'M', '16点'), + (0x3369, 'M', '17点'), + (0x336A, 'M', '18点'), + (0x336B, 'M', '19点'), + (0x336C, 'M', '20点'), + (0x336D, 'M', '21点'), + (0x336E, 'M', '22点'), + (0x336F, 'M', '23点'), + (0x3370, 'M', '24点'), + (0x3371, 'M', 'hpa'), + (0x3372, 'M', 'da'), + (0x3373, 'M', 'au'), + (0x3374, 'M', 'bar'), + (0x3375, 'M', 'ov'), ] def _seg_34(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x3376, 'M', u'pc'), - (0x3377, 'M', u'dm'), - (0x3378, 'M', u'dm2'), - (0x3379, 'M', u'dm3'), - (0x337A, 'M', u'iu'), - (0x337B, 'M', u'平成'), - (0x337C, 'M', u'昭和'), - (0x337D, 'M', u'大正'), - (0x337E, 'M', u'明治'), - (0x337F, 'M', u'株式会社'), - (0x3380, 'M', u'pa'), - (0x3381, 'M', u'na'), - (0x3382, 'M', u'μa'), - (0x3383, 'M', u'ma'), - (0x3384, 'M', u'ka'), - (0x3385, 'M', u'kb'), - (0x3386, 'M', u'mb'), - (0x3387, 'M', u'gb'), - (0x3388, 'M', u'cal'), - (0x3389, 'M', u'kcal'), - (0x338A, 'M', u'pf'), - (0x338B, 'M', u'nf'), - (0x338C, 'M', u'μf'), - (0x338D, 'M', u'μg'), - (0x338E, 'M', u'mg'), - (0x338F, 'M', u'kg'), - (0x3390, 'M', u'hz'), - (0x3391, 'M', u'khz'), - (0x3392, 'M', u'mhz'), - (0x3393, 'M', u'ghz'), - (0x3394, 'M', u'thz'), - (0x3395, 'M', u'μl'), - (0x3396, 'M', u'ml'), - (0x3397, 'M', u'dl'), - (0x3398, 'M', u'kl'), - (0x3399, 'M', u'fm'), - (0x339A, 'M', u'nm'), - (0x339B, 'M', u'μm'), - (0x339C, 'M', u'mm'), - (0x339D, 'M', u'cm'), - (0x339E, 'M', u'km'), - (0x339F, 'M', u'mm2'), - (0x33A0, 'M', u'cm2'), - (0x33A1, 'M', u'm2'), - (0x33A2, 'M', u'km2'), - (0x33A3, 'M', u'mm3'), - (0x33A4, 'M', u'cm3'), - (0x33A5, 'M', u'm3'), - (0x33A6, 'M', u'km3'), - (0x33A7, 'M', u'm∕s'), - (0x33A8, 'M', u'm∕s2'), - (0x33A9, 'M', u'pa'), - (0x33AA, 'M', u'kpa'), - (0x33AB, 'M', u'mpa'), - (0x33AC, 'M', u'gpa'), - (0x33AD, 'M', u'rad'), - (0x33AE, 'M', u'rad∕s'), - (0x33AF, 'M', u'rad∕s2'), - (0x33B0, 'M', u'ps'), - (0x33B1, 'M', u'ns'), - (0x33B2, 'M', u'μs'), - (0x33B3, 'M', u'ms'), - (0x33B4, 'M', u'pv'), - (0x33B5, 'M', u'nv'), - (0x33B6, 'M', u'μv'), - (0x33B7, 'M', u'mv'), - (0x33B8, 'M', u'kv'), - (0x33B9, 'M', u'mv'), - (0x33BA, 'M', u'pw'), - (0x33BB, 'M', u'nw'), - (0x33BC, 'M', u'μw'), - (0x33BD, 'M', u'mw'), - (0x33BE, 'M', u'kw'), - (0x33BF, 'M', u'mw'), - (0x33C0, 'M', u'kω'), - (0x33C1, 'M', u'mω'), + (0x3376, 'M', 'pc'), + (0x3377, 'M', 'dm'), + (0x3378, 'M', 'dm2'), + (0x3379, 'M', 'dm3'), + (0x337A, 'M', 'iu'), + (0x337B, 'M', '平成'), + (0x337C, 'M', '昭和'), + (0x337D, 'M', '大正'), + (0x337E, 'M', '明治'), + (0x337F, 'M', '株式会社'), + (0x3380, 'M', 'pa'), + (0x3381, 'M', 'na'), + (0x3382, 'M', 'μa'), + (0x3383, 'M', 'ma'), + (0x3384, 'M', 'ka'), + (0x3385, 'M', 'kb'), + (0x3386, 'M', 'mb'), + (0x3387, 'M', 'gb'), + (0x3388, 'M', 'cal'), + (0x3389, 'M', 'kcal'), + (0x338A, 'M', 'pf'), + (0x338B, 'M', 'nf'), + (0x338C, 'M', 'μf'), + (0x338D, 'M', 'μg'), + (0x338E, 'M', 'mg'), + (0x338F, 'M', 'kg'), + (0x3390, 'M', 'hz'), + (0x3391, 'M', 'khz'), + (0x3392, 'M', 'mhz'), + (0x3393, 'M', 'ghz'), + (0x3394, 'M', 'thz'), + (0x3395, 'M', 'μl'), + (0x3396, 'M', 'ml'), + (0x3397, 'M', 'dl'), + (0x3398, 'M', 'kl'), + (0x3399, 'M', 'fm'), + (0x339A, 'M', 'nm'), + (0x339B, 'M', 'μm'), + (0x339C, 'M', 'mm'), + (0x339D, 'M', 'cm'), + (0x339E, 'M', 'km'), + (0x339F, 'M', 'mm2'), + (0x33A0, 'M', 'cm2'), + (0x33A1, 'M', 'm2'), + (0x33A2, 'M', 'km2'), + (0x33A3, 'M', 'mm3'), + (0x33A4, 'M', 'cm3'), + (0x33A5, 'M', 'm3'), + (0x33A6, 'M', 'km3'), + (0x33A7, 'M', 'm∕s'), + (0x33A8, 'M', 'm∕s2'), + (0x33A9, 'M', 'pa'), + (0x33AA, 'M', 'kpa'), + (0x33AB, 'M', 'mpa'), + (0x33AC, 'M', 'gpa'), + (0x33AD, 'M', 'rad'), + (0x33AE, 'M', 'rad∕s'), + (0x33AF, 'M', 'rad∕s2'), + (0x33B0, 'M', 'ps'), + (0x33B1, 'M', 'ns'), + (0x33B2, 'M', 'μs'), + (0x33B3, 'M', 'ms'), + (0x33B4, 'M', 'pv'), + (0x33B5, 'M', 'nv'), + (0x33B6, 'M', 'μv'), + (0x33B7, 'M', 'mv'), + (0x33B8, 'M', 'kv'), + (0x33B9, 'M', 'mv'), + (0x33BA, 'M', 'pw'), + (0x33BB, 'M', 'nw'), + (0x33BC, 'M', 'μw'), + (0x33BD, 'M', 'mw'), + (0x33BE, 'M', 'kw'), + (0x33BF, 'M', 'mw'), + (0x33C0, 'M', 'kω'), + (0x33C1, 'M', 'mω'), (0x33C2, 'X'), - (0x33C3, 'M', u'bq'), - (0x33C4, 'M', u'cc'), - (0x33C5, 'M', u'cd'), - (0x33C6, 'M', u'c∕kg'), + (0x33C3, 'M', 'bq'), + (0x33C4, 'M', 'cc'), + (0x33C5, 'M', 'cd'), + (0x33C6, 'M', 'c∕kg'), (0x33C7, 'X'), - (0x33C8, 'M', u'db'), - (0x33C9, 'M', u'gy'), - (0x33CA, 'M', u'ha'), - (0x33CB, 'M', u'hp'), - (0x33CC, 'M', u'in'), - (0x33CD, 'M', u'kk'), - (0x33CE, 'M', u'km'), - (0x33CF, 'M', u'kt'), - (0x33D0, 'M', u'lm'), - (0x33D1, 'M', u'ln'), - (0x33D2, 'M', u'log'), - (0x33D3, 'M', u'lx'), - (0x33D4, 'M', u'mb'), - (0x33D5, 'M', u'mil'), - (0x33D6, 'M', u'mol'), - (0x33D7, 'M', u'ph'), + (0x33C8, 'M', 'db'), + (0x33C9, 'M', 'gy'), + (0x33CA, 'M', 'ha'), + (0x33CB, 'M', 'hp'), + (0x33CC, 'M', 'in'), + (0x33CD, 'M', 'kk'), + (0x33CE, 'M', 'km'), + (0x33CF, 'M', 'kt'), + (0x33D0, 'M', 'lm'), + (0x33D1, 'M', 'ln'), + (0x33D2, 'M', 'log'), + (0x33D3, 'M', 'lx'), + (0x33D4, 'M', 'mb'), + (0x33D5, 'M', 'mil'), + (0x33D6, 'M', 'mol'), + (0x33D7, 'M', 'ph'), (0x33D8, 'X'), - (0x33D9, 'M', u'ppm'), + (0x33D9, 'M', 'ppm'), ] def _seg_35(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x33DA, 'M', u'pr'), - (0x33DB, 'M', u'sr'), - (0x33DC, 'M', u'sv'), - (0x33DD, 'M', u'wb'), - (0x33DE, 'M', u'v∕m'), - (0x33DF, 'M', u'a∕m'), - (0x33E0, 'M', u'1日'), - (0x33E1, 'M', u'2日'), - (0x33E2, 'M', u'3日'), - (0x33E3, 'M', u'4日'), - (0x33E4, 'M', u'5日'), - (0x33E5, 'M', u'6日'), - (0x33E6, 'M', u'7日'), - (0x33E7, 'M', u'8日'), - (0x33E8, 'M', u'9日'), - (0x33E9, 'M', u'10日'), - (0x33EA, 'M', u'11日'), - (0x33EB, 'M', u'12日'), - (0x33EC, 'M', u'13日'), - (0x33ED, 'M', u'14日'), - (0x33EE, 'M', u'15日'), - (0x33EF, 'M', u'16日'), - (0x33F0, 'M', u'17日'), - (0x33F1, 'M', u'18日'), - (0x33F2, 'M', u'19日'), - (0x33F3, 'M', u'20日'), - (0x33F4, 'M', u'21日'), - (0x33F5, 'M', u'22日'), - (0x33F6, 'M', u'23日'), - (0x33F7, 'M', u'24日'), - (0x33F8, 'M', u'25日'), - (0x33F9, 'M', u'26日'), - (0x33FA, 'M', u'27日'), - (0x33FB, 'M', u'28日'), - (0x33FC, 'M', u'29日'), - (0x33FD, 'M', u'30日'), - (0x33FE, 'M', u'31日'), - (0x33FF, 'M', u'gal'), + (0x33DA, 'M', 'pr'), + (0x33DB, 'M', 'sr'), + (0x33DC, 'M', 'sv'), + (0x33DD, 'M', 'wb'), + (0x33DE, 'M', 'v∕m'), + (0x33DF, 'M', 'a∕m'), + (0x33E0, 'M', '1日'), + (0x33E1, 'M', '2日'), + (0x33E2, 'M', '3日'), + (0x33E3, 'M', '4日'), + (0x33E4, 'M', '5日'), + (0x33E5, 'M', '6日'), + (0x33E6, 'M', '7日'), + (0x33E7, 'M', '8日'), + (0x33E8, 'M', '9日'), + (0x33E9, 'M', '10日'), + (0x33EA, 'M', '11日'), + (0x33EB, 'M', '12日'), + (0x33EC, 'M', '13日'), + (0x33ED, 'M', '14日'), + (0x33EE, 'M', '15日'), + (0x33EF, 'M', '16日'), + (0x33F0, 'M', '17日'), + (0x33F1, 'M', '18日'), + (0x33F2, 'M', '19日'), + (0x33F3, 'M', '20日'), + (0x33F4, 'M', '21日'), + (0x33F5, 'M', '22日'), + (0x33F6, 'M', '23日'), + (0x33F7, 'M', '24日'), + (0x33F8, 'M', '25日'), + (0x33F9, 'M', '26日'), + (0x33FA, 'M', '27日'), + (0x33FB, 'M', '28日'), + (0x33FC, 'M', '29日'), + (0x33FD, 'M', '30日'), + (0x33FE, 'M', '31日'), + (0x33FF, 'M', 'gal'), (0x3400, 'V'), (0x9FFD, 'X'), (0xA000, 'V'), @@ -3693,251 +3730,253 @@ def _seg_35(): (0xA4C7, 'X'), (0xA4D0, 'V'), (0xA62C, 'X'), - (0xA640, 'M', u'ꙁ'), + (0xA640, 'M', 'ꙁ'), (0xA641, 'V'), - (0xA642, 'M', u'ꙃ'), + (0xA642, 'M', 'ꙃ'), (0xA643, 'V'), - (0xA644, 'M', u'ꙅ'), + (0xA644, 'M', 'ꙅ'), (0xA645, 'V'), - (0xA646, 'M', u'ꙇ'), + (0xA646, 'M', 'ꙇ'), (0xA647, 'V'), - (0xA648, 'M', u'ꙉ'), + (0xA648, 'M', 'ꙉ'), (0xA649, 'V'), - (0xA64A, 'M', u'ꙋ'), + (0xA64A, 'M', 'ꙋ'), (0xA64B, 'V'), - (0xA64C, 'M', u'ꙍ'), + (0xA64C, 'M', 'ꙍ'), (0xA64D, 'V'), - (0xA64E, 'M', u'ꙏ'), + (0xA64E, 'M', 'ꙏ'), (0xA64F, 'V'), - (0xA650, 'M', u'ꙑ'), + (0xA650, 'M', 'ꙑ'), (0xA651, 'V'), - (0xA652, 'M', u'ꙓ'), + (0xA652, 'M', 'ꙓ'), (0xA653, 'V'), - (0xA654, 'M', u'ꙕ'), + (0xA654, 'M', 'ꙕ'), (0xA655, 'V'), - (0xA656, 'M', u'ꙗ'), + (0xA656, 'M', 'ꙗ'), (0xA657, 'V'), - (0xA658, 'M', u'ꙙ'), + (0xA658, 'M', 'ꙙ'), (0xA659, 'V'), - (0xA65A, 'M', u'ꙛ'), + (0xA65A, 'M', 'ꙛ'), (0xA65B, 'V'), - (0xA65C, 'M', u'ꙝ'), + (0xA65C, 'M', 'ꙝ'), (0xA65D, 'V'), - (0xA65E, 'M', u'ꙟ'), + (0xA65E, 'M', 'ꙟ'), (0xA65F, 'V'), - (0xA660, 'M', u'ꙡ'), + (0xA660, 'M', 'ꙡ'), (0xA661, 'V'), - (0xA662, 'M', u'ꙣ'), + (0xA662, 'M', 'ꙣ'), (0xA663, 'V'), - (0xA664, 'M', u'ꙥ'), + (0xA664, 'M', 'ꙥ'), (0xA665, 'V'), - (0xA666, 'M', u'ꙧ'), + (0xA666, 'M', 'ꙧ'), (0xA667, 'V'), - (0xA668, 'M', u'ꙩ'), + (0xA668, 'M', 'ꙩ'), (0xA669, 'V'), - (0xA66A, 'M', u'ꙫ'), + (0xA66A, 'M', 'ꙫ'), (0xA66B, 'V'), - (0xA66C, 'M', u'ꙭ'), + (0xA66C, 'M', 'ꙭ'), (0xA66D, 'V'), - (0xA680, 'M', u'ꚁ'), + (0xA680, 'M', 'ꚁ'), (0xA681, 'V'), - (0xA682, 'M', u'ꚃ'), + (0xA682, 'M', 'ꚃ'), (0xA683, 'V'), - (0xA684, 'M', u'ꚅ'), + (0xA684, 'M', 'ꚅ'), (0xA685, 'V'), - (0xA686, 'M', u'ꚇ'), + (0xA686, 'M', 'ꚇ'), (0xA687, 'V'), ] def _seg_36(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xA688, 'M', u'ꚉ'), + (0xA688, 'M', 'ꚉ'), (0xA689, 'V'), - (0xA68A, 'M', u'ꚋ'), + (0xA68A, 'M', 'ꚋ'), (0xA68B, 'V'), - (0xA68C, 'M', u'ꚍ'), + (0xA68C, 'M', 'ꚍ'), (0xA68D, 'V'), - (0xA68E, 'M', u'ꚏ'), + (0xA68E, 'M', 'ꚏ'), (0xA68F, 'V'), - (0xA690, 'M', u'ꚑ'), + (0xA690, 'M', 'ꚑ'), (0xA691, 'V'), - (0xA692, 'M', u'ꚓ'), + (0xA692, 'M', 'ꚓ'), (0xA693, 'V'), - (0xA694, 'M', u'ꚕ'), + (0xA694, 'M', 'ꚕ'), (0xA695, 'V'), - (0xA696, 'M', u'ꚗ'), + (0xA696, 'M', 'ꚗ'), (0xA697, 'V'), - (0xA698, 'M', u'ꚙ'), + (0xA698, 'M', 'ꚙ'), (0xA699, 'V'), - (0xA69A, 'M', u'ꚛ'), + (0xA69A, 'M', 'ꚛ'), (0xA69B, 'V'), - (0xA69C, 'M', u'ъ'), - (0xA69D, 'M', u'ь'), + (0xA69C, 'M', 'ъ'), + (0xA69D, 'M', 'ь'), (0xA69E, 'V'), (0xA6F8, 'X'), (0xA700, 'V'), - (0xA722, 'M', u'ꜣ'), + (0xA722, 'M', 'ꜣ'), (0xA723, 'V'), - (0xA724, 'M', u'ꜥ'), + (0xA724, 'M', 'ꜥ'), (0xA725, 'V'), - (0xA726, 'M', u'ꜧ'), + (0xA726, 'M', 'ꜧ'), (0xA727, 'V'), - (0xA728, 'M', u'ꜩ'), + (0xA728, 'M', 'ꜩ'), (0xA729, 'V'), - (0xA72A, 'M', u'ꜫ'), + (0xA72A, 'M', 'ꜫ'), (0xA72B, 'V'), - (0xA72C, 'M', u'ꜭ'), + (0xA72C, 'M', 'ꜭ'), (0xA72D, 'V'), - (0xA72E, 'M', u'ꜯ'), + (0xA72E, 'M', 'ꜯ'), (0xA72F, 'V'), - (0xA732, 'M', u'ꜳ'), + (0xA732, 'M', 'ꜳ'), (0xA733, 'V'), - (0xA734, 'M', u'ꜵ'), + (0xA734, 'M', 'ꜵ'), (0xA735, 'V'), - (0xA736, 'M', u'ꜷ'), + (0xA736, 'M', 'ꜷ'), (0xA737, 'V'), - (0xA738, 'M', u'ꜹ'), + (0xA738, 'M', 'ꜹ'), (0xA739, 'V'), - (0xA73A, 'M', u'ꜻ'), + (0xA73A, 'M', 'ꜻ'), (0xA73B, 'V'), - (0xA73C, 'M', u'ꜽ'), + (0xA73C, 'M', 'ꜽ'), (0xA73D, 'V'), - (0xA73E, 'M', u'ꜿ'), + (0xA73E, 'M', 'ꜿ'), (0xA73F, 'V'), - (0xA740, 'M', u'ꝁ'), + (0xA740, 'M', 'ꝁ'), (0xA741, 'V'), - (0xA742, 'M', u'ꝃ'), + (0xA742, 'M', 'ꝃ'), (0xA743, 'V'), - (0xA744, 'M', u'ꝅ'), + (0xA744, 'M', 'ꝅ'), (0xA745, 'V'), - (0xA746, 'M', u'ꝇ'), + (0xA746, 'M', 'ꝇ'), (0xA747, 'V'), - (0xA748, 'M', u'ꝉ'), + (0xA748, 'M', 'ꝉ'), (0xA749, 'V'), - (0xA74A, 'M', u'ꝋ'), + (0xA74A, 'M', 'ꝋ'), (0xA74B, 'V'), - (0xA74C, 'M', u'ꝍ'), + (0xA74C, 'M', 'ꝍ'), (0xA74D, 'V'), - (0xA74E, 'M', u'ꝏ'), + (0xA74E, 'M', 'ꝏ'), (0xA74F, 'V'), - (0xA750, 'M', u'ꝑ'), + (0xA750, 'M', 'ꝑ'), (0xA751, 'V'), - (0xA752, 'M', u'ꝓ'), + (0xA752, 'M', 'ꝓ'), (0xA753, 'V'), - (0xA754, 'M', u'ꝕ'), + (0xA754, 'M', 'ꝕ'), (0xA755, 'V'), - (0xA756, 'M', u'ꝗ'), + (0xA756, 'M', 'ꝗ'), (0xA757, 'V'), - (0xA758, 'M', u'ꝙ'), + (0xA758, 'M', 'ꝙ'), (0xA759, 'V'), - (0xA75A, 'M', u'ꝛ'), + (0xA75A, 'M', 'ꝛ'), (0xA75B, 'V'), - (0xA75C, 'M', u'ꝝ'), + (0xA75C, 'M', 'ꝝ'), (0xA75D, 'V'), - (0xA75E, 'M', u'ꝟ'), + (0xA75E, 'M', 'ꝟ'), (0xA75F, 'V'), - (0xA760, 'M', u'ꝡ'), + (0xA760, 'M', 'ꝡ'), (0xA761, 'V'), - (0xA762, 'M', u'ꝣ'), + (0xA762, 'M', 'ꝣ'), (0xA763, 'V'), - (0xA764, 'M', u'ꝥ'), + (0xA764, 'M', 'ꝥ'), (0xA765, 'V'), - (0xA766, 'M', u'ꝧ'), + (0xA766, 'M', 'ꝧ'), (0xA767, 'V'), - (0xA768, 'M', u'ꝩ'), + (0xA768, 'M', 'ꝩ'), (0xA769, 'V'), - (0xA76A, 'M', u'ꝫ'), + (0xA76A, 'M', 'ꝫ'), (0xA76B, 'V'), - (0xA76C, 'M', u'ꝭ'), + (0xA76C, 'M', 'ꝭ'), (0xA76D, 'V'), - (0xA76E, 'M', u'ꝯ'), + (0xA76E, 'M', 'ꝯ'), ] def _seg_37(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xA76F, 'V'), - (0xA770, 'M', u'ꝯ'), + (0xA770, 'M', 'ꝯ'), (0xA771, 'V'), - (0xA779, 'M', u'ꝺ'), + (0xA779, 'M', 'ꝺ'), (0xA77A, 'V'), - (0xA77B, 'M', u'ꝼ'), + (0xA77B, 'M', 'ꝼ'), (0xA77C, 'V'), - (0xA77D, 'M', u'ᵹ'), - (0xA77E, 'M', u'ꝿ'), + (0xA77D, 'M', 'ᵹ'), + (0xA77E, 'M', 'ꝿ'), (0xA77F, 'V'), - (0xA780, 'M', u'ꞁ'), + (0xA780, 'M', 'ꞁ'), (0xA781, 'V'), - (0xA782, 'M', u'ꞃ'), + (0xA782, 'M', 'ꞃ'), (0xA783, 'V'), - (0xA784, 'M', u'ꞅ'), + (0xA784, 'M', 'ꞅ'), (0xA785, 'V'), - (0xA786, 'M', u'ꞇ'), + (0xA786, 'M', 'ꞇ'), (0xA787, 'V'), - (0xA78B, 'M', u'ꞌ'), + (0xA78B, 'M', 'ꞌ'), (0xA78C, 'V'), - (0xA78D, 'M', u'ɥ'), + (0xA78D, 'M', 'ɥ'), (0xA78E, 'V'), - (0xA790, 'M', u'ꞑ'), + (0xA790, 'M', 'ꞑ'), (0xA791, 'V'), - (0xA792, 'M', u'ꞓ'), + (0xA792, 'M', 'ꞓ'), (0xA793, 'V'), - (0xA796, 'M', u'ꞗ'), + (0xA796, 'M', 'ꞗ'), (0xA797, 'V'), - (0xA798, 'M', u'ꞙ'), + (0xA798, 'M', 'ꞙ'), (0xA799, 'V'), - (0xA79A, 'M', u'ꞛ'), + (0xA79A, 'M', 'ꞛ'), (0xA79B, 'V'), - (0xA79C, 'M', u'ꞝ'), + (0xA79C, 'M', 'ꞝ'), (0xA79D, 'V'), - (0xA79E, 'M', u'ꞟ'), + (0xA79E, 'M', 'ꞟ'), (0xA79F, 'V'), - (0xA7A0, 'M', u'ꞡ'), + (0xA7A0, 'M', 'ꞡ'), (0xA7A1, 'V'), - (0xA7A2, 'M', u'ꞣ'), + (0xA7A2, 'M', 'ꞣ'), (0xA7A3, 'V'), - (0xA7A4, 'M', u'ꞥ'), + (0xA7A4, 'M', 'ꞥ'), (0xA7A5, 'V'), - (0xA7A6, 'M', u'ꞧ'), + (0xA7A6, 'M', 'ꞧ'), (0xA7A7, 'V'), - (0xA7A8, 'M', u'ꞩ'), + (0xA7A8, 'M', 'ꞩ'), (0xA7A9, 'V'), - (0xA7AA, 'M', u'ɦ'), - (0xA7AB, 'M', u'ɜ'), - (0xA7AC, 'M', u'ɡ'), - (0xA7AD, 'M', u'ɬ'), - (0xA7AE, 'M', u'ɪ'), + (0xA7AA, 'M', 'ɦ'), + (0xA7AB, 'M', 'ɜ'), + (0xA7AC, 'M', 'ɡ'), + (0xA7AD, 'M', 'ɬ'), + (0xA7AE, 'M', 'ɪ'), (0xA7AF, 'V'), - (0xA7B0, 'M', u'ʞ'), - (0xA7B1, 'M', u'ʇ'), - (0xA7B2, 'M', u'ʝ'), - (0xA7B3, 'M', u'ꭓ'), - (0xA7B4, 'M', u'ꞵ'), + (0xA7B0, 'M', 'ʞ'), + (0xA7B1, 'M', 'ʇ'), + (0xA7B2, 'M', 'ʝ'), + (0xA7B3, 'M', 'ꭓ'), + (0xA7B4, 'M', 'ꞵ'), (0xA7B5, 'V'), - (0xA7B6, 'M', u'ꞷ'), + (0xA7B6, 'M', 'ꞷ'), (0xA7B7, 'V'), - (0xA7B8, 'M', u'ꞹ'), + (0xA7B8, 'M', 'ꞹ'), (0xA7B9, 'V'), - (0xA7BA, 'M', u'ꞻ'), + (0xA7BA, 'M', 'ꞻ'), (0xA7BB, 'V'), - (0xA7BC, 'M', u'ꞽ'), + (0xA7BC, 'M', 'ꞽ'), (0xA7BD, 'V'), - (0xA7BE, 'M', u'ꞿ'), + (0xA7BE, 'M', 'ꞿ'), (0xA7BF, 'V'), (0xA7C0, 'X'), - (0xA7C2, 'M', u'ꟃ'), + (0xA7C2, 'M', 'ꟃ'), (0xA7C3, 'V'), - (0xA7C4, 'M', u'ꞔ'), - (0xA7C5, 'M', u'ʂ'), - (0xA7C6, 'M', u'ᶎ'), - (0xA7C7, 'M', u'ꟈ'), + (0xA7C4, 'M', 'ꞔ'), + (0xA7C5, 'M', 'ʂ'), + (0xA7C6, 'M', 'ᶎ'), + (0xA7C7, 'M', 'ꟈ'), (0xA7C8, 'V'), - (0xA7C9, 'M', u'ꟊ'), + (0xA7C9, 'M', 'ꟊ'), (0xA7CA, 'V'), (0xA7CB, 'X'), - (0xA7F5, 'M', u'ꟶ'), + (0xA7F5, 'M', 'ꟶ'), (0xA7F6, 'V'), - (0xA7F8, 'M', u'ħ'), - (0xA7F9, 'M', u'œ'), + (0xA7F8, 'M', 'ħ'), + (0xA7F9, 'M', 'œ'), (0xA7FA, 'V'), (0xA82D, 'X'), (0xA830, 'V'), @@ -3958,6 +3997,7 @@ def _seg_37(): ] def _seg_38(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xA9DA, 'X'), (0xA9DE, 'V'), @@ -3983,98 +4023,99 @@ def _seg_38(): (0xAB28, 'V'), (0xAB2F, 'X'), (0xAB30, 'V'), - (0xAB5C, 'M', u'ꜧ'), - (0xAB5D, 'M', u'ꬷ'), - (0xAB5E, 'M', u'ɫ'), - (0xAB5F, 'M', u'ꭒ'), + (0xAB5C, 'M', 'ꜧ'), + (0xAB5D, 'M', 'ꬷ'), + (0xAB5E, 'M', 'ɫ'), + (0xAB5F, 'M', 'ꭒ'), (0xAB60, 'V'), - (0xAB69, 'M', u'ʍ'), + (0xAB69, 'M', 'ʍ'), (0xAB6A, 'V'), (0xAB6C, 'X'), - (0xAB70, 'M', u'Ꭰ'), - (0xAB71, 'M', u'Ꭱ'), - (0xAB72, 'M', u'Ꭲ'), - (0xAB73, 'M', u'Ꭳ'), - (0xAB74, 'M', u'Ꭴ'), - (0xAB75, 'M', u'Ꭵ'), - (0xAB76, 'M', u'Ꭶ'), - (0xAB77, 'M', u'Ꭷ'), - (0xAB78, 'M', u'Ꭸ'), - (0xAB79, 'M', u'Ꭹ'), - (0xAB7A, 'M', u'Ꭺ'), - (0xAB7B, 'M', u'Ꭻ'), - (0xAB7C, 'M', u'Ꭼ'), - (0xAB7D, 'M', u'Ꭽ'), - (0xAB7E, 'M', u'Ꭾ'), - (0xAB7F, 'M', u'Ꭿ'), - (0xAB80, 'M', u'Ꮀ'), - (0xAB81, 'M', u'Ꮁ'), - (0xAB82, 'M', u'Ꮂ'), - (0xAB83, 'M', u'Ꮃ'), - (0xAB84, 'M', u'Ꮄ'), - (0xAB85, 'M', u'Ꮅ'), - (0xAB86, 'M', u'Ꮆ'), - (0xAB87, 'M', u'Ꮇ'), - (0xAB88, 'M', u'Ꮈ'), - (0xAB89, 'M', u'Ꮉ'), - (0xAB8A, 'M', u'Ꮊ'), - (0xAB8B, 'M', u'Ꮋ'), - (0xAB8C, 'M', u'Ꮌ'), - (0xAB8D, 'M', u'Ꮍ'), - (0xAB8E, 'M', u'Ꮎ'), - (0xAB8F, 'M', u'Ꮏ'), - (0xAB90, 'M', u'Ꮐ'), - (0xAB91, 'M', u'Ꮑ'), - (0xAB92, 'M', u'Ꮒ'), - (0xAB93, 'M', u'Ꮓ'), - (0xAB94, 'M', u'Ꮔ'), - (0xAB95, 'M', u'Ꮕ'), - (0xAB96, 'M', u'Ꮖ'), - (0xAB97, 'M', u'Ꮗ'), - (0xAB98, 'M', u'Ꮘ'), - (0xAB99, 'M', u'Ꮙ'), - (0xAB9A, 'M', u'Ꮚ'), - (0xAB9B, 'M', u'Ꮛ'), - (0xAB9C, 'M', u'Ꮜ'), - (0xAB9D, 'M', u'Ꮝ'), - (0xAB9E, 'M', u'Ꮞ'), - (0xAB9F, 'M', u'Ꮟ'), - (0xABA0, 'M', u'Ꮠ'), - (0xABA1, 'M', u'Ꮡ'), - (0xABA2, 'M', u'Ꮢ'), - (0xABA3, 'M', u'Ꮣ'), - (0xABA4, 'M', u'Ꮤ'), - (0xABA5, 'M', u'Ꮥ'), - (0xABA6, 'M', u'Ꮦ'), - (0xABA7, 'M', u'Ꮧ'), - (0xABA8, 'M', u'Ꮨ'), - (0xABA9, 'M', u'Ꮩ'), - (0xABAA, 'M', u'Ꮪ'), - (0xABAB, 'M', u'Ꮫ'), - (0xABAC, 'M', u'Ꮬ'), - (0xABAD, 'M', u'Ꮭ'), - (0xABAE, 'M', u'Ꮮ'), - (0xABAF, 'M', u'Ꮯ'), - (0xABB0, 'M', u'Ꮰ'), - (0xABB1, 'M', u'Ꮱ'), - (0xABB2, 'M', u'Ꮲ'), - (0xABB3, 'M', u'Ꮳ'), + (0xAB70, 'M', 'Ꭰ'), + (0xAB71, 'M', 'Ꭱ'), + (0xAB72, 'M', 'Ꭲ'), + (0xAB73, 'M', 'Ꭳ'), + (0xAB74, 'M', 'Ꭴ'), + (0xAB75, 'M', 'Ꭵ'), + (0xAB76, 'M', 'Ꭶ'), + (0xAB77, 'M', 'Ꭷ'), + (0xAB78, 'M', 'Ꭸ'), + (0xAB79, 'M', 'Ꭹ'), + (0xAB7A, 'M', 'Ꭺ'), + (0xAB7B, 'M', 'Ꭻ'), + (0xAB7C, 'M', 'Ꭼ'), + (0xAB7D, 'M', 'Ꭽ'), + (0xAB7E, 'M', 'Ꭾ'), + (0xAB7F, 'M', 'Ꭿ'), + (0xAB80, 'M', 'Ꮀ'), + (0xAB81, 'M', 'Ꮁ'), + (0xAB82, 'M', 'Ꮂ'), + (0xAB83, 'M', 'Ꮃ'), + (0xAB84, 'M', 'Ꮄ'), + (0xAB85, 'M', 'Ꮅ'), + (0xAB86, 'M', 'Ꮆ'), + (0xAB87, 'M', 'Ꮇ'), + (0xAB88, 'M', 'Ꮈ'), + (0xAB89, 'M', 'Ꮉ'), + (0xAB8A, 'M', 'Ꮊ'), + (0xAB8B, 'M', 'Ꮋ'), + (0xAB8C, 'M', 'Ꮌ'), + (0xAB8D, 'M', 'Ꮍ'), + (0xAB8E, 'M', 'Ꮎ'), + (0xAB8F, 'M', 'Ꮏ'), + (0xAB90, 'M', 'Ꮐ'), + (0xAB91, 'M', 'Ꮑ'), + (0xAB92, 'M', 'Ꮒ'), + (0xAB93, 'M', 'Ꮓ'), + (0xAB94, 'M', 'Ꮔ'), + (0xAB95, 'M', 'Ꮕ'), + (0xAB96, 'M', 'Ꮖ'), + (0xAB97, 'M', 'Ꮗ'), + (0xAB98, 'M', 'Ꮘ'), + (0xAB99, 'M', 'Ꮙ'), + (0xAB9A, 'M', 'Ꮚ'), + (0xAB9B, 'M', 'Ꮛ'), + (0xAB9C, 'M', 'Ꮜ'), + (0xAB9D, 'M', 'Ꮝ'), + (0xAB9E, 'M', 'Ꮞ'), + (0xAB9F, 'M', 'Ꮟ'), + (0xABA0, 'M', 'Ꮠ'), + (0xABA1, 'M', 'Ꮡ'), + (0xABA2, 'M', 'Ꮢ'), + (0xABA3, 'M', 'Ꮣ'), + (0xABA4, 'M', 'Ꮤ'), + (0xABA5, 'M', 'Ꮥ'), + (0xABA6, 'M', 'Ꮦ'), + (0xABA7, 'M', 'Ꮧ'), + (0xABA8, 'M', 'Ꮨ'), + (0xABA9, 'M', 'Ꮩ'), + (0xABAA, 'M', 'Ꮪ'), + (0xABAB, 'M', 'Ꮫ'), + (0xABAC, 'M', 'Ꮬ'), + (0xABAD, 'M', 'Ꮭ'), + (0xABAE, 'M', 'Ꮮ'), + (0xABAF, 'M', 'Ꮯ'), + (0xABB0, 'M', 'Ꮰ'), + (0xABB1, 'M', 'Ꮱ'), + (0xABB2, 'M', 'Ꮲ'), + (0xABB3, 'M', 'Ꮳ'), ] def _seg_39(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xABB4, 'M', u'Ꮴ'), - (0xABB5, 'M', u'Ꮵ'), - (0xABB6, 'M', u'Ꮶ'), - (0xABB7, 'M', u'Ꮷ'), - (0xABB8, 'M', u'Ꮸ'), - (0xABB9, 'M', u'Ꮹ'), - (0xABBA, 'M', u'Ꮺ'), - (0xABBB, 'M', u'Ꮻ'), - (0xABBC, 'M', u'Ꮼ'), - (0xABBD, 'M', u'Ꮽ'), - (0xABBE, 'M', u'Ꮾ'), - (0xABBF, 'M', u'Ꮿ'), + (0xABB4, 'M', 'Ꮴ'), + (0xABB5, 'M', 'Ꮵ'), + (0xABB6, 'M', 'Ꮶ'), + (0xABB7, 'M', 'Ꮷ'), + (0xABB8, 'M', 'Ꮸ'), + (0xABB9, 'M', 'Ꮹ'), + (0xABBA, 'M', 'Ꮺ'), + (0xABBB, 'M', 'Ꮻ'), + (0xABBC, 'M', 'Ꮼ'), + (0xABBD, 'M', 'Ꮽ'), + (0xABBE, 'M', 'Ꮾ'), + (0xABBF, 'M', 'Ꮿ'), (0xABC0, 'V'), (0xABEE, 'X'), (0xABF0, 'V'), @@ -4085,1432 +4126,1445 @@ def _seg_39(): (0xD7C7, 'X'), (0xD7CB, 'V'), (0xD7FC, 'X'), - (0xF900, 'M', u'豈'), - (0xF901, 'M', u'更'), - (0xF902, 'M', u'車'), - (0xF903, 'M', u'賈'), - (0xF904, 'M', u'滑'), - (0xF905, 'M', u'串'), - (0xF906, 'M', u'句'), - (0xF907, 'M', u'龜'), - (0xF909, 'M', u'契'), - (0xF90A, 'M', u'金'), - (0xF90B, 'M', u'喇'), - (0xF90C, 'M', u'奈'), - (0xF90D, 'M', u'懶'), - (0xF90E, 'M', u'癩'), - (0xF90F, 'M', u'羅'), - (0xF910, 'M', u'蘿'), - (0xF911, 'M', u'螺'), - (0xF912, 'M', u'裸'), - (0xF913, 'M', u'邏'), - (0xF914, 'M', u'樂'), - (0xF915, 'M', u'洛'), - (0xF916, 'M', u'烙'), - (0xF917, 'M', u'珞'), - (0xF918, 'M', u'落'), - (0xF919, 'M', u'酪'), - (0xF91A, 'M', u'駱'), - (0xF91B, 'M', u'亂'), - (0xF91C, 'M', u'卵'), - (0xF91D, 'M', u'欄'), - (0xF91E, 'M', u'爛'), - (0xF91F, 'M', u'蘭'), - (0xF920, 'M', u'鸞'), - (0xF921, 'M', u'嵐'), - (0xF922, 'M', u'濫'), - (0xF923, 'M', u'藍'), - (0xF924, 'M', u'襤'), - (0xF925, 'M', u'拉'), - (0xF926, 'M', u'臘'), - (0xF927, 'M', u'蠟'), - (0xF928, 'M', u'廊'), - (0xF929, 'M', u'朗'), - (0xF92A, 'M', u'浪'), - (0xF92B, 'M', u'狼'), - (0xF92C, 'M', u'郎'), - (0xF92D, 'M', u'來'), - (0xF92E, 'M', u'冷'), - (0xF92F, 'M', u'勞'), - (0xF930, 'M', u'擄'), - (0xF931, 'M', u'櫓'), - (0xF932, 'M', u'爐'), - (0xF933, 'M', u'盧'), - (0xF934, 'M', u'老'), - (0xF935, 'M', u'蘆'), - (0xF936, 'M', u'虜'), - (0xF937, 'M', u'路'), - (0xF938, 'M', u'露'), - (0xF939, 'M', u'魯'), - (0xF93A, 'M', u'鷺'), - (0xF93B, 'M', u'碌'), - (0xF93C, 'M', u'祿'), - (0xF93D, 'M', u'綠'), - (0xF93E, 'M', u'菉'), - (0xF93F, 'M', u'錄'), - (0xF940, 'M', u'鹿'), - (0xF941, 'M', u'論'), - (0xF942, 'M', u'壟'), - (0xF943, 'M', u'弄'), - (0xF944, 'M', u'籠'), - (0xF945, 'M', u'聾'), - (0xF946, 'M', u'牢'), - (0xF947, 'M', u'磊'), - (0xF948, 'M', u'賂'), - (0xF949, 'M', u'雷'), - (0xF94A, 'M', u'壘'), - (0xF94B, 'M', u'屢'), - (0xF94C, 'M', u'樓'), - (0xF94D, 'M', u'淚'), - (0xF94E, 'M', u'漏'), + (0xF900, 'M', '豈'), + (0xF901, 'M', '更'), + (0xF902, 'M', '車'), + (0xF903, 'M', '賈'), + (0xF904, 'M', '滑'), + (0xF905, 'M', '串'), + (0xF906, 'M', '句'), + (0xF907, 'M', '龜'), + (0xF909, 'M', '契'), + (0xF90A, 'M', '金'), + (0xF90B, 'M', '喇'), + (0xF90C, 'M', '奈'), + (0xF90D, 'M', '懶'), + (0xF90E, 'M', '癩'), + (0xF90F, 'M', '羅'), + (0xF910, 'M', '蘿'), + (0xF911, 'M', '螺'), + (0xF912, 'M', '裸'), + (0xF913, 'M', '邏'), + (0xF914, 'M', '樂'), + (0xF915, 'M', '洛'), + (0xF916, 'M', '烙'), + (0xF917, 'M', '珞'), + (0xF918, 'M', '落'), + (0xF919, 'M', '酪'), + (0xF91A, 'M', '駱'), + (0xF91B, 'M', '亂'), + (0xF91C, 'M', '卵'), + (0xF91D, 'M', '欄'), + (0xF91E, 'M', '爛'), + (0xF91F, 'M', '蘭'), + (0xF920, 'M', '鸞'), + (0xF921, 'M', '嵐'), + (0xF922, 'M', '濫'), + (0xF923, 'M', '藍'), + (0xF924, 'M', '襤'), + (0xF925, 'M', '拉'), + (0xF926, 'M', '臘'), + (0xF927, 'M', '蠟'), + (0xF928, 'M', '廊'), + (0xF929, 'M', '朗'), + (0xF92A, 'M', '浪'), + (0xF92B, 'M', '狼'), + (0xF92C, 'M', '郎'), + (0xF92D, 'M', '來'), + (0xF92E, 'M', '冷'), + (0xF92F, 'M', '勞'), + (0xF930, 'M', '擄'), + (0xF931, 'M', '櫓'), + (0xF932, 'M', '爐'), + (0xF933, 'M', '盧'), + (0xF934, 'M', '老'), + (0xF935, 'M', '蘆'), + (0xF936, 'M', '虜'), + (0xF937, 'M', '路'), + (0xF938, 'M', '露'), + (0xF939, 'M', '魯'), + (0xF93A, 'M', '鷺'), + (0xF93B, 'M', '碌'), + (0xF93C, 'M', '祿'), + (0xF93D, 'M', '綠'), + (0xF93E, 'M', '菉'), + (0xF93F, 'M', '錄'), + (0xF940, 'M', '鹿'), + (0xF941, 'M', '論'), + (0xF942, 'M', '壟'), + (0xF943, 'M', '弄'), + (0xF944, 'M', '籠'), + (0xF945, 'M', '聾'), + (0xF946, 'M', '牢'), + (0xF947, 'M', '磊'), + (0xF948, 'M', '賂'), + (0xF949, 'M', '雷'), + (0xF94A, 'M', '壘'), + (0xF94B, 'M', '屢'), + (0xF94C, 'M', '樓'), + (0xF94D, 'M', '淚'), + (0xF94E, 'M', '漏'), ] def _seg_40(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xF94F, 'M', u'累'), - (0xF950, 'M', u'縷'), - (0xF951, 'M', u'陋'), - (0xF952, 'M', u'勒'), - (0xF953, 'M', u'肋'), - (0xF954, 'M', u'凜'), - (0xF955, 'M', u'凌'), - (0xF956, 'M', u'稜'), - (0xF957, 'M', u'綾'), - (0xF958, 'M', u'菱'), - (0xF959, 'M', u'陵'), - (0xF95A, 'M', u'讀'), - (0xF95B, 'M', u'拏'), - (0xF95C, 'M', u'樂'), - (0xF95D, 'M', u'諾'), - (0xF95E, 'M', u'丹'), - (0xF95F, 'M', u'寧'), - (0xF960, 'M', u'怒'), - (0xF961, 'M', u'率'), - (0xF962, 'M', u'異'), - (0xF963, 'M', u'北'), - (0xF964, 'M', u'磻'), - (0xF965, 'M', u'便'), - (0xF966, 'M', u'復'), - (0xF967, 'M', u'不'), - (0xF968, 'M', u'泌'), - (0xF969, 'M', u'數'), - (0xF96A, 'M', u'索'), - (0xF96B, 'M', u'參'), - (0xF96C, 'M', u'塞'), - (0xF96D, 'M', u'省'), - (0xF96E, 'M', u'葉'), - (0xF96F, 'M', u'說'), - (0xF970, 'M', u'殺'), - (0xF971, 'M', u'辰'), - (0xF972, 'M', u'沈'), - (0xF973, 'M', u'拾'), - (0xF974, 'M', u'若'), - (0xF975, 'M', u'掠'), - (0xF976, 'M', u'略'), - (0xF977, 'M', u'亮'), - (0xF978, 'M', u'兩'), - (0xF979, 'M', u'凉'), - (0xF97A, 'M', u'梁'), - (0xF97B, 'M', u'糧'), - (0xF97C, 'M', u'良'), - (0xF97D, 'M', u'諒'), - (0xF97E, 'M', u'量'), - (0xF97F, 'M', u'勵'), - (0xF980, 'M', u'呂'), - (0xF981, 'M', u'女'), - (0xF982, 'M', u'廬'), - (0xF983, 'M', u'旅'), - (0xF984, 'M', u'濾'), - (0xF985, 'M', u'礪'), - (0xF986, 'M', u'閭'), - (0xF987, 'M', u'驪'), - (0xF988, 'M', u'麗'), - (0xF989, 'M', u'黎'), - (0xF98A, 'M', u'力'), - (0xF98B, 'M', u'曆'), - (0xF98C, 'M', u'歷'), - (0xF98D, 'M', u'轢'), - (0xF98E, 'M', u'年'), - (0xF98F, 'M', u'憐'), - (0xF990, 'M', u'戀'), - (0xF991, 'M', u'撚'), - (0xF992, 'M', u'漣'), - (0xF993, 'M', u'煉'), - (0xF994, 'M', u'璉'), - (0xF995, 'M', u'秊'), - (0xF996, 'M', u'練'), - (0xF997, 'M', u'聯'), - (0xF998, 'M', u'輦'), - (0xF999, 'M', u'蓮'), - (0xF99A, 'M', u'連'), - (0xF99B, 'M', u'鍊'), - (0xF99C, 'M', u'列'), - (0xF99D, 'M', u'劣'), - (0xF99E, 'M', u'咽'), - (0xF99F, 'M', u'烈'), - (0xF9A0, 'M', u'裂'), - (0xF9A1, 'M', u'說'), - (0xF9A2, 'M', u'廉'), - (0xF9A3, 'M', u'念'), - (0xF9A4, 'M', u'捻'), - (0xF9A5, 'M', u'殮'), - (0xF9A6, 'M', u'簾'), - (0xF9A7, 'M', u'獵'), - (0xF9A8, 'M', u'令'), - (0xF9A9, 'M', u'囹'), - (0xF9AA, 'M', u'寧'), - (0xF9AB, 'M', u'嶺'), - (0xF9AC, 'M', u'怜'), - (0xF9AD, 'M', u'玲'), - (0xF9AE, 'M', u'瑩'), - (0xF9AF, 'M', u'羚'), - (0xF9B0, 'M', u'聆'), - (0xF9B1, 'M', u'鈴'), - (0xF9B2, 'M', u'零'), + (0xF94F, 'M', '累'), + (0xF950, 'M', '縷'), + (0xF951, 'M', '陋'), + (0xF952, 'M', '勒'), + (0xF953, 'M', '肋'), + (0xF954, 'M', '凜'), + (0xF955, 'M', '凌'), + (0xF956, 'M', '稜'), + (0xF957, 'M', '綾'), + (0xF958, 'M', '菱'), + (0xF959, 'M', '陵'), + (0xF95A, 'M', '讀'), + (0xF95B, 'M', '拏'), + (0xF95C, 'M', '樂'), + (0xF95D, 'M', '諾'), + (0xF95E, 'M', '丹'), + (0xF95F, 'M', '寧'), + (0xF960, 'M', '怒'), + (0xF961, 'M', '率'), + (0xF962, 'M', '異'), + (0xF963, 'M', '北'), + (0xF964, 'M', '磻'), + (0xF965, 'M', '便'), + (0xF966, 'M', '復'), + (0xF967, 'M', '不'), + (0xF968, 'M', '泌'), + (0xF969, 'M', '數'), + (0xF96A, 'M', '索'), + (0xF96B, 'M', '參'), + (0xF96C, 'M', '塞'), + (0xF96D, 'M', '省'), + (0xF96E, 'M', '葉'), + (0xF96F, 'M', '說'), + (0xF970, 'M', '殺'), + (0xF971, 'M', '辰'), + (0xF972, 'M', '沈'), + (0xF973, 'M', '拾'), + (0xF974, 'M', '若'), + (0xF975, 'M', '掠'), + (0xF976, 'M', '略'), + (0xF977, 'M', '亮'), + (0xF978, 'M', '兩'), + (0xF979, 'M', '凉'), + (0xF97A, 'M', '梁'), + (0xF97B, 'M', '糧'), + (0xF97C, 'M', '良'), + (0xF97D, 'M', '諒'), + (0xF97E, 'M', '量'), + (0xF97F, 'M', '勵'), + (0xF980, 'M', '呂'), + (0xF981, 'M', '女'), + (0xF982, 'M', '廬'), + (0xF983, 'M', '旅'), + (0xF984, 'M', '濾'), + (0xF985, 'M', '礪'), + (0xF986, 'M', '閭'), + (0xF987, 'M', '驪'), + (0xF988, 'M', '麗'), + (0xF989, 'M', '黎'), + (0xF98A, 'M', '力'), + (0xF98B, 'M', '曆'), + (0xF98C, 'M', '歷'), + (0xF98D, 'M', '轢'), + (0xF98E, 'M', '年'), + (0xF98F, 'M', '憐'), + (0xF990, 'M', '戀'), + (0xF991, 'M', '撚'), + (0xF992, 'M', '漣'), + (0xF993, 'M', '煉'), + (0xF994, 'M', '璉'), + (0xF995, 'M', '秊'), + (0xF996, 'M', '練'), + (0xF997, 'M', '聯'), + (0xF998, 'M', '輦'), + (0xF999, 'M', '蓮'), + (0xF99A, 'M', '連'), + (0xF99B, 'M', '鍊'), + (0xF99C, 'M', '列'), + (0xF99D, 'M', '劣'), + (0xF99E, 'M', '咽'), + (0xF99F, 'M', '烈'), + (0xF9A0, 'M', '裂'), + (0xF9A1, 'M', '說'), + (0xF9A2, 'M', '廉'), + (0xF9A3, 'M', '念'), + (0xF9A4, 'M', '捻'), + (0xF9A5, 'M', '殮'), + (0xF9A6, 'M', '簾'), + (0xF9A7, 'M', '獵'), + (0xF9A8, 'M', '令'), + (0xF9A9, 'M', '囹'), + (0xF9AA, 'M', '寧'), + (0xF9AB, 'M', '嶺'), + (0xF9AC, 'M', '怜'), + (0xF9AD, 'M', '玲'), + (0xF9AE, 'M', '瑩'), + (0xF9AF, 'M', '羚'), + (0xF9B0, 'M', '聆'), + (0xF9B1, 'M', '鈴'), + (0xF9B2, 'M', '零'), ] def _seg_41(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xF9B3, 'M', u'靈'), - (0xF9B4, 'M', u'領'), - (0xF9B5, 'M', u'例'), - (0xF9B6, 'M', u'禮'), - (0xF9B7, 'M', u'醴'), - (0xF9B8, 'M', u'隸'), - (0xF9B9, 'M', u'惡'), - (0xF9BA, 'M', u'了'), - (0xF9BB, 'M', u'僚'), - (0xF9BC, 'M', u'寮'), - (0xF9BD, 'M', u'尿'), - (0xF9BE, 'M', u'料'), - (0xF9BF, 'M', u'樂'), - (0xF9C0, 'M', u'燎'), - (0xF9C1, 'M', u'療'), - (0xF9C2, 'M', u'蓼'), - (0xF9C3, 'M', u'遼'), - (0xF9C4, 'M', u'龍'), - (0xF9C5, 'M', u'暈'), - (0xF9C6, 'M', u'阮'), - (0xF9C7, 'M', u'劉'), - (0xF9C8, 'M', u'杻'), - (0xF9C9, 'M', u'柳'), - (0xF9CA, 'M', u'流'), - (0xF9CB, 'M', u'溜'), - (0xF9CC, 'M', u'琉'), - (0xF9CD, 'M', u'留'), - (0xF9CE, 'M', u'硫'), - (0xF9CF, 'M', u'紐'), - (0xF9D0, 'M', u'類'), - (0xF9D1, 'M', u'六'), - (0xF9D2, 'M', u'戮'), - (0xF9D3, 'M', u'陸'), - (0xF9D4, 'M', u'倫'), - (0xF9D5, 'M', u'崙'), - (0xF9D6, 'M', u'淪'), - (0xF9D7, 'M', u'輪'), - (0xF9D8, 'M', u'律'), - (0xF9D9, 'M', u'慄'), - (0xF9DA, 'M', u'栗'), - (0xF9DB, 'M', u'率'), - (0xF9DC, 'M', u'隆'), - (0xF9DD, 'M', u'利'), - (0xF9DE, 'M', u'吏'), - (0xF9DF, 'M', u'履'), - (0xF9E0, 'M', u'易'), - (0xF9E1, 'M', u'李'), - (0xF9E2, 'M', u'梨'), - (0xF9E3, 'M', u'泥'), - (0xF9E4, 'M', u'理'), - (0xF9E5, 'M', u'痢'), - (0xF9E6, 'M', u'罹'), - (0xF9E7, 'M', u'裏'), - (0xF9E8, 'M', u'裡'), - (0xF9E9, 'M', u'里'), - (0xF9EA, 'M', u'離'), - (0xF9EB, 'M', u'匿'), - (0xF9EC, 'M', u'溺'), - (0xF9ED, 'M', u'吝'), - (0xF9EE, 'M', u'燐'), - (0xF9EF, 'M', u'璘'), - (0xF9F0, 'M', u'藺'), - (0xF9F1, 'M', u'隣'), - (0xF9F2, 'M', u'鱗'), - (0xF9F3, 'M', u'麟'), - (0xF9F4, 'M', u'林'), - (0xF9F5, 'M', u'淋'), - (0xF9F6, 'M', u'臨'), - (0xF9F7, 'M', u'立'), - (0xF9F8, 'M', u'笠'), - (0xF9F9, 'M', u'粒'), - (0xF9FA, 'M', u'狀'), - (0xF9FB, 'M', u'炙'), - (0xF9FC, 'M', u'識'), - (0xF9FD, 'M', u'什'), - (0xF9FE, 'M', u'茶'), - (0xF9FF, 'M', u'刺'), - (0xFA00, 'M', u'切'), - (0xFA01, 'M', u'度'), - (0xFA02, 'M', u'拓'), - (0xFA03, 'M', u'糖'), - (0xFA04, 'M', u'宅'), - (0xFA05, 'M', u'洞'), - (0xFA06, 'M', u'暴'), - (0xFA07, 'M', u'輻'), - (0xFA08, 'M', u'行'), - (0xFA09, 'M', u'降'), - (0xFA0A, 'M', u'見'), - (0xFA0B, 'M', u'廓'), - (0xFA0C, 'M', u'兀'), - (0xFA0D, 'M', u'嗀'), + (0xF9B3, 'M', '靈'), + (0xF9B4, 'M', '領'), + (0xF9B5, 'M', '例'), + (0xF9B6, 'M', '禮'), + (0xF9B7, 'M', '醴'), + (0xF9B8, 'M', '隸'), + (0xF9B9, 'M', '惡'), + (0xF9BA, 'M', '了'), + (0xF9BB, 'M', '僚'), + (0xF9BC, 'M', '寮'), + (0xF9BD, 'M', '尿'), + (0xF9BE, 'M', '料'), + (0xF9BF, 'M', '樂'), + (0xF9C0, 'M', '燎'), + (0xF9C1, 'M', '療'), + (0xF9C2, 'M', '蓼'), + (0xF9C3, 'M', '遼'), + (0xF9C4, 'M', '龍'), + (0xF9C5, 'M', '暈'), + (0xF9C6, 'M', '阮'), + (0xF9C7, 'M', '劉'), + (0xF9C8, 'M', '杻'), + (0xF9C9, 'M', '柳'), + (0xF9CA, 'M', '流'), + (0xF9CB, 'M', '溜'), + (0xF9CC, 'M', '琉'), + (0xF9CD, 'M', '留'), + (0xF9CE, 'M', '硫'), + (0xF9CF, 'M', '紐'), + (0xF9D0, 'M', '類'), + (0xF9D1, 'M', '六'), + (0xF9D2, 'M', '戮'), + (0xF9D3, 'M', '陸'), + (0xF9D4, 'M', '倫'), + (0xF9D5, 'M', '崙'), + (0xF9D6, 'M', '淪'), + (0xF9D7, 'M', '輪'), + (0xF9D8, 'M', '律'), + (0xF9D9, 'M', '慄'), + (0xF9DA, 'M', '栗'), + (0xF9DB, 'M', '率'), + (0xF9DC, 'M', '隆'), + (0xF9DD, 'M', '利'), + (0xF9DE, 'M', '吏'), + (0xF9DF, 'M', '履'), + (0xF9E0, 'M', '易'), + (0xF9E1, 'M', '李'), + (0xF9E2, 'M', '梨'), + (0xF9E3, 'M', '泥'), + (0xF9E4, 'M', '理'), + (0xF9E5, 'M', '痢'), + (0xF9E6, 'M', '罹'), + (0xF9E7, 'M', '裏'), + (0xF9E8, 'M', '裡'), + (0xF9E9, 'M', '里'), + (0xF9EA, 'M', '離'), + (0xF9EB, 'M', '匿'), + (0xF9EC, 'M', '溺'), + (0xF9ED, 'M', '吝'), + (0xF9EE, 'M', '燐'), + (0xF9EF, 'M', '璘'), + (0xF9F0, 'M', '藺'), + (0xF9F1, 'M', '隣'), + (0xF9F2, 'M', '鱗'), + (0xF9F3, 'M', '麟'), + (0xF9F4, 'M', '林'), + (0xF9F5, 'M', '淋'), + (0xF9F6, 'M', '臨'), + (0xF9F7, 'M', '立'), + (0xF9F8, 'M', '笠'), + (0xF9F9, 'M', '粒'), + (0xF9FA, 'M', '狀'), + (0xF9FB, 'M', '炙'), + (0xF9FC, 'M', '識'), + (0xF9FD, 'M', '什'), + (0xF9FE, 'M', '茶'), + (0xF9FF, 'M', '刺'), + (0xFA00, 'M', '切'), + (0xFA01, 'M', '度'), + (0xFA02, 'M', '拓'), + (0xFA03, 'M', '糖'), + (0xFA04, 'M', '宅'), + (0xFA05, 'M', '洞'), + (0xFA06, 'M', '暴'), + (0xFA07, 'M', '輻'), + (0xFA08, 'M', '行'), + (0xFA09, 'M', '降'), + (0xFA0A, 'M', '見'), + (0xFA0B, 'M', '廓'), + (0xFA0C, 'M', '兀'), + (0xFA0D, 'M', '嗀'), (0xFA0E, 'V'), - (0xFA10, 'M', u'塚'), + (0xFA10, 'M', '塚'), (0xFA11, 'V'), - (0xFA12, 'M', u'晴'), + (0xFA12, 'M', '晴'), (0xFA13, 'V'), - (0xFA15, 'M', u'凞'), - (0xFA16, 'M', u'猪'), - (0xFA17, 'M', u'益'), - (0xFA18, 'M', u'礼'), + (0xFA15, 'M', '凞'), + (0xFA16, 'M', '猪'), + (0xFA17, 'M', '益'), + (0xFA18, 'M', '礼'), ] def _seg_42(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFA19, 'M', u'神'), - (0xFA1A, 'M', u'祥'), - (0xFA1B, 'M', u'福'), - (0xFA1C, 'M', u'靖'), - (0xFA1D, 'M', u'精'), - (0xFA1E, 'M', u'羽'), + (0xFA19, 'M', '神'), + (0xFA1A, 'M', '祥'), + (0xFA1B, 'M', '福'), + (0xFA1C, 'M', '靖'), + (0xFA1D, 'M', '精'), + (0xFA1E, 'M', '羽'), (0xFA1F, 'V'), - (0xFA20, 'M', u'蘒'), + (0xFA20, 'M', '蘒'), (0xFA21, 'V'), - (0xFA22, 'M', u'諸'), + (0xFA22, 'M', '諸'), (0xFA23, 'V'), - (0xFA25, 'M', u'逸'), - (0xFA26, 'M', u'都'), + (0xFA25, 'M', '逸'), + (0xFA26, 'M', '都'), (0xFA27, 'V'), - (0xFA2A, 'M', u'飯'), - (0xFA2B, 'M', u'飼'), - (0xFA2C, 'M', u'館'), - (0xFA2D, 'M', u'鶴'), - (0xFA2E, 'M', u'郞'), - (0xFA2F, 'M', u'隷'), - (0xFA30, 'M', u'侮'), - (0xFA31, 'M', u'僧'), - (0xFA32, 'M', u'免'), - (0xFA33, 'M', u'勉'), - (0xFA34, 'M', u'勤'), - (0xFA35, 'M', u'卑'), - (0xFA36, 'M', u'喝'), - (0xFA37, 'M', u'嘆'), - (0xFA38, 'M', u'器'), - (0xFA39, 'M', u'塀'), - (0xFA3A, 'M', u'墨'), - (0xFA3B, 'M', u'層'), - (0xFA3C, 'M', u'屮'), - (0xFA3D, 'M', u'悔'), - (0xFA3E, 'M', u'慨'), - (0xFA3F, 'M', u'憎'), - (0xFA40, 'M', u'懲'), - (0xFA41, 'M', u'敏'), - (0xFA42, 'M', u'既'), - (0xFA43, 'M', u'暑'), - (0xFA44, 'M', u'梅'), - (0xFA45, 'M', u'海'), - (0xFA46, 'M', u'渚'), - (0xFA47, 'M', u'漢'), - (0xFA48, 'M', u'煮'), - (0xFA49, 'M', u'爫'), - (0xFA4A, 'M', u'琢'), - (0xFA4B, 'M', u'碑'), - (0xFA4C, 'M', u'社'), - (0xFA4D, 'M', u'祉'), - (0xFA4E, 'M', u'祈'), - (0xFA4F, 'M', u'祐'), - (0xFA50, 'M', u'祖'), - (0xFA51, 'M', u'祝'), - (0xFA52, 'M', u'禍'), - (0xFA53, 'M', u'禎'), - (0xFA54, 'M', u'穀'), - (0xFA55, 'M', u'突'), - (0xFA56, 'M', u'節'), - (0xFA57, 'M', u'練'), - (0xFA58, 'M', u'縉'), - (0xFA59, 'M', u'繁'), - (0xFA5A, 'M', u'署'), - (0xFA5B, 'M', u'者'), - (0xFA5C, 'M', u'臭'), - (0xFA5D, 'M', u'艹'), - (0xFA5F, 'M', u'著'), - (0xFA60, 'M', u'褐'), - (0xFA61, 'M', u'視'), - (0xFA62, 'M', u'謁'), - (0xFA63, 'M', u'謹'), - (0xFA64, 'M', u'賓'), - (0xFA65, 'M', u'贈'), - (0xFA66, 'M', u'辶'), - (0xFA67, 'M', u'逸'), - (0xFA68, 'M', u'難'), - (0xFA69, 'M', u'響'), - (0xFA6A, 'M', u'頻'), - (0xFA6B, 'M', u'恵'), - (0xFA6C, 'M', u'𤋮'), - (0xFA6D, 'M', u'舘'), + (0xFA2A, 'M', '飯'), + (0xFA2B, 'M', '飼'), + (0xFA2C, 'M', '館'), + (0xFA2D, 'M', '鶴'), + (0xFA2E, 'M', '郞'), + (0xFA2F, 'M', '隷'), + (0xFA30, 'M', '侮'), + (0xFA31, 'M', '僧'), + (0xFA32, 'M', '免'), + (0xFA33, 'M', '勉'), + (0xFA34, 'M', '勤'), + (0xFA35, 'M', '卑'), + (0xFA36, 'M', '喝'), + (0xFA37, 'M', '嘆'), + (0xFA38, 'M', '器'), + (0xFA39, 'M', '塀'), + (0xFA3A, 'M', '墨'), + (0xFA3B, 'M', '層'), + (0xFA3C, 'M', '屮'), + (0xFA3D, 'M', '悔'), + (0xFA3E, 'M', '慨'), + (0xFA3F, 'M', '憎'), + (0xFA40, 'M', '懲'), + (0xFA41, 'M', '敏'), + (0xFA42, 'M', '既'), + (0xFA43, 'M', '暑'), + (0xFA44, 'M', '梅'), + (0xFA45, 'M', '海'), + (0xFA46, 'M', '渚'), + (0xFA47, 'M', '漢'), + (0xFA48, 'M', '煮'), + (0xFA49, 'M', '爫'), + (0xFA4A, 'M', '琢'), + (0xFA4B, 'M', '碑'), + (0xFA4C, 'M', '社'), + (0xFA4D, 'M', '祉'), + (0xFA4E, 'M', '祈'), + (0xFA4F, 'M', '祐'), + (0xFA50, 'M', '祖'), + (0xFA51, 'M', '祝'), + (0xFA52, 'M', '禍'), + (0xFA53, 'M', '禎'), + (0xFA54, 'M', '穀'), + (0xFA55, 'M', '突'), + (0xFA56, 'M', '節'), + (0xFA57, 'M', '練'), + (0xFA58, 'M', '縉'), + (0xFA59, 'M', '繁'), + (0xFA5A, 'M', '署'), + (0xFA5B, 'M', '者'), + (0xFA5C, 'M', '臭'), + (0xFA5D, 'M', '艹'), + (0xFA5F, 'M', '著'), + (0xFA60, 'M', '褐'), + (0xFA61, 'M', '視'), + (0xFA62, 'M', '謁'), + (0xFA63, 'M', '謹'), + (0xFA64, 'M', '賓'), + (0xFA65, 'M', '贈'), + (0xFA66, 'M', '辶'), + (0xFA67, 'M', '逸'), + (0xFA68, 'M', '難'), + (0xFA69, 'M', '響'), + (0xFA6A, 'M', '頻'), + (0xFA6B, 'M', '恵'), + (0xFA6C, 'M', '𤋮'), + (0xFA6D, 'M', '舘'), (0xFA6E, 'X'), - (0xFA70, 'M', u'並'), - (0xFA71, 'M', u'况'), - (0xFA72, 'M', u'全'), - (0xFA73, 'M', u'侀'), - (0xFA74, 'M', u'充'), - (0xFA75, 'M', u'冀'), - (0xFA76, 'M', u'勇'), - (0xFA77, 'M', u'勺'), - (0xFA78, 'M', u'喝'), - (0xFA79, 'M', u'啕'), - (0xFA7A, 'M', u'喙'), - (0xFA7B, 'M', u'嗢'), - (0xFA7C, 'M', u'塚'), - (0xFA7D, 'M', u'墳'), - (0xFA7E, 'M', u'奄'), - (0xFA7F, 'M', u'奔'), - (0xFA80, 'M', u'婢'), - (0xFA81, 'M', u'嬨'), + (0xFA70, 'M', '並'), + (0xFA71, 'M', '况'), + (0xFA72, 'M', '全'), + (0xFA73, 'M', '侀'), + (0xFA74, 'M', '充'), + (0xFA75, 'M', '冀'), + (0xFA76, 'M', '勇'), + (0xFA77, 'M', '勺'), + (0xFA78, 'M', '喝'), + (0xFA79, 'M', '啕'), + (0xFA7A, 'M', '喙'), + (0xFA7B, 'M', '嗢'), + (0xFA7C, 'M', '塚'), + (0xFA7D, 'M', '墳'), + (0xFA7E, 'M', '奄'), + (0xFA7F, 'M', '奔'), + (0xFA80, 'M', '婢'), + (0xFA81, 'M', '嬨'), ] def _seg_43(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFA82, 'M', u'廒'), - (0xFA83, 'M', u'廙'), - (0xFA84, 'M', u'彩'), - (0xFA85, 'M', u'徭'), - (0xFA86, 'M', u'惘'), - (0xFA87, 'M', u'慎'), - (0xFA88, 'M', u'愈'), - (0xFA89, 'M', u'憎'), - (0xFA8A, 'M', u'慠'), - (0xFA8B, 'M', u'懲'), - (0xFA8C, 'M', u'戴'), - (0xFA8D, 'M', u'揄'), - (0xFA8E, 'M', u'搜'), - (0xFA8F, 'M', u'摒'), - (0xFA90, 'M', u'敖'), - (0xFA91, 'M', u'晴'), - (0xFA92, 'M', u'朗'), - (0xFA93, 'M', u'望'), - (0xFA94, 'M', u'杖'), - (0xFA95, 'M', u'歹'), - (0xFA96, 'M', u'殺'), - (0xFA97, 'M', u'流'), - (0xFA98, 'M', u'滛'), - (0xFA99, 'M', u'滋'), - (0xFA9A, 'M', u'漢'), - (0xFA9B, 'M', u'瀞'), - (0xFA9C, 'M', u'煮'), - (0xFA9D, 'M', u'瞧'), - (0xFA9E, 'M', u'爵'), - (0xFA9F, 'M', u'犯'), - (0xFAA0, 'M', u'猪'), - (0xFAA1, 'M', u'瑱'), - (0xFAA2, 'M', u'甆'), - (0xFAA3, 'M', u'画'), - (0xFAA4, 'M', u'瘝'), - (0xFAA5, 'M', u'瘟'), - (0xFAA6, 'M', u'益'), - (0xFAA7, 'M', u'盛'), - (0xFAA8, 'M', u'直'), - (0xFAA9, 'M', u'睊'), - (0xFAAA, 'M', u'着'), - (0xFAAB, 'M', u'磌'), - (0xFAAC, 'M', u'窱'), - (0xFAAD, 'M', u'節'), - (0xFAAE, 'M', u'类'), - (0xFAAF, 'M', u'絛'), - (0xFAB0, 'M', u'練'), - (0xFAB1, 'M', u'缾'), - (0xFAB2, 'M', u'者'), - (0xFAB3, 'M', u'荒'), - (0xFAB4, 'M', u'華'), - (0xFAB5, 'M', u'蝹'), - (0xFAB6, 'M', u'襁'), - (0xFAB7, 'M', u'覆'), - (0xFAB8, 'M', u'視'), - (0xFAB9, 'M', u'調'), - (0xFABA, 'M', u'諸'), - (0xFABB, 'M', u'請'), - (0xFABC, 'M', u'謁'), - (0xFABD, 'M', u'諾'), - (0xFABE, 'M', u'諭'), - (0xFABF, 'M', u'謹'), - (0xFAC0, 'M', u'變'), - (0xFAC1, 'M', u'贈'), - (0xFAC2, 'M', u'輸'), - (0xFAC3, 'M', u'遲'), - (0xFAC4, 'M', u'醙'), - (0xFAC5, 'M', u'鉶'), - (0xFAC6, 'M', u'陼'), - (0xFAC7, 'M', u'難'), - (0xFAC8, 'M', u'靖'), - (0xFAC9, 'M', u'韛'), - (0xFACA, 'M', u'響'), - (0xFACB, 'M', u'頋'), - (0xFACC, 'M', u'頻'), - (0xFACD, 'M', u'鬒'), - (0xFACE, 'M', u'龜'), - (0xFACF, 'M', u'𢡊'), - (0xFAD0, 'M', u'𢡄'), - (0xFAD1, 'M', u'𣏕'), - (0xFAD2, 'M', u'㮝'), - (0xFAD3, 'M', u'䀘'), - (0xFAD4, 'M', u'䀹'), - (0xFAD5, 'M', u'𥉉'), - (0xFAD6, 'M', u'𥳐'), - (0xFAD7, 'M', u'𧻓'), - (0xFAD8, 'M', u'齃'), - (0xFAD9, 'M', u'龎'), + (0xFA82, 'M', '廒'), + (0xFA83, 'M', '廙'), + (0xFA84, 'M', '彩'), + (0xFA85, 'M', '徭'), + (0xFA86, 'M', '惘'), + (0xFA87, 'M', '慎'), + (0xFA88, 'M', '愈'), + (0xFA89, 'M', '憎'), + (0xFA8A, 'M', '慠'), + (0xFA8B, 'M', '懲'), + (0xFA8C, 'M', '戴'), + (0xFA8D, 'M', '揄'), + (0xFA8E, 'M', '搜'), + (0xFA8F, 'M', '摒'), + (0xFA90, 'M', '敖'), + (0xFA91, 'M', '晴'), + (0xFA92, 'M', '朗'), + (0xFA93, 'M', '望'), + (0xFA94, 'M', '杖'), + (0xFA95, 'M', '歹'), + (0xFA96, 'M', '殺'), + (0xFA97, 'M', '流'), + (0xFA98, 'M', '滛'), + (0xFA99, 'M', '滋'), + (0xFA9A, 'M', '漢'), + (0xFA9B, 'M', '瀞'), + (0xFA9C, 'M', '煮'), + (0xFA9D, 'M', '瞧'), + (0xFA9E, 'M', '爵'), + (0xFA9F, 'M', '犯'), + (0xFAA0, 'M', '猪'), + (0xFAA1, 'M', '瑱'), + (0xFAA2, 'M', '甆'), + (0xFAA3, 'M', '画'), + (0xFAA4, 'M', '瘝'), + (0xFAA5, 'M', '瘟'), + (0xFAA6, 'M', '益'), + (0xFAA7, 'M', '盛'), + (0xFAA8, 'M', '直'), + (0xFAA9, 'M', '睊'), + (0xFAAA, 'M', '着'), + (0xFAAB, 'M', '磌'), + (0xFAAC, 'M', '窱'), + (0xFAAD, 'M', '節'), + (0xFAAE, 'M', '类'), + (0xFAAF, 'M', '絛'), + (0xFAB0, 'M', '練'), + (0xFAB1, 'M', '缾'), + (0xFAB2, 'M', '者'), + (0xFAB3, 'M', '荒'), + (0xFAB4, 'M', '華'), + (0xFAB5, 'M', '蝹'), + (0xFAB6, 'M', '襁'), + (0xFAB7, 'M', '覆'), + (0xFAB8, 'M', '視'), + (0xFAB9, 'M', '調'), + (0xFABA, 'M', '諸'), + (0xFABB, 'M', '請'), + (0xFABC, 'M', '謁'), + (0xFABD, 'M', '諾'), + (0xFABE, 'M', '諭'), + (0xFABF, 'M', '謹'), + (0xFAC0, 'M', '變'), + (0xFAC1, 'M', '贈'), + (0xFAC2, 'M', '輸'), + (0xFAC3, 'M', '遲'), + (0xFAC4, 'M', '醙'), + (0xFAC5, 'M', '鉶'), + (0xFAC6, 'M', '陼'), + (0xFAC7, 'M', '難'), + (0xFAC8, 'M', '靖'), + (0xFAC9, 'M', '韛'), + (0xFACA, 'M', '響'), + (0xFACB, 'M', '頋'), + (0xFACC, 'M', '頻'), + (0xFACD, 'M', '鬒'), + (0xFACE, 'M', '龜'), + (0xFACF, 'M', '𢡊'), + (0xFAD0, 'M', '𢡄'), + (0xFAD1, 'M', '𣏕'), + (0xFAD2, 'M', '㮝'), + (0xFAD3, 'M', '䀘'), + (0xFAD4, 'M', '䀹'), + (0xFAD5, 'M', '𥉉'), + (0xFAD6, 'M', '𥳐'), + (0xFAD7, 'M', '𧻓'), + (0xFAD8, 'M', '齃'), + (0xFAD9, 'M', '龎'), (0xFADA, 'X'), - (0xFB00, 'M', u'ff'), - (0xFB01, 'M', u'fi'), - (0xFB02, 'M', u'fl'), - (0xFB03, 'M', u'ffi'), - (0xFB04, 'M', u'ffl'), - (0xFB05, 'M', u'st'), + (0xFB00, 'M', 'ff'), + (0xFB01, 'M', 'fi'), + (0xFB02, 'M', 'fl'), + (0xFB03, 'M', 'ffi'), + (0xFB04, 'M', 'ffl'), + (0xFB05, 'M', 'st'), (0xFB07, 'X'), - (0xFB13, 'M', u'մն'), - (0xFB14, 'M', u'մե'), - (0xFB15, 'M', u'մի'), - (0xFB16, 'M', u'վն'), + (0xFB13, 'M', 'մն'), + (0xFB14, 'M', 'մե'), + (0xFB15, 'M', 'մի'), + (0xFB16, 'M', 'վն'), ] def _seg_44(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFB17, 'M', u'մխ'), + (0xFB17, 'M', 'մխ'), (0xFB18, 'X'), - (0xFB1D, 'M', u'יִ'), + (0xFB1D, 'M', 'יִ'), (0xFB1E, 'V'), - (0xFB1F, 'M', u'ײַ'), - (0xFB20, 'M', u'ע'), - (0xFB21, 'M', u'א'), - (0xFB22, 'M', u'ד'), - (0xFB23, 'M', u'ה'), - (0xFB24, 'M', u'כ'), - (0xFB25, 'M', u'ל'), - (0xFB26, 'M', u'ם'), - (0xFB27, 'M', u'ר'), - (0xFB28, 'M', u'ת'), - (0xFB29, '3', u'+'), - (0xFB2A, 'M', u'שׁ'), - (0xFB2B, 'M', u'שׂ'), - (0xFB2C, 'M', u'שּׁ'), - (0xFB2D, 'M', u'שּׂ'), - (0xFB2E, 'M', u'אַ'), - (0xFB2F, 'M', u'אָ'), - (0xFB30, 'M', u'אּ'), - (0xFB31, 'M', u'בּ'), - (0xFB32, 'M', u'גּ'), - (0xFB33, 'M', u'דּ'), - (0xFB34, 'M', u'הּ'), - (0xFB35, 'M', u'וּ'), - (0xFB36, 'M', u'זּ'), + (0xFB1F, 'M', 'ײַ'), + (0xFB20, 'M', 'ע'), + (0xFB21, 'M', 'א'), + (0xFB22, 'M', 'ד'), + (0xFB23, 'M', 'ה'), + (0xFB24, 'M', 'כ'), + (0xFB25, 'M', 'ל'), + (0xFB26, 'M', 'ם'), + (0xFB27, 'M', 'ר'), + (0xFB28, 'M', 'ת'), + (0xFB29, '3', '+'), + (0xFB2A, 'M', 'שׁ'), + (0xFB2B, 'M', 'שׂ'), + (0xFB2C, 'M', 'שּׁ'), + (0xFB2D, 'M', 'שּׂ'), + (0xFB2E, 'M', 'אַ'), + (0xFB2F, 'M', 'אָ'), + (0xFB30, 'M', 'אּ'), + (0xFB31, 'M', 'בּ'), + (0xFB32, 'M', 'גּ'), + (0xFB33, 'M', 'דּ'), + (0xFB34, 'M', 'הּ'), + (0xFB35, 'M', 'וּ'), + (0xFB36, 'M', 'זּ'), (0xFB37, 'X'), - (0xFB38, 'M', u'טּ'), - (0xFB39, 'M', u'יּ'), - (0xFB3A, 'M', u'ךּ'), - (0xFB3B, 'M', u'כּ'), - (0xFB3C, 'M', u'לּ'), + (0xFB38, 'M', 'טּ'), + (0xFB39, 'M', 'יּ'), + (0xFB3A, 'M', 'ךּ'), + (0xFB3B, 'M', 'כּ'), + (0xFB3C, 'M', 'לּ'), (0xFB3D, 'X'), - (0xFB3E, 'M', u'מּ'), + (0xFB3E, 'M', 'מּ'), (0xFB3F, 'X'), - (0xFB40, 'M', u'נּ'), - (0xFB41, 'M', u'סּ'), + (0xFB40, 'M', 'נּ'), + (0xFB41, 'M', 'סּ'), (0xFB42, 'X'), - (0xFB43, 'M', u'ףּ'), - (0xFB44, 'M', u'פּ'), + (0xFB43, 'M', 'ףּ'), + (0xFB44, 'M', 'פּ'), (0xFB45, 'X'), - (0xFB46, 'M', u'צּ'), - (0xFB47, 'M', u'קּ'), - (0xFB48, 'M', u'רּ'), - (0xFB49, 'M', u'שּ'), - (0xFB4A, 'M', u'תּ'), - (0xFB4B, 'M', u'וֹ'), - (0xFB4C, 'M', u'בֿ'), - (0xFB4D, 'M', u'כֿ'), - (0xFB4E, 'M', u'פֿ'), - (0xFB4F, 'M', u'אל'), - (0xFB50, 'M', u'ٱ'), - (0xFB52, 'M', u'ٻ'), - (0xFB56, 'M', u'پ'), - (0xFB5A, 'M', u'ڀ'), - (0xFB5E, 'M', u'ٺ'), - (0xFB62, 'M', u'ٿ'), - (0xFB66, 'M', u'ٹ'), - (0xFB6A, 'M', u'ڤ'), - (0xFB6E, 'M', u'ڦ'), - (0xFB72, 'M', u'ڄ'), - (0xFB76, 'M', u'ڃ'), - (0xFB7A, 'M', u'چ'), - (0xFB7E, 'M', u'ڇ'), - (0xFB82, 'M', u'ڍ'), - (0xFB84, 'M', u'ڌ'), - (0xFB86, 'M', u'ڎ'), - (0xFB88, 'M', u'ڈ'), - (0xFB8A, 'M', u'ژ'), - (0xFB8C, 'M', u'ڑ'), - (0xFB8E, 'M', u'ک'), - (0xFB92, 'M', u'گ'), - (0xFB96, 'M', u'ڳ'), - (0xFB9A, 'M', u'ڱ'), - (0xFB9E, 'M', u'ں'), - (0xFBA0, 'M', u'ڻ'), - (0xFBA4, 'M', u'ۀ'), - (0xFBA6, 'M', u'ہ'), - (0xFBAA, 'M', u'ھ'), - (0xFBAE, 'M', u'ے'), - (0xFBB0, 'M', u'ۓ'), + (0xFB46, 'M', 'צּ'), + (0xFB47, 'M', 'קּ'), + (0xFB48, 'M', 'רּ'), + (0xFB49, 'M', 'שּ'), + (0xFB4A, 'M', 'תּ'), + (0xFB4B, 'M', 'וֹ'), + (0xFB4C, 'M', 'בֿ'), + (0xFB4D, 'M', 'כֿ'), + (0xFB4E, 'M', 'פֿ'), + (0xFB4F, 'M', 'אל'), + (0xFB50, 'M', 'ٱ'), + (0xFB52, 'M', 'ٻ'), + (0xFB56, 'M', 'پ'), + (0xFB5A, 'M', 'ڀ'), + (0xFB5E, 'M', 'ٺ'), + (0xFB62, 'M', 'ٿ'), + (0xFB66, 'M', 'ٹ'), + (0xFB6A, 'M', 'ڤ'), + (0xFB6E, 'M', 'ڦ'), + (0xFB72, 'M', 'ڄ'), + (0xFB76, 'M', 'ڃ'), + (0xFB7A, 'M', 'چ'), + (0xFB7E, 'M', 'ڇ'), + (0xFB82, 'M', 'ڍ'), + (0xFB84, 'M', 'ڌ'), + (0xFB86, 'M', 'ڎ'), + (0xFB88, 'M', 'ڈ'), + (0xFB8A, 'M', 'ژ'), + (0xFB8C, 'M', 'ڑ'), + (0xFB8E, 'M', 'ک'), + (0xFB92, 'M', 'گ'), + (0xFB96, 'M', 'ڳ'), + (0xFB9A, 'M', 'ڱ'), + (0xFB9E, 'M', 'ں'), + (0xFBA0, 'M', 'ڻ'), + (0xFBA4, 'M', 'ۀ'), + (0xFBA6, 'M', 'ہ'), + (0xFBAA, 'M', 'ھ'), + (0xFBAE, 'M', 'ے'), + (0xFBB0, 'M', 'ۓ'), (0xFBB2, 'V'), (0xFBC2, 'X'), - (0xFBD3, 'M', u'ڭ'), - (0xFBD7, 'M', u'ۇ'), - (0xFBD9, 'M', u'ۆ'), - (0xFBDB, 'M', u'ۈ'), - (0xFBDD, 'M', u'ۇٴ'), - (0xFBDE, 'M', u'ۋ'), - (0xFBE0, 'M', u'ۅ'), - (0xFBE2, 'M', u'ۉ'), - (0xFBE4, 'M', u'ې'), - (0xFBE8, 'M', u'ى'), - (0xFBEA, 'M', u'ئا'), - (0xFBEC, 'M', u'ئە'), - (0xFBEE, 'M', u'ئو'), - (0xFBF0, 'M', u'ئۇ'), - (0xFBF2, 'M', u'ئۆ'), + (0xFBD3, 'M', 'ڭ'), + (0xFBD7, 'M', 'ۇ'), + (0xFBD9, 'M', 'ۆ'), + (0xFBDB, 'M', 'ۈ'), + (0xFBDD, 'M', 'ۇٴ'), + (0xFBDE, 'M', 'ۋ'), + (0xFBE0, 'M', 'ۅ'), + (0xFBE2, 'M', 'ۉ'), + (0xFBE4, 'M', 'ې'), + (0xFBE8, 'M', 'ى'), + (0xFBEA, 'M', 'ئا'), + (0xFBEC, 'M', 'ئە'), + (0xFBEE, 'M', 'ئو'), + (0xFBF0, 'M', 'ئۇ'), + (0xFBF2, 'M', 'ئۆ'), ] def _seg_45(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFBF4, 'M', u'ئۈ'), - (0xFBF6, 'M', u'ئې'), - (0xFBF9, 'M', u'ئى'), - (0xFBFC, 'M', u'ی'), - (0xFC00, 'M', u'ئج'), - (0xFC01, 'M', u'ئح'), - (0xFC02, 'M', u'ئم'), - (0xFC03, 'M', u'ئى'), - (0xFC04, 'M', u'ئي'), - (0xFC05, 'M', u'بج'), - (0xFC06, 'M', u'بح'), - (0xFC07, 'M', u'بخ'), - (0xFC08, 'M', u'بم'), - (0xFC09, 'M', u'بى'), - (0xFC0A, 'M', u'بي'), - (0xFC0B, 'M', u'تج'), - (0xFC0C, 'M', u'تح'), - (0xFC0D, 'M', u'تخ'), - (0xFC0E, 'M', u'تم'), - (0xFC0F, 'M', u'تى'), - (0xFC10, 'M', u'تي'), - (0xFC11, 'M', u'ثج'), - (0xFC12, 'M', u'ثم'), - (0xFC13, 'M', u'ثى'), - (0xFC14, 'M', u'ثي'), - (0xFC15, 'M', u'جح'), - (0xFC16, 'M', u'جم'), - (0xFC17, 'M', u'حج'), - (0xFC18, 'M', u'حم'), - (0xFC19, 'M', u'خج'), - (0xFC1A, 'M', u'خح'), - (0xFC1B, 'M', u'خم'), - (0xFC1C, 'M', u'سج'), - (0xFC1D, 'M', u'سح'), - (0xFC1E, 'M', u'سخ'), - (0xFC1F, 'M', u'سم'), - (0xFC20, 'M', u'صح'), - (0xFC21, 'M', u'صم'), - (0xFC22, 'M', u'ضج'), - (0xFC23, 'M', u'ضح'), - (0xFC24, 'M', u'ضخ'), - (0xFC25, 'M', u'ضم'), - (0xFC26, 'M', u'طح'), - (0xFC27, 'M', u'طم'), - (0xFC28, 'M', u'ظم'), - (0xFC29, 'M', u'عج'), - (0xFC2A, 'M', u'عم'), - (0xFC2B, 'M', u'غج'), - (0xFC2C, 'M', u'غم'), - (0xFC2D, 'M', u'فج'), - (0xFC2E, 'M', u'فح'), - (0xFC2F, 'M', u'فخ'), - (0xFC30, 'M', u'فم'), - (0xFC31, 'M', u'فى'), - (0xFC32, 'M', u'في'), - (0xFC33, 'M', u'قح'), - (0xFC34, 'M', u'قم'), - (0xFC35, 'M', u'قى'), - (0xFC36, 'M', u'قي'), - (0xFC37, 'M', u'كا'), - (0xFC38, 'M', u'كج'), - (0xFC39, 'M', u'كح'), - (0xFC3A, 'M', u'كخ'), - (0xFC3B, 'M', u'كل'), - (0xFC3C, 'M', u'كم'), - (0xFC3D, 'M', u'كى'), - (0xFC3E, 'M', u'كي'), - (0xFC3F, 'M', u'لج'), - (0xFC40, 'M', u'لح'), - (0xFC41, 'M', u'لخ'), - (0xFC42, 'M', u'لم'), - (0xFC43, 'M', u'لى'), - (0xFC44, 'M', u'لي'), - (0xFC45, 'M', u'مج'), - (0xFC46, 'M', u'مح'), - (0xFC47, 'M', u'مخ'), - (0xFC48, 'M', u'مم'), - (0xFC49, 'M', u'مى'), - (0xFC4A, 'M', u'مي'), - (0xFC4B, 'M', u'نج'), - (0xFC4C, 'M', u'نح'), - (0xFC4D, 'M', u'نخ'), - (0xFC4E, 'M', u'نم'), - (0xFC4F, 'M', u'نى'), - (0xFC50, 'M', u'ني'), - (0xFC51, 'M', u'هج'), - (0xFC52, 'M', u'هم'), - (0xFC53, 'M', u'هى'), - (0xFC54, 'M', u'هي'), - (0xFC55, 'M', u'يج'), - (0xFC56, 'M', u'يح'), - (0xFC57, 'M', u'يخ'), - (0xFC58, 'M', u'يم'), - (0xFC59, 'M', u'يى'), - (0xFC5A, 'M', u'يي'), - (0xFC5B, 'M', u'ذٰ'), - (0xFC5C, 'M', u'رٰ'), - (0xFC5D, 'M', u'ىٰ'), - (0xFC5E, '3', u' ٌّ'), - (0xFC5F, '3', u' ٍّ'), + (0xFBF4, 'M', 'ئۈ'), + (0xFBF6, 'M', 'ئې'), + (0xFBF9, 'M', 'ئى'), + (0xFBFC, 'M', 'ی'), + (0xFC00, 'M', 'ئج'), + (0xFC01, 'M', 'ئح'), + (0xFC02, 'M', 'ئم'), + (0xFC03, 'M', 'ئى'), + (0xFC04, 'M', 'ئي'), + (0xFC05, 'M', 'بج'), + (0xFC06, 'M', 'بح'), + (0xFC07, 'M', 'بخ'), + (0xFC08, 'M', 'بم'), + (0xFC09, 'M', 'بى'), + (0xFC0A, 'M', 'بي'), + (0xFC0B, 'M', 'تج'), + (0xFC0C, 'M', 'تح'), + (0xFC0D, 'M', 'تخ'), + (0xFC0E, 'M', 'تم'), + (0xFC0F, 'M', 'تى'), + (0xFC10, 'M', 'تي'), + (0xFC11, 'M', 'ثج'), + (0xFC12, 'M', 'ثم'), + (0xFC13, 'M', 'ثى'), + (0xFC14, 'M', 'ثي'), + (0xFC15, 'M', 'جح'), + (0xFC16, 'M', 'جم'), + (0xFC17, 'M', 'حج'), + (0xFC18, 'M', 'حم'), + (0xFC19, 'M', 'خج'), + (0xFC1A, 'M', 'خح'), + (0xFC1B, 'M', 'خم'), + (0xFC1C, 'M', 'سج'), + (0xFC1D, 'M', 'سح'), + (0xFC1E, 'M', 'سخ'), + (0xFC1F, 'M', 'سم'), + (0xFC20, 'M', 'صح'), + (0xFC21, 'M', 'صم'), + (0xFC22, 'M', 'ضج'), + (0xFC23, 'M', 'ضح'), + (0xFC24, 'M', 'ضخ'), + (0xFC25, 'M', 'ضم'), + (0xFC26, 'M', 'طح'), + (0xFC27, 'M', 'طم'), + (0xFC28, 'M', 'ظم'), + (0xFC29, 'M', 'عج'), + (0xFC2A, 'M', 'عم'), + (0xFC2B, 'M', 'غج'), + (0xFC2C, 'M', 'غم'), + (0xFC2D, 'M', 'فج'), + (0xFC2E, 'M', 'فح'), + (0xFC2F, 'M', 'فخ'), + (0xFC30, 'M', 'فم'), + (0xFC31, 'M', 'فى'), + (0xFC32, 'M', 'في'), + (0xFC33, 'M', 'قح'), + (0xFC34, 'M', 'قم'), + (0xFC35, 'M', 'قى'), + (0xFC36, 'M', 'قي'), + (0xFC37, 'M', 'كا'), + (0xFC38, 'M', 'كج'), + (0xFC39, 'M', 'كح'), + (0xFC3A, 'M', 'كخ'), + (0xFC3B, 'M', 'كل'), + (0xFC3C, 'M', 'كم'), + (0xFC3D, 'M', 'كى'), + (0xFC3E, 'M', 'كي'), + (0xFC3F, 'M', 'لج'), + (0xFC40, 'M', 'لح'), + (0xFC41, 'M', 'لخ'), + (0xFC42, 'M', 'لم'), + (0xFC43, 'M', 'لى'), + (0xFC44, 'M', 'لي'), + (0xFC45, 'M', 'مج'), + (0xFC46, 'M', 'مح'), + (0xFC47, 'M', 'مخ'), + (0xFC48, 'M', 'مم'), + (0xFC49, 'M', 'مى'), + (0xFC4A, 'M', 'مي'), + (0xFC4B, 'M', 'نج'), + (0xFC4C, 'M', 'نح'), + (0xFC4D, 'M', 'نخ'), + (0xFC4E, 'M', 'نم'), + (0xFC4F, 'M', 'نى'), + (0xFC50, 'M', 'ني'), + (0xFC51, 'M', 'هج'), + (0xFC52, 'M', 'هم'), + (0xFC53, 'M', 'هى'), + (0xFC54, 'M', 'هي'), + (0xFC55, 'M', 'يج'), + (0xFC56, 'M', 'يح'), + (0xFC57, 'M', 'يخ'), + (0xFC58, 'M', 'يم'), + (0xFC59, 'M', 'يى'), + (0xFC5A, 'M', 'يي'), + (0xFC5B, 'M', 'ذٰ'), + (0xFC5C, 'M', 'رٰ'), + (0xFC5D, 'M', 'ىٰ'), + (0xFC5E, '3', ' ٌّ'), + (0xFC5F, '3', ' ٍّ'), ] def _seg_46(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFC60, '3', u' َّ'), - (0xFC61, '3', u' ُّ'), - (0xFC62, '3', u' ِّ'), - (0xFC63, '3', u' ّٰ'), - (0xFC64, 'M', u'ئر'), - (0xFC65, 'M', u'ئز'), - (0xFC66, 'M', u'ئم'), - (0xFC67, 'M', u'ئن'), - (0xFC68, 'M', u'ئى'), - (0xFC69, 'M', u'ئي'), - (0xFC6A, 'M', u'بر'), - (0xFC6B, 'M', u'بز'), - (0xFC6C, 'M', u'بم'), - (0xFC6D, 'M', u'بن'), - (0xFC6E, 'M', u'بى'), - (0xFC6F, 'M', u'بي'), - (0xFC70, 'M', u'تر'), - (0xFC71, 'M', u'تز'), - (0xFC72, 'M', u'تم'), - (0xFC73, 'M', u'تن'), - (0xFC74, 'M', u'تى'), - (0xFC75, 'M', u'تي'), - (0xFC76, 'M', u'ثر'), - (0xFC77, 'M', u'ثز'), - (0xFC78, 'M', u'ثم'), - (0xFC79, 'M', u'ثن'), - (0xFC7A, 'M', u'ثى'), - (0xFC7B, 'M', u'ثي'), - (0xFC7C, 'M', u'فى'), - (0xFC7D, 'M', u'في'), - (0xFC7E, 'M', u'قى'), - (0xFC7F, 'M', u'قي'), - (0xFC80, 'M', u'كا'), - (0xFC81, 'M', u'كل'), - (0xFC82, 'M', u'كم'), - (0xFC83, 'M', u'كى'), - (0xFC84, 'M', u'كي'), - (0xFC85, 'M', u'لم'), - (0xFC86, 'M', u'لى'), - (0xFC87, 'M', u'لي'), - (0xFC88, 'M', u'ما'), - (0xFC89, 'M', u'مم'), - (0xFC8A, 'M', u'نر'), - (0xFC8B, 'M', u'نز'), - (0xFC8C, 'M', u'نم'), - (0xFC8D, 'M', u'نن'), - (0xFC8E, 'M', u'نى'), - (0xFC8F, 'M', u'ني'), - (0xFC90, 'M', u'ىٰ'), - (0xFC91, 'M', u'ير'), - (0xFC92, 'M', u'يز'), - (0xFC93, 'M', u'يم'), - (0xFC94, 'M', u'ين'), - (0xFC95, 'M', u'يى'), - (0xFC96, 'M', u'يي'), - (0xFC97, 'M', u'ئج'), - (0xFC98, 'M', u'ئح'), - (0xFC99, 'M', u'ئخ'), - (0xFC9A, 'M', u'ئم'), - (0xFC9B, 'M', u'ئه'), - (0xFC9C, 'M', u'بج'), - (0xFC9D, 'M', u'بح'), - (0xFC9E, 'M', u'بخ'), - (0xFC9F, 'M', u'بم'), - (0xFCA0, 'M', u'به'), - (0xFCA1, 'M', u'تج'), - (0xFCA2, 'M', u'تح'), - (0xFCA3, 'M', u'تخ'), - (0xFCA4, 'M', u'تم'), - (0xFCA5, 'M', u'ته'), - (0xFCA6, 'M', u'ثم'), - (0xFCA7, 'M', u'جح'), - (0xFCA8, 'M', u'جم'), - (0xFCA9, 'M', u'حج'), - (0xFCAA, 'M', u'حم'), - (0xFCAB, 'M', u'خج'), - (0xFCAC, 'M', u'خم'), - (0xFCAD, 'M', u'سج'), - (0xFCAE, 'M', u'سح'), - (0xFCAF, 'M', u'سخ'), - (0xFCB0, 'M', u'سم'), - (0xFCB1, 'M', u'صح'), - (0xFCB2, 'M', u'صخ'), - (0xFCB3, 'M', u'صم'), - (0xFCB4, 'M', u'ضج'), - (0xFCB5, 'M', u'ضح'), - (0xFCB6, 'M', u'ضخ'), - (0xFCB7, 'M', u'ضم'), - (0xFCB8, 'M', u'طح'), - (0xFCB9, 'M', u'ظم'), - (0xFCBA, 'M', u'عج'), - (0xFCBB, 'M', u'عم'), - (0xFCBC, 'M', u'غج'), - (0xFCBD, 'M', u'غم'), - (0xFCBE, 'M', u'فج'), - (0xFCBF, 'M', u'فح'), - (0xFCC0, 'M', u'فخ'), - (0xFCC1, 'M', u'فم'), - (0xFCC2, 'M', u'قح'), - (0xFCC3, 'M', u'قم'), + (0xFC60, '3', ' َّ'), + (0xFC61, '3', ' ُّ'), + (0xFC62, '3', ' ِّ'), + (0xFC63, '3', ' ّٰ'), + (0xFC64, 'M', 'ئر'), + (0xFC65, 'M', 'ئز'), + (0xFC66, 'M', 'ئم'), + (0xFC67, 'M', 'ئن'), + (0xFC68, 'M', 'ئى'), + (0xFC69, 'M', 'ئي'), + (0xFC6A, 'M', 'بر'), + (0xFC6B, 'M', 'بز'), + (0xFC6C, 'M', 'بم'), + (0xFC6D, 'M', 'بن'), + (0xFC6E, 'M', 'بى'), + (0xFC6F, 'M', 'بي'), + (0xFC70, 'M', 'تر'), + (0xFC71, 'M', 'تز'), + (0xFC72, 'M', 'تم'), + (0xFC73, 'M', 'تن'), + (0xFC74, 'M', 'تى'), + (0xFC75, 'M', 'تي'), + (0xFC76, 'M', 'ثر'), + (0xFC77, 'M', 'ثز'), + (0xFC78, 'M', 'ثم'), + (0xFC79, 'M', 'ثن'), + (0xFC7A, 'M', 'ثى'), + (0xFC7B, 'M', 'ثي'), + (0xFC7C, 'M', 'فى'), + (0xFC7D, 'M', 'في'), + (0xFC7E, 'M', 'قى'), + (0xFC7F, 'M', 'قي'), + (0xFC80, 'M', 'كا'), + (0xFC81, 'M', 'كل'), + (0xFC82, 'M', 'كم'), + (0xFC83, 'M', 'كى'), + (0xFC84, 'M', 'كي'), + (0xFC85, 'M', 'لم'), + (0xFC86, 'M', 'لى'), + (0xFC87, 'M', 'لي'), + (0xFC88, 'M', 'ما'), + (0xFC89, 'M', 'مم'), + (0xFC8A, 'M', 'نر'), + (0xFC8B, 'M', 'نز'), + (0xFC8C, 'M', 'نم'), + (0xFC8D, 'M', 'نن'), + (0xFC8E, 'M', 'نى'), + (0xFC8F, 'M', 'ني'), + (0xFC90, 'M', 'ىٰ'), + (0xFC91, 'M', 'ير'), + (0xFC92, 'M', 'يز'), + (0xFC93, 'M', 'يم'), + (0xFC94, 'M', 'ين'), + (0xFC95, 'M', 'يى'), + (0xFC96, 'M', 'يي'), + (0xFC97, 'M', 'ئج'), + (0xFC98, 'M', 'ئح'), + (0xFC99, 'M', 'ئخ'), + (0xFC9A, 'M', 'ئم'), + (0xFC9B, 'M', 'ئه'), + (0xFC9C, 'M', 'بج'), + (0xFC9D, 'M', 'بح'), + (0xFC9E, 'M', 'بخ'), + (0xFC9F, 'M', 'بم'), + (0xFCA0, 'M', 'به'), + (0xFCA1, 'M', 'تج'), + (0xFCA2, 'M', 'تح'), + (0xFCA3, 'M', 'تخ'), + (0xFCA4, 'M', 'تم'), + (0xFCA5, 'M', 'ته'), + (0xFCA6, 'M', 'ثم'), + (0xFCA7, 'M', 'جح'), + (0xFCA8, 'M', 'جم'), + (0xFCA9, 'M', 'حج'), + (0xFCAA, 'M', 'حم'), + (0xFCAB, 'M', 'خج'), + (0xFCAC, 'M', 'خم'), + (0xFCAD, 'M', 'سج'), + (0xFCAE, 'M', 'سح'), + (0xFCAF, 'M', 'سخ'), + (0xFCB0, 'M', 'سم'), + (0xFCB1, 'M', 'صح'), + (0xFCB2, 'M', 'صخ'), + (0xFCB3, 'M', 'صم'), + (0xFCB4, 'M', 'ضج'), + (0xFCB5, 'M', 'ضح'), + (0xFCB6, 'M', 'ضخ'), + (0xFCB7, 'M', 'ضم'), + (0xFCB8, 'M', 'طح'), + (0xFCB9, 'M', 'ظم'), + (0xFCBA, 'M', 'عج'), + (0xFCBB, 'M', 'عم'), + (0xFCBC, 'M', 'غج'), + (0xFCBD, 'M', 'غم'), + (0xFCBE, 'M', 'فج'), + (0xFCBF, 'M', 'فح'), + (0xFCC0, 'M', 'فخ'), + (0xFCC1, 'M', 'فم'), + (0xFCC2, 'M', 'قح'), + (0xFCC3, 'M', 'قم'), ] def _seg_47(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFCC4, 'M', u'كج'), - (0xFCC5, 'M', u'كح'), - (0xFCC6, 'M', u'كخ'), - (0xFCC7, 'M', u'كل'), - (0xFCC8, 'M', u'كم'), - (0xFCC9, 'M', u'لج'), - (0xFCCA, 'M', u'لح'), - (0xFCCB, 'M', u'لخ'), - (0xFCCC, 'M', u'لم'), - (0xFCCD, 'M', u'له'), - (0xFCCE, 'M', u'مج'), - (0xFCCF, 'M', u'مح'), - (0xFCD0, 'M', u'مخ'), - (0xFCD1, 'M', u'مم'), - (0xFCD2, 'M', u'نج'), - (0xFCD3, 'M', u'نح'), - (0xFCD4, 'M', u'نخ'), - (0xFCD5, 'M', u'نم'), - (0xFCD6, 'M', u'نه'), - (0xFCD7, 'M', u'هج'), - (0xFCD8, 'M', u'هم'), - (0xFCD9, 'M', u'هٰ'), - (0xFCDA, 'M', u'يج'), - (0xFCDB, 'M', u'يح'), - (0xFCDC, 'M', u'يخ'), - (0xFCDD, 'M', u'يم'), - (0xFCDE, 'M', u'يه'), - (0xFCDF, 'M', u'ئم'), - (0xFCE0, 'M', u'ئه'), - (0xFCE1, 'M', u'بم'), - (0xFCE2, 'M', u'به'), - (0xFCE3, 'M', u'تم'), - (0xFCE4, 'M', u'ته'), - (0xFCE5, 'M', u'ثم'), - (0xFCE6, 'M', u'ثه'), - (0xFCE7, 'M', u'سم'), - (0xFCE8, 'M', u'سه'), - (0xFCE9, 'M', u'شم'), - (0xFCEA, 'M', u'شه'), - (0xFCEB, 'M', u'كل'), - (0xFCEC, 'M', u'كم'), - (0xFCED, 'M', u'لم'), - (0xFCEE, 'M', u'نم'), - (0xFCEF, 'M', u'نه'), - (0xFCF0, 'M', u'يم'), - (0xFCF1, 'M', u'يه'), - (0xFCF2, 'M', u'ـَّ'), - (0xFCF3, 'M', u'ـُّ'), - (0xFCF4, 'M', u'ـِّ'), - (0xFCF5, 'M', u'طى'), - (0xFCF6, 'M', u'طي'), - (0xFCF7, 'M', u'عى'), - (0xFCF8, 'M', u'عي'), - (0xFCF9, 'M', u'غى'), - (0xFCFA, 'M', u'غي'), - (0xFCFB, 'M', u'سى'), - (0xFCFC, 'M', u'سي'), - (0xFCFD, 'M', u'شى'), - (0xFCFE, 'M', u'شي'), - (0xFCFF, 'M', u'حى'), - (0xFD00, 'M', u'حي'), - (0xFD01, 'M', u'جى'), - (0xFD02, 'M', u'جي'), - (0xFD03, 'M', u'خى'), - (0xFD04, 'M', u'خي'), - (0xFD05, 'M', u'صى'), - (0xFD06, 'M', u'صي'), - (0xFD07, 'M', u'ضى'), - (0xFD08, 'M', u'ضي'), - (0xFD09, 'M', u'شج'), - (0xFD0A, 'M', u'شح'), - (0xFD0B, 'M', u'شخ'), - (0xFD0C, 'M', u'شم'), - (0xFD0D, 'M', u'شر'), - (0xFD0E, 'M', u'سر'), - (0xFD0F, 'M', u'صر'), - (0xFD10, 'M', u'ضر'), - (0xFD11, 'M', u'طى'), - (0xFD12, 'M', u'طي'), - (0xFD13, 'M', u'عى'), - (0xFD14, 'M', u'عي'), - (0xFD15, 'M', u'غى'), - (0xFD16, 'M', u'غي'), - (0xFD17, 'M', u'سى'), - (0xFD18, 'M', u'سي'), - (0xFD19, 'M', u'شى'), - (0xFD1A, 'M', u'شي'), - (0xFD1B, 'M', u'حى'), - (0xFD1C, 'M', u'حي'), - (0xFD1D, 'M', u'جى'), - (0xFD1E, 'M', u'جي'), - (0xFD1F, 'M', u'خى'), - (0xFD20, 'M', u'خي'), - (0xFD21, 'M', u'صى'), - (0xFD22, 'M', u'صي'), - (0xFD23, 'M', u'ضى'), - (0xFD24, 'M', u'ضي'), - (0xFD25, 'M', u'شج'), - (0xFD26, 'M', u'شح'), - (0xFD27, 'M', u'شخ'), + (0xFCC4, 'M', 'كج'), + (0xFCC5, 'M', 'كح'), + (0xFCC6, 'M', 'كخ'), + (0xFCC7, 'M', 'كل'), + (0xFCC8, 'M', 'كم'), + (0xFCC9, 'M', 'لج'), + (0xFCCA, 'M', 'لح'), + (0xFCCB, 'M', 'لخ'), + (0xFCCC, 'M', 'لم'), + (0xFCCD, 'M', 'له'), + (0xFCCE, 'M', 'مج'), + (0xFCCF, 'M', 'مح'), + (0xFCD0, 'M', 'مخ'), + (0xFCD1, 'M', 'مم'), + (0xFCD2, 'M', 'نج'), + (0xFCD3, 'M', 'نح'), + (0xFCD4, 'M', 'نخ'), + (0xFCD5, 'M', 'نم'), + (0xFCD6, 'M', 'نه'), + (0xFCD7, 'M', 'هج'), + (0xFCD8, 'M', 'هم'), + (0xFCD9, 'M', 'هٰ'), + (0xFCDA, 'M', 'يج'), + (0xFCDB, 'M', 'يح'), + (0xFCDC, 'M', 'يخ'), + (0xFCDD, 'M', 'يم'), + (0xFCDE, 'M', 'يه'), + (0xFCDF, 'M', 'ئم'), + (0xFCE0, 'M', 'ئه'), + (0xFCE1, 'M', 'بم'), + (0xFCE2, 'M', 'به'), + (0xFCE3, 'M', 'تم'), + (0xFCE4, 'M', 'ته'), + (0xFCE5, 'M', 'ثم'), + (0xFCE6, 'M', 'ثه'), + (0xFCE7, 'M', 'سم'), + (0xFCE8, 'M', 'سه'), + (0xFCE9, 'M', 'شم'), + (0xFCEA, 'M', 'شه'), + (0xFCEB, 'M', 'كل'), + (0xFCEC, 'M', 'كم'), + (0xFCED, 'M', 'لم'), + (0xFCEE, 'M', 'نم'), + (0xFCEF, 'M', 'نه'), + (0xFCF0, 'M', 'يم'), + (0xFCF1, 'M', 'يه'), + (0xFCF2, 'M', 'ـَّ'), + (0xFCF3, 'M', 'ـُّ'), + (0xFCF4, 'M', 'ـِّ'), + (0xFCF5, 'M', 'طى'), + (0xFCF6, 'M', 'طي'), + (0xFCF7, 'M', 'عى'), + (0xFCF8, 'M', 'عي'), + (0xFCF9, 'M', 'غى'), + (0xFCFA, 'M', 'غي'), + (0xFCFB, 'M', 'سى'), + (0xFCFC, 'M', 'سي'), + (0xFCFD, 'M', 'شى'), + (0xFCFE, 'M', 'شي'), + (0xFCFF, 'M', 'حى'), + (0xFD00, 'M', 'حي'), + (0xFD01, 'M', 'جى'), + (0xFD02, 'M', 'جي'), + (0xFD03, 'M', 'خى'), + (0xFD04, 'M', 'خي'), + (0xFD05, 'M', 'صى'), + (0xFD06, 'M', 'صي'), + (0xFD07, 'M', 'ضى'), + (0xFD08, 'M', 'ضي'), + (0xFD09, 'M', 'شج'), + (0xFD0A, 'M', 'شح'), + (0xFD0B, 'M', 'شخ'), + (0xFD0C, 'M', 'شم'), + (0xFD0D, 'M', 'شر'), + (0xFD0E, 'M', 'سر'), + (0xFD0F, 'M', 'صر'), + (0xFD10, 'M', 'ضر'), + (0xFD11, 'M', 'طى'), + (0xFD12, 'M', 'طي'), + (0xFD13, 'M', 'عى'), + (0xFD14, 'M', 'عي'), + (0xFD15, 'M', 'غى'), + (0xFD16, 'M', 'غي'), + (0xFD17, 'M', 'سى'), + (0xFD18, 'M', 'سي'), + (0xFD19, 'M', 'شى'), + (0xFD1A, 'M', 'شي'), + (0xFD1B, 'M', 'حى'), + (0xFD1C, 'M', 'حي'), + (0xFD1D, 'M', 'جى'), + (0xFD1E, 'M', 'جي'), + (0xFD1F, 'M', 'خى'), + (0xFD20, 'M', 'خي'), + (0xFD21, 'M', 'صى'), + (0xFD22, 'M', 'صي'), + (0xFD23, 'M', 'ضى'), + (0xFD24, 'M', 'ضي'), + (0xFD25, 'M', 'شج'), + (0xFD26, 'M', 'شح'), + (0xFD27, 'M', 'شخ'), ] def _seg_48(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFD28, 'M', u'شم'), - (0xFD29, 'M', u'شر'), - (0xFD2A, 'M', u'سر'), - (0xFD2B, 'M', u'صر'), - (0xFD2C, 'M', u'ضر'), - (0xFD2D, 'M', u'شج'), - (0xFD2E, 'M', u'شح'), - (0xFD2F, 'M', u'شخ'), - (0xFD30, 'M', u'شم'), - (0xFD31, 'M', u'سه'), - (0xFD32, 'M', u'شه'), - (0xFD33, 'M', u'طم'), - (0xFD34, 'M', u'سج'), - (0xFD35, 'M', u'سح'), - (0xFD36, 'M', u'سخ'), - (0xFD37, 'M', u'شج'), - (0xFD38, 'M', u'شح'), - (0xFD39, 'M', u'شخ'), - (0xFD3A, 'M', u'طم'), - (0xFD3B, 'M', u'ظم'), - (0xFD3C, 'M', u'اً'), + (0xFD28, 'M', 'شم'), + (0xFD29, 'M', 'شر'), + (0xFD2A, 'M', 'سر'), + (0xFD2B, 'M', 'صر'), + (0xFD2C, 'M', 'ضر'), + (0xFD2D, 'M', 'شج'), + (0xFD2E, 'M', 'شح'), + (0xFD2F, 'M', 'شخ'), + (0xFD30, 'M', 'شم'), + (0xFD31, 'M', 'سه'), + (0xFD32, 'M', 'شه'), + (0xFD33, 'M', 'طم'), + (0xFD34, 'M', 'سج'), + (0xFD35, 'M', 'سح'), + (0xFD36, 'M', 'سخ'), + (0xFD37, 'M', 'شج'), + (0xFD38, 'M', 'شح'), + (0xFD39, 'M', 'شخ'), + (0xFD3A, 'M', 'طم'), + (0xFD3B, 'M', 'ظم'), + (0xFD3C, 'M', 'اً'), (0xFD3E, 'V'), (0xFD40, 'X'), - (0xFD50, 'M', u'تجم'), - (0xFD51, 'M', u'تحج'), - (0xFD53, 'M', u'تحم'), - (0xFD54, 'M', u'تخم'), - (0xFD55, 'M', u'تمج'), - (0xFD56, 'M', u'تمح'), - (0xFD57, 'M', u'تمخ'), - (0xFD58, 'M', u'جمح'), - (0xFD5A, 'M', u'حمي'), - (0xFD5B, 'M', u'حمى'), - (0xFD5C, 'M', u'سحج'), - (0xFD5D, 'M', u'سجح'), - (0xFD5E, 'M', u'سجى'), - (0xFD5F, 'M', u'سمح'), - (0xFD61, 'M', u'سمج'), - (0xFD62, 'M', u'سمم'), - (0xFD64, 'M', u'صحح'), - (0xFD66, 'M', u'صمم'), - (0xFD67, 'M', u'شحم'), - (0xFD69, 'M', u'شجي'), - (0xFD6A, 'M', u'شمخ'), - (0xFD6C, 'M', u'شمم'), - (0xFD6E, 'M', u'ضحى'), - (0xFD6F, 'M', u'ضخم'), - (0xFD71, 'M', u'طمح'), - (0xFD73, 'M', u'طمم'), - (0xFD74, 'M', u'طمي'), - (0xFD75, 'M', u'عجم'), - (0xFD76, 'M', u'عمم'), - (0xFD78, 'M', u'عمى'), - (0xFD79, 'M', u'غمم'), - (0xFD7A, 'M', u'غمي'), - (0xFD7B, 'M', u'غمى'), - (0xFD7C, 'M', u'فخم'), - (0xFD7E, 'M', u'قمح'), - (0xFD7F, 'M', u'قمم'), - (0xFD80, 'M', u'لحم'), - (0xFD81, 'M', u'لحي'), - (0xFD82, 'M', u'لحى'), - (0xFD83, 'M', u'لجج'), - (0xFD85, 'M', u'لخم'), - (0xFD87, 'M', u'لمح'), - (0xFD89, 'M', u'محج'), - (0xFD8A, 'M', u'محم'), - (0xFD8B, 'M', u'محي'), - (0xFD8C, 'M', u'مجح'), - (0xFD8D, 'M', u'مجم'), - (0xFD8E, 'M', u'مخج'), - (0xFD8F, 'M', u'مخم'), + (0xFD50, 'M', 'تجم'), + (0xFD51, 'M', 'تحج'), + (0xFD53, 'M', 'تحم'), + (0xFD54, 'M', 'تخم'), + (0xFD55, 'M', 'تمج'), + (0xFD56, 'M', 'تمح'), + (0xFD57, 'M', 'تمخ'), + (0xFD58, 'M', 'جمح'), + (0xFD5A, 'M', 'حمي'), + (0xFD5B, 'M', 'حمى'), + (0xFD5C, 'M', 'سحج'), + (0xFD5D, 'M', 'سجح'), + (0xFD5E, 'M', 'سجى'), + (0xFD5F, 'M', 'سمح'), + (0xFD61, 'M', 'سمج'), + (0xFD62, 'M', 'سمم'), + (0xFD64, 'M', 'صحح'), + (0xFD66, 'M', 'صمم'), + (0xFD67, 'M', 'شحم'), + (0xFD69, 'M', 'شجي'), + (0xFD6A, 'M', 'شمخ'), + (0xFD6C, 'M', 'شمم'), + (0xFD6E, 'M', 'ضحى'), + (0xFD6F, 'M', 'ضخم'), + (0xFD71, 'M', 'طمح'), + (0xFD73, 'M', 'طمم'), + (0xFD74, 'M', 'طمي'), + (0xFD75, 'M', 'عجم'), + (0xFD76, 'M', 'عمم'), + (0xFD78, 'M', 'عمى'), + (0xFD79, 'M', 'غمم'), + (0xFD7A, 'M', 'غمي'), + (0xFD7B, 'M', 'غمى'), + (0xFD7C, 'M', 'فخم'), + (0xFD7E, 'M', 'قمح'), + (0xFD7F, 'M', 'قمم'), + (0xFD80, 'M', 'لحم'), + (0xFD81, 'M', 'لحي'), + (0xFD82, 'M', 'لحى'), + (0xFD83, 'M', 'لجج'), + (0xFD85, 'M', 'لخم'), + (0xFD87, 'M', 'لمح'), + (0xFD89, 'M', 'محج'), + (0xFD8A, 'M', 'محم'), + (0xFD8B, 'M', 'محي'), + (0xFD8C, 'M', 'مجح'), + (0xFD8D, 'M', 'مجم'), + (0xFD8E, 'M', 'مخج'), + (0xFD8F, 'M', 'مخم'), (0xFD90, 'X'), - (0xFD92, 'M', u'مجخ'), - (0xFD93, 'M', u'همج'), - (0xFD94, 'M', u'همم'), - (0xFD95, 'M', u'نحم'), - (0xFD96, 'M', u'نحى'), - (0xFD97, 'M', u'نجم'), - (0xFD99, 'M', u'نجى'), - (0xFD9A, 'M', u'نمي'), - (0xFD9B, 'M', u'نمى'), - (0xFD9C, 'M', u'يمم'), - (0xFD9E, 'M', u'بخي'), - (0xFD9F, 'M', u'تجي'), - (0xFDA0, 'M', u'تجى'), - (0xFDA1, 'M', u'تخي'), - (0xFDA2, 'M', u'تخى'), - (0xFDA3, 'M', u'تمي'), - (0xFDA4, 'M', u'تمى'), - (0xFDA5, 'M', u'جمي'), - (0xFDA6, 'M', u'جحى'), - (0xFDA7, 'M', u'جمى'), - (0xFDA8, 'M', u'سخى'), - (0xFDA9, 'M', u'صحي'), - (0xFDAA, 'M', u'شحي'), - (0xFDAB, 'M', u'ضحي'), - (0xFDAC, 'M', u'لجي'), - (0xFDAD, 'M', u'لمي'), - (0xFDAE, 'M', u'يحي'), + (0xFD92, 'M', 'مجخ'), + (0xFD93, 'M', 'همج'), + (0xFD94, 'M', 'همم'), + (0xFD95, 'M', 'نحم'), + (0xFD96, 'M', 'نحى'), + (0xFD97, 'M', 'نجم'), + (0xFD99, 'M', 'نجى'), + (0xFD9A, 'M', 'نمي'), + (0xFD9B, 'M', 'نمى'), + (0xFD9C, 'M', 'يمم'), + (0xFD9E, 'M', 'بخي'), + (0xFD9F, 'M', 'تجي'), + (0xFDA0, 'M', 'تجى'), + (0xFDA1, 'M', 'تخي'), + (0xFDA2, 'M', 'تخى'), + (0xFDA3, 'M', 'تمي'), + (0xFDA4, 'M', 'تمى'), + (0xFDA5, 'M', 'جمي'), + (0xFDA6, 'M', 'جحى'), + (0xFDA7, 'M', 'جمى'), + (0xFDA8, 'M', 'سخى'), + (0xFDA9, 'M', 'صحي'), + (0xFDAA, 'M', 'شحي'), + (0xFDAB, 'M', 'ضحي'), + (0xFDAC, 'M', 'لجي'), + (0xFDAD, 'M', 'لمي'), + (0xFDAE, 'M', 'يحي'), ] def _seg_49(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFDAF, 'M', u'يجي'), - (0xFDB0, 'M', u'يمي'), - (0xFDB1, 'M', u'ممي'), - (0xFDB2, 'M', u'قمي'), - (0xFDB3, 'M', u'نحي'), - (0xFDB4, 'M', u'قمح'), - (0xFDB5, 'M', u'لحم'), - (0xFDB6, 'M', u'عمي'), - (0xFDB7, 'M', u'كمي'), - (0xFDB8, 'M', u'نجح'), - (0xFDB9, 'M', u'مخي'), - (0xFDBA, 'M', u'لجم'), - (0xFDBB, 'M', u'كمم'), - (0xFDBC, 'M', u'لجم'), - (0xFDBD, 'M', u'نجح'), - (0xFDBE, 'M', u'جحي'), - (0xFDBF, 'M', u'حجي'), - (0xFDC0, 'M', u'مجي'), - (0xFDC1, 'M', u'فمي'), - (0xFDC2, 'M', u'بحي'), - (0xFDC3, 'M', u'كمم'), - (0xFDC4, 'M', u'عجم'), - (0xFDC5, 'M', u'صمم'), - (0xFDC6, 'M', u'سخي'), - (0xFDC7, 'M', u'نجي'), + (0xFDAF, 'M', 'يجي'), + (0xFDB0, 'M', 'يمي'), + (0xFDB1, 'M', 'ممي'), + (0xFDB2, 'M', 'قمي'), + (0xFDB3, 'M', 'نحي'), + (0xFDB4, 'M', 'قمح'), + (0xFDB5, 'M', 'لحم'), + (0xFDB6, 'M', 'عمي'), + (0xFDB7, 'M', 'كمي'), + (0xFDB8, 'M', 'نجح'), + (0xFDB9, 'M', 'مخي'), + (0xFDBA, 'M', 'لجم'), + (0xFDBB, 'M', 'كمم'), + (0xFDBC, 'M', 'لجم'), + (0xFDBD, 'M', 'نجح'), + (0xFDBE, 'M', 'جحي'), + (0xFDBF, 'M', 'حجي'), + (0xFDC0, 'M', 'مجي'), + (0xFDC1, 'M', 'فمي'), + (0xFDC2, 'M', 'بحي'), + (0xFDC3, 'M', 'كمم'), + (0xFDC4, 'M', 'عجم'), + (0xFDC5, 'M', 'صمم'), + (0xFDC6, 'M', 'سخي'), + (0xFDC7, 'M', 'نجي'), (0xFDC8, 'X'), - (0xFDF0, 'M', u'صلے'), - (0xFDF1, 'M', u'قلے'), - (0xFDF2, 'M', u'الله'), - (0xFDF3, 'M', u'اكبر'), - (0xFDF4, 'M', u'محمد'), - (0xFDF5, 'M', u'صلعم'), - (0xFDF6, 'M', u'رسول'), - (0xFDF7, 'M', u'عليه'), - (0xFDF8, 'M', u'وسلم'), - (0xFDF9, 'M', u'صلى'), - (0xFDFA, '3', u'صلى الله عليه وسلم'), - (0xFDFB, '3', u'جل جلاله'), - (0xFDFC, 'M', u'ریال'), + (0xFDF0, 'M', 'صلے'), + (0xFDF1, 'M', 'قلے'), + (0xFDF2, 'M', 'الله'), + (0xFDF3, 'M', 'اكبر'), + (0xFDF4, 'M', 'محمد'), + (0xFDF5, 'M', 'صلعم'), + (0xFDF6, 'M', 'رسول'), + (0xFDF7, 'M', 'عليه'), + (0xFDF8, 'M', 'وسلم'), + (0xFDF9, 'M', 'صلى'), + (0xFDFA, '3', 'صلى الله عليه وسلم'), + (0xFDFB, '3', 'جل جلاله'), + (0xFDFC, 'M', 'ریال'), (0xFDFD, 'V'), (0xFDFE, 'X'), (0xFE00, 'I'), - (0xFE10, '3', u','), - (0xFE11, 'M', u'、'), + (0xFE10, '3', ','), + (0xFE11, 'M', '、'), (0xFE12, 'X'), - (0xFE13, '3', u':'), - (0xFE14, '3', u';'), - (0xFE15, '3', u'!'), - (0xFE16, '3', u'?'), - (0xFE17, 'M', u'〖'), - (0xFE18, 'M', u'〗'), + (0xFE13, '3', ':'), + (0xFE14, '3', ';'), + (0xFE15, '3', '!'), + (0xFE16, '3', '?'), + (0xFE17, 'M', '〖'), + (0xFE18, 'M', '〗'), (0xFE19, 'X'), (0xFE20, 'V'), (0xFE30, 'X'), - (0xFE31, 'M', u'—'), - (0xFE32, 'M', u'–'), - (0xFE33, '3', u'_'), - (0xFE35, '3', u'('), - (0xFE36, '3', u')'), - (0xFE37, '3', u'{'), - (0xFE38, '3', u'}'), - (0xFE39, 'M', u'〔'), - (0xFE3A, 'M', u'〕'), - (0xFE3B, 'M', u'【'), - (0xFE3C, 'M', u'】'), - (0xFE3D, 'M', u'《'), - (0xFE3E, 'M', u'》'), - (0xFE3F, 'M', u'〈'), - (0xFE40, 'M', u'〉'), - (0xFE41, 'M', u'「'), - (0xFE42, 'M', u'」'), - (0xFE43, 'M', u'『'), - (0xFE44, 'M', u'』'), + (0xFE31, 'M', '—'), + (0xFE32, 'M', '–'), + (0xFE33, '3', '_'), + (0xFE35, '3', '('), + (0xFE36, '3', ')'), + (0xFE37, '3', '{'), + (0xFE38, '3', '}'), + (0xFE39, 'M', '〔'), + (0xFE3A, 'M', '〕'), + (0xFE3B, 'M', '【'), + (0xFE3C, 'M', '】'), + (0xFE3D, 'M', '《'), + (0xFE3E, 'M', '》'), + (0xFE3F, 'M', '〈'), + (0xFE40, 'M', '〉'), + (0xFE41, 'M', '「'), + (0xFE42, 'M', '」'), + (0xFE43, 'M', '『'), + (0xFE44, 'M', '』'), (0xFE45, 'V'), - (0xFE47, '3', u'['), - (0xFE48, '3', u']'), - (0xFE49, '3', u' ̅'), - (0xFE4D, '3', u'_'), - (0xFE50, '3', u','), - (0xFE51, 'M', u'、'), + (0xFE47, '3', '['), + (0xFE48, '3', ']'), + (0xFE49, '3', ' ̅'), + (0xFE4D, '3', '_'), + (0xFE50, '3', ','), + (0xFE51, 'M', '、'), (0xFE52, 'X'), - (0xFE54, '3', u';'), - (0xFE55, '3', u':'), - (0xFE56, '3', u'?'), - (0xFE57, '3', u'!'), - (0xFE58, 'M', u'—'), - (0xFE59, '3', u'('), - (0xFE5A, '3', u')'), - (0xFE5B, '3', u'{'), - (0xFE5C, '3', u'}'), - (0xFE5D, 'M', u'〔'), - (0xFE5E, 'M', u'〕'), - (0xFE5F, '3', u'#'), - (0xFE60, '3', u'&'), - (0xFE61, '3', u'*'), - (0xFE62, '3', u'+'), - (0xFE63, 'M', u'-'), - (0xFE64, '3', u'<'), - (0xFE65, '3', u'>'), - (0xFE66, '3', u'='), + (0xFE54, '3', ';'), + (0xFE55, '3', ':'), + (0xFE56, '3', '?'), + (0xFE57, '3', '!'), + (0xFE58, 'M', '—'), + (0xFE59, '3', '('), + (0xFE5A, '3', ')'), + (0xFE5B, '3', '{'), + (0xFE5C, '3', '}'), + (0xFE5D, 'M', '〔'), + (0xFE5E, 'M', '〕'), + (0xFE5F, '3', '#'), + (0xFE60, '3', '&'), + (0xFE61, '3', '*'), + (0xFE62, '3', '+'), + (0xFE63, 'M', '-'), + (0xFE64, '3', '<'), + (0xFE65, '3', '>'), + (0xFE66, '3', '='), ] def _seg_50(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0xFE67, 'X'), - (0xFE68, '3', u'\\'), - (0xFE69, '3', u'$'), - (0xFE6A, '3', u'%'), - (0xFE6B, '3', u'@'), + (0xFE68, '3', '\\'), + (0xFE69, '3', '$'), + (0xFE6A, '3', '%'), + (0xFE6B, '3', '@'), (0xFE6C, 'X'), - (0xFE70, '3', u' ً'), - (0xFE71, 'M', u'ـً'), - (0xFE72, '3', u' ٌ'), + (0xFE70, '3', ' ً'), + (0xFE71, 'M', 'ـً'), + (0xFE72, '3', ' ٌ'), (0xFE73, 'V'), - (0xFE74, '3', u' ٍ'), + (0xFE74, '3', ' ٍ'), (0xFE75, 'X'), - (0xFE76, '3', u' َ'), - (0xFE77, 'M', u'ـَ'), - (0xFE78, '3', u' ُ'), - (0xFE79, 'M', u'ـُ'), - (0xFE7A, '3', u' ِ'), - (0xFE7B, 'M', u'ـِ'), - (0xFE7C, '3', u' ّ'), - (0xFE7D, 'M', u'ـّ'), - (0xFE7E, '3', u' ْ'), - (0xFE7F, 'M', u'ـْ'), - (0xFE80, 'M', u'ء'), - (0xFE81, 'M', u'آ'), - (0xFE83, 'M', u'أ'), - (0xFE85, 'M', u'ؤ'), - (0xFE87, 'M', u'إ'), - (0xFE89, 'M', u'ئ'), - (0xFE8D, 'M', u'ا'), - (0xFE8F, 'M', u'ب'), - (0xFE93, 'M', u'ة'), - (0xFE95, 'M', u'ت'), - (0xFE99, 'M', u'ث'), - (0xFE9D, 'M', u'ج'), - (0xFEA1, 'M', u'ح'), - (0xFEA5, 'M', u'خ'), - (0xFEA9, 'M', u'د'), - (0xFEAB, 'M', u'ذ'), - (0xFEAD, 'M', u'ر'), - (0xFEAF, 'M', u'ز'), - (0xFEB1, 'M', u'س'), - (0xFEB5, 'M', u'ش'), - (0xFEB9, 'M', u'ص'), - (0xFEBD, 'M', u'ض'), - (0xFEC1, 'M', u'ط'), - (0xFEC5, 'M', u'ظ'), - (0xFEC9, 'M', u'ع'), - (0xFECD, 'M', u'غ'), - (0xFED1, 'M', u'ف'), - (0xFED5, 'M', u'ق'), - (0xFED9, 'M', u'ك'), - (0xFEDD, 'M', u'ل'), - (0xFEE1, 'M', u'م'), - (0xFEE5, 'M', u'ن'), - (0xFEE9, 'M', u'ه'), - (0xFEED, 'M', u'و'), - (0xFEEF, 'M', u'ى'), - (0xFEF1, 'M', u'ي'), - (0xFEF5, 'M', u'لآ'), - (0xFEF7, 'M', u'لأ'), - (0xFEF9, 'M', u'لإ'), - (0xFEFB, 'M', u'لا'), + (0xFE76, '3', ' َ'), + (0xFE77, 'M', 'ـَ'), + (0xFE78, '3', ' ُ'), + (0xFE79, 'M', 'ـُ'), + (0xFE7A, '3', ' ِ'), + (0xFE7B, 'M', 'ـِ'), + (0xFE7C, '3', ' ّ'), + (0xFE7D, 'M', 'ـّ'), + (0xFE7E, '3', ' ْ'), + (0xFE7F, 'M', 'ـْ'), + (0xFE80, 'M', 'ء'), + (0xFE81, 'M', 'آ'), + (0xFE83, 'M', 'أ'), + (0xFE85, 'M', 'ؤ'), + (0xFE87, 'M', 'إ'), + (0xFE89, 'M', 'ئ'), + (0xFE8D, 'M', 'ا'), + (0xFE8F, 'M', 'ب'), + (0xFE93, 'M', 'ة'), + (0xFE95, 'M', 'ت'), + (0xFE99, 'M', 'ث'), + (0xFE9D, 'M', 'ج'), + (0xFEA1, 'M', 'ح'), + (0xFEA5, 'M', 'خ'), + (0xFEA9, 'M', 'د'), + (0xFEAB, 'M', 'ذ'), + (0xFEAD, 'M', 'ر'), + (0xFEAF, 'M', 'ز'), + (0xFEB1, 'M', 'س'), + (0xFEB5, 'M', 'ش'), + (0xFEB9, 'M', 'ص'), + (0xFEBD, 'M', 'ض'), + (0xFEC1, 'M', 'ط'), + (0xFEC5, 'M', 'ظ'), + (0xFEC9, 'M', 'ع'), + (0xFECD, 'M', 'غ'), + (0xFED1, 'M', 'ف'), + (0xFED5, 'M', 'ق'), + (0xFED9, 'M', 'ك'), + (0xFEDD, 'M', 'ل'), + (0xFEE1, 'M', 'م'), + (0xFEE5, 'M', 'ن'), + (0xFEE9, 'M', 'ه'), + (0xFEED, 'M', 'و'), + (0xFEEF, 'M', 'ى'), + (0xFEF1, 'M', 'ي'), + (0xFEF5, 'M', 'لآ'), + (0xFEF7, 'M', 'لأ'), + (0xFEF9, 'M', 'لإ'), + (0xFEFB, 'M', 'لا'), (0xFEFD, 'X'), (0xFEFF, 'I'), (0xFF00, 'X'), - (0xFF01, '3', u'!'), - (0xFF02, '3', u'"'), - (0xFF03, '3', u'#'), - (0xFF04, '3', u'$'), - (0xFF05, '3', u'%'), - (0xFF06, '3', u'&'), - (0xFF07, '3', u'\''), - (0xFF08, '3', u'('), - (0xFF09, '3', u')'), - (0xFF0A, '3', u'*'), - (0xFF0B, '3', u'+'), - (0xFF0C, '3', u','), - (0xFF0D, 'M', u'-'), - (0xFF0E, 'M', u'.'), - (0xFF0F, '3', u'/'), - (0xFF10, 'M', u'0'), - (0xFF11, 'M', u'1'), - (0xFF12, 'M', u'2'), - (0xFF13, 'M', u'3'), - (0xFF14, 'M', u'4'), - (0xFF15, 'M', u'5'), - (0xFF16, 'M', u'6'), - (0xFF17, 'M', u'7'), - (0xFF18, 'M', u'8'), - (0xFF19, 'M', u'9'), - (0xFF1A, '3', u':'), - (0xFF1B, '3', u';'), - (0xFF1C, '3', u'<'), - (0xFF1D, '3', u'='), - (0xFF1E, '3', u'>'), - (0xFF1F, '3', u'?'), - (0xFF20, '3', u'@'), - (0xFF21, 'M', u'a'), - (0xFF22, 'M', u'b'), - (0xFF23, 'M', u'c'), + (0xFF01, '3', '!'), + (0xFF02, '3', '"'), + (0xFF03, '3', '#'), + (0xFF04, '3', '$'), + (0xFF05, '3', '%'), + (0xFF06, '3', '&'), + (0xFF07, '3', '\''), + (0xFF08, '3', '('), + (0xFF09, '3', ')'), + (0xFF0A, '3', '*'), + (0xFF0B, '3', '+'), + (0xFF0C, '3', ','), + (0xFF0D, 'M', '-'), + (0xFF0E, 'M', '.'), + (0xFF0F, '3', '/'), + (0xFF10, 'M', '0'), + (0xFF11, 'M', '1'), + (0xFF12, 'M', '2'), + (0xFF13, 'M', '3'), + (0xFF14, 'M', '4'), + (0xFF15, 'M', '5'), + (0xFF16, 'M', '6'), + (0xFF17, 'M', '7'), + (0xFF18, 'M', '8'), + (0xFF19, 'M', '9'), + (0xFF1A, '3', ':'), + (0xFF1B, '3', ';'), + (0xFF1C, '3', '<'), + (0xFF1D, '3', '='), + (0xFF1E, '3', '>'), + (0xFF1F, '3', '?'), + (0xFF20, '3', '@'), + (0xFF21, 'M', 'a'), + (0xFF22, 'M', 'b'), + (0xFF23, 'M', 'c'), ] def _seg_51(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFF24, 'M', u'd'), - (0xFF25, 'M', u'e'), - (0xFF26, 'M', u'f'), - (0xFF27, 'M', u'g'), - (0xFF28, 'M', u'h'), - (0xFF29, 'M', u'i'), - (0xFF2A, 'M', u'j'), - (0xFF2B, 'M', u'k'), - (0xFF2C, 'M', u'l'), - (0xFF2D, 'M', u'm'), - (0xFF2E, 'M', u'n'), - (0xFF2F, 'M', u'o'), - (0xFF30, 'M', u'p'), - (0xFF31, 'M', u'q'), - (0xFF32, 'M', u'r'), - (0xFF33, 'M', u's'), - (0xFF34, 'M', u't'), - (0xFF35, 'M', u'u'), - (0xFF36, 'M', u'v'), - (0xFF37, 'M', u'w'), - (0xFF38, 'M', u'x'), - (0xFF39, 'M', u'y'), - (0xFF3A, 'M', u'z'), - (0xFF3B, '3', u'['), - (0xFF3C, '3', u'\\'), - (0xFF3D, '3', u']'), - (0xFF3E, '3', u'^'), - (0xFF3F, '3', u'_'), - (0xFF40, '3', u'`'), - (0xFF41, 'M', u'a'), - (0xFF42, 'M', u'b'), - (0xFF43, 'M', u'c'), - (0xFF44, 'M', u'd'), - (0xFF45, 'M', u'e'), - (0xFF46, 'M', u'f'), - (0xFF47, 'M', u'g'), - (0xFF48, 'M', u'h'), - (0xFF49, 'M', u'i'), - (0xFF4A, 'M', u'j'), - (0xFF4B, 'M', u'k'), - (0xFF4C, 'M', u'l'), - (0xFF4D, 'M', u'm'), - (0xFF4E, 'M', u'n'), - (0xFF4F, 'M', u'o'), - (0xFF50, 'M', u'p'), - (0xFF51, 'M', u'q'), - (0xFF52, 'M', u'r'), - (0xFF53, 'M', u's'), - (0xFF54, 'M', u't'), - (0xFF55, 'M', u'u'), - (0xFF56, 'M', u'v'), - (0xFF57, 'M', u'w'), - (0xFF58, 'M', u'x'), - (0xFF59, 'M', u'y'), - (0xFF5A, 'M', u'z'), - (0xFF5B, '3', u'{'), - (0xFF5C, '3', u'|'), - (0xFF5D, '3', u'}'), - (0xFF5E, '3', u'~'), - (0xFF5F, 'M', u'⦅'), - (0xFF60, 'M', u'⦆'), - (0xFF61, 'M', u'.'), - (0xFF62, 'M', u'「'), - (0xFF63, 'M', u'」'), - (0xFF64, 'M', u'、'), - (0xFF65, 'M', u'・'), - (0xFF66, 'M', u'ヲ'), - (0xFF67, 'M', u'ァ'), - (0xFF68, 'M', u'ィ'), - (0xFF69, 'M', u'ゥ'), - (0xFF6A, 'M', u'ェ'), - (0xFF6B, 'M', u'ォ'), - (0xFF6C, 'M', u'ャ'), - (0xFF6D, 'M', u'ュ'), - (0xFF6E, 'M', u'ョ'), - (0xFF6F, 'M', u'ッ'), - (0xFF70, 'M', u'ー'), - (0xFF71, 'M', u'ア'), - (0xFF72, 'M', u'イ'), - (0xFF73, 'M', u'ウ'), - (0xFF74, 'M', u'エ'), - (0xFF75, 'M', u'オ'), - (0xFF76, 'M', u'カ'), - (0xFF77, 'M', u'キ'), - (0xFF78, 'M', u'ク'), - (0xFF79, 'M', u'ケ'), - (0xFF7A, 'M', u'コ'), - (0xFF7B, 'M', u'サ'), - (0xFF7C, 'M', u'シ'), - (0xFF7D, 'M', u'ス'), - (0xFF7E, 'M', u'セ'), - (0xFF7F, 'M', u'ソ'), - (0xFF80, 'M', u'タ'), - (0xFF81, 'M', u'チ'), - (0xFF82, 'M', u'ツ'), - (0xFF83, 'M', u'テ'), - (0xFF84, 'M', u'ト'), - (0xFF85, 'M', u'ナ'), - (0xFF86, 'M', u'ニ'), - (0xFF87, 'M', u'ヌ'), + (0xFF24, 'M', 'd'), + (0xFF25, 'M', 'e'), + (0xFF26, 'M', 'f'), + (0xFF27, 'M', 'g'), + (0xFF28, 'M', 'h'), + (0xFF29, 'M', 'i'), + (0xFF2A, 'M', 'j'), + (0xFF2B, 'M', 'k'), + (0xFF2C, 'M', 'l'), + (0xFF2D, 'M', 'm'), + (0xFF2E, 'M', 'n'), + (0xFF2F, 'M', 'o'), + (0xFF30, 'M', 'p'), + (0xFF31, 'M', 'q'), + (0xFF32, 'M', 'r'), + (0xFF33, 'M', 's'), + (0xFF34, 'M', 't'), + (0xFF35, 'M', 'u'), + (0xFF36, 'M', 'v'), + (0xFF37, 'M', 'w'), + (0xFF38, 'M', 'x'), + (0xFF39, 'M', 'y'), + (0xFF3A, 'M', 'z'), + (0xFF3B, '3', '['), + (0xFF3C, '3', '\\'), + (0xFF3D, '3', ']'), + (0xFF3E, '3', '^'), + (0xFF3F, '3', '_'), + (0xFF40, '3', '`'), + (0xFF41, 'M', 'a'), + (0xFF42, 'M', 'b'), + (0xFF43, 'M', 'c'), + (0xFF44, 'M', 'd'), + (0xFF45, 'M', 'e'), + (0xFF46, 'M', 'f'), + (0xFF47, 'M', 'g'), + (0xFF48, 'M', 'h'), + (0xFF49, 'M', 'i'), + (0xFF4A, 'M', 'j'), + (0xFF4B, 'M', 'k'), + (0xFF4C, 'M', 'l'), + (0xFF4D, 'M', 'm'), + (0xFF4E, 'M', 'n'), + (0xFF4F, 'M', 'o'), + (0xFF50, 'M', 'p'), + (0xFF51, 'M', 'q'), + (0xFF52, 'M', 'r'), + (0xFF53, 'M', 's'), + (0xFF54, 'M', 't'), + (0xFF55, 'M', 'u'), + (0xFF56, 'M', 'v'), + (0xFF57, 'M', 'w'), + (0xFF58, 'M', 'x'), + (0xFF59, 'M', 'y'), + (0xFF5A, 'M', 'z'), + (0xFF5B, '3', '{'), + (0xFF5C, '3', '|'), + (0xFF5D, '3', '}'), + (0xFF5E, '3', '~'), + (0xFF5F, 'M', '⦅'), + (0xFF60, 'M', '⦆'), + (0xFF61, 'M', '.'), + (0xFF62, 'M', '「'), + (0xFF63, 'M', '」'), + (0xFF64, 'M', '、'), + (0xFF65, 'M', '・'), + (0xFF66, 'M', 'ヲ'), + (0xFF67, 'M', 'ァ'), + (0xFF68, 'M', 'ィ'), + (0xFF69, 'M', 'ゥ'), + (0xFF6A, 'M', 'ェ'), + (0xFF6B, 'M', 'ォ'), + (0xFF6C, 'M', 'ャ'), + (0xFF6D, 'M', 'ュ'), + (0xFF6E, 'M', 'ョ'), + (0xFF6F, 'M', 'ッ'), + (0xFF70, 'M', 'ー'), + (0xFF71, 'M', 'ア'), + (0xFF72, 'M', 'イ'), + (0xFF73, 'M', 'ウ'), + (0xFF74, 'M', 'エ'), + (0xFF75, 'M', 'オ'), + (0xFF76, 'M', 'カ'), + (0xFF77, 'M', 'キ'), + (0xFF78, 'M', 'ク'), + (0xFF79, 'M', 'ケ'), + (0xFF7A, 'M', 'コ'), + (0xFF7B, 'M', 'サ'), + (0xFF7C, 'M', 'シ'), + (0xFF7D, 'M', 'ス'), + (0xFF7E, 'M', 'セ'), + (0xFF7F, 'M', 'ソ'), + (0xFF80, 'M', 'タ'), + (0xFF81, 'M', 'チ'), + (0xFF82, 'M', 'ツ'), + (0xFF83, 'M', 'テ'), + (0xFF84, 'M', 'ト'), + (0xFF85, 'M', 'ナ'), + (0xFF86, 'M', 'ニ'), + (0xFF87, 'M', 'ヌ'), ] def _seg_52(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0xFF88, 'M', u'ネ'), - (0xFF89, 'M', u'ノ'), - (0xFF8A, 'M', u'ハ'), - (0xFF8B, 'M', u'ヒ'), - (0xFF8C, 'M', u'フ'), - (0xFF8D, 'M', u'ヘ'), - (0xFF8E, 'M', u'ホ'), - (0xFF8F, 'M', u'マ'), - (0xFF90, 'M', u'ミ'), - (0xFF91, 'M', u'ム'), - (0xFF92, 'M', u'メ'), - (0xFF93, 'M', u'モ'), - (0xFF94, 'M', u'ヤ'), - (0xFF95, 'M', u'ユ'), - (0xFF96, 'M', u'ヨ'), - (0xFF97, 'M', u'ラ'), - (0xFF98, 'M', u'リ'), - (0xFF99, 'M', u'ル'), - (0xFF9A, 'M', u'レ'), - (0xFF9B, 'M', u'ロ'), - (0xFF9C, 'M', u'ワ'), - (0xFF9D, 'M', u'ン'), - (0xFF9E, 'M', u'゙'), - (0xFF9F, 'M', u'゚'), + (0xFF88, 'M', 'ネ'), + (0xFF89, 'M', 'ノ'), + (0xFF8A, 'M', 'ハ'), + (0xFF8B, 'M', 'ヒ'), + (0xFF8C, 'M', 'フ'), + (0xFF8D, 'M', 'ヘ'), + (0xFF8E, 'M', 'ホ'), + (0xFF8F, 'M', 'マ'), + (0xFF90, 'M', 'ミ'), + (0xFF91, 'M', 'ム'), + (0xFF92, 'M', 'メ'), + (0xFF93, 'M', 'モ'), + (0xFF94, 'M', 'ヤ'), + (0xFF95, 'M', 'ユ'), + (0xFF96, 'M', 'ヨ'), + (0xFF97, 'M', 'ラ'), + (0xFF98, 'M', 'リ'), + (0xFF99, 'M', 'ル'), + (0xFF9A, 'M', 'レ'), + (0xFF9B, 'M', 'ロ'), + (0xFF9C, 'M', 'ワ'), + (0xFF9D, 'M', 'ン'), + (0xFF9E, 'M', '゙'), + (0xFF9F, 'M', '゚'), (0xFFA0, 'X'), - (0xFFA1, 'M', u'ᄀ'), - (0xFFA2, 'M', u'ᄁ'), - (0xFFA3, 'M', u'ᆪ'), - (0xFFA4, 'M', u'ᄂ'), - (0xFFA5, 'M', u'ᆬ'), - (0xFFA6, 'M', u'ᆭ'), - (0xFFA7, 'M', u'ᄃ'), - (0xFFA8, 'M', u'ᄄ'), - (0xFFA9, 'M', u'ᄅ'), - (0xFFAA, 'M', u'ᆰ'), - (0xFFAB, 'M', u'ᆱ'), - (0xFFAC, 'M', u'ᆲ'), - (0xFFAD, 'M', u'ᆳ'), - (0xFFAE, 'M', u'ᆴ'), - (0xFFAF, 'M', u'ᆵ'), - (0xFFB0, 'M', u'ᄚ'), - (0xFFB1, 'M', u'ᄆ'), - (0xFFB2, 'M', u'ᄇ'), - (0xFFB3, 'M', u'ᄈ'), - (0xFFB4, 'M', u'ᄡ'), - (0xFFB5, 'M', u'ᄉ'), - (0xFFB6, 'M', u'ᄊ'), - (0xFFB7, 'M', u'ᄋ'), - (0xFFB8, 'M', u'ᄌ'), - (0xFFB9, 'M', u'ᄍ'), - (0xFFBA, 'M', u'ᄎ'), - (0xFFBB, 'M', u'ᄏ'), - (0xFFBC, 'M', u'ᄐ'), - (0xFFBD, 'M', u'ᄑ'), - (0xFFBE, 'M', u'ᄒ'), + (0xFFA1, 'M', 'ᄀ'), + (0xFFA2, 'M', 'ᄁ'), + (0xFFA3, 'M', 'ᆪ'), + (0xFFA4, 'M', 'ᄂ'), + (0xFFA5, 'M', 'ᆬ'), + (0xFFA6, 'M', 'ᆭ'), + (0xFFA7, 'M', 'ᄃ'), + (0xFFA8, 'M', 'ᄄ'), + (0xFFA9, 'M', 'ᄅ'), + (0xFFAA, 'M', 'ᆰ'), + (0xFFAB, 'M', 'ᆱ'), + (0xFFAC, 'M', 'ᆲ'), + (0xFFAD, 'M', 'ᆳ'), + (0xFFAE, 'M', 'ᆴ'), + (0xFFAF, 'M', 'ᆵ'), + (0xFFB0, 'M', 'ᄚ'), + (0xFFB1, 'M', 'ᄆ'), + (0xFFB2, 'M', 'ᄇ'), + (0xFFB3, 'M', 'ᄈ'), + (0xFFB4, 'M', 'ᄡ'), + (0xFFB5, 'M', 'ᄉ'), + (0xFFB6, 'M', 'ᄊ'), + (0xFFB7, 'M', 'ᄋ'), + (0xFFB8, 'M', 'ᄌ'), + (0xFFB9, 'M', 'ᄍ'), + (0xFFBA, 'M', 'ᄎ'), + (0xFFBB, 'M', 'ᄏ'), + (0xFFBC, 'M', 'ᄐ'), + (0xFFBD, 'M', 'ᄑ'), + (0xFFBE, 'M', 'ᄒ'), (0xFFBF, 'X'), - (0xFFC2, 'M', u'ᅡ'), - (0xFFC3, 'M', u'ᅢ'), - (0xFFC4, 'M', u'ᅣ'), - (0xFFC5, 'M', u'ᅤ'), - (0xFFC6, 'M', u'ᅥ'), - (0xFFC7, 'M', u'ᅦ'), + (0xFFC2, 'M', 'ᅡ'), + (0xFFC3, 'M', 'ᅢ'), + (0xFFC4, 'M', 'ᅣ'), + (0xFFC5, 'M', 'ᅤ'), + (0xFFC6, 'M', 'ᅥ'), + (0xFFC7, 'M', 'ᅦ'), (0xFFC8, 'X'), - (0xFFCA, 'M', u'ᅧ'), - (0xFFCB, 'M', u'ᅨ'), - (0xFFCC, 'M', u'ᅩ'), - (0xFFCD, 'M', u'ᅪ'), - (0xFFCE, 'M', u'ᅫ'), - (0xFFCF, 'M', u'ᅬ'), + (0xFFCA, 'M', 'ᅧ'), + (0xFFCB, 'M', 'ᅨ'), + (0xFFCC, 'M', 'ᅩ'), + (0xFFCD, 'M', 'ᅪ'), + (0xFFCE, 'M', 'ᅫ'), + (0xFFCF, 'M', 'ᅬ'), (0xFFD0, 'X'), - (0xFFD2, 'M', u'ᅭ'), - (0xFFD3, 'M', u'ᅮ'), - (0xFFD4, 'M', u'ᅯ'), - (0xFFD5, 'M', u'ᅰ'), - (0xFFD6, 'M', u'ᅱ'), - (0xFFD7, 'M', u'ᅲ'), + (0xFFD2, 'M', 'ᅭ'), + (0xFFD3, 'M', 'ᅮ'), + (0xFFD4, 'M', 'ᅯ'), + (0xFFD5, 'M', 'ᅰ'), + (0xFFD6, 'M', 'ᅱ'), + (0xFFD7, 'M', 'ᅲ'), (0xFFD8, 'X'), - (0xFFDA, 'M', u'ᅳ'), - (0xFFDB, 'M', u'ᅴ'), - (0xFFDC, 'M', u'ᅵ'), + (0xFFDA, 'M', 'ᅳ'), + (0xFFDB, 'M', 'ᅴ'), + (0xFFDC, 'M', 'ᅵ'), (0xFFDD, 'X'), - (0xFFE0, 'M', u'¢'), - (0xFFE1, 'M', u'£'), - (0xFFE2, 'M', u'¬'), - (0xFFE3, '3', u' ̄'), - (0xFFE4, 'M', u'¦'), - (0xFFE5, 'M', u'¥'), - (0xFFE6, 'M', u'₩'), + (0xFFE0, 'M', '¢'), + (0xFFE1, 'M', '£'), + (0xFFE2, 'M', '¬'), + (0xFFE3, '3', ' ̄'), + (0xFFE4, 'M', '¦'), + (0xFFE5, 'M', '¥'), + (0xFFE6, 'M', '₩'), (0xFFE7, 'X'), - (0xFFE8, 'M', u'│'), - (0xFFE9, 'M', u'←'), - (0xFFEA, 'M', u'↑'), - (0xFFEB, 'M', u'→'), - (0xFFEC, 'M', u'↓'), - (0xFFED, 'M', u'■'), - (0xFFEE, 'M', u'○'), + (0xFFE8, 'M', '│'), + (0xFFE9, 'M', '←'), + (0xFFEA, 'M', '↑'), + (0xFFEB, 'M', '→'), + (0xFFEC, 'M', '↓'), + (0xFFED, 'M', '■'), + (0xFFEE, 'M', '○'), (0xFFEF, 'X'), (0x10000, 'V'), (0x1000C, 'X'), @@ -5518,6 +5572,7 @@ def _seg_52(): ] def _seg_53(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x10027, 'X'), (0x10028, 'V'), @@ -5560,90 +5615,91 @@ def _seg_53(): (0x103C4, 'X'), (0x103C8, 'V'), (0x103D6, 'X'), - (0x10400, 'M', u'𐐨'), - (0x10401, 'M', u'𐐩'), - (0x10402, 'M', u'𐐪'), - (0x10403, 'M', u'𐐫'), - (0x10404, 'M', u'𐐬'), - (0x10405, 'M', u'𐐭'), - (0x10406, 'M', u'𐐮'), - (0x10407, 'M', u'𐐯'), - (0x10408, 'M', u'𐐰'), - (0x10409, 'M', u'𐐱'), - (0x1040A, 'M', u'𐐲'), - (0x1040B, 'M', u'𐐳'), - (0x1040C, 'M', u'𐐴'), - (0x1040D, 'M', u'𐐵'), - (0x1040E, 'M', u'𐐶'), - (0x1040F, 'M', u'𐐷'), - (0x10410, 'M', u'𐐸'), - (0x10411, 'M', u'𐐹'), - (0x10412, 'M', u'𐐺'), - (0x10413, 'M', u'𐐻'), - (0x10414, 'M', u'𐐼'), - (0x10415, 'M', u'𐐽'), - (0x10416, 'M', u'𐐾'), - (0x10417, 'M', u'𐐿'), - (0x10418, 'M', u'𐑀'), - (0x10419, 'M', u'𐑁'), - (0x1041A, 'M', u'𐑂'), - (0x1041B, 'M', u'𐑃'), - (0x1041C, 'M', u'𐑄'), - (0x1041D, 'M', u'𐑅'), - (0x1041E, 'M', u'𐑆'), - (0x1041F, 'M', u'𐑇'), - (0x10420, 'M', u'𐑈'), - (0x10421, 'M', u'𐑉'), - (0x10422, 'M', u'𐑊'), - (0x10423, 'M', u'𐑋'), - (0x10424, 'M', u'𐑌'), - (0x10425, 'M', u'𐑍'), - (0x10426, 'M', u'𐑎'), - (0x10427, 'M', u'𐑏'), + (0x10400, 'M', '𐐨'), + (0x10401, 'M', '𐐩'), + (0x10402, 'M', '𐐪'), + (0x10403, 'M', '𐐫'), + (0x10404, 'M', '𐐬'), + (0x10405, 'M', '𐐭'), + (0x10406, 'M', '𐐮'), + (0x10407, 'M', '𐐯'), + (0x10408, 'M', '𐐰'), + (0x10409, 'M', '𐐱'), + (0x1040A, 'M', '𐐲'), + (0x1040B, 'M', '𐐳'), + (0x1040C, 'M', '𐐴'), + (0x1040D, 'M', '𐐵'), + (0x1040E, 'M', '𐐶'), + (0x1040F, 'M', '𐐷'), + (0x10410, 'M', '𐐸'), + (0x10411, 'M', '𐐹'), + (0x10412, 'M', '𐐺'), + (0x10413, 'M', '𐐻'), + (0x10414, 'M', '𐐼'), + (0x10415, 'M', '𐐽'), + (0x10416, 'M', '𐐾'), + (0x10417, 'M', '𐐿'), + (0x10418, 'M', '𐑀'), + (0x10419, 'M', '𐑁'), + (0x1041A, 'M', '𐑂'), + (0x1041B, 'M', '𐑃'), + (0x1041C, 'M', '𐑄'), + (0x1041D, 'M', '𐑅'), + (0x1041E, 'M', '𐑆'), + (0x1041F, 'M', '𐑇'), + (0x10420, 'M', '𐑈'), + (0x10421, 'M', '𐑉'), + (0x10422, 'M', '𐑊'), + (0x10423, 'M', '𐑋'), + (0x10424, 'M', '𐑌'), + (0x10425, 'M', '𐑍'), + (0x10426, 'M', '𐑎'), + (0x10427, 'M', '𐑏'), (0x10428, 'V'), (0x1049E, 'X'), (0x104A0, 'V'), (0x104AA, 'X'), - (0x104B0, 'M', u'𐓘'), - (0x104B1, 'M', u'𐓙'), - (0x104B2, 'M', u'𐓚'), - (0x104B3, 'M', u'𐓛'), - (0x104B4, 'M', u'𐓜'), - (0x104B5, 'M', u'𐓝'), - (0x104B6, 'M', u'𐓞'), - (0x104B7, 'M', u'𐓟'), - (0x104B8, 'M', u'𐓠'), - (0x104B9, 'M', u'𐓡'), - (0x104BA, 'M', u'𐓢'), - (0x104BB, 'M', u'𐓣'), - (0x104BC, 'M', u'𐓤'), - (0x104BD, 'M', u'𐓥'), - (0x104BE, 'M', u'𐓦'), + (0x104B0, 'M', '𐓘'), + (0x104B1, 'M', '𐓙'), + (0x104B2, 'M', '𐓚'), + (0x104B3, 'M', '𐓛'), + (0x104B4, 'M', '𐓜'), + (0x104B5, 'M', '𐓝'), + (0x104B6, 'M', '𐓞'), + (0x104B7, 'M', '𐓟'), + (0x104B8, 'M', '𐓠'), + (0x104B9, 'M', '𐓡'), + (0x104BA, 'M', '𐓢'), + (0x104BB, 'M', '𐓣'), + (0x104BC, 'M', '𐓤'), + (0x104BD, 'M', '𐓥'), + (0x104BE, 'M', '𐓦'), ] def _seg_54(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x104BF, 'M', u'𐓧'), - (0x104C0, 'M', u'𐓨'), - (0x104C1, 'M', u'𐓩'), - (0x104C2, 'M', u'𐓪'), - (0x104C3, 'M', u'𐓫'), - (0x104C4, 'M', u'𐓬'), - (0x104C5, 'M', u'𐓭'), - (0x104C6, 'M', u'𐓮'), - (0x104C7, 'M', u'𐓯'), - (0x104C8, 'M', u'𐓰'), - (0x104C9, 'M', u'𐓱'), - (0x104CA, 'M', u'𐓲'), - (0x104CB, 'M', u'𐓳'), - (0x104CC, 'M', u'𐓴'), - (0x104CD, 'M', u'𐓵'), - (0x104CE, 'M', u'𐓶'), - (0x104CF, 'M', u'𐓷'), - (0x104D0, 'M', u'𐓸'), - (0x104D1, 'M', u'𐓹'), - (0x104D2, 'M', u'𐓺'), - (0x104D3, 'M', u'𐓻'), + (0x104BF, 'M', '𐓧'), + (0x104C0, 'M', '𐓨'), + (0x104C1, 'M', '𐓩'), + (0x104C2, 'M', '𐓪'), + (0x104C3, 'M', '𐓫'), + (0x104C4, 'M', '𐓬'), + (0x104C5, 'M', '𐓭'), + (0x104C6, 'M', '𐓮'), + (0x104C7, 'M', '𐓯'), + (0x104C8, 'M', '𐓰'), + (0x104C9, 'M', '𐓱'), + (0x104CA, 'M', '𐓲'), + (0x104CB, 'M', '𐓳'), + (0x104CC, 'M', '𐓴'), + (0x104CD, 'M', '𐓵'), + (0x104CE, 'M', '𐓶'), + (0x104CF, 'M', '𐓷'), + (0x104D0, 'M', '𐓸'), + (0x104D1, 'M', '𐓹'), + (0x104D2, 'M', '𐓺'), + (0x104D3, 'M', '𐓻'), (0x104D4, 'X'), (0x104D8, 'V'), (0x104FC, 'X'), @@ -5726,60 +5782,61 @@ def _seg_54(): ] def _seg_55(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x10C00, 'V'), (0x10C49, 'X'), - (0x10C80, 'M', u'𐳀'), - (0x10C81, 'M', u'𐳁'), - (0x10C82, 'M', u'𐳂'), - (0x10C83, 'M', u'𐳃'), - (0x10C84, 'M', u'𐳄'), - (0x10C85, 'M', u'𐳅'), - (0x10C86, 'M', u'𐳆'), - (0x10C87, 'M', u'𐳇'), - (0x10C88, 'M', u'𐳈'), - (0x10C89, 'M', u'𐳉'), - (0x10C8A, 'M', u'𐳊'), - (0x10C8B, 'M', u'𐳋'), - (0x10C8C, 'M', u'𐳌'), - (0x10C8D, 'M', u'𐳍'), - (0x10C8E, 'M', u'𐳎'), - (0x10C8F, 'M', u'𐳏'), - (0x10C90, 'M', u'𐳐'), - (0x10C91, 'M', u'𐳑'), - (0x10C92, 'M', u'𐳒'), - (0x10C93, 'M', u'𐳓'), - (0x10C94, 'M', u'𐳔'), - (0x10C95, 'M', u'𐳕'), - (0x10C96, 'M', u'𐳖'), - (0x10C97, 'M', u'𐳗'), - (0x10C98, 'M', u'𐳘'), - (0x10C99, 'M', u'𐳙'), - (0x10C9A, 'M', u'𐳚'), - (0x10C9B, 'M', u'𐳛'), - (0x10C9C, 'M', u'𐳜'), - (0x10C9D, 'M', u'𐳝'), - (0x10C9E, 'M', u'𐳞'), - (0x10C9F, 'M', u'𐳟'), - (0x10CA0, 'M', u'𐳠'), - (0x10CA1, 'M', u'𐳡'), - (0x10CA2, 'M', u'𐳢'), - (0x10CA3, 'M', u'𐳣'), - (0x10CA4, 'M', u'𐳤'), - (0x10CA5, 'M', u'𐳥'), - (0x10CA6, 'M', u'𐳦'), - (0x10CA7, 'M', u'𐳧'), - (0x10CA8, 'M', u'𐳨'), - (0x10CA9, 'M', u'𐳩'), - (0x10CAA, 'M', u'𐳪'), - (0x10CAB, 'M', u'𐳫'), - (0x10CAC, 'M', u'𐳬'), - (0x10CAD, 'M', u'𐳭'), - (0x10CAE, 'M', u'𐳮'), - (0x10CAF, 'M', u'𐳯'), - (0x10CB0, 'M', u'𐳰'), - (0x10CB1, 'M', u'𐳱'), - (0x10CB2, 'M', u'𐳲'), + (0x10C80, 'M', '𐳀'), + (0x10C81, 'M', '𐳁'), + (0x10C82, 'M', '𐳂'), + (0x10C83, 'M', '𐳃'), + (0x10C84, 'M', '𐳄'), + (0x10C85, 'M', '𐳅'), + (0x10C86, 'M', '𐳆'), + (0x10C87, 'M', '𐳇'), + (0x10C88, 'M', '𐳈'), + (0x10C89, 'M', '𐳉'), + (0x10C8A, 'M', '𐳊'), + (0x10C8B, 'M', '𐳋'), + (0x10C8C, 'M', '𐳌'), + (0x10C8D, 'M', '𐳍'), + (0x10C8E, 'M', '𐳎'), + (0x10C8F, 'M', '𐳏'), + (0x10C90, 'M', '𐳐'), + (0x10C91, 'M', '𐳑'), + (0x10C92, 'M', '𐳒'), + (0x10C93, 'M', '𐳓'), + (0x10C94, 'M', '𐳔'), + (0x10C95, 'M', '𐳕'), + (0x10C96, 'M', '𐳖'), + (0x10C97, 'M', '𐳗'), + (0x10C98, 'M', '𐳘'), + (0x10C99, 'M', '𐳙'), + (0x10C9A, 'M', '𐳚'), + (0x10C9B, 'M', '𐳛'), + (0x10C9C, 'M', '𐳜'), + (0x10C9D, 'M', '𐳝'), + (0x10C9E, 'M', '𐳞'), + (0x10C9F, 'M', '𐳟'), + (0x10CA0, 'M', '𐳠'), + (0x10CA1, 'M', '𐳡'), + (0x10CA2, 'M', '𐳢'), + (0x10CA3, 'M', '𐳣'), + (0x10CA4, 'M', '𐳤'), + (0x10CA5, 'M', '𐳥'), + (0x10CA6, 'M', '𐳦'), + (0x10CA7, 'M', '𐳧'), + (0x10CA8, 'M', '𐳨'), + (0x10CA9, 'M', '𐳩'), + (0x10CAA, 'M', '𐳪'), + (0x10CAB, 'M', '𐳫'), + (0x10CAC, 'M', '𐳬'), + (0x10CAD, 'M', '𐳭'), + (0x10CAE, 'M', '𐳮'), + (0x10CAF, 'M', '𐳯'), + (0x10CB0, 'M', '𐳰'), + (0x10CB1, 'M', '𐳱'), + (0x10CB2, 'M', '𐳲'), (0x10CB3, 'X'), (0x10CC0, 'V'), (0x10CF3, 'X'), @@ -5830,6 +5887,7 @@ def _seg_55(): ] def _seg_56(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x11213, 'V'), (0x1123F, 'X'), @@ -5907,42 +5965,43 @@ def _seg_56(): (0x11740, 'X'), (0x11800, 'V'), (0x1183C, 'X'), - (0x118A0, 'M', u'𑣀'), - (0x118A1, 'M', u'𑣁'), - (0x118A2, 'M', u'𑣂'), - (0x118A3, 'M', u'𑣃'), - (0x118A4, 'M', u'𑣄'), - (0x118A5, 'M', u'𑣅'), - (0x118A6, 'M', u'𑣆'), - (0x118A7, 'M', u'𑣇'), - (0x118A8, 'M', u'𑣈'), - (0x118A9, 'M', u'𑣉'), - (0x118AA, 'M', u'𑣊'), - (0x118AB, 'M', u'𑣋'), - (0x118AC, 'M', u'𑣌'), - (0x118AD, 'M', u'𑣍'), - (0x118AE, 'M', u'𑣎'), - (0x118AF, 'M', u'𑣏'), - (0x118B0, 'M', u'𑣐'), - (0x118B1, 'M', u'𑣑'), - (0x118B2, 'M', u'𑣒'), - (0x118B3, 'M', u'𑣓'), - (0x118B4, 'M', u'𑣔'), - (0x118B5, 'M', u'𑣕'), - (0x118B6, 'M', u'𑣖'), - (0x118B7, 'M', u'𑣗'), + (0x118A0, 'M', '𑣀'), + (0x118A1, 'M', '𑣁'), + (0x118A2, 'M', '𑣂'), + (0x118A3, 'M', '𑣃'), + (0x118A4, 'M', '𑣄'), + (0x118A5, 'M', '𑣅'), + (0x118A6, 'M', '𑣆'), + (0x118A7, 'M', '𑣇'), + (0x118A8, 'M', '𑣈'), + (0x118A9, 'M', '𑣉'), + (0x118AA, 'M', '𑣊'), + (0x118AB, 'M', '𑣋'), + (0x118AC, 'M', '𑣌'), + (0x118AD, 'M', '𑣍'), + (0x118AE, 'M', '𑣎'), + (0x118AF, 'M', '𑣏'), + (0x118B0, 'M', '𑣐'), + (0x118B1, 'M', '𑣑'), + (0x118B2, 'M', '𑣒'), + (0x118B3, 'M', '𑣓'), + (0x118B4, 'M', '𑣔'), + (0x118B5, 'M', '𑣕'), + (0x118B6, 'M', '𑣖'), + (0x118B7, 'M', '𑣗'), ] def _seg_57(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x118B8, 'M', u'𑣘'), - (0x118B9, 'M', u'𑣙'), - (0x118BA, 'M', u'𑣚'), - (0x118BB, 'M', u'𑣛'), - (0x118BC, 'M', u'𑣜'), - (0x118BD, 'M', u'𑣝'), - (0x118BE, 'M', u'𑣞'), - (0x118BF, 'M', u'𑣟'), + (0x118B8, 'M', '𑣘'), + (0x118B9, 'M', '𑣙'), + (0x118BA, 'M', '𑣚'), + (0x118BB, 'M', '𑣛'), + (0x118BC, 'M', '𑣜'), + (0x118BD, 'M', '𑣝'), + (0x118BE, 'M', '𑣞'), + (0x118BF, 'M', '𑣟'), (0x118C0, 'V'), (0x118F3, 'X'), (0x118FF, 'V'), @@ -6038,6 +6097,7 @@ def _seg_57(): ] def _seg_58(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x16A60, 'V'), (0x16A6A, 'X'), @@ -6057,38 +6117,38 @@ def _seg_58(): (0x16B78, 'X'), (0x16B7D, 'V'), (0x16B90, 'X'), - (0x16E40, 'M', u'𖹠'), - (0x16E41, 'M', u'𖹡'), - (0x16E42, 'M', u'𖹢'), - (0x16E43, 'M', u'𖹣'), - (0x16E44, 'M', u'𖹤'), - (0x16E45, 'M', u'𖹥'), - (0x16E46, 'M', u'𖹦'), - (0x16E47, 'M', u'𖹧'), - (0x16E48, 'M', u'𖹨'), - (0x16E49, 'M', u'𖹩'), - (0x16E4A, 'M', u'𖹪'), - (0x16E4B, 'M', u'𖹫'), - (0x16E4C, 'M', u'𖹬'), - (0x16E4D, 'M', u'𖹭'), - (0x16E4E, 'M', u'𖹮'), - (0x16E4F, 'M', u'𖹯'), - (0x16E50, 'M', u'𖹰'), - (0x16E51, 'M', u'𖹱'), - (0x16E52, 'M', u'𖹲'), - (0x16E53, 'M', u'𖹳'), - (0x16E54, 'M', u'𖹴'), - (0x16E55, 'M', u'𖹵'), - (0x16E56, 'M', u'𖹶'), - (0x16E57, 'M', u'𖹷'), - (0x16E58, 'M', u'𖹸'), - (0x16E59, 'M', u'𖹹'), - (0x16E5A, 'M', u'𖹺'), - (0x16E5B, 'M', u'𖹻'), - (0x16E5C, 'M', u'𖹼'), - (0x16E5D, 'M', u'𖹽'), - (0x16E5E, 'M', u'𖹾'), - (0x16E5F, 'M', u'𖹿'), + (0x16E40, 'M', '𖹠'), + (0x16E41, 'M', '𖹡'), + (0x16E42, 'M', '𖹢'), + (0x16E43, 'M', '𖹣'), + (0x16E44, 'M', '𖹤'), + (0x16E45, 'M', '𖹥'), + (0x16E46, 'M', '𖹦'), + (0x16E47, 'M', '𖹧'), + (0x16E48, 'M', '𖹨'), + (0x16E49, 'M', '𖹩'), + (0x16E4A, 'M', '𖹪'), + (0x16E4B, 'M', '𖹫'), + (0x16E4C, 'M', '𖹬'), + (0x16E4D, 'M', '𖹭'), + (0x16E4E, 'M', '𖹮'), + (0x16E4F, 'M', '𖹯'), + (0x16E50, 'M', '𖹰'), + (0x16E51, 'M', '𖹱'), + (0x16E52, 'M', '𖹲'), + (0x16E53, 'M', '𖹳'), + (0x16E54, 'M', '𖹴'), + (0x16E55, 'M', '𖹵'), + (0x16E56, 'M', '𖹶'), + (0x16E57, 'M', '𖹷'), + (0x16E58, 'M', '𖹸'), + (0x16E59, 'M', '𖹹'), + (0x16E5A, 'M', '𖹺'), + (0x16E5B, 'M', '𖹻'), + (0x16E5C, 'M', '𖹼'), + (0x16E5D, 'M', '𖹽'), + (0x16E5E, 'M', '𖹾'), + (0x16E5F, 'M', '𖹿'), (0x16E60, 'V'), (0x16E9B, 'X'), (0x16F00, 'V'), @@ -6131,26 +6191,27 @@ def _seg_58(): (0x1D100, 'V'), (0x1D127, 'X'), (0x1D129, 'V'), - (0x1D15E, 'M', u'𝅗𝅥'), - (0x1D15F, 'M', u'𝅘𝅥'), - (0x1D160, 'M', u'𝅘𝅥𝅮'), - (0x1D161, 'M', u'𝅘𝅥𝅯'), - (0x1D162, 'M', u'𝅘𝅥𝅰'), - (0x1D163, 'M', u'𝅘𝅥𝅱'), - (0x1D164, 'M', u'𝅘𝅥𝅲'), + (0x1D15E, 'M', '𝅗𝅥'), + (0x1D15F, 'M', '𝅘𝅥'), + (0x1D160, 'M', '𝅘𝅥𝅮'), + (0x1D161, 'M', '𝅘𝅥𝅯'), + (0x1D162, 'M', '𝅘𝅥𝅰'), + (0x1D163, 'M', '𝅘𝅥𝅱'), + (0x1D164, 'M', '𝅘𝅥𝅲'), (0x1D165, 'V'), ] def _seg_59(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1D173, 'X'), (0x1D17B, 'V'), - (0x1D1BB, 'M', u'𝆹𝅥'), - (0x1D1BC, 'M', u'𝆺𝅥'), - (0x1D1BD, 'M', u'𝆹𝅥𝅮'), - (0x1D1BE, 'M', u'𝆺𝅥𝅮'), - (0x1D1BF, 'M', u'𝆹𝅥𝅯'), - (0x1D1C0, 'M', u'𝆺𝅥𝅯'), + (0x1D1BB, 'M', '𝆹𝅥'), + (0x1D1BC, 'M', '𝆺𝅥'), + (0x1D1BD, 'M', '𝆹𝅥𝅮'), + (0x1D1BE, 'M', '𝆺𝅥𝅮'), + (0x1D1BF, 'M', '𝆹𝅥𝅯'), + (0x1D1C0, 'M', '𝆺𝅥𝅯'), (0x1D1C1, 'V'), (0x1D1E9, 'X'), (0x1D200, 'V'), @@ -6161,1056 +6222,1066 @@ def _seg_59(): (0x1D357, 'X'), (0x1D360, 'V'), (0x1D379, 'X'), - (0x1D400, 'M', u'a'), - (0x1D401, 'M', u'b'), - (0x1D402, 'M', u'c'), - (0x1D403, 'M', u'd'), - (0x1D404, 'M', u'e'), - (0x1D405, 'M', u'f'), - (0x1D406, 'M', u'g'), - (0x1D407, 'M', u'h'), - (0x1D408, 'M', u'i'), - (0x1D409, 'M', u'j'), - (0x1D40A, 'M', u'k'), - (0x1D40B, 'M', u'l'), - (0x1D40C, 'M', u'm'), - (0x1D40D, 'M', u'n'), - (0x1D40E, 'M', u'o'), - (0x1D40F, 'M', u'p'), - (0x1D410, 'M', u'q'), - (0x1D411, 'M', u'r'), - (0x1D412, 'M', u's'), - (0x1D413, 'M', u't'), - (0x1D414, 'M', u'u'), - (0x1D415, 'M', u'v'), - (0x1D416, 'M', u'w'), - (0x1D417, 'M', u'x'), - (0x1D418, 'M', u'y'), - (0x1D419, 'M', u'z'), - (0x1D41A, 'M', u'a'), - (0x1D41B, 'M', u'b'), - (0x1D41C, 'M', u'c'), - (0x1D41D, 'M', u'd'), - (0x1D41E, 'M', u'e'), - (0x1D41F, 'M', u'f'), - (0x1D420, 'M', u'g'), - (0x1D421, 'M', u'h'), - (0x1D422, 'M', u'i'), - (0x1D423, 'M', u'j'), - (0x1D424, 'M', u'k'), - (0x1D425, 'M', u'l'), - (0x1D426, 'M', u'm'), - (0x1D427, 'M', u'n'), - (0x1D428, 'M', u'o'), - (0x1D429, 'M', u'p'), - (0x1D42A, 'M', u'q'), - (0x1D42B, 'M', u'r'), - (0x1D42C, 'M', u's'), - (0x1D42D, 'M', u't'), - (0x1D42E, 'M', u'u'), - (0x1D42F, 'M', u'v'), - (0x1D430, 'M', u'w'), - (0x1D431, 'M', u'x'), - (0x1D432, 'M', u'y'), - (0x1D433, 'M', u'z'), - (0x1D434, 'M', u'a'), - (0x1D435, 'M', u'b'), - (0x1D436, 'M', u'c'), - (0x1D437, 'M', u'd'), - (0x1D438, 'M', u'e'), - (0x1D439, 'M', u'f'), - (0x1D43A, 'M', u'g'), - (0x1D43B, 'M', u'h'), - (0x1D43C, 'M', u'i'), - (0x1D43D, 'M', u'j'), - (0x1D43E, 'M', u'k'), - (0x1D43F, 'M', u'l'), - (0x1D440, 'M', u'm'), - (0x1D441, 'M', u'n'), - (0x1D442, 'M', u'o'), - (0x1D443, 'M', u'p'), - (0x1D444, 'M', u'q'), - (0x1D445, 'M', u'r'), - (0x1D446, 'M', u's'), - (0x1D447, 'M', u't'), - (0x1D448, 'M', u'u'), - (0x1D449, 'M', u'v'), - (0x1D44A, 'M', u'w'), - (0x1D44B, 'M', u'x'), - (0x1D44C, 'M', u'y'), - (0x1D44D, 'M', u'z'), - (0x1D44E, 'M', u'a'), - (0x1D44F, 'M', u'b'), - (0x1D450, 'M', u'c'), - (0x1D451, 'M', u'd'), + (0x1D400, 'M', 'a'), + (0x1D401, 'M', 'b'), + (0x1D402, 'M', 'c'), + (0x1D403, 'M', 'd'), + (0x1D404, 'M', 'e'), + (0x1D405, 'M', 'f'), + (0x1D406, 'M', 'g'), + (0x1D407, 'M', 'h'), + (0x1D408, 'M', 'i'), + (0x1D409, 'M', 'j'), + (0x1D40A, 'M', 'k'), + (0x1D40B, 'M', 'l'), + (0x1D40C, 'M', 'm'), + (0x1D40D, 'M', 'n'), + (0x1D40E, 'M', 'o'), + (0x1D40F, 'M', 'p'), + (0x1D410, 'M', 'q'), + (0x1D411, 'M', 'r'), + (0x1D412, 'M', 's'), + (0x1D413, 'M', 't'), + (0x1D414, 'M', 'u'), + (0x1D415, 'M', 'v'), + (0x1D416, 'M', 'w'), + (0x1D417, 'M', 'x'), + (0x1D418, 'M', 'y'), + (0x1D419, 'M', 'z'), + (0x1D41A, 'M', 'a'), + (0x1D41B, 'M', 'b'), + (0x1D41C, 'M', 'c'), + (0x1D41D, 'M', 'd'), + (0x1D41E, 'M', 'e'), + (0x1D41F, 'M', 'f'), + (0x1D420, 'M', 'g'), + (0x1D421, 'M', 'h'), + (0x1D422, 'M', 'i'), + (0x1D423, 'M', 'j'), + (0x1D424, 'M', 'k'), + (0x1D425, 'M', 'l'), + (0x1D426, 'M', 'm'), + (0x1D427, 'M', 'n'), + (0x1D428, 'M', 'o'), + (0x1D429, 'M', 'p'), + (0x1D42A, 'M', 'q'), + (0x1D42B, 'M', 'r'), + (0x1D42C, 'M', 's'), + (0x1D42D, 'M', 't'), + (0x1D42E, 'M', 'u'), + (0x1D42F, 'M', 'v'), + (0x1D430, 'M', 'w'), + (0x1D431, 'M', 'x'), + (0x1D432, 'M', 'y'), + (0x1D433, 'M', 'z'), + (0x1D434, 'M', 'a'), + (0x1D435, 'M', 'b'), + (0x1D436, 'M', 'c'), + (0x1D437, 'M', 'd'), + (0x1D438, 'M', 'e'), + (0x1D439, 'M', 'f'), + (0x1D43A, 'M', 'g'), + (0x1D43B, 'M', 'h'), + (0x1D43C, 'M', 'i'), + (0x1D43D, 'M', 'j'), + (0x1D43E, 'M', 'k'), + (0x1D43F, 'M', 'l'), + (0x1D440, 'M', 'm'), + (0x1D441, 'M', 'n'), + (0x1D442, 'M', 'o'), + (0x1D443, 'M', 'p'), + (0x1D444, 'M', 'q'), + (0x1D445, 'M', 'r'), + (0x1D446, 'M', 's'), + (0x1D447, 'M', 't'), + (0x1D448, 'M', 'u'), + (0x1D449, 'M', 'v'), + (0x1D44A, 'M', 'w'), + (0x1D44B, 'M', 'x'), + (0x1D44C, 'M', 'y'), + (0x1D44D, 'M', 'z'), + (0x1D44E, 'M', 'a'), + (0x1D44F, 'M', 'b'), + (0x1D450, 'M', 'c'), + (0x1D451, 'M', 'd'), ] def _seg_60(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D452, 'M', u'e'), - (0x1D453, 'M', u'f'), - (0x1D454, 'M', u'g'), + (0x1D452, 'M', 'e'), + (0x1D453, 'M', 'f'), + (0x1D454, 'M', 'g'), (0x1D455, 'X'), - (0x1D456, 'M', u'i'), - (0x1D457, 'M', u'j'), - (0x1D458, 'M', u'k'), - (0x1D459, 'M', u'l'), - (0x1D45A, 'M', u'm'), - (0x1D45B, 'M', u'n'), - (0x1D45C, 'M', u'o'), - (0x1D45D, 'M', u'p'), - (0x1D45E, 'M', u'q'), - (0x1D45F, 'M', u'r'), - (0x1D460, 'M', u's'), - (0x1D461, 'M', u't'), - (0x1D462, 'M', u'u'), - (0x1D463, 'M', u'v'), - (0x1D464, 'M', u'w'), - (0x1D465, 'M', u'x'), - (0x1D466, 'M', u'y'), - (0x1D467, 'M', u'z'), - (0x1D468, 'M', u'a'), - (0x1D469, 'M', u'b'), - (0x1D46A, 'M', u'c'), - (0x1D46B, 'M', u'd'), - (0x1D46C, 'M', u'e'), - (0x1D46D, 'M', u'f'), - (0x1D46E, 'M', u'g'), - (0x1D46F, 'M', u'h'), - (0x1D470, 'M', u'i'), - (0x1D471, 'M', u'j'), - (0x1D472, 'M', u'k'), - (0x1D473, 'M', u'l'), - (0x1D474, 'M', u'm'), - (0x1D475, 'M', u'n'), - (0x1D476, 'M', u'o'), - (0x1D477, 'M', u'p'), - (0x1D478, 'M', u'q'), - (0x1D479, 'M', u'r'), - (0x1D47A, 'M', u's'), - (0x1D47B, 'M', u't'), - (0x1D47C, 'M', u'u'), - (0x1D47D, 'M', u'v'), - (0x1D47E, 'M', u'w'), - (0x1D47F, 'M', u'x'), - (0x1D480, 'M', u'y'), - (0x1D481, 'M', u'z'), - (0x1D482, 'M', u'a'), - (0x1D483, 'M', u'b'), - (0x1D484, 'M', u'c'), - (0x1D485, 'M', u'd'), - (0x1D486, 'M', u'e'), - (0x1D487, 'M', u'f'), - (0x1D488, 'M', u'g'), - (0x1D489, 'M', u'h'), - (0x1D48A, 'M', u'i'), - (0x1D48B, 'M', u'j'), - (0x1D48C, 'M', u'k'), - (0x1D48D, 'M', u'l'), - (0x1D48E, 'M', u'm'), - (0x1D48F, 'M', u'n'), - (0x1D490, 'M', u'o'), - (0x1D491, 'M', u'p'), - (0x1D492, 'M', u'q'), - (0x1D493, 'M', u'r'), - (0x1D494, 'M', u's'), - (0x1D495, 'M', u't'), - (0x1D496, 'M', u'u'), - (0x1D497, 'M', u'v'), - (0x1D498, 'M', u'w'), - (0x1D499, 'M', u'x'), - (0x1D49A, 'M', u'y'), - (0x1D49B, 'M', u'z'), - (0x1D49C, 'M', u'a'), + (0x1D456, 'M', 'i'), + (0x1D457, 'M', 'j'), + (0x1D458, 'M', 'k'), + (0x1D459, 'M', 'l'), + (0x1D45A, 'M', 'm'), + (0x1D45B, 'M', 'n'), + (0x1D45C, 'M', 'o'), + (0x1D45D, 'M', 'p'), + (0x1D45E, 'M', 'q'), + (0x1D45F, 'M', 'r'), + (0x1D460, 'M', 's'), + (0x1D461, 'M', 't'), + (0x1D462, 'M', 'u'), + (0x1D463, 'M', 'v'), + (0x1D464, 'M', 'w'), + (0x1D465, 'M', 'x'), + (0x1D466, 'M', 'y'), + (0x1D467, 'M', 'z'), + (0x1D468, 'M', 'a'), + (0x1D469, 'M', 'b'), + (0x1D46A, 'M', 'c'), + (0x1D46B, 'M', 'd'), + (0x1D46C, 'M', 'e'), + (0x1D46D, 'M', 'f'), + (0x1D46E, 'M', 'g'), + (0x1D46F, 'M', 'h'), + (0x1D470, 'M', 'i'), + (0x1D471, 'M', 'j'), + (0x1D472, 'M', 'k'), + (0x1D473, 'M', 'l'), + (0x1D474, 'M', 'm'), + (0x1D475, 'M', 'n'), + (0x1D476, 'M', 'o'), + (0x1D477, 'M', 'p'), + (0x1D478, 'M', 'q'), + (0x1D479, 'M', 'r'), + (0x1D47A, 'M', 's'), + (0x1D47B, 'M', 't'), + (0x1D47C, 'M', 'u'), + (0x1D47D, 'M', 'v'), + (0x1D47E, 'M', 'w'), + (0x1D47F, 'M', 'x'), + (0x1D480, 'M', 'y'), + (0x1D481, 'M', 'z'), + (0x1D482, 'M', 'a'), + (0x1D483, 'M', 'b'), + (0x1D484, 'M', 'c'), + (0x1D485, 'M', 'd'), + (0x1D486, 'M', 'e'), + (0x1D487, 'M', 'f'), + (0x1D488, 'M', 'g'), + (0x1D489, 'M', 'h'), + (0x1D48A, 'M', 'i'), + (0x1D48B, 'M', 'j'), + (0x1D48C, 'M', 'k'), + (0x1D48D, 'M', 'l'), + (0x1D48E, 'M', 'm'), + (0x1D48F, 'M', 'n'), + (0x1D490, 'M', 'o'), + (0x1D491, 'M', 'p'), + (0x1D492, 'M', 'q'), + (0x1D493, 'M', 'r'), + (0x1D494, 'M', 's'), + (0x1D495, 'M', 't'), + (0x1D496, 'M', 'u'), + (0x1D497, 'M', 'v'), + (0x1D498, 'M', 'w'), + (0x1D499, 'M', 'x'), + (0x1D49A, 'M', 'y'), + (0x1D49B, 'M', 'z'), + (0x1D49C, 'M', 'a'), (0x1D49D, 'X'), - (0x1D49E, 'M', u'c'), - (0x1D49F, 'M', u'd'), + (0x1D49E, 'M', 'c'), + (0x1D49F, 'M', 'd'), (0x1D4A0, 'X'), - (0x1D4A2, 'M', u'g'), + (0x1D4A2, 'M', 'g'), (0x1D4A3, 'X'), - (0x1D4A5, 'M', u'j'), - (0x1D4A6, 'M', u'k'), + (0x1D4A5, 'M', 'j'), + (0x1D4A6, 'M', 'k'), (0x1D4A7, 'X'), - (0x1D4A9, 'M', u'n'), - (0x1D4AA, 'M', u'o'), - (0x1D4AB, 'M', u'p'), - (0x1D4AC, 'M', u'q'), + (0x1D4A9, 'M', 'n'), + (0x1D4AA, 'M', 'o'), + (0x1D4AB, 'M', 'p'), + (0x1D4AC, 'M', 'q'), (0x1D4AD, 'X'), - (0x1D4AE, 'M', u's'), - (0x1D4AF, 'M', u't'), - (0x1D4B0, 'M', u'u'), - (0x1D4B1, 'M', u'v'), - (0x1D4B2, 'M', u'w'), - (0x1D4B3, 'M', u'x'), - (0x1D4B4, 'M', u'y'), - (0x1D4B5, 'M', u'z'), - (0x1D4B6, 'M', u'a'), - (0x1D4B7, 'M', u'b'), - (0x1D4B8, 'M', u'c'), + (0x1D4AE, 'M', 's'), + (0x1D4AF, 'M', 't'), + (0x1D4B0, 'M', 'u'), + (0x1D4B1, 'M', 'v'), + (0x1D4B2, 'M', 'w'), + (0x1D4B3, 'M', 'x'), + (0x1D4B4, 'M', 'y'), + (0x1D4B5, 'M', 'z'), + (0x1D4B6, 'M', 'a'), + (0x1D4B7, 'M', 'b'), + (0x1D4B8, 'M', 'c'), ] def _seg_61(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D4B9, 'M', u'd'), + (0x1D4B9, 'M', 'd'), (0x1D4BA, 'X'), - (0x1D4BB, 'M', u'f'), + (0x1D4BB, 'M', 'f'), (0x1D4BC, 'X'), - (0x1D4BD, 'M', u'h'), - (0x1D4BE, 'M', u'i'), - (0x1D4BF, 'M', u'j'), - (0x1D4C0, 'M', u'k'), - (0x1D4C1, 'M', u'l'), - (0x1D4C2, 'M', u'm'), - (0x1D4C3, 'M', u'n'), + (0x1D4BD, 'M', 'h'), + (0x1D4BE, 'M', 'i'), + (0x1D4BF, 'M', 'j'), + (0x1D4C0, 'M', 'k'), + (0x1D4C1, 'M', 'l'), + (0x1D4C2, 'M', 'm'), + (0x1D4C3, 'M', 'n'), (0x1D4C4, 'X'), - (0x1D4C5, 'M', u'p'), - (0x1D4C6, 'M', u'q'), - (0x1D4C7, 'M', u'r'), - (0x1D4C8, 'M', u's'), - (0x1D4C9, 'M', u't'), - (0x1D4CA, 'M', u'u'), - (0x1D4CB, 'M', u'v'), - (0x1D4CC, 'M', u'w'), - (0x1D4CD, 'M', u'x'), - (0x1D4CE, 'M', u'y'), - (0x1D4CF, 'M', u'z'), - (0x1D4D0, 'M', u'a'), - (0x1D4D1, 'M', u'b'), - (0x1D4D2, 'M', u'c'), - (0x1D4D3, 'M', u'd'), - (0x1D4D4, 'M', u'e'), - (0x1D4D5, 'M', u'f'), - (0x1D4D6, 'M', u'g'), - (0x1D4D7, 'M', u'h'), - (0x1D4D8, 'M', u'i'), - (0x1D4D9, 'M', u'j'), - (0x1D4DA, 'M', u'k'), - (0x1D4DB, 'M', u'l'), - (0x1D4DC, 'M', u'm'), - (0x1D4DD, 'M', u'n'), - (0x1D4DE, 'M', u'o'), - (0x1D4DF, 'M', u'p'), - (0x1D4E0, 'M', u'q'), - (0x1D4E1, 'M', u'r'), - (0x1D4E2, 'M', u's'), - (0x1D4E3, 'M', u't'), - (0x1D4E4, 'M', u'u'), - (0x1D4E5, 'M', u'v'), - (0x1D4E6, 'M', u'w'), - (0x1D4E7, 'M', u'x'), - (0x1D4E8, 'M', u'y'), - (0x1D4E9, 'M', u'z'), - (0x1D4EA, 'M', u'a'), - (0x1D4EB, 'M', u'b'), - (0x1D4EC, 'M', u'c'), - (0x1D4ED, 'M', u'd'), - (0x1D4EE, 'M', u'e'), - (0x1D4EF, 'M', u'f'), - (0x1D4F0, 'M', u'g'), - (0x1D4F1, 'M', u'h'), - (0x1D4F2, 'M', u'i'), - (0x1D4F3, 'M', u'j'), - (0x1D4F4, 'M', u'k'), - (0x1D4F5, 'M', u'l'), - (0x1D4F6, 'M', u'm'), - (0x1D4F7, 'M', u'n'), - (0x1D4F8, 'M', u'o'), - (0x1D4F9, 'M', u'p'), - (0x1D4FA, 'M', u'q'), - (0x1D4FB, 'M', u'r'), - (0x1D4FC, 'M', u's'), - (0x1D4FD, 'M', u't'), - (0x1D4FE, 'M', u'u'), - (0x1D4FF, 'M', u'v'), - (0x1D500, 'M', u'w'), - (0x1D501, 'M', u'x'), - (0x1D502, 'M', u'y'), - (0x1D503, 'M', u'z'), - (0x1D504, 'M', u'a'), - (0x1D505, 'M', u'b'), + (0x1D4C5, 'M', 'p'), + (0x1D4C6, 'M', 'q'), + (0x1D4C7, 'M', 'r'), + (0x1D4C8, 'M', 's'), + (0x1D4C9, 'M', 't'), + (0x1D4CA, 'M', 'u'), + (0x1D4CB, 'M', 'v'), + (0x1D4CC, 'M', 'w'), + (0x1D4CD, 'M', 'x'), + (0x1D4CE, 'M', 'y'), + (0x1D4CF, 'M', 'z'), + (0x1D4D0, 'M', 'a'), + (0x1D4D1, 'M', 'b'), + (0x1D4D2, 'M', 'c'), + (0x1D4D3, 'M', 'd'), + (0x1D4D4, 'M', 'e'), + (0x1D4D5, 'M', 'f'), + (0x1D4D6, 'M', 'g'), + (0x1D4D7, 'M', 'h'), + (0x1D4D8, 'M', 'i'), + (0x1D4D9, 'M', 'j'), + (0x1D4DA, 'M', 'k'), + (0x1D4DB, 'M', 'l'), + (0x1D4DC, 'M', 'm'), + (0x1D4DD, 'M', 'n'), + (0x1D4DE, 'M', 'o'), + (0x1D4DF, 'M', 'p'), + (0x1D4E0, 'M', 'q'), + (0x1D4E1, 'M', 'r'), + (0x1D4E2, 'M', 's'), + (0x1D4E3, 'M', 't'), + (0x1D4E4, 'M', 'u'), + (0x1D4E5, 'M', 'v'), + (0x1D4E6, 'M', 'w'), + (0x1D4E7, 'M', 'x'), + (0x1D4E8, 'M', 'y'), + (0x1D4E9, 'M', 'z'), + (0x1D4EA, 'M', 'a'), + (0x1D4EB, 'M', 'b'), + (0x1D4EC, 'M', 'c'), + (0x1D4ED, 'M', 'd'), + (0x1D4EE, 'M', 'e'), + (0x1D4EF, 'M', 'f'), + (0x1D4F0, 'M', 'g'), + (0x1D4F1, 'M', 'h'), + (0x1D4F2, 'M', 'i'), + (0x1D4F3, 'M', 'j'), + (0x1D4F4, 'M', 'k'), + (0x1D4F5, 'M', 'l'), + (0x1D4F6, 'M', 'm'), + (0x1D4F7, 'M', 'n'), + (0x1D4F8, 'M', 'o'), + (0x1D4F9, 'M', 'p'), + (0x1D4FA, 'M', 'q'), + (0x1D4FB, 'M', 'r'), + (0x1D4FC, 'M', 's'), + (0x1D4FD, 'M', 't'), + (0x1D4FE, 'M', 'u'), + (0x1D4FF, 'M', 'v'), + (0x1D500, 'M', 'w'), + (0x1D501, 'M', 'x'), + (0x1D502, 'M', 'y'), + (0x1D503, 'M', 'z'), + (0x1D504, 'M', 'a'), + (0x1D505, 'M', 'b'), (0x1D506, 'X'), - (0x1D507, 'M', u'd'), - (0x1D508, 'M', u'e'), - (0x1D509, 'M', u'f'), - (0x1D50A, 'M', u'g'), + (0x1D507, 'M', 'd'), + (0x1D508, 'M', 'e'), + (0x1D509, 'M', 'f'), + (0x1D50A, 'M', 'g'), (0x1D50B, 'X'), - (0x1D50D, 'M', u'j'), - (0x1D50E, 'M', u'k'), - (0x1D50F, 'M', u'l'), - (0x1D510, 'M', u'm'), - (0x1D511, 'M', u'n'), - (0x1D512, 'M', u'o'), - (0x1D513, 'M', u'p'), - (0x1D514, 'M', u'q'), + (0x1D50D, 'M', 'j'), + (0x1D50E, 'M', 'k'), + (0x1D50F, 'M', 'l'), + (0x1D510, 'M', 'm'), + (0x1D511, 'M', 'n'), + (0x1D512, 'M', 'o'), + (0x1D513, 'M', 'p'), + (0x1D514, 'M', 'q'), (0x1D515, 'X'), - (0x1D516, 'M', u's'), - (0x1D517, 'M', u't'), - (0x1D518, 'M', u'u'), - (0x1D519, 'M', u'v'), - (0x1D51A, 'M', u'w'), - (0x1D51B, 'M', u'x'), - (0x1D51C, 'M', u'y'), + (0x1D516, 'M', 's'), + (0x1D517, 'M', 't'), + (0x1D518, 'M', 'u'), + (0x1D519, 'M', 'v'), + (0x1D51A, 'M', 'w'), + (0x1D51B, 'M', 'x'), + (0x1D51C, 'M', 'y'), (0x1D51D, 'X'), ] def _seg_62(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D51E, 'M', u'a'), - (0x1D51F, 'M', u'b'), - (0x1D520, 'M', u'c'), - (0x1D521, 'M', u'd'), - (0x1D522, 'M', u'e'), - (0x1D523, 'M', u'f'), - (0x1D524, 'M', u'g'), - (0x1D525, 'M', u'h'), - (0x1D526, 'M', u'i'), - (0x1D527, 'M', u'j'), - (0x1D528, 'M', u'k'), - (0x1D529, 'M', u'l'), - (0x1D52A, 'M', u'm'), - (0x1D52B, 'M', u'n'), - (0x1D52C, 'M', u'o'), - (0x1D52D, 'M', u'p'), - (0x1D52E, 'M', u'q'), - (0x1D52F, 'M', u'r'), - (0x1D530, 'M', u's'), - (0x1D531, 'M', u't'), - (0x1D532, 'M', u'u'), - (0x1D533, 'M', u'v'), - (0x1D534, 'M', u'w'), - (0x1D535, 'M', u'x'), - (0x1D536, 'M', u'y'), - (0x1D537, 'M', u'z'), - (0x1D538, 'M', u'a'), - (0x1D539, 'M', u'b'), + (0x1D51E, 'M', 'a'), + (0x1D51F, 'M', 'b'), + (0x1D520, 'M', 'c'), + (0x1D521, 'M', 'd'), + (0x1D522, 'M', 'e'), + (0x1D523, 'M', 'f'), + (0x1D524, 'M', 'g'), + (0x1D525, 'M', 'h'), + (0x1D526, 'M', 'i'), + (0x1D527, 'M', 'j'), + (0x1D528, 'M', 'k'), + (0x1D529, 'M', 'l'), + (0x1D52A, 'M', 'm'), + (0x1D52B, 'M', 'n'), + (0x1D52C, 'M', 'o'), + (0x1D52D, 'M', 'p'), + (0x1D52E, 'M', 'q'), + (0x1D52F, 'M', 'r'), + (0x1D530, 'M', 's'), + (0x1D531, 'M', 't'), + (0x1D532, 'M', 'u'), + (0x1D533, 'M', 'v'), + (0x1D534, 'M', 'w'), + (0x1D535, 'M', 'x'), + (0x1D536, 'M', 'y'), + (0x1D537, 'M', 'z'), + (0x1D538, 'M', 'a'), + (0x1D539, 'M', 'b'), (0x1D53A, 'X'), - (0x1D53B, 'M', u'd'), - (0x1D53C, 'M', u'e'), - (0x1D53D, 'M', u'f'), - (0x1D53E, 'M', u'g'), + (0x1D53B, 'M', 'd'), + (0x1D53C, 'M', 'e'), + (0x1D53D, 'M', 'f'), + (0x1D53E, 'M', 'g'), (0x1D53F, 'X'), - (0x1D540, 'M', u'i'), - (0x1D541, 'M', u'j'), - (0x1D542, 'M', u'k'), - (0x1D543, 'M', u'l'), - (0x1D544, 'M', u'm'), + (0x1D540, 'M', 'i'), + (0x1D541, 'M', 'j'), + (0x1D542, 'M', 'k'), + (0x1D543, 'M', 'l'), + (0x1D544, 'M', 'm'), (0x1D545, 'X'), - (0x1D546, 'M', u'o'), + (0x1D546, 'M', 'o'), (0x1D547, 'X'), - (0x1D54A, 'M', u's'), - (0x1D54B, 'M', u't'), - (0x1D54C, 'M', u'u'), - (0x1D54D, 'M', u'v'), - (0x1D54E, 'M', u'w'), - (0x1D54F, 'M', u'x'), - (0x1D550, 'M', u'y'), + (0x1D54A, 'M', 's'), + (0x1D54B, 'M', 't'), + (0x1D54C, 'M', 'u'), + (0x1D54D, 'M', 'v'), + (0x1D54E, 'M', 'w'), + (0x1D54F, 'M', 'x'), + (0x1D550, 'M', 'y'), (0x1D551, 'X'), - (0x1D552, 'M', u'a'), - (0x1D553, 'M', u'b'), - (0x1D554, 'M', u'c'), - (0x1D555, 'M', u'd'), - (0x1D556, 'M', u'e'), - (0x1D557, 'M', u'f'), - (0x1D558, 'M', u'g'), - (0x1D559, 'M', u'h'), - (0x1D55A, 'M', u'i'), - (0x1D55B, 'M', u'j'), - (0x1D55C, 'M', u'k'), - (0x1D55D, 'M', u'l'), - (0x1D55E, 'M', u'm'), - (0x1D55F, 'M', u'n'), - (0x1D560, 'M', u'o'), - (0x1D561, 'M', u'p'), - (0x1D562, 'M', u'q'), - (0x1D563, 'M', u'r'), - (0x1D564, 'M', u's'), - (0x1D565, 'M', u't'), - (0x1D566, 'M', u'u'), - (0x1D567, 'M', u'v'), - (0x1D568, 'M', u'w'), - (0x1D569, 'M', u'x'), - (0x1D56A, 'M', u'y'), - (0x1D56B, 'M', u'z'), - (0x1D56C, 'M', u'a'), - (0x1D56D, 'M', u'b'), - (0x1D56E, 'M', u'c'), - (0x1D56F, 'M', u'd'), - (0x1D570, 'M', u'e'), - (0x1D571, 'M', u'f'), - (0x1D572, 'M', u'g'), - (0x1D573, 'M', u'h'), - (0x1D574, 'M', u'i'), - (0x1D575, 'M', u'j'), - (0x1D576, 'M', u'k'), - (0x1D577, 'M', u'l'), - (0x1D578, 'M', u'm'), - (0x1D579, 'M', u'n'), - (0x1D57A, 'M', u'o'), - (0x1D57B, 'M', u'p'), - (0x1D57C, 'M', u'q'), - (0x1D57D, 'M', u'r'), - (0x1D57E, 'M', u's'), - (0x1D57F, 'M', u't'), - (0x1D580, 'M', u'u'), - (0x1D581, 'M', u'v'), - (0x1D582, 'M', u'w'), - (0x1D583, 'M', u'x'), + (0x1D552, 'M', 'a'), + (0x1D553, 'M', 'b'), + (0x1D554, 'M', 'c'), + (0x1D555, 'M', 'd'), + (0x1D556, 'M', 'e'), + (0x1D557, 'M', 'f'), + (0x1D558, 'M', 'g'), + (0x1D559, 'M', 'h'), + (0x1D55A, 'M', 'i'), + (0x1D55B, 'M', 'j'), + (0x1D55C, 'M', 'k'), + (0x1D55D, 'M', 'l'), + (0x1D55E, 'M', 'm'), + (0x1D55F, 'M', 'n'), + (0x1D560, 'M', 'o'), + (0x1D561, 'M', 'p'), + (0x1D562, 'M', 'q'), + (0x1D563, 'M', 'r'), + (0x1D564, 'M', 's'), + (0x1D565, 'M', 't'), + (0x1D566, 'M', 'u'), + (0x1D567, 'M', 'v'), + (0x1D568, 'M', 'w'), + (0x1D569, 'M', 'x'), + (0x1D56A, 'M', 'y'), + (0x1D56B, 'M', 'z'), + (0x1D56C, 'M', 'a'), + (0x1D56D, 'M', 'b'), + (0x1D56E, 'M', 'c'), + (0x1D56F, 'M', 'd'), + (0x1D570, 'M', 'e'), + (0x1D571, 'M', 'f'), + (0x1D572, 'M', 'g'), + (0x1D573, 'M', 'h'), + (0x1D574, 'M', 'i'), + (0x1D575, 'M', 'j'), + (0x1D576, 'M', 'k'), + (0x1D577, 'M', 'l'), + (0x1D578, 'M', 'm'), + (0x1D579, 'M', 'n'), + (0x1D57A, 'M', 'o'), + (0x1D57B, 'M', 'p'), + (0x1D57C, 'M', 'q'), + (0x1D57D, 'M', 'r'), + (0x1D57E, 'M', 's'), + (0x1D57F, 'M', 't'), + (0x1D580, 'M', 'u'), + (0x1D581, 'M', 'v'), + (0x1D582, 'M', 'w'), + (0x1D583, 'M', 'x'), ] def _seg_63(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D584, 'M', u'y'), - (0x1D585, 'M', u'z'), - (0x1D586, 'M', u'a'), - (0x1D587, 'M', u'b'), - (0x1D588, 'M', u'c'), - (0x1D589, 'M', u'd'), - (0x1D58A, 'M', u'e'), - (0x1D58B, 'M', u'f'), - (0x1D58C, 'M', u'g'), - (0x1D58D, 'M', u'h'), - (0x1D58E, 'M', u'i'), - (0x1D58F, 'M', u'j'), - (0x1D590, 'M', u'k'), - (0x1D591, 'M', u'l'), - (0x1D592, 'M', u'm'), - (0x1D593, 'M', u'n'), - (0x1D594, 'M', u'o'), - (0x1D595, 'M', u'p'), - (0x1D596, 'M', u'q'), - (0x1D597, 'M', u'r'), - (0x1D598, 'M', u's'), - (0x1D599, 'M', u't'), - (0x1D59A, 'M', u'u'), - (0x1D59B, 'M', u'v'), - (0x1D59C, 'M', u'w'), - (0x1D59D, 'M', u'x'), - (0x1D59E, 'M', u'y'), - (0x1D59F, 'M', u'z'), - (0x1D5A0, 'M', u'a'), - (0x1D5A1, 'M', u'b'), - (0x1D5A2, 'M', u'c'), - (0x1D5A3, 'M', u'd'), - (0x1D5A4, 'M', u'e'), - (0x1D5A5, 'M', u'f'), - (0x1D5A6, 'M', u'g'), - (0x1D5A7, 'M', u'h'), - (0x1D5A8, 'M', u'i'), - (0x1D5A9, 'M', u'j'), - (0x1D5AA, 'M', u'k'), - (0x1D5AB, 'M', u'l'), - (0x1D5AC, 'M', u'm'), - (0x1D5AD, 'M', u'n'), - (0x1D5AE, 'M', u'o'), - (0x1D5AF, 'M', u'p'), - (0x1D5B0, 'M', u'q'), - (0x1D5B1, 'M', u'r'), - (0x1D5B2, 'M', u's'), - (0x1D5B3, 'M', u't'), - (0x1D5B4, 'M', u'u'), - (0x1D5B5, 'M', u'v'), - (0x1D5B6, 'M', u'w'), - (0x1D5B7, 'M', u'x'), - (0x1D5B8, 'M', u'y'), - (0x1D5B9, 'M', u'z'), - (0x1D5BA, 'M', u'a'), - (0x1D5BB, 'M', u'b'), - (0x1D5BC, 'M', u'c'), - (0x1D5BD, 'M', u'd'), - (0x1D5BE, 'M', u'e'), - (0x1D5BF, 'M', u'f'), - (0x1D5C0, 'M', u'g'), - (0x1D5C1, 'M', u'h'), - (0x1D5C2, 'M', u'i'), - (0x1D5C3, 'M', u'j'), - (0x1D5C4, 'M', u'k'), - (0x1D5C5, 'M', u'l'), - (0x1D5C6, 'M', u'm'), - (0x1D5C7, 'M', u'n'), - (0x1D5C8, 'M', u'o'), - (0x1D5C9, 'M', u'p'), - (0x1D5CA, 'M', u'q'), - (0x1D5CB, 'M', u'r'), - (0x1D5CC, 'M', u's'), - (0x1D5CD, 'M', u't'), - (0x1D5CE, 'M', u'u'), - (0x1D5CF, 'M', u'v'), - (0x1D5D0, 'M', u'w'), - (0x1D5D1, 'M', u'x'), - (0x1D5D2, 'M', u'y'), - (0x1D5D3, 'M', u'z'), - (0x1D5D4, 'M', u'a'), - (0x1D5D5, 'M', u'b'), - (0x1D5D6, 'M', u'c'), - (0x1D5D7, 'M', u'd'), - (0x1D5D8, 'M', u'e'), - (0x1D5D9, 'M', u'f'), - (0x1D5DA, 'M', u'g'), - (0x1D5DB, 'M', u'h'), - (0x1D5DC, 'M', u'i'), - (0x1D5DD, 'M', u'j'), - (0x1D5DE, 'M', u'k'), - (0x1D5DF, 'M', u'l'), - (0x1D5E0, 'M', u'm'), - (0x1D5E1, 'M', u'n'), - (0x1D5E2, 'M', u'o'), - (0x1D5E3, 'M', u'p'), - (0x1D5E4, 'M', u'q'), - (0x1D5E5, 'M', u'r'), - (0x1D5E6, 'M', u's'), - (0x1D5E7, 'M', u't'), + (0x1D584, 'M', 'y'), + (0x1D585, 'M', 'z'), + (0x1D586, 'M', 'a'), + (0x1D587, 'M', 'b'), + (0x1D588, 'M', 'c'), + (0x1D589, 'M', 'd'), + (0x1D58A, 'M', 'e'), + (0x1D58B, 'M', 'f'), + (0x1D58C, 'M', 'g'), + (0x1D58D, 'M', 'h'), + (0x1D58E, 'M', 'i'), + (0x1D58F, 'M', 'j'), + (0x1D590, 'M', 'k'), + (0x1D591, 'M', 'l'), + (0x1D592, 'M', 'm'), + (0x1D593, 'M', 'n'), + (0x1D594, 'M', 'o'), + (0x1D595, 'M', 'p'), + (0x1D596, 'M', 'q'), + (0x1D597, 'M', 'r'), + (0x1D598, 'M', 's'), + (0x1D599, 'M', 't'), + (0x1D59A, 'M', 'u'), + (0x1D59B, 'M', 'v'), + (0x1D59C, 'M', 'w'), + (0x1D59D, 'M', 'x'), + (0x1D59E, 'M', 'y'), + (0x1D59F, 'M', 'z'), + (0x1D5A0, 'M', 'a'), + (0x1D5A1, 'M', 'b'), + (0x1D5A2, 'M', 'c'), + (0x1D5A3, 'M', 'd'), + (0x1D5A4, 'M', 'e'), + (0x1D5A5, 'M', 'f'), + (0x1D5A6, 'M', 'g'), + (0x1D5A7, 'M', 'h'), + (0x1D5A8, 'M', 'i'), + (0x1D5A9, 'M', 'j'), + (0x1D5AA, 'M', 'k'), + (0x1D5AB, 'M', 'l'), + (0x1D5AC, 'M', 'm'), + (0x1D5AD, 'M', 'n'), + (0x1D5AE, 'M', 'o'), + (0x1D5AF, 'M', 'p'), + (0x1D5B0, 'M', 'q'), + (0x1D5B1, 'M', 'r'), + (0x1D5B2, 'M', 's'), + (0x1D5B3, 'M', 't'), + (0x1D5B4, 'M', 'u'), + (0x1D5B5, 'M', 'v'), + (0x1D5B6, 'M', 'w'), + (0x1D5B7, 'M', 'x'), + (0x1D5B8, 'M', 'y'), + (0x1D5B9, 'M', 'z'), + (0x1D5BA, 'M', 'a'), + (0x1D5BB, 'M', 'b'), + (0x1D5BC, 'M', 'c'), + (0x1D5BD, 'M', 'd'), + (0x1D5BE, 'M', 'e'), + (0x1D5BF, 'M', 'f'), + (0x1D5C0, 'M', 'g'), + (0x1D5C1, 'M', 'h'), + (0x1D5C2, 'M', 'i'), + (0x1D5C3, 'M', 'j'), + (0x1D5C4, 'M', 'k'), + (0x1D5C5, 'M', 'l'), + (0x1D5C6, 'M', 'm'), + (0x1D5C7, 'M', 'n'), + (0x1D5C8, 'M', 'o'), + (0x1D5C9, 'M', 'p'), + (0x1D5CA, 'M', 'q'), + (0x1D5CB, 'M', 'r'), + (0x1D5CC, 'M', 's'), + (0x1D5CD, 'M', 't'), + (0x1D5CE, 'M', 'u'), + (0x1D5CF, 'M', 'v'), + (0x1D5D0, 'M', 'w'), + (0x1D5D1, 'M', 'x'), + (0x1D5D2, 'M', 'y'), + (0x1D5D3, 'M', 'z'), + (0x1D5D4, 'M', 'a'), + (0x1D5D5, 'M', 'b'), + (0x1D5D6, 'M', 'c'), + (0x1D5D7, 'M', 'd'), + (0x1D5D8, 'M', 'e'), + (0x1D5D9, 'M', 'f'), + (0x1D5DA, 'M', 'g'), + (0x1D5DB, 'M', 'h'), + (0x1D5DC, 'M', 'i'), + (0x1D5DD, 'M', 'j'), + (0x1D5DE, 'M', 'k'), + (0x1D5DF, 'M', 'l'), + (0x1D5E0, 'M', 'm'), + (0x1D5E1, 'M', 'n'), + (0x1D5E2, 'M', 'o'), + (0x1D5E3, 'M', 'p'), + (0x1D5E4, 'M', 'q'), + (0x1D5E5, 'M', 'r'), + (0x1D5E6, 'M', 's'), + (0x1D5E7, 'M', 't'), ] def _seg_64(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D5E8, 'M', u'u'), - (0x1D5E9, 'M', u'v'), - (0x1D5EA, 'M', u'w'), - (0x1D5EB, 'M', u'x'), - (0x1D5EC, 'M', u'y'), - (0x1D5ED, 'M', u'z'), - (0x1D5EE, 'M', u'a'), - (0x1D5EF, 'M', u'b'), - (0x1D5F0, 'M', u'c'), - (0x1D5F1, 'M', u'd'), - (0x1D5F2, 'M', u'e'), - (0x1D5F3, 'M', u'f'), - (0x1D5F4, 'M', u'g'), - (0x1D5F5, 'M', u'h'), - (0x1D5F6, 'M', u'i'), - (0x1D5F7, 'M', u'j'), - (0x1D5F8, 'M', u'k'), - (0x1D5F9, 'M', u'l'), - (0x1D5FA, 'M', u'm'), - (0x1D5FB, 'M', u'n'), - (0x1D5FC, 'M', u'o'), - (0x1D5FD, 'M', u'p'), - (0x1D5FE, 'M', u'q'), - (0x1D5FF, 'M', u'r'), - (0x1D600, 'M', u's'), - (0x1D601, 'M', u't'), - (0x1D602, 'M', u'u'), - (0x1D603, 'M', u'v'), - (0x1D604, 'M', u'w'), - (0x1D605, 'M', u'x'), - (0x1D606, 'M', u'y'), - (0x1D607, 'M', u'z'), - (0x1D608, 'M', u'a'), - (0x1D609, 'M', u'b'), - (0x1D60A, 'M', u'c'), - (0x1D60B, 'M', u'd'), - (0x1D60C, 'M', u'e'), - (0x1D60D, 'M', u'f'), - (0x1D60E, 'M', u'g'), - (0x1D60F, 'M', u'h'), - (0x1D610, 'M', u'i'), - (0x1D611, 'M', u'j'), - (0x1D612, 'M', u'k'), - (0x1D613, 'M', u'l'), - (0x1D614, 'M', u'm'), - (0x1D615, 'M', u'n'), - (0x1D616, 'M', u'o'), - (0x1D617, 'M', u'p'), - (0x1D618, 'M', u'q'), - (0x1D619, 'M', u'r'), - (0x1D61A, 'M', u's'), - (0x1D61B, 'M', u't'), - (0x1D61C, 'M', u'u'), - (0x1D61D, 'M', u'v'), - (0x1D61E, 'M', u'w'), - (0x1D61F, 'M', u'x'), - (0x1D620, 'M', u'y'), - (0x1D621, 'M', u'z'), - (0x1D622, 'M', u'a'), - (0x1D623, 'M', u'b'), - (0x1D624, 'M', u'c'), - (0x1D625, 'M', u'd'), - (0x1D626, 'M', u'e'), - (0x1D627, 'M', u'f'), - (0x1D628, 'M', u'g'), - (0x1D629, 'M', u'h'), - (0x1D62A, 'M', u'i'), - (0x1D62B, 'M', u'j'), - (0x1D62C, 'M', u'k'), - (0x1D62D, 'M', u'l'), - (0x1D62E, 'M', u'm'), - (0x1D62F, 'M', u'n'), - (0x1D630, 'M', u'o'), - (0x1D631, 'M', u'p'), - (0x1D632, 'M', u'q'), - (0x1D633, 'M', u'r'), - (0x1D634, 'M', u's'), - (0x1D635, 'M', u't'), - (0x1D636, 'M', u'u'), - (0x1D637, 'M', u'v'), - (0x1D638, 'M', u'w'), - (0x1D639, 'M', u'x'), - (0x1D63A, 'M', u'y'), - (0x1D63B, 'M', u'z'), - (0x1D63C, 'M', u'a'), - (0x1D63D, 'M', u'b'), - (0x1D63E, 'M', u'c'), - (0x1D63F, 'M', u'd'), - (0x1D640, 'M', u'e'), - (0x1D641, 'M', u'f'), - (0x1D642, 'M', u'g'), - (0x1D643, 'M', u'h'), - (0x1D644, 'M', u'i'), - (0x1D645, 'M', u'j'), - (0x1D646, 'M', u'k'), - (0x1D647, 'M', u'l'), - (0x1D648, 'M', u'm'), - (0x1D649, 'M', u'n'), - (0x1D64A, 'M', u'o'), - (0x1D64B, 'M', u'p'), + (0x1D5E8, 'M', 'u'), + (0x1D5E9, 'M', 'v'), + (0x1D5EA, 'M', 'w'), + (0x1D5EB, 'M', 'x'), + (0x1D5EC, 'M', 'y'), + (0x1D5ED, 'M', 'z'), + (0x1D5EE, 'M', 'a'), + (0x1D5EF, 'M', 'b'), + (0x1D5F0, 'M', 'c'), + (0x1D5F1, 'M', 'd'), + (0x1D5F2, 'M', 'e'), + (0x1D5F3, 'M', 'f'), + (0x1D5F4, 'M', 'g'), + (0x1D5F5, 'M', 'h'), + (0x1D5F6, 'M', 'i'), + (0x1D5F7, 'M', 'j'), + (0x1D5F8, 'M', 'k'), + (0x1D5F9, 'M', 'l'), + (0x1D5FA, 'M', 'm'), + (0x1D5FB, 'M', 'n'), + (0x1D5FC, 'M', 'o'), + (0x1D5FD, 'M', 'p'), + (0x1D5FE, 'M', 'q'), + (0x1D5FF, 'M', 'r'), + (0x1D600, 'M', 's'), + (0x1D601, 'M', 't'), + (0x1D602, 'M', 'u'), + (0x1D603, 'M', 'v'), + (0x1D604, 'M', 'w'), + (0x1D605, 'M', 'x'), + (0x1D606, 'M', 'y'), + (0x1D607, 'M', 'z'), + (0x1D608, 'M', 'a'), + (0x1D609, 'M', 'b'), + (0x1D60A, 'M', 'c'), + (0x1D60B, 'M', 'd'), + (0x1D60C, 'M', 'e'), + (0x1D60D, 'M', 'f'), + (0x1D60E, 'M', 'g'), + (0x1D60F, 'M', 'h'), + (0x1D610, 'M', 'i'), + (0x1D611, 'M', 'j'), + (0x1D612, 'M', 'k'), + (0x1D613, 'M', 'l'), + (0x1D614, 'M', 'm'), + (0x1D615, 'M', 'n'), + (0x1D616, 'M', 'o'), + (0x1D617, 'M', 'p'), + (0x1D618, 'M', 'q'), + (0x1D619, 'M', 'r'), + (0x1D61A, 'M', 's'), + (0x1D61B, 'M', 't'), + (0x1D61C, 'M', 'u'), + (0x1D61D, 'M', 'v'), + (0x1D61E, 'M', 'w'), + (0x1D61F, 'M', 'x'), + (0x1D620, 'M', 'y'), + (0x1D621, 'M', 'z'), + (0x1D622, 'M', 'a'), + (0x1D623, 'M', 'b'), + (0x1D624, 'M', 'c'), + (0x1D625, 'M', 'd'), + (0x1D626, 'M', 'e'), + (0x1D627, 'M', 'f'), + (0x1D628, 'M', 'g'), + (0x1D629, 'M', 'h'), + (0x1D62A, 'M', 'i'), + (0x1D62B, 'M', 'j'), + (0x1D62C, 'M', 'k'), + (0x1D62D, 'M', 'l'), + (0x1D62E, 'M', 'm'), + (0x1D62F, 'M', 'n'), + (0x1D630, 'M', 'o'), + (0x1D631, 'M', 'p'), + (0x1D632, 'M', 'q'), + (0x1D633, 'M', 'r'), + (0x1D634, 'M', 's'), + (0x1D635, 'M', 't'), + (0x1D636, 'M', 'u'), + (0x1D637, 'M', 'v'), + (0x1D638, 'M', 'w'), + (0x1D639, 'M', 'x'), + (0x1D63A, 'M', 'y'), + (0x1D63B, 'M', 'z'), + (0x1D63C, 'M', 'a'), + (0x1D63D, 'M', 'b'), + (0x1D63E, 'M', 'c'), + (0x1D63F, 'M', 'd'), + (0x1D640, 'M', 'e'), + (0x1D641, 'M', 'f'), + (0x1D642, 'M', 'g'), + (0x1D643, 'M', 'h'), + (0x1D644, 'M', 'i'), + (0x1D645, 'M', 'j'), + (0x1D646, 'M', 'k'), + (0x1D647, 'M', 'l'), + (0x1D648, 'M', 'm'), + (0x1D649, 'M', 'n'), + (0x1D64A, 'M', 'o'), + (0x1D64B, 'M', 'p'), ] def _seg_65(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D64C, 'M', u'q'), - (0x1D64D, 'M', u'r'), - (0x1D64E, 'M', u's'), - (0x1D64F, 'M', u't'), - (0x1D650, 'M', u'u'), - (0x1D651, 'M', u'v'), - (0x1D652, 'M', u'w'), - (0x1D653, 'M', u'x'), - (0x1D654, 'M', u'y'), - (0x1D655, 'M', u'z'), - (0x1D656, 'M', u'a'), - (0x1D657, 'M', u'b'), - (0x1D658, 'M', u'c'), - (0x1D659, 'M', u'd'), - (0x1D65A, 'M', u'e'), - (0x1D65B, 'M', u'f'), - (0x1D65C, 'M', u'g'), - (0x1D65D, 'M', u'h'), - (0x1D65E, 'M', u'i'), - (0x1D65F, 'M', u'j'), - (0x1D660, 'M', u'k'), - (0x1D661, 'M', u'l'), - (0x1D662, 'M', u'm'), - (0x1D663, 'M', u'n'), - (0x1D664, 'M', u'o'), - (0x1D665, 'M', u'p'), - (0x1D666, 'M', u'q'), - (0x1D667, 'M', u'r'), - (0x1D668, 'M', u's'), - (0x1D669, 'M', u't'), - (0x1D66A, 'M', u'u'), - (0x1D66B, 'M', u'v'), - (0x1D66C, 'M', u'w'), - (0x1D66D, 'M', u'x'), - (0x1D66E, 'M', u'y'), - (0x1D66F, 'M', u'z'), - (0x1D670, 'M', u'a'), - (0x1D671, 'M', u'b'), - (0x1D672, 'M', u'c'), - (0x1D673, 'M', u'd'), - (0x1D674, 'M', u'e'), - (0x1D675, 'M', u'f'), - (0x1D676, 'M', u'g'), - (0x1D677, 'M', u'h'), - (0x1D678, 'M', u'i'), - (0x1D679, 'M', u'j'), - (0x1D67A, 'M', u'k'), - (0x1D67B, 'M', u'l'), - (0x1D67C, 'M', u'm'), - (0x1D67D, 'M', u'n'), - (0x1D67E, 'M', u'o'), - (0x1D67F, 'M', u'p'), - (0x1D680, 'M', u'q'), - (0x1D681, 'M', u'r'), - (0x1D682, 'M', u's'), - (0x1D683, 'M', u't'), - (0x1D684, 'M', u'u'), - (0x1D685, 'M', u'v'), - (0x1D686, 'M', u'w'), - (0x1D687, 'M', u'x'), - (0x1D688, 'M', u'y'), - (0x1D689, 'M', u'z'), - (0x1D68A, 'M', u'a'), - (0x1D68B, 'M', u'b'), - (0x1D68C, 'M', u'c'), - (0x1D68D, 'M', u'd'), - (0x1D68E, 'M', u'e'), - (0x1D68F, 'M', u'f'), - (0x1D690, 'M', u'g'), - (0x1D691, 'M', u'h'), - (0x1D692, 'M', u'i'), - (0x1D693, 'M', u'j'), - (0x1D694, 'M', u'k'), - (0x1D695, 'M', u'l'), - (0x1D696, 'M', u'm'), - (0x1D697, 'M', u'n'), - (0x1D698, 'M', u'o'), - (0x1D699, 'M', u'p'), - (0x1D69A, 'M', u'q'), - (0x1D69B, 'M', u'r'), - (0x1D69C, 'M', u's'), - (0x1D69D, 'M', u't'), - (0x1D69E, 'M', u'u'), - (0x1D69F, 'M', u'v'), - (0x1D6A0, 'M', u'w'), - (0x1D6A1, 'M', u'x'), - (0x1D6A2, 'M', u'y'), - (0x1D6A3, 'M', u'z'), - (0x1D6A4, 'M', u'ı'), - (0x1D6A5, 'M', u'ȷ'), + (0x1D64C, 'M', 'q'), + (0x1D64D, 'M', 'r'), + (0x1D64E, 'M', 's'), + (0x1D64F, 'M', 't'), + (0x1D650, 'M', 'u'), + (0x1D651, 'M', 'v'), + (0x1D652, 'M', 'w'), + (0x1D653, 'M', 'x'), + (0x1D654, 'M', 'y'), + (0x1D655, 'M', 'z'), + (0x1D656, 'M', 'a'), + (0x1D657, 'M', 'b'), + (0x1D658, 'M', 'c'), + (0x1D659, 'M', 'd'), + (0x1D65A, 'M', 'e'), + (0x1D65B, 'M', 'f'), + (0x1D65C, 'M', 'g'), + (0x1D65D, 'M', 'h'), + (0x1D65E, 'M', 'i'), + (0x1D65F, 'M', 'j'), + (0x1D660, 'M', 'k'), + (0x1D661, 'M', 'l'), + (0x1D662, 'M', 'm'), + (0x1D663, 'M', 'n'), + (0x1D664, 'M', 'o'), + (0x1D665, 'M', 'p'), + (0x1D666, 'M', 'q'), + (0x1D667, 'M', 'r'), + (0x1D668, 'M', 's'), + (0x1D669, 'M', 't'), + (0x1D66A, 'M', 'u'), + (0x1D66B, 'M', 'v'), + (0x1D66C, 'M', 'w'), + (0x1D66D, 'M', 'x'), + (0x1D66E, 'M', 'y'), + (0x1D66F, 'M', 'z'), + (0x1D670, 'M', 'a'), + (0x1D671, 'M', 'b'), + (0x1D672, 'M', 'c'), + (0x1D673, 'M', 'd'), + (0x1D674, 'M', 'e'), + (0x1D675, 'M', 'f'), + (0x1D676, 'M', 'g'), + (0x1D677, 'M', 'h'), + (0x1D678, 'M', 'i'), + (0x1D679, 'M', 'j'), + (0x1D67A, 'M', 'k'), + (0x1D67B, 'M', 'l'), + (0x1D67C, 'M', 'm'), + (0x1D67D, 'M', 'n'), + (0x1D67E, 'M', 'o'), + (0x1D67F, 'M', 'p'), + (0x1D680, 'M', 'q'), + (0x1D681, 'M', 'r'), + (0x1D682, 'M', 's'), + (0x1D683, 'M', 't'), + (0x1D684, 'M', 'u'), + (0x1D685, 'M', 'v'), + (0x1D686, 'M', 'w'), + (0x1D687, 'M', 'x'), + (0x1D688, 'M', 'y'), + (0x1D689, 'M', 'z'), + (0x1D68A, 'M', 'a'), + (0x1D68B, 'M', 'b'), + (0x1D68C, 'M', 'c'), + (0x1D68D, 'M', 'd'), + (0x1D68E, 'M', 'e'), + (0x1D68F, 'M', 'f'), + (0x1D690, 'M', 'g'), + (0x1D691, 'M', 'h'), + (0x1D692, 'M', 'i'), + (0x1D693, 'M', 'j'), + (0x1D694, 'M', 'k'), + (0x1D695, 'M', 'l'), + (0x1D696, 'M', 'm'), + (0x1D697, 'M', 'n'), + (0x1D698, 'M', 'o'), + (0x1D699, 'M', 'p'), + (0x1D69A, 'M', 'q'), + (0x1D69B, 'M', 'r'), + (0x1D69C, 'M', 's'), + (0x1D69D, 'M', 't'), + (0x1D69E, 'M', 'u'), + (0x1D69F, 'M', 'v'), + (0x1D6A0, 'M', 'w'), + (0x1D6A1, 'M', 'x'), + (0x1D6A2, 'M', 'y'), + (0x1D6A3, 'M', 'z'), + (0x1D6A4, 'M', 'ı'), + (0x1D6A5, 'M', 'ȷ'), (0x1D6A6, 'X'), - (0x1D6A8, 'M', u'α'), - (0x1D6A9, 'M', u'β'), - (0x1D6AA, 'M', u'γ'), - (0x1D6AB, 'M', u'δ'), - (0x1D6AC, 'M', u'ε'), - (0x1D6AD, 'M', u'ζ'), - (0x1D6AE, 'M', u'η'), - (0x1D6AF, 'M', u'θ'), - (0x1D6B0, 'M', u'ι'), + (0x1D6A8, 'M', 'α'), + (0x1D6A9, 'M', 'β'), + (0x1D6AA, 'M', 'γ'), + (0x1D6AB, 'M', 'δ'), + (0x1D6AC, 'M', 'ε'), + (0x1D6AD, 'M', 'ζ'), + (0x1D6AE, 'M', 'η'), + (0x1D6AF, 'M', 'θ'), + (0x1D6B0, 'M', 'ι'), ] def _seg_66(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D6B1, 'M', u'κ'), - (0x1D6B2, 'M', u'λ'), - (0x1D6B3, 'M', u'μ'), - (0x1D6B4, 'M', u'ν'), - (0x1D6B5, 'M', u'ξ'), - (0x1D6B6, 'M', u'ο'), - (0x1D6B7, 'M', u'π'), - (0x1D6B8, 'M', u'ρ'), - (0x1D6B9, 'M', u'θ'), - (0x1D6BA, 'M', u'σ'), - (0x1D6BB, 'M', u'τ'), - (0x1D6BC, 'M', u'υ'), - (0x1D6BD, 'M', u'φ'), - (0x1D6BE, 'M', u'χ'), - (0x1D6BF, 'M', u'ψ'), - (0x1D6C0, 'M', u'ω'), - (0x1D6C1, 'M', u'∇'), - (0x1D6C2, 'M', u'α'), - (0x1D6C3, 'M', u'β'), - (0x1D6C4, 'M', u'γ'), - (0x1D6C5, 'M', u'δ'), - (0x1D6C6, 'M', u'ε'), - (0x1D6C7, 'M', u'ζ'), - (0x1D6C8, 'M', u'η'), - (0x1D6C9, 'M', u'θ'), - (0x1D6CA, 'M', u'ι'), - (0x1D6CB, 'M', u'κ'), - (0x1D6CC, 'M', u'λ'), - (0x1D6CD, 'M', u'μ'), - (0x1D6CE, 'M', u'ν'), - (0x1D6CF, 'M', u'ξ'), - (0x1D6D0, 'M', u'ο'), - (0x1D6D1, 'M', u'π'), - (0x1D6D2, 'M', u'ρ'), - (0x1D6D3, 'M', u'σ'), - (0x1D6D5, 'M', u'τ'), - (0x1D6D6, 'M', u'υ'), - (0x1D6D7, 'M', u'φ'), - (0x1D6D8, 'M', u'χ'), - (0x1D6D9, 'M', u'ψ'), - (0x1D6DA, 'M', u'ω'), - (0x1D6DB, 'M', u'∂'), - (0x1D6DC, 'M', u'ε'), - (0x1D6DD, 'M', u'θ'), - (0x1D6DE, 'M', u'κ'), - (0x1D6DF, 'M', u'φ'), - (0x1D6E0, 'M', u'ρ'), - (0x1D6E1, 'M', u'π'), - (0x1D6E2, 'M', u'α'), - (0x1D6E3, 'M', u'β'), - (0x1D6E4, 'M', u'γ'), - (0x1D6E5, 'M', u'δ'), - (0x1D6E6, 'M', u'ε'), - (0x1D6E7, 'M', u'ζ'), - (0x1D6E8, 'M', u'η'), - (0x1D6E9, 'M', u'θ'), - (0x1D6EA, 'M', u'ι'), - (0x1D6EB, 'M', u'κ'), - (0x1D6EC, 'M', u'λ'), - (0x1D6ED, 'M', u'μ'), - (0x1D6EE, 'M', u'ν'), - (0x1D6EF, 'M', u'ξ'), - (0x1D6F0, 'M', u'ο'), - (0x1D6F1, 'M', u'π'), - (0x1D6F2, 'M', u'ρ'), - (0x1D6F3, 'M', u'θ'), - (0x1D6F4, 'M', u'σ'), - (0x1D6F5, 'M', u'τ'), - (0x1D6F6, 'M', u'υ'), - (0x1D6F7, 'M', u'φ'), - (0x1D6F8, 'M', u'χ'), - (0x1D6F9, 'M', u'ψ'), - (0x1D6FA, 'M', u'ω'), - (0x1D6FB, 'M', u'∇'), - (0x1D6FC, 'M', u'α'), - (0x1D6FD, 'M', u'β'), - (0x1D6FE, 'M', u'γ'), - (0x1D6FF, 'M', u'δ'), - (0x1D700, 'M', u'ε'), - (0x1D701, 'M', u'ζ'), - (0x1D702, 'M', u'η'), - (0x1D703, 'M', u'θ'), - (0x1D704, 'M', u'ι'), - (0x1D705, 'M', u'κ'), - (0x1D706, 'M', u'λ'), - (0x1D707, 'M', u'μ'), - (0x1D708, 'M', u'ν'), - (0x1D709, 'M', u'ξ'), - (0x1D70A, 'M', u'ο'), - (0x1D70B, 'M', u'π'), - (0x1D70C, 'M', u'ρ'), - (0x1D70D, 'M', u'σ'), - (0x1D70F, 'M', u'τ'), - (0x1D710, 'M', u'υ'), - (0x1D711, 'M', u'φ'), - (0x1D712, 'M', u'χ'), - (0x1D713, 'M', u'ψ'), - (0x1D714, 'M', u'ω'), - (0x1D715, 'M', u'∂'), - (0x1D716, 'M', u'ε'), + (0x1D6B1, 'M', 'κ'), + (0x1D6B2, 'M', 'λ'), + (0x1D6B3, 'M', 'μ'), + (0x1D6B4, 'M', 'ν'), + (0x1D6B5, 'M', 'ξ'), + (0x1D6B6, 'M', 'ο'), + (0x1D6B7, 'M', 'π'), + (0x1D6B8, 'M', 'ρ'), + (0x1D6B9, 'M', 'θ'), + (0x1D6BA, 'M', 'σ'), + (0x1D6BB, 'M', 'τ'), + (0x1D6BC, 'M', 'υ'), + (0x1D6BD, 'M', 'φ'), + (0x1D6BE, 'M', 'χ'), + (0x1D6BF, 'M', 'ψ'), + (0x1D6C0, 'M', 'ω'), + (0x1D6C1, 'M', '∇'), + (0x1D6C2, 'M', 'α'), + (0x1D6C3, 'M', 'β'), + (0x1D6C4, 'M', 'γ'), + (0x1D6C5, 'M', 'δ'), + (0x1D6C6, 'M', 'ε'), + (0x1D6C7, 'M', 'ζ'), + (0x1D6C8, 'M', 'η'), + (0x1D6C9, 'M', 'θ'), + (0x1D6CA, 'M', 'ι'), + (0x1D6CB, 'M', 'κ'), + (0x1D6CC, 'M', 'λ'), + (0x1D6CD, 'M', 'μ'), + (0x1D6CE, 'M', 'ν'), + (0x1D6CF, 'M', 'ξ'), + (0x1D6D0, 'M', 'ο'), + (0x1D6D1, 'M', 'π'), + (0x1D6D2, 'M', 'ρ'), + (0x1D6D3, 'M', 'σ'), + (0x1D6D5, 'M', 'τ'), + (0x1D6D6, 'M', 'υ'), + (0x1D6D7, 'M', 'φ'), + (0x1D6D8, 'M', 'χ'), + (0x1D6D9, 'M', 'ψ'), + (0x1D6DA, 'M', 'ω'), + (0x1D6DB, 'M', '∂'), + (0x1D6DC, 'M', 'ε'), + (0x1D6DD, 'M', 'θ'), + (0x1D6DE, 'M', 'κ'), + (0x1D6DF, 'M', 'φ'), + (0x1D6E0, 'M', 'ρ'), + (0x1D6E1, 'M', 'π'), + (0x1D6E2, 'M', 'α'), + (0x1D6E3, 'M', 'β'), + (0x1D6E4, 'M', 'γ'), + (0x1D6E5, 'M', 'δ'), + (0x1D6E6, 'M', 'ε'), + (0x1D6E7, 'M', 'ζ'), + (0x1D6E8, 'M', 'η'), + (0x1D6E9, 'M', 'θ'), + (0x1D6EA, 'M', 'ι'), + (0x1D6EB, 'M', 'κ'), + (0x1D6EC, 'M', 'λ'), + (0x1D6ED, 'M', 'μ'), + (0x1D6EE, 'M', 'ν'), + (0x1D6EF, 'M', 'ξ'), + (0x1D6F0, 'M', 'ο'), + (0x1D6F1, 'M', 'π'), + (0x1D6F2, 'M', 'ρ'), + (0x1D6F3, 'M', 'θ'), + (0x1D6F4, 'M', 'σ'), + (0x1D6F5, 'M', 'τ'), + (0x1D6F6, 'M', 'υ'), + (0x1D6F7, 'M', 'φ'), + (0x1D6F8, 'M', 'χ'), + (0x1D6F9, 'M', 'ψ'), + (0x1D6FA, 'M', 'ω'), + (0x1D6FB, 'M', '∇'), + (0x1D6FC, 'M', 'α'), + (0x1D6FD, 'M', 'β'), + (0x1D6FE, 'M', 'γ'), + (0x1D6FF, 'M', 'δ'), + (0x1D700, 'M', 'ε'), + (0x1D701, 'M', 'ζ'), + (0x1D702, 'M', 'η'), + (0x1D703, 'M', 'θ'), + (0x1D704, 'M', 'ι'), + (0x1D705, 'M', 'κ'), + (0x1D706, 'M', 'λ'), + (0x1D707, 'M', 'μ'), + (0x1D708, 'M', 'ν'), + (0x1D709, 'M', 'ξ'), + (0x1D70A, 'M', 'ο'), + (0x1D70B, 'M', 'π'), + (0x1D70C, 'M', 'ρ'), + (0x1D70D, 'M', 'σ'), + (0x1D70F, 'M', 'τ'), + (0x1D710, 'M', 'υ'), + (0x1D711, 'M', 'φ'), + (0x1D712, 'M', 'χ'), + (0x1D713, 'M', 'ψ'), + (0x1D714, 'M', 'ω'), + (0x1D715, 'M', '∂'), + (0x1D716, 'M', 'ε'), ] def _seg_67(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D717, 'M', u'θ'), - (0x1D718, 'M', u'κ'), - (0x1D719, 'M', u'φ'), - (0x1D71A, 'M', u'ρ'), - (0x1D71B, 'M', u'π'), - (0x1D71C, 'M', u'α'), - (0x1D71D, 'M', u'β'), - (0x1D71E, 'M', u'γ'), - (0x1D71F, 'M', u'δ'), - (0x1D720, 'M', u'ε'), - (0x1D721, 'M', u'ζ'), - (0x1D722, 'M', u'η'), - (0x1D723, 'M', u'θ'), - (0x1D724, 'M', u'ι'), - (0x1D725, 'M', u'κ'), - (0x1D726, 'M', u'λ'), - (0x1D727, 'M', u'μ'), - (0x1D728, 'M', u'ν'), - (0x1D729, 'M', u'ξ'), - (0x1D72A, 'M', u'ο'), - (0x1D72B, 'M', u'π'), - (0x1D72C, 'M', u'ρ'), - (0x1D72D, 'M', u'θ'), - (0x1D72E, 'M', u'σ'), - (0x1D72F, 'M', u'τ'), - (0x1D730, 'M', u'υ'), - (0x1D731, 'M', u'φ'), - (0x1D732, 'M', u'χ'), - (0x1D733, 'M', u'ψ'), - (0x1D734, 'M', u'ω'), - (0x1D735, 'M', u'∇'), - (0x1D736, 'M', u'α'), - (0x1D737, 'M', u'β'), - (0x1D738, 'M', u'γ'), - (0x1D739, 'M', u'δ'), - (0x1D73A, 'M', u'ε'), - (0x1D73B, 'M', u'ζ'), - (0x1D73C, 'M', u'η'), - (0x1D73D, 'M', u'θ'), - (0x1D73E, 'M', u'ι'), - (0x1D73F, 'M', u'κ'), - (0x1D740, 'M', u'λ'), - (0x1D741, 'M', u'μ'), - (0x1D742, 'M', u'ν'), - (0x1D743, 'M', u'ξ'), - (0x1D744, 'M', u'ο'), - (0x1D745, 'M', u'π'), - (0x1D746, 'M', u'ρ'), - (0x1D747, 'M', u'σ'), - (0x1D749, 'M', u'τ'), - (0x1D74A, 'M', u'υ'), - (0x1D74B, 'M', u'φ'), - (0x1D74C, 'M', u'χ'), - (0x1D74D, 'M', u'ψ'), - (0x1D74E, 'M', u'ω'), - (0x1D74F, 'M', u'∂'), - (0x1D750, 'M', u'ε'), - (0x1D751, 'M', u'θ'), - (0x1D752, 'M', u'κ'), - (0x1D753, 'M', u'φ'), - (0x1D754, 'M', u'ρ'), - (0x1D755, 'M', u'π'), - (0x1D756, 'M', u'α'), - (0x1D757, 'M', u'β'), - (0x1D758, 'M', u'γ'), - (0x1D759, 'M', u'δ'), - (0x1D75A, 'M', u'ε'), - (0x1D75B, 'M', u'ζ'), - (0x1D75C, 'M', u'η'), - (0x1D75D, 'M', u'θ'), - (0x1D75E, 'M', u'ι'), - (0x1D75F, 'M', u'κ'), - (0x1D760, 'M', u'λ'), - (0x1D761, 'M', u'μ'), - (0x1D762, 'M', u'ν'), - (0x1D763, 'M', u'ξ'), - (0x1D764, 'M', u'ο'), - (0x1D765, 'M', u'π'), - (0x1D766, 'M', u'ρ'), - (0x1D767, 'M', u'θ'), - (0x1D768, 'M', u'σ'), - (0x1D769, 'M', u'τ'), - (0x1D76A, 'M', u'υ'), - (0x1D76B, 'M', u'φ'), - (0x1D76C, 'M', u'χ'), - (0x1D76D, 'M', u'ψ'), - (0x1D76E, 'M', u'ω'), - (0x1D76F, 'M', u'∇'), - (0x1D770, 'M', u'α'), - (0x1D771, 'M', u'β'), - (0x1D772, 'M', u'γ'), - (0x1D773, 'M', u'δ'), - (0x1D774, 'M', u'ε'), - (0x1D775, 'M', u'ζ'), - (0x1D776, 'M', u'η'), - (0x1D777, 'M', u'θ'), - (0x1D778, 'M', u'ι'), - (0x1D779, 'M', u'κ'), - (0x1D77A, 'M', u'λ'), - (0x1D77B, 'M', u'μ'), + (0x1D717, 'M', 'θ'), + (0x1D718, 'M', 'κ'), + (0x1D719, 'M', 'φ'), + (0x1D71A, 'M', 'ρ'), + (0x1D71B, 'M', 'π'), + (0x1D71C, 'M', 'α'), + (0x1D71D, 'M', 'β'), + (0x1D71E, 'M', 'γ'), + (0x1D71F, 'M', 'δ'), + (0x1D720, 'M', 'ε'), + (0x1D721, 'M', 'ζ'), + (0x1D722, 'M', 'η'), + (0x1D723, 'M', 'θ'), + (0x1D724, 'M', 'ι'), + (0x1D725, 'M', 'κ'), + (0x1D726, 'M', 'λ'), + (0x1D727, 'M', 'μ'), + (0x1D728, 'M', 'ν'), + (0x1D729, 'M', 'ξ'), + (0x1D72A, 'M', 'ο'), + (0x1D72B, 'M', 'π'), + (0x1D72C, 'M', 'ρ'), + (0x1D72D, 'M', 'θ'), + (0x1D72E, 'M', 'σ'), + (0x1D72F, 'M', 'τ'), + (0x1D730, 'M', 'υ'), + (0x1D731, 'M', 'φ'), + (0x1D732, 'M', 'χ'), + (0x1D733, 'M', 'ψ'), + (0x1D734, 'M', 'ω'), + (0x1D735, 'M', '∇'), + (0x1D736, 'M', 'α'), + (0x1D737, 'M', 'β'), + (0x1D738, 'M', 'γ'), + (0x1D739, 'M', 'δ'), + (0x1D73A, 'M', 'ε'), + (0x1D73B, 'M', 'ζ'), + (0x1D73C, 'M', 'η'), + (0x1D73D, 'M', 'θ'), + (0x1D73E, 'M', 'ι'), + (0x1D73F, 'M', 'κ'), + (0x1D740, 'M', 'λ'), + (0x1D741, 'M', 'μ'), + (0x1D742, 'M', 'ν'), + (0x1D743, 'M', 'ξ'), + (0x1D744, 'M', 'ο'), + (0x1D745, 'M', 'π'), + (0x1D746, 'M', 'ρ'), + (0x1D747, 'M', 'σ'), + (0x1D749, 'M', 'τ'), + (0x1D74A, 'M', 'υ'), + (0x1D74B, 'M', 'φ'), + (0x1D74C, 'M', 'χ'), + (0x1D74D, 'M', 'ψ'), + (0x1D74E, 'M', 'ω'), + (0x1D74F, 'M', '∂'), + (0x1D750, 'M', 'ε'), + (0x1D751, 'M', 'θ'), + (0x1D752, 'M', 'κ'), + (0x1D753, 'M', 'φ'), + (0x1D754, 'M', 'ρ'), + (0x1D755, 'M', 'π'), + (0x1D756, 'M', 'α'), + (0x1D757, 'M', 'β'), + (0x1D758, 'M', 'γ'), + (0x1D759, 'M', 'δ'), + (0x1D75A, 'M', 'ε'), + (0x1D75B, 'M', 'ζ'), + (0x1D75C, 'M', 'η'), + (0x1D75D, 'M', 'θ'), + (0x1D75E, 'M', 'ι'), + (0x1D75F, 'M', 'κ'), + (0x1D760, 'M', 'λ'), + (0x1D761, 'M', 'μ'), + (0x1D762, 'M', 'ν'), + (0x1D763, 'M', 'ξ'), + (0x1D764, 'M', 'ο'), + (0x1D765, 'M', 'π'), + (0x1D766, 'M', 'ρ'), + (0x1D767, 'M', 'θ'), + (0x1D768, 'M', 'σ'), + (0x1D769, 'M', 'τ'), + (0x1D76A, 'M', 'υ'), + (0x1D76B, 'M', 'φ'), + (0x1D76C, 'M', 'χ'), + (0x1D76D, 'M', 'ψ'), + (0x1D76E, 'M', 'ω'), + (0x1D76F, 'M', '∇'), + (0x1D770, 'M', 'α'), + (0x1D771, 'M', 'β'), + (0x1D772, 'M', 'γ'), + (0x1D773, 'M', 'δ'), + (0x1D774, 'M', 'ε'), + (0x1D775, 'M', 'ζ'), + (0x1D776, 'M', 'η'), + (0x1D777, 'M', 'θ'), + (0x1D778, 'M', 'ι'), + (0x1D779, 'M', 'κ'), + (0x1D77A, 'M', 'λ'), + (0x1D77B, 'M', 'μ'), ] def _seg_68(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D77C, 'M', u'ν'), - (0x1D77D, 'M', u'ξ'), - (0x1D77E, 'M', u'ο'), - (0x1D77F, 'M', u'π'), - (0x1D780, 'M', u'ρ'), - (0x1D781, 'M', u'σ'), - (0x1D783, 'M', u'τ'), - (0x1D784, 'M', u'υ'), - (0x1D785, 'M', u'φ'), - (0x1D786, 'M', u'χ'), - (0x1D787, 'M', u'ψ'), - (0x1D788, 'M', u'ω'), - (0x1D789, 'M', u'∂'), - (0x1D78A, 'M', u'ε'), - (0x1D78B, 'M', u'θ'), - (0x1D78C, 'M', u'κ'), - (0x1D78D, 'M', u'φ'), - (0x1D78E, 'M', u'ρ'), - (0x1D78F, 'M', u'π'), - (0x1D790, 'M', u'α'), - (0x1D791, 'M', u'β'), - (0x1D792, 'M', u'γ'), - (0x1D793, 'M', u'δ'), - (0x1D794, 'M', u'ε'), - (0x1D795, 'M', u'ζ'), - (0x1D796, 'M', u'η'), - (0x1D797, 'M', u'θ'), - (0x1D798, 'M', u'ι'), - (0x1D799, 'M', u'κ'), - (0x1D79A, 'M', u'λ'), - (0x1D79B, 'M', u'μ'), - (0x1D79C, 'M', u'ν'), - (0x1D79D, 'M', u'ξ'), - (0x1D79E, 'M', u'ο'), - (0x1D79F, 'M', u'π'), - (0x1D7A0, 'M', u'ρ'), - (0x1D7A1, 'M', u'θ'), - (0x1D7A2, 'M', u'σ'), - (0x1D7A3, 'M', u'τ'), - (0x1D7A4, 'M', u'υ'), - (0x1D7A5, 'M', u'φ'), - (0x1D7A6, 'M', u'χ'), - (0x1D7A7, 'M', u'ψ'), - (0x1D7A8, 'M', u'ω'), - (0x1D7A9, 'M', u'∇'), - (0x1D7AA, 'M', u'α'), - (0x1D7AB, 'M', u'β'), - (0x1D7AC, 'M', u'γ'), - (0x1D7AD, 'M', u'δ'), - (0x1D7AE, 'M', u'ε'), - (0x1D7AF, 'M', u'ζ'), - (0x1D7B0, 'M', u'η'), - (0x1D7B1, 'M', u'θ'), - (0x1D7B2, 'M', u'ι'), - (0x1D7B3, 'M', u'κ'), - (0x1D7B4, 'M', u'λ'), - (0x1D7B5, 'M', u'μ'), - (0x1D7B6, 'M', u'ν'), - (0x1D7B7, 'M', u'ξ'), - (0x1D7B8, 'M', u'ο'), - (0x1D7B9, 'M', u'π'), - (0x1D7BA, 'M', u'ρ'), - (0x1D7BB, 'M', u'σ'), - (0x1D7BD, 'M', u'τ'), - (0x1D7BE, 'M', u'υ'), - (0x1D7BF, 'M', u'φ'), - (0x1D7C0, 'M', u'χ'), - (0x1D7C1, 'M', u'ψ'), - (0x1D7C2, 'M', u'ω'), - (0x1D7C3, 'M', u'∂'), - (0x1D7C4, 'M', u'ε'), - (0x1D7C5, 'M', u'θ'), - (0x1D7C6, 'M', u'κ'), - (0x1D7C7, 'M', u'φ'), - (0x1D7C8, 'M', u'ρ'), - (0x1D7C9, 'M', u'π'), - (0x1D7CA, 'M', u'ϝ'), + (0x1D77C, 'M', 'ν'), + (0x1D77D, 'M', 'ξ'), + (0x1D77E, 'M', 'ο'), + (0x1D77F, 'M', 'π'), + (0x1D780, 'M', 'ρ'), + (0x1D781, 'M', 'σ'), + (0x1D783, 'M', 'τ'), + (0x1D784, 'M', 'υ'), + (0x1D785, 'M', 'φ'), + (0x1D786, 'M', 'χ'), + (0x1D787, 'M', 'ψ'), + (0x1D788, 'M', 'ω'), + (0x1D789, 'M', '∂'), + (0x1D78A, 'M', 'ε'), + (0x1D78B, 'M', 'θ'), + (0x1D78C, 'M', 'κ'), + (0x1D78D, 'M', 'φ'), + (0x1D78E, 'M', 'ρ'), + (0x1D78F, 'M', 'π'), + (0x1D790, 'M', 'α'), + (0x1D791, 'M', 'β'), + (0x1D792, 'M', 'γ'), + (0x1D793, 'M', 'δ'), + (0x1D794, 'M', 'ε'), + (0x1D795, 'M', 'ζ'), + (0x1D796, 'M', 'η'), + (0x1D797, 'M', 'θ'), + (0x1D798, 'M', 'ι'), + (0x1D799, 'M', 'κ'), + (0x1D79A, 'M', 'λ'), + (0x1D79B, 'M', 'μ'), + (0x1D79C, 'M', 'ν'), + (0x1D79D, 'M', 'ξ'), + (0x1D79E, 'M', 'ο'), + (0x1D79F, 'M', 'π'), + (0x1D7A0, 'M', 'ρ'), + (0x1D7A1, 'M', 'θ'), + (0x1D7A2, 'M', 'σ'), + (0x1D7A3, 'M', 'τ'), + (0x1D7A4, 'M', 'υ'), + (0x1D7A5, 'M', 'φ'), + (0x1D7A6, 'M', 'χ'), + (0x1D7A7, 'M', 'ψ'), + (0x1D7A8, 'M', 'ω'), + (0x1D7A9, 'M', '∇'), + (0x1D7AA, 'M', 'α'), + (0x1D7AB, 'M', 'β'), + (0x1D7AC, 'M', 'γ'), + (0x1D7AD, 'M', 'δ'), + (0x1D7AE, 'M', 'ε'), + (0x1D7AF, 'M', 'ζ'), + (0x1D7B0, 'M', 'η'), + (0x1D7B1, 'M', 'θ'), + (0x1D7B2, 'M', 'ι'), + (0x1D7B3, 'M', 'κ'), + (0x1D7B4, 'M', 'λ'), + (0x1D7B5, 'M', 'μ'), + (0x1D7B6, 'M', 'ν'), + (0x1D7B7, 'M', 'ξ'), + (0x1D7B8, 'M', 'ο'), + (0x1D7B9, 'M', 'π'), + (0x1D7BA, 'M', 'ρ'), + (0x1D7BB, 'M', 'σ'), + (0x1D7BD, 'M', 'τ'), + (0x1D7BE, 'M', 'υ'), + (0x1D7BF, 'M', 'φ'), + (0x1D7C0, 'M', 'χ'), + (0x1D7C1, 'M', 'ψ'), + (0x1D7C2, 'M', 'ω'), + (0x1D7C3, 'M', '∂'), + (0x1D7C4, 'M', 'ε'), + (0x1D7C5, 'M', 'θ'), + (0x1D7C6, 'M', 'κ'), + (0x1D7C7, 'M', 'φ'), + (0x1D7C8, 'M', 'ρ'), + (0x1D7C9, 'M', 'π'), + (0x1D7CA, 'M', 'ϝ'), (0x1D7CC, 'X'), - (0x1D7CE, 'M', u'0'), - (0x1D7CF, 'M', u'1'), - (0x1D7D0, 'M', u'2'), - (0x1D7D1, 'M', u'3'), - (0x1D7D2, 'M', u'4'), - (0x1D7D3, 'M', u'5'), - (0x1D7D4, 'M', u'6'), - (0x1D7D5, 'M', u'7'), - (0x1D7D6, 'M', u'8'), - (0x1D7D7, 'M', u'9'), - (0x1D7D8, 'M', u'0'), - (0x1D7D9, 'M', u'1'), - (0x1D7DA, 'M', u'2'), - (0x1D7DB, 'M', u'3'), - (0x1D7DC, 'M', u'4'), - (0x1D7DD, 'M', u'5'), - (0x1D7DE, 'M', u'6'), - (0x1D7DF, 'M', u'7'), - (0x1D7E0, 'M', u'8'), - (0x1D7E1, 'M', u'9'), - (0x1D7E2, 'M', u'0'), - (0x1D7E3, 'M', u'1'), + (0x1D7CE, 'M', '0'), + (0x1D7CF, 'M', '1'), + (0x1D7D0, 'M', '2'), + (0x1D7D1, 'M', '3'), + (0x1D7D2, 'M', '4'), + (0x1D7D3, 'M', '5'), + (0x1D7D4, 'M', '6'), + (0x1D7D5, 'M', '7'), + (0x1D7D6, 'M', '8'), + (0x1D7D7, 'M', '9'), + (0x1D7D8, 'M', '0'), + (0x1D7D9, 'M', '1'), + (0x1D7DA, 'M', '2'), + (0x1D7DB, 'M', '3'), + (0x1D7DC, 'M', '4'), + (0x1D7DD, 'M', '5'), + (0x1D7DE, 'M', '6'), + (0x1D7DF, 'M', '7'), + (0x1D7E0, 'M', '8'), + (0x1D7E1, 'M', '9'), + (0x1D7E2, 'M', '0'), + (0x1D7E3, 'M', '1'), ] def _seg_69(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1D7E4, 'M', u'2'), - (0x1D7E5, 'M', u'3'), - (0x1D7E6, 'M', u'4'), - (0x1D7E7, 'M', u'5'), - (0x1D7E8, 'M', u'6'), - (0x1D7E9, 'M', u'7'), - (0x1D7EA, 'M', u'8'), - (0x1D7EB, 'M', u'9'), - (0x1D7EC, 'M', u'0'), - (0x1D7ED, 'M', u'1'), - (0x1D7EE, 'M', u'2'), - (0x1D7EF, 'M', u'3'), - (0x1D7F0, 'M', u'4'), - (0x1D7F1, 'M', u'5'), - (0x1D7F2, 'M', u'6'), - (0x1D7F3, 'M', u'7'), - (0x1D7F4, 'M', u'8'), - (0x1D7F5, 'M', u'9'), - (0x1D7F6, 'M', u'0'), - (0x1D7F7, 'M', u'1'), - (0x1D7F8, 'M', u'2'), - (0x1D7F9, 'M', u'3'), - (0x1D7FA, 'M', u'4'), - (0x1D7FB, 'M', u'5'), - (0x1D7FC, 'M', u'6'), - (0x1D7FD, 'M', u'7'), - (0x1D7FE, 'M', u'8'), - (0x1D7FF, 'M', u'9'), + (0x1D7E4, 'M', '2'), + (0x1D7E5, 'M', '3'), + (0x1D7E6, 'M', '4'), + (0x1D7E7, 'M', '5'), + (0x1D7E8, 'M', '6'), + (0x1D7E9, 'M', '7'), + (0x1D7EA, 'M', '8'), + (0x1D7EB, 'M', '9'), + (0x1D7EC, 'M', '0'), + (0x1D7ED, 'M', '1'), + (0x1D7EE, 'M', '2'), + (0x1D7EF, 'M', '3'), + (0x1D7F0, 'M', '4'), + (0x1D7F1, 'M', '5'), + (0x1D7F2, 'M', '6'), + (0x1D7F3, 'M', '7'), + (0x1D7F4, 'M', '8'), + (0x1D7F5, 'M', '9'), + (0x1D7F6, 'M', '0'), + (0x1D7F7, 'M', '1'), + (0x1D7F8, 'M', '2'), + (0x1D7F9, 'M', '3'), + (0x1D7FA, 'M', '4'), + (0x1D7FB, 'M', '5'), + (0x1D7FC, 'M', '6'), + (0x1D7FD, 'M', '7'), + (0x1D7FE, 'M', '8'), + (0x1D7FF, 'M', '9'), (0x1D800, 'V'), (0x1DA8C, 'X'), (0x1DA9B, 'V'), @@ -7243,40 +7314,40 @@ def _seg_69(): (0x1E8C5, 'X'), (0x1E8C7, 'V'), (0x1E8D7, 'X'), - (0x1E900, 'M', u'𞤢'), - (0x1E901, 'M', u'𞤣'), - (0x1E902, 'M', u'𞤤'), - (0x1E903, 'M', u'𞤥'), - (0x1E904, 'M', u'𞤦'), - (0x1E905, 'M', u'𞤧'), - (0x1E906, 'M', u'𞤨'), - (0x1E907, 'M', u'𞤩'), - (0x1E908, 'M', u'𞤪'), - (0x1E909, 'M', u'𞤫'), - (0x1E90A, 'M', u'𞤬'), - (0x1E90B, 'M', u'𞤭'), - (0x1E90C, 'M', u'𞤮'), - (0x1E90D, 'M', u'𞤯'), - (0x1E90E, 'M', u'𞤰'), - (0x1E90F, 'M', u'𞤱'), - (0x1E910, 'M', u'𞤲'), - (0x1E911, 'M', u'𞤳'), - (0x1E912, 'M', u'𞤴'), - (0x1E913, 'M', u'𞤵'), - (0x1E914, 'M', u'𞤶'), - (0x1E915, 'M', u'𞤷'), - (0x1E916, 'M', u'𞤸'), - (0x1E917, 'M', u'𞤹'), - (0x1E918, 'M', u'𞤺'), - (0x1E919, 'M', u'𞤻'), - (0x1E91A, 'M', u'𞤼'), - (0x1E91B, 'M', u'𞤽'), - (0x1E91C, 'M', u'𞤾'), - (0x1E91D, 'M', u'𞤿'), - (0x1E91E, 'M', u'𞥀'), - (0x1E91F, 'M', u'𞥁'), - (0x1E920, 'M', u'𞥂'), - (0x1E921, 'M', u'𞥃'), + (0x1E900, 'M', '𞤢'), + (0x1E901, 'M', '𞤣'), + (0x1E902, 'M', '𞤤'), + (0x1E903, 'M', '𞤥'), + (0x1E904, 'M', '𞤦'), + (0x1E905, 'M', '𞤧'), + (0x1E906, 'M', '𞤨'), + (0x1E907, 'M', '𞤩'), + (0x1E908, 'M', '𞤪'), + (0x1E909, 'M', '𞤫'), + (0x1E90A, 'M', '𞤬'), + (0x1E90B, 'M', '𞤭'), + (0x1E90C, 'M', '𞤮'), + (0x1E90D, 'M', '𞤯'), + (0x1E90E, 'M', '𞤰'), + (0x1E90F, 'M', '𞤱'), + (0x1E910, 'M', '𞤲'), + (0x1E911, 'M', '𞤳'), + (0x1E912, 'M', '𞤴'), + (0x1E913, 'M', '𞤵'), + (0x1E914, 'M', '𞤶'), + (0x1E915, 'M', '𞤷'), + (0x1E916, 'M', '𞤸'), + (0x1E917, 'M', '𞤹'), + (0x1E918, 'M', '𞤺'), + (0x1E919, 'M', '𞤻'), + (0x1E91A, 'M', '𞤼'), + (0x1E91B, 'M', '𞤽'), + (0x1E91C, 'M', '𞤾'), + (0x1E91D, 'M', '𞤿'), + (0x1E91E, 'M', '𞥀'), + (0x1E91F, 'M', '𞥁'), + (0x1E920, 'M', '𞥂'), + (0x1E921, 'M', '𞥃'), (0x1E922, 'V'), (0x1E94C, 'X'), (0x1E950, 'V'), @@ -7286,188 +7357,190 @@ def _seg_69(): ] def _seg_70(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1EC71, 'V'), (0x1ECB5, 'X'), (0x1ED01, 'V'), (0x1ED3E, 'X'), - (0x1EE00, 'M', u'ا'), - (0x1EE01, 'M', u'ب'), - (0x1EE02, 'M', u'ج'), - (0x1EE03, 'M', u'د'), + (0x1EE00, 'M', 'ا'), + (0x1EE01, 'M', 'ب'), + (0x1EE02, 'M', 'ج'), + (0x1EE03, 'M', 'د'), (0x1EE04, 'X'), - (0x1EE05, 'M', u'و'), - (0x1EE06, 'M', u'ز'), - (0x1EE07, 'M', u'ح'), - (0x1EE08, 'M', u'ط'), - (0x1EE09, 'M', u'ي'), - (0x1EE0A, 'M', u'ك'), - (0x1EE0B, 'M', u'ل'), - (0x1EE0C, 'M', u'م'), - (0x1EE0D, 'M', u'ن'), - (0x1EE0E, 'M', u'س'), - (0x1EE0F, 'M', u'ع'), - (0x1EE10, 'M', u'ف'), - (0x1EE11, 'M', u'ص'), - (0x1EE12, 'M', u'ق'), - (0x1EE13, 'M', u'ر'), - (0x1EE14, 'M', u'ش'), - (0x1EE15, 'M', u'ت'), - (0x1EE16, 'M', u'ث'), - (0x1EE17, 'M', u'خ'), - (0x1EE18, 'M', u'ذ'), - (0x1EE19, 'M', u'ض'), - (0x1EE1A, 'M', u'ظ'), - (0x1EE1B, 'M', u'غ'), - (0x1EE1C, 'M', u'ٮ'), - (0x1EE1D, 'M', u'ں'), - (0x1EE1E, 'M', u'ڡ'), - (0x1EE1F, 'M', u'ٯ'), + (0x1EE05, 'M', 'و'), + (0x1EE06, 'M', 'ز'), + (0x1EE07, 'M', 'ح'), + (0x1EE08, 'M', 'ط'), + (0x1EE09, 'M', 'ي'), + (0x1EE0A, 'M', 'ك'), + (0x1EE0B, 'M', 'ل'), + (0x1EE0C, 'M', 'م'), + (0x1EE0D, 'M', 'ن'), + (0x1EE0E, 'M', 'س'), + (0x1EE0F, 'M', 'ع'), + (0x1EE10, 'M', 'ف'), + (0x1EE11, 'M', 'ص'), + (0x1EE12, 'M', 'ق'), + (0x1EE13, 'M', 'ر'), + (0x1EE14, 'M', 'ش'), + (0x1EE15, 'M', 'ت'), + (0x1EE16, 'M', 'ث'), + (0x1EE17, 'M', 'خ'), + (0x1EE18, 'M', 'ذ'), + (0x1EE19, 'M', 'ض'), + (0x1EE1A, 'M', 'ظ'), + (0x1EE1B, 'M', 'غ'), + (0x1EE1C, 'M', 'ٮ'), + (0x1EE1D, 'M', 'ں'), + (0x1EE1E, 'M', 'ڡ'), + (0x1EE1F, 'M', 'ٯ'), (0x1EE20, 'X'), - (0x1EE21, 'M', u'ب'), - (0x1EE22, 'M', u'ج'), + (0x1EE21, 'M', 'ب'), + (0x1EE22, 'M', 'ج'), (0x1EE23, 'X'), - (0x1EE24, 'M', u'ه'), + (0x1EE24, 'M', 'ه'), (0x1EE25, 'X'), - (0x1EE27, 'M', u'ح'), + (0x1EE27, 'M', 'ح'), (0x1EE28, 'X'), - (0x1EE29, 'M', u'ي'), - (0x1EE2A, 'M', u'ك'), - (0x1EE2B, 'M', u'ل'), - (0x1EE2C, 'M', u'م'), - (0x1EE2D, 'M', u'ن'), - (0x1EE2E, 'M', u'س'), - (0x1EE2F, 'M', u'ع'), - (0x1EE30, 'M', u'ف'), - (0x1EE31, 'M', u'ص'), - (0x1EE32, 'M', u'ق'), + (0x1EE29, 'M', 'ي'), + (0x1EE2A, 'M', 'ك'), + (0x1EE2B, 'M', 'ل'), + (0x1EE2C, 'M', 'م'), + (0x1EE2D, 'M', 'ن'), + (0x1EE2E, 'M', 'س'), + (0x1EE2F, 'M', 'ع'), + (0x1EE30, 'M', 'ف'), + (0x1EE31, 'M', 'ص'), + (0x1EE32, 'M', 'ق'), (0x1EE33, 'X'), - (0x1EE34, 'M', u'ش'), - (0x1EE35, 'M', u'ت'), - (0x1EE36, 'M', u'ث'), - (0x1EE37, 'M', u'خ'), + (0x1EE34, 'M', 'ش'), + (0x1EE35, 'M', 'ت'), + (0x1EE36, 'M', 'ث'), + (0x1EE37, 'M', 'خ'), (0x1EE38, 'X'), - (0x1EE39, 'M', u'ض'), + (0x1EE39, 'M', 'ض'), (0x1EE3A, 'X'), - (0x1EE3B, 'M', u'غ'), + (0x1EE3B, 'M', 'غ'), (0x1EE3C, 'X'), - (0x1EE42, 'M', u'ج'), + (0x1EE42, 'M', 'ج'), (0x1EE43, 'X'), - (0x1EE47, 'M', u'ح'), + (0x1EE47, 'M', 'ح'), (0x1EE48, 'X'), - (0x1EE49, 'M', u'ي'), + (0x1EE49, 'M', 'ي'), (0x1EE4A, 'X'), - (0x1EE4B, 'M', u'ل'), + (0x1EE4B, 'M', 'ل'), (0x1EE4C, 'X'), - (0x1EE4D, 'M', u'ن'), - (0x1EE4E, 'M', u'س'), - (0x1EE4F, 'M', u'ع'), + (0x1EE4D, 'M', 'ن'), + (0x1EE4E, 'M', 'س'), + (0x1EE4F, 'M', 'ع'), (0x1EE50, 'X'), - (0x1EE51, 'M', u'ص'), - (0x1EE52, 'M', u'ق'), + (0x1EE51, 'M', 'ص'), + (0x1EE52, 'M', 'ق'), (0x1EE53, 'X'), - (0x1EE54, 'M', u'ش'), + (0x1EE54, 'M', 'ش'), (0x1EE55, 'X'), - (0x1EE57, 'M', u'خ'), + (0x1EE57, 'M', 'خ'), (0x1EE58, 'X'), - (0x1EE59, 'M', u'ض'), + (0x1EE59, 'M', 'ض'), (0x1EE5A, 'X'), - (0x1EE5B, 'M', u'غ'), + (0x1EE5B, 'M', 'غ'), (0x1EE5C, 'X'), - (0x1EE5D, 'M', u'ں'), + (0x1EE5D, 'M', 'ں'), (0x1EE5E, 'X'), - (0x1EE5F, 'M', u'ٯ'), + (0x1EE5F, 'M', 'ٯ'), (0x1EE60, 'X'), - (0x1EE61, 'M', u'ب'), - (0x1EE62, 'M', u'ج'), + (0x1EE61, 'M', 'ب'), + (0x1EE62, 'M', 'ج'), (0x1EE63, 'X'), - (0x1EE64, 'M', u'ه'), + (0x1EE64, 'M', 'ه'), (0x1EE65, 'X'), - (0x1EE67, 'M', u'ح'), - (0x1EE68, 'M', u'ط'), - (0x1EE69, 'M', u'ي'), - (0x1EE6A, 'M', u'ك'), + (0x1EE67, 'M', 'ح'), + (0x1EE68, 'M', 'ط'), + (0x1EE69, 'M', 'ي'), + (0x1EE6A, 'M', 'ك'), ] def _seg_71(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1EE6B, 'X'), - (0x1EE6C, 'M', u'م'), - (0x1EE6D, 'M', u'ن'), - (0x1EE6E, 'M', u'س'), - (0x1EE6F, 'M', u'ع'), - (0x1EE70, 'M', u'ف'), - (0x1EE71, 'M', u'ص'), - (0x1EE72, 'M', u'ق'), + (0x1EE6C, 'M', 'م'), + (0x1EE6D, 'M', 'ن'), + (0x1EE6E, 'M', 'س'), + (0x1EE6F, 'M', 'ع'), + (0x1EE70, 'M', 'ف'), + (0x1EE71, 'M', 'ص'), + (0x1EE72, 'M', 'ق'), (0x1EE73, 'X'), - (0x1EE74, 'M', u'ش'), - (0x1EE75, 'M', u'ت'), - (0x1EE76, 'M', u'ث'), - (0x1EE77, 'M', u'خ'), + (0x1EE74, 'M', 'ش'), + (0x1EE75, 'M', 'ت'), + (0x1EE76, 'M', 'ث'), + (0x1EE77, 'M', 'خ'), (0x1EE78, 'X'), - (0x1EE79, 'M', u'ض'), - (0x1EE7A, 'M', u'ظ'), - (0x1EE7B, 'M', u'غ'), - (0x1EE7C, 'M', u'ٮ'), + (0x1EE79, 'M', 'ض'), + (0x1EE7A, 'M', 'ظ'), + (0x1EE7B, 'M', 'غ'), + (0x1EE7C, 'M', 'ٮ'), (0x1EE7D, 'X'), - (0x1EE7E, 'M', u'ڡ'), + (0x1EE7E, 'M', 'ڡ'), (0x1EE7F, 'X'), - (0x1EE80, 'M', u'ا'), - (0x1EE81, 'M', u'ب'), - (0x1EE82, 'M', u'ج'), - (0x1EE83, 'M', u'د'), - (0x1EE84, 'M', u'ه'), - (0x1EE85, 'M', u'و'), - (0x1EE86, 'M', u'ز'), - (0x1EE87, 'M', u'ح'), - (0x1EE88, 'M', u'ط'), - (0x1EE89, 'M', u'ي'), + (0x1EE80, 'M', 'ا'), + (0x1EE81, 'M', 'ب'), + (0x1EE82, 'M', 'ج'), + (0x1EE83, 'M', 'د'), + (0x1EE84, 'M', 'ه'), + (0x1EE85, 'M', 'و'), + (0x1EE86, 'M', 'ز'), + (0x1EE87, 'M', 'ح'), + (0x1EE88, 'M', 'ط'), + (0x1EE89, 'M', 'ي'), (0x1EE8A, 'X'), - (0x1EE8B, 'M', u'ل'), - (0x1EE8C, 'M', u'م'), - (0x1EE8D, 'M', u'ن'), - (0x1EE8E, 'M', u'س'), - (0x1EE8F, 'M', u'ع'), - (0x1EE90, 'M', u'ف'), - (0x1EE91, 'M', u'ص'), - (0x1EE92, 'M', u'ق'), - (0x1EE93, 'M', u'ر'), - (0x1EE94, 'M', u'ش'), - (0x1EE95, 'M', u'ت'), - (0x1EE96, 'M', u'ث'), - (0x1EE97, 'M', u'خ'), - (0x1EE98, 'M', u'ذ'), - (0x1EE99, 'M', u'ض'), - (0x1EE9A, 'M', u'ظ'), - (0x1EE9B, 'M', u'غ'), + (0x1EE8B, 'M', 'ل'), + (0x1EE8C, 'M', 'م'), + (0x1EE8D, 'M', 'ن'), + (0x1EE8E, 'M', 'س'), + (0x1EE8F, 'M', 'ع'), + (0x1EE90, 'M', 'ف'), + (0x1EE91, 'M', 'ص'), + (0x1EE92, 'M', 'ق'), + (0x1EE93, 'M', 'ر'), + (0x1EE94, 'M', 'ش'), + (0x1EE95, 'M', 'ت'), + (0x1EE96, 'M', 'ث'), + (0x1EE97, 'M', 'خ'), + (0x1EE98, 'M', 'ذ'), + (0x1EE99, 'M', 'ض'), + (0x1EE9A, 'M', 'ظ'), + (0x1EE9B, 'M', 'غ'), (0x1EE9C, 'X'), - (0x1EEA1, 'M', u'ب'), - (0x1EEA2, 'M', u'ج'), - (0x1EEA3, 'M', u'د'), + (0x1EEA1, 'M', 'ب'), + (0x1EEA2, 'M', 'ج'), + (0x1EEA3, 'M', 'د'), (0x1EEA4, 'X'), - (0x1EEA5, 'M', u'و'), - (0x1EEA6, 'M', u'ز'), - (0x1EEA7, 'M', u'ح'), - (0x1EEA8, 'M', u'ط'), - (0x1EEA9, 'M', u'ي'), + (0x1EEA5, 'M', 'و'), + (0x1EEA6, 'M', 'ز'), + (0x1EEA7, 'M', 'ح'), + (0x1EEA8, 'M', 'ط'), + (0x1EEA9, 'M', 'ي'), (0x1EEAA, 'X'), - (0x1EEAB, 'M', u'ل'), - (0x1EEAC, 'M', u'م'), - (0x1EEAD, 'M', u'ن'), - (0x1EEAE, 'M', u'س'), - (0x1EEAF, 'M', u'ع'), - (0x1EEB0, 'M', u'ف'), - (0x1EEB1, 'M', u'ص'), - (0x1EEB2, 'M', u'ق'), - (0x1EEB3, 'M', u'ر'), - (0x1EEB4, 'M', u'ش'), - (0x1EEB5, 'M', u'ت'), - (0x1EEB6, 'M', u'ث'), - (0x1EEB7, 'M', u'خ'), - (0x1EEB8, 'M', u'ذ'), - (0x1EEB9, 'M', u'ض'), - (0x1EEBA, 'M', u'ظ'), - (0x1EEBB, 'M', u'غ'), + (0x1EEAB, 'M', 'ل'), + (0x1EEAC, 'M', 'م'), + (0x1EEAD, 'M', 'ن'), + (0x1EEAE, 'M', 'س'), + (0x1EEAF, 'M', 'ع'), + (0x1EEB0, 'M', 'ف'), + (0x1EEB1, 'M', 'ص'), + (0x1EEB2, 'M', 'ق'), + (0x1EEB3, 'M', 'ر'), + (0x1EEB4, 'M', 'ش'), + (0x1EEB5, 'M', 'ت'), + (0x1EEB6, 'M', 'ث'), + (0x1EEB7, 'M', 'خ'), + (0x1EEB8, 'M', 'ذ'), + (0x1EEB9, 'M', 'ض'), + (0x1EEBA, 'M', 'ظ'), + (0x1EEBB, 'M', 'غ'), (0x1EEBC, 'X'), (0x1EEF0, 'V'), (0x1EEF2, 'X'), @@ -7483,159 +7556,161 @@ def _seg_71(): (0x1F0D0, 'X'), (0x1F0D1, 'V'), (0x1F0F6, 'X'), - (0x1F101, '3', u'0,'), - (0x1F102, '3', u'1,'), - (0x1F103, '3', u'2,'), - (0x1F104, '3', u'3,'), - (0x1F105, '3', u'4,'), - (0x1F106, '3', u'5,'), - (0x1F107, '3', u'6,'), - (0x1F108, '3', u'7,'), + (0x1F101, '3', '0,'), + (0x1F102, '3', '1,'), + (0x1F103, '3', '2,'), + (0x1F104, '3', '3,'), + (0x1F105, '3', '4,'), + (0x1F106, '3', '5,'), + (0x1F107, '3', '6,'), + (0x1F108, '3', '7,'), ] def _seg_72(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1F109, '3', u'8,'), - (0x1F10A, '3', u'9,'), + (0x1F109, '3', '8,'), + (0x1F10A, '3', '9,'), (0x1F10B, 'V'), - (0x1F110, '3', u'(a)'), - (0x1F111, '3', u'(b)'), - (0x1F112, '3', u'(c)'), - (0x1F113, '3', u'(d)'), - (0x1F114, '3', u'(e)'), - (0x1F115, '3', u'(f)'), - (0x1F116, '3', u'(g)'), - (0x1F117, '3', u'(h)'), - (0x1F118, '3', u'(i)'), - (0x1F119, '3', u'(j)'), - (0x1F11A, '3', u'(k)'), - (0x1F11B, '3', u'(l)'), - (0x1F11C, '3', u'(m)'), - (0x1F11D, '3', u'(n)'), - (0x1F11E, '3', u'(o)'), - (0x1F11F, '3', u'(p)'), - (0x1F120, '3', u'(q)'), - (0x1F121, '3', u'(r)'), - (0x1F122, '3', u'(s)'), - (0x1F123, '3', u'(t)'), - (0x1F124, '3', u'(u)'), - (0x1F125, '3', u'(v)'), - (0x1F126, '3', u'(w)'), - (0x1F127, '3', u'(x)'), - (0x1F128, '3', u'(y)'), - (0x1F129, '3', u'(z)'), - (0x1F12A, 'M', u'〔s〕'), - (0x1F12B, 'M', u'c'), - (0x1F12C, 'M', u'r'), - (0x1F12D, 'M', u'cd'), - (0x1F12E, 'M', u'wz'), + (0x1F110, '3', '(a)'), + (0x1F111, '3', '(b)'), + (0x1F112, '3', '(c)'), + (0x1F113, '3', '(d)'), + (0x1F114, '3', '(e)'), + (0x1F115, '3', '(f)'), + (0x1F116, '3', '(g)'), + (0x1F117, '3', '(h)'), + (0x1F118, '3', '(i)'), + (0x1F119, '3', '(j)'), + (0x1F11A, '3', '(k)'), + (0x1F11B, '3', '(l)'), + (0x1F11C, '3', '(m)'), + (0x1F11D, '3', '(n)'), + (0x1F11E, '3', '(o)'), + (0x1F11F, '3', '(p)'), + (0x1F120, '3', '(q)'), + (0x1F121, '3', '(r)'), + (0x1F122, '3', '(s)'), + (0x1F123, '3', '(t)'), + (0x1F124, '3', '(u)'), + (0x1F125, '3', '(v)'), + (0x1F126, '3', '(w)'), + (0x1F127, '3', '(x)'), + (0x1F128, '3', '(y)'), + (0x1F129, '3', '(z)'), + (0x1F12A, 'M', '〔s〕'), + (0x1F12B, 'M', 'c'), + (0x1F12C, 'M', 'r'), + (0x1F12D, 'M', 'cd'), + (0x1F12E, 'M', 'wz'), (0x1F12F, 'V'), - (0x1F130, 'M', u'a'), - (0x1F131, 'M', u'b'), - (0x1F132, 'M', u'c'), - (0x1F133, 'M', u'd'), - (0x1F134, 'M', u'e'), - (0x1F135, 'M', u'f'), - (0x1F136, 'M', u'g'), - (0x1F137, 'M', u'h'), - (0x1F138, 'M', u'i'), - (0x1F139, 'M', u'j'), - (0x1F13A, 'M', u'k'), - (0x1F13B, 'M', u'l'), - (0x1F13C, 'M', u'm'), - (0x1F13D, 'M', u'n'), - (0x1F13E, 'M', u'o'), - (0x1F13F, 'M', u'p'), - (0x1F140, 'M', u'q'), - (0x1F141, 'M', u'r'), - (0x1F142, 'M', u's'), - (0x1F143, 'M', u't'), - (0x1F144, 'M', u'u'), - (0x1F145, 'M', u'v'), - (0x1F146, 'M', u'w'), - (0x1F147, 'M', u'x'), - (0x1F148, 'M', u'y'), - (0x1F149, 'M', u'z'), - (0x1F14A, 'M', u'hv'), - (0x1F14B, 'M', u'mv'), - (0x1F14C, 'M', u'sd'), - (0x1F14D, 'M', u'ss'), - (0x1F14E, 'M', u'ppv'), - (0x1F14F, 'M', u'wc'), + (0x1F130, 'M', 'a'), + (0x1F131, 'M', 'b'), + (0x1F132, 'M', 'c'), + (0x1F133, 'M', 'd'), + (0x1F134, 'M', 'e'), + (0x1F135, 'M', 'f'), + (0x1F136, 'M', 'g'), + (0x1F137, 'M', 'h'), + (0x1F138, 'M', 'i'), + (0x1F139, 'M', 'j'), + (0x1F13A, 'M', 'k'), + (0x1F13B, 'M', 'l'), + (0x1F13C, 'M', 'm'), + (0x1F13D, 'M', 'n'), + (0x1F13E, 'M', 'o'), + (0x1F13F, 'M', 'p'), + (0x1F140, 'M', 'q'), + (0x1F141, 'M', 'r'), + (0x1F142, 'M', 's'), + (0x1F143, 'M', 't'), + (0x1F144, 'M', 'u'), + (0x1F145, 'M', 'v'), + (0x1F146, 'M', 'w'), + (0x1F147, 'M', 'x'), + (0x1F148, 'M', 'y'), + (0x1F149, 'M', 'z'), + (0x1F14A, 'M', 'hv'), + (0x1F14B, 'M', 'mv'), + (0x1F14C, 'M', 'sd'), + (0x1F14D, 'M', 'ss'), + (0x1F14E, 'M', 'ppv'), + (0x1F14F, 'M', 'wc'), (0x1F150, 'V'), - (0x1F16A, 'M', u'mc'), - (0x1F16B, 'M', u'md'), - (0x1F16C, 'M', u'mr'), + (0x1F16A, 'M', 'mc'), + (0x1F16B, 'M', 'md'), + (0x1F16C, 'M', 'mr'), (0x1F16D, 'V'), - (0x1F190, 'M', u'dj'), + (0x1F190, 'M', 'dj'), (0x1F191, 'V'), (0x1F1AE, 'X'), (0x1F1E6, 'V'), - (0x1F200, 'M', u'ほか'), - (0x1F201, 'M', u'ココ'), - (0x1F202, 'M', u'サ'), + (0x1F200, 'M', 'ほか'), + (0x1F201, 'M', 'ココ'), + (0x1F202, 'M', 'サ'), (0x1F203, 'X'), - (0x1F210, 'M', u'手'), - (0x1F211, 'M', u'字'), - (0x1F212, 'M', u'双'), - (0x1F213, 'M', u'デ'), - (0x1F214, 'M', u'二'), - (0x1F215, 'M', u'多'), - (0x1F216, 'M', u'解'), - (0x1F217, 'M', u'天'), - (0x1F218, 'M', u'交'), - (0x1F219, 'M', u'映'), - (0x1F21A, 'M', u'無'), - (0x1F21B, 'M', u'料'), - (0x1F21C, 'M', u'前'), - (0x1F21D, 'M', u'後'), - (0x1F21E, 'M', u'再'), - (0x1F21F, 'M', u'新'), - (0x1F220, 'M', u'初'), - (0x1F221, 'M', u'終'), - (0x1F222, 'M', u'生'), - (0x1F223, 'M', u'販'), + (0x1F210, 'M', '手'), + (0x1F211, 'M', '字'), + (0x1F212, 'M', '双'), + (0x1F213, 'M', 'デ'), + (0x1F214, 'M', '二'), + (0x1F215, 'M', '多'), + (0x1F216, 'M', '解'), + (0x1F217, 'M', '天'), + (0x1F218, 'M', '交'), + (0x1F219, 'M', '映'), + (0x1F21A, 'M', '無'), + (0x1F21B, 'M', '料'), + (0x1F21C, 'M', '前'), + (0x1F21D, 'M', '後'), + (0x1F21E, 'M', '再'), + (0x1F21F, 'M', '新'), + (0x1F220, 'M', '初'), + (0x1F221, 'M', '終'), + (0x1F222, 'M', '生'), + (0x1F223, 'M', '販'), ] def _seg_73(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x1F224, 'M', u'声'), - (0x1F225, 'M', u'吹'), - (0x1F226, 'M', u'演'), - (0x1F227, 'M', u'投'), - (0x1F228, 'M', u'捕'), - (0x1F229, 'M', u'一'), - (0x1F22A, 'M', u'三'), - (0x1F22B, 'M', u'遊'), - (0x1F22C, 'M', u'左'), - (0x1F22D, 'M', u'中'), - (0x1F22E, 'M', u'右'), - (0x1F22F, 'M', u'指'), - (0x1F230, 'M', u'走'), - (0x1F231, 'M', u'打'), - (0x1F232, 'M', u'禁'), - (0x1F233, 'M', u'空'), - (0x1F234, 'M', u'合'), - (0x1F235, 'M', u'満'), - (0x1F236, 'M', u'有'), - (0x1F237, 'M', u'月'), - (0x1F238, 'M', u'申'), - (0x1F239, 'M', u'割'), - (0x1F23A, 'M', u'営'), - (0x1F23B, 'M', u'配'), + (0x1F224, 'M', '声'), + (0x1F225, 'M', '吹'), + (0x1F226, 'M', '演'), + (0x1F227, 'M', '投'), + (0x1F228, 'M', '捕'), + (0x1F229, 'M', '一'), + (0x1F22A, 'M', '三'), + (0x1F22B, 'M', '遊'), + (0x1F22C, 'M', '左'), + (0x1F22D, 'M', '中'), + (0x1F22E, 'M', '右'), + (0x1F22F, 'M', '指'), + (0x1F230, 'M', '走'), + (0x1F231, 'M', '打'), + (0x1F232, 'M', '禁'), + (0x1F233, 'M', '空'), + (0x1F234, 'M', '合'), + (0x1F235, 'M', '満'), + (0x1F236, 'M', '有'), + (0x1F237, 'M', '月'), + (0x1F238, 'M', '申'), + (0x1F239, 'M', '割'), + (0x1F23A, 'M', '営'), + (0x1F23B, 'M', '配'), (0x1F23C, 'X'), - (0x1F240, 'M', u'〔本〕'), - (0x1F241, 'M', u'〔三〕'), - (0x1F242, 'M', u'〔二〕'), - (0x1F243, 'M', u'〔安〕'), - (0x1F244, 'M', u'〔点〕'), - (0x1F245, 'M', u'〔打〕'), - (0x1F246, 'M', u'〔盗〕'), - (0x1F247, 'M', u'〔勝〕'), - (0x1F248, 'M', u'〔敗〕'), + (0x1F240, 'M', '〔本〕'), + (0x1F241, 'M', '〔三〕'), + (0x1F242, 'M', '〔二〕'), + (0x1F243, 'M', '〔安〕'), + (0x1F244, 'M', '〔点〕'), + (0x1F245, 'M', '〔打〕'), + (0x1F246, 'M', '〔盗〕'), + (0x1F247, 'M', '〔勝〕'), + (0x1F248, 'M', '〔敗〕'), (0x1F249, 'X'), - (0x1F250, 'M', u'得'), - (0x1F251, 'M', u'可'), + (0x1F250, 'M', '得'), + (0x1F251, 'M', '可'), (0x1F252, 'X'), (0x1F260, 'V'), (0x1F266, 'X'), @@ -7689,19 +7764,20 @@ def _seg_73(): (0x1FB93, 'X'), (0x1FB94, 'V'), (0x1FBCB, 'X'), - (0x1FBF0, 'M', u'0'), - (0x1FBF1, 'M', u'1'), - (0x1FBF2, 'M', u'2'), - (0x1FBF3, 'M', u'3'), - (0x1FBF4, 'M', u'4'), - (0x1FBF5, 'M', u'5'), - (0x1FBF6, 'M', u'6'), - (0x1FBF7, 'M', u'7'), - (0x1FBF8, 'M', u'8'), - (0x1FBF9, 'M', u'9'), + (0x1FBF0, 'M', '0'), + (0x1FBF1, 'M', '1'), + (0x1FBF2, 'M', '2'), + (0x1FBF3, 'M', '3'), + (0x1FBF4, 'M', '4'), + (0x1FBF5, 'M', '5'), + (0x1FBF6, 'M', '6'), + (0x1FBF7, 'M', '7'), + (0x1FBF8, 'M', '8'), + (0x1FBF9, 'M', '9'), ] def _seg_74(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ (0x1FBFA, 'X'), (0x20000, 'V'), @@ -7714,558 +7790,563 @@ def _seg_74(): (0x2CEA2, 'X'), (0x2CEB0, 'V'), (0x2EBE1, 'X'), - (0x2F800, 'M', u'丽'), - (0x2F801, 'M', u'丸'), - (0x2F802, 'M', u'乁'), - (0x2F803, 'M', u'𠄢'), - (0x2F804, 'M', u'你'), - (0x2F805, 'M', u'侮'), - (0x2F806, 'M', u'侻'), - (0x2F807, 'M', u'倂'), - (0x2F808, 'M', u'偺'), - (0x2F809, 'M', u'備'), - (0x2F80A, 'M', u'僧'), - (0x2F80B, 'M', u'像'), - (0x2F80C, 'M', u'㒞'), - (0x2F80D, 'M', u'𠘺'), - (0x2F80E, 'M', u'免'), - (0x2F80F, 'M', u'兔'), - (0x2F810, 'M', u'兤'), - (0x2F811, 'M', u'具'), - (0x2F812, 'M', u'𠔜'), - (0x2F813, 'M', u'㒹'), - (0x2F814, 'M', u'內'), - (0x2F815, 'M', u'再'), - (0x2F816, 'M', u'𠕋'), - (0x2F817, 'M', u'冗'), - (0x2F818, 'M', u'冤'), - (0x2F819, 'M', u'仌'), - (0x2F81A, 'M', u'冬'), - (0x2F81B, 'M', u'况'), - (0x2F81C, 'M', u'𩇟'), - (0x2F81D, 'M', u'凵'), - (0x2F81E, 'M', u'刃'), - (0x2F81F, 'M', u'㓟'), - (0x2F820, 'M', u'刻'), - (0x2F821, 'M', u'剆'), - (0x2F822, 'M', u'割'), - (0x2F823, 'M', u'剷'), - (0x2F824, 'M', u'㔕'), - (0x2F825, 'M', u'勇'), - (0x2F826, 'M', u'勉'), - (0x2F827, 'M', u'勤'), - (0x2F828, 'M', u'勺'), - (0x2F829, 'M', u'包'), - (0x2F82A, 'M', u'匆'), - (0x2F82B, 'M', u'北'), - (0x2F82C, 'M', u'卉'), - (0x2F82D, 'M', u'卑'), - (0x2F82E, 'M', u'博'), - (0x2F82F, 'M', u'即'), - (0x2F830, 'M', u'卽'), - (0x2F831, 'M', u'卿'), - (0x2F834, 'M', u'𠨬'), - (0x2F835, 'M', u'灰'), - (0x2F836, 'M', u'及'), - (0x2F837, 'M', u'叟'), - (0x2F838, 'M', u'𠭣'), - (0x2F839, 'M', u'叫'), - (0x2F83A, 'M', u'叱'), - (0x2F83B, 'M', u'吆'), - (0x2F83C, 'M', u'咞'), - (0x2F83D, 'M', u'吸'), - (0x2F83E, 'M', u'呈'), - (0x2F83F, 'M', u'周'), - (0x2F840, 'M', u'咢'), - (0x2F841, 'M', u'哶'), - (0x2F842, 'M', u'唐'), - (0x2F843, 'M', u'啓'), - (0x2F844, 'M', u'啣'), - (0x2F845, 'M', u'善'), - (0x2F847, 'M', u'喙'), - (0x2F848, 'M', u'喫'), - (0x2F849, 'M', u'喳'), - (0x2F84A, 'M', u'嗂'), - (0x2F84B, 'M', u'圖'), - (0x2F84C, 'M', u'嘆'), - (0x2F84D, 'M', u'圗'), - (0x2F84E, 'M', u'噑'), - (0x2F84F, 'M', u'噴'), - (0x2F850, 'M', u'切'), - (0x2F851, 'M', u'壮'), - (0x2F852, 'M', u'城'), - (0x2F853, 'M', u'埴'), - (0x2F854, 'M', u'堍'), - (0x2F855, 'M', u'型'), - (0x2F856, 'M', u'堲'), - (0x2F857, 'M', u'報'), - (0x2F858, 'M', u'墬'), - (0x2F859, 'M', u'𡓤'), - (0x2F85A, 'M', u'売'), - (0x2F85B, 'M', u'壷'), + (0x2F800, 'M', '丽'), + (0x2F801, 'M', '丸'), + (0x2F802, 'M', '乁'), + (0x2F803, 'M', '𠄢'), + (0x2F804, 'M', '你'), + (0x2F805, 'M', '侮'), + (0x2F806, 'M', '侻'), + (0x2F807, 'M', '倂'), + (0x2F808, 'M', '偺'), + (0x2F809, 'M', '備'), + (0x2F80A, 'M', '僧'), + (0x2F80B, 'M', '像'), + (0x2F80C, 'M', '㒞'), + (0x2F80D, 'M', '𠘺'), + (0x2F80E, 'M', '免'), + (0x2F80F, 'M', '兔'), + (0x2F810, 'M', '兤'), + (0x2F811, 'M', '具'), + (0x2F812, 'M', '𠔜'), + (0x2F813, 'M', '㒹'), + (0x2F814, 'M', '內'), + (0x2F815, 'M', '再'), + (0x2F816, 'M', '𠕋'), + (0x2F817, 'M', '冗'), + (0x2F818, 'M', '冤'), + (0x2F819, 'M', '仌'), + (0x2F81A, 'M', '冬'), + (0x2F81B, 'M', '况'), + (0x2F81C, 'M', '𩇟'), + (0x2F81D, 'M', '凵'), + (0x2F81E, 'M', '刃'), + (0x2F81F, 'M', '㓟'), + (0x2F820, 'M', '刻'), + (0x2F821, 'M', '剆'), + (0x2F822, 'M', '割'), + (0x2F823, 'M', '剷'), + (0x2F824, 'M', '㔕'), + (0x2F825, 'M', '勇'), + (0x2F826, 'M', '勉'), + (0x2F827, 'M', '勤'), + (0x2F828, 'M', '勺'), + (0x2F829, 'M', '包'), + (0x2F82A, 'M', '匆'), + (0x2F82B, 'M', '北'), + (0x2F82C, 'M', '卉'), + (0x2F82D, 'M', '卑'), + (0x2F82E, 'M', '博'), + (0x2F82F, 'M', '即'), + (0x2F830, 'M', '卽'), + (0x2F831, 'M', '卿'), + (0x2F834, 'M', '𠨬'), + (0x2F835, 'M', '灰'), + (0x2F836, 'M', '及'), + (0x2F837, 'M', '叟'), + (0x2F838, 'M', '𠭣'), + (0x2F839, 'M', '叫'), + (0x2F83A, 'M', '叱'), + (0x2F83B, 'M', '吆'), + (0x2F83C, 'M', '咞'), + (0x2F83D, 'M', '吸'), + (0x2F83E, 'M', '呈'), + (0x2F83F, 'M', '周'), + (0x2F840, 'M', '咢'), + (0x2F841, 'M', '哶'), + (0x2F842, 'M', '唐'), + (0x2F843, 'M', '啓'), + (0x2F844, 'M', '啣'), + (0x2F845, 'M', '善'), + (0x2F847, 'M', '喙'), + (0x2F848, 'M', '喫'), + (0x2F849, 'M', '喳'), + (0x2F84A, 'M', '嗂'), + (0x2F84B, 'M', '圖'), + (0x2F84C, 'M', '嘆'), + (0x2F84D, 'M', '圗'), + (0x2F84E, 'M', '噑'), + (0x2F84F, 'M', '噴'), + (0x2F850, 'M', '切'), + (0x2F851, 'M', '壮'), + (0x2F852, 'M', '城'), + (0x2F853, 'M', '埴'), + (0x2F854, 'M', '堍'), + (0x2F855, 'M', '型'), + (0x2F856, 'M', '堲'), + (0x2F857, 'M', '報'), + (0x2F858, 'M', '墬'), + (0x2F859, 'M', '𡓤'), + (0x2F85A, 'M', '売'), + (0x2F85B, 'M', '壷'), ] def _seg_75(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F85C, 'M', u'夆'), - (0x2F85D, 'M', u'多'), - (0x2F85E, 'M', u'夢'), - (0x2F85F, 'M', u'奢'), - (0x2F860, 'M', u'𡚨'), - (0x2F861, 'M', u'𡛪'), - (0x2F862, 'M', u'姬'), - (0x2F863, 'M', u'娛'), - (0x2F864, 'M', u'娧'), - (0x2F865, 'M', u'姘'), - (0x2F866, 'M', u'婦'), - (0x2F867, 'M', u'㛮'), + (0x2F85C, 'M', '夆'), + (0x2F85D, 'M', '多'), + (0x2F85E, 'M', '夢'), + (0x2F85F, 'M', '奢'), + (0x2F860, 'M', '𡚨'), + (0x2F861, 'M', '𡛪'), + (0x2F862, 'M', '姬'), + (0x2F863, 'M', '娛'), + (0x2F864, 'M', '娧'), + (0x2F865, 'M', '姘'), + (0x2F866, 'M', '婦'), + (0x2F867, 'M', '㛮'), (0x2F868, 'X'), - (0x2F869, 'M', u'嬈'), - (0x2F86A, 'M', u'嬾'), - (0x2F86C, 'M', u'𡧈'), - (0x2F86D, 'M', u'寃'), - (0x2F86E, 'M', u'寘'), - (0x2F86F, 'M', u'寧'), - (0x2F870, 'M', u'寳'), - (0x2F871, 'M', u'𡬘'), - (0x2F872, 'M', u'寿'), - (0x2F873, 'M', u'将'), + (0x2F869, 'M', '嬈'), + (0x2F86A, 'M', '嬾'), + (0x2F86C, 'M', '𡧈'), + (0x2F86D, 'M', '寃'), + (0x2F86E, 'M', '寘'), + (0x2F86F, 'M', '寧'), + (0x2F870, 'M', '寳'), + (0x2F871, 'M', '𡬘'), + (0x2F872, 'M', '寿'), + (0x2F873, 'M', '将'), (0x2F874, 'X'), - (0x2F875, 'M', u'尢'), - (0x2F876, 'M', u'㞁'), - (0x2F877, 'M', u'屠'), - (0x2F878, 'M', u'屮'), - (0x2F879, 'M', u'峀'), - (0x2F87A, 'M', u'岍'), - (0x2F87B, 'M', u'𡷤'), - (0x2F87C, 'M', u'嵃'), - (0x2F87D, 'M', u'𡷦'), - (0x2F87E, 'M', u'嵮'), - (0x2F87F, 'M', u'嵫'), - (0x2F880, 'M', u'嵼'), - (0x2F881, 'M', u'巡'), - (0x2F882, 'M', u'巢'), - (0x2F883, 'M', u'㠯'), - (0x2F884, 'M', u'巽'), - (0x2F885, 'M', u'帨'), - (0x2F886, 'M', u'帽'), - (0x2F887, 'M', u'幩'), - (0x2F888, 'M', u'㡢'), - (0x2F889, 'M', u'𢆃'), - (0x2F88A, 'M', u'㡼'), - (0x2F88B, 'M', u'庰'), - (0x2F88C, 'M', u'庳'), - (0x2F88D, 'M', u'庶'), - (0x2F88E, 'M', u'廊'), - (0x2F88F, 'M', u'𪎒'), - (0x2F890, 'M', u'廾'), - (0x2F891, 'M', u'𢌱'), - (0x2F893, 'M', u'舁'), - (0x2F894, 'M', u'弢'), - (0x2F896, 'M', u'㣇'), - (0x2F897, 'M', u'𣊸'), - (0x2F898, 'M', u'𦇚'), - (0x2F899, 'M', u'形'), - (0x2F89A, 'M', u'彫'), - (0x2F89B, 'M', u'㣣'), - (0x2F89C, 'M', u'徚'), - (0x2F89D, 'M', u'忍'), - (0x2F89E, 'M', u'志'), - (0x2F89F, 'M', u'忹'), - (0x2F8A0, 'M', u'悁'), - (0x2F8A1, 'M', u'㤺'), - (0x2F8A2, 'M', u'㤜'), - (0x2F8A3, 'M', u'悔'), - (0x2F8A4, 'M', u'𢛔'), - (0x2F8A5, 'M', u'惇'), - (0x2F8A6, 'M', u'慈'), - (0x2F8A7, 'M', u'慌'), - (0x2F8A8, 'M', u'慎'), - (0x2F8A9, 'M', u'慌'), - (0x2F8AA, 'M', u'慺'), - (0x2F8AB, 'M', u'憎'), - (0x2F8AC, 'M', u'憲'), - (0x2F8AD, 'M', u'憤'), - (0x2F8AE, 'M', u'憯'), - (0x2F8AF, 'M', u'懞'), - (0x2F8B0, 'M', u'懲'), - (0x2F8B1, 'M', u'懶'), - (0x2F8B2, 'M', u'成'), - (0x2F8B3, 'M', u'戛'), - (0x2F8B4, 'M', u'扝'), - (0x2F8B5, 'M', u'抱'), - (0x2F8B6, 'M', u'拔'), - (0x2F8B7, 'M', u'捐'), - (0x2F8B8, 'M', u'𢬌'), - (0x2F8B9, 'M', u'挽'), - (0x2F8BA, 'M', u'拼'), - (0x2F8BB, 'M', u'捨'), - (0x2F8BC, 'M', u'掃'), - (0x2F8BD, 'M', u'揤'), - (0x2F8BE, 'M', u'𢯱'), - (0x2F8BF, 'M', u'搢'), - (0x2F8C0, 'M', u'揅'), - (0x2F8C1, 'M', u'掩'), - (0x2F8C2, 'M', u'㨮'), + (0x2F875, 'M', '尢'), + (0x2F876, 'M', '㞁'), + (0x2F877, 'M', '屠'), + (0x2F878, 'M', '屮'), + (0x2F879, 'M', '峀'), + (0x2F87A, 'M', '岍'), + (0x2F87B, 'M', '𡷤'), + (0x2F87C, 'M', '嵃'), + (0x2F87D, 'M', '𡷦'), + (0x2F87E, 'M', '嵮'), + (0x2F87F, 'M', '嵫'), + (0x2F880, 'M', '嵼'), + (0x2F881, 'M', '巡'), + (0x2F882, 'M', '巢'), + (0x2F883, 'M', '㠯'), + (0x2F884, 'M', '巽'), + (0x2F885, 'M', '帨'), + (0x2F886, 'M', '帽'), + (0x2F887, 'M', '幩'), + (0x2F888, 'M', '㡢'), + (0x2F889, 'M', '𢆃'), + (0x2F88A, 'M', '㡼'), + (0x2F88B, 'M', '庰'), + (0x2F88C, 'M', '庳'), + (0x2F88D, 'M', '庶'), + (0x2F88E, 'M', '廊'), + (0x2F88F, 'M', '𪎒'), + (0x2F890, 'M', '廾'), + (0x2F891, 'M', '𢌱'), + (0x2F893, 'M', '舁'), + (0x2F894, 'M', '弢'), + (0x2F896, 'M', '㣇'), + (0x2F897, 'M', '𣊸'), + (0x2F898, 'M', '𦇚'), + (0x2F899, 'M', '形'), + (0x2F89A, 'M', '彫'), + (0x2F89B, 'M', '㣣'), + (0x2F89C, 'M', '徚'), + (0x2F89D, 'M', '忍'), + (0x2F89E, 'M', '志'), + (0x2F89F, 'M', '忹'), + (0x2F8A0, 'M', '悁'), + (0x2F8A1, 'M', '㤺'), + (0x2F8A2, 'M', '㤜'), + (0x2F8A3, 'M', '悔'), + (0x2F8A4, 'M', '𢛔'), + (0x2F8A5, 'M', '惇'), + (0x2F8A6, 'M', '慈'), + (0x2F8A7, 'M', '慌'), + (0x2F8A8, 'M', '慎'), + (0x2F8A9, 'M', '慌'), + (0x2F8AA, 'M', '慺'), + (0x2F8AB, 'M', '憎'), + (0x2F8AC, 'M', '憲'), + (0x2F8AD, 'M', '憤'), + (0x2F8AE, 'M', '憯'), + (0x2F8AF, 'M', '懞'), + (0x2F8B0, 'M', '懲'), + (0x2F8B1, 'M', '懶'), + (0x2F8B2, 'M', '成'), + (0x2F8B3, 'M', '戛'), + (0x2F8B4, 'M', '扝'), + (0x2F8B5, 'M', '抱'), + (0x2F8B6, 'M', '拔'), + (0x2F8B7, 'M', '捐'), + (0x2F8B8, 'M', '𢬌'), + (0x2F8B9, 'M', '挽'), + (0x2F8BA, 'M', '拼'), + (0x2F8BB, 'M', '捨'), + (0x2F8BC, 'M', '掃'), + (0x2F8BD, 'M', '揤'), + (0x2F8BE, 'M', '𢯱'), + (0x2F8BF, 'M', '搢'), + (0x2F8C0, 'M', '揅'), + (0x2F8C1, 'M', '掩'), + (0x2F8C2, 'M', '㨮'), ] def _seg_76(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F8C3, 'M', u'摩'), - (0x2F8C4, 'M', u'摾'), - (0x2F8C5, 'M', u'撝'), - (0x2F8C6, 'M', u'摷'), - (0x2F8C7, 'M', u'㩬'), - (0x2F8C8, 'M', u'敏'), - (0x2F8C9, 'M', u'敬'), - (0x2F8CA, 'M', u'𣀊'), - (0x2F8CB, 'M', u'旣'), - (0x2F8CC, 'M', u'書'), - (0x2F8CD, 'M', u'晉'), - (0x2F8CE, 'M', u'㬙'), - (0x2F8CF, 'M', u'暑'), - (0x2F8D0, 'M', u'㬈'), - (0x2F8D1, 'M', u'㫤'), - (0x2F8D2, 'M', u'冒'), - (0x2F8D3, 'M', u'冕'), - (0x2F8D4, 'M', u'最'), - (0x2F8D5, 'M', u'暜'), - (0x2F8D6, 'M', u'肭'), - (0x2F8D7, 'M', u'䏙'), - (0x2F8D8, 'M', u'朗'), - (0x2F8D9, 'M', u'望'), - (0x2F8DA, 'M', u'朡'), - (0x2F8DB, 'M', u'杞'), - (0x2F8DC, 'M', u'杓'), - (0x2F8DD, 'M', u'𣏃'), - (0x2F8DE, 'M', u'㭉'), - (0x2F8DF, 'M', u'柺'), - (0x2F8E0, 'M', u'枅'), - (0x2F8E1, 'M', u'桒'), - (0x2F8E2, 'M', u'梅'), - (0x2F8E3, 'M', u'𣑭'), - (0x2F8E4, 'M', u'梎'), - (0x2F8E5, 'M', u'栟'), - (0x2F8E6, 'M', u'椔'), - (0x2F8E7, 'M', u'㮝'), - (0x2F8E8, 'M', u'楂'), - (0x2F8E9, 'M', u'榣'), - (0x2F8EA, 'M', u'槪'), - (0x2F8EB, 'M', u'檨'), - (0x2F8EC, 'M', u'𣚣'), - (0x2F8ED, 'M', u'櫛'), - (0x2F8EE, 'M', u'㰘'), - (0x2F8EF, 'M', u'次'), - (0x2F8F0, 'M', u'𣢧'), - (0x2F8F1, 'M', u'歔'), - (0x2F8F2, 'M', u'㱎'), - (0x2F8F3, 'M', u'歲'), - (0x2F8F4, 'M', u'殟'), - (0x2F8F5, 'M', u'殺'), - (0x2F8F6, 'M', u'殻'), - (0x2F8F7, 'M', u'𣪍'), - (0x2F8F8, 'M', u'𡴋'), - (0x2F8F9, 'M', u'𣫺'), - (0x2F8FA, 'M', u'汎'), - (0x2F8FB, 'M', u'𣲼'), - (0x2F8FC, 'M', u'沿'), - (0x2F8FD, 'M', u'泍'), - (0x2F8FE, 'M', u'汧'), - (0x2F8FF, 'M', u'洖'), - (0x2F900, 'M', u'派'), - (0x2F901, 'M', u'海'), - (0x2F902, 'M', u'流'), - (0x2F903, 'M', u'浩'), - (0x2F904, 'M', u'浸'), - (0x2F905, 'M', u'涅'), - (0x2F906, 'M', u'𣴞'), - (0x2F907, 'M', u'洴'), - (0x2F908, 'M', u'港'), - (0x2F909, 'M', u'湮'), - (0x2F90A, 'M', u'㴳'), - (0x2F90B, 'M', u'滋'), - (0x2F90C, 'M', u'滇'), - (0x2F90D, 'M', u'𣻑'), - (0x2F90E, 'M', u'淹'), - (0x2F90F, 'M', u'潮'), - (0x2F910, 'M', u'𣽞'), - (0x2F911, 'M', u'𣾎'), - (0x2F912, 'M', u'濆'), - (0x2F913, 'M', u'瀹'), - (0x2F914, 'M', u'瀞'), - (0x2F915, 'M', u'瀛'), - (0x2F916, 'M', u'㶖'), - (0x2F917, 'M', u'灊'), - (0x2F918, 'M', u'災'), - (0x2F919, 'M', u'灷'), - (0x2F91A, 'M', u'炭'), - (0x2F91B, 'M', u'𠔥'), - (0x2F91C, 'M', u'煅'), - (0x2F91D, 'M', u'𤉣'), - (0x2F91E, 'M', u'熜'), + (0x2F8C3, 'M', '摩'), + (0x2F8C4, 'M', '摾'), + (0x2F8C5, 'M', '撝'), + (0x2F8C6, 'M', '摷'), + (0x2F8C7, 'M', '㩬'), + (0x2F8C8, 'M', '敏'), + (0x2F8C9, 'M', '敬'), + (0x2F8CA, 'M', '𣀊'), + (0x2F8CB, 'M', '旣'), + (0x2F8CC, 'M', '書'), + (0x2F8CD, 'M', '晉'), + (0x2F8CE, 'M', '㬙'), + (0x2F8CF, 'M', '暑'), + (0x2F8D0, 'M', '㬈'), + (0x2F8D1, 'M', '㫤'), + (0x2F8D2, 'M', '冒'), + (0x2F8D3, 'M', '冕'), + (0x2F8D4, 'M', '最'), + (0x2F8D5, 'M', '暜'), + (0x2F8D6, 'M', '肭'), + (0x2F8D7, 'M', '䏙'), + (0x2F8D8, 'M', '朗'), + (0x2F8D9, 'M', '望'), + (0x2F8DA, 'M', '朡'), + (0x2F8DB, 'M', '杞'), + (0x2F8DC, 'M', '杓'), + (0x2F8DD, 'M', '𣏃'), + (0x2F8DE, 'M', '㭉'), + (0x2F8DF, 'M', '柺'), + (0x2F8E0, 'M', '枅'), + (0x2F8E1, 'M', '桒'), + (0x2F8E2, 'M', '梅'), + (0x2F8E3, 'M', '𣑭'), + (0x2F8E4, 'M', '梎'), + (0x2F8E5, 'M', '栟'), + (0x2F8E6, 'M', '椔'), + (0x2F8E7, 'M', '㮝'), + (0x2F8E8, 'M', '楂'), + (0x2F8E9, 'M', '榣'), + (0x2F8EA, 'M', '槪'), + (0x2F8EB, 'M', '檨'), + (0x2F8EC, 'M', '𣚣'), + (0x2F8ED, 'M', '櫛'), + (0x2F8EE, 'M', '㰘'), + (0x2F8EF, 'M', '次'), + (0x2F8F0, 'M', '𣢧'), + (0x2F8F1, 'M', '歔'), + (0x2F8F2, 'M', '㱎'), + (0x2F8F3, 'M', '歲'), + (0x2F8F4, 'M', '殟'), + (0x2F8F5, 'M', '殺'), + (0x2F8F6, 'M', '殻'), + (0x2F8F7, 'M', '𣪍'), + (0x2F8F8, 'M', '𡴋'), + (0x2F8F9, 'M', '𣫺'), + (0x2F8FA, 'M', '汎'), + (0x2F8FB, 'M', '𣲼'), + (0x2F8FC, 'M', '沿'), + (0x2F8FD, 'M', '泍'), + (0x2F8FE, 'M', '汧'), + (0x2F8FF, 'M', '洖'), + (0x2F900, 'M', '派'), + (0x2F901, 'M', '海'), + (0x2F902, 'M', '流'), + (0x2F903, 'M', '浩'), + (0x2F904, 'M', '浸'), + (0x2F905, 'M', '涅'), + (0x2F906, 'M', '𣴞'), + (0x2F907, 'M', '洴'), + (0x2F908, 'M', '港'), + (0x2F909, 'M', '湮'), + (0x2F90A, 'M', '㴳'), + (0x2F90B, 'M', '滋'), + (0x2F90C, 'M', '滇'), + (0x2F90D, 'M', '𣻑'), + (0x2F90E, 'M', '淹'), + (0x2F90F, 'M', '潮'), + (0x2F910, 'M', '𣽞'), + (0x2F911, 'M', '𣾎'), + (0x2F912, 'M', '濆'), + (0x2F913, 'M', '瀹'), + (0x2F914, 'M', '瀞'), + (0x2F915, 'M', '瀛'), + (0x2F916, 'M', '㶖'), + (0x2F917, 'M', '灊'), + (0x2F918, 'M', '災'), + (0x2F919, 'M', '灷'), + (0x2F91A, 'M', '炭'), + (0x2F91B, 'M', '𠔥'), + (0x2F91C, 'M', '煅'), + (0x2F91D, 'M', '𤉣'), + (0x2F91E, 'M', '熜'), (0x2F91F, 'X'), - (0x2F920, 'M', u'爨'), - (0x2F921, 'M', u'爵'), - (0x2F922, 'M', u'牐'), - (0x2F923, 'M', u'𤘈'), - (0x2F924, 'M', u'犀'), - (0x2F925, 'M', u'犕'), - (0x2F926, 'M', u'𤜵'), + (0x2F920, 'M', '爨'), + (0x2F921, 'M', '爵'), + (0x2F922, 'M', '牐'), + (0x2F923, 'M', '𤘈'), + (0x2F924, 'M', '犀'), + (0x2F925, 'M', '犕'), + (0x2F926, 'M', '𤜵'), ] def _seg_77(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F927, 'M', u'𤠔'), - (0x2F928, 'M', u'獺'), - (0x2F929, 'M', u'王'), - (0x2F92A, 'M', u'㺬'), - (0x2F92B, 'M', u'玥'), - (0x2F92C, 'M', u'㺸'), - (0x2F92E, 'M', u'瑇'), - (0x2F92F, 'M', u'瑜'), - (0x2F930, 'M', u'瑱'), - (0x2F931, 'M', u'璅'), - (0x2F932, 'M', u'瓊'), - (0x2F933, 'M', u'㼛'), - (0x2F934, 'M', u'甤'), - (0x2F935, 'M', u'𤰶'), - (0x2F936, 'M', u'甾'), - (0x2F937, 'M', u'𤲒'), - (0x2F938, 'M', u'異'), - (0x2F939, 'M', u'𢆟'), - (0x2F93A, 'M', u'瘐'), - (0x2F93B, 'M', u'𤾡'), - (0x2F93C, 'M', u'𤾸'), - (0x2F93D, 'M', u'𥁄'), - (0x2F93E, 'M', u'㿼'), - (0x2F93F, 'M', u'䀈'), - (0x2F940, 'M', u'直'), - (0x2F941, 'M', u'𥃳'), - (0x2F942, 'M', u'𥃲'), - (0x2F943, 'M', u'𥄙'), - (0x2F944, 'M', u'𥄳'), - (0x2F945, 'M', u'眞'), - (0x2F946, 'M', u'真'), - (0x2F948, 'M', u'睊'), - (0x2F949, 'M', u'䀹'), - (0x2F94A, 'M', u'瞋'), - (0x2F94B, 'M', u'䁆'), - (0x2F94C, 'M', u'䂖'), - (0x2F94D, 'M', u'𥐝'), - (0x2F94E, 'M', u'硎'), - (0x2F94F, 'M', u'碌'), - (0x2F950, 'M', u'磌'), - (0x2F951, 'M', u'䃣'), - (0x2F952, 'M', u'𥘦'), - (0x2F953, 'M', u'祖'), - (0x2F954, 'M', u'𥚚'), - (0x2F955, 'M', u'𥛅'), - (0x2F956, 'M', u'福'), - (0x2F957, 'M', u'秫'), - (0x2F958, 'M', u'䄯'), - (0x2F959, 'M', u'穀'), - (0x2F95A, 'M', u'穊'), - (0x2F95B, 'M', u'穏'), - (0x2F95C, 'M', u'𥥼'), - (0x2F95D, 'M', u'𥪧'), + (0x2F927, 'M', '𤠔'), + (0x2F928, 'M', '獺'), + (0x2F929, 'M', '王'), + (0x2F92A, 'M', '㺬'), + (0x2F92B, 'M', '玥'), + (0x2F92C, 'M', '㺸'), + (0x2F92E, 'M', '瑇'), + (0x2F92F, 'M', '瑜'), + (0x2F930, 'M', '瑱'), + (0x2F931, 'M', '璅'), + (0x2F932, 'M', '瓊'), + (0x2F933, 'M', '㼛'), + (0x2F934, 'M', '甤'), + (0x2F935, 'M', '𤰶'), + (0x2F936, 'M', '甾'), + (0x2F937, 'M', '𤲒'), + (0x2F938, 'M', '異'), + (0x2F939, 'M', '𢆟'), + (0x2F93A, 'M', '瘐'), + (0x2F93B, 'M', '𤾡'), + (0x2F93C, 'M', '𤾸'), + (0x2F93D, 'M', '𥁄'), + (0x2F93E, 'M', '㿼'), + (0x2F93F, 'M', '䀈'), + (0x2F940, 'M', '直'), + (0x2F941, 'M', '𥃳'), + (0x2F942, 'M', '𥃲'), + (0x2F943, 'M', '𥄙'), + (0x2F944, 'M', '𥄳'), + (0x2F945, 'M', '眞'), + (0x2F946, 'M', '真'), + (0x2F948, 'M', '睊'), + (0x2F949, 'M', '䀹'), + (0x2F94A, 'M', '瞋'), + (0x2F94B, 'M', '䁆'), + (0x2F94C, 'M', '䂖'), + (0x2F94D, 'M', '𥐝'), + (0x2F94E, 'M', '硎'), + (0x2F94F, 'M', '碌'), + (0x2F950, 'M', '磌'), + (0x2F951, 'M', '䃣'), + (0x2F952, 'M', '𥘦'), + (0x2F953, 'M', '祖'), + (0x2F954, 'M', '𥚚'), + (0x2F955, 'M', '𥛅'), + (0x2F956, 'M', '福'), + (0x2F957, 'M', '秫'), + (0x2F958, 'M', '䄯'), + (0x2F959, 'M', '穀'), + (0x2F95A, 'M', '穊'), + (0x2F95B, 'M', '穏'), + (0x2F95C, 'M', '𥥼'), + (0x2F95D, 'M', '𥪧'), (0x2F95F, 'X'), - (0x2F960, 'M', u'䈂'), - (0x2F961, 'M', u'𥮫'), - (0x2F962, 'M', u'篆'), - (0x2F963, 'M', u'築'), - (0x2F964, 'M', u'䈧'), - (0x2F965, 'M', u'𥲀'), - (0x2F966, 'M', u'糒'), - (0x2F967, 'M', u'䊠'), - (0x2F968, 'M', u'糨'), - (0x2F969, 'M', u'糣'), - (0x2F96A, 'M', u'紀'), - (0x2F96B, 'M', u'𥾆'), - (0x2F96C, 'M', u'絣'), - (0x2F96D, 'M', u'䌁'), - (0x2F96E, 'M', u'緇'), - (0x2F96F, 'M', u'縂'), - (0x2F970, 'M', u'繅'), - (0x2F971, 'M', u'䌴'), - (0x2F972, 'M', u'𦈨'), - (0x2F973, 'M', u'𦉇'), - (0x2F974, 'M', u'䍙'), - (0x2F975, 'M', u'𦋙'), - (0x2F976, 'M', u'罺'), - (0x2F977, 'M', u'𦌾'), - (0x2F978, 'M', u'羕'), - (0x2F979, 'M', u'翺'), - (0x2F97A, 'M', u'者'), - (0x2F97B, 'M', u'𦓚'), - (0x2F97C, 'M', u'𦔣'), - (0x2F97D, 'M', u'聠'), - (0x2F97E, 'M', u'𦖨'), - (0x2F97F, 'M', u'聰'), - (0x2F980, 'M', u'𣍟'), - (0x2F981, 'M', u'䏕'), - (0x2F982, 'M', u'育'), - (0x2F983, 'M', u'脃'), - (0x2F984, 'M', u'䐋'), - (0x2F985, 'M', u'脾'), - (0x2F986, 'M', u'媵'), - (0x2F987, 'M', u'𦞧'), - (0x2F988, 'M', u'𦞵'), - (0x2F989, 'M', u'𣎓'), - (0x2F98A, 'M', u'𣎜'), - (0x2F98B, 'M', u'舁'), - (0x2F98C, 'M', u'舄'), - (0x2F98D, 'M', u'辞'), + (0x2F960, 'M', '䈂'), + (0x2F961, 'M', '𥮫'), + (0x2F962, 'M', '篆'), + (0x2F963, 'M', '築'), + (0x2F964, 'M', '䈧'), + (0x2F965, 'M', '𥲀'), + (0x2F966, 'M', '糒'), + (0x2F967, 'M', '䊠'), + (0x2F968, 'M', '糨'), + (0x2F969, 'M', '糣'), + (0x2F96A, 'M', '紀'), + (0x2F96B, 'M', '𥾆'), + (0x2F96C, 'M', '絣'), + (0x2F96D, 'M', '䌁'), + (0x2F96E, 'M', '緇'), + (0x2F96F, 'M', '縂'), + (0x2F970, 'M', '繅'), + (0x2F971, 'M', '䌴'), + (0x2F972, 'M', '𦈨'), + (0x2F973, 'M', '𦉇'), + (0x2F974, 'M', '䍙'), + (0x2F975, 'M', '𦋙'), + (0x2F976, 'M', '罺'), + (0x2F977, 'M', '𦌾'), + (0x2F978, 'M', '羕'), + (0x2F979, 'M', '翺'), + (0x2F97A, 'M', '者'), + (0x2F97B, 'M', '𦓚'), + (0x2F97C, 'M', '𦔣'), + (0x2F97D, 'M', '聠'), + (0x2F97E, 'M', '𦖨'), + (0x2F97F, 'M', '聰'), + (0x2F980, 'M', '𣍟'), + (0x2F981, 'M', '䏕'), + (0x2F982, 'M', '育'), + (0x2F983, 'M', '脃'), + (0x2F984, 'M', '䐋'), + (0x2F985, 'M', '脾'), + (0x2F986, 'M', '媵'), + (0x2F987, 'M', '𦞧'), + (0x2F988, 'M', '𦞵'), + (0x2F989, 'M', '𣎓'), + (0x2F98A, 'M', '𣎜'), + (0x2F98B, 'M', '舁'), + (0x2F98C, 'M', '舄'), + (0x2F98D, 'M', '辞'), ] def _seg_78(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F98E, 'M', u'䑫'), - (0x2F98F, 'M', u'芑'), - (0x2F990, 'M', u'芋'), - (0x2F991, 'M', u'芝'), - (0x2F992, 'M', u'劳'), - (0x2F993, 'M', u'花'), - (0x2F994, 'M', u'芳'), - (0x2F995, 'M', u'芽'), - (0x2F996, 'M', u'苦'), - (0x2F997, 'M', u'𦬼'), - (0x2F998, 'M', u'若'), - (0x2F999, 'M', u'茝'), - (0x2F99A, 'M', u'荣'), - (0x2F99B, 'M', u'莭'), - (0x2F99C, 'M', u'茣'), - (0x2F99D, 'M', u'莽'), - (0x2F99E, 'M', u'菧'), - (0x2F99F, 'M', u'著'), - (0x2F9A0, 'M', u'荓'), - (0x2F9A1, 'M', u'菊'), - (0x2F9A2, 'M', u'菌'), - (0x2F9A3, 'M', u'菜'), - (0x2F9A4, 'M', u'𦰶'), - (0x2F9A5, 'M', u'𦵫'), - (0x2F9A6, 'M', u'𦳕'), - (0x2F9A7, 'M', u'䔫'), - (0x2F9A8, 'M', u'蓱'), - (0x2F9A9, 'M', u'蓳'), - (0x2F9AA, 'M', u'蔖'), - (0x2F9AB, 'M', u'𧏊'), - (0x2F9AC, 'M', u'蕤'), - (0x2F9AD, 'M', u'𦼬'), - (0x2F9AE, 'M', u'䕝'), - (0x2F9AF, 'M', u'䕡'), - (0x2F9B0, 'M', u'𦾱'), - (0x2F9B1, 'M', u'𧃒'), - (0x2F9B2, 'M', u'䕫'), - (0x2F9B3, 'M', u'虐'), - (0x2F9B4, 'M', u'虜'), - (0x2F9B5, 'M', u'虧'), - (0x2F9B6, 'M', u'虩'), - (0x2F9B7, 'M', u'蚩'), - (0x2F9B8, 'M', u'蚈'), - (0x2F9B9, 'M', u'蜎'), - (0x2F9BA, 'M', u'蛢'), - (0x2F9BB, 'M', u'蝹'), - (0x2F9BC, 'M', u'蜨'), - (0x2F9BD, 'M', u'蝫'), - (0x2F9BE, 'M', u'螆'), + (0x2F98E, 'M', '䑫'), + (0x2F98F, 'M', '芑'), + (0x2F990, 'M', '芋'), + (0x2F991, 'M', '芝'), + (0x2F992, 'M', '劳'), + (0x2F993, 'M', '花'), + (0x2F994, 'M', '芳'), + (0x2F995, 'M', '芽'), + (0x2F996, 'M', '苦'), + (0x2F997, 'M', '𦬼'), + (0x2F998, 'M', '若'), + (0x2F999, 'M', '茝'), + (0x2F99A, 'M', '荣'), + (0x2F99B, 'M', '莭'), + (0x2F99C, 'M', '茣'), + (0x2F99D, 'M', '莽'), + (0x2F99E, 'M', '菧'), + (0x2F99F, 'M', '著'), + (0x2F9A0, 'M', '荓'), + (0x2F9A1, 'M', '菊'), + (0x2F9A2, 'M', '菌'), + (0x2F9A3, 'M', '菜'), + (0x2F9A4, 'M', '𦰶'), + (0x2F9A5, 'M', '𦵫'), + (0x2F9A6, 'M', '𦳕'), + (0x2F9A7, 'M', '䔫'), + (0x2F9A8, 'M', '蓱'), + (0x2F9A9, 'M', '蓳'), + (0x2F9AA, 'M', '蔖'), + (0x2F9AB, 'M', '𧏊'), + (0x2F9AC, 'M', '蕤'), + (0x2F9AD, 'M', '𦼬'), + (0x2F9AE, 'M', '䕝'), + (0x2F9AF, 'M', '䕡'), + (0x2F9B0, 'M', '𦾱'), + (0x2F9B1, 'M', '𧃒'), + (0x2F9B2, 'M', '䕫'), + (0x2F9B3, 'M', '虐'), + (0x2F9B4, 'M', '虜'), + (0x2F9B5, 'M', '虧'), + (0x2F9B6, 'M', '虩'), + (0x2F9B7, 'M', '蚩'), + (0x2F9B8, 'M', '蚈'), + (0x2F9B9, 'M', '蜎'), + (0x2F9BA, 'M', '蛢'), + (0x2F9BB, 'M', '蝹'), + (0x2F9BC, 'M', '蜨'), + (0x2F9BD, 'M', '蝫'), + (0x2F9BE, 'M', '螆'), (0x2F9BF, 'X'), - (0x2F9C0, 'M', u'蟡'), - (0x2F9C1, 'M', u'蠁'), - (0x2F9C2, 'M', u'䗹'), - (0x2F9C3, 'M', u'衠'), - (0x2F9C4, 'M', u'衣'), - (0x2F9C5, 'M', u'𧙧'), - (0x2F9C6, 'M', u'裗'), - (0x2F9C7, 'M', u'裞'), - (0x2F9C8, 'M', u'䘵'), - (0x2F9C9, 'M', u'裺'), - (0x2F9CA, 'M', u'㒻'), - (0x2F9CB, 'M', u'𧢮'), - (0x2F9CC, 'M', u'𧥦'), - (0x2F9CD, 'M', u'䚾'), - (0x2F9CE, 'M', u'䛇'), - (0x2F9CF, 'M', u'誠'), - (0x2F9D0, 'M', u'諭'), - (0x2F9D1, 'M', u'變'), - (0x2F9D2, 'M', u'豕'), - (0x2F9D3, 'M', u'𧲨'), - (0x2F9D4, 'M', u'貫'), - (0x2F9D5, 'M', u'賁'), - (0x2F9D6, 'M', u'贛'), - (0x2F9D7, 'M', u'起'), - (0x2F9D8, 'M', u'𧼯'), - (0x2F9D9, 'M', u'𠠄'), - (0x2F9DA, 'M', u'跋'), - (0x2F9DB, 'M', u'趼'), - (0x2F9DC, 'M', u'跰'), - (0x2F9DD, 'M', u'𠣞'), - (0x2F9DE, 'M', u'軔'), - (0x2F9DF, 'M', u'輸'), - (0x2F9E0, 'M', u'𨗒'), - (0x2F9E1, 'M', u'𨗭'), - (0x2F9E2, 'M', u'邔'), - (0x2F9E3, 'M', u'郱'), - (0x2F9E4, 'M', u'鄑'), - (0x2F9E5, 'M', u'𨜮'), - (0x2F9E6, 'M', u'鄛'), - (0x2F9E7, 'M', u'鈸'), - (0x2F9E8, 'M', u'鋗'), - (0x2F9E9, 'M', u'鋘'), - (0x2F9EA, 'M', u'鉼'), - (0x2F9EB, 'M', u'鏹'), - (0x2F9EC, 'M', u'鐕'), - (0x2F9ED, 'M', u'𨯺'), - (0x2F9EE, 'M', u'開'), - (0x2F9EF, 'M', u'䦕'), - (0x2F9F0, 'M', u'閷'), - (0x2F9F1, 'M', u'𨵷'), + (0x2F9C0, 'M', '蟡'), + (0x2F9C1, 'M', '蠁'), + (0x2F9C2, 'M', '䗹'), + (0x2F9C3, 'M', '衠'), + (0x2F9C4, 'M', '衣'), + (0x2F9C5, 'M', '𧙧'), + (0x2F9C6, 'M', '裗'), + (0x2F9C7, 'M', '裞'), + (0x2F9C8, 'M', '䘵'), + (0x2F9C9, 'M', '裺'), + (0x2F9CA, 'M', '㒻'), + (0x2F9CB, 'M', '𧢮'), + (0x2F9CC, 'M', '𧥦'), + (0x2F9CD, 'M', '䚾'), + (0x2F9CE, 'M', '䛇'), + (0x2F9CF, 'M', '誠'), + (0x2F9D0, 'M', '諭'), + (0x2F9D1, 'M', '變'), + (0x2F9D2, 'M', '豕'), + (0x2F9D3, 'M', '𧲨'), + (0x2F9D4, 'M', '貫'), + (0x2F9D5, 'M', '賁'), + (0x2F9D6, 'M', '贛'), + (0x2F9D7, 'M', '起'), + (0x2F9D8, 'M', '𧼯'), + (0x2F9D9, 'M', '𠠄'), + (0x2F9DA, 'M', '跋'), + (0x2F9DB, 'M', '趼'), + (0x2F9DC, 'M', '跰'), + (0x2F9DD, 'M', '𠣞'), + (0x2F9DE, 'M', '軔'), + (0x2F9DF, 'M', '輸'), + (0x2F9E0, 'M', '𨗒'), + (0x2F9E1, 'M', '𨗭'), + (0x2F9E2, 'M', '邔'), + (0x2F9E3, 'M', '郱'), + (0x2F9E4, 'M', '鄑'), + (0x2F9E5, 'M', '𨜮'), + (0x2F9E6, 'M', '鄛'), + (0x2F9E7, 'M', '鈸'), + (0x2F9E8, 'M', '鋗'), + (0x2F9E9, 'M', '鋘'), + (0x2F9EA, 'M', '鉼'), + (0x2F9EB, 'M', '鏹'), + (0x2F9EC, 'M', '鐕'), + (0x2F9ED, 'M', '𨯺'), + (0x2F9EE, 'M', '開'), + (0x2F9EF, 'M', '䦕'), + (0x2F9F0, 'M', '閷'), + (0x2F9F1, 'M', '𨵷'), ] def _seg_79(): + # type: () -> List[Union[Tuple[int, str], Tuple[int, str, str]]] return [ - (0x2F9F2, 'M', u'䧦'), - (0x2F9F3, 'M', u'雃'), - (0x2F9F4, 'M', u'嶲'), - (0x2F9F5, 'M', u'霣'), - (0x2F9F6, 'M', u'𩅅'), - (0x2F9F7, 'M', u'𩈚'), - (0x2F9F8, 'M', u'䩮'), - (0x2F9F9, 'M', u'䩶'), - (0x2F9FA, 'M', u'韠'), - (0x2F9FB, 'M', u'𩐊'), - (0x2F9FC, 'M', u'䪲'), - (0x2F9FD, 'M', u'𩒖'), - (0x2F9FE, 'M', u'頋'), - (0x2FA00, 'M', u'頩'), - (0x2FA01, 'M', u'𩖶'), - (0x2FA02, 'M', u'飢'), - (0x2FA03, 'M', u'䬳'), - (0x2FA04, 'M', u'餩'), - (0x2FA05, 'M', u'馧'), - (0x2FA06, 'M', u'駂'), - (0x2FA07, 'M', u'駾'), - (0x2FA08, 'M', u'䯎'), - (0x2FA09, 'M', u'𩬰'), - (0x2FA0A, 'M', u'鬒'), - (0x2FA0B, 'M', u'鱀'), - (0x2FA0C, 'M', u'鳽'), - (0x2FA0D, 'M', u'䳎'), - (0x2FA0E, 'M', u'䳭'), - (0x2FA0F, 'M', u'鵧'), - (0x2FA10, 'M', u'𪃎'), - (0x2FA11, 'M', u'䳸'), - (0x2FA12, 'M', u'𪄅'), - (0x2FA13, 'M', u'𪈎'), - (0x2FA14, 'M', u'𪊑'), - (0x2FA15, 'M', u'麻'), - (0x2FA16, 'M', u'䵖'), - (0x2FA17, 'M', u'黹'), - (0x2FA18, 'M', u'黾'), - (0x2FA19, 'M', u'鼅'), - (0x2FA1A, 'M', u'鼏'), - (0x2FA1B, 'M', u'鼖'), - (0x2FA1C, 'M', u'鼻'), - (0x2FA1D, 'M', u'𪘀'), + (0x2F9F2, 'M', '䧦'), + (0x2F9F3, 'M', '雃'), + (0x2F9F4, 'M', '嶲'), + (0x2F9F5, 'M', '霣'), + (0x2F9F6, 'M', '𩅅'), + (0x2F9F7, 'M', '𩈚'), + (0x2F9F8, 'M', '䩮'), + (0x2F9F9, 'M', '䩶'), + (0x2F9FA, 'M', '韠'), + (0x2F9FB, 'M', '𩐊'), + (0x2F9FC, 'M', '䪲'), + (0x2F9FD, 'M', '𩒖'), + (0x2F9FE, 'M', '頋'), + (0x2FA00, 'M', '頩'), + (0x2FA01, 'M', '𩖶'), + (0x2FA02, 'M', '飢'), + (0x2FA03, 'M', '䬳'), + (0x2FA04, 'M', '餩'), + (0x2FA05, 'M', '馧'), + (0x2FA06, 'M', '駂'), + (0x2FA07, 'M', '駾'), + (0x2FA08, 'M', '䯎'), + (0x2FA09, 'M', '𩬰'), + (0x2FA0A, 'M', '鬒'), + (0x2FA0B, 'M', '鱀'), + (0x2FA0C, 'M', '鳽'), + (0x2FA0D, 'M', '䳎'), + (0x2FA0E, 'M', '䳭'), + (0x2FA0F, 'M', '鵧'), + (0x2FA10, 'M', '𪃎'), + (0x2FA11, 'M', '䳸'), + (0x2FA12, 'M', '𪄅'), + (0x2FA13, 'M', '𪈎'), + (0x2FA14, 'M', '𪊑'), + (0x2FA15, 'M', '麻'), + (0x2FA16, 'M', '䵖'), + (0x2FA17, 'M', '黹'), + (0x2FA18, 'M', '黾'), + (0x2FA19, 'M', '鼅'), + (0x2FA1A, 'M', '鼏'), + (0x2FA1B, 'M', '鼖'), + (0x2FA1C, 'M', '鼻'), + (0x2FA1D, 'M', '𪘀'), (0x2FA1E, 'X'), (0x30000, 'V'), (0x3134B, 'X'), @@ -8354,4 +8435,4 @@ uts46data = tuple( + _seg_77() + _seg_78() + _seg_79() -) +) # type: Tuple[Union[Tuple[int, str], Tuple[int, str, str]], ...] diff --git a/pipenv/vendor/importlib_metadata/__init__.py b/pipenv/vendor/importlib_metadata/__init__.py index 7031323d..1705129d 100644 --- a/pipenv/vendor/importlib_metadata/__init__.py +++ b/pipenv/vendor/importlib_metadata/__init__.py @@ -1,73 +1,144 @@ -from __future__ import unicode_literals, absolute_import - -import io import os import re import abc import csv import sys import zipp +import email +import pathlib import operator +import platform +import textwrap +import warnings import functools import itertools import posixpath import collections +from . import _adapters, _meta +from ._collections import FreezableDefaultDict, Pair from ._compat import ( - install, NullFinder, - ConfigParser, - suppress, - map, - FileNotFoundError, - IsADirectoryError, - NotADirectoryError, - PermissionError, - pathlib, - ModuleNotFoundError, - MetaPathFinder, - email_message_from_string, PyPy_repr, - unique_ordered, - str, - ) + install, +) +from ._functools import method_cache +from ._itertools import unique_everseen +from ._meta import PackageMetadata, SimplePath + +from contextlib import suppress from importlib import import_module +from importlib.abc import MetaPathFinder from itertools import starmap - - -__metaclass__ = type +from typing import List, Mapping, Optional, Union __all__ = [ 'Distribution', 'DistributionFinder', + 'PackageMetadata', 'PackageNotFoundError', 'distribution', 'distributions', 'entry_points', 'files', 'metadata', + 'packages_distributions', 'requires', 'version', - ] +] + + +def _pypy_partial(val): + """ + Adjust for variable stacklevel on partial under PyPy. + + Workaround for #327. + """ + is_pypy = platform.python_implementation() == 'PyPy' + return val + is_pypy class PackageNotFoundError(ModuleNotFoundError): """The package was not found.""" def __str__(self): - tmpl = "No package metadata was found for {self.name}" - return tmpl.format(**locals()) + return f"No package metadata was found for {self.name}" @property def name(self): - name, = self.args + (name,) = self.args return name +class Sectioned: + """ + A simple entry point config parser for performance + + >>> for item in Sectioned.read(Sectioned._sample): + ... print(item) + Pair(name='sec1', value='# comments ignored') + Pair(name='sec1', value='a = 1') + Pair(name='sec1', value='b = 2') + Pair(name='sec2', value='a = 2') + + >>> res = Sectioned.section_pairs(Sectioned._sample) + >>> item = next(res) + >>> item.name + 'sec1' + >>> item.value + Pair(name='a', value='1') + >>> item = next(res) + >>> item.value + Pair(name='b', value='2') + >>> item = next(res) + >>> item.name + 'sec2' + >>> item.value + Pair(name='a', value='2') + >>> list(res) + [] + """ + + _sample = textwrap.dedent( + """ + [sec1] + # comments ignored + a = 1 + b = 2 + + [sec2] + a = 2 + """ + ).lstrip() + + @classmethod + def section_pairs(cls, text): + return ( + section._replace(value=Pair.parse(section.value)) + for section in cls.read(text, filter_=cls.valid) + if section.name is not None + ) + + @staticmethod + def read(text, filter_=None): + lines = filter(filter_, map(str.strip, text.splitlines())) + name = None + for value in lines: + section_match = value.startswith('[') and value.endswith(']') + if section_match: + name = value.strip('[]') + continue + yield Pair(name, value) + + @staticmethod + def valid(line): + return line and not line.startswith('#') + + class EntryPoint( - PyPy_repr, - collections.namedtuple('EntryPointBase', 'name value group')): + PyPy_repr, collections.namedtuple('EntryPointBase', 'name value group') +): """An entry point as defined by Python packaging conventions. See `the packaging docs on entry points @@ -79,7 +150,7 @@ class EntryPoint( r'(?P[\w.]+)\s*' r'(:\s*(?P[\w.]+))?\s*' r'(?P\[.*\])?\s*$' - ) + ) """ A regular expression describing the syntax for an entry point, which might look like: @@ -96,6 +167,8 @@ class EntryPoint( following the attr, and following any extras. """ + dist: Optional['Distribution'] = None + def load(self): """Load the entry point from its definition. If only a module is indicated by the value, return that module. Otherwise, @@ -121,37 +194,283 @@ class EntryPoint( match = self.pattern.match(self.value) return list(re.finditer(r'\w+', match.group('extras') or '')) - @classmethod - def _from_config(cls, config): - return [ - cls(name, value, group) - for group in config.sections() - for name, value in config.items(group) - ] - - @classmethod - def _from_text(cls, text): - config = ConfigParser(delimiters='=') - # case sensitive: https://stackoverflow.com/q/1611799/812183 - config.optionxform = str - try: - config.read_string(text) - except AttributeError: # pragma: nocover - # Python 2 has no read_string - config.readfp(io.StringIO(text)) - return EntryPoint._from_config(config) + def _for(self, dist): + self.dist = dist + return self def __iter__(self): """ - Supply iter so one may construct dicts of EntryPoints easily. + Supply iter so one may construct dicts of EntryPoints by name. """ + msg = ( + "Construction of dict of EntryPoints is deprecated in " + "favor of EntryPoints." + ) + warnings.warn(msg, DeprecationWarning) return iter((self.name, self)) def __reduce__(self): return ( self.__class__, (self.name, self.value, self.group), + ) + + def matches(self, **params): + attrs = (getattr(self, param) for param in params) + return all(map(operator.eq, params.values(), attrs)) + + +class DeprecatedList(list): + """ + Allow an otherwise immutable object to implement mutability + for compatibility. + + >>> recwarn = getfixture('recwarn') + >>> dl = DeprecatedList(range(3)) + >>> dl[0] = 1 + >>> dl.append(3) + >>> del dl[3] + >>> dl.reverse() + >>> dl.sort() + >>> dl.extend([4]) + >>> dl.pop(-1) + 4 + >>> dl.remove(1) + >>> dl += [5] + >>> dl + [6] + [1, 2, 5, 6] + >>> dl + (6,) + [1, 2, 5, 6] + >>> dl.insert(0, 0) + >>> dl + [0, 1, 2, 5] + >>> dl == [0, 1, 2, 5] + True + >>> dl == (0, 1, 2, 5) + True + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "EntryPoints list interface is deprecated. Cast to list if needed.", + DeprecationWarning, + stacklevel=_pypy_partial(2), + ) + + def __setitem__(self, *args, **kwargs): + self._warn() + return super().__setitem__(*args, **kwargs) + + def __delitem__(self, *args, **kwargs): + self._warn() + return super().__delitem__(*args, **kwargs) + + def append(self, *args, **kwargs): + self._warn() + return super().append(*args, **kwargs) + + def reverse(self, *args, **kwargs): + self._warn() + return super().reverse(*args, **kwargs) + + def extend(self, *args, **kwargs): + self._warn() + return super().extend(*args, **kwargs) + + def pop(self, *args, **kwargs): + self._warn() + return super().pop(*args, **kwargs) + + def remove(self, *args, **kwargs): + self._warn() + return super().remove(*args, **kwargs) + + def __iadd__(self, *args, **kwargs): + self._warn() + return super().__iadd__(*args, **kwargs) + + def __add__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + return self.__class__(tuple(self) + other) + + def insert(self, *args, **kwargs): + self._warn() + return super().insert(*args, **kwargs) + + def sort(self, *args, **kwargs): + self._warn() + return super().sort(*args, **kwargs) + + def __eq__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + + return tuple(self).__eq__(other) + + +class EntryPoints(DeprecatedList): + """ + An immutable collection of selectable EntryPoint objects. + """ + + __slots__ = () + + def __getitem__(self, name): # -> EntryPoint: + """ + Get the EntryPoint in self matching name. + """ + if isinstance(name, int): + warnings.warn( + "Accessing entry points by index is deprecated. " + "Cast to tuple if needed.", + DeprecationWarning, + stacklevel=2, ) + return super().__getitem__(name) + try: + return next(iter(self.select(name=name))) + except StopIteration: + raise KeyError(name) + + def select(self, **params): + """ + Select entry points from self that match the + given parameters (typically group and/or name). + """ + return EntryPoints(ep for ep in self if ep.matches(**params)) + + @property + def names(self): + """ + Return the set of all names of all entry points. + """ + return set(ep.name for ep in self) + + @property + def groups(self): + """ + Return the set of all groups of all entry points. + + For coverage while SelectableGroups is present. + >>> EntryPoints().groups + set() + """ + return set(ep.group for ep in self) + + @classmethod + def _from_text_for(cls, text, dist): + return cls(ep._for(dist) for ep in cls._from_text(text)) + + @classmethod + def _from_text(cls, text): + return itertools.starmap(EntryPoint, cls._parse_groups(text or '')) + + @staticmethod + def _parse_groups(text): + return ( + (item.value.name, item.value.value, item.name) + for item in Sectioned.section_pairs(text) + ) + + +class Deprecated: + """ + Compatibility add-in for mapping to indicate that + mapping behavior is deprecated. + + >>> recwarn = getfixture('recwarn') + >>> class DeprecatedDict(Deprecated, dict): pass + >>> dd = DeprecatedDict(foo='bar') + >>> dd.get('baz', None) + >>> dd['foo'] + 'bar' + >>> list(dd) + ['foo'] + >>> list(dd.keys()) + ['foo'] + >>> 'foo' in dd + True + >>> list(dd.values()) + ['bar'] + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "SelectableGroups dict interface is deprecated. Use select.", + DeprecationWarning, + stacklevel=_pypy_partial(2), + ) + + def __getitem__(self, name): + self._warn() + return super().__getitem__(name) + + def get(self, name, default=None): + self._warn() + return super().get(name, default) + + def __iter__(self): + self._warn() + return super().__iter__() + + def __contains__(self, *args): + self._warn() + return super().__contains__(*args) + + def keys(self): + self._warn() + return super().keys() + + def values(self): + self._warn() + return super().values() + + +class SelectableGroups(Deprecated, dict): + """ + A backward- and forward-compatible result from + entry_points that fully implements the dict interface. + """ + + @classmethod + def load(cls, eps): + by_group = operator.attrgetter('group') + ordered = sorted(eps, key=by_group) + grouped = itertools.groupby(ordered, by_group) + return cls((group, EntryPoints(eps)) for group, eps in grouped) + + @property + def _all(self): + """ + Reconstruct a list of all entrypoints from the groups. + """ + groups = super(Deprecated, self).values() + return EntryPoints(itertools.chain.from_iterable(groups)) + + @property + def groups(self): + return self._all.groups + + @property + def names(self): + """ + for coverage: + >>> SelectableGroups().names + set() + """ + return self._all.names + + def select(self, **params): + if not params: + return self + return self._all.select(**params) class PackagePath(pathlib.PurePosixPath): @@ -175,7 +494,7 @@ class FileHash: self.mode, _, self.value = spec.partition('=') def __repr__(self): - return ''.format(self.mode, self.value) + return f'' class Distribution: @@ -229,9 +548,8 @@ class Distribution: raise ValueError("cannot accept context and kwargs") context = context or DistributionFinder.Context(**kwargs) return itertools.chain.from_iterable( - resolver(context) - for resolver in cls._discover_resolvers() - ) + resolver(context) for resolver in cls._discover_resolvers() + ) @staticmethod def at(path): @@ -246,24 +564,24 @@ class Distribution: def _discover_resolvers(): """Search the meta_path for resolvers.""" declared = ( - getattr(finder, 'find_distributions', None) - for finder in sys.meta_path - ) + getattr(finder, 'find_distributions', None) for finder in sys.meta_path + ) return filter(None, declared) @classmethod def _local(cls, root='.'): from pep517 import build, meta + system = build.compat_system(root) builder = functools.partial( meta.build, source_dir=root, system=system, - ) + ) return PathDistribution(zipp.Path(meta.build_as_zip(builder))) @property - def metadata(self): + def metadata(self) -> _meta.PackageMetadata: """Return the parsed metadata for this Distribution. The returned object will have keys that name the various bits of @@ -276,8 +594,18 @@ class Distribution: # effect is to just end up using the PathDistribution's self._path # (which points to the egg-info file) attribute unchanged. or self.read_text('') - ) - return email_message_from_string(text) + ) + return _adapters.Message(email.message_from_string(text)) + + @property + def name(self): + """Return the 'Name' metadata for the distribution package.""" + return self.metadata['Name'] + + @property + def _normalized_name(self): + """Return a normalized version of the name.""" + return Prepared.normalize(self.name) @property def version(self): @@ -286,7 +614,7 @@ class Distribution: @property def entry_points(self): - return EntryPoint._from_text(self.read_text('entry_points.txt')) + return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self) @property def files(self): @@ -340,23 +668,7 @@ class Distribution: @classmethod def _deps_from_requires_text(cls, source): - section_pairs = cls._read_sections(source.splitlines()) - sections = { - section: list(map(operator.itemgetter('line'), results)) - for section, results in - itertools.groupby(section_pairs, operator.itemgetter('section')) - } - return cls._convert_egg_info_reqs_to_simple_reqs(sections) - - @staticmethod - def _read_sections(lines): - section = None - for line in filter(None, lines): - section_match = re.match(r'\[(.*)\]$', line) - if section_match: - section = section_match.group(1) - continue - yield locals() + return cls._convert_egg_info_reqs_to_simple_reqs(Sectioned.read(source)) @staticmethod def _convert_egg_info_reqs_to_simple_reqs(sections): @@ -369,20 +681,20 @@ class Distribution: requirement. This method converts the former to the latter. See _test_deps_from_requires_text for an example. """ + def make_condition(name): - return name and 'extra == "{name}"'.format(name=name) + return name and f'extra == "{name}"' def parse_condition(section): section = section or '' extra, sep, markers = section.partition(':') if extra and markers: - markers = '({markers})'.format(markers=markers) + markers = f'({markers})' conditions = list(filter(None, [markers, make_condition(extra)])) return '; ' + ' and '.join(conditions) if conditions else '' - for section, deps in sections.items(): - for dep in deps: - yield dep + parse_condition(section) + for section in sections: + yield section.value + parse_condition(section.name) class DistributionFinder(MetaPathFinder): @@ -414,10 +726,11 @@ class DistributionFinder(MetaPathFinder): @property def path(self): """ - The path that a distribution finder should search. + The sequence of directory path that a distribution finder + should search. - Typically refers to Python package paths and defaults - to ``sys.path``. + Typically refers to Python installed package paths such as + "site-packages" directories and defaults to ``sys.path``. """ return vars(self).get('path', sys.path) @@ -438,9 +751,12 @@ class FastPath: children. """ + @functools.lru_cache() # type: ignore + def __new__(cls, root): + return super().__new__(cls) + def __init__(self, root): self.root = str(root) - self.base = os.path.basename(self.root).lower() def joinpath(self, child): return pathlib.Path(self.root, child) @@ -457,48 +773,90 @@ class FastPath: names = zip_path.root.namelist() self.joinpath = zip_path.joinpath - return unique_ordered( - child.split(posixpath.sep, 1)[0] - for child in names - ) - - def is_egg(self, search): - base = self.base - return ( - base == search.versionless_egg_name - or base.startswith(search.prefix) - and base.endswith('.egg')) + return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names) def search(self, name): - for child in self.children(): - n_low = child.lower() - if (n_low in name.exact_matches - or n_low.startswith(name.prefix) - and n_low.endswith(name.suffixes) - # legacy case: - or self.is_egg(name) and n_low == 'egg-info'): - yield self.joinpath(child) + return self.lookup(self.mtime).search(name) + + @property + def mtime(self): + with suppress(OSError): + return os.stat(self.root).st_mtime + self.lookup.cache_clear() + + @method_cache + def lookup(self, mtime): + return Lookup(self) + + +class Lookup: + def __init__(self, path: FastPath): + base = os.path.basename(path.root).lower() + base_is_egg = base.endswith(".egg") + self.infos = FreezableDefaultDict(list) + self.eggs = FreezableDefaultDict(list) + + for child in path.children(): + low = child.lower() + if low.endswith((".dist-info", ".egg-info")): + # rpartition is faster than splitext and suitable for this purpose. + name = low.rpartition(".")[0].partition("-")[0] + normalized = Prepared.normalize(name) + self.infos[normalized].append(path.joinpath(child)) + elif base_is_egg and low == "egg-info": + name = base.rpartition(".")[0].partition("-")[0] + legacy_normalized = Prepared.legacy_normalize(name) + self.eggs[legacy_normalized].append(path.joinpath(child)) + + self.infos.freeze() + self.eggs.freeze() + + def search(self, prepared): + infos = ( + self.infos[prepared.normalized] + if prepared + else itertools.chain.from_iterable(self.infos.values()) + ) + eggs = ( + self.eggs[prepared.legacy_normalized] + if prepared + else itertools.chain.from_iterable(self.eggs.values()) + ) + return itertools.chain(infos, eggs) class Prepared: """ A prepared search for metadata on a possibly-named package. """ - normalized = '' - prefix = '' - suffixes = '.dist-info', '.egg-info' - exact_matches = [''][:0] - versionless_egg_name = '' + + normalized = None + legacy_normalized = None def __init__(self, name): self.name = name if name is None: return - self.normalized = name.lower().replace('-', '_') - self.prefix = self.normalized + '-' - self.exact_matches = [ - self.normalized + suffix for suffix in self.suffixes] - self.versionless_egg_name = self.normalized + '.egg' + self.normalized = self.normalize(name) + self.legacy_normalized = self.legacy_normalize(name) + + @staticmethod + def normalize(name): + """ + PEP 503 normalization plus dashes as underscores. + """ + return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') + + @staticmethod + def legacy_normalize(name): + """ + Normalize the package name as found in the convention in + older packaging tools versions and specs. + """ + return name.lower().replace('-', '_') + + def __bool__(self): + return bool(self.name) @install @@ -524,30 +882,54 @@ class MetadataPathFinder(NullFinder, DistributionFinder): @classmethod def _search_paths(cls, name, paths): """Find metadata directories in paths heuristically.""" + prepared = Prepared(name) return itertools.chain.from_iterable( - path.search(Prepared(name)) - for path in map(FastPath, paths) - ) + path.search(prepared) for path in map(FastPath, paths) + ) + + def invalidate_caches(cls): + FastPath.__new__.cache_clear() class PathDistribution(Distribution): - def __init__(self, path): - """Construct a distribution from a path to the metadata directory. + def __init__(self, path: SimplePath): + """Construct a distribution. - :param path: A pathlib.Path or similar object supporting - .joinpath(), __div__, .parent, and .read_text(). + :param path: SimplePath indicating the metadata directory. """ self._path = path def read_text(self, filename): - with suppress(FileNotFoundError, IsADirectoryError, KeyError, - NotADirectoryError, PermissionError): + with suppress( + FileNotFoundError, + IsADirectoryError, + KeyError, + NotADirectoryError, + PermissionError, + ): return self._path.joinpath(filename).read_text(encoding='utf-8') + read_text.__doc__ = Distribution.read_text.__doc__ def locate_file(self, path): return self._path.parent / path + @property + def _normalized_name(self): + """ + Performance optimization: where possible, resolve the + normalized name from the file system path. + """ + stem = os.path.basename(str(self._path)) + return self._name_from_stem(stem) or super()._normalized_name + + def _name_from_stem(self, stem): + name, ext = os.path.splitext(stem) + if ext not in ('.dist-info', '.egg-info'): + return + name, sep, rest = stem.partition('-') + return name + def distribution(distribution_name): """Get the ``Distribution`` instance for the named package. @@ -566,11 +948,11 @@ def distributions(**kwargs): return Distribution.discover(**kwargs) -def metadata(distribution_name): +def metadata(distribution_name) -> _meta.PackageMetadata: """Get the metadata for the named package. :param distribution_name: The name of the distribution package to query. - :return: An email.Message containing the parsed metadata. + :return: A PackageMetadata containing the parsed metadata. """ return Distribution.from_name(distribution_name).metadata @@ -585,20 +967,29 @@ def version(distribution_name): return distribution(distribution_name).version -def entry_points(): +def entry_points(**params) -> Union[EntryPoints, SelectableGroups]: """Return EntryPoint objects for all installed packages. - :return: EntryPoint objects for all installed packages. + Pass selection parameters (group or name) to filter the + result to entry points matching those properties (see + EntryPoints.select()). + + For compatibility, returns ``SelectableGroups`` object unless + selection parameters are supplied. In the future, this function + will return ``EntryPoints`` instead of ``SelectableGroups`` + even when no selection parameters are supplied. + + For maximum future compatibility, pass selection parameters + or invoke ``.select`` with parameters on the result. + + :return: EntryPoints or SelectableGroups for all installed packages. """ + norm_name = operator.attrgetter('_normalized_name') + unique = functools.partial(unique_everseen, key=norm_name) eps = itertools.chain.from_iterable( - dist.entry_points for dist in distributions()) - by_group = operator.attrgetter('group') - ordered = sorted(eps, key=by_group) - grouped = itertools.groupby(ordered, by_group) - return { - group: tuple(eps) - for group, eps in grouped - } + dist.entry_points for dist in unique(distributions()) + ) + return SelectableGroups.load(eps).select(**params) def files(distribution_name): @@ -615,6 +1006,23 @@ def requires(distribution_name): Return a list of requirements for the named package. :return: An iterator of requirements, suitable for - packaging.requirement.Requirement. + packaging.requirement.Requirement. """ return distribution(distribution_name).requires + + +def packages_distributions() -> Mapping[str, List[str]]: + """ + Return a mapping of top-level packages to their + distributions. + + >>> import collections.abc + >>> pkgs = packages_distributions() + >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values()) + True + """ + pkg_to_dist = collections.defaultdict(list) + for dist in distributions(): + for pkg in (dist.read_text('top_level.txt') or '').split(): + pkg_to_dist[pkg].append(dist.metadata['Name']) + return dict(pkg_to_dist) diff --git a/pipenv/vendor/importlib_metadata/_adapters.py b/pipenv/vendor/importlib_metadata/_adapters.py new file mode 100644 index 00000000..aa460d3e --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_adapters.py @@ -0,0 +1,68 @@ +import re +import textwrap +import email.message + +from ._text import FoldedCase + + +class Message(email.message.Message): + multiple_use_keys = set( + map( + FoldedCase, + [ + 'Classifier', + 'Obsoletes-Dist', + 'Platform', + 'Project-URL', + 'Provides-Dist', + 'Provides-Extra', + 'Requires-Dist', + 'Requires-External', + 'Supported-Platform', + 'Dynamic', + ], + ) + ) + """ + Keys that may be indicated multiple times per PEP 566. + """ + + def __new__(cls, orig: email.message.Message): + res = super().__new__(cls) + vars(res).update(vars(orig)) + return res + + def __init__(self, *args, **kwargs): + self._headers = self._repair_headers() + + # suppress spurious error from mypy + def __iter__(self): + return super().__iter__() + + def _repair_headers(self): + def redent(value): + "Correct for RFC822 indentation" + if not value or '\n' not in value: + return value + return textwrap.dedent(' ' * 8 + value) + + headers = [(key, redent(value)) for key, value in vars(self)['_headers']] + if self._payload: + headers.append(('Description', self.get_payload())) + return headers + + @property + def json(self): + """ + Convert PackageMetadata to a JSON-compatible format + per PEP 0566. + """ + + def transform(key): + value = self.get_all(key) if key in self.multiple_use_keys else self[key] + if key == 'Keywords': + value = re.split(r'\s+', value) + tk = key.lower().replace('-', '_') + return tk, value + + return dict(map(transform, map(FoldedCase, self))) diff --git a/pipenv/vendor/importlib_metadata/_collections.py b/pipenv/vendor/importlib_metadata/_collections.py new file mode 100644 index 00000000..cf0954e1 --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_collections.py @@ -0,0 +1,30 @@ +import collections + + +# from jaraco.collections 3.3 +class FreezableDefaultDict(collections.defaultdict): + """ + Often it is desirable to prevent the mutation of + a default dict after its initial construction, such + as to prevent mutation during iteration. + + >>> dd = FreezableDefaultDict(list) + >>> dd[0].append('1') + >>> dd.freeze() + >>> dd[1] + [] + >>> len(dd) + 1 + """ + + def __missing__(self, key): + return getattr(self, '_frozen', super().__missing__)(key) + + def freeze(self): + self._frozen = lambda key: self.default_factory() + + +class Pair(collections.namedtuple('Pair', 'name value')): + @classmethod + def parse(cls, text): + return cls(*map(str.strip, text.split("=", 1))) diff --git a/pipenv/vendor/importlib_metadata/_compat.py b/pipenv/vendor/importlib_metadata/_compat.py index 303d4a22..043ece02 100644 --- a/pipenv/vendor/importlib_metadata/_compat.py +++ b/pipenv/vendor/importlib_metadata/_compat.py @@ -1,59 +1,18 @@ -from __future__ import absolute_import, unicode_literals - -import io -import abc import sys -import email -if sys.version_info > (3,): # pragma: nocover - import builtins - from configparser import ConfigParser - import contextlib - FileNotFoundError = builtins.FileNotFoundError - IsADirectoryError = builtins.IsADirectoryError - NotADirectoryError = builtins.NotADirectoryError - PermissionError = builtins.PermissionError - map = builtins.map - from itertools import filterfalse -else: # pragma: nocover - from backports.configparser import ConfigParser - from itertools import imap as map # type: ignore - from itertools import ifilterfalse as filterfalse - import contextlib2 as contextlib - FileNotFoundError = IOError, OSError - IsADirectoryError = IOError, OSError - NotADirectoryError = IOError, OSError - PermissionError = IOError, OSError +__all__ = ['install', 'NullFinder', 'PyPy_repr', 'Protocol'] -str = type('') - -suppress = contextlib.suppress - -if sys.version_info > (3, 5): # pragma: nocover - import pathlib -else: # pragma: nocover - import pathlib2 as pathlib try: - ModuleNotFoundError = builtins.FileNotFoundError -except (NameError, AttributeError): # pragma: nocover - ModuleNotFoundError = ImportError # type: ignore - - -if sys.version_info >= (3,): # pragma: nocover - from importlib.abc import MetaPathFinder -else: # pragma: nocover - class MetaPathFinder(object): - __metaclass__ = abc.ABCMeta - - -__metaclass__ = type -__all__ = [ - 'install', 'NullFinder', 'MetaPathFinder', 'ModuleNotFoundError', - 'pathlib', 'ConfigParser', 'map', 'suppress', 'FileNotFoundError', - 'NotADirectoryError', 'email_message_from_string', - ] + from typing import Protocol +except ImportError: # pragma: no cover + """ + pytest-mypy complains here because: + error: Incompatible import of "Protocol" (imported name has type + "typing_extensions._SpecialForm", local name has type "typing._SpecialForm") + """ + from typing_extensions import Protocol # type: ignore def install(cls): @@ -77,11 +36,12 @@ def disable_stdlib_finder(): See #91 for more background for rationale on this sketchy behavior. """ + def matches(finder): - return ( - getattr(finder, '__module__', None) == '_frozen_importlib_external' - and hasattr(finder, 'find_distributions') - ) + return getattr( + finder, '__module__', None + ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions') + for finder in filter(matches, sys.meta_path): # pragma: nocover del finder.find_distributions @@ -91,6 +51,7 @@ class NullFinder: A "Finder" (aka "MetaClassFinder") that never finds any modules, but may find distributions. """ + @staticmethod def find_spec(*args, **kwargs): return None @@ -104,49 +65,22 @@ class NullFinder: find_module = find_spec -def py2_message_from_string(text): # nocoverpy3 - # Work around https://bugs.python.org/issue25545 where - # email.message_from_string cannot handle Unicode on Python 2. - io_buffer = io.StringIO(text) - return email.message_from_file(io_buffer) - - -email_message_from_string = ( - py2_message_from_string - if sys.version_info < (3,) else - email.message_from_string - ) - - class PyPy_repr: """ Override repr for EntryPoint objects on PyPy to avoid __iter__ access. Ref #97, #102. """ + affected = hasattr(sys, 'pypy_version_info') def __compat_repr__(self): # pragma: nocover def make_param(name): value = getattr(self, name) - return '{name}={value!r}'.format(**locals()) + return f'{name}={value!r}' + params = ', '.join(map(make_param, self._fields)) - return 'EntryPoint({params})'.format(**locals()) + return f'EntryPoint({params})' if affected: # pragma: nocover __repr__ = __compat_repr__ del affected - - -# from itertools recipes -def unique_everseen(iterable): # pragma: nocover - "List unique elements, preserving order. Remember all elements ever seen." - seen = set() - seen_add = seen.add - - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - - -unique_ordered = ( - unique_everseen if sys.version_info < (3, 7) else dict.fromkeys) diff --git a/pipenv/vendor/importlib_metadata/_functools.py b/pipenv/vendor/importlib_metadata/_functools.py new file mode 100644 index 00000000..73f50d00 --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_functools.py @@ -0,0 +1,85 @@ +import types +import functools + + +# from jaraco.functools 3.3 +def method_cache(method, cache_wrapper=None): + """ + Wrap lru_cache to support storing the cache data in the object instances. + + Abstracts the common paradigm where the method explicitly saves an + underscore-prefixed protected property on first call and returns that + subsequently. + + >>> class MyClass: + ... calls = 0 + ... + ... @method_cache + ... def method(self, value): + ... self.calls += 1 + ... return value + + >>> a = MyClass() + >>> a.method(3) + 3 + >>> for x in range(75): + ... res = a.method(x) + >>> a.calls + 75 + + Note that the apparent behavior will be exactly like that of lru_cache + except that the cache is stored on each instance, so values in one + instance will not flush values from another, and when an instance is + deleted, so are the cached values for that instance. + + >>> b = MyClass() + >>> for x in range(35): + ... res = b.method(x) + >>> b.calls + 35 + >>> a.method(0) + 0 + >>> a.calls + 75 + + Note that if method had been decorated with ``functools.lru_cache()``, + a.calls would have been 76 (due to the cached value of 0 having been + flushed by the 'b' instance). + + Clear the cache with ``.cache_clear()`` + + >>> a.method.cache_clear() + + Same for a method that hasn't yet been called. + + >>> c = MyClass() + >>> c.method.cache_clear() + + Another cache wrapper may be supplied: + + >>> cache = functools.lru_cache(maxsize=2) + >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) + >>> a = MyClass() + >>> a.method2() + 3 + + Caution - do not subsequently wrap the method with another decorator, such + as ``@property``, which changes the semantics of the function. + + See also + http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ + for another implementation and additional justification. + """ + cache_wrapper = cache_wrapper or functools.lru_cache() + + def wrapper(self, *args, **kwargs): + # it's the first call, replace the method with a cached, bound method + bound_method = types.MethodType(method, self) + cached_method = cache_wrapper(bound_method) + setattr(self, method.__name__, cached_method) + return cached_method(*args, **kwargs) + + # Support cache clear even before cache has been created. + wrapper.cache_clear = lambda: None + + return wrapper diff --git a/pipenv/vendor/importlib_metadata/_itertools.py b/pipenv/vendor/importlib_metadata/_itertools.py new file mode 100644 index 00000000..dd45f2f0 --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_itertools.py @@ -0,0 +1,19 @@ +from itertools import filterfalse + + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/pipenv/vendor/importlib_metadata/_meta.py b/pipenv/vendor/importlib_metadata/_meta.py new file mode 100644 index 00000000..dd68c429 --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_meta.py @@ -0,0 +1,48 @@ +from ._compat import Protocol +from typing import Any, Dict, Iterator, List, TypeVar, Union + + +_T = TypeVar("_T") + + +class PackageMetadata(Protocol): + def __len__(self) -> int: + ... # pragma: no cover + + def __contains__(self, item: str) -> bool: + ... # pragma: no cover + + def __getitem__(self, key: str) -> str: + ... # pragma: no cover + + def __iter__(self) -> Iterator[str]: + ... # pragma: no cover + + def get_all(self, name: str, failobj: _T = ...) -> Union[List[Any], _T]: + """ + Return all values associated with a possibly multi-valued key. + """ + + @property + def json(self) -> Dict[str, Union[str, List[str]]]: + """ + A JSON-compatible form of the metadata. + """ + + +class SimplePath(Protocol): + """ + A minimal subset of pathlib.Path required by PathDistribution. + """ + + def joinpath(self) -> 'SimplePath': + ... # pragma: no cover + + def __div__(self) -> 'SimplePath': + ... # pragma: no cover + + def parent(self) -> 'SimplePath': + ... # pragma: no cover + + def read_text(self) -> str: + ... # pragma: no cover diff --git a/pipenv/vendor/importlib_metadata/_text.py b/pipenv/vendor/importlib_metadata/_text.py new file mode 100644 index 00000000..766979d9 --- /dev/null +++ b/pipenv/vendor/importlib_metadata/_text.py @@ -0,0 +1,99 @@ +import re + +from ._functools import method_cache + + +# from jaraco.text 3.5 +class FoldedCase(str): + """ + A case insensitive string class; behaves just like str + except compares equal when the only variation is case. + + >>> s = FoldedCase('hello world') + + >>> s == 'Hello World' + True + + >>> 'Hello World' == s + True + + >>> s != 'Hello World' + False + + >>> s.index('O') + 4 + + >>> s.split('O') + ['hell', ' w', 'rld'] + + >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) + ['alpha', 'Beta', 'GAMMA'] + + Sequence membership is straightforward. + + >>> "Hello World" in [s] + True + >>> s in ["Hello World"] + True + + You may test for set inclusion, but candidate and elements + must both be folded. + + >>> FoldedCase("Hello World") in {s} + True + >>> s in {FoldedCase("Hello World")} + True + + String inclusion works as long as the FoldedCase object + is on the right. + + >>> "hello" in FoldedCase("Hello World") + True + + But not if the FoldedCase object is on the left: + + >>> FoldedCase('hello') in 'Hello World' + False + + In that case, use in_: + + >>> FoldedCase('hello').in_('Hello World') + True + + >>> FoldedCase('hello') > FoldedCase('Hello') + False + """ + + def __lt__(self, other): + return self.lower() < other.lower() + + def __gt__(self, other): + return self.lower() > other.lower() + + def __eq__(self, other): + return self.lower() == other.lower() + + def __ne__(self, other): + return self.lower() != other.lower() + + def __hash__(self): + return hash(self.lower()) + + def __contains__(self, other): + return super(FoldedCase, self).lower().__contains__(other.lower()) + + def in_(self, other): + "Does self appear in other?" + return self in FoldedCase(other) + + # cache lower since it's likely to be called frequently. + @method_cache + def lower(self): + return super(FoldedCase, self).lower() + + def index(self, sub): + return self.lower().index(sub.lower()) + + def split(self, splitter=' ', maxsplit=0): + pattern = re.compile(re.escape(splitter), re.I) + return pattern.split(self, maxsplit) diff --git a/pipenv/vendor/importlib_metadata/docs/changelog.rst b/pipenv/vendor/importlib_metadata/docs/changelog.rst deleted file mode 100644 index b7e93b5d..00000000 --- a/pipenv/vendor/importlib_metadata/docs/changelog.rst +++ /dev/null @@ -1,307 +0,0 @@ -========================= - importlib_metadata NEWS -========================= - -v2.0.0 -====== - -* ``importlib_metadata`` no longer presents a - ``__version__`` attribute. Consumers wishing to - resolve the version of the package should query it - directly with - ``importlib_metadata.version('importlib-metadata')``. - Closes #71. - -v1.7.0 -====== - -* ``PathNotFoundError`` now has a custom ``__str__`` - mentioning "package metadata" being missing to help - guide users to the cause when the package is installed - but no metadata is present. Closes #124. - -v1.6.1 -====== - -* Added ``Distribution._local()`` as a provisional - demonstration of how to load metadata for a local - package. Implicitly requires that - `pep517 `_ is - installed. Ref #42. -* Ensure inputs to FastPath are Unicode. Closes #121. -* Tests now rely on ``importlib.resources.files`` (and - backport) instead of the older ``path`` function. -* Support any iterable from ``find_distributions``. - Closes #122. - -v1.6.0 -====== - -* Added ``module`` and ``attr`` attributes to ``EntryPoint`` - -v1.5.2 -====== - -* Fix redundant entries from ``FastPath.zip_children``. - Closes #117. - -v1.5.1 -====== - -* Improve reliability and consistency of compatibility - imports for contextlib and pathlib when running tests. - Closes #116. - -v1.5.0 -====== - -* Additional performance optimizations in FastPath now - saves an additional 20% on a typical call. -* Correct for issue where PyOxidizer finder has no - ``__module__`` attribute. Closes #110. - -v1.4.0 -====== - -* Through careful optimization, ``distribution()`` is - 3-4x faster. Thanks to Antony Lee for the - contribution. Closes #95. - -* When searching through ``sys.path``, if any error - occurs attempting to list a path entry, that entry - is skipped, making the system much more lenient - to errors. Closes #94. - -v1.3.0 -====== - -* Improve custom finders documentation. Closes #105. - -v1.2.0 -====== - -* Once again, drop support for Python 3.4. Ref #104. - -v1.1.3 -====== - -* Restored support for Python 3.4 due to improper version - compatibility declarations in the v1.1.0 and v1.1.1 - releases. Closes #104. - -v1.1.2 -====== - -* Repaired project metadata to correctly declare the - ``python_requires`` directive. Closes #103. - -v1.1.1 -====== - -* Fixed ``repr(EntryPoint)`` on PyPy 3 also. Closes #102. - -v1.1.0 -====== - -* Dropped support for Python 3.4. -* EntryPoints are now pickleable. Closes #96. -* Fixed ``repr(EntryPoint)`` on PyPy 2. Closes #97. - -v1.0.0 -====== - -* Project adopts semver for versioning. - -* Removed compatibility shim introduced in 0.23. - -* For better compatibility with the stdlib implementation and to - avoid the same distributions being discovered by the stdlib and - backport implementations, the backport now disables the - stdlib DistributionFinder during initialization (import time). - Closes #91 and closes #100. - -0.23 -==== -* Added a compatibility shim to prevent failures on beta releases - of Python before the signature changed to accept the - "context" parameter on find_distributions. This workaround - will have a limited lifespan, not to extend beyond release of - Python 3.8 final. - -0.22 -==== -* Renamed ``package`` parameter to ``distribution_name`` - as `recommended `_ - in the following functions: ``distribution``, ``metadata``, - ``version``, ``files``, and ``requires``. This - backward-incompatible change is expected to have little impact - as these functions are assumed to be primarily used with - positional parameters. - -0.21 -==== -* ``importlib.metadata`` now exposes the ``DistributionFinder`` - metaclass and references it in the docs for extending the - search algorithm. -* Add ``Distribution.at`` for constructing a Distribution object - from a known metadata directory on the file system. Closes #80. -* Distribution finders now receive a context object that - supplies ``.path`` and ``.name`` properties. This change - introduces a fundamental backward incompatibility for - any projects implementing a ``find_distributions`` method - on a ``MetaPathFinder``. This new layer of abstraction - allows this context to be supplied directly or constructed - on demand and opens the opportunity for a - ``find_distributions`` method to solicit additional - context from the caller. Closes #85. - -0.20 -==== -* Clarify in the docs that calls to ``.files`` could return - ``None`` when the metadata is not present. Closes #69. -* Return all requirements and not just the first for dist-info - packages. Closes #67. - -0.19 -==== -* Restrain over-eager egg metadata resolution. -* Add support for entry points with colons in the name. Closes #75. - -0.18 -==== -* Parse entry points case sensitively. Closes #68 -* Add a version constraint on the backport configparser package. Closes #66 - -0.17 -==== -* Fix a permission problem in the tests on Windows. - -0.16 -==== -* Don't crash if there exists an EGG-INFO directory on sys.path. - -0.15 -==== -* Fix documentation. - -0.14 -==== -* Removed ``local_distribution`` function from the API. - **This backward-incompatible change removes this - behavior summarily**. Projects should remove their - reliance on this behavior. A replacement behavior is - under review in the `pep517 project - `_. Closes #42. - -0.13 -==== -* Update docstrings to match PEP 8. Closes #63. -* Merged modules into one module. Closes #62. - -0.12 -==== -* Add support for eggs. !65; Closes #19. - -0.11 -==== -* Support generic zip files (not just wheels). Closes #59 -* Support zip files with multiple distributions in them. Closes #60 -* Fully expose the public API in ``importlib_metadata.__all__``. - -0.10 -==== -* The ``Distribution`` ABC is now officially part of the public API. - Closes #37. -* Fixed support for older single file egg-info formats. Closes #43. -* Fixed a testing bug when ``$CWD`` has spaces in the path. Closes #50. -* Add Python 3.8 to the ``tox`` testing matrix. - -0.9 -=== -* Fixed issue where entry points without an attribute would raise an - Exception. Closes #40. -* Removed unused ``name`` parameter from ``entry_points()``. Closes #44. -* ``DistributionFinder`` classes must now be instantiated before - being placed on ``sys.meta_path``. - -0.8 -=== -* This library can now discover/enumerate all installed packages. **This - backward-incompatible change alters the protocol finders must - implement to support distribution package discovery.** Closes #24. -* The signature of ``find_distributions()`` on custom installer finders - should now accept two parameters, ``name`` and ``path`` and - these parameters must supply defaults. -* The ``entry_points()`` method no longer accepts a package name - but instead returns all entry points in a dictionary keyed by the - ``EntryPoint.group``. The ``resolve`` method has been removed. Instead, - call ``EntryPoint.load()``, which has the same semantics as - ``pkg_resources`` and ``entrypoints``. **This is a backward incompatible - change.** -* Metadata is now always returned as Unicode text regardless of - Python version. Closes #29. -* This library can now discover metadata for a 'local' package (found - in the current-working directory). Closes #27. -* Added ``files()`` function for resolving files from a distribution. -* Added a new ``requires()`` function, which returns the requirements - for a package suitable for parsing by - ``packaging.requirements.Requirement``. Closes #18. -* The top-level ``read_text()`` function has been removed. Use - ``PackagePath.read_text()`` on instances returned by the ``files()`` - function. **This is a backward incompatible change.** -* Release dates are now automatically injected into the changelog - based on SCM tags. - -0.7 -=== -* Fixed issue where packages with dashes in their names would - not be discovered. Closes #21. -* Distribution lookup is now case-insensitive. Closes #20. -* Wheel distributions can no longer be discovered by their module - name. Like Path distributions, they must be indicated by their - distribution package name. - -0.6 -=== -* Removed ``importlib_metadata.distribution`` function. Now - the public interface is primarily the utility functions exposed - in ``importlib_metadata.__all__``. Closes #14. -* Added two new utility functions ``read_text`` and - ``metadata``. - -0.5 -=== -* Updated README and removed details about Distribution - class, now considered private. Closes #15. -* Added test suite support for Python 3.4+. -* Fixed SyntaxErrors on Python 3.4 and 3.5. !12 -* Fixed errors on Windows joining Path elements. !15 - -0.4 -=== -* Housekeeping. - -0.3 -=== -* Added usage documentation. Closes #8 -* Add support for getting metadata from wheels on ``sys.path``. Closes #9 - -0.2 -=== -* Added ``importlib_metadata.entry_points()``. Closes #1 -* Added ``importlib_metadata.resolve()``. Closes #12 -* Add support for Python 2.7. Closes #4 - -0.1 -=== -* Initial release. - - -.. - Local Variables: - mode: change-log-mode - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 78 - coding: utf-8 - End: diff --git a/pipenv/vendor/importlib_metadata/docs/conf.py b/pipenv/vendor/importlib_metadata/docs/conf.py deleted file mode 100644 index 129a7a4e..00000000 --- a/pipenv/vendor/importlib_metadata/docs/conf.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# importlib_metadata documentation build configuration file, created by -# sphinx-quickstart on Thu Nov 30 10:21:00 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'rst.linker', - 'sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', - ] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = 'importlib_metadata' -copyright = '2017-2019, Jason R. Coombs, Barry Warsaw' -author = 'Jason R. Coombs, Barry Warsaw' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '0.1' -# The full version, including alpha/beta/rc tags. -release = '0.1' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = False - - -# -- 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 = 'default' - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - ] - } - - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = 'importlib_metadatadoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', - } - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'importlib_metadata.tex', - 'importlib\\_metadata Documentation', - 'Brett Cannon, Barry Warsaw', 'manual'), - ] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'importlib_metadata', 'importlib_metadata Documentation', - [author], 1) - ] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'importlib_metadata', 'importlib_metadata Documentation', - author, 'importlib_metadata', 'One line description of project.', - 'Miscellaneous'), - ] - - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), - 'importlib_resources': ( - 'https://importlib-resources.readthedocs.io/en/latest/', None - ), - } - - -# For rst.linker, inject release dates into changelog.rst -link_files = { - 'changelog.rst': dict( - replace=[ - dict( - pattern=r'^(?m)((?Pv?\d+(\.\d+){1,2}))\n[-=]+\n', - with_scm='{text}\n{rev[timestamp]:%Y-%m-%d}\n\n', - ), - ], - ), - } diff --git a/pipenv/vendor/importlib_metadata/docs/index.rst b/pipenv/vendor/importlib_metadata/docs/index.rst deleted file mode 100644 index 530197cf..00000000 --- a/pipenv/vendor/importlib_metadata/docs/index.rst +++ /dev/null @@ -1,50 +0,0 @@ -=============================== - Welcome to importlib_metadata -=============================== - -``importlib_metadata`` is a library which provides an API for accessing an -installed package's metadata (see :pep:`566`), such as its entry points or its top-level -name. This functionality intends to replace most uses of ``pkg_resources`` -`entry point API`_ and `metadata API`_. Along with :mod:`importlib.resources` in -Python 3.7 and newer (backported as :doc:`importlib_resources ` for older -versions of Python), this can eliminate the need to use the older and less -efficient ``pkg_resources`` package. - -``importlib_metadata`` is a backport of Python 3.8's standard library -:doc:`importlib.metadata ` module for Python 2.7, and 3.4 through 3.7. Users of -Python 3.8 and beyond are encouraged to use the standard library module. -When imported on Python 3.8 and later, ``importlib_metadata`` replaces the -DistributionFinder behavior from the stdlib, but leaves the API in tact. -Developers looking for detailed API descriptions should refer to the Python -3.8 standard library documentation. - -The documentation here includes a general :ref:`usage ` guide. - - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - using.rst - changelog (links).rst - - -Project details -=============== - - * Project home: https://gitlab.com/python-devs/importlib_metadata - * Report bugs at: https://gitlab.com/python-devs/importlib_metadata/issues - * Code hosting: https://gitlab.com/python-devs/importlib_metadata.git - * Documentation: http://importlib_metadata.readthedocs.io/ - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - - -.. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points -.. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api diff --git a/pipenv/vendor/importlib_metadata/docs/using.rst b/pipenv/vendor/importlib_metadata/docs/using.rst deleted file mode 100644 index 11965147..00000000 --- a/pipenv/vendor/importlib_metadata/docs/using.rst +++ /dev/null @@ -1,260 +0,0 @@ -.. _using: - -================================= - Using :mod:`!importlib_metadata` -================================= - -``importlib_metadata`` is a library that provides for access to installed -package metadata. Built in part on Python's import system, this library -intends to replace similar functionality in the `entry point -API`_ and `metadata API`_ of ``pkg_resources``. Along with -:mod:`importlib.resources` in Python 3.7 -and newer (backported as :doc:`importlib_resources ` for older versions of -Python), this can eliminate the need to use the older and less efficient -``pkg_resources`` package. - -By "installed package" we generally mean a third-party package installed into -Python's ``site-packages`` directory via tools such as `pip -`_. Specifically, -it means a package with either a discoverable ``dist-info`` or ``egg-info`` -directory, and metadata defined by :pep:`566` or its older specifications. -By default, package metadata can live on the file system or in zip archives on -:data:`sys.path`. Through an extension mechanism, the metadata can live almost -anywhere. - - -Overview -======== - -Let's say you wanted to get the version string for a package you've installed -using ``pip``. We start by creating a virtual environment and installing -something into it:: - - $ python3 -m venv example - $ source example/bin/activate - (example) $ pip install importlib_metadata - (example) $ pip install wheel - -You can get the version string for ``wheel`` by running the following:: - - (example) $ python - >>> from importlib_metadata import version - >>> version('wheel') - '0.32.3' - -You can also get the set of entry points keyed by group, such as -``console_scripts``, ``distutils.commands`` and others. Each group contains a -sequence of :ref:`EntryPoint ` objects. - -You can get the :ref:`metadata for a distribution `:: - - >>> list(metadata('wheel')) - ['Metadata-Version', 'Name', 'Version', 'Summary', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License', 'Project-URL', 'Project-URL', 'Project-URL', 'Keywords', 'Platform', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Classifier', 'Requires-Python', 'Provides-Extra', 'Requires-Dist', 'Requires-Dist'] - -You can also get a :ref:`distribution's version number `, list its -:ref:`constituent files `, and get a list of the distribution's -:ref:`requirements`. - - -Functional API -============== - -This package provides the following functionality via its public API. - - -.. _entry-points: - -Entry points ------------- - -The ``entry_points()`` function returns a dictionary of all entry points, -keyed by group. Entry points are represented by ``EntryPoint`` instances; -each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and -a ``.load()`` method to resolve the value. There are also ``.module``, -``.attr``, and ``.extras`` attributes for getting the components of the -``.value`` attribute:: - - >>> eps = entry_points() - >>> list(eps) - ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation'] - >>> scripts = eps['console_scripts'] - >>> wheel = [ep for ep in scripts if ep.name == 'wheel'][0] - >>> wheel - EntryPoint(name='wheel', value='wheel.cli:main', group='console_scripts') - >>> wheel.module - 'wheel.cli' - >>> wheel.attr - 'main' - >>> wheel.extras - [] - >>> main = wheel.load() - >>> main - - -The ``group`` and ``name`` are arbitrary values defined by the package author -and usually a client will wish to resolve all entry points for a particular -group. Read `the setuptools docs -`_ -for more information on entry points, their definition, and usage. - - -.. _metadata: - -Distribution metadata ---------------------- - -Every distribution includes some metadata, which you can extract using the -``metadata()`` function:: - - >>> wheel_metadata = metadata('wheel') - -The keys of the returned data structure [#f1]_ name the metadata keywords, and -their values are returned unparsed from the distribution metadata:: - - >>> wheel_metadata['Requires-Python'] - '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' - - -.. _version: - -Distribution versions ---------------------- - -The ``version()`` function is the quickest way to get a distribution's version -number, as a string:: - - >>> version('wheel') - '0.32.3' - - -.. _files: - -Distribution files ------------------- - -You can also get the full set of files contained within a distribution. The -``files()`` function takes a distribution package name and returns all of the -files installed by this distribution. Each file object returned is a -``PackagePath``, a :class:`pathlib.Path` derived object with additional ``dist``, -``size``, and ``hash`` properties as indicated by the metadata. For example:: - - >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] - >>> util - PackagePath('wheel/util.py') - >>> util.size - 859 - >>> util.dist - - >>> util.hash - - -Once you have the file, you can also read its contents:: - - >>> print(util.read_text()) - import base64 - import sys - ... - def as_bytes(s): - if isinstance(s, text_type): - return s.encode('utf-8') - return s - -In the case where the metadata file listing files -(RECORD or SOURCES.txt) is missing, ``files()`` will -return ``None``. The caller may wish to wrap calls to -``files()`` in `always_iterable -`_ -or otherwise guard against this condition if the target -distribution is not known to have the metadata present. - -.. _requirements: - -Distribution requirements -------------------------- - -To get the full set of requirements for a distribution, use the ``requires()`` -function:: - - >>> requires('wheel') - ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"] - - -Distributions -============= - -While the above API is the most common and convenient usage, you can get all -of that information from the ``Distribution`` class. A ``Distribution`` is an -abstract object that represents the metadata for a Python package. You can -get the ``Distribution`` instance:: - - >>> from importlib_metadata import distribution - >>> dist = distribution('wheel') - -Thus, an alternative way to get the version number is through the -``Distribution`` instance:: - - >>> dist.version - '0.32.3' - -There are all kinds of additional metadata available on the ``Distribution`` -instance:: - - >>> d.metadata['Requires-Python'] - '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' - >>> d.metadata['License'] - 'MIT' - -The full set of available metadata is not described here. See :pep:`566` -for additional details. - - -Extending the search algorithm -============================== - -Because package metadata is not available through :data:`sys.path` searches, or -package loaders directly, the metadata for a package is found through import -system `finders`_. To find a distribution package's metadata, -``importlib.metadata`` queries the list of :term:`meta path finders ` on -:data:`sys.meta_path`. - -By default ``importlib_metadata`` installs a finder for distribution packages -found on the file system. This finder doesn't actually find any *packages*, -but it can find the packages' metadata. - -The abstract class :py:class:`importlib.abc.MetaPathFinder` defines the -interface expected of finders by Python's import system. -``importlib_metadata`` extends this protocol by looking for an optional -``find_distributions`` callable on the finders from -:data:`sys.meta_path` and presents this extended interface as the -``DistributionFinder`` abstract base class, which defines this abstract -method:: - - @abc.abstractmethod - def find_distributions(context=DistributionFinder.Context()): - """Return an iterable of all Distribution instances capable of - loading the metadata for packages for the indicated ``context``. - """ - -The ``DistributionFinder.Context`` object provides ``.path`` and ``.name`` -properties indicating the path to search and name to match and may -supply other relevant context. - -What this means in practice is that to support finding distribution package -metadata in locations other than the file system, subclass -``Distribution`` and implement the abstract methods. Then from -a custom finder, return instances of this derived ``Distribution`` in the -``find_distributions()`` method. - - -.. _`entry point API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#entry-points -.. _`metadata API`: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#metadata-api -.. _`finders`: https://docs.python.org/3/reference/import.html#finders-and-loaders - - -.. rubric:: Footnotes - -.. [#f1] Technically, the returned distribution metadata object is an - :class:`email.message.EmailMessage` - instance, but this is an implementation detail, and not part of the - stable API. You should only use dictionary-like methods and syntax - to access the metadata contents. diff --git a/pipenv/vendor/resolvelib/compat/__init__.py b/pipenv/vendor/importlib_metadata/py.typed similarity index 100% rename from pipenv/vendor/resolvelib/compat/__init__.py rename to pipenv/vendor/importlib_metadata/py.typed diff --git a/pipenv/vendor/importlib_metadata/tests/data/example-21.12-py3-none-any.whl b/pipenv/vendor/importlib_metadata/tests/data/example-21.12-py3-none-any.whl deleted file mode 100644 index 641ab07f7aadd5c3ffe199b1e397b84504444994..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1455 zcmWIWW@Zs#U|`^2sH#5hC#89?LJ`OVVPPOntw_u*$Vt_YkI&4@EQycTE2#AL^bJ1Y zd*;mL3tJuqF*Gf@GU?JH8`iH^x{lmwniEp0#}EKFaSqT#mVX%$)j*SW1F-_aL|r38 zJwqeCl+5B1-ORkSe0^Wn5Jwls5Xac=ja-KeL|ngr7ya2Na>+2-+_Beb<+qte)Tv+?!=mXP3IU>yCSok_B-aII-Kw3 zQMDMLgF#ppkHf<~TwQ&*&wKcuy~yjWt99!gle zr#}12zzYT!jLohYUwp!K>b(BNuR7OwHFUksp7hxiq@k(h`;^PmXM2#w3X^MRPoMX` z>U(DOlSfQw;W@=u^`JJ;IgUWAfyY^?c_l@a@df#rc_qbqB^4#ze&^0>pF8i_tM8|G zN=HMp?`hFmk2AU_JVQ5xdbDm>QzUHsc}LJj?qWtX3-6|I25|u`;s9b*JQkMZ7sThJ zmZj!^Z1aYg{S@8xHoufE=rJ-dTm)h{Jcb3iI{OE?l%CmH)a1axaN%A)u3Q2l zE(Z%%TzIplh-=e{bsROdT|LH`74jc0G1}d-ie(BgQ)O((bmtPEAigxe^3+zD^2ZPA z=Kj_@llnHb%pqs>={~b{JFAWU-FsQLpa0z(9XLnn{J!+d2H)mi39tFM zWw~J?v;DQj2W5<}*`3O4x;giZz4dIBjE_o=poHl8P!xz%}R z^2PdUhwx4OykW7N0@LpsPXda2KAh-#t~vYAon3*GEN%;5X|j5I`Pcv4f`xLoSdG>m z=t|fwwtn6&&3ktpt-?;-J{BOG-L!7y`!yP=+rIT|ef?5o>krldZ$>5&X54uh7~Ej6 zq!C16$=S#TV9UA??FDpj9zYni2#-I~9cJVf#soY@LK1&~H!B-RJsS|72YTxiGl&NO07LVy diff --git a/pipenv/vendor/importlib_metadata/tests/fixtures.py b/pipenv/vendor/importlib_metadata/tests/fixtures.py deleted file mode 100644 index 20982fa1..00000000 --- a/pipenv/vendor/importlib_metadata/tests/fixtures.py +++ /dev/null @@ -1,232 +0,0 @@ -from __future__ import unicode_literals - -import os -import sys -import shutil -import tempfile -import textwrap -import test.support - -from .._compat import pathlib, contextlib - - -__metaclass__ = type - - -@contextlib.contextmanager -def tempdir(): - tmpdir = tempfile.mkdtemp() - try: - yield pathlib.Path(tmpdir) - finally: - shutil.rmtree(tmpdir) - - -@contextlib.contextmanager -def save_cwd(): - orig = os.getcwd() - try: - yield - finally: - os.chdir(orig) - - -@contextlib.contextmanager -def tempdir_as_cwd(): - with tempdir() as tmp: - with save_cwd(): - os.chdir(str(tmp)) - yield tmp - - -@contextlib.contextmanager -def install_finder(finder): - sys.meta_path.append(finder) - try: - yield - finally: - sys.meta_path.remove(finder) - - -class Fixtures: - def setUp(self): - self.fixtures = contextlib.ExitStack() - self.addCleanup(self.fixtures.close) - - -class SiteDir(Fixtures): - def setUp(self): - super(SiteDir, self).setUp() - self.site_dir = self.fixtures.enter_context(tempdir()) - - -class OnSysPath(Fixtures): - @staticmethod - @contextlib.contextmanager - def add_sys_path(dir): - sys.path[:0] = [str(dir)] - try: - yield - finally: - sys.path.remove(str(dir)) - - def setUp(self): - super(OnSysPath, self).setUp() - self.fixtures.enter_context(self.add_sys_path(self.site_dir)) - - -class DistInfoPkg(OnSysPath, SiteDir): - files = { - "distinfo_pkg-1.0.0.dist-info": { - "METADATA": """ - Name: distinfo-pkg - Author: Steven Ma - Version: 1.0.0 - Requires-Dist: wheel >= 1.0 - Requires-Dist: pytest; extra == 'test' - """, - "RECORD": "mod.py,sha256=abc,20\n", - "entry_points.txt": """ - [entries] - main = mod:main - ns:sub = mod:main - """ - }, - "mod.py": """ - def main(): - print("hello world") - """, - } - - def setUp(self): - super(DistInfoPkg, self).setUp() - build_files(DistInfoPkg.files, self.site_dir) - - -class DistInfoPkgOffPath(SiteDir): - def setUp(self): - super(DistInfoPkgOffPath, self).setUp() - build_files(DistInfoPkg.files, self.site_dir) - - -class EggInfoPkg(OnSysPath, SiteDir): - files = { - "egginfo_pkg.egg-info": { - "PKG-INFO": """ - Name: egginfo-pkg - Author: Steven Ma - License: Unknown - Version: 1.0.0 - Classifier: Intended Audience :: Developers - Classifier: Topic :: Software Development :: Libraries - """, - "SOURCES.txt": """ - mod.py - egginfo_pkg.egg-info/top_level.txt - """, - "entry_points.txt": """ - [entries] - main = mod:main - """, - "requires.txt": """ - wheel >= 1.0; python_version >= "2.7" - [test] - pytest - """, - "top_level.txt": "mod\n" - }, - "mod.py": """ - def main(): - print("hello world") - """, - } - - def setUp(self): - super(EggInfoPkg, self).setUp() - build_files(EggInfoPkg.files, prefix=self.site_dir) - - -class EggInfoFile(OnSysPath, SiteDir): - files = { - "egginfo_file.egg-info": """ - Metadata-Version: 1.0 - Name: egginfo_file - Version: 0.1 - Summary: An example package - Home-page: www.example.com - Author: Eric Haffa-Vee - Author-email: eric@example.coms - License: UNKNOWN - Description: UNKNOWN - Platform: UNKNOWN - """, - } - - def setUp(self): - super(EggInfoFile, self).setUp() - build_files(EggInfoFile.files, prefix=self.site_dir) - - -class LocalPackage: - files = { - "setup.py": """ - import setuptools - setuptools.setup(name="local-pkg", version="2.0.1") - """, - } - - def setUp(self): - self.fixtures = contextlib.ExitStack() - self.addCleanup(self.fixtures.close) - self.fixtures.enter_context(tempdir_as_cwd()) - build_files(self.files) - - -def build_files(file_defs, prefix=pathlib.Path()): - """Build a set of files/directories, as described by the - - file_defs dictionary. Each key/value pair in the dictionary is - interpreted as a filename/contents pair. If the contents value is a - dictionary, a directory is created, and the dictionary interpreted - as the files within it, recursively. - - For example: - - {"README.txt": "A README file", - "foo": { - "__init__.py": "", - "bar": { - "__init__.py": "", - }, - "baz.py": "# Some code", - } - } - """ - for name, contents in file_defs.items(): - full_name = prefix / name - if isinstance(contents, dict): - full_name.mkdir() - build_files(contents, prefix=full_name) - else: - if isinstance(contents, bytes): - with full_name.open('wb') as f: - f.write(contents) - else: - with full_name.open('w') as f: - f.write(DALS(contents)) - - -class FileBuilder: - def unicode_filename(self): - return test.support.FS_NONASCII or \ - self.skip("File system does not support non-ascii.") - - -def DALS(str): - "Dedent and left-strip" - return textwrap.dedent(str).lstrip() - - -class NullFinder: - def find_module(self, name): - pass diff --git a/pipenv/vendor/importlib_metadata/tests/test_api.py b/pipenv/vendor/importlib_metadata/tests/test_api.py deleted file mode 100644 index eb0ff53b..00000000 --- a/pipenv/vendor/importlib_metadata/tests/test_api.py +++ /dev/null @@ -1,177 +0,0 @@ -import re -import textwrap -import unittest - -from . import fixtures -from .. import ( - Distribution, PackageNotFoundError, distribution, - entry_points, files, metadata, requires, version, - ) - -try: - from collections.abc import Iterator -except ImportError: - from collections import Iterator # noqa: F401 - -try: - from builtins import str as text -except ImportError: - from __builtin__ import unicode as text - - -class APITests( - fixtures.EggInfoPkg, - fixtures.DistInfoPkg, - fixtures.EggInfoFile, - unittest.TestCase): - - version_pattern = r'\d+\.\d+(\.\d)?' - - def test_retrieves_version_of_self(self): - pkg_version = version('egginfo-pkg') - assert isinstance(pkg_version, text) - assert re.match(self.version_pattern, pkg_version) - - def test_retrieves_version_of_distinfo_pkg(self): - pkg_version = version('distinfo-pkg') - assert isinstance(pkg_version, text) - assert re.match(self.version_pattern, pkg_version) - - def test_for_name_does_not_exist(self): - with self.assertRaises(PackageNotFoundError): - distribution('does-not-exist') - - def test_for_top_level(self): - self.assertEqual( - distribution('egginfo-pkg').read_text('top_level.txt').strip(), - 'mod') - - def test_read_text(self): - top_level = [ - path for path in files('egginfo-pkg') - if path.name == 'top_level.txt' - ][0] - self.assertEqual(top_level.read_text(), 'mod\n') - - def test_entry_points(self): - entries = dict(entry_points()['entries']) - ep = entries['main'] - self.assertEqual(ep.value, 'mod:main') - self.assertEqual(ep.extras, []) - - def test_metadata_for_this_package(self): - md = metadata('egginfo-pkg') - assert md['author'] == 'Steven Ma' - assert md['LICENSE'] == 'Unknown' - assert md['Name'] == 'egginfo-pkg' - classifiers = md.get_all('Classifier') - assert 'Topic :: Software Development :: Libraries' in classifiers - - def test_importlib_metadata_version(self): - resolved = version('importlib-metadata') - assert re.match(self.version_pattern, resolved) - - @staticmethod - def _test_files(files): - root = files[0].root - for file in files: - assert file.root == root - assert not file.hash or file.hash.value - assert not file.hash or file.hash.mode == 'sha256' - assert not file.size or file.size >= 0 - assert file.locate().exists() - assert isinstance(file.read_binary(), bytes) - if file.name.endswith('.py'): - file.read_text() - - def test_file_hash_repr(self): - try: - assertRegex = self.assertRegex - except AttributeError: - # Python 2 - assertRegex = self.assertRegexpMatches - - util = [ - p for p in files('distinfo-pkg') - if p.name == 'mod.py' - ][0] - assertRegex( - repr(util.hash), - '') - - def test_files_dist_info(self): - self._test_files(files('distinfo-pkg')) - - def test_files_egg_info(self): - self._test_files(files('egginfo-pkg')) - - def test_version_egg_info_file(self): - self.assertEqual(version('egginfo-file'), '0.1') - - def test_requires_egg_info_file(self): - requirements = requires('egginfo-file') - self.assertIsNone(requirements) - - def test_requires_egg_info(self): - deps = requires('egginfo-pkg') - assert len(deps) == 2 - assert any( - dep == 'wheel >= 1.0; python_version >= "2.7"' - for dep in deps - ) - - def test_requires_dist_info(self): - deps = requires('distinfo-pkg') - assert len(deps) == 2 - assert all(deps) - assert 'wheel >= 1.0' in deps - assert "pytest; extra == 'test'" in deps - - def test_more_complex_deps_requires_text(self): - requires = textwrap.dedent(""" - dep1 - dep2 - - [:python_version < "3"] - dep3 - - [extra1] - dep4 - - [extra2:python_version < "3"] - dep5 - """) - deps = sorted(Distribution._deps_from_requires_text(requires)) - expected = [ - 'dep1', - 'dep2', - 'dep3; python_version < "3"', - 'dep4; extra == "extra1"', - 'dep5; (python_version < "3") and extra == "extra2"', - ] - # It's important that the environment marker expression be - # wrapped in parentheses to avoid the following 'and' binding more - # tightly than some other part of the environment expression. - - assert deps == expected - - -class OffSysPathTests(fixtures.DistInfoPkgOffPath, unittest.TestCase): - def test_find_distributions_specified_path(self): - dists = Distribution.discover(path=[str(self.site_dir)]) - assert any( - dist.metadata['Name'] == 'distinfo-pkg' - for dist in dists - ) - - def test_distribution_at_pathlib(self): - """Demonstrate how to load metadata direct from a directory. - """ - dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info' - dist = Distribution.at(dist_info_path) - assert dist.version == '1.0.0' - - def test_distribution_at_str(self): - dist_info_path = self.site_dir / 'distinfo_pkg-1.0.0.dist-info' - dist = Distribution.at(str(dist_info_path)) - assert dist.version == '1.0.0' diff --git a/pipenv/vendor/importlib_metadata/tests/test_integration.py b/pipenv/vendor/importlib_metadata/tests/test_integration.py deleted file mode 100644 index cbb940bd..00000000 --- a/pipenv/vendor/importlib_metadata/tests/test_integration.py +++ /dev/null @@ -1,54 +0,0 @@ -# coding: utf-8 - -from __future__ import unicode_literals - -import unittest -import packaging.requirements -import packaging.version - -from . import fixtures -from .. import ( - Distribution, - _compat, - version, - ) - - -class IntegrationTests(fixtures.DistInfoPkg, unittest.TestCase): - - def test_package_spec_installed(self): - """ - Illustrate the recommended procedure to determine if - a specified version of a package is installed. - """ - def is_installed(package_spec): - req = packaging.requirements.Requirement(package_spec) - return version(req.name) in req.specifier - - assert is_installed('distinfo-pkg==1.0') - assert is_installed('distinfo-pkg>=1.0,<2.0') - assert not is_installed('distinfo-pkg<1.0') - - -class FinderTests(fixtures.Fixtures, unittest.TestCase): - - def test_finder_without_module(self): - class ModuleFreeFinder(fixtures.NullFinder): - """ - A finder without an __module__ attribute - """ - def __getattribute__(self, name): - if name == '__module__': - raise AttributeError(name) - return super().__getattribute__(name) - - self.fixtures.enter_context( - fixtures.install_finder(ModuleFreeFinder())) - _compat.disable_stdlib_finder() - - -class LocalProjectTests(fixtures.LocalPackage, unittest.TestCase): - def test_find_local(self): - dist = Distribution._local() - assert dist.metadata['Name'] == 'local-pkg' - assert dist.version == '2.0.1' diff --git a/pipenv/vendor/importlib_metadata/tests/test_main.py b/pipenv/vendor/importlib_metadata/tests/test_main.py deleted file mode 100644 index 4ffdd5d6..00000000 --- a/pipenv/vendor/importlib_metadata/tests/test_main.py +++ /dev/null @@ -1,285 +0,0 @@ -# coding: utf-8 -from __future__ import unicode_literals - -import re -import json -import pickle -import textwrap -import unittest -import importlib -import importlib_metadata -import pyfakefs.fake_filesystem_unittest as ffs - -from . import fixtures -from .. import ( - Distribution, EntryPoint, MetadataPathFinder, - PackageNotFoundError, distributions, - entry_points, metadata, version, - ) - -try: - from builtins import str as text -except ImportError: - from __builtin__ import unicode as text - - -class BasicTests(fixtures.DistInfoPkg, unittest.TestCase): - version_pattern = r'\d+\.\d+(\.\d)?' - - def test_retrieves_version_of_self(self): - dist = Distribution.from_name('distinfo-pkg') - assert isinstance(dist.version, text) - assert re.match(self.version_pattern, dist.version) - - def test_for_name_does_not_exist(self): - with self.assertRaises(PackageNotFoundError): - Distribution.from_name('does-not-exist') - - def test_package_not_found_mentions_metadata(self): - """ - When a package is not found, that could indicate that the - packgae is not installed or that it is installed without - metadata. Ensure the exception mentions metadata to help - guide users toward the cause. See #124. - """ - with self.assertRaises(PackageNotFoundError) as ctx: - Distribution.from_name('does-not-exist') - - assert "metadata" in str(ctx.exception) - - def test_new_style_classes(self): - self.assertIsInstance(Distribution, type) - self.assertIsInstance(MetadataPathFinder, type) - - -class ImportTests(fixtures.DistInfoPkg, unittest.TestCase): - def test_import_nonexistent_module(self): - # Ensure that the MetadataPathFinder does not crash an import of a - # non-existent module. - with self.assertRaises(ImportError): - importlib.import_module('does_not_exist') - - def test_resolve(self): - entries = dict(entry_points()['entries']) - ep = entries['main'] - self.assertEqual(ep.load().__name__, "main") - - def test_entrypoint_with_colon_in_name(self): - entries = dict(entry_points()['entries']) - ep = entries['ns:sub'] - self.assertEqual(ep.value, 'mod:main') - - def test_resolve_without_attr(self): - ep = EntryPoint( - name='ep', - value='importlib_metadata', - group='grp', - ) - assert ep.load() is importlib_metadata - - -class NameNormalizationTests( - fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): - @staticmethod - def pkg_with_dashes(site_dir): - """ - Create minimal metadata for a package with dashes - in the name (and thus underscores in the filename). - """ - metadata_dir = site_dir / 'my_pkg.dist-info' - metadata_dir.mkdir() - metadata = metadata_dir / 'METADATA' - with metadata.open('w') as strm: - strm.write('Version: 1.0\n') - return 'my-pkg' - - def test_dashes_in_dist_name_found_as_underscores(self): - """ - For a package with a dash in the name, the dist-info metadata - uses underscores in the name. Ensure the metadata loads. - """ - pkg_name = self.pkg_with_dashes(self.site_dir) - assert version(pkg_name) == '1.0' - - @staticmethod - def pkg_with_mixed_case(site_dir): - """ - Create minimal metadata for a package with mixed case - in the name. - """ - metadata_dir = site_dir / 'CherryPy.dist-info' - metadata_dir.mkdir() - metadata = metadata_dir / 'METADATA' - with metadata.open('w') as strm: - strm.write('Version: 1.0\n') - return 'CherryPy' - - def test_dist_name_found_as_any_case(self): - """ - Ensure the metadata loads when queried with any case. - """ - pkg_name = self.pkg_with_mixed_case(self.site_dir) - assert version(pkg_name) == '1.0' - assert version(pkg_name.lower()) == '1.0' - assert version(pkg_name.upper()) == '1.0' - - -class NonASCIITests(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): - @staticmethod - def pkg_with_non_ascii_description(site_dir): - """ - Create minimal metadata for a package with non-ASCII in - the description. - """ - metadata_dir = site_dir / 'portend.dist-info' - metadata_dir.mkdir() - metadata = metadata_dir / 'METADATA' - with metadata.open('w', encoding='utf-8') as fp: - fp.write('Description: pôrˈtend\n') - return 'portend' - - @staticmethod - def pkg_with_non_ascii_description_egg_info(site_dir): - """ - Create minimal metadata for an egg-info package with - non-ASCII in the description. - """ - metadata_dir = site_dir / 'portend.dist-info' - metadata_dir.mkdir() - metadata = metadata_dir / 'METADATA' - with metadata.open('w', encoding='utf-8') as fp: - fp.write(textwrap.dedent(""" - Name: portend - - pôrˈtend - """).lstrip()) - return 'portend' - - def test_metadata_loads(self): - pkg_name = self.pkg_with_non_ascii_description(self.site_dir) - meta = metadata(pkg_name) - assert meta['Description'] == 'pôrˈtend' - - def test_metadata_loads_egg_info(self): - pkg_name = self.pkg_with_non_ascii_description_egg_info(self.site_dir) - meta = metadata(pkg_name) - assert meta.get_payload() == 'pôrˈtend\n' - - -class DiscoveryTests(fixtures.EggInfoPkg, - fixtures.DistInfoPkg, - unittest.TestCase): - - def test_package_discovery(self): - dists = list(distributions()) - assert all( - isinstance(dist, Distribution) - for dist in dists - ) - assert any( - dist.metadata['Name'] == 'egginfo-pkg' - for dist in dists - ) - assert any( - dist.metadata['Name'] == 'distinfo-pkg' - for dist in dists - ) - - def test_invalid_usage(self): - with self.assertRaises(ValueError): - list(distributions(context='something', name='else')) - - -class DirectoryTest(fixtures.OnSysPath, fixtures.SiteDir, unittest.TestCase): - def test_egg_info(self): - # make an `EGG-INFO` directory that's unrelated - self.site_dir.joinpath('EGG-INFO').mkdir() - # used to crash with `IsADirectoryError` - with self.assertRaises(PackageNotFoundError): - version('unknown-package') - - def test_egg(self): - egg = self.site_dir.joinpath('foo-3.6.egg') - egg.mkdir() - with self.add_sys_path(egg): - with self.assertRaises(PackageNotFoundError): - version('foo') - - -class MissingSysPath(fixtures.OnSysPath, unittest.TestCase): - site_dir = '/does-not-exist' - - def test_discovery(self): - """ - Discovering distributions should succeed even if - there is an invalid path on sys.path. - """ - importlib_metadata.distributions() - - -class InaccessibleSysPath(fixtures.OnSysPath, ffs.TestCase): - site_dir = '/access-denied' - - def setUp(self): - super(InaccessibleSysPath, self).setUp() - self.setUpPyfakefs() - self.fs.create_dir(self.site_dir, perm_bits=000) - - def test_discovery(self): - """ - Discovering distributions should succeed even if - there is an invalid path on sys.path. - """ - list(importlib_metadata.distributions()) - - -class TestEntryPoints(unittest.TestCase): - def __init__(self, *args): - super(TestEntryPoints, self).__init__(*args) - self.ep = importlib_metadata.EntryPoint('name', 'value', 'group') - - def test_entry_point_pickleable(self): - revived = pickle.loads(pickle.dumps(self.ep)) - assert revived == self.ep - - def test_immutable(self): - """EntryPoints should be immutable""" - with self.assertRaises(AttributeError): - self.ep.name = 'badactor' - - def test_repr(self): - assert 'EntryPoint' in repr(self.ep) - assert 'name=' in repr(self.ep) - assert "'name'" in repr(self.ep) - - def test_hashable(self): - """EntryPoints should be hashable""" - hash(self.ep) - - def test_json_dump(self): - """ - json should not expect to be able to dump an EntryPoint - """ - with self.assertRaises(Exception): - json.dumps(self.ep) - - def test_module(self): - assert self.ep.module == 'value' - - def test_attr(self): - assert self.ep.attr is None - - -class FileSystem( - fixtures.OnSysPath, fixtures.SiteDir, fixtures.FileBuilder, - unittest.TestCase): - def test_unicode_dir_on_sys_path(self): - """ - Ensure a Unicode subdirectory of a directory on sys.path - does not crash. - """ - fixtures.build_files( - {self.unicode_filename(): {}}, - prefix=self.site_dir, - ) - list(distributions()) diff --git a/pipenv/vendor/importlib_metadata/tests/test_zip.py b/pipenv/vendor/importlib_metadata/tests/test_zip.py deleted file mode 100644 index 4aae933d..00000000 --- a/pipenv/vendor/importlib_metadata/tests/test_zip.py +++ /dev/null @@ -1,80 +0,0 @@ -import sys -import unittest - -from .. import ( - distribution, entry_points, files, PackageNotFoundError, - version, distributions, - ) - -try: - from importlib import resources - getattr(resources, 'files') - getattr(resources, 'as_file') -except (ImportError, AttributeError): - import importlib_resources as resources - -try: - from contextlib import ExitStack -except ImportError: - from contextlib2 import ExitStack - - -class TestZip(unittest.TestCase): - root = 'importlib_metadata.tests.data' - - def _fixture_on_path(self, filename): - pkg_file = resources.files(self.root).joinpath(filename) - file = self.resources.enter_context(resources.as_file(pkg_file)) - assert file.name.startswith('example-'), file.name - sys.path.insert(0, str(file)) - self.resources.callback(sys.path.pop, 0) - - def setUp(self): - # Find the path to the example-*.whl so we can add it to the front of - # sys.path, where we'll then try to find the metadata thereof. - self.resources = ExitStack() - self.addCleanup(self.resources.close) - self._fixture_on_path('example-21.12-py3-none-any.whl') - - def test_zip_version(self): - self.assertEqual(version('example'), '21.12') - - def test_zip_version_does_not_match(self): - with self.assertRaises(PackageNotFoundError): - version('definitely-not-installed') - - def test_zip_entry_points(self): - scripts = dict(entry_points()['console_scripts']) - entry_point = scripts['example'] - self.assertEqual(entry_point.value, 'example:main') - entry_point = scripts['Example'] - self.assertEqual(entry_point.value, 'example:main') - - def test_missing_metadata(self): - self.assertIsNone(distribution('example').read_text('does not exist')) - - def test_case_insensitive(self): - self.assertEqual(version('Example'), '21.12') - - def test_files(self): - for file in files('example'): - path = str(file.dist.locate_file(file)) - assert '.whl/' in path, path - - def test_one_distribution(self): - dists = list(distributions(path=sys.path[:1])) - assert len(dists) == 1 - - -class TestEgg(TestZip): - def setUp(self): - # Find the path to the example-*.egg so we can add it to the front of - # sys.path, where we'll then try to find the metadata thereof. - self.resources = ExitStack() - self.addCleanup(self.resources.close) - self._fixture_on_path('example-21.12-py3.6.egg') - - def test_files(self): - for file in files('example'): - path = str(file.dist.locate_file(file)) - assert '.egg/' in path, path diff --git a/pipenv/vendor/importlib_resources/__init__.py b/pipenv/vendor/importlib_resources/__init__.py index f122f95e..2468f575 100644 --- a/pipenv/vendor/importlib_resources/__init__.py +++ b/pipenv/vendor/importlib_resources/__init__.py @@ -1,14 +1,23 @@ """Read resources contained within a package.""" -import sys - from ._common import ( - as_file, files, - ) + as_file, + files, + Package, + Resource, +) -# For compatibility. Ref #88. -# Also requires hook-importlib_resources.py (Ref #101). -__import__('importlib_resources.trees') +from ._legacy import ( + contents, + open_binary, + read_binary, + open_text, + read_text, + is_resource, + path, +) + +from importlib_resources.abc import ResourceReader __all__ = [ @@ -24,30 +33,4 @@ __all__ = [ 'path', 'read_binary', 'read_text', - ] - - -if sys.version_info >= (3,): - from importlib_resources._py3 import ( - Package, - Resource, - contents, - is_resource, - open_binary, - open_text, - path, - read_binary, - read_text, - ) - from importlib_resources.abc import ResourceReader -else: - from importlib_resources._py2 import ( - contents, - is_resource, - open_binary, - open_text, - path, - read_binary, - read_text, - ) - del __all__[:3] +] diff --git a/pipenv/vendor/importlib_resources/_adapters.py b/pipenv/vendor/importlib_resources/_adapters.py new file mode 100644 index 00000000..9907b148 --- /dev/null +++ b/pipenv/vendor/importlib_resources/_adapters.py @@ -0,0 +1,170 @@ +from contextlib import suppress +from io import TextIOWrapper + +from . import abc + + +class SpecLoaderAdapter: + """ + Adapt a package spec to adapt the underlying loader. + """ + + def __init__(self, spec, adapter=lambda spec: spec.loader): + self.spec = spec + self.loader = adapter(spec) + + def __getattr__(self, name): + return getattr(self.spec, name) + + +class TraversableResourcesLoader: + """ + Adapt a loader to provide TraversableResources. + """ + + def __init__(self, spec): + self.spec = spec + + def get_resource_reader(self, name): + return CompatibilityFiles(self.spec)._native() + + +def _io_wrapper(file, mode='r', *args, **kwargs): + if mode == 'r': + return TextIOWrapper(file, *args, **kwargs) + elif mode == 'rb': + return file + raise ValueError( + "Invalid mode value '{}', only 'r' and 'rb' are supported".format(mode) + ) + + +class CompatibilityFiles: + """ + Adapter for an existing or non-existant resource reader + to provide a compability .files(). + """ + + class SpecPath(abc.Traversable): + """ + Path tied to a module spec. + Can be read and exposes the resource reader children. + """ + + def __init__(self, spec, reader): + self._spec = spec + self._reader = reader + + def iterdir(self): + if not self._reader: + return iter(()) + return iter( + CompatibilityFiles.ChildPath(self._reader, path) + for path in self._reader.contents() + ) + + def is_file(self): + return False + + is_dir = is_file + + def joinpath(self, other): + if not self._reader: + return CompatibilityFiles.OrphanPath(other) + return CompatibilityFiles.ChildPath(self._reader, other) + + @property + def name(self): + return self._spec.name + + def open(self, mode='r', *args, **kwargs): + return _io_wrapper(self._reader.open_resource(None), mode, *args, **kwargs) + + class ChildPath(abc.Traversable): + """ + Path tied to a resource reader child. + Can be read but doesn't expose any meaningfull children. + """ + + def __init__(self, reader, name): + self._reader = reader + self._name = name + + def iterdir(self): + return iter(()) + + def is_file(self): + return self._reader.is_resource(self.name) + + def is_dir(self): + return not self.is_file() + + def joinpath(self, other): + return CompatibilityFiles.OrphanPath(self.name, other) + + @property + def name(self): + return self._name + + def open(self, mode='r', *args, **kwargs): + return _io_wrapper( + self._reader.open_resource(self.name), mode, *args, **kwargs + ) + + class OrphanPath(abc.Traversable): + """ + Orphan path, not tied to a module spec or resource reader. + Can't be read and doesn't expose any meaningful children. + """ + + def __init__(self, *path_parts): + if len(path_parts) < 1: + raise ValueError('Need at least one path part to construct a path') + self._path = path_parts + + def iterdir(self): + return iter(()) + + def is_file(self): + return False + + is_dir = is_file + + def joinpath(self, other): + return CompatibilityFiles.OrphanPath(*self._path, other) + + @property + def name(self): + return self._path[-1] + + def open(self, mode='r', *args, **kwargs): + raise FileNotFoundError("Can't open orphan path") + + def __init__(self, spec): + self.spec = spec + + @property + def _reader(self): + with suppress(AttributeError): + return self.spec.loader.get_resource_reader(self.spec.name) + + def _native(self): + """ + Return the native reader if it supports files(). + """ + reader = self._reader + return reader if hasattr(reader, 'files') else self + + def __getattr__(self, attr): + return getattr(self._reader, attr) + + def files(self): + return CompatibilityFiles.SpecPath(self.spec, self._reader) + + +def wrap_spec(package): + """ + Construct a package spec with traversable compatibility + on the spec/loader/reader. + """ + return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/pipenv/vendor/importlib_resources/_common.py b/pipenv/vendor/importlib_resources/_common.py index a7c2bf81..9bb6bda5 100644 --- a/pipenv/vendor/importlib_resources/_common.py +++ b/pipenv/vendor/importlib_resources/_common.py @@ -1,23 +1,22 @@ -from __future__ import absolute_import - import os +import pathlib import tempfile +import functools import contextlib import types import importlib -from ._compat import ( - Path, FileNotFoundError, - singledispatch, package_spec, - ) +from typing import Union, Any, Optional +from .abc import ResourceReader, Traversable -if False: # TYPE_CHECKING - from typing import Union, Any, Optional - from .abc import ResourceReader - Package = Union[types.ModuleType, str] +from ._compat import wrap_spec + +Package = Union[types.ModuleType, str] +Resource = Union[str, os.PathLike] def files(package): + # type: (Package) -> Traversable """ Get a Traversable resource from a package """ @@ -33,7 +32,7 @@ def normalize_path(path): str_path = str(path) parent, file_name = os.path.split(str_path) if parent: - raise ValueError('{!r} must be only a file name'.format(path)) + raise ValueError(f'{path!r} must be only a file name') return file_name @@ -48,18 +47,15 @@ def get_resource_reader(package): # zipimport.zipimporter does not support weak references, resulting in a # TypeError. That seems terrible. spec = package.__spec__ - reader = getattr(spec.loader, 'get_resource_reader', None) + reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore if reader is None: return None - return reader(spec.name) + return reader(spec.name) # type: ignore def resolve(cand): # type: (Package) -> types.ModuleType - return ( - cand if isinstance(cand, types.ModuleType) - else importlib.import_module(cand) - ) + return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand) def get_package(package): @@ -69,8 +65,8 @@ def get_package(package): Raise an exception if the resolved module is not a package. """ resolved = resolve(package) - if package_spec(resolved).submodule_search_locations is None: - raise TypeError('{!r} is not a package'.format(package)) + if wrap_spec(resolved).submodule_search_locations is None: + raise TypeError(f'{package!r} is not a package') return resolved @@ -79,7 +75,7 @@ def from_package(package): Return a Traversable object for the given package. """ - spec = package_spec(package) + spec = wrap_spec(package) reader = spec.loader.get_resource_reader(spec.name) return reader.files() @@ -94,15 +90,15 @@ def _tempfile(reader, suffix=''): os.write(fd, reader()) os.close(fd) del reader - yield Path(raw_path) + yield pathlib.Path(raw_path) finally: try: os.remove(raw_path) - except FileNotFoundError: + except (FileNotFoundError, PermissionError): pass -@singledispatch +@functools.singledispatch def as_file(path): """ Given a Traversable object, return that object as a @@ -111,7 +107,7 @@ def as_file(path): return _tempfile(path.read_bytes, suffix=path.name) -@as_file.register(Path) +@as_file.register(pathlib.Path) @contextlib.contextmanager def _(path): """ diff --git a/pipenv/vendor/importlib_resources/_compat.py b/pipenv/vendor/importlib_resources/_compat.py index 70b0f6b4..61e48d47 100644 --- a/pipenv/vendor/importlib_resources/_compat.py +++ b/pipenv/vendor/importlib_resources/_compat.py @@ -1,56 +1,20 @@ -from __future__ import absolute_import -import sys - # flake8: noqa -if sys.version_info > (3,5): - from pathlib import Path, PurePath -else: - from pathlib2 import Path, PurePath # type: ignore +import abc +import sys +import pathlib +from contextlib import suppress - -if sys.version_info > (3,): - from contextlib import suppress -else: - from contextlib2 import suppress # type: ignore - - -try: - from functools import singledispatch -except ImportError: - from singledispatch import singledispatch # type: ignore - - -try: - from abc import ABC # type: ignore -except ImportError: - from abc import ABCMeta - - class ABC(object): # type: ignore - __metaclass__ = ABCMeta - - -try: - FileNotFoundError = FileNotFoundError # type: ignore -except NameError: - FileNotFoundError = OSError # type: ignore - - -try: - NotADirectoryError = NotADirectoryError # type: ignore -except NameError: - NotADirectoryError = OSError # type: ignore - - -try: +if sys.version_info >= (3, 10): from zipfile import Path as ZipPath # type: ignore -except ImportError: +else: from zipp import Path as ZipPath # type: ignore try: from typing import runtime_checkable # type: ignore except ImportError: + def runtime_checkable(cls): # type: ignore return cls @@ -58,42 +22,27 @@ except ImportError: try: from typing import Protocol # type: ignore except ImportError: - Protocol = ABC # type: ignore + Protocol = abc.ABC # type: ignore -__metaclass__ = type - - -class PackageSpec: - def __init__(self, **kwargs): - vars(self).update(kwargs) - - -class TraversableResourcesAdapter: - def __init__(self, spec): - self.spec = spec - self.loader = LoaderAdapter(spec) - - def __getattr__(self, name): - return getattr(self.spec, name) - - -class LoaderAdapter: +class TraversableResourcesLoader: """ Adapt loaders to provide TraversableResources and other compatibility. + + Used primarily for Python 3.9 and earlier where the native + loaders do not yet implement TraversableResources. """ + def __init__(self, spec): self.spec = spec @property def path(self): - # Python < 3 return self.spec.origin def get_resource_reader(self, name): - # Python < 3.9 - from . import readers + from . import readers, _adapters def _zip_reader(spec): with suppress(AttributeError): @@ -111,29 +60,39 @@ class LoaderAdapter: reader = _available_reader(spec) return reader if hasattr(reader, 'files') else None + def _file_reader(spec): + try: + path = pathlib.Path(self.path) + except TypeError: + return None + if path.exists(): + return readers.FileReader(self) + return ( # native reader if it supplies 'files' - _native_reader(self.spec) or + _native_reader(self.spec) + or # local ZipReader if a zip module - _zip_reader(self.spec) or + _zip_reader(self.spec) + or # local NamespaceReader if a namespace module - _namespace_reader(self.spec) or + _namespace_reader(self.spec) + or # local FileReader - readers.FileReader(self) - ) - - -def package_spec(package): - """ - Construct a minimal package spec suitable for - matching the interfaces this library relies upon - in later Python versions. - """ - spec = getattr(package, '__spec__', None) or \ - PackageSpec( - origin=package.__file__, - loader=getattr(package, '__loader__', None), - name=package.__name__, - submodule_search_locations=getattr(package, '__path__', None), + _file_reader(self.spec) + # fallback - adapt the spec ResourceReader to TraversableReader + or _adapters.CompatibilityFiles(self.spec) ) - return TraversableResourcesAdapter(spec) + + +def wrap_spec(package): + """ + Construct a package spec with traversable compatibility + on the spec/loader/reader. + + Supersedes _adapters.wrap_spec to use TraversableResourcesLoader + from above for older Python compatibility (<3.10). + """ + from . import _adapters + + return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/pipenv/vendor/importlib_resources/_itertools.py b/pipenv/vendor/importlib_resources/_itertools.py new file mode 100644 index 00000000..dd45f2f0 --- /dev/null +++ b/pipenv/vendor/importlib_resources/_itertools.py @@ -0,0 +1,19 @@ +from itertools import filterfalse + + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/pipenv/vendor/importlib_resources/_legacy.py b/pipenv/vendor/importlib_resources/_legacy.py new file mode 100644 index 00000000..3b9a5342 --- /dev/null +++ b/pipenv/vendor/importlib_resources/_legacy.py @@ -0,0 +1,85 @@ +import os +import pathlib +import types + +from typing import Union, Iterable, ContextManager +from typing.io import BinaryIO, TextIO + +from . import _common + +Package = Union[types.ModuleType, str] +Resource = Union[str, os.PathLike] + + +def open_binary(package: Package, resource: Resource) -> BinaryIO: + """Return a file-like object opened for binary reading of the resource.""" + return (_common.files(package) / _common.normalize_path(resource)).open('rb') + + +def read_binary(package: Package, resource: Resource) -> bytes: + """Return the binary contents of the resource.""" + return (_common.files(package) / _common.normalize_path(resource)).read_bytes() + + +def open_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict', +) -> TextIO: + """Return a file-like object opened for text reading of the resource.""" + return (_common.files(package) / _common.normalize_path(resource)).open( + 'r', encoding=encoding, errors=errors + ) + + +def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict', +) -> str: + """Return the decoded string of the resource. + + The decoding-related arguments have the same semantics as those of + bytes.decode(). + """ + with open_text(package, resource, encoding, errors) as fp: + return fp.read() + + +def contents(package: Package) -> Iterable[str]: + """Return an iterable of entries in `package`. + + Note that not all entries are resources. Specifically, directories are + not considered resources. Use `is_resource()` on each entry returned here + to check if it is a resource or not. + """ + return [path.name for path in _common.files(package).iterdir()] + + +def is_resource(package: Package, name: str) -> bool: + """True if `name` is a resource inside `package`. + + Directories are *not* resources. + """ + resource = _common.normalize_path(name) + return any( + traversable.name == resource and traversable.is_file() + for traversable in _common.files(package).iterdir() + ) + + +def path( + package: Package, + resource: Resource, +) -> ContextManager[pathlib.Path]: + """A context manager providing a file path object to the resource. + + If the resource does not already exist on its own on the file system, + a temporary file will be created. If the file was created, the file + will be deleted upon exiting the context manager (no exception is + raised if the file was deleted prior to the context manager + exiting). + """ + return _common.as_file(_common.files(package) / _common.normalize_path(resource)) diff --git a/pipenv/vendor/importlib_resources/_py2.py b/pipenv/vendor/importlib_resources/_py2.py deleted file mode 100644 index dd8c7d62..00000000 --- a/pipenv/vendor/importlib_resources/_py2.py +++ /dev/null @@ -1,107 +0,0 @@ -import os -import errno - -from . import _common -from ._compat import FileNotFoundError -from io import BytesIO, TextIOWrapper, open as io_open - - -def open_binary(package, resource): - """Return a file-like object opened for binary reading of the resource.""" - resource = _common.normalize_path(resource) - package = _common.get_package(package) - # Using pathlib doesn't work well here due to the lack of 'strict' argument - # for pathlib.Path.resolve() prior to Python 3.6. - package_path = os.path.dirname(package.__file__) - relative_path = os.path.join(package_path, resource) - full_path = os.path.abspath(relative_path) - try: - return io_open(full_path, 'rb') - except IOError: - # This might be a package in a zip file. zipimport provides a loader - # with a functioning get_data() method, however we have to strip the - # archive (i.e. the .zip file's name) off the front of the path. This - # is because the zipimport loader in Python 2 doesn't actually follow - # PEP 302. It should allow the full path, but actually requires that - # the path be relative to the zip file. - try: - loader = package.__loader__ - full_path = relative_path[len(loader.archive)+1:] - data = loader.get_data(full_path) - except (IOError, AttributeError): - package_name = package.__name__ - message = '{!r} resource not found in {!r}'.format( - resource, package_name) - raise FileNotFoundError(message) - return BytesIO(data) - - -def open_text(package, resource, encoding='utf-8', errors='strict'): - """Return a file-like object opened for text reading of the resource.""" - return TextIOWrapper( - open_binary(package, resource), encoding=encoding, errors=errors) - - -def read_binary(package, resource): - """Return the binary contents of the resource.""" - with open_binary(package, resource) as fp: - return fp.read() - - -def read_text(package, resource, encoding='utf-8', errors='strict'): - """Return the decoded string of the resource. - - The decoding-related arguments have the same semantics as those of - bytes.decode(). - """ - with open_text(package, resource, encoding, errors) as fp: - return fp.read() - - -def path(package, resource): - """A context manager providing a file path object to the resource. - - If the resource does not already exist on its own on the file system, - a temporary file will be created. If the file was created, the file - will be deleted upon exiting the context manager (no exception is - raised if the file was deleted prior to the context manager - exiting). - """ - path = _common.files(package).joinpath(_common.normalize_path(resource)) - if not path.is_file(): - raise FileNotFoundError(path) - return _common.as_file(path) - - -def is_resource(package, name): - """True if name is a resource inside package. - - Directories are *not* resources. - """ - package = _common.get_package(package) - _common.normalize_path(name) - try: - package_contents = set(contents(package)) - except OSError as error: - if error.errno not in (errno.ENOENT, errno.ENOTDIR): - # We won't hit this in the Python 2 tests, so it'll appear - # uncovered. We could mock os.listdir() to return a non-ENOENT or - # ENOTDIR, but then we'd have to depend on another external - # library since Python 2 doesn't have unittest.mock. It's not - # worth it. - raise # pragma: nocover - return False - if name not in package_contents: - return False - return (_common.from_package(package) / name).is_file() - - -def contents(package): - """Return an iterable of entries in `package`. - - Note that not all entries are resources. Specifically, directories are - not considered resources. Use `is_resource()` on each entry returned here - to check if it is a resource or not. - """ - package = _common.get_package(package) - return list(item.name for item in _common.from_package(package).iterdir()) diff --git a/pipenv/vendor/importlib_resources/_py3.py b/pipenv/vendor/importlib_resources/_py3.py deleted file mode 100644 index ffeb616d..00000000 --- a/pipenv/vendor/importlib_resources/_py3.py +++ /dev/null @@ -1,160 +0,0 @@ -import os -import io - -from . import _common -from contextlib import suppress -from importlib.abc import ResourceLoader -from io import BytesIO, TextIOWrapper -from pathlib import Path -from types import ModuleType -from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401 -from typing import cast -from typing.io import BinaryIO, TextIO -from collections.abc import Sequence -from functools import singledispatch - -if False: # TYPE_CHECKING - from typing import ContextManager - -Package = Union[ModuleType, str] -Resource = Union[str, os.PathLike] - - -def open_binary(package: Package, resource: Resource) -> BinaryIO: - """Return a file-like object opened for binary reading of the resource.""" - resource = _common.normalize_path(resource) - package = _common.get_package(package) - reader = _common.get_resource_reader(package) - if reader is not None: - return reader.open_resource(resource) - # Using pathlib doesn't work well here due to the lack of 'strict' - # argument for pathlib.Path.resolve() prior to Python 3.6. - if package.__spec__.submodule_search_locations is not None: - paths = package.__spec__.submodule_search_locations - elif package.__spec__.origin is not None: - paths = [os.path.dirname(os.path.abspath(package.__spec__.origin))] - - for package_path in paths: - full_path = os.path.join(package_path, resource) - try: - return open(full_path, mode='rb') - except OSError: - # Just assume the loader is a resource loader; all the relevant - # importlib.machinery loaders are and an AttributeError for - # get_data() will make it clear what is needed from the loader. - loader = cast(ResourceLoader, package.__spec__.loader) - data = None - if hasattr(package.__spec__.loader, 'get_data'): - with suppress(OSError): - data = loader.get_data(full_path) - if data is not None: - return BytesIO(data) - - raise FileNotFoundError('{!r} resource not found in {!r}'.format( - resource, package.__spec__.name)) - - -def open_text(package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict') -> TextIO: - """Return a file-like object opened for text reading of the resource.""" - return TextIOWrapper( - open_binary(package, resource), encoding=encoding, errors=errors) - - -def read_binary(package: Package, resource: Resource) -> bytes: - """Return the binary contents of the resource.""" - with open_binary(package, resource) as fp: - return fp.read() - - -def read_text(package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict') -> str: - """Return the decoded string of the resource. - - The decoding-related arguments have the same semantics as those of - bytes.decode(). - """ - with open_text(package, resource, encoding, errors) as fp: - return fp.read() - - -def path( - package: Package, resource: Resource, - ) -> 'ContextManager[Path]': - """A context manager providing a file path object to the resource. - - If the resource does not already exist on its own on the file system, - a temporary file will be created. If the file was created, the file - will be deleted upon exiting the context manager (no exception is - raised if the file was deleted prior to the context manager - exiting). - """ - reader = _common.get_resource_reader(_common.get_package(package)) - return ( - _path_from_reader(reader, _common.normalize_path(resource)) - if reader else - _common.as_file( - _common.files(package).joinpath(_common.normalize_path(resource))) - ) - - -def _path_from_reader(reader, resource): - return _path_from_resource_path(reader, resource) or \ - _path_from_open_resource(reader, resource) - - -def _path_from_resource_path(reader, resource): - with suppress(FileNotFoundError): - return Path(reader.resource_path(resource)) - - -def _path_from_open_resource(reader, resource): - saved = io.BytesIO(reader.open_resource(resource).read()) - return _common._tempfile(saved.read, suffix=resource) - - -def is_resource(package: Package, name: str) -> bool: - """True if `name` is a resource inside `package`. - - Directories are *not* resources. - """ - package = _common.get_package(package) - _common.normalize_path(name) - reader = _common.get_resource_reader(package) - if reader is not None: - return reader.is_resource(name) - package_contents = set(contents(package)) - if name not in package_contents: - return False - return (_common.from_package(package) / name).is_file() - - -def contents(package: Package) -> Iterable[str]: - """Return an iterable of entries in `package`. - - Note that not all entries are resources. Specifically, directories are - not considered resources. Use `is_resource()` on each entry returned here - to check if it is a resource or not. - """ - package = _common.get_package(package) - reader = _common.get_resource_reader(package) - if reader is not None: - return _ensure_sequence(reader.contents()) - transversable = _common.from_package(package) - if transversable.is_dir(): - return list(item.name for item in transversable.iterdir()) - return [] - - -@singledispatch -def _ensure_sequence(iterable): - return list(iterable) - - -@_ensure_sequence.register(Sequence) -def _(iterable): - return iterable diff --git a/pipenv/vendor/importlib_resources/abc.py b/pipenv/vendor/importlib_resources/abc.py index 18bc4ef8..56dc8127 100644 --- a/pipenv/vendor/importlib_resources/abc.py +++ b/pipenv/vendor/importlib_resources/abc.py @@ -1,22 +1,14 @@ -from __future__ import absolute_import - import abc +from typing import BinaryIO, Iterable, Text -from ._compat import ABC, FileNotFoundError, runtime_checkable, Protocol - -# Use mypy's comment syntax for Python 2 compatibility -try: - from typing import BinaryIO, Iterable, Text -except ImportError: - pass +from ._compat import runtime_checkable, Protocol -class ResourceReader(ABC): +class ResourceReader(metaclass=abc.ABCMeta): """Abstract base class for loaders to provide resource reading support.""" @abc.abstractmethod - def open_resource(self, resource): - # type: (Text) -> BinaryIO + def open_resource(self, resource: Text) -> BinaryIO: """Return an opened, file-like object for binary reading. The 'resource' argument is expected to represent only a file name. @@ -28,8 +20,7 @@ class ResourceReader(ABC): raise FileNotFoundError @abc.abstractmethod - def resource_path(self, resource): - # type: (Text) -> Text + def resource_path(self, resource: Text) -> Text: """Return the file system path to the specified resource. The 'resource' argument is expected to represent only a file name. @@ -42,8 +33,7 @@ class ResourceReader(ABC): raise FileNotFoundError @abc.abstractmethod - def is_resource(self, path): - # type: (Text) -> bool + def is_resource(self, path: Text) -> bool: """Return True if the named 'path' is a resource. Files are resources, directories are not. @@ -51,8 +41,7 @@ class ResourceReader(ABC): raise FileNotFoundError @abc.abstractmethod - def contents(self): - # type: () -> Iterable[str] + def contents(self) -> Iterable[str]: """Return an iterable of entries in `package`.""" raise FileNotFoundError @@ -70,26 +59,28 @@ class Traversable(Protocol): Yield Traversable objects in self """ - @abc.abstractmethod def read_bytes(self): """ Read contents of self as bytes """ + with self.open('rb') as strm: + return strm.read() - @abc.abstractmethod def read_text(self, encoding=None): """ - Read contents of self as bytes + Read contents of self as text """ + with self.open(encoding=encoding) as strm: + return strm.read() @abc.abstractmethod - def is_dir(self): + def is_dir(self) -> bool: """ Return True if self is a dir """ @abc.abstractmethod - def is_file(self): + def is_file(self) -> bool: """ Return True if self is a file """ @@ -100,11 +91,11 @@ class Traversable(Protocol): Return Traversable child in self """ - @abc.abstractmethod def __truediv__(self, child): """ Return Traversable child in self """ + return self.joinpath(child) @abc.abstractmethod def open(self, mode='r', *args, **kwargs): @@ -117,14 +108,18 @@ class Traversable(Protocol): """ @abc.abstractproperty - def name(self): - # type: () -> str + def name(self) -> str: """ The base name of this object without any parent references. """ class TraversableResources(ResourceReader): + """ + The required interface for providing traversable + resources. + """ + @abc.abstractmethod def files(self): """Return a Traversable object for the loaded package.""" diff --git a/pipenv/vendor/importlib_resources/readers.py b/pipenv/vendor/importlib_resources/readers.py index ce9c0cae..f1190ca4 100644 --- a/pipenv/vendor/importlib_resources/readers.py +++ b/pipenv/vendor/importlib_resources/readers.py @@ -1,16 +1,20 @@ -import os.path - -from collections import OrderedDict +import collections +import pathlib +import operator from . import abc -from ._compat import Path, ZipPath -from ._compat import FileNotFoundError, NotADirectoryError +from ._itertools import unique_everseen +from ._compat import ZipPath + + +def remove_duplicates(items): + return iter(collections.OrderedDict.fromkeys(items)) class FileReader(abc.TraversableResources): def __init__(self, loader): - self.path = Path(loader.path).parent + self.path = pathlib.Path(loader.path).parent def resource_path(self, resource): """ @@ -53,30 +57,24 @@ class MultiplexedPath(abc.Traversable): namespace packages which may be multihomed at a single name. """ + def __init__(self, *paths): - paths = list(OrderedDict.fromkeys(paths)) # remove duplicates - self._paths = list(map(Path, paths)) + self._paths = list(map(pathlib.Path, remove_duplicates(paths))) if not self._paths: message = 'MultiplexedPath must contain at least one path' raise FileNotFoundError(message) - if any(not path.is_dir() for path in self._paths): - raise NotADirectoryError( - 'MultiplexedPath only supports directories') + if not all(path.is_dir() for path in self._paths): + raise NotADirectoryError('MultiplexedPath only supports directories') def iterdir(self): - visited = [] - for path in self._paths: - for file in path.iterdir(): - if file.name in visited: - continue - visited.append(file.name) - yield file + files = (file for path in self._paths for file in path.iterdir()) + return unique_everseen(files, key=operator.attrgetter('name')) def read_bytes(self): - raise FileNotFoundError('{} is not a file'.format(self)) + raise FileNotFoundError(f'{self} is not a file') def read_text(self, *args, **kwargs): - raise FileNotFoundError('{} is not a file'.format(self)) + raise FileNotFoundError(f'{self} is not a file') def is_dir(self): return True @@ -95,14 +93,15 @@ class MultiplexedPath(abc.Traversable): __truediv__ = joinpath def open(self, *args, **kwargs): - raise FileNotFoundError('{} is not a file'.format(self)) + raise FileNotFoundError(f'{self} is not a file') + @property def name(self): - return os.path.basename(self._paths[0]) + return self._paths[0].name def __repr__(self): - return 'MultiplexedPath({})'.format( - ', '.join("'{}'".format(path) for path in self._paths)) + paths = ', '.join(f"'{path}'" for path in self._paths) + return f'MultiplexedPath({paths})' class NamespaceReader(abc.TraversableResources): diff --git a/pipenv/vendor/importlib_resources/simple.py b/pipenv/vendor/importlib_resources/simple.py new file mode 100644 index 00000000..da073cbd --- /dev/null +++ b/pipenv/vendor/importlib_resources/simple.py @@ -0,0 +1,116 @@ +""" +Interface adapters for low-level readers. +""" + +import abc +import io +import itertools +from typing import BinaryIO, List + +from .abc import Traversable, TraversableResources + + +class SimpleReader(abc.ABC): + """ + The minimum, low-level interface required from a resource + provider. + """ + + @abc.abstractproperty + def package(self): + # type: () -> str + """ + The name of the package for which this reader loads resources. + """ + + @abc.abstractmethod + def children(self): + # type: () -> List['SimpleReader'] + """ + Obtain an iterable of SimpleReader for available + child containers (e.g. directories). + """ + + @abc.abstractmethod + def resources(self): + # type: () -> List[str] + """ + Obtain available named resources for this virtual package. + """ + + @abc.abstractmethod + def open_binary(self, resource): + # type: (str) -> BinaryIO + """ + Obtain a File-like for a named resource. + """ + + @property + def name(self): + return self.package.split('.')[-1] + + +class ResourceHandle(Traversable): + """ + Handle to a named resource in a ResourceReader. + """ + + def __init__(self, parent, name): + # type: (ResourceContainer, str) -> None + self.parent = parent + self.name = name # type: ignore + + def is_file(self): + return True + + def is_dir(self): + return False + + def open(self, mode='r', *args, **kwargs): + stream = self.parent.reader.open_binary(self.name) + if 'b' not in mode: + stream = io.TextIOWrapper(*args, **kwargs) + return stream + + def joinpath(self, name): + raise RuntimeError("Cannot traverse into a resource") + + +class ResourceContainer(Traversable): + """ + Traversable container for a package's resources via its reader. + """ + + def __init__(self, reader): + # type: (SimpleReader) -> None + self.reader = reader + + def is_dir(self): + return True + + def is_file(self): + return False + + def iterdir(self): + files = (ResourceHandle(self, name) for name in self.reader.resources) + dirs = map(ResourceContainer, self.reader.children()) + return itertools.chain(files, dirs) + + def open(self, *args, **kwargs): + raise IsADirectoryError() + + def joinpath(self, name): + return next( + traversable for traversable in self.iterdir() if traversable.name == name + ) + + +class TraversableReader(TraversableResources, SimpleReader): + """ + A TraversableResources based on SimpleReader. Resource providers + may derive from this class to provide the TraversableResources + interface by supplying the SimpleReader interface. + """ + + def files(self): + return ResourceContainer(self) diff --git a/pipenv/vendor/importlib_resources/tests/_compat.py b/pipenv/vendor/importlib_resources/tests/_compat.py new file mode 100644 index 00000000..4c99cffd --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/_compat.py @@ -0,0 +1,19 @@ +import os + + +try: + from test.support import import_helper # type: ignore +except ImportError: + # Python 3.9 and earlier + class import_helper: # type: ignore + from test.support import modules_setup, modules_cleanup + + +try: + # Python 3.10 + from test.support.os_helper import unlink +except ImportError: + from test.support import unlink as _unlink + + def unlink(target): + return _unlink(os.fspath(target)) diff --git a/pipenv/vendor/importlib_resources/tests/namespacedata01/binary.file b/pipenv/vendor/importlib_resources/tests/namespacedata01/binary.file new file mode 100644 index 0000000000000000000000000000000000000000..eaf36c1daccfdf325514461cd1a2ffbc139b5464 GIT binary patch literal 4 LcmZQzWMT#Y01f~L literal 0 HcmV?d00001 diff --git a/pipenv/vendor/importlib_resources/tests/namespacedata01/utf-16.file b/pipenv/vendor/importlib_resources/tests/namespacedata01/utf-16.file new file mode 100644 index 0000000000000000000000000000000000000000..2cb772295ef4b480a8d83725bd5006a0236d8f68 GIT binary patch literal 44 ucmezW&x0YAAqNQa8FUyF7(y9B7~B|i84MZBfV^^`Xc15@g+Y;liva-T)Ce>H literal 0 HcmV?d00001 diff --git a/pipenv/vendor/importlib_resources/tests/namespacedata01/utf-8.file b/pipenv/vendor/importlib_resources/tests/namespacedata01/utf-8.file new file mode 100644 index 00000000..1c0132ad --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/namespacedata01/utf-8.file @@ -0,0 +1 @@ +Hello, UTF-8 world! diff --git a/pipenv/vendor/importlib_resources/tests/test_compatibilty_files.py b/pipenv/vendor/importlib_resources/tests/test_compatibilty_files.py new file mode 100644 index 00000000..d92c7c56 --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/test_compatibilty_files.py @@ -0,0 +1,102 @@ +import io +import unittest + +import importlib_resources as resources + +from importlib_resources._adapters import ( + CompatibilityFiles, + wrap_spec, +) + +from . import util + + +class CompatibilityFilesTests(unittest.TestCase): + @property + def package(self): + bytes_data = io.BytesIO(b'Hello, world!') + return util.create_package( + file=bytes_data, + path='some_path', + contents=('a', 'b', 'c'), + ) + + @property + def files(self): + return resources.files(self.package) + + def test_spec_path_iter(self): + self.assertEqual( + sorted(path.name for path in self.files.iterdir()), + ['a', 'b', 'c'], + ) + + def test_child_path_iter(self): + self.assertEqual(list((self.files / 'a').iterdir()), []) + + def test_orphan_path_iter(self): + self.assertEqual(list((self.files / 'a' / 'a').iterdir()), []) + self.assertEqual(list((self.files / 'a' / 'a' / 'a').iterdir()), []) + + def test_spec_path_is(self): + self.assertFalse(self.files.is_file()) + self.assertFalse(self.files.is_dir()) + + def test_child_path_is(self): + self.assertTrue((self.files / 'a').is_file()) + self.assertFalse((self.files / 'a').is_dir()) + + def test_orphan_path_is(self): + self.assertFalse((self.files / 'a' / 'a').is_file()) + self.assertFalse((self.files / 'a' / 'a').is_dir()) + self.assertFalse((self.files / 'a' / 'a' / 'a').is_file()) + self.assertFalse((self.files / 'a' / 'a' / 'a').is_dir()) + + def test_spec_path_name(self): + self.assertEqual(self.files.name, 'testingpackage') + + def test_child_path_name(self): + self.assertEqual((self.files / 'a').name, 'a') + + def test_orphan_path_name(self): + self.assertEqual((self.files / 'a' / 'b').name, 'b') + self.assertEqual((self.files / 'a' / 'b' / 'c').name, 'c') + + def test_spec_path_open(self): + self.assertEqual(self.files.read_bytes(), b'Hello, world!') + self.assertEqual(self.files.read_text(), 'Hello, world!') + + def test_child_path_open(self): + self.assertEqual((self.files / 'a').read_bytes(), b'Hello, world!') + self.assertEqual((self.files / 'a').read_text(), 'Hello, world!') + + def test_orphan_path_open(self): + with self.assertRaises(FileNotFoundError): + (self.files / 'a' / 'b').read_bytes() + with self.assertRaises(FileNotFoundError): + (self.files / 'a' / 'b' / 'c').read_bytes() + + def test_open_invalid_mode(self): + with self.assertRaises(ValueError): + self.files.open('0') + + def test_orphan_path_invalid(self): + with self.assertRaises(ValueError): + CompatibilityFiles.OrphanPath() + + def test_wrap_spec(self): + spec = wrap_spec(self.package) + self.assertIsInstance(spec.loader.get_resource_reader(None), CompatibilityFiles) + + +class CompatibilityFilesNoReaderTests(unittest.TestCase): + @property + def package(self): + return util.create_package_from_loader(None) + + @property + def files(self): + return resources.files(self.package) + + def test_spec_path_joinpath(self): + self.assertIsInstance(self.files / 'a', CompatibilityFiles.OrphanPath) diff --git a/pipenv/vendor/importlib_resources/tests/test_contents.py b/pipenv/vendor/importlib_resources/tests/test_contents.py new file mode 100644 index 00000000..2af70607 --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/test_contents.py @@ -0,0 +1,42 @@ +import unittest +import importlib_resources as resources + +from . import data01 +from . import util + + +class ContentsTests: + expected = { + '__init__.py', + 'binary.file', + 'subdirectory', + 'utf-16.file', + 'utf-8.file', + } + + def test_contents(self): + assert self.expected <= set(resources.contents(self.data)) + + +class ContentsDiskTests(ContentsTests, unittest.TestCase): + def setUp(self): + self.data = data01 + + +class ContentsZipTests(ContentsTests, util.ZipSetup, unittest.TestCase): + pass + + +class ContentsNamespaceTests(ContentsTests, unittest.TestCase): + expected = { + # no __init__ because of namespace design + # no subdirectory as incidental difference in fixture + 'binary.file', + 'utf-16.file', + 'utf-8.file', + } + + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 diff --git a/pipenv/vendor/importlib_resources/tests/test_files.py b/pipenv/vendor/importlib_resources/tests/test_files.py index 5a9cf9c7..2676b49e 100644 --- a/pipenv/vendor/importlib_resources/tests/test_files.py +++ b/pipenv/vendor/importlib_resources/tests/test_files.py @@ -15,13 +15,13 @@ class FilesTests: def test_read_text(self): files = resources.files(self.data) - actual = files.joinpath('utf-8.file').read_text() + actual = files.joinpath('utf-8.file').read_text(encoding='utf-8') assert actual == 'Hello, UTF-8 world!\n' @unittest.skipUnless( hasattr(typing, 'runtime_checkable'), "Only suitable when typing supports runtime_checkable", - ) + ) def test_traversable(self): assert isinstance(resources.files(self.data), Traversable) @@ -35,5 +35,12 @@ class OpenZipTests(FilesTests, util.ZipSetup, unittest.TestCase): pass +class OpenNamespaceTests(FilesTests, unittest.TestCase): + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 + + if __name__ == '__main__': unittest.main() diff --git a/pipenv/vendor/importlib_resources/tests/test_open.py b/pipenv/vendor/importlib_resources/tests/test_open.py index 8a3429f2..919fc0db 100644 --- a/pipenv/vendor/importlib_resources/tests/test_open.py +++ b/pipenv/vendor/importlib_resources/tests/test_open.py @@ -3,7 +3,6 @@ import unittest import importlib_resources as resources from . import data01 from . import util -from .._compat import FileNotFoundError class CommonBinaryTests(util.CommonTests, unittest.TestCase): @@ -30,34 +29,32 @@ class OpenTests: self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_open_text_given_encoding(self): - with resources.open_text( - self.data, 'utf-16.file', 'utf-16', 'strict') as fp: + with resources.open_text(self.data, 'utf-16.file', 'utf-16', 'strict') as fp: result = fp.read() self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_open_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - with resources.open_text( - self.data, 'utf-16.file', 'utf-8', 'strict') as fp: + with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'strict') as fp: self.assertRaises(UnicodeError, fp.read) - with resources.open_text( - self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: + with resources.open_text(self.data, 'utf-16.file', 'utf-8', 'ignore') as fp: result = fp.read() self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00') + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + ) def test_open_binary_FileNotFoundError(self): self.assertRaises( - FileNotFoundError, - resources.open_binary, self.data, 'does-not-exist') + FileNotFoundError, resources.open_binary, self.data, 'does-not-exist' + ) def test_open_text_FileNotFoundError(self): self.assertRaises( - FileNotFoundError, - resources.open_text, self.data, 'does-not-exist') + FileNotFoundError, resources.open_text, self.data, 'does-not-exist' + ) class OpenDiskTests(OpenTests, unittest.TestCase): @@ -65,6 +62,13 @@ class OpenDiskTests(OpenTests, unittest.TestCase): self.data = data01 +class OpenDiskNamespaceTests(OpenTests, unittest.TestCase): + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 + + class OpenZipTests(OpenTests, util.ZipSetup, unittest.TestCase): pass diff --git a/pipenv/vendor/importlib_resources/tests/test_path.py b/pipenv/vendor/importlib_resources/tests/test_path.py index f6004756..9180626f 100644 --- a/pipenv/vendor/importlib_resources/tests/test_path.py +++ b/pipenv/vendor/importlib_resources/tests/test_path.py @@ -1,3 +1,4 @@ +import io import unittest import importlib_resources as resources @@ -6,14 +7,12 @@ from . import util class CommonTests(util.CommonTests, unittest.TestCase): - def execute(self, package, path): with resources.path(package, path): pass class PathTests: - def test_reading(self): # Path should be readable. # Test also implicitly verifies the returned object is a pathlib.Path @@ -29,6 +28,26 @@ class PathTests: class PathDiskTests(PathTests, unittest.TestCase): data = data01 + def test_natural_path(self): + """ + Guarantee the internal implementation detail that + file-system-backed resources do not get the tempdir + treatment. + """ + with resources.path(self.data, 'utf-8.file') as path: + assert 'data' in str(path) + + +class PathMemoryTests(PathTests, unittest.TestCase): + def setUp(self): + file = io.BytesIO(b'Hello, UTF-8 world!\n') + self.addCleanup(file.close) + self.data = util.create_package( + file=file, path=FileNotFoundError("package exists only in memory") + ) + self.data.__spec__.origin = None + self.data.__spec__.has_location = False + class PathZipTests(PathTests, util.ZipSetup, unittest.TestCase): def test_remove_in_context_manager(self): diff --git a/pipenv/vendor/importlib_resources/tests/test_read.py b/pipenv/vendor/importlib_resources/tests/test_read.py index ee94d8ad..2616fbf5 100644 --- a/pipenv/vendor/importlib_resources/tests/test_read.py +++ b/pipenv/vendor/importlib_resources/tests/test_read.py @@ -26,20 +26,19 @@ class ReadTests: self.assertEqual(result, 'Hello, UTF-8 world!\n') def test_read_text_given_encoding(self): - result = resources.read_text( - self.data, 'utf-16.file', encoding='utf-16') + result = resources.read_text(self.data, 'utf-16.file', encoding='utf-16') self.assertEqual(result, 'Hello, UTF-16 world!\n') def test_read_text_with_errors(self): # Raises UnicodeError without the 'errors' argument. - self.assertRaises( - UnicodeError, resources.read_text, self.data, 'utf-16.file') + self.assertRaises(UnicodeError, resources.read_text, self.data, 'utf-16.file') result = resources.read_text(self.data, 'utf-16.file', errors='ignore') self.assertEqual( result, 'H\x00e\x00l\x00l\x00o\x00,\x00 ' '\x00U\x00T\x00F\x00-\x001\x006\x00 ' - '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00') + '\x00w\x00o\x00r\x00l\x00d\x00!\x00\n\x00', + ) class ReadDiskTests(ReadTests, unittest.TestCase): @@ -49,15 +48,20 @@ class ReadDiskTests(ReadTests, unittest.TestCase): class ReadZipTests(ReadTests, util.ZipSetup, unittest.TestCase): def test_read_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - result = resources.read_binary( - submodule, 'binary.file') + result = resources.read_binary(submodule, 'binary.file') self.assertEqual(result, b'\0\1\2\3') def test_read_submodule_resource_by_name(self): - result = resources.read_binary( - 'ziptestdata.subdirectory', 'binary.file') + result = resources.read_binary('ziptestdata.subdirectory', 'binary.file') self.assertEqual(result, b'\0\1\2\3') +class ReadNamespaceTests(ReadTests, unittest.TestCase): + def setUp(self): + from . import namespacedata01 + + self.data = namespacedata01 + + if __name__ == '__main__': unittest.main() diff --git a/pipenv/vendor/importlib_resources/tests/test_reader.py b/pipenv/vendor/importlib_resources/tests/test_reader.py new file mode 100644 index 00000000..16841a50 --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/test_reader.py @@ -0,0 +1,128 @@ +import os.path +import sys +import pathlib +import unittest + +from importlib import import_module +from importlib_resources.readers import MultiplexedPath, NamespaceReader + + +class MultiplexedPathTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + path = pathlib.Path(__file__).parent / 'namespacedata01' + cls.folder = str(path) + + def test_init_no_paths(self): + with self.assertRaises(FileNotFoundError): + MultiplexedPath() + + def test_init_file(self): + with self.assertRaises(NotADirectoryError): + MultiplexedPath(os.path.join(self.folder, 'binary.file')) + + def test_iterdir(self): + contents = {path.name for path in MultiplexedPath(self.folder).iterdir()} + try: + contents.remove('__pycache__') + except (KeyError, ValueError): + pass + self.assertEqual(contents, {'binary.file', 'utf-16.file', 'utf-8.file'}) + + def test_iterdir_duplicate(self): + data01 = os.path.abspath(os.path.join(__file__, '..', 'data01')) + contents = { + path.name for path in MultiplexedPath(self.folder, data01).iterdir() + } + for remove in ('__pycache__', '__init__.pyc'): + try: + contents.remove(remove) + except (KeyError, ValueError): + pass + self.assertEqual( + contents, + {'__init__.py', 'binary.file', 'subdirectory', 'utf-16.file', 'utf-8.file'}, + ) + + def test_is_dir(self): + self.assertEqual(MultiplexedPath(self.folder).is_dir(), True) + + def test_is_file(self): + self.assertEqual(MultiplexedPath(self.folder).is_file(), False) + + def test_open_file(self): + path = MultiplexedPath(self.folder) + with self.assertRaises(FileNotFoundError): + path.read_bytes() + with self.assertRaises(FileNotFoundError): + path.read_text() + with self.assertRaises(FileNotFoundError): + path.open() + + def test_join_path(self): + prefix = os.path.abspath(os.path.join(__file__, '..')) + data01 = os.path.join(prefix, 'data01') + path = MultiplexedPath(self.folder, data01) + self.assertEqual( + str(path.joinpath('binary.file'))[len(prefix) + 1 :], + os.path.join('namespacedata01', 'binary.file'), + ) + self.assertEqual( + str(path.joinpath('subdirectory'))[len(prefix) + 1 :], + os.path.join('data01', 'subdirectory'), + ) + self.assertEqual( + str(path.joinpath('imaginary'))[len(prefix) + 1 :], + os.path.join('namespacedata01', 'imaginary'), + ) + + def test_repr(self): + self.assertEqual( + repr(MultiplexedPath(self.folder)), + f"MultiplexedPath('{self.folder}')", + ) + + def test_name(self): + self.assertEqual( + MultiplexedPath(self.folder).name, + os.path.basename(self.folder), + ) + + +class NamespaceReaderTest(unittest.TestCase): + site_dir = str(pathlib.Path(__file__).parent) + + @classmethod + def setUpClass(cls): + sys.path.append(cls.site_dir) + + @classmethod + def tearDownClass(cls): + sys.path.remove(cls.site_dir) + + def test_init_error(self): + with self.assertRaises(ValueError): + NamespaceReader(['path1', 'path2']) + + def test_resource_path(self): + namespacedata01 = import_module('namespacedata01') + reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) + + root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01')) + self.assertEqual( + reader.resource_path('binary.file'), os.path.join(root, 'binary.file') + ) + self.assertEqual( + reader.resource_path('imaginary'), os.path.join(root, 'imaginary') + ) + + def test_files(self): + namespacedata01 = import_module('namespacedata01') + reader = NamespaceReader(namespacedata01.__spec__.submodule_search_locations) + root = os.path.abspath(os.path.join(__file__, '..', 'namespacedata01')) + self.assertIsInstance(reader.files(), MultiplexedPath) + self.assertEqual(repr(reader.files()), f"MultiplexedPath('{root}')") + + +if __name__ == '__main__': + unittest.main() diff --git a/pipenv/vendor/importlib_resources/tests/test_resource.py b/pipenv/vendor/importlib_resources/tests/test_resource.py index 8c5a72cb..071cb8d4 100644 --- a/pipenv/vendor/importlib_resources/tests/test_resource.py +++ b/pipenv/vendor/importlib_resources/tests/test_resource.py @@ -1,11 +1,14 @@ import sys import unittest import importlib_resources as resources +import uuid +import pathlib from . import data01 from . import zipdata01, zipdata02 from . import util from importlib import import_module +from ._compat import import_helper, unlink class ResourceTests: @@ -24,20 +27,21 @@ class ResourceTests: def test_contents(self): contents = set(resources.contents(self.data)) # There may be cruft in the directory listing of the data directory. - # Under Python 3 we could have a __pycache__ directory, and under - # Python 2 we could have .pyc files. These are both artifacts of the - # test suite importing these modules and writing these caches. They - # aren't germane to this test, so just filter them out. + # It could have a __pycache__ directory, + # an artifact of the + # test suite importing these modules, which + # are not germane to this test, so just filter them out. contents.discard('__pycache__') - contents.discard('__init__.pyc') - contents.discard('__init__.pyo') - self.assertEqual(contents, { - '__init__.py', - 'subdirectory', - 'utf-8.file', - 'binary.file', - 'utf-16.file', - }) + self.assertEqual( + sorted(contents), + [ + '__init__.py', + 'binary.file', + 'subdirectory', + 'utf-16.file', + 'utf-8.file', + ], + ) class ResourceDiskTests(ResourceTests, unittest.TestCase): @@ -49,31 +53,29 @@ class ResourceZipTests(ResourceTests, util.ZipSetup, unittest.TestCase): pass -@unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') class ResourceLoaderTests(unittest.TestCase): def test_resource_contents(self): package = util.create_package( - file=data01, path=data01.__file__, contents=['A', 'B', 'C']) - self.assertEqual( - set(resources.contents(package)), - {'A', 'B', 'C'}) + file=data01, path=data01.__file__, contents=['A', 'B', 'C'] + ) + self.assertEqual(set(resources.contents(package)), {'A', 'B', 'C'}) def test_resource_is_resource(self): package = util.create_package( - file=data01, path=data01.__file__, - contents=['A', 'B', 'C', 'D/E', 'D/F']) + file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] + ) self.assertTrue(resources.is_resource(package, 'B')) def test_resource_directory_is_not_resource(self): package = util.create_package( - file=data01, path=data01.__file__, - contents=['A', 'B', 'C', 'D/E', 'D/F']) + file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] + ) self.assertFalse(resources.is_resource(package, 'D')) def test_resource_missing_is_not_resource(self): package = util.create_package( - file=data01, path=data01.__file__, - contents=['A', 'B', 'C', 'D/E', 'D/F']) + file=data01, path=data01.__file__, contents=['A', 'B', 'C', 'D/E', 'D/F'] + ) self.assertFalse(resources.is_resource(package, 'Z')) @@ -84,86 +86,168 @@ class ResourceCornerCaseTests(unittest.TestCase): # 2. Are not on the file system # 3. Are not in a zip file module = util.create_package( - file=data01, path=data01.__file__, contents=['A', 'B', 'C']) + file=data01, path=data01.__file__, contents=['A', 'B', 'C'] + ) # Give the module a dummy loader. module.__loader__ = object() # Give the module a dummy origin. module.__file__ = '/path/which/shall/not/be/named' - if sys.version_info >= (3,): - module.__spec__.loader = module.__loader__ - module.__spec__.origin = module.__file__ + module.__spec__.loader = module.__loader__ + module.__spec__.origin = module.__file__ self.assertFalse(resources.is_resource(module, 'A')) class ResourceFromZipsTest01(util.ZipSetupBase, unittest.TestCase): - ZIP_MODULE = zipdata01 # type: ignore + ZIP_MODULE = zipdata01 # type: ignore def test_is_submodule_resource(self): submodule = import_module('ziptestdata.subdirectory') - self.assertTrue( - resources.is_resource(submodule, 'binary.file')) + self.assertTrue(resources.is_resource(submodule, 'binary.file')) def test_read_submodule_resource_by_name(self): self.assertTrue( - resources.is_resource('ziptestdata.subdirectory', 'binary.file')) + resources.is_resource('ziptestdata.subdirectory', 'binary.file') + ) def test_submodule_contents(self): submodule = import_module('ziptestdata.subdirectory') self.assertEqual( - set(resources.contents(submodule)), - {'__init__.py', 'binary.file'}) + set(resources.contents(submodule)), {'__init__.py', 'binary.file'} + ) def test_submodule_contents_by_name(self): self.assertEqual( set(resources.contents('ziptestdata.subdirectory')), - {'__init__.py', 'binary.file'}) + {'__init__.py', 'binary.file'}, + ) class ResourceFromZipsTest02(util.ZipSetupBase, unittest.TestCase): - ZIP_MODULE = zipdata02 # type: ignore + ZIP_MODULE = zipdata02 # type: ignore def test_unrelated_contents(self): - # https://gitlab.com/python-devs/importlib_resources/issues/44 - # - # Here we have a zip file with two unrelated subpackages. The bug - # reports that getting the contents of a resource returns unrelated - # files. + """ + Test thata zip with two unrelated subpackages return + distinct resources. Ref python/importlib_resources#44. + """ self.assertEqual( - set(resources.contents('ziptestdata.one')), - {'__init__.py', 'resource1.txt'}) + set(resources.contents('ziptestdata.one')), {'__init__.py', 'resource1.txt'} + ) self.assertEqual( - set(resources.contents('ziptestdata.two')), - {'__init__.py', 'resource2.txt'}) + set(resources.contents('ziptestdata.two')), {'__init__.py', 'resource2.txt'} + ) -@unittest.skipIf(sys.version_info < (3,), 'No namespace packages in Python 2') -class NamespaceTest(unittest.TestCase): - def test_namespaces_cannot_have_resources(self): - contents = resources.contents( - 'importlib_resources.tests.data03.namespace') - self.assertFalse(list(contents)) - # Even though there is a file in the namespace directory, it is not - # considered a resource, since namespace packages can't have them. - self.assertFalse(resources.is_resource( - 'importlib_resources.tests.data03.namespace', - 'resource1.txt')) - # We should get an exception if we try to read it or open it. - self.assertRaises( - FileNotFoundError, - resources.open_text, - 'importlib_resources.tests.data03.namespace', 'resource1.txt') - self.assertRaises( - FileNotFoundError, - resources.open_binary, - 'importlib_resources.tests.data03.namespace', 'resource1.txt') - self.assertRaises( - FileNotFoundError, - resources.read_text, - 'importlib_resources.tests.data03.namespace', 'resource1.txt') - self.assertRaises( - FileNotFoundError, - resources.read_binary, - 'importlib_resources.tests.data03.namespace', 'resource1.txt') +class DeletingZipsTest(unittest.TestCase): + """Having accessed resources in a zip file should not keep an open + reference to the zip. + """ + + ZIP_MODULE = zipdata01 + + def setUp(self): + modules = import_helper.modules_setup() + self.addCleanup(import_helper.modules_cleanup, *modules) + + data_path = pathlib.Path(self.ZIP_MODULE.__file__) + data_dir = data_path.parent + self.source_zip_path = data_dir / 'ziptestdata.zip' + self.zip_path = pathlib.Path(f'{uuid.uuid4()}.zip').absolute() + self.zip_path.write_bytes(self.source_zip_path.read_bytes()) + sys.path.append(str(self.zip_path)) + self.data = import_module('ziptestdata') + + def tearDown(self): + try: + sys.path.remove(str(self.zip_path)) + except ValueError: + pass + + try: + del sys.path_importer_cache[str(self.zip_path)] + del sys.modules[self.data.__name__] + except KeyError: + pass + + try: + unlink(self.zip_path) + except OSError: + # If the test fails, this will probably fail too + pass + + def test_contents_does_not_keep_open(self): + c = resources.contents('ziptestdata') + self.zip_path.unlink() + del c + + def test_is_resource_does_not_keep_open(self): + c = resources.is_resource('ziptestdata', 'binary.file') + self.zip_path.unlink() + del c + + def test_is_resource_failure_does_not_keep_open(self): + c = resources.is_resource('ziptestdata', 'not-present') + self.zip_path.unlink() + del c + + @unittest.skip("Desired but not supported.") + def test_path_does_not_keep_open(self): + c = resources.path('ziptestdata', 'binary.file') + self.zip_path.unlink() + del c + + def test_entered_path_does_not_keep_open(self): + # This is what certifi does on import to make its bundle + # available for the process duration. + c = resources.path('ziptestdata', 'binary.file').__enter__() + self.zip_path.unlink() + del c + + def test_read_binary_does_not_keep_open(self): + c = resources.read_binary('ziptestdata', 'binary.file') + self.zip_path.unlink() + del c + + def test_read_text_does_not_keep_open(self): + c = resources.read_text('ziptestdata', 'utf-8.file', encoding='utf-8') + self.zip_path.unlink() + del c + + +class ResourceFromNamespaceTest01(unittest.TestCase): + site_dir = str(pathlib.Path(__file__).parent) + + @classmethod + def setUpClass(cls): + sys.path.append(cls.site_dir) + + @classmethod + def tearDownClass(cls): + sys.path.remove(cls.site_dir) + + def test_is_submodule_resource(self): + self.assertTrue( + resources.is_resource(import_module('namespacedata01'), 'binary.file') + ) + + def test_read_submodule_resource_by_name(self): + self.assertTrue(resources.is_resource('namespacedata01', 'binary.file')) + + def test_submodule_contents(self): + contents = set(resources.contents(import_module('namespacedata01'))) + try: + contents.remove('__pycache__') + except KeyError: + pass + self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) + + def test_submodule_contents_by_name(self): + contents = set(resources.contents('namespacedata01')) + try: + contents.remove('__pycache__') + except KeyError: + pass + self.assertEqual(contents, {'binary.file', 'utf-8.file', 'utf-16.file'}) if __name__ == '__main__': diff --git a/pipenv/vendor/importlib_resources/tests/update-zips.py b/pipenv/vendor/importlib_resources/tests/update-zips.py new file mode 100644 index 00000000..9ef0224c --- /dev/null +++ b/pipenv/vendor/importlib_resources/tests/update-zips.py @@ -0,0 +1,53 @@ +""" +Generate the zip test data files. + +Run to build the tests/zipdataNN/ziptestdata.zip files from +files in tests/dataNN. + +Replaces the file with the working copy, but does commit anything +to the source repo. +""" + +import contextlib +import os +import pathlib +import zipfile + + +def main(): + """ + >>> from unittest import mock + >>> monkeypatch = getfixture('monkeypatch') + >>> monkeypatch.setattr(zipfile, 'ZipFile', mock.MagicMock()) + >>> print(); main() # print workaround for bpo-32509 + + ...data01... -> ziptestdata/... + ... + ...data02... -> ziptestdata/... + ... + """ + suffixes = '01', '02' + tuple(map(generate, suffixes)) + + +def generate(suffix): + root = pathlib.Path(__file__).parent.relative_to(os.getcwd()) + zfpath = root / f'zipdata{suffix}/ziptestdata.zip' + with zipfile.ZipFile(zfpath, 'w') as zf: + for src, rel in walk(root / f'data{suffix}'): + dst = 'ziptestdata' / pathlib.PurePosixPath(rel.as_posix()) + print(src, '->', dst) + zf.write(src, dst) + + +def walk(datapath): + for dirpath, dirnames, filenames in os.walk(datapath): + with contextlib.suppress(KeyError): + dirnames.remove('__pycache__') + for filename in filenames: + res = pathlib.Path(dirpath) / filename + rel = res.relative_to(datapath) + yield res, rel + + +__name__ == '__main__' and main() diff --git a/pipenv/vendor/importlib_resources/tests/util.py b/pipenv/vendor/importlib_resources/tests/util.py index 8c26496d..6ac4332e 100644 --- a/pipenv/vendor/importlib_resources/tests/util.py +++ b/pipenv/vendor/importlib_resources/tests/util.py @@ -3,107 +3,81 @@ import importlib import io import sys import types -import unittest +from pathlib import Path, PurePath from . import data01 from . import zipdata01 -from .._compat import ABC, Path, PurePath, FileNotFoundError from ..abc import ResourceReader - -try: - from test.support import modules_setup, modules_cleanup -except ImportError: - # Python 2.7. - def modules_setup(): - return sys.modules.copy(), - - def modules_cleanup(oldmodules): - # Encoders/decoders are registered permanently within the internal - # codec cache. If we destroy the corresponding modules their - # globals will be set to None which will trip up the cached functions. - encodings = [(k, v) for k, v in sys.modules.items() - if k.startswith('encodings.')] - sys.modules.clear() - sys.modules.update(encodings) - # XXX: This kind of problem can affect more than just encodings. In - # particular extension modules (such as _ssl) don't cope with reloading - # properly. Really, test modules should be cleaning out the test - # specific modules they know they added (ala test_runpy) rather than - # relying on this function (as test_importhooks and test_pkg do - # currently). Implicitly imported *real* modules should be left alone - # (see issue 10556). - sys.modules.update(oldmodules) +from ._compat import import_helper -try: - from importlib.machinery import ModuleSpec -except ImportError: - ModuleSpec = None # type: ignore +from importlib.machinery import ModuleSpec -def create_package(file, path, is_package=True, contents=()): - class Reader(ResourceReader): - def get_resource_reader(self, package): - return self +class Reader(ResourceReader): + def __init__(self, **kwargs): + vars(self).update(kwargs) - def open_resource(self, path): - self._path = path - if isinstance(file, Exception): - raise file - else: - return file + def get_resource_reader(self, package): + return self - def resource_path(self, path_): - self._path = path_ - if isinstance(path, Exception): - raise path - else: - return path + def open_resource(self, path): + self._path = path + if isinstance(self.file, Exception): + raise self.file + return self.file - def is_resource(self, path_): - self._path = path_ - if isinstance(path, Exception): - raise path - for entry in contents: - parts = entry.split('/') - if len(parts) == 1 and parts[0] == path_: - return True - return False + def resource_path(self, path_): + self._path = path_ + if isinstance(self.path, Exception): + raise self.path + return self.path - def contents(self): - if isinstance(path, Exception): - raise path - # There's no yield from in baseball, er, Python 2. - for entry in contents: - yield entry + def is_resource(self, path_): + self._path = path_ + if isinstance(self.path, Exception): + raise self.path + def part(entry): + return entry.split('/') + + return any( + len(parts) == 1 and parts[0] == path_ for parts in map(part, self._contents) + ) + + def contents(self): + if isinstance(self.path, Exception): + raise self.path + yield from self._contents + + +def create_package_from_loader(loader, is_package=True): name = 'testingpackage' - # Unforunately importlib.util.module_from_spec() was not introduced until - # Python 3.5. module = types.ModuleType(name) - if ModuleSpec is None: - # Python 2. - module.__name__ = name - module.__file__ = 'does-not-exist' - if is_package: - module.__path__ = [] - else: - # Python 3. - loader = Reader() - spec = ModuleSpec( - name, loader, - origin='does-not-exist', - is_package=is_package) - module.__spec__ = spec - module.__loader__ = loader + spec = ModuleSpec(name, loader, origin='does-not-exist', is_package=is_package) + module.__spec__ = spec + module.__loader__ = loader return module -class CommonTests(ABC): +def create_package(file=None, path=None, is_package=True, contents=()): + return create_package_from_loader( + Reader(file=file, path=path, _contents=contents), + is_package, + ) + + +class CommonTests(metaclass=abc.ABCMeta): + """ + Tests shared by test_open, test_path, and test_read. + """ @abc.abstractmethod def execute(self, package, path): - raise NotImplementedError + """ + Call the pertinent legacy API function (e.g. open_text, path) + on package and path. + """ def test_package_name(self): # Passing in the package name should succeed. @@ -118,7 +92,6 @@ class CommonTests(ABC): path = 'utf-8.file' self.execute(data01, path) - @unittest.skipIf(sys.version_info < (3, 6), 'requires os.PathLike support') def test_pathlib_path(self): # Passing in a pathlib.PurePath object for the path should succeed. path = PurePath('utf-8.file') @@ -127,7 +100,7 @@ class CommonTests(ABC): def test_absolute_path(self): # An absolute path is a ValueError. path = Path(__file__) - full_path = path.parent/'utf-8.file' + full_path = path.parent / 'utf-8.file' with self.assertRaises(ValueError): self.execute(data01, full_path) @@ -152,24 +125,28 @@ class CommonTests(ABC): module = sys.modules['importlib_resources.tests.util'] self.execute(module, 'utf-8.file') - @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') - def test_resource_opener(self): + def test_missing_path(self): + # Attempting to open or read or request the path for a + # non-existent path should succeed if open_resource + # can return a viable data stream. bytes_data = io.BytesIO(b'Hello, world!') package = create_package(file=bytes_data, path=FileNotFoundError()) self.execute(package, 'utf-8.file') self.assertEqual(package.__loader__._path, 'utf-8.file') - @unittest.skipIf(sys.version_info < (3,), 'No ResourceReader in Python 2') - def test_resource_path(self): + def test_extant_path(self): + # Attempting to open or read or request the path when the + # path does exist should still succeed. Does not assert + # anything about the result. bytes_data = io.BytesIO(b'Hello, world!') + # any path that exists path = __file__ package = create_package(file=bytes_data, path=path) self.execute(package, 'utf-8.file') self.assertEqual(package.__loader__._path, 'utf-8.file') def test_useless_loader(self): - package = create_package(file=FileNotFoundError(), - path=FileNotFoundError()) + package = create_package(file=FileNotFoundError(), path=FileNotFoundError()) with self.assertRaises(FileNotFoundError): self.execute(package, 'utf-8.file') @@ -205,9 +182,9 @@ class ZipSetupBase: pass def setUp(self): - modules = modules_setup() - self.addCleanup(modules_cleanup, *modules) + modules = import_helper.modules_setup() + self.addCleanup(import_helper.modules_cleanup, *modules) class ZipSetup(ZipSetupBase): - ZIP_MODULE = zipdata01 # type: ignore + ZIP_MODULE = zipdata01 # type: ignore diff --git a/pipenv/vendor/importlib_resources/tests/zipdata01/ziptestdata.zip b/pipenv/vendor/importlib_resources/tests/zipdata01/ziptestdata.zip index ddcccfb37368b3d80af8a5f5ebdd04c2a887c8c0..9a3bb0739f87e97c1084b94d7d153680f6727738 100644 GIT binary patch delta 266 zcmaFE_J)lwz?+#xgaHJcH>U+owa2SPWzY6fBv{%cL%gVmMGn93~B< zmrM?1(tuc0%Ot_LWb!m74S948D##id#V6}C%K+WSJ2{_;3v9S>+s3kOmz1ZWaIMqz|BszK;s4KsL2<9jRy!Q2E6`2cTLHjr{wAk1ZCU@!+_ G1_l6Bc%f?m literal 698 zcmWIWW@Zs#0D&?E(z02lENC@Ig!?SR;Polaa10BMBT zX9RKpPypEhj7%cTxC0L88!*_?2%>NXBW^=L0SN= (3, 2, 0): diff --git a/pipenv/vendor/iso8601/iso8601.pyi b/pipenv/vendor/iso8601/iso8601.pyi new file mode 100644 index 00000000..ba5fe398 --- /dev/null +++ b/pipenv/vendor/iso8601/iso8601.pyi @@ -0,0 +1,67 @@ +import datetime +import sys +from typing import Any, Mapping, Optional, Pattern, TypeVar + + +__all__ = ["parse_date", "ParseError", "UTC", "FixedOffset"] + + +if sys.version_info >= (3, 0, 0): + basestring = str + +if sys.version_info >= (3, 2): + UTC: datetime.timezone = ... + + def FixedOffset( + offset_hours: float, offset_minutes: float, name: str + ) -> datetime.timezone: + ... + + +else: + ZERO: datetime.timedelta = ... + + class Utc(datetime.tzinfo): + ... + + UTC: Utc = ... + + class FixedOffset(datetime.tzinfo): + def __init__( + self, offset_hours: float, offset_minutes: float, name: str + ) -> None: + ... + + +ISO8601_REGEX: Pattern[basestring] = ... + + +class ParseError(ValueError): + + ... + + +_T = TypeVar("_T") + + +def to_int( + d: Mapping[_T, Any], + key: _T, + default_to_zero: bool = ..., + default: Any = ..., + required: bool = ..., +) -> int: + ... + + +def parse_timezone( + matches: Mapping[basestring, basestring], + default_timezone: Optional[datetime.tzinfo] = ..., +) -> datetime.tzinfo: + ... + + +def parse_date( + datestring: basestring, default_timezone: Optional[datetime.tzinfo] = ... +) -> datetime.datetime: + ... diff --git a/pipenv/vendor/jinja2/__init__.py b/pipenv/vendor/jinja2/__init__.py index 1229ba42..a833c120 100644 --- a/pipenv/vendor/jinja2/__init__.py +++ b/pipenv/vendor/jinja2/__init__.py @@ -1,44 +1,45 @@ -# -*- 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 .bccache import BytecodeCache as BytecodeCache +from .bccache import FileSystemBytecodeCache as FileSystemBytecodeCache +from .bccache import MemcachedBytecodeCache as MemcachedBytecodeCache +from .environment import Environment as Environment +from .environment import Template as Template +from .exceptions import TemplateAssertionError as TemplateAssertionError +from .exceptions import TemplateError as TemplateError +from .exceptions import TemplateNotFound as TemplateNotFound +from .exceptions import TemplateRuntimeError as TemplateRuntimeError +from .exceptions import TemplatesNotFound as TemplatesNotFound +from .exceptions import TemplateSyntaxError as TemplateSyntaxError +from .exceptions import UndefinedError as 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 .loaders import BaseLoader as BaseLoader +from .loaders import ChoiceLoader as ChoiceLoader +from .loaders import DictLoader as DictLoader +from .loaders import FileSystemLoader as FileSystemLoader +from .loaders import FunctionLoader as FunctionLoader +from .loaders import ModuleLoader as ModuleLoader +from .loaders import PackageLoader as PackageLoader +from .loaders import PrefixLoader as PrefixLoader +from .runtime import ChainableUndefined as ChainableUndefined +from .runtime import DebugUndefined as DebugUndefined +from .runtime import make_logging_undefined as make_logging_undefined +from .runtime import StrictUndefined as StrictUndefined +from .runtime import Undefined as Undefined +from .utils import clear_caches as clear_caches from .utils import contextfunction from .utils import environmentfunction +from .utils import escape from .utils import evalcontextfunction -from .utils import is_undefined -from .utils import select_autoescape +from .utils import is_undefined as is_undefined +from .utils import Markup +from .utils import pass_context as pass_context +from .utils import pass_environment as pass_environment +from .utils import pass_eval_context as pass_eval_context +from .utils import select_autoescape as select_autoescape -__version__ = "2.11.2" +__version__ = "3.0.1" diff --git a/pipenv/vendor/jinja2/_compat.py b/pipenv/vendor/jinja2/_compat.py deleted file mode 100644 index 1f044954..00000000 --- a/pipenv/vendor/jinja2/_compat.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- 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/pipenv/vendor/jinja2/async_utils.py b/pipenv/vendor/jinja2/async_utils.py new file mode 100644 index 00000000..cedd7ba8 --- /dev/null +++ b/pipenv/vendor/jinja2/async_utils.py @@ -0,0 +1,68 @@ +import inspect +import typing as t +from functools import wraps + +from .utils import _PassArg +from .utils import pass_eval_context + +V = t.TypeVar("V") + + +def async_variant(normal_func): # type: ignore + def decorator(async_func): # type: ignore + pass_arg = _PassArg.from_obj(normal_func) + need_eval_context = pass_arg is None + + if pass_arg is _PassArg.environment: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].is_async) + + else: + + def is_async(args: t.Any) -> bool: + return t.cast(bool, args[0].environment.is_async) + + @wraps(normal_func) + def wrapper(*args, **kwargs): # type: ignore + b = is_async(args) + + if need_eval_context: + args = args[1:] + + if b: + return async_func(*args, **kwargs) + + return normal_func(*args, **kwargs) + + if need_eval_context: + wrapper = pass_eval_context(wrapper) + + wrapper.jinja_async_variant = True + return wrapper + + return decorator + + +async def auto_await(value: t.Union[t.Awaitable["V"], "V"]) -> "V": + if inspect.isawaitable(value): + return await t.cast("t.Awaitable[V]", value) + + return t.cast("V", value) + + +async def auto_aiter( + iterable: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> "t.AsyncIterator[V]": + if hasattr(iterable, "__aiter__"): + async for item in t.cast("t.AsyncIterable[V]", iterable): + yield item + else: + for item in t.cast("t.Iterable[V]", iterable): + yield item + + +async def auto_to_list( + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", +) -> t.List["V"]: + return [x async for x in auto_aiter(value)] diff --git a/pipenv/vendor/jinja2/asyncfilters.py b/pipenv/vendor/jinja2/asyncfilters.py deleted file mode 100644 index 3d98dbcc..00000000 --- a/pipenv/vendor/jinja2/asyncfilters.py +++ /dev/null @@ -1,158 +0,0 @@ -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/pipenv/vendor/jinja2/asyncsupport.py b/pipenv/vendor/jinja2/asyncsupport.py deleted file mode 100644 index 78ba3739..00000000 --- a/pipenv/vendor/jinja2/asyncsupport.py +++ /dev/null @@ -1,264 +0,0 @@ -# -*- 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/pipenv/vendor/jinja2/bccache.py b/pipenv/vendor/jinja2/bccache.py index 9c066103..ee210ef0 100644 --- a/pipenv/vendor/jinja2/bccache.py +++ b/pipenv/vendor/jinja2/bccache.py @@ -1,4 +1,3 @@ -# -*- 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. @@ -8,22 +7,30 @@ are initialized on the first request. """ import errno import fnmatch +import marshal import os +import pickle import stat import sys import tempfile +import typing as t from hashlib import sha1 -from os import listdir -from os import path +from io import BytesIO +from types import CodeType -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 +if t.TYPE_CHECKING: + import typing_extensions as te + from .environment import Environment -bc_version = 4 + class _MemcachedClient(te.Protocol): + def get(self, key: str) -> bytes: + ... + + def set(self, key: str, value: bytes, timeout: t.Optional[int] = None) -> None: + ... + + +bc_version = 5 # 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. @@ -34,7 +41,7 @@ bc_magic = ( ) -class Bucket(object): +class Bucket: """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. @@ -43,17 +50,17 @@ class Bucket(object): cache subclasses don't have to care about cache invalidation. """ - def __init__(self, environment, key, checksum): + def __init__(self, environment: "Environment", key: str, checksum: str) -> None: self.environment = environment self.key = key self.checksum = checksum self.reset() - def reset(self): + def reset(self) -> None: """Resets the bucket (unloads the bytecode).""" - self.code = None + self.code: t.Optional[CodeType] = None - def load_bytecode(self, f): + def load_bytecode(self, f: t.BinaryIO) -> None: """Loads bytecode from a file or file like object.""" # make sure the magic header is correct magic = f.read(len(bc_magic)) @@ -67,31 +74,31 @@ class Bucket(object): return # if marshal_load fails then we need to reload try: - self.code = marshal_load(f) + self.code = marshal.load(f) except (EOFError, ValueError, TypeError): self.reset() return - def write_bytecode(self, f): + def write_bytecode(self, f: t.BinaryIO) -> None: """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) + marshal.dump(self.code, f) - def bytecode_from_string(self, string): - """Load bytecode from a string.""" + def bytecode_from_string(self, string: bytes) -> None: + """Load bytecode from bytes.""" self.load_bytecode(BytesIO(string)) - def bytecode_to_string(self): - """Return the bytecode as string.""" + def bytecode_to_string(self) -> bytes: + """Return the bytecode as bytes.""" out = BytesIO() self.write_bytecode(out) return out.getvalue() -class BytecodeCache(object): +class BytecodeCache: """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`. @@ -120,41 +127,48 @@ class BytecodeCache(object): Jinja. """ - def load_bytecode(self, bucket): + def load_bytecode(self, bucket: Bucket) -> None: """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): + def dump_bytecode(self, bucket: Bucket) -> None: """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): + def clear(self) -> None: """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): + def get_cache_key( + self, name: str, filename: t.Optional[t.Union[str]] = None + ) -> str: """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) + hash.update(f"|{filename}".encode("utf-8")) + return hash.hexdigest() - def get_source_checksum(self, source): + def get_source_checksum(self, source: str) -> str: """Returns a checksum for the source.""" return sha1(source.encode("utf-8")).hexdigest() - def get_bucket(self, environment, name, filename, source): + def get_bucket( + self, + environment: "Environment", + name: str, + filename: t.Optional[str], + source: str, + ) -> Bucket: """Return a cache bucket for the given template. All arguments are mandatory but filename may be `None`. """ @@ -164,7 +178,7 @@ class BytecodeCache(object): self.load_bytecode(bucket) return bucket - def set_bucket(self, bucket): + def set_bucket(self, bucket: Bucket) -> None: """Put the bucket into the cache.""" self.dump_bytecode(bucket) @@ -187,14 +201,16 @@ class FileSystemBytecodeCache(BytecodeCache): This bytecode cache supports clearing of the cache using the clear method. """ - def __init__(self, directory=None, pattern="__jinja2_%s.cache"): + def __init__( + self, directory: t.Optional[str] = None, pattern: str = "__jinja2_%s.cache" + ) -> None: 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(): + def _get_default_cache_dir(self) -> str: + def _unsafe_dir() -> "te.NoReturn": raise RuntimeError( "Cannot determine safe temp directory. You " "need to explicitly provide one." @@ -209,7 +225,7 @@ class FileSystemBytecodeCache(BytecodeCache): if not hasattr(os, "getuid"): _unsafe_dir() - dirname = "_jinja2-cache-%d" % os.getuid() + dirname = f"_jinja2-cache-{os.getuid()}" actual_dir = os.path.join(tmpdir, dirname) try: @@ -240,34 +256,30 @@ class FileSystemBytecodeCache(BytecodeCache): return actual_dir - def _get_cache_filename(self, bucket): - return path.join(self.directory, self.pattern % bucket.key) + def _get_cache_filename(self, bucket: Bucket) -> str: + return os.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: + def load_bytecode(self, bucket: Bucket) -> None: + filename = self._get_cache_filename(bucket) + + if os.path.exists(filename): + with open(filename, "rb") as f: bucket.load_bytecode(f) - finally: - f.close() - def dump_bytecode(self, bucket): - f = open(self._get_cache_filename(bucket), "wb") - try: + def dump_bytecode(self, bucket: Bucket) -> None: + with open(self._get_cache_filename(bucket), "wb") as f: bucket.write_bytecode(f) - finally: - f.close() - def clear(self): + def clear(self) -> None: # 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 % "*") + files = fnmatch.filter(os.listdir(self.directory), self.pattern % ("*",)) for filename in files: try: - remove(path.join(self.directory, filename)) + remove(os.path.join(self.directory, filename)) except OSError: pass @@ -284,7 +296,7 @@ class MemcachedBytecodeCache(BytecodeCache): - `python-memcached `_ (Unfortunately the django cache interface is not compatible because it - does not support storing binary data, only unicode. You can however pass + does not support storing binary data, only text. You can however pass the underlying cache client to the bytecode cache which is available as `django.core.cache.cache._client`.) @@ -319,32 +331,34 @@ class MemcachedBytecodeCache(BytecodeCache): def __init__( self, - client, - prefix="jinja2/bytecode/", - timeout=None, - ignore_memcache_errors=True, + client: "_MemcachedClient", + prefix: str = "jinja2/bytecode/", + timeout: t.Optional[int] = None, + ignore_memcache_errors: bool = True, ): self.client = client self.prefix = prefix self.timeout = timeout self.ignore_memcache_errors = ignore_memcache_errors - def load_bytecode(self, bucket): + def load_bytecode(self, bucket: Bucket) -> None: 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: + else: 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,) + def dump_bytecode(self, bucket: Bucket) -> None: + key = self.prefix + bucket.key + value = bucket.bytecode_to_string() + try: - self.client.set(*args) + if self.timeout is not None: + self.client.set(key, value, self.timeout) + else: + self.client.set(key, value) except Exception: if not self.ignore_memcache_errors: raise diff --git a/pipenv/vendor/jinja2/compiler.py b/pipenv/vendor/jinja2/compiler.py index 63297b42..ef4c0a1f 100644 --- a/pipenv/vendor/jinja2/compiler.py +++ b/pipenv/vendor/jinja2/compiler.py @@ -1,7 +1,8 @@ -# -*- coding: utf-8 -*- """Compiles nodes from the parser into Python code.""" -from collections import namedtuple +import typing as t +from contextlib import contextmanager from functools import update_wrapper +from io import StringIO from itertools import chain from keyword import iskeyword as is_python_keyword @@ -9,13 +10,6 @@ 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 @@ -24,9 +18,16 @@ from .idtracking import VAR_LOAD_RESOLVE from .idtracking import VAR_LOAD_UNDEFINED from .nodes import EvalContext from .optimizer import Optimizer +from .utils import _PassArg from .utils import concat from .visitor import NodeVisitor +if t.TYPE_CHECKING: + import typing_extensions as te + from .environment import Environment + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + operators = { "eq": "==", "ne": "!=", @@ -38,79 +39,109 @@ operators = { "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): +def optimizeconst(f: F) -> F: + def new_func( + self: "CodeGenerator", node: nodes.Expr, frame: "Frame", **kwargs: t.Any + ) -> t.Any: # Only optimize if the frame is not volatile - if self.optimized and not frame.eval_ctx.volatile: + if self.optimizer is not None 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) + return update_wrapper(t.cast(F, new_func), f) + + +def _make_binop(op: str) -> t.Callable[["CodeGenerator", nodes.BinExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.BinExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed + and op in self.environment.intercepted_binops # type: ignore + ): + self.write(f"environment.call_binop(context, {op!r}, ") + self.visit(node.left, frame) + self.write(", ") + self.visit(node.right, frame) + else: + self.write("(") + self.visit(node.left, frame) + self.write(f" {op} ") + self.visit(node.right, frame) + + self.write(")") + + return visitor + + +def _make_unop( + op: str, +) -> t.Callable[["CodeGenerator", nodes.UnaryExpr, "Frame"], None]: + @optimizeconst + def visitor(self: "CodeGenerator", node: nodes.UnaryExpr, frame: Frame) -> None: + if ( + self.environment.sandboxed + and op in self.environment.intercepted_unops # type: ignore + ): + self.write(f"environment.call_unop(context, {op!r}, ") + self.visit(node.node, frame) + else: + self.write("(" + op) + self.visit(node.node, frame) + + self.write(")") + + return visitor def generate( - node, environment, name, filename, stream=None, defer_init=False, optimized=True -): + node: nodes.Template, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, +) -> t.Optional[str]: """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() + return generator.stream.getvalue() # type: ignore + + return None -def has_safe_repr(value): +def has_safe_repr(value: t.Any) -> bool: """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 + + if type(value) in {bool, int, float, complex, range, str, Markup}: return True + + if type(value) in {tuple, list, set, frozenset}: + return all(has_safe_repr(v) for v in value) + + if type(value) is dict: + return all(has_safe_repr(k) and has_safe_repr(v) for k, v in value.items()) + return False -def find_undeclared(nodes, names): +def find_undeclared( + nodes: t.Iterable[nodes.Node], names: t.Iterable[str] +) -> t.Set[str]: """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. """ @@ -123,20 +154,49 @@ def find_undeclared(nodes, names): return visitor.undeclared -class MacroRef(object): - def __init__(self, node): +class MacroRef: + def __init__(self, node: t.Union[nodes.Macro, nodes.CallBlock]) -> None: self.node = node self.accesses_caller = False self.accesses_kwargs = False self.accesses_varargs = False -class Frame(object): +class Frame: """Holds compile time information for us.""" - def __init__(self, eval_ctx, parent=None, level=None): + def __init__( + self, + eval_ctx: EvalContext, + parent: t.Optional["Frame"] = None, + level: t.Optional[int] = None, + ) -> None: self.eval_ctx = eval_ctx - self.symbols = Symbols(parent and parent.symbols or None, level=level) + + # the parent of this frame + self.parent = parent + + if parent is None: + self.symbols = Symbols(level=level) + + # in some dynamic inheritance situations the compiler needs to add + # write tests around output statements. + self.require_output_check = False + + # 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: t.Optional[str] = None + + # the name of the block we're in, otherwise None. + self.block: t.Optional[str] = None + + else: + self.symbols = Symbols(parent.symbols, level=level) + self.require_output_check = parent.require_output_check + self.buffer = parent.buffer + self.block = parent.block # a toplevel frame is the root + soft frames such as if conditions. self.toplevel = False @@ -146,47 +206,40 @@ class Frame(object): # 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 + # variables set inside of loops and blocks should not affect outer frames, + # but they still needs to be kept track of as part of the active context. + self.loop_frame = False + self.block_frame = False - # 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 + # track whether the frame is being used in an if-statement or conditional + # expression as it determines which errors should be raised during runtime + # or compile time. + self.soft_frame = False - # 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): + def copy(self) -> "Frame": """Create a copy of the current one.""" - rv = object.__new__(self.__class__) + rv = t.cast(Frame, object.__new__(self.__class__)) rv.__dict__.update(self.__dict__) rv.symbols = self.symbols.copy() return rv - def inner(self, isolated=False): + def inner(self, isolated: bool = False) -> "Frame": """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): + def soft(self) -> "Frame": """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. + This is only used to implement if-statements and conditional + expressions. """ rv = self.copy() rv.rootlevel = False + rv.soft_frame = True return rv __copy__ = copy @@ -199,19 +252,19 @@ class VisitorExit(RuntimeError): class DependencyFinderVisitor(NodeVisitor): """A visitor that collects filter and test calls.""" - def __init__(self): - self.filters = set() - self.tests = set() + def __init__(self) -> None: + self.filters: t.Set[str] = set() + self.tests: t.Set[str] = set() - def visit_Filter(self, node): + def visit_Filter(self, node: nodes.Filter) -> None: self.generic_visit(node) self.filters.add(node.name) - def visit_Test(self, node): + def visit_Test(self, node: nodes.Test) -> None: self.generic_visit(node) self.tests.add(node.name) - def visit_Block(self, node): + def visit_Block(self, node: nodes.Block) -> None: """Stop visiting at blocks.""" @@ -221,11 +274,11 @@ class UndeclaredNameVisitor(NodeVisitor): not stop at closure frames. """ - def __init__(self, names): + def __init__(self, names: t.Iterable[str]) -> None: self.names = set(names) - self.undeclared = set() + self.undeclared: t.Set[str] = set() - def visit_Name(self, node): + def visit_Name(self, node: nodes.Name) -> None: if node.ctx == "load" and node.name in self.names: self.undeclared.add(node.name) if self.undeclared == self.names: @@ -233,7 +286,7 @@ class UndeclaredNameVisitor(NodeVisitor): else: self.names.discard(node.name) - def visit_Block(self, node): + def visit_Block(self, node: nodes.Block) -> None: """Stop visiting a blocks.""" @@ -246,26 +299,33 @@ class CompilerExit(Exception): class CodeGenerator(NodeVisitor): def __init__( - self, environment, name, filename, stream=None, defer_init=False, optimized=True - ): + self, + environment: "Environment", + name: t.Optional[str], + filename: t.Optional[str], + stream: t.Optional[t.TextIO] = None, + defer_init: bool = False, + optimized: bool = True, + ) -> None: if stream is None: - stream = NativeStringIO() + stream = StringIO() 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 + self.optimizer: t.Optional[Optimizer] = None + if optimized: self.optimizer = Optimizer(environment) # aliases for imports - self.import_aliases = {} + self.import_aliases: t.Dict[str, str] = {} # a registry for all blocks. Because blocks are moved out # into the global python scope they are registered here - self.blocks = {} + self.blocks: t.Dict[str, nodes.Block] = {} # the number of extends statements so far self.extends_so_far = 0 @@ -279,12 +339,12 @@ class CodeGenerator(NodeVisitor): self.code_lineno = 1 # registry of all filters and tests (global, not block local) - self.tests = {} - self.filters = {} + self.tests: t.Dict[str, str] = {} + self.filters: t.Dict[str, str] = {} # the debug information - self.debug_info = [] - self._write_debug_info = None + self.debug_info: t.List[t.Tuple[int, int]] = [] + self._write_debug_info: t.Optional[int] = None # the number of new lines before the next write() self._new_lines = 0 @@ -303,75 +363,83 @@ class CodeGenerator(NodeVisitor): self._indentation = 0 # Tracks toplevel assignments - self._assign_stack = [] + self._assign_stack: t.List[t.Set[str]] = [] # Tracks parameter definition blocks - self._param_def_block = [] + self._param_def_block: t.List[t.Set[str]] = [] # Tracks the current context. self._context_reference_stack = ["context"] + @property + def optimized(self) -> bool: + return self.optimizer is not None + # -- Various compilation helpers - def fail(self, msg, lineno): + def fail(self, msg: str, lineno: int) -> "te.NoReturn": """Fail with a :exc:`TemplateAssertionError`.""" raise TemplateAssertionError(msg, lineno, self.name, self.filename) - def temporary_identifier(self): + def temporary_identifier(self) -> str: """Get a new unique identifier.""" self._last_identifier += 1 - return "t_%d" % self._last_identifier + return f"t_{self._last_identifier}" - def buffer(self, frame): + def buffer(self, frame: Frame) -> None: """Enable buffering for the frame from that point onwards.""" frame.buffer = self.temporary_identifier() - self.writeline("%s = []" % frame.buffer) + self.writeline(f"{frame.buffer} = []") - def return_buffer_contents(self, frame, force_unescaped=False): + def return_buffer_contents( + self, frame: Frame, force_unescaped: bool = False + ) -> None: """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.writeline(f"return Markup(concat({frame.buffer}))") self.outdent() self.writeline("else:") self.indent() - self.writeline("return concat(%s)" % frame.buffer) + self.writeline(f"return concat({frame.buffer})") self.outdent() return elif frame.eval_ctx.autoescape: - self.writeline("return Markup(concat(%s))" % frame.buffer) + self.writeline(f"return Markup(concat({frame.buffer}))") return - self.writeline("return concat(%s)" % frame.buffer) + self.writeline(f"return concat({frame.buffer})") - def indent(self): + def indent(self) -> None: """Indent by one.""" self._indentation += 1 - def outdent(self, step=1): + def outdent(self, step: int = 1) -> None: """Outdent by step.""" self._indentation -= step - def start_write(self, frame, node=None): + def start_write(self, frame: Frame, node: t.Optional[nodes.Node] = None) -> 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) + self.writeline(f"{frame.buffer}.append(", node) - def end_write(self, frame): + def end_write(self, frame: Frame) -> None: """End the writing process started by `start_write`.""" if frame.buffer is not None: self.write(")") - def simple_write(self, s, frame, node=None): + def simple_write( + self, s: str, frame: Frame, node: t.Optional[nodes.Node] = None + ) -> 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): + def blockvisit(self, nodes: t.Iterable[nodes.Node], frame: Frame) -> None: """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. """ @@ -382,7 +450,7 @@ class CodeGenerator(NodeVisitor): except CompilerExit: pass - def write(self, x): + def write(self, x: str) -> None: """Write a string into the output stream.""" if self._new_lines: if not self._first_write: @@ -396,19 +464,26 @@ class CodeGenerator(NodeVisitor): self._new_lines = 0 self.stream.write(x) - def writeline(self, x, node=None, extra=0): + def writeline( + self, x: str, node: t.Optional[nodes.Node] = None, extra: int = 0 + ) -> None: """Combination of newline and write.""" self.newline(node, extra) self.write(x) - def newline(self, node=None, extra=0): + def newline(self, node: t.Optional[nodes.Node] = None, extra: int = 0) -> None: """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): + def signature( + self, + node: t.Union[nodes.Call, nodes.Filter, nodes.Test], + frame: Frame, + extra_kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + ) -> 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 @@ -417,11 +492,10 @@ class CodeGenerator(NodeVisitor): """ # 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 + kwarg_workaround = any( + is_python_keyword(t.cast(str, k)) + for k in chain((x.key for x in node.kwargs), extra_kwargs or ()) + ) for arg in node.args: self.write(", ") @@ -432,8 +506,8 @@ class CodeGenerator(NodeVisitor): 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)) + for key, value in extra_kwargs.items(): + self.write(f", {key}={value}") if node.dyn_args: self.write(", *") self.visit(node.dyn_args, frame) @@ -444,12 +518,12 @@ class CodeGenerator(NodeVisitor): else: self.write(", **{") for kwarg in node.kwargs: - self.write("%r: " % kwarg.key) + self.write(f"{kwarg.key!r}: ") 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)) + for key, value in extra_kwargs.items(): + self.write(f"{key!r}: {value}, ") if node.dyn_kwargs is not None: self.write("}, **") self.visit(node.dyn_kwargs, frame) @@ -461,50 +535,82 @@ class CodeGenerator(NodeVisitor): self.write(", **") self.visit(node.dyn_kwargs, frame) - def pull_dependencies(self, nodes): - """Pull all the dependencies.""" + def pull_dependencies(self, nodes: t.Iterable[nodes.Node]) -> None: + """Find all filter and test names used in the template and + assign them to variables in the compiled namespace. Checking + that the names are registered with the environment is done when + compiling the Filter and Test nodes. If the node is in an If or + CondExpr node, the check is done at runtime instead. + + .. versionchanged:: 3.0 + Filters and tests in If and CondExpr nodes are checked at + runtime instead of compile time. + """ 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): + for id_map, names, dependency in (self.filters, visitor.filters, "filters"), ( + self.tests, + visitor.tests, + "tests", + ): + for name in names: + if name not in id_map: + id_map[name] = self.temporary_identifier() + + # add check during runtime that dependencies used inside of executed + # blocks are defined, as this step may be skipped during compile time + self.writeline("try:") + self.indent() + self.writeline(f"{id_map[name]} = environment.{dependency}[{name!r}]") + self.outdent() + self.writeline("except KeyError:") + self.indent() + self.writeline("@internalcode") + self.writeline(f"def {id_map[name]}(*unused):") + self.indent() + self.writeline( + f'raise TemplateRuntimeError("No {dependency[:-1]}' + f' named {name!r} found.")' + ) + self.outdent() + self.outdent() + + def enter_frame(self, frame: Frame) -> None: undefs = [] - for target, (action, param) in iteritems(frame.symbols.loads): + for target, (action, param) in frame.symbols.loads.items(): if action == VAR_LOAD_PARAMETER: pass elif action == VAR_LOAD_RESOLVE: - self.writeline("%s = %s(%r)" % (target, self.get_resolve_func(), param)) + self.writeline(f"{target} = {self.get_resolve_func()}({param!r})") elif action == VAR_LOAD_ALIAS: - self.writeline("%s = %s" % (target, param)) + self.writeline(f"{target} = {param}") elif action == VAR_LOAD_UNDEFINED: undefs.append(target) else: raise NotImplementedError("unknown load instruction") if undefs: - self.writeline("%s = missing" % " = ".join(undefs)) + self.writeline(f"{' = '.join(undefs)} = missing") - def leave_frame(self, frame, with_python_scope=False): + def leave_frame(self, frame: Frame, with_python_scope: bool = False) -> None: if not with_python_scope: undefs = [] - for target, _ in iteritems(frame.symbols.loads): + for target in frame.symbols.loads: undefs.append(target) if undefs: - self.writeline("%s = missing" % " = ".join(undefs)) + self.writeline(f"{' = '.join(undefs)} = missing") - def func(self, name): - if self.environment.is_async: - return "async def %s" % name - return "def %s" % name + def choose_async(self, async_value: str = "async ", sync_value: str = "") -> str: + return async_value if self.environment.is_async else sync_value - def macro_body(self, node, frame): + def func(self, name: str) -> str: + return f"{self.choose_async()}def {name}" + + def macro_body( + self, node: t.Union[nodes.Macro, nodes.CallBlock], frame: Frame + ) -> t.Tuple[Frame, MacroRef]: """Dump the function def of a macro or call block.""" frame = frame.inner() frame.symbols.analyze_node(node) @@ -513,6 +619,7 @@ class CodeGenerator(NodeVisitor): explicit_caller = None skip_special_params = set() args = [] + for idx, arg in enumerate(node.args): if arg.name == "caller": explicit_caller = idx @@ -552,7 +659,7 @@ class CodeGenerator(NodeVisitor): # 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.writeline(f"{self.func('macro')}({', '.join(args)}):", node) self.indent() self.buffer(frame) @@ -561,17 +668,17 @@ class CodeGenerator(NodeVisitor): 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.writeline(f"if {ref} is missing:") 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) + f'{ref} = undefined("parameter {arg.name!r} was not provided",' + f" name={arg.name!r})" ) else: - self.writeline("%s = " % ref) + self.writeline(f"{ref} = ") self.visit(default, frame) self.mark_parameter_stored(ref) self.outdent() @@ -584,38 +691,33 @@ class CodeGenerator(NodeVisitor): return frame, macro_ref - def macro_def(self, macro_ref, frame): + def macro_def(self, macro_ref: MacroRef, frame: Frame) -> None: """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, - ) + f"Macro(environment, macro, {name!r}, ({arg_tuple})," + f" {macro_ref.accesses_kwargs!r}, {macro_ref.accesses_varargs!r}," + f" {macro_ref.accesses_caller!r}, context.eval_ctx.autoescape)" ) - def position(self, node): + def position(self, node: nodes.Node) -> str: """Return a human readable position for the node.""" - rv = "line %d" % node.lineno + rv = f"line {node.lineno}" if self.name is not None: - rv += " in " + repr(self.name) + rv = f"{rv} in {self.name!r}" 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 dump_local_context(self, frame: Frame) -> str: + items_kv = ", ".join( + f"{name!r}: {target}" + for name, target in frame.symbols.dump_stores().items() ) + return f"{{{items_kv}}}" - def write_commons(self): + def write_commons(self) -> None: """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. @@ -627,7 +729,7 @@ class CodeGenerator(NodeVisitor): self.writeline("cond_expr_undefined = Undefined") self.writeline("if 0: yield None") - def push_parameter_definitions(self, frame): + def push_parameter_definitions(self, frame: Frame) -> None: """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 @@ -636,97 +738,109 @@ class CodeGenerator(NodeVisitor): """ self._param_def_block.append(frame.symbols.dump_param_targets()) - def pop_parameter_definitions(self): + def pop_parameter_definitions(self) -> None: """Pops the current parameter definitions set.""" self._param_def_block.pop() - def mark_parameter_stored(self, target): + def mark_parameter_stored(self, target: str) -> None: """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): + def push_context_reference(self, target: str) -> None: self._context_reference_stack.append(target) - def pop_context_reference(self): + def pop_context_reference(self) -> None: self._context_reference_stack.pop() - def get_context_ref(self): + def get_context_ref(self) -> str: return self._context_reference_stack[-1] - def get_resolve_func(self): + def get_resolve_func(self) -> str: target = self._context_reference_stack[-1] if target == "context": return "resolve" - return "%s.resolve" % target + return f"{target}.resolve" - def derive_context(self, frame): - return "%s.derived(%s)" % ( - self.get_context_ref(), - self.dump_local_context(frame), - ) + def derive_context(self, frame: Frame) -> str: + return f"{self.get_context_ref()}.derived({self.dump_local_context(frame)})" - def parameter_is_undeclared(self, target): + def parameter_is_undeclared(self, target: str) -> bool: """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): + def push_assign_tracking(self) -> None: """Pushes a new layer for assignment tracking.""" self._assign_stack.append(set()) - def pop_assign_tracking(self, frame): + def pop_assign_tracking(self, frame: Frame) -> None: """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: + if ( + not frame.block_frame + and not frame.loop_frame + and 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)) + if frame.loop_frame: + self.writeline(f"_loop_vars[{name!r}] = {ref}") + return + if frame.block_frame: + self.writeline(f"_block_vars[{name!r}] = {ref}") + return + self.writeline(f"context.vars[{name!r}] = {ref}") else: - self.writeline("context.vars.update({") + if frame.loop_frame: + self.writeline("_loop_vars.update({") + elif frame.block_frame: + self.writeline("_block_vars.update({") + 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(f"{name!r}: {ref}") self.write("})") - if public_names: + if not frame.block_frame and not frame.loop_frame and public_names: if len(public_names) == 1: - self.writeline("context.exported_vars.add(%r)" % public_names[0]) + self.writeline(f"context.exported_vars.add({public_names[0]!r})") else: - self.writeline( - "context.exported_vars.update((%s))" - % ", ".join(imap(repr, public_names)) - ) + names_str = ", ".join(map(repr, public_names)) + self.writeline(f"context.exported_vars.update(({names_str}))") # -- Statement Visitors - def visit_Template(self, node, frame=None): + def visit_Template( + self, node: nodes.Template, frame: t.Optional[Frame] = None + ) -> 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)) + from .runtime import exported, async_exported if self.environment.is_async: - self.writeline( - "from jinja2.asyncsupport import auto_await, " - "auto_aiter, AsyncLoopContext" - ) + exported_names = sorted(exported + async_exported) + else: + exported_names = sorted(exported) + + self.writeline("from __future__ import generator_stop") # Python < 3.7 + self.writeline("from jinja2.runtime import " + ", ".join(exported_names)) # if we want a deferred initialization we cannot move the # environment into a local name - envenv = not self.defer_init and ", environment=environment" or "" + envenv = "" if self.defer_init else ", environment=environment" # do we have an extends tag at all? If not, we can save some # overhead by just not processing any inheritance code. @@ -735,7 +849,7 @@ class CodeGenerator(NodeVisitor): # 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.fail(f"block {block.name!r} defined twice", block.lineno) self.blocks[block.name] = block # find all imports and import them @@ -745,16 +859,16 @@ class CodeGenerator(NodeVisitor): 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)) + self.writeline(f"from {module} import {obj} as {alias}") else: - self.writeline("import %s as %s" % (imp, alias)) + self.writeline(f"import {imp} as {alias}") # add the load name - self.writeline("name = %r" % self.name) + self.writeline(f"name = {self.name!r}") # generate the root render function. self.writeline( - "%s(context, missing=missing%s):" % (self.func("root"), envenv), extra=1 + f"{self.func('root')}(context, missing=missing{envenv}):", extra=1 ) self.indent() self.write_commons() @@ -763,7 +877,7 @@ class CodeGenerator(NodeVisitor): frame = Frame(eval_ctx) if "self" in find_undeclared(node.body, ("self",)): ref = frame.symbols.declare_parameter("self") - self.writeline("%s = TemplateReference(context)" % ref) + self.writeline(f"{ref} = TemplateReference(context)") frame.symbols.analyze_node(node) frame.toplevel = frame.rootlevel = True frame.require_output_check = have_extends and not self.has_known_extends @@ -781,13 +895,11 @@ class CodeGenerator(NodeVisitor): self.indent() self.writeline("if parent_template is not None:") self.indent() - if supports_yield_from and not self.environment.is_async: + if 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 "") + "async for event in parent_template.root_render_func(context):" ) self.indent() self.writeline("yield event") @@ -795,10 +907,9 @@ class CodeGenerator(NodeVisitor): 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): + for name, block in self.blocks.items(): self.writeline( - "%s(context, missing=missing%s):" - % (self.func("block_" + name), envenv), + f"{self.func('block_' + name)}(context, missing=missing{envenv}):", block, 1, ) @@ -808,32 +919,29 @@ class CodeGenerator(NodeVisitor): # toplevel template. This would cause a variety of # interesting issues with identifier tracking. block_frame = Frame(eval_ctx) + block_frame.block_frame = True undeclared = find_undeclared(block.body, ("self", "super")) if "self" in undeclared: ref = block_frame.symbols.declare_parameter("self") - self.writeline("%s = TemplateReference(context)" % ref) + self.writeline(f"{ref} = TemplateReference(context)") if "super" in undeclared: ref = block_frame.symbols.declare_parameter("super") - self.writeline("%s = context.super(%r, block_%s)" % (ref, name, name)) + self.writeline(f"{ref} = context.super({name!r}, block_{name})") block_frame.symbols.analyze_node(block) block_frame.block = name + self.writeline("_block_vars = {}") 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, - ) + blocks_kv_str = ", ".join(f"{x!r}: block_{x}" for x in self.blocks) + self.writeline(f"blocks = {{{blocks_kv_str}}}", extra=1) + debug_kv_str = "&".join(f"{k}={v}" for k, v in self.debug_info) + self.writeline(f"debug_info = {debug_kv_str!r}") - # 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): + def visit_Block(self, node: nodes.Block, frame: Frame) -> None: """Call a block and register it for the template.""" level = 0 if frame.toplevel: @@ -851,18 +959,23 @@ class CodeGenerator(NodeVisitor): else: context = self.get_context_ref() - if ( - supports_yield_from - and not self.environment.is_async - and frame.buffer is None - ): + if node.required: + self.writeline(f"if len(context.blocks[{node.name!r}]) <= 1:", node) + self.indent() self.writeline( - "yield from context.blocks[%r][0](%s)" % (node.name, context), node + f'raise TemplateRuntimeError("Required block {node.name!r} not found")', + node, + ) + self.outdent() + + if not self.environment.is_async and frame.buffer is None: + self.writeline( + f"yield from context.blocks[{node.name!r}][0]({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), + f"{self.choose_async()}for event in" + f" context.blocks[{node.name!r}][0]({context}):", node, ) self.indent() @@ -871,7 +984,7 @@ class CodeGenerator(NodeVisitor): self.outdent(level) - def visit_Extends(self, node, frame): + def visit_Extends(self, node: nodes.Extends, frame: Frame) -> None: """Calls the extender.""" if not frame.toplevel: self.fail("cannot use extend from a non top-level scope", node.lineno) @@ -888,7 +1001,7 @@ class CodeGenerator(NodeVisitor): if not self.has_known_extends: self.writeline("if parent_template is not None:") self.indent() - self.writeline("raise TemplateRuntimeError(%r)" % "extended multiple times") + self.writeline('raise TemplateRuntimeError("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. @@ -899,10 +1012,8 @@ class CodeGenerator(NodeVisitor): 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.write(f", {self.name!r})") + self.writeline("for name, parent_block in parent_template.blocks.items():") self.indent() self.writeline("context.blocks.setdefault(name, []).append(parent_block)") self.outdent() @@ -916,7 +1027,7 @@ class CodeGenerator(NodeVisitor): # and now we have one more self.extends_so_far += 1 - def visit_Include(self, node, frame): + def visit_Include(self, node: nodes.Include, frame: Frame) -> None: """Handles includes.""" if node.ignore_missing: self.writeline("try:") @@ -924,16 +1035,16 @@ class CodeGenerator(NodeVisitor): func_name = "get_or_select_template" if isinstance(node.template, nodes.Const): - if isinstance(node.template.value, string_types): + if isinstance(node.template.value, str): 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.writeline(f"template = environment.{func_name}(", node) self.visit(node.template, frame) - self.write(", %r)" % self.name) + self.write(f", {self.name!r})") if node.ignore_missing: self.outdent() self.writeline("except TemplateNotFound:") @@ -945,26 +1056,19 @@ class CodeGenerator(NodeVisitor): 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)) + f"{self.choose_async()}for event in template.root_render_func(" + "template.new_context(context.get_all(), True," + f" {self.dump_local_context(frame)})):" ) elif self.environment.is_async: self.writeline( - "for event in (await " - "template._get_default_module_async())" + "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:" - ) + self.writeline("yield from template._get_default_module()._body_stream") + skip_event_yield = True if not skip_event_yield: self.indent() @@ -974,53 +1078,39 @@ class CodeGenerator(NodeVisitor): 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(") + def _import_common( + self, node: t.Union[nodes.Import, nodes.FromImport], frame: Frame + ) -> None: + self.write(f"{self.choose_async('await ')}environment.get_template(") self.visit(node.template, frame) - self.write(", %r)." % self.name) + self.write(f", {self.name!r}).") + if node.with_context: + f_name = f"make_module{self.choose_async('_async')}" self.write( - "make_module%s(context.get_all(), True, %s)" - % ( - self.environment.is_async and "_async" or "", - self.dump_local_context(frame), - ) + f"{f_name}(context.get_all(), True, {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) + self.write("_get_default_module(context)") - def visit_FromImport(self, node, frame): + def visit_Import(self, node: nodes.Import, frame: Frame) -> None: + """Visit regular imports.""" + self.writeline(f"{frame.symbols.ref(node.target)} = ", node) + if frame.toplevel: + self.write(f"context.vars[{node.target!r}] = ") + + self._import_common(node, frame) + + if frame.toplevel and not node.target.startswith("_"): + self.writeline(f"context.exported_vars.discard({node.target!r})") + + def visit_FromImport(self, node: nodes.FromImport, frame: Frame) -> None: """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()") - + self.write("included_template = ") + self._import_common(node, frame) var_names = [] discarded_names = [] for name in node.names: @@ -1029,22 +1119,18 @@ class CodeGenerator(NodeVisitor): else: alias = name self.writeline( - "%s = getattr(included_template, " - "%r, missing)" % (frame.symbols.ref(alias), name) + f"{frame.symbols.ref(alias)} =" + f" getattr(included_template, {name!r}, missing)" ) - self.writeline("if %s is missing:" % frame.symbols.ref(alias)) + self.writeline(f"if {frame.symbols.ref(alias)} is missing:") self.indent() + message = ( + "the template {included_template.__name__!r}" + f" (imported on {self.position(node)})" + f" does not export the requested name {name!r}" + ) 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, - ) + f"{frame.symbols.ref(alias)} = undefined(f{message!r}, name={name!r})" ) self.outdent() if frame.toplevel: @@ -1055,35 +1141,35 @@ class CodeGenerator(NodeVisitor): if var_names: if len(var_names) == 1: name = var_names[0] - self.writeline( - "context.vars[%r] = %s" % (name, frame.symbols.ref(name)) - ) + self.writeline(f"context.vars[{name!r}] = {frame.symbols.ref(name)}") else: - self.writeline( - "context.vars.update({%s})" - % ", ".join( - "%r: %s" % (name, frame.symbols.ref(name)) for name in var_names - ) + names_kv = ", ".join( + f"{name!r}: {frame.symbols.ref(name)}" for name in var_names ) + self.writeline(f"context.vars.update({{{names_kv}}})") if discarded_names: if len(discarded_names) == 1: - self.writeline("context.exported_vars.discard(%r)" % discarded_names[0]) + self.writeline(f"context.exported_vars.discard({discarded_names[0]!r})") else: + names_str = ", ".join(map(repr, discarded_names)) self.writeline( - "context.exported_vars.difference_" - "update((%s))" % ", ".join(imap(repr, discarded_names)) + f"context.exported_vars.difference_update(({names_str}))" ) - def visit_For(self, node, frame): + def visit_For(self, node: nodes.For, frame: Frame) -> None: loop_frame = frame.inner() + loop_frame.loop_frame = True 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",) + # variable is accessed in the body if the body is a scoped block. + extended_loop = ( + node.recursive + or "loop" + in find_undeclared(node.iter_child_nodes(only=("body",)), ("loop",)) + or any(block.scoped for block in node.find_all(nodes.Block)) ) loop_ref = None @@ -1097,13 +1183,13 @@ class CodeGenerator(NodeVisitor): 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.writeline(f"{self.func(loop_filter_func)}(fiter):", node.test) self.indent() self.enter_frame(test_frame) - self.writeline(self.environment.is_async and "async for " or "for ") + self.writeline(self.choose_async("async for ", "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.choose_async("auto_aiter(fiter)", "fiter")) self.write(":") self.indent() self.writeline("if ", node.test) @@ -1120,7 +1206,7 @@ class CodeGenerator(NodeVisitor): # 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 + f"{self.func('loop')}(reciter, loop_render_func, depth=0):", node ) self.indent() self.buffer(loop_frame) @@ -1131,7 +1217,7 @@ class CodeGenerator(NodeVisitor): # 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) + self.writeline(f"{loop_ref} = missing") for name in node.find_all(nodes.Name): if name.ctx == "store" and name.name == "loop": @@ -1142,20 +1228,17 @@ class CodeGenerator(NodeVisitor): if node.else_: iteration_indicator = self.temporary_identifier() - self.writeline("%s = 1" % iteration_indicator) + self.writeline(f"{iteration_indicator} = 1") - self.writeline(self.environment.is_async and "async for " or "for ", node) + self.writeline(self.choose_async("async for ", "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) + self.write(f", {loop_ref} in {self.choose_async('Async')}LoopContext(") else: self.write(" in ") if node.test: - self.write("%s(" % loop_filter_func) + self.write(f"{loop_filter_func}(") if node.recursive: self.write("reciter") else: @@ -1170,21 +1253,22 @@ class CodeGenerator(NodeVisitor): if node.recursive: self.write(", undefined, loop_render_func, depth):") else: - self.write(extended_loop and ", undefined):" or ":") + self.write(", undefined):" if extended_loop else ":") self.indent() self.enter_frame(loop_frame) + self.writeline("_loop_vars = {}") self.blockvisit(node.body, loop_frame) if node.else_: - self.writeline("%s = 0" % iteration_indicator) + self.writeline(f"{iteration_indicator} = 0") 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.writeline(f"if {iteration_indicator}:") self.indent() self.enter_frame(else_frame) self.blockvisit(node.else_, else_frame) @@ -1197,9 +1281,7 @@ class CodeGenerator(NodeVisitor): self.return_buffer_contents(loop_frame) self.outdent() self.start_write(frame, node) - if self.environment.is_async: - self.write("await ") - self.write("loop(") + self.write(f"{self.choose_async('await ')}loop(") if self.environment.is_async: self.write("auto_aiter(") self.visit(node.iter, frame) @@ -1208,7 +1290,7 @@ class CodeGenerator(NodeVisitor): self.write(", loop)") self.end_write(frame) - def visit_If(self, node, frame): + def visit_If(self, node: nodes.If, frame: Frame) -> None: if_frame = frame.soft() self.writeline("if ", node) self.visit(node.test, if_frame) @@ -1229,17 +1311,17 @@ class CodeGenerator(NodeVisitor): self.blockvisit(node.else_, if_frame) self.outdent() - def visit_Macro(self, node, frame): + def visit_Macro(self, node: nodes.Macro, frame: Frame) -> None: 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.write(f"context.exported_vars.add({node.name!r})") + self.writeline(f"context.vars[{node.name!r}] = ") + self.write(f"{frame.symbols.ref(node.name)} = ") self.macro_def(macro_ref, macro_frame) - def visit_CallBlock(self, node, frame): + def visit_CallBlock(self, node: nodes.CallBlock, frame: Frame) -> None: call_frame, macro_ref = self.macro_body(node, frame) self.writeline("caller = ") self.macro_def(macro_ref, call_frame) @@ -1247,7 +1329,7 @@ class CodeGenerator(NodeVisitor): self.visit_Call(node.call, frame, forward_caller=True) self.end_write(frame) - def visit_FilterBlock(self, node, frame): + def visit_FilterBlock(self, node: nodes.FilterBlock, frame: Frame) -> None: filter_frame = frame.inner() filter_frame.symbols.analyze_node(node) self.enter_frame(filter_frame) @@ -1258,11 +1340,11 @@ class CodeGenerator(NodeVisitor): self.end_write(frame) self.leave_frame(filter_frame) - def visit_With(self, node, frame): + def visit_With(self, node: nodes.With, frame: Frame) -> None: with_frame = frame.inner() with_frame.symbols.analyze_node(node) self.enter_frame(with_frame) - for target, expr in izip(node.targets, node.values): + for target, expr in zip(node.targets, node.values): self.newline() self.visit(target, with_frame) self.write(" = ") @@ -1270,18 +1352,25 @@ class CodeGenerator(NodeVisitor): self.blockvisit(node.body, with_frame) self.leave_frame(with_frame) - def visit_ExprStmt(self, node, frame): + def visit_ExprStmt(self, node: nodes.ExprStmt, frame: Frame) -> None: 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 + class _FinalizeInfo(t.NamedTuple): + const: t.Optional[t.Callable[..., str]] + src: t.Optional[str] - def _make_finalize(self): + @staticmethod + def _default_finalize(value: t.Any) -> t.Any: + """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. + """ + return str(value) + + _finalize: t.Optional[_FinalizeInfo] = None + + def _make_finalize(self) -> _FinalizeInfo: """Build the finalize function to be used on constants and at runtime. Cached so it's only created once for all output nodes. @@ -1297,39 +1386,48 @@ class CodeGenerator(NodeVisitor): if self._finalize is not None: return self._finalize + finalize: t.Optional[t.Callable[..., t.Any]] finalize = default = self._default_finalize src = None if self.environment.finalize: src = "environment.finalize(" env_finalize = self.environment.finalize + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(env_finalize) # type: ignore + ) + finalize = None - def finalize(value): - return default(env_finalize(value)) + if pass_arg is None: - 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: t.Any) -> t.Any: + return default(env_finalize(value)) - def finalize(value): - return default(env_finalize(self.environment, value)) + else: + src = f"{src}{pass_arg}, " + + if pass_arg == "environment": + + def finalize(value: t.Any) -> t.Any: + return default(env_finalize(self.environment, value)) self._finalize = self._FinalizeInfo(finalize, src) return self._finalize - def _output_const_repr(self, group): + def _output_const_repr(self, group: t.Iterable[t.Any]) -> str: """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): + def _output_child_to_const( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> str: """Try to optimize a child of an ``Output`` node by trying to convert it to constant, finalized data at compile time. @@ -1344,25 +1442,29 @@ class CodeGenerator(NodeVisitor): # Template data doesn't go through finalize. if isinstance(node, nodes.TemplateData): - return text_type(const) + return str(const) - return finalize.const(const) + return finalize.const(const) # type: ignore - def _output_child_pre(self, node, frame, finalize): + def _output_child_pre( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: """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)(") + self.write("(escape if context.eval_ctx.autoescape else str)(") elif frame.eval_ctx.autoescape: self.write("escape(") else: - self.write("to_string(") + self.write("str(") if finalize.src is not None: self.write(finalize.src) - def _output_child_post(self, node, frame, finalize): + def _output_child_post( + self, node: nodes.Expr, frame: Frame, finalize: _FinalizeInfo + ) -> None: """Output extra source code after visiting a child of an ``Output`` node. """ @@ -1371,7 +1473,7 @@ class CodeGenerator(NodeVisitor): if finalize.src is not None: self.write(")") - def visit_Output(self, node, frame): + def visit_Output(self, node: nodes.Output, frame: Frame) -> None: # 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. @@ -1382,7 +1484,7 @@ class CodeGenerator(NodeVisitor): self.indent() finalize = self._make_finalize() - body = [] + body: t.List[t.Union[t.List[t.Any], nodes.Expr]] = [] # Evaluate constants at compile time if possible. Each item in # body will be either a list of static data or a node to be @@ -1414,9 +1516,9 @@ class CodeGenerator(NodeVisitor): if frame.buffer is not None: if len(body) == 1: - self.writeline("%s.append(" % frame.buffer) + self.writeline(f"{frame.buffer}.append(") else: - self.writeline("%s.extend((" % frame.buffer) + self.writeline(f"{frame.buffer}.extend((") self.indent() @@ -1450,7 +1552,7 @@ class CodeGenerator(NodeVisitor): if frame.require_output_check: self.outdent() - def visit_Assign(self, node, frame): + def visit_Assign(self, node: nodes.Assign, frame: Frame) -> None: self.push_assign_tracking() self.newline(node) self.visit(node.target, frame) @@ -1458,7 +1560,7 @@ class CodeGenerator(NodeVisitor): self.visit(node.node, frame) self.pop_assign_tracking(frame) - def visit_AssignBlock(self, node, frame): + def visit_AssignBlock(self, node: nodes.AssignBlock, frame: Frame) -> None: self.push_assign_tracking() block_frame = frame.inner() # This is a special case. Since a set block always captures we @@ -1475,15 +1577,17 @@ class CodeGenerator(NodeVisitor): if node.filter is not None: self.visit_Filter(node.filter, block_frame) else: - self.write("concat(%s)" % block_frame.buffer) + self.write(f"concat({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: + def visit_Name(self, node: nodes.Name, frame: Frame) -> None: + if node.ctx == "store" and ( + frame.toplevel or frame.loop_frame or frame.block_frame + ): if self._assign_stack: self._assign_stack[-1].add(node.name) ref = frame.symbols.ref(node.name) @@ -1499,52 +1603,51 @@ class CodeGenerator(NodeVisitor): and not self.parameter_is_undeclared(ref) ): self.write( - "(undefined(name=%r) if %s is missing else %s)" - % (node.name, ref, ref) + f"(undefined(name={node.name!r}) if {ref} is missing else {ref})" ) return self.write(ref) - def visit_NSRef(self, node, frame): + def visit_NSRef(self, node: nodes.NSRef, frame: Frame) -> None: # 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.writeline(f"if not isinstance({ref}, Namespace):") self.indent() self.writeline( - "raise TemplateRuntimeError(%r)" - % "cannot assign attribute on non-namespace object" + "raise TemplateRuntimeError" + '("cannot assign attribute on non-namespace object")' ) self.outdent() - self.writeline("%s[%r]" % (ref, node.attr)) + self.writeline(f"{ref}[{node.attr!r}]") - def visit_Const(self, node, frame): + def visit_Const(self, node: nodes.Const, frame: Frame) -> None: 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): + def visit_TemplateData(self, node: nodes.TemplateData, frame: Frame) -> None: 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 + f"(Markup if context.eval_ctx.autoescape else identity)({node.data!r})" ) - def visit_Tuple(self, node, frame): + def visit_Tuple(self, node: nodes.Tuple, frame: Frame) -> None: 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 ")") + self.write(",)" if idx == 0 else ")") - def visit_List(self, node, frame): + def visit_List(self, node: nodes.List, frame: Frame) -> None: self.write("[") for idx, item in enumerate(node.items): if idx: @@ -1552,7 +1655,7 @@ class CodeGenerator(NodeVisitor): self.visit(item, frame) self.write("]") - def visit_Dict(self, node, frame): + def visit_Dict(self, node: nodes.Dict, frame: Frame) -> None: self.write("{") for idx, item in enumerate(node.items): if idx: @@ -1562,96 +1665,59 @@ class CodeGenerator(NodeVisitor): 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 + visit_Add = _make_binop("+") + visit_Sub = _make_binop("-") + visit_Mul = _make_binop("*") + visit_Div = _make_binop("/") + visit_FloorDiv = _make_binop("//") + visit_Pow = _make_binop("**") + visit_Mod = _make_binop("%") + visit_And = _make_binop("and") + visit_Or = _make_binop("or") + visit_Pos = _make_unop("+") + visit_Neg = _make_unop("-") + visit_Not = _make_unop("not ") @optimizeconst - def visit_Concat(self, node, frame): + def visit_Concat(self, node: nodes.Concat, frame: Frame) -> None: if frame.eval_ctx.volatile: - func_name = "(context.eval_ctx.volatile and markup_join or unicode_join)" + func_name = "(markup_join if context.eval_ctx.volatile else str_join)" elif frame.eval_ctx.autoescape: func_name = "markup_join" else: - func_name = "unicode_join" - self.write("%s((" % func_name) + func_name = "str_join" + self.write(f"{func_name}((") for arg in node.nodes: self.visit(arg, frame) self.write(", ") self.write("))") @optimizeconst - def visit_Compare(self, node, frame): + def visit_Compare(self, node: nodes.Compare, frame: Frame) -> None: 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]) + def visit_Operand(self, node: nodes.Operand, frame: Frame) -> None: + self.write(f" {operators[node.op]} ") self.visit(node.expr, frame) @optimizeconst - def visit_Getattr(self, node, frame): + def visit_Getattr(self, node: nodes.Getattr, frame: Frame) -> None: if self.environment.is_async: self.write("(await auto_await(") self.write("environment.getattr(") self.visit(node.node, frame) - self.write(", %r)" % node.attr) + self.write(f", {node.attr!r})") if self.environment.is_async: self.write("))") @optimizeconst - def visit_Getitem(self, node, frame): + def visit_Getitem(self, node: nodes.Getitem, frame: Frame) -> None: # slices bypass the environment getitem method. if isinstance(node.arg, nodes.Slice): self.visit(node.node, frame) @@ -1671,7 +1737,7 @@ class CodeGenerator(NodeVisitor): if self.environment.is_async: self.write("))") - def visit_Slice(self, node, frame): + def visit_Slice(self, node: nodes.Slice, frame: Frame) -> None: if node.start is not None: self.visit(node.start, frame) self.write(":") @@ -1681,60 +1747,83 @@ class CodeGenerator(NodeVisitor): self.write(":") self.visit(node.step, frame) - @optimizeconst - def visit_Filter(self, node, frame): + @contextmanager + def _filter_test_common( + self, node: t.Union[nodes.Filter, nodes.Test], frame: Frame, is_filter: bool + ) -> t.Iterator[None]: 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) + if is_filter: + self.write(f"{self.filters[node.name]}(") + func = self.environment.filters.get(node.name) else: - self.write("concat(%s)" % frame.buffer) + self.write(f"{self.tests[node.name]}(") + func = self.environment.tests.get(node.name) + + # When inside an If or CondExpr frame, allow the filter to be + # undefined at compile time and only raise an error if it's + # actually called at runtime. See pull_dependencies. + if func is None and not frame.soft_frame: + type_name = "filter" if is_filter else "test" + self.fail(f"No {type_name} named {node.name!r}.", node.lineno) + + pass_arg = { + _PassArg.context: "context", + _PassArg.eval_context: "context.eval_ctx", + _PassArg.environment: "environment", + }.get( + _PassArg.from_obj(func) # type: ignore + ) + + if pass_arg is not None: + self.write(f"{pass_arg}, ") + + # Back to the visitor function to handle visiting the target of + # the filter or test. + yield + 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(")") + def visit_Filter(self, node: nodes.Filter, frame: Frame) -> None: + with self._filter_test_common(node, frame, True): + # 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( + f"(Markup(concat({frame.buffer}))" + f" if context.eval_ctx.autoescape else concat({frame.buffer}))" + ) + elif frame.eval_ctx.autoescape: + self.write(f"Markup(concat({frame.buffer}))") + else: + self.write(f"concat({frame.buffer})") @optimizeconst - def visit_CondExpr(self, node, frame): - def write_expr2(): + def visit_Test(self, node: nodes.Test, frame: Frame) -> None: + with self._filter_test_common(node, frame, False): + self.visit(node.node, frame) + + @optimizeconst + def visit_CondExpr(self, node: nodes.CondExpr, frame: Frame) -> None: + frame = frame.soft() + + def write_expr2() -> None: if node.expr2 is not None: - return self.visit(node.expr2, frame) + self.visit(node.expr2, frame) + return + self.write( - "cond_expr_undefined(%r)" - % ( - "the inline if-" - "expression on %s evaluated to false and " - "no else section was defined." % self.position(node) - ) + f'cond_expr_undefined("the inline if-expression on' + f" {self.position(node)} evaluated to false and no else" + f' section was defined.")' ) self.write("(") @@ -1746,7 +1835,9 @@ class CodeGenerator(NodeVisitor): self.write(")") @optimizeconst - def visit_Call(self, node, frame, forward_caller=False): + def visit_Call( + self, node: nodes.Call, frame: Frame, forward_caller: bool = False + ) -> None: if self.environment.is_async: self.write("await auto_await(") if self.environment.sandboxed: @@ -1754,63 +1845,79 @@ class CodeGenerator(NodeVisitor): else: self.write("context.call(") self.visit(node.node, frame) - extra_kwargs = forward_caller and {"caller": "caller"} or None + extra_kwargs = {"caller": "caller"} if forward_caller else None + loop_kwargs = {"_loop_vars": "_loop_vars"} if frame.loop_frame else {} + block_kwargs = {"_block_vars": "_block_vars"} if frame.block_frame else {} + if extra_kwargs: + extra_kwargs.update(loop_kwargs, **block_kwargs) + elif loop_kwargs or block_kwargs: + extra_kwargs = dict(loop_kwargs, **block_kwargs) self.signature(node, frame, extra_kwargs) self.write(")") if self.environment.is_async: self.write(")") - def visit_Keyword(self, node, frame): + def visit_Keyword(self, node: nodes.Keyword, frame: Frame) -> None: self.write(node.key + "=") self.visit(node.value, frame) # -- Unused nodes for extensions - def visit_MarkSafe(self, node, frame): + def visit_MarkSafe(self, node: nodes.MarkSafe, frame: Frame) -> None: 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)(") + def visit_MarkSafeIfAutoescape( + self, node: nodes.MarkSafeIfAutoescape, frame: Frame + ) -> None: + self.write("(Markup if context.eval_ctx.autoescape else identity)(") self.visit(node.expr, frame) self.write(")") - def visit_EnvironmentAttribute(self, node, frame): + def visit_EnvironmentAttribute( + self, node: nodes.EnvironmentAttribute, frame: Frame + ) -> None: self.write("environment." + node.name) - def visit_ExtensionAttribute(self, node, frame): - self.write("environment.extensions[%r].%s" % (node.identifier, node.name)) + def visit_ExtensionAttribute( + self, node: nodes.ExtensionAttribute, frame: Frame + ) -> None: + self.write(f"environment.extensions[{node.identifier!r}].{node.name}") - def visit_ImportedName(self, node, frame): + def visit_ImportedName(self, node: nodes.ImportedName, frame: Frame) -> None: self.write(self.import_aliases[node.importname]) - def visit_InternalName(self, node, frame): + def visit_InternalName(self, node: nodes.InternalName, frame: Frame) -> None: self.write(node.name) - def visit_ContextReference(self, node, frame): + def visit_ContextReference( + self, node: nodes.ContextReference, frame: Frame + ) -> None: self.write("context") - def visit_DerivedContextReference(self, node, frame): + def visit_DerivedContextReference( + self, node: nodes.DerivedContextReference, frame: Frame + ) -> None: self.write(self.derive_context(frame)) - def visit_Continue(self, node, frame): + def visit_Continue(self, node: nodes.Continue, frame: Frame) -> None: self.writeline("continue", node) - def visit_Break(self, node, frame): + def visit_Break(self, node: nodes.Break, frame: Frame) -> None: self.writeline("break", node) - def visit_Scope(self, node, frame): + def visit_Scope(self, node: nodes.Scope, frame: Frame) -> None: 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): + def visit_OverlayScope(self, node: nodes.OverlayScope, frame: Frame) -> None: ctx = self.temporary_identifier() - self.writeline("%s = %s" % (ctx, self.derive_context(frame))) - self.writeline("%s.vars = " % ctx) + self.writeline(f"{ctx} = {self.derive_context(frame)}") + self.writeline(f"{ctx}.vars = ") self.visit(node.context, frame) self.push_context_reference(ctx) @@ -1821,9 +1928,11 @@ class CodeGenerator(NodeVisitor): self.leave_frame(scope_frame) self.pop_context_reference() - def visit_EvalContextModifier(self, node, frame): + def visit_EvalContextModifier( + self, node: nodes.EvalContextModifier, frame: Frame + ) -> None: for keyword in node.options: - self.writeline("context.eval_ctx.%s = " % keyword.key) + self.writeline(f"context.eval_ctx.{keyword.key} = ") self.visit(keyword.value, frame) try: val = keyword.value.as_const(frame.eval_ctx) @@ -1832,12 +1941,14 @@ class CodeGenerator(NodeVisitor): else: setattr(frame.eval_ctx, keyword.key, val) - def visit_ScopedEvalContextModifier(self, node, frame): + def visit_ScopedEvalContextModifier( + self, node: nodes.ScopedEvalContextModifier, frame: Frame + ) -> None: old_ctx_name = self.temporary_identifier() saved_ctx = frame.eval_ctx.save() - self.writeline("%s = context.eval_ctx.save()" % old_ctx_name) + self.writeline(f"{old_ctx_name} = context.eval_ctx.save()") 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) + self.writeline(f"context.eval_ctx.revert({old_ctx_name})") diff --git a/pipenv/vendor/jinja2/constants.py b/pipenv/vendor/jinja2/constants.py index bf7f2ca7..41a1c23b 100644 --- a/pipenv/vendor/jinja2/constants.py +++ b/pipenv/vendor/jinja2/constants.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- #: list of lorem ipsum words used by the lipsum() helper function -LOREM_IPSUM_WORDS = u"""\ +LOREM_IPSUM_WORDS = """\ 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 diff --git a/pipenv/vendor/jinja2/debug.py b/pipenv/vendor/jinja2/debug.py index 5d8aec31..02de4ee7 100644 --- a/pipenv/vendor/jinja2/debug.py +++ b/pipenv/vendor/jinja2/debug.py @@ -1,38 +1,38 @@ +import platform import sys +import typing as t from types import CodeType +from types import TracebackType -from . import TemplateSyntaxError -from ._compat import PYPY +from .exceptions import TemplateSyntaxError from .utils import internal_code from .utils import missing +if t.TYPE_CHECKING: + from .runtime import Context -def rewrite_traceback_stack(source=None): + +def rewrite_traceback_stack(source: t.Optional[str] = None) -> BaseException: """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. + :return: The original exception with the rewritten traceback. """ - exc_type, exc_value, tb = sys.exc_info() + _, exc_value, tb = sys.exc_info() + exc_value = t.cast(BaseException, exc_value) + tb = t.cast(TracebackType, tb) 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 - + # Remove the old traceback, otherwise the frames from the + # compiler still show up. + exc_value.with_traceback(None) # Outside of runtime, so the frame isn't executing template # code, but it still needs to point at the template. tb = fake_traceback( @@ -70,10 +70,12 @@ def rewrite_traceback_stack(source=None): for tb in reversed(stack): tb_next = tb_set_next(tb, tb_next) - return exc_type, exc_value, tb_next + return exc_value.with_traceback(tb_next) -def fake_traceback(exc_value, tb, filename, lineno): +def fake_traceback( # type: ignore + exc_value: BaseException, tb: t.Optional[TracebackType], filename: str, lineno: int +) -> TracebackType: """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 @@ -113,7 +115,7 @@ def fake_traceback(exc_value, tb, filename, lineno): if function == "root": location = "top-level template code" elif function.startswith("block_"): - location = 'block "%s"' % function[6:] + location = f"block {function[6:]!r}" # Collect arguments for the new code object. CodeType only # accepts positional arguments, and arguments were inserted in @@ -123,7 +125,7 @@ def fake_traceback(exc_value, tb, filename, lineno): for attr in ( "argcount", "posonlyargcount", # Python 3.8 - "kwonlyargcount", # Python 3 + "kwonlyargcount", "nlocals", "stacksize", "flags", @@ -137,6 +139,7 @@ def fake_traceback(exc_value, tb, filename, lineno): "lnotab", "freevars", "cellvars", + "linetable", # Python 3.10 ): if isinstance(attr, tuple): # Replace with given value. @@ -145,7 +148,7 @@ def fake_traceback(exc_value, tb, filename, lineno): try: # Copy original value if it exists. - code_args.append(getattr(code, "co_" + attr)) + code_args.append(getattr(code, "co_" + t.cast(str, attr))) except AttributeError: # Some arguments were added later. continue @@ -161,18 +164,18 @@ def fake_traceback(exc_value, tb, filename, lineno): try: exec(code, globals, locals) except BaseException: - return sys.exc_info()[2].tb_next + return sys.exc_info()[2].tb_next # type: ignore -def get_template_locals(real_locals): +def get_template_locals(real_locals: t.Mapping[str, t.Any]) -> t.Dict[str, t.Any]: """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") + ctx: "t.Optional[Context]" = real_locals.get("context") - if ctx: - data = ctx.get_all().copy() + if ctx is not None: + data: t.Dict[str, t.Any] = ctx.get_all().copy() else: data = {} @@ -180,7 +183,7 @@ def get_template_locals(real_locals): # 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 = {} + local_overrides: t.Dict[str, t.Tuple[int, t.Any]] = {} for name, value in real_locals.items(): if not name.startswith("l_") or value is missing: @@ -188,8 +191,8 @@ def get_template_locals(real_locals): continue try: - _, depth, name = name.split("_", 2) - depth = int(depth) + _, depth_str, name = name.split("_", 2) + depth = int(depth_str) except ValueError: continue @@ -210,31 +213,37 @@ def get_template_locals(real_locals): if sys.version_info >= (3, 7): # tb_next is directly assignable as of Python 3.7 - def tb_set_next(tb, tb_next): + def tb_set_next( + tb: TracebackType, tb_next: t.Optional[TracebackType] + ) -> TracebackType: tb.tb_next = tb_next return tb -elif PYPY: +elif platform.python_implementation() == "PyPy": # PyPy might have special support, and won't work with ctypes. try: - import tputil + import tputil # type: ignore except ImportError: # Without tproxy support, use the original traceback. - def tb_set_next(tb, tb_next): + def tb_set_next( + tb: TracebackType, tb_next: t.Optional[TracebackType] + ) -> TracebackType: 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): + def tb_set_next( + tb: TracebackType, tb_next: t.Optional[TracebackType] + ) -> TracebackType: + def controller(op): # type: ignore if op.opname == "__getattribute__" and op.args[0] == "tb_next": return tb_next return op.delegate() - return tputil.make_proxy(controller, obj=tb) + return tputil.make_proxy(controller, obj=tb) # type: ignore else: @@ -250,7 +259,9 @@ else: ("tb_next", ctypes.py_object), ] - def tb_set_next(tb, tb_next): + def tb_set_next( + tb: TracebackType, tb_next: t.Optional[TracebackType] + ) -> TracebackType: c_tb = _CTraceback.from_address(id(tb)) # Clear out the old tb_next. diff --git a/pipenv/vendor/jinja2/defaults.py b/pipenv/vendor/jinja2/defaults.py index 8e0e7d77..638cad3d 100644 --- a/pipenv/vendor/jinja2/defaults.py +++ b/pipenv/vendor/jinja2/defaults.py @@ -1,5 +1,5 @@ -# -*- coding: utf-8 -*- -from ._compat import range_type +import typing as t + from .filters import FILTERS as DEFAULT_FILTERS # noqa: F401 from .tests import TESTS as DEFAULT_TESTS # noqa: F401 from .utils import Cycler @@ -7,6 +7,9 @@ from .utils import generate_lorem_ipsum from .utils import Joiner from .utils import Namespace +if t.TYPE_CHECKING: + import typing_extensions as te + # defaults for the parser / lexer BLOCK_START_STRING = "{%" BLOCK_END_STRING = "%}" @@ -14,17 +17,17 @@ VARIABLE_START_STRING = "{{" VARIABLE_END_STRING = "}}" COMMENT_START_STRING = "{#" COMMENT_END_STRING = "#}" -LINE_STATEMENT_PREFIX = None -LINE_COMMENT_PREFIX = None +LINE_STATEMENT_PREFIX: t.Optional[str] = None +LINE_COMMENT_PREFIX: t.Optional[str] = None TRIM_BLOCKS = False LSTRIP_BLOCKS = False -NEWLINE_SEQUENCE = "\n" +NEWLINE_SEQUENCE: "te.Literal['\\n', '\\r\\n', '\\r']" = "\n" KEEP_TRAILING_NEWLINE = False # default filters, tests and namespace DEFAULT_NAMESPACE = { - "range": range_type, + "range": range, "dict": dict, "lipsum": generate_lorem_ipsum, "cycler": Cycler, @@ -33,10 +36,11 @@ DEFAULT_NAMESPACE = { } # default policies -DEFAULT_POLICIES = { +DEFAULT_POLICIES: t.Dict[str, t.Any] = { "compiler.ascii_str": True, "urlize.rel": "noopener", "urlize.target": None, + "urlize.extra_schemes": None, "truncate.leeway": 5, "json.dumps_function": None, "json.dumps_kwargs": {"sort_keys": True}, diff --git a/pipenv/vendor/jinja2/environment.py b/pipenv/vendor/jinja2/environment.py index 8430390e..8a831db8 100644 --- a/pipenv/vendor/jinja2/environment.py +++ b/pipenv/vendor/jinja2/environment.py @@ -1,25 +1,20 @@ -# -*- coding: utf-8 -*- """Classes for managing templates and their runtime and compile time options. """ import os import sys +import typing +import typing as t import weakref +from collections import ChainMap +from functools import lru_cache from functools import partial from functools import reduce +from types import CodeType 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 @@ -44,25 +39,33 @@ from .exceptions import TemplatesNotFound from .exceptions import TemplateSyntaxError from .exceptions import UndefinedError from .lexer import get_lexer +from .lexer import 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 _PassArg 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 +if t.TYPE_CHECKING: + import typing_extensions as te + from .bccache import BytecodeCache + from .ext import Extension + from .loaders import BaseLoader + +_env_bound = t.TypeVar("_env_bound", bound="Environment") + + # for direct template usage we have up to ten living environments -_spontaneous_environments = LRUCache(10) - - -def get_spontaneous_environment(cls, *args): +@lru_cache(maxsize=10) +def get_spontaneous_environment(cls: t.Type[_env_bound], *args: t.Any) -> _env_bound: """Return a new spontaneous environment. A spontaneous environment is used for templates created directly rather than through an existing environment. @@ -70,75 +73,74 @@ def get_spontaneous_environment(cls, *args): :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 + env = cls(*args) + env.shared = True + return env -def create_cache(size): +def create_cache( + size: int, +) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]: """Return the cache class for the given size.""" if size == 0: return None + if size < 0: return {} - return LRUCache(size) + + return LRUCache(size) # type: ignore -def copy_cache(cache): +def copy_cache( + cache: t.Optional[t.MutableMapping], +) -> t.Optional[t.MutableMapping[t.Tuple[weakref.ref, str], "Template"]]: """Create an empty copy of the given cache.""" if cache is None: return None - elif type(cache) is dict: + + if type(cache) is dict: return {} - return LRUCache(cache.capacity) + + return LRUCache(cache.capacity) # type: ignore -def load_extensions(environment, extensions): +def load_extensions( + environment: "Environment", + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]], +) -> t.Dict[str, "Extension"]: """Load the extensions from the list and bind it to the environment. - Returns a dict of instantiated environments. + Returns a dict of instantiated extensions. """ result = {} + for extension in extensions: - if isinstance(extension, string_types): - extension = import_string(extension) + if isinstance(extension, str): + extension = t.cast(t.Type["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): +def _environment_config_check(environment: "Environment") -> "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." + ), "'undefined' must be a subclass of 'jinja2.Undefined'." 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 ( + ), "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." + }, "'newline_sequence' must be one of '\\n', '\\r\\n', or '\\r'." return environment -class Environment(object): +class Environment: 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 @@ -256,9 +258,8 @@ class Environment(object): 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 set to true this enables async template execution which + allows using async functions and generators. """ #: if this environment is sandboxed. Modifying this variable won't make @@ -271,7 +272,7 @@ class Environment(object): overlayed = False #: the environment this environment is linked to if it is an overlay - linked_to = None + linked_to: t.Optional["Environment"] = None #: shared environments have this set to `True`. A shared environment #: must not be modified @@ -279,36 +280,38 @@ class Environment(object): #: the class that is used for code generation. See #: :class:`~jinja2.compiler.CodeGenerator` for more information. - code_generator_class = CodeGenerator + code_generator_class: t.Type["CodeGenerator"] = CodeGenerator - #: the context class thatis used for templates. See + #: the context class that is used for templates. See #: :class:`~jinja2.runtime.Context` for more information. - context_class = Context + context_class: t.Type[Context] = Context + + template_class: t.Type["Template"] 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, + block_start_string: str = BLOCK_START_STRING, + block_end_string: str = BLOCK_END_STRING, + variable_start_string: str = VARIABLE_START_STRING, + variable_end_string: str = VARIABLE_END_STRING, + comment_start_string: str = COMMENT_START_STRING, + comment_end_string: str = COMMENT_END_STRING, + line_statement_prefix: t.Optional[str] = LINE_STATEMENT_PREFIX, + line_comment_prefix: t.Optional[str] = LINE_COMMENT_PREFIX, + trim_blocks: bool = TRIM_BLOCKS, + lstrip_blocks: bool = LSTRIP_BLOCKS, + newline_sequence: "te.Literal['\\n', '\\r\\n', '\\r']" = NEWLINE_SEQUENCE, + keep_trailing_newline: bool = KEEP_TRAILING_NEWLINE, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = (), + optimized: bool = True, + undefined: t.Type[Undefined] = Undefined, + finalize: t.Optional[t.Callable[..., t.Any]] = None, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = False, + loader: t.Optional["BaseLoader"] = None, + cache_size: int = 400, + auto_reload: bool = True, + bytecode_cache: t.Optional["BytecodeCache"] = None, + enable_async: bool = False, ): # !!Important notice!! # The constructor accepts quite a few arguments that should be @@ -336,7 +339,7 @@ class Environment(object): self.keep_trailing_newline = keep_trailing_newline # runtime information - self.undefined = undefined + self.undefined: t.Type[Undefined] = undefined self.optimized = optimized self.finalize = finalize self.autoescape = autoescape @@ -358,52 +361,47 @@ class Environment(object): # 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 + self.is_async = enable_async + _environment_config_check(self) - _environment_sanity_check(self) - - def add_extension(self, extension): + def add_extension(self, extension: t.Union[str, t.Type["Extension"]]) -> None: """Adds an extension after the environment was created. .. versionadded:: 2.5 """ self.extensions.update(load_extensions(self, [extension])) - def extend(self, **attributes): + def extend(self, **attributes: t.Any) -> None: """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): + for key, value in attributes.items(): 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, - ): + block_start_string: str = missing, + block_end_string: str = missing, + variable_start_string: str = missing, + variable_end_string: str = missing, + comment_start_string: str = missing, + comment_end_string: str = missing, + line_statement_prefix: t.Optional[str] = missing, + line_comment_prefix: t.Optional[str] = missing, + trim_blocks: bool = missing, + lstrip_blocks: bool = missing, + extensions: t.Sequence[t.Union[str, t.Type["Extension"]]] = missing, + optimized: bool = missing, + undefined: t.Type[Undefined] = missing, + finalize: t.Optional[t.Callable[..., t.Any]] = missing, + autoescape: t.Union[bool, t.Callable[[t.Optional[str]], bool]] = missing, + loader: t.Optional["BaseLoader"] = missing, + cache_size: int = missing, + auto_reload: bool = missing, + bytecode_cache: t.Optional["BytecodeCache"] = missing, + ) -> "Environment": """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 @@ -423,7 +421,7 @@ class Environment(object): rv.overlayed = True rv.linked_to = self - for key, value in iteritems(args): + for key, value in args.items(): if value is not missing: setattr(rv, key, value) @@ -433,25 +431,30 @@ class Environment(object): rv.cache = copy_cache(self.cache) rv.extensions = {} - for key, value in iteritems(self.extensions): + for key, value in self.extensions.items(): rv.extensions[key] = value.bind(rv) if extensions is not missing: rv.extensions.update(load_extensions(rv, extensions)) - return _environment_sanity_check(rv) + return _environment_config_check(rv) - lexer = property(get_lexer, doc="The lexer for this environment.") + @property + def lexer(self) -> Lexer: + """The lexer for this environment.""" + return get_lexer(self) - def iter_extensions(self): + def iter_extensions(self) -> t.Iterator["Extension"]: """Iterates over the extensions by priority.""" return iter(sorted(self.extensions.values(), key=lambda x: x.priority)) - def getitem(self, obj, argument): + def getitem( + self, obj: t.Any, argument: t.Union[str, t.Any] + ) -> t.Union[t.Any, Undefined]: """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): + if isinstance(argument, str): try: attr = str(argument) except Exception: @@ -463,9 +466,9 @@ class Environment(object): pass return self.undefined(obj=obj, name=argument) - def getattr(self, obj, attribute): + def getattr(self, obj: t.Any, attribute: str) -> t.Any: """Get an item or attribute of an object but prefer the attribute. - Unlike :meth:`getitem` the attribute *must* be a bytestring. + Unlike :meth:`getitem` the attribute *must* be a string. """ try: return getattr(obj, attribute) @@ -476,51 +479,113 @@ class Environment(object): 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. + def _filter_test_common( + self, + name: t.Union[str, Undefined], + value: t.Any, + args: t.Optional[t.Sequence[t.Any]], + kwargs: t.Optional[t.Mapping[str, t.Any]], + context: t.Optional[Context], + eval_ctx: t.Optional[EvalContext], + is_filter: bool, + ) -> t.Any: + if is_filter: + env_map = self.filters + type_name = "filter" + else: + env_map = self.tests + type_name = "test" - 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. + func = env_map.get(name) # type: ignore - .. 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: + msg = f"No {type_name} named {name!r}." + + if isinstance(name, Undefined): + try: + name._fail_with_undefined_error() + except Exception as e: + msg = f"{msg} ({e}; did you forget to quote the callable name?)" + + raise TemplateRuntimeError(msg) + + args = [value, *(args if args is not None else ())] + kwargs = kwargs if kwargs is not None else {} + pass_arg = _PassArg.from_obj(func) + + if pass_arg is _PassArg.context: if context is None: raise TemplateRuntimeError( - "Attempted to invoke context filter without context" + f"Attempted to invoke a context {type_name} without context." ) + args.insert(0, context) - elif getattr(func, "evalcontextfilter", False) is True: + elif pass_arg is _PassArg.eval_context: 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. + args.insert(0, eval_ctx) + elif pass_arg is _PassArg.environment: + args.insert(0, self) + + return func(*args, **kwargs) + + def call_filter( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a filter on a value the same way the compiler does. + + This might return a coroutine if 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.tests.get(name) - if func is None: - fail_for_missing_callable("no test named %r", name) - return func(value, *(args or ()), **(kwargs or {})) + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, True + ) + + def call_test( + self, + name: str, + value: t.Any, + args: t.Optional[t.Sequence[t.Any]] = None, + kwargs: t.Optional[t.Mapping[str, t.Any]] = None, + context: t.Optional[Context] = None, + eval_ctx: t.Optional[EvalContext] = None, + ) -> t.Any: + """Invoke a test on a value the same way the compiler does. + + This might return a coroutine if the test is running from an + environment in async mode and the test supports async execution. + It's your responsibility to await this if needed. + + .. versionchanged:: 3.0 + Tests support ``@pass_context``, etc. decorators. Added + the ``context`` and ``eval_ctx`` parameters. + + .. versionadded:: 2.7 + """ + return self._filter_test_common( + name, value, args, kwargs, context, eval_ctx, False + ) @internalcode - def parse(self, source, name=None, filename=None): + def parse( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> nodes.Template: """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 @@ -534,11 +599,18 @@ class Environment(object): except TemplateSyntaxError: self.handle_exception(source=source) - def _parse(self, source, name, filename): + def _parse( + self, source: str, name: t.Optional[str], filename: t.Optional[str] + ) -> nodes.Template: """Internal parsing function used by `parse` and `compile`.""" - return Parser(self, source, name, encode_filename(filename)).parse() + return Parser(self, source, name, filename).parse() - def lex(self, source, name=None, filename=None): + def lex( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> t.Iterator[t.Tuple[int, str, str]]: """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 ` @@ -548,13 +620,18 @@ class Environment(object): of the extensions to be applied you have to filter source through the :meth:`preprocess` method. """ - source = text_type(source) + source = str(source) try: return self.lexer.tokeniter(source, name, filename) except TemplateSyntaxError: self.handle_exception(source=source) - def preprocess(self, source, name=None, filename=None): + def preprocess( + self, + source: str, + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + ) -> str: """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. @@ -562,28 +639,43 @@ class Environment(object): return reduce( lambda s, e: e.preprocess(s, name, filename), self.iter_extensions(), - text_type(source), + str(source), ) - def _tokenize(self, source, name, filename=None, state=None): + def _tokenize( + self, + source: str, + name: t.Optional[str], + filename: t.Optional[str] = None, + state: t.Optional[str] = None, + ) -> TokenStream: """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) + stream = ext.filter_stream(stream) # type: ignore + if not isinstance(stream, TokenStream): - stream = TokenStream(stream, name, filename) + stream = TokenStream(stream, name, filename) # type: ignore + return stream - def _generate(self, source, name, filename, defer_init=False): + def _generate( + self, + source: nodes.Template, + name: t.Optional[str], + filename: t.Optional[str], + defer_init: bool = False, + ) -> str: """Internal hook that can be overridden to hook a different generate method in. .. versionadded:: 2.5 """ - return generate( + return generate( # type: ignore source, self, name, @@ -592,16 +684,45 @@ class Environment(object): optimized=self.optimized, ) - def _compile(self, source, filename): + def _compile(self, source: str, filename: str) -> CodeType: """Internal hook that can be overridden to hook a different compile method in. .. versionadded:: 2.5 """ - return compile(source, filename, "exec") + return compile(source, filename, "exec") # type: ignore + + @typing.overload + def compile( # type: ignore + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[False]" = False, + defer_init: bool = False, + ) -> CodeType: + ... + + @typing.overload + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: "te.Literal[True]" = ..., + defer_init: bool = False, + ) -> str: + ... @internalcode - def compile(self, source, name=None, filename=None, raw=False, defer_init=False): + def compile( + self, + source: t.Union[str, nodes.Template], + name: t.Optional[str] = None, + filename: t.Optional[str] = None, + raw: bool = False, + defer_init: bool = False, + ) -> t.Union[str, CodeType]: """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. @@ -623,7 +744,7 @@ class Environment(object): """ source_hint = None try: - if isinstance(source, string_types): + if isinstance(source, str): source_hint = source source = self._parse(source, name, filename) source = self._generate(source, name, filename, defer_init=defer_init) @@ -631,13 +752,13 @@ class Environment(object): return source if filename is None: filename = "