From 6a17ef03318ec3a05cc827ad56fd15f57d42651e Mon Sep 17 00:00:00 2001 From: Vladimir Roncevic Date: Sat, 1 Nov 2025 08:01:09 +0100 Subject: [PATCH] [codecipher] Update setup.py removed License classifiers, update codecoverage --- .../workflows/codecipher_package_checker.yml | 4 +- .../workflows/codecipher_python3_build.yml | 2 +- README.md | 31 +- codecipher/__init__.py | 2 +- codecipher/a1z52n62/__init__.py | 22 +- codecipher/a1z52n62/decode.py | 16 +- codecipher/a1z52n62/encode.py | 16 +- codecipher/atbs/__init__.py | 22 +- codecipher/atbs/decode.py | 22 +- codecipher/atbs/encode.py | 22 +- codecipher/atbs/lookup_table.py | 16 +- codecipher/b64/__init__.py | 22 +- codecipher/b64/decode.py | 16 +- codecipher/b64/encode.py | 16 +- codecipher/caesar/__init__.py | 22 +- codecipher/caesar/decode.py | 16 +- codecipher/caesar/encode.py | 16 +- codecipher/vernam/__init__.py | 22 +- codecipher/vernam/decode.py | 16 +- codecipher/vernam/encode.py | 16 +- codecipher/vigenere/__init__.py | 22 +- codecipher/vigenere/decode.py | 22 +- codecipher/vigenere/encode.py | 22 +- codecipher/vigenere/key_generator.py | 16 +- codecipher/vigenere/lookup_table.py | 16 +- .../codecipher.a1z52n62.decode.doctree | Bin 25955 -> 25995 bytes .../doctrees/codecipher.a1z52n62.doctree | Bin 12558 -> 12598 bytes .../codecipher.a1z52n62.encode.doctree | Bin 25903 -> 25943 bytes .../doctrees/codecipher.atbs.decode.doctree | Bin 26055 -> 26095 bytes docs/build/doctrees/codecipher.atbs.doctree | Bin 12641 -> 12681 bytes .../doctrees/codecipher.atbs.encode.doctree | Bin 26017 -> 26057 bytes .../codecipher.atbs.lookup_table.doctree | Bin 6772 -> 6812 bytes .../doctrees/codecipher.b64.decode.doctree | Bin 25662 -> 25702 bytes docs/build/doctrees/codecipher.b64.doctree | Bin 12273 -> 12313 bytes .../doctrees/codecipher.b64.encode.doctree | Bin 25564 -> 25604 bytes .../doctrees/codecipher.caesar.decode.doctree | Bin 28622 -> 28662 bytes docs/build/doctrees/codecipher.caesar.doctree | Bin 12444 -> 12484 bytes .../doctrees/codecipher.caesar.encode.doctree | Bin 28584 -> 28624 bytes docs/build/doctrees/codecipher.doctree | Bin 7058 -> 7090 bytes .../doctrees/codecipher.vernam.decode.doctree | Bin 28526 -> 28566 bytes docs/build/doctrees/codecipher.vernam.doctree | Bin 12444 -> 12484 bytes .../doctrees/codecipher.vernam.encode.doctree | Bin 28488 -> 28528 bytes .../codecipher.vigenere.decode.doctree | Bin 38795 -> 38835 bytes .../doctrees/codecipher.vigenere.doctree | Bin 13132 -> 13172 bytes .../codecipher.vigenere.encode.doctree | Bin 38785 -> 38825 bytes .../codecipher.vigenere.key_generator.doctree | Bin 32340 -> 32380 bytes .../codecipher.vigenere.lookup_table.doctree | Bin 28817 -> 28857 bytes docs/build/doctrees/environment.pickle | Bin 763476 -> 765616 bytes docs/build/doctrees/index.doctree | Bin 24128 -> 24146 bytes docs/build/doctrees/modules.doctree | Bin 2773 -> 2788 bytes docs/build/html/.buildinfo | 2 +- .../html/_modules/codecipher/a1z52n62.html | 24 +- .../_modules/codecipher/a1z52n62/decode.html | 18 +- .../_modules/codecipher/a1z52n62/encode.html | 18 +- docs/build/html/_modules/codecipher/atbs.html | 24 +- .../html/_modules/codecipher/atbs/decode.html | 24 +- .../html/_modules/codecipher/atbs/encode.html | 24 +- docs/build/html/_modules/codecipher/b64.html | 24 +- .../html/_modules/codecipher/b64/decode.html | 18 +- .../html/_modules/codecipher/b64/encode.html | 18 +- .../html/_modules/codecipher/caesar.html | 24 +- .../_modules/codecipher/caesar/decode.html | 18 +- .../_modules/codecipher/caesar/encode.html | 18 +- .../html/_modules/codecipher/vernam.html | 24 +- .../_modules/codecipher/vernam/decode.html | 18 +- .../_modules/codecipher/vernam/encode.html | 18 +- .../html/_modules/codecipher/vigenere.html | 24 +- .../_modules/codecipher/vigenere/decode.html | 24 +- .../_modules/codecipher/vigenere/encode.html | 24 +- .../codecipher/vigenere/key_generator.html | 18 +- .../codecipher/vigenere/lookup_table.html | 18 +- docs/build/html/_modules/index.html | 2 +- docs/build/html/_sources/index.rst.txt | 2 +- .../html/codecipher.a1z52n62.decode.html | 4 +- .../html/codecipher.a1z52n62.encode.html | 4 +- docs/build/html/codecipher.a1z52n62.html | 4 +- docs/build/html/codecipher.atbs.decode.html | 4 +- docs/build/html/codecipher.atbs.encode.html | 4 +- docs/build/html/codecipher.atbs.html | 4 +- .../html/codecipher.atbs.lookup_table.html | 4 +- docs/build/html/codecipher.b64.decode.html | 4 +- docs/build/html/codecipher.b64.encode.html | 4 +- docs/build/html/codecipher.b64.html | 4 +- docs/build/html/codecipher.caesar.decode.html | 4 +- docs/build/html/codecipher.caesar.encode.html | 4 +- docs/build/html/codecipher.caesar.html | 4 +- docs/build/html/codecipher.html | 4 +- docs/build/html/codecipher.vernam.decode.html | 4 +- docs/build/html/codecipher.vernam.encode.html | 4 +- docs/build/html/codecipher.vernam.html | 4 +- .../html/codecipher.vigenere.decode.html | 4 +- .../html/codecipher.vigenere.encode.html | 4 +- docs/build/html/codecipher.vigenere.html | 4 +- .../codecipher.vigenere.key_generator.html | 4 +- .../codecipher.vigenere.lookup_table.html | 4 +- docs/build/html/genindex.html | 2 +- docs/build/html/index.html | 4 +- docs/build/html/modules.html | 2 +- docs/build/html/objects.inv | Bin 1243 -> 1243 bytes docs/build/html/py-modindex.html | 2 +- docs/build/html/search.html | 2 +- docs/build/html/searchindex.js | 2 +- docs/source/conf.py | 6 +- docs/source/index.rst | 2 +- setup.cfg | 44 -- setup.py | 31 +- tests/.coverage | Bin 53248 -> 53248 bytes tests/a1z52n62_test.py | 16 +- tests/atbs_test.py | 16 +- tests/ats_coverage.py | 215 +++++ tests/b64_test.py | 16 +- tests/caesar_test.py | 16 +- tests/codecipher_coverage.json | 1 + tests/codecipher_coverage.xml | 705 +++++++++++++++++ tests/htmlcov/class_index.html | 443 +++++++++++ tests/htmlcov/coverage_html_cb_6fb7b396.js | 733 ++++++++++++++++++ tests/htmlcov/favicon_32_cb_58284776.png | Bin 0 -> 1732 bytes tests/htmlcov/function_index.html | 675 ++++++++++++++++ tests/htmlcov/index.html | 258 ++++++ tests/htmlcov/keybd_closed_cb_ce680311.png | Bin 0 -> 9004 bytes tests/htmlcov/status.json | 1 + tests/htmlcov/style_cb_8e611ae1.css | 337 ++++++++ .../z_094bd7de807a5f14___init___py.html | 159 ++++ .../htmlcov/z_094bd7de807a5f14_decode_py.html | 207 +++++ .../htmlcov/z_094bd7de807a5f14_encode_py.html | 207 +++++ .../z_75799433d8182c47___init___py.html | 160 ++++ .../htmlcov/z_75799433d8182c47_decode_py.html | 226 ++++++ .../htmlcov/z_75799433d8182c47_encode_py.html | 226 ++++++ .../z_75799433d8182c47_key_generator_py.html | 216 ++++++ .../z_75799433d8182c47_lookup_table_py.html | 155 ++++ .../z_7dc3960ecaf412e4___init___py.html | 115 +++ .../z_8f54ab6b5b508ca0___init___py.html | 159 ++++ .../htmlcov/z_8f54ab6b5b508ca0_decode_py.html | 185 +++++ .../htmlcov/z_8f54ab6b5b508ca0_encode_py.html | 185 +++++ .../z_96938f9400a5cdf6___init___py.html | 159 ++++ .../htmlcov/z_96938f9400a5cdf6_decode_py.html | 196 +++++ .../htmlcov/z_96938f9400a5cdf6_encode_py.html | 196 +++++ .../z_9927f90504198b80___init___py.html | 159 ++++ .../htmlcov/z_9927f90504198b80_decode_py.html | 194 +++++ .../htmlcov/z_9927f90504198b80_encode_py.html | 194 +++++ .../z_9927f90504198b80_lookup_table_py.html | 144 ++++ .../z_aba196749d301797___init___py.html | 159 ++++ .../htmlcov/z_aba196749d301797_decode_py.html | 201 +++++ .../htmlcov/z_aba196749d301797_encode_py.html | 201 +++++ tests/run_coverage.sh | 8 +- tests/vernam_test.py | 16 +- tests/vigenere_test.py | 16 +- 147 files changed, 7938 insertions(+), 583 deletions(-) delete mode 100644 setup.cfg create mode 100644 tests/ats_coverage.py create mode 100644 tests/codecipher_coverage.json create mode 100644 tests/codecipher_coverage.xml create mode 100644 tests/htmlcov/class_index.html create mode 100644 tests/htmlcov/coverage_html_cb_6fb7b396.js create mode 100644 tests/htmlcov/favicon_32_cb_58284776.png create mode 100644 tests/htmlcov/function_index.html create mode 100644 tests/htmlcov/index.html create mode 100644 tests/htmlcov/keybd_closed_cb_ce680311.png create mode 100644 tests/htmlcov/status.json create mode 100644 tests/htmlcov/style_cb_8e611ae1.css create mode 100644 tests/htmlcov/z_094bd7de807a5f14___init___py.html create mode 100644 tests/htmlcov/z_094bd7de807a5f14_decode_py.html create mode 100644 tests/htmlcov/z_094bd7de807a5f14_encode_py.html create mode 100644 tests/htmlcov/z_75799433d8182c47___init___py.html create mode 100644 tests/htmlcov/z_75799433d8182c47_decode_py.html create mode 100644 tests/htmlcov/z_75799433d8182c47_encode_py.html create mode 100644 tests/htmlcov/z_75799433d8182c47_key_generator_py.html create mode 100644 tests/htmlcov/z_75799433d8182c47_lookup_table_py.html create mode 100644 tests/htmlcov/z_7dc3960ecaf412e4___init___py.html create mode 100644 tests/htmlcov/z_8f54ab6b5b508ca0___init___py.html create mode 100644 tests/htmlcov/z_8f54ab6b5b508ca0_decode_py.html create mode 100644 tests/htmlcov/z_8f54ab6b5b508ca0_encode_py.html create mode 100644 tests/htmlcov/z_96938f9400a5cdf6___init___py.html create mode 100644 tests/htmlcov/z_96938f9400a5cdf6_decode_py.html create mode 100644 tests/htmlcov/z_96938f9400a5cdf6_encode_py.html create mode 100644 tests/htmlcov/z_9927f90504198b80___init___py.html create mode 100644 tests/htmlcov/z_9927f90504198b80_decode_py.html create mode 100644 tests/htmlcov/z_9927f90504198b80_encode_py.html create mode 100644 tests/htmlcov/z_9927f90504198b80_lookup_table_py.html create mode 100644 tests/htmlcov/z_aba196749d301797___init___py.html create mode 100644 tests/htmlcov/z_aba196749d301797_decode_py.html create mode 100644 tests/htmlcov/z_aba196749d301797_encode_py.html diff --git a/.github/workflows/codecipher_package_checker.yml b/.github/workflows/codecipher_package_checker.yml index f7caa27..d7604ee 100755 --- a/.github/workflows/codecipher_package_checker.yml +++ b/.github/workflows/codecipher_package_checker.yml @@ -17,11 +17,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 - name: set up python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: install dependencies diff --git a/.github/workflows/codecipher_python3_build.yml b/.github/workflows/codecipher_python3_build.yml index 07675a7..58e29ec 100644 --- a/.github/workflows/codecipher_python3_build.yml +++ b/.github/workflows/codecipher_python3_build.yml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up python3 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install dependencies diff --git a/README.md b/README.md index 34651b3..49d4271 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ other information that should be provided before the modules are installed. - [Dependencies](#dependencies) - [Usage](#usage) - [Package structure](#package-structure) +- [Code coverage](#code-coverage) - [Docs](#docs) - [Contributing](#contributing) - [Copyright and Licence](#copyright-and-licence) @@ -235,6 +236,34 @@ Package structure 7 directories, 23 files ``` +### Code coverage + +| Name | Stmts | Miss | Cover | +|------|-------|------|-------| +| `codecipher/__init__.py` | 0 | 0 | 100%| +| `codecipher/a1z52n62/__init__.py` | 16 | 0 | 100%| +| `codecipher/a1z52n62/decode.py` | 32 | 2 | 94%| +| `codecipher/a1z52n62/encode.py` | 32 | 2 | 94%| +| `codecipher/atbs/__init__.py` | 16 | 0 | 100%| +| `codecipher/atbs/decode.py` | 29 | 2 | 93%| +| `codecipher/atbs/encode.py` | 29 | 2 | 93%| +| `codecipher/atbs/lookup_table.py` | 10 | 0 | 100%| +| `codecipher/b64/__init__.py` | 16 | 0 | 100%| +| `codecipher/b64/decode.py` | 24 | 2 | 92%| +| `codecipher/b64/encode.py` | 24 | 2 | 92%| +| `codecipher/caesar/__init__.py` | 16 | 0 | 100%| +| `codecipher/caesar/decode.py` | 41 | 2 | 95%| +| `codecipher/caesar/encode.py` | 41 | 2 | 95%| +| `codecipher/vernam/__init__.py` | 16 | 0 | 100%| +| `codecipher/vernam/decode.py` | 36 | 2 | 94%| +| `codecipher/vernam/encode.py` | 36 | 2 | 94%| +| `codecipher/vigenere/__init__.py` | 17 | 0 | 100%| +| `codecipher/vigenere/decode.py` | 37 | 2 | 95%| +| `codecipher/vigenere/encode.py` | 37 | 2 | 95%| +| `codecipher/vigenere/key_generator.py` | 37 | 2 | 95%| +| `codecipher/vigenere/lookup_table.py` | 16 | 0 | 100%| +| **Total** | 558 | 26 | 95% | + ### Docs [![documentation status](https://readthedocs.org/projects/codecipher/badge/?version=latest)](https://codecipher.readthedocs.io/en/latest/?badge=latest) @@ -252,7 +281,7 @@ More documentation and info at [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -Copyright (C) 2021 - 2024 by [electux.github.io/codecipher](https://electux.github.io/codecipher/) +Copyright (C) 2021 - 2025 by [electux.github.io/codecipher](https://electux.github.io/codecipher/) **codecipher** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/codecipher/__init__.py b/codecipher/__init__.py index 89e4273..f0ae770 100644 --- a/codecipher/__init__.py +++ b/codecipher/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or diff --git a/codecipher/a1z52n62/__init__.py b/codecipher/a1z52n62/__init__.py index bbdd5d5..899450c 100644 --- a/codecipher/a1z52n62/__init__.py +++ b/codecipher/a1z52n62/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.a1z52n62.encode import A1z52N62Encode from codecipher.a1z52n62.decode import A1z52N62Decode -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class A1z52N62(A1z52N62Encode, A1z52N62Decode): diff --git a/codecipher/a1z52n62/decode.py b/codecipher/a1z52n62/decode.py index 3eaab33..26be5a4 100644 --- a/codecipher/a1z52n62/decode.py +++ b/codecipher/a1z52n62/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/a1z52n62/encode.py b/codecipher/a1z52n62/encode.py index 37bfcf0..d121123 100644 --- a/codecipher/a1z52n62/encode.py +++ b/codecipher/a1z52n62/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/atbs/__init__.py b/codecipher/atbs/__init__.py index 4326e6a..6301b4c 100644 --- a/codecipher/atbs/__init__.py +++ b/codecipher/atbs/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.atbs.encode import AlephTawBetShinEncode from codecipher.atbs.decode import AlephTawBetShinDecode -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class AlephTawBetShin(AlephTawBetShinEncode, AlephTawBetShinDecode): diff --git a/codecipher/atbs/decode.py b/codecipher/atbs/decode.py index 465d9aa..21f9a3e 100644 --- a/codecipher/atbs/decode.py +++ b/codecipher/atbs/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.atbs.lookup_table import LOOKUP_TABLE -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/atbs/encode.py b/codecipher/atbs/encode.py index 444fc88..0305506 100644 --- a/codecipher/atbs/encode.py +++ b/codecipher/atbs/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.atbs.lookup_table import LOOKUP_TABLE -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/atbs/lookup_table.py b/codecipher/atbs/lookup_table.py index 7ef1bf0..5b24e76 100644 --- a/codecipher/atbs/lookup_table.py +++ b/codecipher/atbs/lookup_table.py @@ -4,7 +4,7 @@ Module lookup_table.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -21,14 +21,14 @@ from typing import List, Dict -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' LOOKUP_TABLE: Dict[str, str] = { 'A': 'Z', 'B': 'Y', 'C': 'X', 'D': 'W', 'E': 'V', diff --git a/codecipher/b64/__init__.py b/codecipher/b64/__init__.py index 3d171b1..5be2e31 100644 --- a/codecipher/b64/__init__.py +++ b/codecipher/b64/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.b64.encode import B64Encode from codecipher.b64.decode import B64Decode -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class B64(B64Encode, B64Decode): diff --git a/codecipher/b64/decode.py b/codecipher/b64/decode.py index 0b5c3cb..b3117d8 100644 --- a/codecipher/b64/decode.py +++ b/codecipher/b64/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -24,14 +24,14 @@ from base64 import b64decode from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/b64/encode.py b/codecipher/b64/encode.py index 0d0ee80..7bf6ae5 100644 --- a/codecipher/b64/encode.py +++ b/codecipher/b64/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -24,14 +24,14 @@ from base64 import b64encode from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/caesar/__init__.py b/codecipher/caesar/__init__.py index facc1ba..f299f48 100644 --- a/codecipher/caesar/__init__.py +++ b/codecipher/caesar/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.caesar.encode import CaesarEncode from codecipher.caesar.decode import CaesarDecode -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class Caesar(CaesarEncode, CaesarDecode): diff --git a/codecipher/caesar/decode.py b/codecipher/caesar/decode.py index 798924c..d64a273 100644 --- a/codecipher/caesar/decode.py +++ b/codecipher/caesar/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/caesar/encode.py b/codecipher/caesar/encode.py index ab66c98..69d50dd 100644 --- a/codecipher/caesar/encode.py +++ b/codecipher/caesar/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vernam/__init__.py b/codecipher/vernam/__init__.py index 64900de..3822bae 100644 --- a/codecipher/vernam/__init__.py +++ b/codecipher/vernam/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.vernam.encode import VernamEncode from codecipher.vernam.decode import VernamDecode -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class Vernam(VernamEncode, VernamDecode): diff --git a/codecipher/vernam/decode.py b/codecipher/vernam/decode.py index 05d1046..203ede9 100644 --- a/codecipher/vernam/decode.py +++ b/codecipher/vernam/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vernam/encode.py b/codecipher/vernam/encode.py index ae2e6c6..efcbdfc 100644 --- a/codecipher/vernam/encode.py +++ b/codecipher/vernam/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vigenere/__init__.py b/codecipher/vigenere/__init__.py index 5f0d551..2dd27c5 100644 --- a/codecipher/vigenere/__init__.py +++ b/codecipher/vigenere/__init__.py @@ -4,7 +4,7 @@ Module __init__.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -27,18 +27,18 @@ from codecipher.vigenere.encode import VigenereEncode from codecipher.vigenere.decode import VigenereDecode from codecipher.vigenere.key_generator import KeyGenerator -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class Vigenere(VigenereEncode, VigenereDecode, KeyGenerator): diff --git a/codecipher/vigenere/decode.py b/codecipher/vigenere/decode.py index b70ef5e..9c108a3 100644 --- a/codecipher/vigenere/decode.py +++ b/codecipher/vigenere/decode.py @@ -4,7 +4,7 @@ Module decode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.vigenere.lookup_table import LookUpTable -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vigenere/encode.py b/codecipher/vigenere/encode.py index f2a274a..44890d2 100644 --- a/codecipher/vigenere/encode.py +++ b/codecipher/vigenere/encode.py @@ -4,7 +4,7 @@ Module encode.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -26,18 +26,18 @@ try: from codecipher.vigenere.lookup_table import LookUpTable -except ImportError as ats_error_message: - # Force close python ATS ################################################## - sys.exit(f'\n{__file__}\n{ats_error_message}\n') +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vigenere/key_generator.py b/codecipher/vigenere/key_generator.py index 7927a58..6bc47ab 100644 --- a/codecipher/vigenere/key_generator.py +++ b/codecipher/vigenere/key_generator.py @@ -4,7 +4,7 @@ Module key_generator.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -23,14 +23,14 @@ from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' @dataclass diff --git a/codecipher/vigenere/lookup_table.py b/codecipher/vigenere/lookup_table.py index ad04d66..30ff8db 100644 --- a/codecipher/vigenere/lookup_table.py +++ b/codecipher/vigenere/lookup_table.py @@ -4,7 +4,7 @@ Module lookup_table.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -22,14 +22,14 @@ from typing import List, Dict -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class LookUpTable: diff --git a/docs/build/doctrees/codecipher.a1z52n62.decode.doctree b/docs/build/doctrees/codecipher.a1z52n62.decode.doctree index 5aa0ebc4c27d444ebf8a998f624100c7d15c8afa..0626828b82557f2e2d47db6b1d0cfb4ee694214c 100644 GIT binary patch delta 222 zcmaESin04NBTED8)P{{L)hz6?8Ic)s-b|D0SW*~GH;ZvhV47Uap2EmH`3Ac!SYS01 zkUGTW%EAp%%90_SQ9b!$g#6?_K~A7LWBv!M{6MkGlkc$0OlDKMJ6TXL8md+REDlu* zR^>1`KT4S|!!8427$Z;t&*TqUHk&zwTD=8|^7BjL3yMt<8 delta 207 zcmeA^&G`5fBTED8)QF8N)hx`?8LpELM#)cJ$>PXpvRRH}0@LJb_7q0m$q(3V!2+w9 zfYd22SCG$!fq%$s;CS^oV{tzm;*;T-t5vcMqs!D;$ z8w9nur89UkWHOjRx+nX4S#MSpYW1GHBi2L2o3V$tI5oK>uQWHlA}zltcZxUTW}!F* mM#i?y#_`{nn1EcZq!>nyGaL*I8L~aalMR%MH#4SmF#-TV*+PN< diff --git a/docs/build/doctrees/codecipher.a1z52n62.doctree b/docs/build/doctrees/codecipher.a1z52n62.doctree index 7c1eb6d979a8e097d94effbf5c012b9962c22ed9..fb5cce38673a027ec69cc286f1b588449cb2b5b1 100644 GIT binary patch delta 223 zcmeB6+Lpx9z&cfXBa0I|w`|6m3^{M64C#y+lP8KOOl}b2m|Vzi!DzbqF4qL6$yQt` zjLehgbJ>CgRx<&qPF`;os5Ta$wsSCTjLegSUNQ1-el3*G$Okc2AVWG!jgf%?ri7Ir zsA2Nt0ySl!jENZ#HH<)^{0x~4=FJC1%0vW;^7BjL3yMts?8KGA$UAvCmn~dyIuoPG=83%C zEX>jw=OzcTYXId1gkCWUZ2m2j&p5eAM2}Hm@MwSNFsXiN7s#(}&Ga@tOyqPA~v7|7XZWiO1z%;p-J%y2Z@(p%du)u02 zAa#h#m4zFklqEwtqk3|nmi**CK~A7LWBv!M{6MkGlkc$0OlDKMJ6TXL8md+REDlx6 z2~y>dA(O!j(k+x>mjN-55h%<965f14u+v+hC_ld>zMv>IEwf@u52OB+$>FhHLLEK4 t#i_|9d8N7W6>0fJxl=keZ;e%8WbD{{E$$l=kUEzb!^n7Uvvx8I69AyZNmKv; delta 204 zcmcb9igEoZMwSNFsVW;;s#%z&Gh8P#x+zRv#p1wdvRRH}0@LJb_7q0m$q(3V!2+w9 zfYd22SCG8O#vPew$wkc6v{4iS-ciX6)fDPE9V!E6t6sNXswEo#M^7`ChC7BV*g< i|8d`#n1I}Gi7|{EXE+!bGGu#-Cl~q@Z$6vc#RvfJn?cF| diff --git a/docs/build/doctrees/codecipher.atbs.decode.doctree b/docs/build/doctrees/codecipher.atbs.decode.doctree index 0009f506fcbcb12cc436204fb78e050c4402b327..8069bd6d9fab03ae4970b7b68842c08453397403 100644 GIT binary patch delta 227 zcmX?pn(_TE>VT6PPB4 zv!^gJPu|0B3l><-1f-U6xx%!u0JT-av;ozL^FL?g-~69HjS*_D08qhYxB~vk69u*S zAvQ7sWq2}VGMFdxnObaS6#C&UP?Vov5?@f1nwD8HrH4^}%H;2{UP2u`yv3=>C3&T} t@fB(LMY&TtHiyP3Ffw**E{p%h1f=qkVi;M@aWF7UHefE_?3&WV2mpHrN^k%G delta 204 zcmaEVn(_E)MwSNFse3lE#IrCGfMgV8=Ly-Ug diff --git a/docs/build/doctrees/codecipher.atbs.doctree b/docs/build/doctrees/codecipher.atbs.doctree index 718e1bf9a6d032f82de1b5fcd951a71c8ca3b12f..e4bf4dc6c01a31950c57aa657c827c4088f7bac0 100644 GIT binary patch delta 213 zcmaEu)S1lEz&f>VBa0n7yKKg~3^{M6$&TzPjHa7!a!p{GY{r$s$UJ#Amn~ReH4~6( z<@IKPDrK2`UQh=p|3~m6Bmd@iLbZ(C5Hkcaq_Z?88;Z+MelN(w$Uk|Oh?X!!hA~4r zqcB4zgSj**qj_?GzQp8uCjQNTMW%`f6y@ia#1|B$re#)4>0#8LGI@fgmrzF!Z*gjJ yNnUAgd_`J*QSOwE&F?f77#Zz0^J{-&V(i$=uGhfG(!$KZFj;`DX!BqF6h;87kVXvv delta 174 zcmeB7ewf74z&bT-Ba0n7vvkI+$sg3@C+Dy`GMa3D$Tfj!vK?0nBk$zJT()3=)l7^g zlOJ-4Y+lG~&NBIdpf*sBN9ZG?z~+BKwT#TtSsIfM$SY6IW#?cO$dJyMI{A&7vS7w! zAhR$-CWARcHe+3eoZsfxA_qh!@744W@n-DdEly1?$t%r`uSm-;%AMlPxLI6FfsxT> XvxW9ICMFE>VT6PPB4 zv!^gJPu|0B3l><-1f-U6xx%!u0JT-av;ozL^FL?g-~69HjS*_D08qhYxB~vk69u)P zGK@eOp2^(WHk%oRE_n+S<>!~g7ZjzYWmZh-Vbq^8`C_b>P)84MacXi&UTJQ8MOuDQ o?v#$r`f&=3j2)W;;=eHgDUYNWMwW9N3=ESEn9DcIr!+AF0R1*dApigX delta 190 zcmX?knsMQ2MwSNFsna&H#IrC`qE?1D&YM53=-pT6x&lv?a^9!Ug0wpfPB?Km~6x8CD z&fv+A$zaZq&4`>VV`{xwO6ZdJC3&T}@fB(LMY&VF88=77DKIj& YZLW;}#>52V79_KQ|M&`-C*locAtC@h* z6E0U4K8RA54C##O(xlYM5BX&$`|xuxGH(v$U&9DBNMMp+I6p)oBTykvhD-+Y=2XF0 zMuDRI{F3;BqSUm^iYYye`coz!5b_f0=;19+O)kkR&5f@}%P-2E(y>`iSb>qzYO}q_ gHzvl8&F11Uj2sP&3=A2vJ>`?@8TB@wlvvFO0QR~(`~Uy| delta 179 zcmbPZ`o)B$fpu!;MwYoOY|cHj`%#BB)DSdGxg!N|Kgm46K*Q1miP)JD*lPdbAqLnebcLpCEa zL(Xq=onS2EC3&T}@fB(LMY&VF88^END=;!zY|aq*#>52V#*4== MGS+S0Bk_O{0Gfimmy3$3s@ykJ0tUC0siNV{F{I9r!lfa%odm& zE2zWBKeWXSepPHynd+`J{JixB`y Cqf3GS delta 202 zcmaEMf^pvoMwSNFsm2>wB3PKEGh8PJddN?1V{v3O+5DS*0@LIO_7q0m$$Qyt!2+w9 zfYfp>SCGNQ)T7FUP6mQ1O-(wUQ a8QV5X#C>C80&@8iV;C9FY|csg#Rvd$;X$4N diff --git a/docs/build/doctrees/codecipher.b64.doctree b/docs/build/doctrees/codecipher.b64.doctree index 63f31f0f81186c4161cb9e2b31b9c20d1b4f0939..1b4715f660ce6087c664db16db10fe7254f232ad 100644 GIT binary patch delta 224 zcmewuKQn=~fpsdM!A4eoc5c~>H5qc=Oc~M{GbRU!C``5&;h1dCZoz1}c{SGrrpX*! zDU8gMbGdB60;`#TR5-6U3p+#`%jAWEIzahzf=@a4Go-WB7#SEQ7jnr=J}LKT@=oCd zK8P{_m=x3kM*hhjB3k?qNk*X6`57`9%$plTmIw!~g7ZjzYWmZh-Vbq^8SxLi7 ysH2CsI5oK>uQWHlA}zltcS^_R1`P#9Mw`tGHNP=2c5I%h)4<5sv{_2;IwJtm??p8L delta 179 zcmbQ4@G+jXfpzLL{f(^r?99>`GbUe9lAmnH?#O7exqKr-fuDPvw#Y z3r=8~?9408XfnBhU1W1HuQ|))O@i8typ!(5Tjg znGEI(*^D(Aa(bWxaG&*H#ny7>Uh7baF_pkVdn z5BxHdud>U61t%~~Zsw9^G@X2aMP&14E<>1h7O+Z)b`D17$pZYh8TmKA;rC;NnlAuU za2aYo2PZ#}=a3C3&T}@fB(LMY&TtHs{1BFfw**?v4G%1f*IMVi;M@aWF7U)@Cl<9F^3> F2mnsJPw4;v delta 179 zcmZoU!FcC5BTED8)QcNgB3PKEGh8Pxbd#Ul#^T6mviUdr1g6Om>?w@AllQXQf(2GH z0jcF&t{|n=Af;Rx&Ka^9kr{H{ypt99Z?g(yNM~H0e2`scvy6Zq;RQd0*@&m;#Pd>*kvsp#Jgb}Jx04xYq$O%&7 zkRg-74ALrSmjN-15h%(765YH<&>>8qC_ld>zMv>IEwf@u52OB+$-mOQggSb7i&K+J p@=9~#E7J0da;J1`j>u48WIVaKGV>b~W5?#goESz%{>A5VnE)vUNe2J` delta 222 zcmex%pYhy%MwSNFsfRbR?xeQ8PXZmrAZml zlh4OVO#Z|!3zl5X#Aq^EfJ0>S1ujF7)@rC$PDb9zru_Ff1%SFPLv=|`ex`V1GOu9t zcP4B4Li$%Z2Nlh-nHY%a-b GVgvw9W=Hk_ diff --git a/docs/build/doctrees/codecipher.caesar.doctree b/docs/build/doctrees/codecipher.caesar.doctree index 5f2b67c734670e02fd9223a5819414d36423944c..237d3989cc040fa1d56a0d8f3c6d097d8ce40f0d 100644 GIT binary patch delta 205 zcmbP}cqEaffpzN6jVyZX?6MhaGUU9OCL6M+Fq&>Y$u)s#vKm(kBlF~LE?cm`Y9=66 z%InPnRmw7Xzn~6K{*B-Z4*m@3EHy?3hROY0GMj%0c`!oN2u!vY(P!kJoG+p!46%SQ zLpmcrLnec{G%2HTaxRnl=1U^qg$0W8^Go6jic-@uE2i`?>Q9+`T*FJKqldRRHMu0O pG&jB?Ex#ytO2=kZO$A0qo6T-o-X25Y%Smo%~1e1*5>`r$X6`Y|>e3j0_Ag<5&fN z`X^78S5p?umvc)eNJA-Y&5KM>Rb%JT|o@k2xyf##HF$Yd~Yb`_e$C{UE2UlLzX zl$w@VF{Ou5f6C;m!d^lhJ-o%K$t8KEx$zZg`9--?IyM`NC@?bSZ4MFr#>CjM*+-&* Mk#WoBvyw*{0s6{0%>V!Z delta 144 zcmdmFKFOS=fpu#8Mizhe$^ox{k$(8HHnRFq#d*-=z@^CZ!mOiVz@9Ek=-#!Z{wN*-kd00WyYS^xk5 diff --git a/docs/build/doctrees/codecipher.vernam.decode.doctree b/docs/build/doctrees/codecipher.vernam.decode.doctree index c91651c2012c844ba7a4c70ba3b46b0bdc14764b..633f573ec4bf0d478dc830aaed973107736e4ccd 100644 GIT binary patch delta 221 zcmaENk8#?4MwSNFsofh{a#`4AGa@tOyqP8!u%s}WZsy>az%)6PJ%y2Z@+o#(u)u02 zAhm_dm4zFklqEwtqk8hhB!$T`{2V}as{Hp@`GI1WC!b@N*{mX9!U$C;02YKQzMv>IEwf@u52OB+$+ObEggSb7i&K+J p@=9~#E7J0da;J1`{*kW0$ar$IWac*}#*WQ`IWdfk{EPE)nE*RNM+5)> delta 222 zcmbPspYh#2MwSNFsmU8za#@(AGh8P#s>@HF&Em*tvRQy*0@LJN_7qOu4C##O(xi;& z$%d{HlRvS`f+bfoF`7&k;1Jn-fy)r2wHm6GlaY6_DgQlA0idqSP+gLfpDEs$%qti@ zxj;~x6(r*@xiMH-FvAYW+AI8GCq(Qb zN^|2Y((;RPr+71NR?JXfWIVpvDf1f>6Oe0}6T`^C%f-NuA={Hb*-#{Z@>*t&%_4bC Fi~#(fMMVGr diff --git a/docs/build/doctrees/codecipher.vernam.doctree b/docs/build/doctrees/codecipher.vernam.doctree index 357b72f0eb2d55aa6fd97690ca0085ba8a641e94..d2931197aa465b9f7e7847d4ddb9aeb31835e274 100644 GIT binary patch delta 205 zcmbP}cqEaffpzN6jVyZX?6MhaGUU9OCL6M+Fq&>Y$u)s#vKm(kBlF~LE?cm`Y9=66 z%InPnRmw7Xzn~6K{*B-Z4*m@3EHy?3hROY0GMj%0c`!oN2u!vY(P!kJoG+p!46%SQ zLpmcrLnec{G%2HTaxRnl=1U^qg$0W8^Go6jic-@uE2i`?>Q9+`T*FJKqldRRHMu0O pG&jB?Ex#ytO2=kZO$A0qo6T-o-X25Y%Smo%~1e1*5>`r$X6`Y|>e3j0_Ag<5&fN z`X^78S5p?umaz%)6PJ%y2Z@+o#(u)u02 zAhm_dm4zFklqEwtqk8f|e}&01{2V}as{Hp@`GI1WC!b@N*{mX9!U$C;02YKQDYWJU4fDDS1ujF7_G%>U9E`k^P5JL}3IKIphU%1@{7mu2 zWM0AO$pwPii~^JA2x@UlXYgdmWH4vQW<*YIG_l^yE7TM^d11PTh&N*oZ*gjJNnUAg nd_`J*QSKCP#?8Oe6&M+hZ52V3g^TyGV(4i$YlZm^S41} diff --git a/docs/build/doctrees/codecipher.vigenere.decode.doctree b/docs/build/doctrees/codecipher.vigenere.decode.doctree index 1abd571edc479a4ee6bed1c7fddbe0817837f891..4cd5db66cc4d47b9cc8e9d27fcdaa974b81efa82 100644 GIT binary patch delta 242 zcmeBP&$M|x6H5c@)D;_9s#(}&Ga@tOyqPA~v7|7XZWiO1z%;p-J%y7wLpr0nG$|u` za$=jrXe+!u5@Rz zpkOpqy#PoKrXH-)AwwpE86?7&VV40hlo6#_O9kCVpdL?AWX@C5Dkvc604i GJ|+NY7*Cr3 delta 207 zcmdnIo~e616H5c@)P{{L)hx`?8LpEjYRgYv$>PXpvRRH}0@LJb_7q0m$q(3V!2+w9 zfYd22SCG$!fq%$s;CS^oV=IfB$>?&Z+2vm6)Ri(h> z4T4(S(iuD%G8xPu-IMcTtT!tPEv}t>t=~h$o3V$tI5oK>uQWHlA}zltcZxUTW`hX| mjEq+|2TuIP#02DeOo?ISkmh4x$dK(Ro@}68yjgzQ6h;7XDnd8_ diff --git a/docs/build/doctrees/codecipher.vigenere.doctree b/docs/build/doctrees/codecipher.vigenere.doctree index b883f5cc4f127cba78ae294bb637877bf02895fd..1339d3a9066956273b5b219dc6365195769c6797 100644 GIT binary patch delta 206 zcmX?;_9cy_fpu!;MwZF!+_D)PGUU9OGNd!+Ox`G>G5HX?1*7R^J?;rile@W67?~%3 z;Iah^tY!jIw|Ko-pjudfS}uXK0M!Hvy<+6wY$Ke{$PO`2VDc&veMbJtw?wprAtH=G z<;58?8O)_g8Lg8qN@{Gj6EznTD9X<-i7zNhP0Os9(!;1fWpc5$mrzF!Z*gjJNnUAg nd_`J*QSOwE%@?&57#UMGf71EJ#MrUSFKq=z#-z>C dy5E?XfLtMi21b?@%nS^ZW7(=U3mBy^0sw~sKV$#^ diff --git a/docs/build/doctrees/codecipher.vigenere.encode.doctree b/docs/build/doctrees/codecipher.vigenere.encode.doctree index 086e90037cc31a1a5101da3cc87c56982daa10e6..e4a12f08a76fbaf22e84952f07fccc7394242dde 100644 GIT binary patch delta 249 zcmZo%&$Mzq6H5c@)Oj0Os#(}&Ga@tOyqPA~v7|7XZWiO1z%;p-J%y7wLpr0nG$|u` zGNY%&wbxKZVSGqG< zP%s**UH~KqQ_l)g=`cAUT3IN=E(2m9BT$GZLnecH^98|+wE{)?`6clMMX70-6;pZ` z^`}gp-|r>V(ZgGunp~1snj2q{mS2=RrDOBoeg#Ix>zm~!eq&w^OGu0s!7uQj`Dy delta 202 zcmZ3vo~dy?6H5c@)Uu5%)hx`?8LpEPWo0HWV{u_L*(}E~foXCzdkQ1(doB|or8JA0wGNLCx^po7|DqzkCRD2mj zvB2aFf?C|t89W&>8O$I9CfC+jZ&nnVSv&bmzlVr7V-Ig}YH~?lX>NQ)T7FUP6mQ1O eY7-O~8Lw`3pZJZ53COjZ62r(Sy?ORjJ|+MHO+g0$ diff --git a/docs/build/doctrees/codecipher.vigenere.key_generator.doctree b/docs/build/doctrees/codecipher.vigenere.key_generator.doctree index 1406609bd5992be49f55b91b54cfc4a6eb4067f4..a579002a8b4b81fcc878ffbb3417927e400efcda 100644 GIT binary patch delta 219 zcmccehw;xJMwSNFsf8O^4zqB}W<+Mlc{625XShxd440qGBg8rR6N?3->E<|&2~3lB zv!^gJPgdZt1q-ZZ0#aPut}N^jZ7h@h_;rBt)%>3r`8VeY)G$KL69Afb8D<_UKal4z z*`QciD8nuTqLUFQ#FHVD!8}<%*(6wZNqWt`l_=2L;w9JYrJ&gKOCP$Td33c@F v7N;hceSES_^?xeQ8PXZmrAZmllQ-r`O!nZA z1xv1G0#ZWUt}K(|`L!8&CwKFIViee1Cs4yUnMp{SQDCy3kQTRe22X}e26KjNM&#uA z5!RdM3tdZ|++OA(;?3B@Tb!C)l2@7=Uy+tylsm}27V&4|p9^JdDB&TyUFs3t%8K8qux>1IXNFHEe=K*8$C zu>vxa%{XMif)kh~KjD&QG@Y!-DzaIG+YqLm1*{UHos*Gyav}e7M*hu_0%?rw5c35l z?-SHvgeGuPE9V!E6t6sNXswEozk)SZH59PKo#J2tcB#xQbNb1*Pu U$oAAvimadfmYHMo$GioM02qKx?*IS* delta 204 zcmdn_ka6NeMwSNFscjoscCs)_XShzjpd&N+35yG($>tc22~3lBvZpZePL|`a1q-ZZ z0#Y2@t{|n=Af>#e8QK}n8L}CX8FJpdlNMobR$u-;rEWEM7gPlktxH)9WPacXi&UTJQ8MOuDQ?i6pv&0?7f bjEtW*n`eDvVghpYa$^`7EjM@P=`jHS5+XrC diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle index c37800fcd1593f63a77126176e2d57c2cc3d3dc5..364a3e079c4fc33ea9d23587c6b3b21d09b8e054 100644 GIT binary patch literal 765616 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

RW4DXJEs4|3rkR_nS6stAPnky6h8&;c{EP5n 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 z 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 N0YB?=4ftlo{|6rcqs#yR literal 763476 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%0DRmxv*6=g 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 diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree index 9db264e2690490de450cd1dd810d656956156bae..0be36e8aa57152d300c6ac0fee94a7de2907f632 100644 GIT binary patch delta 623 zcmX@Ghw;)LMwSNFsqPzDBsm%RHp_8_Ffj^lF6KVP$SAVej`uVpqts?D{#%TU;+vle zC^K=(X6R(ddGlpRXPHk<5R;g^fth`?k?;gYsDvO;A_Ok+M#L5-Ap(>rgi8dAWy2)I zff9Xii5KEUFbOH3#A>)iizFW_qxR;>a<)u75I1N8!pJyl zbFSAKn1WeA1%D9=oPG3|g&=-f0F=>ZWnjpV$za~x|;u9l_BO3$5Fq<+|<01#FEVXJcVK)T?$m;$~IXcN{-2mZL&j@D5Lx2>S!rOkIB=b6&XD@ J?}+YT0szLPzw`hA delta 577 zcmcb#hw;E3MwSNFsiqrQBsm!wHp_8_FafDz?o*6F%8vImh~nbE1)`n`C^PX&XPGlH zFl5MP=w!%wPo5YgyV*#10wYj31Wovjh%HFC5KTB(EE^=;hbH_&ya*(`8cn!Gl8+T= z^JF<&kj-{Xs5bvnn8C#4&A558vMU##be17AP+BH~8RWRh22Aps+4M4afV%Uo_JEwP zW3wJ)1qTbNA*^u3WD*AlbiYvd%tw%!1Nc`m6|tX2|(%ZuVcph(*{ja2X>TMD=7x zY4OSTbp$qx2FEf^ZVB-a@n-DdEly1?$t%r`uSm-;%AEoXhlrK!bJvK%MNM@um}O}2`bW^o28m?S4H tndJgf$)A&%oSIjhYNe1~kfTs$JSEF@axYM=+vF9|ij3}?Pepey0RYYFq*4F? diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree index aaddba16ab60cd301fb95300f21c6a18d8345b68..67458c1259a167f7122b108139e3de944574221d 100644 GIT binary patch delta 72 zcmcaA`b3nafpzN5jV#P80!8`xCGiDCscD%NQ+gQnr%YyL@e=Cj;Vn*0F3Bs+jju?{ cFUp<{9 delta 58 zcmaDNdR3IAfpzMsjV#P8lO diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo index 1ab6f58..969073b 100644 --- a/docs/build/html/.buildinfo +++ b/docs/build/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 60c181649dca153e7de237730f7adc94 +config: caefd34d4082d2b7f99de43a23803684 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_modules/codecipher/a1z52n62.html b/docs/build/html/_modules/codecipher/a1z52n62.html index ae2711d..482c58d 100644 --- a/docs/build/html/_modules/codecipher/a1z52n62.html +++ b/docs/build/html/_modules/codecipher/a1z52n62.html @@ -42,7 +42,7 @@

Source code for codecipher.a1z52n62

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -64,18 +64,18 @@ 

Source code for codecipher.a1z52n62

 try:
     from codecipher.a1z52n62.encode import A1z52N62Encode
     from codecipher.a1z52n62.decode import A1z52N62Decode
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -138,7 +138,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/a1z52n62/decode.html b/docs/build/html/_modules/codecipher/a1z52n62/decode.html index ac47854..6fd78a9 100644 --- a/docs/build/html/_modules/codecipher/a1z52n62/decode.html +++ b/docs/build/html/_modules/codecipher/a1z52n62/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.a1z52n62.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.a1z52n62.decode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -180,7 +180,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/a1z52n62/encode.html b/docs/build/html/_modules/codecipher/a1z52n62/encode.html index 26d292d..9855019 100644 --- a/docs/build/html/_modules/codecipher/a1z52n62/encode.html +++ b/docs/build/html/_modules/codecipher/a1z52n62/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.a1z52n62.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.a1z52n62.encode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -180,7 +180,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/atbs.html b/docs/build/html/_modules/codecipher/atbs.html index 83b3a13..e79f189 100644 --- a/docs/build/html/_modules/codecipher/atbs.html +++ b/docs/build/html/_modules/codecipher/atbs.html @@ -42,7 +42,7 @@

Source code for codecipher.atbs

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -64,18 +64,18 @@ 

Source code for codecipher.atbs

 try:
     from codecipher.atbs.encode import AlephTawBetShinEncode
     from codecipher.atbs.decode import AlephTawBetShinDecode
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -138,7 +138,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/atbs/decode.html b/docs/build/html/_modules/codecipher/atbs/decode.html index c1f065f..f3457cd 100644 --- a/docs/build/html/_modules/codecipher/atbs/decode.html +++ b/docs/build/html/_modules/codecipher/atbs/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.atbs.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -65,18 +65,18 @@ 

Source code for codecipher.atbs.decode

 
 try:
     from codecipher.atbs.lookup_table import LOOKUP_TABLE
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -178,7 +178,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/atbs/encode.html b/docs/build/html/_modules/codecipher/atbs/encode.html index e4ea49e..f23820c 100644 --- a/docs/build/html/_modules/codecipher/atbs/encode.html +++ b/docs/build/html/_modules/codecipher/atbs/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.atbs.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -65,18 +65,18 @@ 

Source code for codecipher.atbs.encode

 
 try:
     from codecipher.atbs.lookup_table import LOOKUP_TABLE
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -178,7 +178,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/b64.html b/docs/build/html/_modules/codecipher/b64.html index 944f451..16c4c0c 100644 --- a/docs/build/html/_modules/codecipher/b64.html +++ b/docs/build/html/_modules/codecipher/b64.html @@ -42,7 +42,7 @@

Source code for codecipher.b64

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -64,18 +64,18 @@ 

Source code for codecipher.b64

 try:
     from codecipher.b64.encode import B64Encode
     from codecipher.b64.decode import B64Decode
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -138,7 +138,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/b64/decode.html b/docs/build/html/_modules/codecipher/b64/decode.html index c22c376..28dd00b 100644 --- a/docs/build/html/_modules/codecipher/b64/decode.html +++ b/docs/build/html/_modules/codecipher/b64/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.b64.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -63,14 +63,14 @@ 

Source code for codecipher.b64.decode

 from base64 import b64decode
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -169,7 +169,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/b64/encode.html b/docs/build/html/_modules/codecipher/b64/encode.html index 114f864..66cdf78 100644 --- a/docs/build/html/_modules/codecipher/b64/encode.html +++ b/docs/build/html/_modules/codecipher/b64/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.b64.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -63,14 +63,14 @@ 

Source code for codecipher.b64.encode

 from base64 import b64encode
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -169,7 +169,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/caesar.html b/docs/build/html/_modules/codecipher/caesar.html index ffa4214..c87a550 100644 --- a/docs/build/html/_modules/codecipher/caesar.html +++ b/docs/build/html/_modules/codecipher/caesar.html @@ -42,7 +42,7 @@

Source code for codecipher.caesar

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -64,18 +64,18 @@ 

Source code for codecipher.caesar

 try:
     from codecipher.caesar.encode import CaesarEncode
     from codecipher.caesar.decode import CaesarDecode
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -138,7 +138,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/caesar/decode.html b/docs/build/html/_modules/codecipher/caesar/decode.html index e7e3ba2..f594e9f 100644 --- a/docs/build/html/_modules/codecipher/caesar/decode.html +++ b/docs/build/html/_modules/codecipher/caesar/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.caesar.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.caesar.decode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -191,7 +191,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/caesar/encode.html b/docs/build/html/_modules/codecipher/caesar/encode.html index a609dd9..fb6ce64 100644 --- a/docs/build/html/_modules/codecipher/caesar/encode.html +++ b/docs/build/html/_modules/codecipher/caesar/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.caesar.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.caesar.encode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -191,7 +191,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vernam.html b/docs/build/html/_modules/codecipher/vernam.html index a74de9a..9d7ca98 100644 --- a/docs/build/html/_modules/codecipher/vernam.html +++ b/docs/build/html/_modules/codecipher/vernam.html @@ -42,7 +42,7 @@

Source code for codecipher.vernam

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -64,18 +64,18 @@ 

Source code for codecipher.vernam

 try:
     from codecipher.vernam.encode import VernamEncode
     from codecipher.vernam.decode import VernamDecode
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -138,7 +138,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vernam/decode.html b/docs/build/html/_modules/codecipher/vernam/decode.html index f009eea..45b7e89 100644 --- a/docs/build/html/_modules/codecipher/vernam/decode.html +++ b/docs/build/html/_modules/codecipher/vernam/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.vernam.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.vernam.decode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -185,7 +185,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vernam/encode.html b/docs/build/html/_modules/codecipher/vernam/encode.html index 232a52e..55eb739 100644 --- a/docs/build/html/_modules/codecipher/vernam/encode.html +++ b/docs/build/html/_modules/codecipher/vernam/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.vernam.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -62,14 +62,14 @@ 

Source code for codecipher.vernam.encode

 from dataclasses import dataclass, field
 from typing import List, Optional
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -185,7 +185,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vigenere.html b/docs/build/html/_modules/codecipher/vigenere.html index f268606..18d789d 100644 --- a/docs/build/html/_modules/codecipher/vigenere.html +++ b/docs/build/html/_modules/codecipher/vigenere.html @@ -42,7 +42,7 @@

Source code for codecipher.vigenere

 Module
     __init__.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -65,18 +65,18 @@ 

Source code for codecipher.vigenere

     from codecipher.vigenere.encode import VigenereEncode
     from codecipher.vigenere.decode import VigenereDecode
     from codecipher.vigenere.key_generator import KeyGenerator
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -139,7 +139,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vigenere/decode.html b/docs/build/html/_modules/codecipher/vigenere/decode.html index c837bff..0ef04f3 100644 --- a/docs/build/html/_modules/codecipher/vigenere/decode.html +++ b/docs/build/html/_modules/codecipher/vigenere/decode.html @@ -43,7 +43,7 @@

Source code for codecipher.vigenere.decode

 Module
     decode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -65,18 +65,18 @@ 

Source code for codecipher.vigenere.decode

 
 try:
     from codecipher.vigenere.lookup_table import LookUpTable
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -213,7 +213,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vigenere/encode.html b/docs/build/html/_modules/codecipher/vigenere/encode.html index 5d9a193..7585dc7 100644 --- a/docs/build/html/_modules/codecipher/vigenere/encode.html +++ b/docs/build/html/_modules/codecipher/vigenere/encode.html @@ -43,7 +43,7 @@

Source code for codecipher.vigenere.encode

 Module
     encode.py
 Copyright
-    Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com>
+    Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com>
     codecipher is free software: you can redistribute it and/or modify it
     under the terms of the GNU General Public License as published by the
     Free Software Foundation, either version 3 of the License, or
@@ -65,18 +65,18 @@ 

Source code for codecipher.vigenere.encode

 
 try:
     from codecipher.vigenere.lookup_table import LookUpTable
-except ImportError as ats_error_message:
-    # Force close python ATS ##################################################
-    sys.exit(f'\n{__file__}\n{ats_error_message}\n')
+except ImportError as ats_error_message:  # pragma: no cover
+    # Force exit python #######################################################
+    sys.exit(f'\n{__file__}\n{ats_error_message}\n')  # pragma: no cover
 
-__author__ = 'Vladimir Roncevic'
-__copyright__ = '(C) 2024, https://electux.github.io/codecipher'
+__author__: str = 'Vladimir Roncevic'
+__copyright__: str = '(C) 2025, https://electux.github.io/codecipher'
 __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
-__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE'
-__version__ = '1.4.7'
-__maintainer__ = 'Vladimir Roncevic'
-__email__ = 'elektron.ronca@gmail.com'
-__status__ = 'Updated'
+__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE'
+__version__: str = '1.4.8'
+__maintainer__: str = 'Vladimir Roncevic'
+__email__: str = 'elektron.ronca@gmail.com'
+__status__: str = 'Updated'
 
 
 
@@ -213,7 +213,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vigenere/key_generator.html b/docs/build/html/_modules/codecipher/vigenere/key_generator.html index 166e2f3..6c2286c 100644 --- a/docs/build/html/_modules/codecipher/vigenere/key_generator.html +++ b/docs/build/html/_modules/codecipher/vigenere/key_generator.html @@ -43,7 +43,7 @@

Source code for codecipher.vigenere.key_generator

Module key_generator.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> + Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -62,14 +62,14 @@

Source code for codecipher.vigenere.key_generator

from dataclasses import dataclass, field from typing import List, Optional -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -200,7 +200,7 @@

Navigation

diff --git a/docs/build/html/_modules/codecipher/vigenere/lookup_table.html b/docs/build/html/_modules/codecipher/vigenere/lookup_table.html index 887f2db..aba76cc 100644 --- a/docs/build/html/_modules/codecipher/vigenere/lookup_table.html +++ b/docs/build/html/_modules/codecipher/vigenere/lookup_table.html @@ -43,7 +43,7 @@

Source code for codecipher.vigenere.lookup_table

Module lookup_table.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> + Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -61,14 +61,14 @@

Source code for codecipher.vigenere.lookup_table

from typing import List, Dict -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated'
@@ -136,7 +136,7 @@

Navigation

diff --git a/docs/build/html/_modules/index.html b/docs/build/html/_modules/index.html index c372bdd..490cbe4 100644 --- a/docs/build/html/_modules/index.html +++ b/docs/build/html/_modules/index.html @@ -91,7 +91,7 @@

Navigation

diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt index 45179ba..f6049b7 100644 --- a/docs/build/html/_sources/index.rst.txt +++ b/docs/build/html/_sources/index.rst.txt @@ -136,7 +136,7 @@ Copyright and licence .. |license: apache 2.0| image:: https://img.shields.io/badge/license-apache%202.0-blue.svg :target: https://opensource.org/licenses/apache-2.0 -Copyright (C) 2021 - 2024 by `electux.github.io/codecipher `_ +Copyright (C) 2021 - 2025 by `electux.github.io/codecipher `_ **codecipher** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/docs/build/html/codecipher.a1z52n62.decode.html b/docs/build/html/codecipher.a1z52n62.decode.html index 010ccdc..e946c86 100644 --- a/docs/build/html/codecipher.a1z52n62.decode.html +++ b/docs/build/html/codecipher.a1z52n62.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.a1z52n62.encode.html b/docs/build/html/codecipher.a1z52n62.encode.html index 298fb93..ce21f84 100644 --- a/docs/build/html/codecipher.a1z52n62.encode.html +++ b/docs/build/html/codecipher.a1z52n62.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.a1z52n62.html b/docs/build/html/codecipher.a1z52n62.html index d982f46..d46032c 100644 --- a/docs/build/html/codecipher.a1z52n62.html +++ b/docs/build/html/codecipher.a1z52n62.html @@ -77,7 +77,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -193,7 +193,7 @@

Navigation

diff --git a/docs/build/html/codecipher.atbs.decode.html b/docs/build/html/codecipher.atbs.decode.html index 1f09541..c12c3ac 100644 --- a/docs/build/html/codecipher.atbs.decode.html +++ b/docs/build/html/codecipher.atbs.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.atbs.encode.html b/docs/build/html/codecipher.atbs.encode.html index 942c2d8..4ba4db7 100644 --- a/docs/build/html/codecipher.atbs.encode.html +++ b/docs/build/html/codecipher.atbs.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.atbs.html b/docs/build/html/codecipher.atbs.html index 8130b1a..847b8d2 100644 --- a/docs/build/html/codecipher.atbs.html +++ b/docs/build/html/codecipher.atbs.html @@ -78,7 +78,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -194,7 +194,7 @@

Navigation

diff --git a/docs/build/html/codecipher.atbs.lookup_table.html b/docs/build/html/codecipher.atbs.lookup_table.html index 01ba754..9bd7c7b 100644 --- a/docs/build/html/codecipher.atbs.lookup_table.html +++ b/docs/build/html/codecipher.atbs.lookup_table.html @@ -51,7 +51,7 @@

Navigation

Module

lookup_table.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -129,7 +129,7 @@

Navigation

diff --git a/docs/build/html/codecipher.b64.decode.html b/docs/build/html/codecipher.b64.decode.html index 44637ea..4c64fc5 100644 --- a/docs/build/html/codecipher.b64.decode.html +++ b/docs/build/html/codecipher.b64.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.b64.encode.html b/docs/build/html/codecipher.b64.encode.html index 4b7bf9d..24d5d7b 100644 --- a/docs/build/html/codecipher.b64.encode.html +++ b/docs/build/html/codecipher.b64.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -208,7 +208,7 @@

Navigation

diff --git a/docs/build/html/codecipher.b64.html b/docs/build/html/codecipher.b64.html index 765a5e4..a280faf 100644 --- a/docs/build/html/codecipher.b64.html +++ b/docs/build/html/codecipher.b64.html @@ -77,7 +77,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -193,7 +193,7 @@

Navigation

diff --git a/docs/build/html/codecipher.caesar.decode.html b/docs/build/html/codecipher.caesar.decode.html index 01d8e98..2fba1fb 100644 --- a/docs/build/html/codecipher.caesar.decode.html +++ b/docs/build/html/codecipher.caesar.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -211,7 +211,7 @@

Navigation

diff --git a/docs/build/html/codecipher.caesar.encode.html b/docs/build/html/codecipher.caesar.encode.html index f47db95..0fa611b 100644 --- a/docs/build/html/codecipher.caesar.encode.html +++ b/docs/build/html/codecipher.caesar.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -211,7 +211,7 @@

Navigation

diff --git a/docs/build/html/codecipher.caesar.html b/docs/build/html/codecipher.caesar.html index 0f14fa1..e38e5d0 100644 --- a/docs/build/html/codecipher.caesar.html +++ b/docs/build/html/codecipher.caesar.html @@ -77,7 +77,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -193,7 +193,7 @@

Navigation

diff --git a/docs/build/html/codecipher.html b/docs/build/html/codecipher.html index 7e11d2b..e944f71 100644 --- a/docs/build/html/codecipher.html +++ b/docs/build/html/codecipher.html @@ -175,7 +175,7 @@

Subpackages
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -261,7 +261,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vernam.decode.html b/docs/build/html/codecipher.vernam.decode.html index 274196c..762f130 100644 --- a/docs/build/html/codecipher.vernam.decode.html +++ b/docs/build/html/codecipher.vernam.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -211,7 +211,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vernam.encode.html b/docs/build/html/codecipher.vernam.encode.html index e356e31..086f5f3 100644 --- a/docs/build/html/codecipher.vernam.encode.html +++ b/docs/build/html/codecipher.vernam.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -211,7 +211,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vernam.html b/docs/build/html/codecipher.vernam.html index c209dab..9ff0eed 100644 --- a/docs/build/html/codecipher.vernam.html +++ b/docs/build/html/codecipher.vernam.html @@ -77,7 +77,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -193,7 +193,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vigenere.decode.html b/docs/build/html/codecipher.vigenere.decode.html index db93501..5f0b518 100644 --- a/docs/build/html/codecipher.vigenere.decode.html +++ b/docs/build/html/codecipher.vigenere.decode.html @@ -51,7 +51,7 @@

Navigation

Module

decode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -236,7 +236,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vigenere.encode.html b/docs/build/html/codecipher.vigenere.encode.html index 34ba5e5..314a859 100644 --- a/docs/build/html/codecipher.vigenere.encode.html +++ b/docs/build/html/codecipher.vigenere.encode.html @@ -51,7 +51,7 @@

Navigation

Module

encode.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -236,7 +236,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vigenere.html b/docs/build/html/codecipher.vigenere.html index 5762e1c..87b388a 100644 --- a/docs/build/html/codecipher.vigenere.html +++ b/docs/build/html/codecipher.vigenere.html @@ -102,7 +102,7 @@

Submodules
Module

__init__.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -218,7 +218,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vigenere.key_generator.html b/docs/build/html/codecipher.vigenere.key_generator.html index 4042edc..b1db8c9 100644 --- a/docs/build/html/codecipher.vigenere.key_generator.html +++ b/docs/build/html/codecipher.vigenere.key_generator.html @@ -51,7 +51,7 @@

Navigation

Module

key_generator.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -231,7 +231,7 @@

Navigation

diff --git a/docs/build/html/codecipher.vigenere.lookup_table.html b/docs/build/html/codecipher.vigenere.lookup_table.html index d6f5c17..5ab7cd8 100644 --- a/docs/build/html/codecipher.vigenere.lookup_table.html +++ b/docs/build/html/codecipher.vigenere.lookup_table.html @@ -47,7 +47,7 @@

Navigation

Module

lookup_table.py

-
Copyright

Copyright (C) 2021 - 2024 Vladimir Roncevic <elektron.ronca@gmail.com> +

Copyright

Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -194,7 +194,7 @@

Navigation

diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html index 2b8e1f5..32d3457 100644 --- a/docs/build/html/genindex.html +++ b/docs/build/html/genindex.html @@ -545,7 +545,7 @@

Navigation

diff --git a/docs/build/html/index.html b/docs/build/html/index.html index 0b759c8..df28275 100644 --- a/docs/build/html/index.html +++ b/docs/build/html/index.html @@ -148,7 +148,7 @@

Package structure

Copyright and licence¶

license: gpl v3 license: apache 2.0

-

Copyright (C) 2021 - 2024 by electux.github.io/codecipher

+

Copyright (C) 2021 - 2025 by electux.github.io/codecipher

codecipher is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, at your option, any later version of Python 3 you may have available.

@@ -227,7 +227,7 @@

Navigation

diff --git a/docs/build/html/modules.html b/docs/build/html/modules.html index 97c8b06..576e9ee 100644 --- a/docs/build/html/modules.html +++ b/docs/build/html/modules.html @@ -146,7 +146,7 @@

Navigation

diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv index f717bd051b00b28be8334ac375bd3c9a2ed9cd5b..28c94bec193212a106fe14c83e6c25e3b6b04494 100644 GIT binary patch delta 12 Tcmcc3d7E>B6QjjO=NT*jAHM`- delta 12 Tcmcc3d7E>B6QlV?=NT*jAG!o% diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html index 3415f1e..7710cfe 100644 --- a/docs/build/html/py-modindex.html +++ b/docs/build/html/py-modindex.html @@ -196,7 +196,7 @@

Navigation

diff --git a/docs/build/html/search.html b/docs/build/html/search.html index b5946a0..e3ff178 100644 --- a/docs/build/html/search.html +++ b/docs/build/html/search.html @@ -95,7 +95,7 @@

Navigation

diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 1cbde71..53ef145 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["codecipher", "codecipher.a1z52n62", "codecipher.a1z52n62.decode", "codecipher.a1z52n62.encode", "codecipher.atbs", "codecipher.atbs.decode", "codecipher.atbs.encode", "codecipher.atbs.lookup_table", "codecipher.b64", "codecipher.b64.decode", "codecipher.b64.encode", "codecipher.caesar", "codecipher.caesar.decode", "codecipher.caesar.encode", "codecipher.vernam", "codecipher.vernam.decode", "codecipher.vernam.encode", "codecipher.vigenere", "codecipher.vigenere.decode", "codecipher.vigenere.encode", "codecipher.vigenere.key_generator", "codecipher.vigenere.lookup_table", "index", "modules"], "filenames": ["codecipher.rst", "codecipher.a1z52n62.rst", "codecipher.a1z52n62.decode.rst", "codecipher.a1z52n62.encode.rst", "codecipher.atbs.rst", "codecipher.atbs.decode.rst", "codecipher.atbs.encode.rst", "codecipher.atbs.lookup_table.rst", "codecipher.b64.rst", "codecipher.b64.decode.rst", "codecipher.b64.encode.rst", "codecipher.caesar.rst", "codecipher.caesar.decode.rst", "codecipher.caesar.encode.rst", "codecipher.vernam.rst", "codecipher.vernam.decode.rst", "codecipher.vernam.encode.rst", "codecipher.vigenere.rst", "codecipher.vigenere.decode.rst", "codecipher.vigenere.encode.rst", "codecipher.vigenere.key_generator.rst", "codecipher.vigenere.lookup_table.rst", "index.rst", "modules.rst"], "titles": ["codecipher package", "codecipher.a1z52n62 package", "codecipher.a1z52n62.decode module", "codecipher.a1z52n62.encode module", "codecipher.atbs package", "codecipher.atbs.decode module", "codecipher.atbs.encode module", "codecipher.atbs.lookup_table module", "codecipher.b64 package", "codecipher.b64.decode module", "codecipher.b64.encode module", "codecipher.caesar package", "codecipher.caesar.decode module", "codecipher.caesar.encode module", "codecipher.vernam package", "codecipher.vernam.decode module", "codecipher.vernam.encode module", "codecipher.vigenere package", "codecipher.vigenere.decode module", "codecipher.vigenere.encode module", "codecipher.vigenere.key_generator module", "codecipher.vigenere.lookup_table module", "CODECipher", "codecipher"], "terms": {"a1z52n62": [0, 22, 23], "submodul": [0, 23], "decod": [0, 1, 4, 8, 11, 14, 17, 20, 21, 22], "a1z52n62decod": [0, 1, 2], "encod": [0, 1, 4, 8, 11, 14, 17, 20, 21, 22], "a1z52n62encod": [0, 1, 3], "atb": [0, 22, 23], "alephtawbetshindecod": [0, 4, 5, 9], "alephtawbetshinencod": [0, 4, 6], "lookup_t": [0, 4, 17, 22], "alephtawbetshin": [0, 4, 5, 6, 7, 9, 10], "b64": [0, 22, 23], "b64decod": [0, 8, 9], "b64encod": [0, 8, 10], "caesar": [0, 22, 23], "caesardecod": [0, 11, 12], "caesarencod": [0, 11, 13], "vernam": [0, 22, 23], "vernamdecod": [0, 14, 15], "vernamencod": [0, 14, 16], "vigener": [0, 22, 23], "vigeneredecod": [0, 17, 18], "vigenereencod": [0, 17, 19], "key_gener": [0, 17, 22], "keygener": [0, 17, 20], "lookupt": [0, 17, 21], "__init__": [0, 1, 4, 8, 11, 14, 17, 22], "py": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "copyright": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "2021": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "2024": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "vladimir": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "roncev": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "elektron": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "ronca": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "gmail": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "com": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "free": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "softwar": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "you": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "can": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "redistribut": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "modifi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "under": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "term": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "gnu": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "gener": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "public": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "licens": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "publish": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "foundat": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "either": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "version": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "3": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "your": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "option": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "ani": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "later": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "distribut": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "hope": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "us": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "without": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "warranti": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "even": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "impli": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "merchant": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "fit": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "FOR": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "A": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "particular": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "purpos": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "see": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "more": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "detail": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "should": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "have": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "receiv": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "copi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "along": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "program": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "If": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "http": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "www": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "org": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "_decode_data": [1, 2, 4, 5, 8, 9, 11, 12, 14, 15, 17, 18], "decode_data": [1, 2, 4, 5, 8, 9, 11, 12, 14, 15, 17, 18], "_encode_data": [1, 3, 4, 6, 8, 10, 11, 13, 14, 16, 17, 19], "encode_data": [1, 3, 4, 6, 8, 10, 11, 13, 14, 16, 17, 19], "info": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "defin": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "class": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "attribut": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "method": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "creat": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "contain": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22], "aggreg": [1, 4, 8, 11, 14, 17, 21], "backend": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "api": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "sourc": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "base": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "It": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "none": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "initi": [1, 4, 8, 11, 14, 17], "constructor": [1, 4, 8, 11, 14, 17], "str": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21], "object": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21], "data": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "properti": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "from": [2, 5, 9, 12, 15, 18], "format": [2, 3, 5, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19], "paramet": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19], "which": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19], "return": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "except": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "get": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "type": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 22], "dict": [7, 21], "shift_count": [12, 13], "int": [12, 13, 20, 21], "shift": [12, 13], "count": [12, 13], "kei": [15, 16, 17, 18, 19, 20], "_split_data_decod": [17, 18], "_split_data_encod": [17, 19], "_data_len": [17, 20], "_kei": [17, 20], "data_len": [17, 20], "generate_kei": [17, 20], "alpha": [17, 21], "alphanum": [17, 21], "index_to_lett": [17, 21], "letter_to_index": [17, 21], "num": [17, 21], "white_spac": [17, 21], "_split_data": [18, 19], "split": [18, 19], "data_to_decod": 18, "list": [18, 19], "data_to_encod": 19, "vigen": 20, "length": 20, "lookup": 21, "tabl": 21, "support": [21, 22], "alphabet": 21, "numer": 21, "white": 21, "space": 21, "char": 21, "index": [21, 22], "letter": 21, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz": 21, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789": 21, "0": 21, "1": 21, "b": 21, "2": 21, "d": 21, "4": 21, "e": 21, "5": 21, "f": 21, "6": 21, "g": 21, "7": [21, 22], "h": 21, "8": 21, "9": 21, "j": 21, "10": 21, "k": 21, "11": 21, "l": 21, "12": 21, "m": [21, 22], "13": 21, "n": 21, "14": 21, "o": 21, "15": 21, "p": 21, "16": 21, "q": 21, "17": 21, "r": [21, 22], "18": 21, "19": 21, "t": 21, "20": 21, "u": 21, "21": 21, "v": 21, "22": 21, "w": 21, "23": [21, 22], "x": [21, 22], "24": 21, "y": [21, 22], "25": 21, "z": [21, 22], "26": 21, "27": 21, "28": 21, "29": 21, "30": 21, "31": 21, "32": 21, "33": 21, "34": 21, "35": 21, "36": 21, "37": 21, "38": 21, "39": 21, "40": 21, "41": 21, "42": 21, "43": 21, "44": 21, "45": 21, "46": 21, "47": 21, "48": 21, "49": 21, "50": 21, "51": 21, "52": 21, "53": 21, "54": 21, "55": 21, "56": 21, "57": 21, "58": 21, "59": 21, "60": 21, "61": 21, "62": 21, "0123456789": 21, "cipher": 22, "util": 22, "develop": 22, "python": 22, "code": 22, "The": 22, "readm": 22, "introduc": 22, "modul": [22, 23], "provid": 22, "instruct": 22, "how": 22, "machin": 22, "mai": 22, "other": 22, "inform": 22, "befor": 22, "ar": 22, "subpackag": [22, 23], "next": 22, "environ": 22, "navig": 22, "releas": 22, "page": 22, "download": 22, "extract": 22, "archiv": 22, "To": 22, "follow": 22, "tar": 22, "xvzf": 22, "gz": 22, "cd": 22, "pyton3": 22, "pip3": 22, "requir": 22, "txt": 22, "python3": 22, "build": 22, "isol": 22, "wheel": 22, "py3": 22, "whl": 22, "old": 22, "fashion": 22, "wai": 22, "setup": 22, "install_lib": 22, "install_egg_info": 22, "docker": 22, "imag": 22, "pip": 22, "librari": 22, "oop": 22, "directori": 22, "file": 22, "electux": 22, "github": 22, "io": 22, "same": 22, "itself": 22, "avail": 22, "let": 22, "help": 22, "psf": 22, "search": 22, "packag": 23, "content": 23}, "objects": {"": [[0, 0, 0, "-", "codecipher"]], "codecipher": [[1, 0, 0, "-", "a1z52n62"], [4, 0, 0, "-", "atbs"], [8, 0, 0, "-", "b64"], [11, 0, 0, "-", "caesar"], [14, 0, 0, "-", "vernam"], [17, 0, 0, "-", "vigenere"]], "codecipher.a1z52n62": [[1, 1, 1, "", "A1z52N62"], [2, 0, 0, "-", "decode"], [3, 0, 0, "-", "encode"]], "codecipher.a1z52n62.decode": [[2, 1, 1, "", "A1z52N62Decode"]], "codecipher.a1z52n62.decode.A1z52N62Decode": [[2, 2, 1, "", "_decode_data"], [2, 3, 1, "", "decode"], [2, 4, 1, "", "decode_data"]], "codecipher.a1z52n62.encode": [[3, 1, 1, "", "A1z52N62Encode"]], "codecipher.a1z52n62.encode.A1z52N62Encode": [[3, 2, 1, "", "_encode_data"], [3, 3, 1, "", "encode"], [3, 4, 1, "", "encode_data"]], "codecipher.atbs": [[4, 1, 1, "", "AlephTawBetShin"], [5, 0, 0, "-", "decode"], [6, 0, 0, "-", "encode"], [7, 0, 0, "-", "lookup_table"]], "codecipher.atbs.decode": [[5, 1, 1, "", "AlephTawBetShinDecode"]], "codecipher.atbs.decode.AlephTawBetShinDecode": [[5, 2, 1, "", "_decode_data"], [5, 3, 1, "", "decode"], [5, 4, 1, "", "decode_data"]], "codecipher.atbs.encode": [[6, 1, 1, "", "AlephTawBetShinEncode"]], "codecipher.atbs.encode.AlephTawBetShinEncode": [[6, 2, 1, "", "_encode_data"], [6, 3, 1, "", "encode"], [6, 4, 1, "", "encode_data"]], "codecipher.b64": [[8, 1, 1, "", "B64"], [9, 0, 0, "-", "decode"], [10, 0, 0, "-", "encode"]], "codecipher.b64.decode": [[9, 1, 1, "", "B64Decode"]], "codecipher.b64.decode.B64Decode": [[9, 2, 1, "", "_decode_data"], [9, 3, 1, "", "decode"], [9, 4, 1, "", "decode_data"]], "codecipher.b64.encode": [[10, 1, 1, "", "B64Encode"]], "codecipher.b64.encode.B64Encode": [[10, 2, 1, "", "_encode_data"], [10, 3, 1, "", "encode"], [10, 4, 1, "", "encode_data"]], "codecipher.caesar": [[11, 1, 1, "", "Caesar"], [12, 0, 0, "-", "decode"], [13, 0, 0, "-", "encode"]], "codecipher.caesar.decode": [[12, 1, 1, "", "CaesarDecode"]], "codecipher.caesar.decode.CaesarDecode": [[12, 2, 1, "", "_decode_data"], [12, 3, 1, "", "decode"], [12, 4, 1, "", "decode_data"]], "codecipher.caesar.encode": [[13, 1, 1, "", "CaesarEncode"]], "codecipher.caesar.encode.CaesarEncode": [[13, 2, 1, "", "_encode_data"], [13, 3, 1, "", "encode"], [13, 4, 1, "", "encode_data"]], "codecipher.vernam": [[14, 1, 1, "", "Vernam"], [15, 0, 0, "-", "decode"], [16, 0, 0, "-", "encode"]], "codecipher.vernam.decode": [[15, 1, 1, "", "VernamDecode"]], "codecipher.vernam.decode.VernamDecode": [[15, 2, 1, "", "_decode_data"], [15, 3, 1, "", "decode"], [15, 4, 1, "", "decode_data"]], "codecipher.vernam.encode": [[16, 1, 1, "", "VernamEncode"]], "codecipher.vernam.encode.VernamEncode": [[16, 2, 1, "", "_encode_data"], [16, 3, 1, "", "encode"], [16, 4, 1, "", "encode_data"]], "codecipher.vigenere": [[17, 1, 1, "", "Vigenere"], [18, 0, 0, "-", "decode"], [19, 0, 0, "-", "encode"], [20, 0, 0, "-", "key_generator"], [21, 0, 0, "-", "lookup_table"]], "codecipher.vigenere.decode": [[18, 1, 1, "", "VigenereDecode"]], "codecipher.vigenere.decode.VigenereDecode": [[18, 2, 1, "", "_decode_data"], [18, 3, 1, "", "_split_data_decode"], [18, 3, 1, "", "decode"], [18, 4, 1, "", "decode_data"]], "codecipher.vigenere.encode": [[19, 1, 1, "", "VigenereEncode"]], "codecipher.vigenere.encode.VigenereEncode": [[19, 2, 1, "", "_encode_data"], [19, 3, 1, "", "_split_data_encode"], [19, 3, 1, "", "encode"], [19, 4, 1, "", "encode_data"]], "codecipher.vigenere.key_generator": [[20, 1, 1, "", "KeyGenerator"]], "codecipher.vigenere.key_generator.KeyGenerator": [[20, 2, 1, "", "_data_len"], [20, 2, 1, "", "_key"], [20, 4, 1, "", "data_len"], [20, 3, 1, "", "generate_key"], [20, 4, 1, "", "key"]], "codecipher.vigenere.lookup_table": [[21, 1, 1, "", "LookUpTable"]], "codecipher.vigenere.lookup_table.LookUpTable": [[21, 2, 1, "", "ALPHA"], [21, 2, 1, "", "ALPHANUM"], [21, 2, 1, "", "INDEX_TO_LETTER"], [21, 2, 1, "", "LETTER_TO_INDEX"], [21, 2, 1, "", "NUM"], [21, 2, 1, "", "WHITE_SPACE"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:attribute", "3": "py:method", "4": "py:property"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"], "4": ["py", "property", "Python property"]}, "titleterms": {"codeciph": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], "packag": [0, 1, 4, 8, 11, 14, 17, 22], "subpackag": 0, "modul": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "content": [0, 1, 4, 8, 11, 14, 17, 22], "a1z52n62": [1, 2, 3], "submodul": [1, 4, 8, 11, 14, 17], "decod": [2, 5, 9, 12, 15, 18], "encod": [3, 6, 10, 13, 16, 19], "atb": [4, 5, 6, 7], "lookup_t": [7, 21], "b64": [8, 9, 10], "caesar": [11, 12, 13], "vernam": [14, 15, 16], "vigener": [17, 18, 19, 20, 21], "key_gener": 20, "instal": 22, "depend": 22, "structur": 22, "copyright": 22, "licenc": 22, "indic": 22, "tabl": 22}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"codecipher package": [[0, "codecipher-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-codecipher"], [1, "module-codecipher.a1z52n62"], [4, "module-codecipher.atbs"], [8, "module-codecipher.b64"], [11, "module-codecipher.caesar"], [14, "module-codecipher.vernam"], [17, "module-codecipher.vigenere"]], "codecipher.a1z52n62 package": [[1, "codecipher-a1z52n62-package"]], "Submodules": [[1, "submodules"], [4, "submodules"], [8, "submodules"], [11, "submodules"], [14, "submodules"], [17, "submodules"]], "codecipher.a1z52n62.decode module": [[2, "module-codecipher.a1z52n62.decode"]], "codecipher.a1z52n62.encode module": [[3, "module-codecipher.a1z52n62.encode"]], "codecipher.atbs package": [[4, "codecipher-atbs-package"]], "codecipher.atbs.decode module": [[5, "module-codecipher.atbs.decode"]], "codecipher.atbs.encode module": [[6, "module-codecipher.atbs.encode"]], "codecipher.atbs.lookup_table module": [[7, "module-codecipher.atbs.lookup_table"]], "codecipher.b64 package": [[8, "codecipher-b64-package"]], "codecipher.b64.decode module": [[9, "module-codecipher.b64.decode"]], "codecipher.b64.encode module": [[10, "module-codecipher.b64.encode"]], "codecipher.caesar package": [[11, "codecipher-caesar-package"]], "codecipher.caesar.decode module": [[12, "module-codecipher.caesar.decode"]], "codecipher.caesar.encode module": [[13, "module-codecipher.caesar.encode"]], "codecipher.vernam package": [[14, "codecipher-vernam-package"]], "codecipher.vernam.decode module": [[15, "module-codecipher.vernam.decode"]], "codecipher.vernam.encode module": [[16, "module-codecipher.vernam.encode"]], "codecipher.vigenere package": [[17, "codecipher-vigenere-package"]], "codecipher.vigenere.decode module": [[18, "module-codecipher.vigenere.decode"]], "codecipher.vigenere.encode module": [[19, "module-codecipher.vigenere.encode"]], "codecipher.vigenere.key_generator module": [[20, "module-codecipher.vigenere.key_generator"]], "codecipher.vigenere.lookup_table module": [[21, "module-codecipher.vigenere.lookup_table"]], "CODECipher": [[22, "codecipher"]], "Contents": [[22, null]], "Installation": [[22, "installation"]], "Dependencies": [[22, "dependencies"]], "Package structure": [[22, "package-structure"]], "Copyright and licence": [[22, "copyright-and-licence"]], "Indices and tables": [[22, "indices-and-tables"]], "codecipher": [[23, "codecipher"]]}, "indexentries": {"codecipher": [[0, "module-codecipher"]], "module": [[0, "module-codecipher"], [1, "module-codecipher.a1z52n62"], [2, "module-codecipher.a1z52n62.decode"], [3, "module-codecipher.a1z52n62.encode"], [4, "module-codecipher.atbs"], [5, "module-codecipher.atbs.decode"], [6, "module-codecipher.atbs.encode"], [7, "module-codecipher.atbs.lookup_table"], [8, "module-codecipher.b64"], [9, "module-codecipher.b64.decode"], [10, "module-codecipher.b64.encode"], [11, "module-codecipher.caesar"], [12, "module-codecipher.caesar.decode"], [13, "module-codecipher.caesar.encode"], [14, "module-codecipher.vernam"], [15, "module-codecipher.vernam.decode"], [16, "module-codecipher.vernam.encode"], [17, "module-codecipher.vigenere"], [18, "module-codecipher.vigenere.decode"], [19, "module-codecipher.vigenere.encode"], [20, "module-codecipher.vigenere.key_generator"], [21, "module-codecipher.vigenere.lookup_table"]], "a1z52n62 (class in codecipher.a1z52n62)": [[1, "codecipher.a1z52n62.A1z52N62"]], "codecipher.a1z52n62": [[1, "module-codecipher.a1z52n62"]], "a1z52n62decode (class in codecipher.a1z52n62.decode)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode"]], "_decode_data (codecipher.a1z52n62.decode.a1z52n62decode attribute)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode._decode_data"]], "codecipher.a1z52n62.decode": [[2, "module-codecipher.a1z52n62.decode"]], "decode() (codecipher.a1z52n62.decode.a1z52n62decode method)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode.decode"]], "decode_data (codecipher.a1z52n62.decode.a1z52n62decode property)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode.decode_data"]], "a1z52n62encode (class in codecipher.a1z52n62.encode)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode"]], "_encode_data (codecipher.a1z52n62.encode.a1z52n62encode attribute)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode._encode_data"]], "codecipher.a1z52n62.encode": [[3, "module-codecipher.a1z52n62.encode"]], "encode() (codecipher.a1z52n62.encode.a1z52n62encode method)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode.encode"]], "encode_data (codecipher.a1z52n62.encode.a1z52n62encode property)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode.encode_data"]], "alephtawbetshin (class in codecipher.atbs)": [[4, "codecipher.atbs.AlephTawBetShin"]], "codecipher.atbs": [[4, "module-codecipher.atbs"]], "alephtawbetshindecode (class in codecipher.atbs.decode)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode"]], "_decode_data (codecipher.atbs.decode.alephtawbetshindecode attribute)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode._decode_data"]], "codecipher.atbs.decode": [[5, "module-codecipher.atbs.decode"]], "decode() (codecipher.atbs.decode.alephtawbetshindecode method)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode.decode"]], "decode_data (codecipher.atbs.decode.alephtawbetshindecode property)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode.decode_data"]], "alephtawbetshinencode (class in codecipher.atbs.encode)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode"]], "_encode_data (codecipher.atbs.encode.alephtawbetshinencode attribute)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode._encode_data"]], "codecipher.atbs.encode": [[6, "module-codecipher.atbs.encode"]], "encode() (codecipher.atbs.encode.alephtawbetshinencode method)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode.encode"]], "encode_data (codecipher.atbs.encode.alephtawbetshinencode property)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode.encode_data"]], "codecipher.atbs.lookup_table": [[7, "module-codecipher.atbs.lookup_table"]], "b64 (class in codecipher.b64)": [[8, "codecipher.b64.B64"]], "codecipher.b64": [[8, "module-codecipher.b64"]], "b64decode (class in codecipher.b64.decode)": [[9, "codecipher.b64.decode.B64Decode"]], "_decode_data (codecipher.b64.decode.b64decode attribute)": [[9, "codecipher.b64.decode.B64Decode._decode_data"]], "codecipher.b64.decode": [[9, "module-codecipher.b64.decode"]], "decode() (codecipher.b64.decode.b64decode method)": [[9, "codecipher.b64.decode.B64Decode.decode"]], "decode_data (codecipher.b64.decode.b64decode property)": [[9, "codecipher.b64.decode.B64Decode.decode_data"]], "b64encode (class in codecipher.b64.encode)": [[10, "codecipher.b64.encode.B64Encode"]], "_encode_data (codecipher.b64.encode.b64encode attribute)": [[10, "codecipher.b64.encode.B64Encode._encode_data"]], "codecipher.b64.encode": [[10, "module-codecipher.b64.encode"]], "encode() (codecipher.b64.encode.b64encode method)": [[10, "codecipher.b64.encode.B64Encode.encode"]], "encode_data (codecipher.b64.encode.b64encode property)": [[10, "codecipher.b64.encode.B64Encode.encode_data"]], "caesar (class in codecipher.caesar)": [[11, "codecipher.caesar.Caesar"]], "codecipher.caesar": [[11, "module-codecipher.caesar"]], "caesardecode (class in codecipher.caesar.decode)": [[12, "codecipher.caesar.decode.CaesarDecode"]], "_decode_data (codecipher.caesar.decode.caesardecode attribute)": [[12, "codecipher.caesar.decode.CaesarDecode._decode_data"]], "codecipher.caesar.decode": [[12, "module-codecipher.caesar.decode"]], "decode() (codecipher.caesar.decode.caesardecode method)": [[12, "codecipher.caesar.decode.CaesarDecode.decode"]], "decode_data (codecipher.caesar.decode.caesardecode property)": [[12, "codecipher.caesar.decode.CaesarDecode.decode_data"]], "caesarencode (class in codecipher.caesar.encode)": [[13, "codecipher.caesar.encode.CaesarEncode"]], "_encode_data (codecipher.caesar.encode.caesarencode attribute)": [[13, "codecipher.caesar.encode.CaesarEncode._encode_data"]], "codecipher.caesar.encode": [[13, "module-codecipher.caesar.encode"]], "encode() (codecipher.caesar.encode.caesarencode method)": [[13, "codecipher.caesar.encode.CaesarEncode.encode"]], "encode_data (codecipher.caesar.encode.caesarencode property)": [[13, "codecipher.caesar.encode.CaesarEncode.encode_data"]], "vernam (class in codecipher.vernam)": [[14, "codecipher.vernam.Vernam"]], "codecipher.vernam": [[14, "module-codecipher.vernam"]], "vernamdecode (class in codecipher.vernam.decode)": [[15, "codecipher.vernam.decode.VernamDecode"]], "_decode_data (codecipher.vernam.decode.vernamdecode attribute)": [[15, "codecipher.vernam.decode.VernamDecode._decode_data"]], "codecipher.vernam.decode": [[15, "module-codecipher.vernam.decode"]], "decode() (codecipher.vernam.decode.vernamdecode method)": [[15, "codecipher.vernam.decode.VernamDecode.decode"]], "decode_data (codecipher.vernam.decode.vernamdecode property)": [[15, "codecipher.vernam.decode.VernamDecode.decode_data"]], "vernamencode (class in codecipher.vernam.encode)": [[16, "codecipher.vernam.encode.VernamEncode"]], "_encode_data (codecipher.vernam.encode.vernamencode attribute)": [[16, "codecipher.vernam.encode.VernamEncode._encode_data"]], "codecipher.vernam.encode": [[16, "module-codecipher.vernam.encode"]], "encode() (codecipher.vernam.encode.vernamencode method)": [[16, "codecipher.vernam.encode.VernamEncode.encode"]], "encode_data (codecipher.vernam.encode.vernamencode property)": [[16, "codecipher.vernam.encode.VernamEncode.encode_data"]], "vigenere (class in codecipher.vigenere)": [[17, "codecipher.vigenere.Vigenere"]], "codecipher.vigenere": [[17, "module-codecipher.vigenere"]], "vigeneredecode (class in codecipher.vigenere.decode)": [[18, "codecipher.vigenere.decode.VigenereDecode"]], "_decode_data (codecipher.vigenere.decode.vigeneredecode attribute)": [[18, "codecipher.vigenere.decode.VigenereDecode._decode_data"]], "_split_data_decode() (codecipher.vigenere.decode.vigeneredecode method)": [[18, "codecipher.vigenere.decode.VigenereDecode._split_data_decode"]], "codecipher.vigenere.decode": [[18, "module-codecipher.vigenere.decode"]], "decode() (codecipher.vigenere.decode.vigeneredecode method)": [[18, "codecipher.vigenere.decode.VigenereDecode.decode"]], "decode_data (codecipher.vigenere.decode.vigeneredecode property)": [[18, "codecipher.vigenere.decode.VigenereDecode.decode_data"]], "vigenereencode (class in codecipher.vigenere.encode)": [[19, "codecipher.vigenere.encode.VigenereEncode"]], "_encode_data (codecipher.vigenere.encode.vigenereencode attribute)": [[19, "codecipher.vigenere.encode.VigenereEncode._encode_data"]], "_split_data_encode() (codecipher.vigenere.encode.vigenereencode method)": [[19, "codecipher.vigenere.encode.VigenereEncode._split_data_encode"]], "codecipher.vigenere.encode": [[19, "module-codecipher.vigenere.encode"]], "encode() (codecipher.vigenere.encode.vigenereencode method)": [[19, "codecipher.vigenere.encode.VigenereEncode.encode"]], "encode_data (codecipher.vigenere.encode.vigenereencode property)": [[19, "codecipher.vigenere.encode.VigenereEncode.encode_data"]], "keygenerator (class in codecipher.vigenere.key_generator)": [[20, "codecipher.vigenere.key_generator.KeyGenerator"]], "_data_len (codecipher.vigenere.key_generator.keygenerator attribute)": [[20, "codecipher.vigenere.key_generator.KeyGenerator._data_len"]], "_key (codecipher.vigenere.key_generator.keygenerator attribute)": [[20, "codecipher.vigenere.key_generator.KeyGenerator._key"]], "codecipher.vigenere.key_generator": [[20, "module-codecipher.vigenere.key_generator"]], "data_len (codecipher.vigenere.key_generator.keygenerator property)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.data_len"]], "generate_key() (codecipher.vigenere.key_generator.keygenerator method)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.generate_key"]], "key (codecipher.vigenere.key_generator.keygenerator property)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.key"]], "alpha (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.ALPHA"]], "alphanum (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.ALPHANUM"]], "index_to_letter (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.INDEX_TO_LETTER"]], "letter_to_index (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.LETTER_TO_INDEX"]], "lookuptable (class in codecipher.vigenere.lookup_table)": [[21, "codecipher.vigenere.lookup_table.LookUpTable"]], "num (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.NUM"]], "white_space (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.WHITE_SPACE"]], "codecipher.vigenere.lookup_table": [[21, "module-codecipher.vigenere.lookup_table"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["codecipher", "codecipher.a1z52n62", "codecipher.a1z52n62.decode", "codecipher.a1z52n62.encode", "codecipher.atbs", "codecipher.atbs.decode", "codecipher.atbs.encode", "codecipher.atbs.lookup_table", "codecipher.b64", "codecipher.b64.decode", "codecipher.b64.encode", "codecipher.caesar", "codecipher.caesar.decode", "codecipher.caesar.encode", "codecipher.vernam", "codecipher.vernam.decode", "codecipher.vernam.encode", "codecipher.vigenere", "codecipher.vigenere.decode", "codecipher.vigenere.encode", "codecipher.vigenere.key_generator", "codecipher.vigenere.lookup_table", "index", "modules"], "filenames": ["codecipher.rst", "codecipher.a1z52n62.rst", "codecipher.a1z52n62.decode.rst", "codecipher.a1z52n62.encode.rst", "codecipher.atbs.rst", "codecipher.atbs.decode.rst", "codecipher.atbs.encode.rst", "codecipher.atbs.lookup_table.rst", "codecipher.b64.rst", "codecipher.b64.decode.rst", "codecipher.b64.encode.rst", "codecipher.caesar.rst", "codecipher.caesar.decode.rst", "codecipher.caesar.encode.rst", "codecipher.vernam.rst", "codecipher.vernam.decode.rst", "codecipher.vernam.encode.rst", "codecipher.vigenere.rst", "codecipher.vigenere.decode.rst", "codecipher.vigenere.encode.rst", "codecipher.vigenere.key_generator.rst", "codecipher.vigenere.lookup_table.rst", "index.rst", "modules.rst"], "titles": ["codecipher package", "codecipher.a1z52n62 package", "codecipher.a1z52n62.decode module", "codecipher.a1z52n62.encode module", "codecipher.atbs package", "codecipher.atbs.decode module", "codecipher.atbs.encode module", "codecipher.atbs.lookup_table module", "codecipher.b64 package", "codecipher.b64.decode module", "codecipher.b64.encode module", "codecipher.caesar package", "codecipher.caesar.decode module", "codecipher.caesar.encode module", "codecipher.vernam package", "codecipher.vernam.decode module", "codecipher.vernam.encode module", "codecipher.vigenere package", "codecipher.vigenere.decode module", "codecipher.vigenere.encode module", "codecipher.vigenere.key_generator module", "codecipher.vigenere.lookup_table module", "CODECipher", "codecipher"], "terms": {"a1z52n62": [0, 22, 23], "submodul": [0, 23], "decod": [0, 1, 4, 8, 11, 14, 17, 20, 21, 22], "a1z52n62decod": [0, 1, 2], "encod": [0, 1, 4, 8, 11, 14, 17, 20, 21, 22], "a1z52n62encod": [0, 1, 3], "atb": [0, 22, 23], "alephtawbetshindecod": [0, 4, 5, 9], "alephtawbetshinencod": [0, 4, 6], "lookup_t": [0, 4, 17, 22], "alephtawbetshin": [0, 4, 5, 6, 7, 9, 10], "b64": [0, 22, 23], "b64decod": [0, 8, 9], "b64encod": [0, 8, 10], "caesar": [0, 22, 23], "caesardecod": [0, 11, 12], "caesarencod": [0, 11, 13], "vernam": [0, 22, 23], "vernamdecod": [0, 14, 15], "vernamencod": [0, 14, 16], "vigener": [0, 22, 23], "vigeneredecod": [0, 17, 18], "vigenereencod": [0, 17, 19], "key_gener": [0, 17, 22], "keygener": [0, 17, 20], "lookupt": [0, 17, 21], "__init__": [0, 1, 4, 8, 11, 14, 17, 22], "py": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "copyright": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "2021": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "2025": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "vladimir": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "roncev": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "elektron": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "ronca": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "gmail": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "com": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "free": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "softwar": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "you": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "can": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "redistribut": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "modifi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "under": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "term": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "gnu": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "gener": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "public": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "licens": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "publish": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "foundat": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "either": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "version": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "3": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "your": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "option": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "ani": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "later": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "distribut": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "hope": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "us": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "without": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "warranti": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "even": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "impli": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "merchant": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "fit": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "FOR": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "A": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "particular": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "purpos": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "see": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "more": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "detail": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "should": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "have": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "receiv": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "copi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "along": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "thi": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "program": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "If": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "http": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "www": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "org": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "_decode_data": [1, 2, 4, 5, 8, 9, 11, 12, 14, 15, 17, 18], "decode_data": [1, 2, 4, 5, 8, 9, 11, 12, 14, 15, 17, 18], "_encode_data": [1, 3, 4, 6, 8, 10, 11, 13, 14, 16, 17, 19], "encode_data": [1, 3, 4, 6, 8, 10, 11, 13, 14, 16, 17, 19], "info": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "defin": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "class": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "attribut": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "method": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "creat": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "contain": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22], "aggreg": [1, 4, 8, 11, 14, 17, 21], "backend": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "api": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], "sourc": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "base": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "It": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "none": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22], "initi": [1, 4, 8, 11, 14, 17], "constructor": [1, 4, 8, 11, 14, 17], "str": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21], "object": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 21], "data": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "properti": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "from": [2, 5, 9, 12, 15, 18], "format": [2, 3, 5, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19], "paramet": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19], "which": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19], "return": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "except": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "get": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20], "type": [2, 3, 5, 6, 9, 10, 12, 13, 15, 16, 18, 19, 20, 22], "dict": [7, 21], "shift_count": [12, 13], "int": [12, 13, 20, 21], "shift": [12, 13], "count": [12, 13], "kei": [15, 16, 17, 18, 19, 20], "_split_data_decod": [17, 18], "_split_data_encod": [17, 19], "_data_len": [17, 20], "_kei": [17, 20], "data_len": [17, 20], "generate_kei": [17, 20], "alpha": [17, 21], "alphanum": [17, 21], "index_to_lett": [17, 21], "letter_to_index": [17, 21], "num": [17, 21], "white_spac": [17, 21], "_split_data": [18, 19], "split": [18, 19], "data_to_decod": 18, "list": [18, 19], "data_to_encod": 19, "vigen": 20, "length": 20, "lookup": 21, "tabl": 21, "support": [21, 22], "alphabet": 21, "numer": 21, "white": 21, "space": 21, "char": 21, "index": [21, 22], "letter": 21, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz": 21, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789": 21, "0": 21, "1": 21, "b": 21, "2": 21, "d": 21, "4": 21, "e": 21, "5": 21, "f": 21, "6": 21, "g": 21, "7": [21, 22], "h": 21, "8": 21, "9": 21, "j": 21, "10": 21, "k": 21, "11": 21, "l": 21, "12": 21, "m": [21, 22], "13": 21, "n": 21, "14": 21, "o": 21, "15": 21, "p": 21, "16": 21, "q": 21, "17": 21, "r": [21, 22], "18": 21, "19": 21, "t": 21, "20": 21, "u": 21, "21": 21, "v": 21, "22": 21, "w": 21, "23": [21, 22], "x": [21, 22], "24": 21, "y": [21, 22], "25": 21, "z": [21, 22], "26": 21, "27": 21, "28": 21, "29": 21, "30": 21, "31": 21, "32": 21, "33": 21, "34": 21, "35": 21, "36": 21, "37": 21, "38": 21, "39": 21, "40": 21, "41": 21, "42": 21, "43": 21, "44": 21, "45": 21, "46": 21, "47": 21, "48": 21, "49": 21, "50": 21, "51": 21, "52": 21, "53": 21, "54": 21, "55": 21, "56": 21, "57": 21, "58": 21, "59": 21, "60": 21, "61": 21, "62": 21, "0123456789": 21, "cipher": 22, "util": 22, "develop": 22, "python": 22, "code": 22, "The": 22, "readm": 22, "introduc": 22, "modul": [22, 23], "provid": 22, "instruct": 22, "how": 22, "machin": 22, "mai": 22, "other": 22, "inform": 22, "befor": 22, "ar": 22, "subpackag": [22, 23], "next": 22, "environ": 22, "navig": 22, "releas": 22, "page": 22, "download": 22, "extract": 22, "archiv": 22, "To": 22, "follow": 22, "tar": 22, "xvzf": 22, "gz": 22, "cd": 22, "pyton3": 22, "pip3": 22, "requir": 22, "txt": 22, "python3": 22, "build": 22, "isol": 22, "wheel": 22, "py3": 22, "whl": 22, "old": 22, "fashion": 22, "wai": 22, "setup": 22, "install_lib": 22, "install_egg_info": 22, "docker": 22, "imag": 22, "pip": 22, "librari": 22, "oop": 22, "directori": 22, "file": 22, "electux": 22, "github": 22, "io": 22, "same": 22, "itself": 22, "avail": 22, "let": 22, "help": 22, "psf": 22, "search": 22, "packag": 23, "content": 23}, "objects": {"": [[0, 0, 0, "-", "codecipher"]], "codecipher": [[1, 0, 0, "-", "a1z52n62"], [4, 0, 0, "-", "atbs"], [8, 0, 0, "-", "b64"], [11, 0, 0, "-", "caesar"], [14, 0, 0, "-", "vernam"], [17, 0, 0, "-", "vigenere"]], "codecipher.a1z52n62": [[1, 1, 1, "", "A1z52N62"], [2, 0, 0, "-", "decode"], [3, 0, 0, "-", "encode"]], "codecipher.a1z52n62.decode": [[2, 1, 1, "", "A1z52N62Decode"]], "codecipher.a1z52n62.decode.A1z52N62Decode": [[2, 2, 1, "", "_decode_data"], [2, 3, 1, "", "decode"], [2, 4, 1, "", "decode_data"]], "codecipher.a1z52n62.encode": [[3, 1, 1, "", "A1z52N62Encode"]], "codecipher.a1z52n62.encode.A1z52N62Encode": [[3, 2, 1, "", "_encode_data"], [3, 3, 1, "", "encode"], [3, 4, 1, "", "encode_data"]], "codecipher.atbs": [[4, 1, 1, "", "AlephTawBetShin"], [5, 0, 0, "-", "decode"], [6, 0, 0, "-", "encode"], [7, 0, 0, "-", "lookup_table"]], "codecipher.atbs.decode": [[5, 1, 1, "", "AlephTawBetShinDecode"]], "codecipher.atbs.decode.AlephTawBetShinDecode": [[5, 2, 1, "", "_decode_data"], [5, 3, 1, "", "decode"], [5, 4, 1, "", "decode_data"]], "codecipher.atbs.encode": [[6, 1, 1, "", "AlephTawBetShinEncode"]], "codecipher.atbs.encode.AlephTawBetShinEncode": [[6, 2, 1, "", "_encode_data"], [6, 3, 1, "", "encode"], [6, 4, 1, "", "encode_data"]], "codecipher.b64": [[8, 1, 1, "", "B64"], [9, 0, 0, "-", "decode"], [10, 0, 0, "-", "encode"]], "codecipher.b64.decode": [[9, 1, 1, "", "B64Decode"]], "codecipher.b64.decode.B64Decode": [[9, 2, 1, "", "_decode_data"], [9, 3, 1, "", "decode"], [9, 4, 1, "", "decode_data"]], "codecipher.b64.encode": [[10, 1, 1, "", "B64Encode"]], "codecipher.b64.encode.B64Encode": [[10, 2, 1, "", "_encode_data"], [10, 3, 1, "", "encode"], [10, 4, 1, "", "encode_data"]], "codecipher.caesar": [[11, 1, 1, "", "Caesar"], [12, 0, 0, "-", "decode"], [13, 0, 0, "-", "encode"]], "codecipher.caesar.decode": [[12, 1, 1, "", "CaesarDecode"]], "codecipher.caesar.decode.CaesarDecode": [[12, 2, 1, "", "_decode_data"], [12, 3, 1, "", "decode"], [12, 4, 1, "", "decode_data"]], "codecipher.caesar.encode": [[13, 1, 1, "", "CaesarEncode"]], "codecipher.caesar.encode.CaesarEncode": [[13, 2, 1, "", "_encode_data"], [13, 3, 1, "", "encode"], [13, 4, 1, "", "encode_data"]], "codecipher.vernam": [[14, 1, 1, "", "Vernam"], [15, 0, 0, "-", "decode"], [16, 0, 0, "-", "encode"]], "codecipher.vernam.decode": [[15, 1, 1, "", "VernamDecode"]], "codecipher.vernam.decode.VernamDecode": [[15, 2, 1, "", "_decode_data"], [15, 3, 1, "", "decode"], [15, 4, 1, "", "decode_data"]], "codecipher.vernam.encode": [[16, 1, 1, "", "VernamEncode"]], "codecipher.vernam.encode.VernamEncode": [[16, 2, 1, "", "_encode_data"], [16, 3, 1, "", "encode"], [16, 4, 1, "", "encode_data"]], "codecipher.vigenere": [[17, 1, 1, "", "Vigenere"], [18, 0, 0, "-", "decode"], [19, 0, 0, "-", "encode"], [20, 0, 0, "-", "key_generator"], [21, 0, 0, "-", "lookup_table"]], "codecipher.vigenere.decode": [[18, 1, 1, "", "VigenereDecode"]], "codecipher.vigenere.decode.VigenereDecode": [[18, 2, 1, "", "_decode_data"], [18, 3, 1, "", "_split_data_decode"], [18, 3, 1, "", "decode"], [18, 4, 1, "", "decode_data"]], "codecipher.vigenere.encode": [[19, 1, 1, "", "VigenereEncode"]], "codecipher.vigenere.encode.VigenereEncode": [[19, 2, 1, "", "_encode_data"], [19, 3, 1, "", "_split_data_encode"], [19, 3, 1, "", "encode"], [19, 4, 1, "", "encode_data"]], "codecipher.vigenere.key_generator": [[20, 1, 1, "", "KeyGenerator"]], "codecipher.vigenere.key_generator.KeyGenerator": [[20, 2, 1, "", "_data_len"], [20, 2, 1, "", "_key"], [20, 4, 1, "", "data_len"], [20, 3, 1, "", "generate_key"], [20, 4, 1, "", "key"]], "codecipher.vigenere.lookup_table": [[21, 1, 1, "", "LookUpTable"]], "codecipher.vigenere.lookup_table.LookUpTable": [[21, 2, 1, "", "ALPHA"], [21, 2, 1, "", "ALPHANUM"], [21, 2, 1, "", "INDEX_TO_LETTER"], [21, 2, 1, "", "LETTER_TO_INDEX"], [21, 2, 1, "", "NUM"], [21, 2, 1, "", "WHITE_SPACE"]]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:attribute", "3": "py:method", "4": "py:property"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "attribute", "Python attribute"], "3": ["py", "method", "Python method"], "4": ["py", "property", "Python property"]}, "titleterms": {"codeciph": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], "packag": [0, 1, 4, 8, 11, 14, 17, 22], "subpackag": 0, "modul": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], "content": [0, 1, 4, 8, 11, 14, 17, 22], "a1z52n62": [1, 2, 3], "submodul": [1, 4, 8, 11, 14, 17], "decod": [2, 5, 9, 12, 15, 18], "encod": [3, 6, 10, 13, 16, 19], "atb": [4, 5, 6, 7], "lookup_t": [7, 21], "b64": [8, 9, 10], "caesar": [11, 12, 13], "vernam": [14, 15, 16], "vigener": [17, 18, 19, 20, 21], "key_gener": 20, "instal": 22, "depend": 22, "structur": 22, "copyright": 22, "licenc": 22, "indic": 22, "tabl": 22}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.viewcode": 1, "sphinx": 60}, "alltitles": {"codecipher package": [[0, "codecipher-package"]], "Subpackages": [[0, "subpackages"]], "Module contents": [[0, "module-codecipher"], [1, "module-codecipher.a1z52n62"], [4, "module-codecipher.atbs"], [8, "module-codecipher.b64"], [11, "module-codecipher.caesar"], [14, "module-codecipher.vernam"], [17, "module-codecipher.vigenere"]], "codecipher.a1z52n62 package": [[1, "codecipher-a1z52n62-package"]], "Submodules": [[1, "submodules"], [4, "submodules"], [8, "submodules"], [11, "submodules"], [14, "submodules"], [17, "submodules"]], "codecipher.a1z52n62.decode module": [[2, "module-codecipher.a1z52n62.decode"]], "codecipher.a1z52n62.encode module": [[3, "module-codecipher.a1z52n62.encode"]], "codecipher.atbs package": [[4, "codecipher-atbs-package"]], "codecipher.atbs.decode module": [[5, "module-codecipher.atbs.decode"]], "codecipher.atbs.encode module": [[6, "module-codecipher.atbs.encode"]], "codecipher.atbs.lookup_table module": [[7, "module-codecipher.atbs.lookup_table"]], "codecipher.b64 package": [[8, "codecipher-b64-package"]], "codecipher.b64.decode module": [[9, "module-codecipher.b64.decode"]], "codecipher.b64.encode module": [[10, "module-codecipher.b64.encode"]], "codecipher.caesar package": [[11, "codecipher-caesar-package"]], "codecipher.caesar.decode module": [[12, "module-codecipher.caesar.decode"]], "codecipher.caesar.encode module": [[13, "module-codecipher.caesar.encode"]], "codecipher.vernam package": [[14, "codecipher-vernam-package"]], "codecipher.vernam.decode module": [[15, "module-codecipher.vernam.decode"]], "codecipher.vernam.encode module": [[16, "module-codecipher.vernam.encode"]], "codecipher.vigenere package": [[17, "codecipher-vigenere-package"]], "codecipher.vigenere.decode module": [[18, "module-codecipher.vigenere.decode"]], "codecipher.vigenere.encode module": [[19, "module-codecipher.vigenere.encode"]], "codecipher.vigenere.key_generator module": [[20, "module-codecipher.vigenere.key_generator"]], "codecipher.vigenere.lookup_table module": [[21, "module-codecipher.vigenere.lookup_table"]], "CODECipher": [[22, "codecipher"]], "Contents": [[22, null]], "Installation": [[22, "installation"]], "Dependencies": [[22, "dependencies"]], "Package structure": [[22, "package-structure"]], "Copyright and licence": [[22, "copyright-and-licence"]], "Indices and tables": [[22, "indices-and-tables"]], "codecipher": [[23, "codecipher"]]}, "indexentries": {"codecipher": [[0, "module-codecipher"]], "module": [[0, "module-codecipher"], [1, "module-codecipher.a1z52n62"], [2, "module-codecipher.a1z52n62.decode"], [3, "module-codecipher.a1z52n62.encode"], [4, "module-codecipher.atbs"], [5, "module-codecipher.atbs.decode"], [6, "module-codecipher.atbs.encode"], [7, "module-codecipher.atbs.lookup_table"], [8, "module-codecipher.b64"], [9, "module-codecipher.b64.decode"], [10, "module-codecipher.b64.encode"], [11, "module-codecipher.caesar"], [12, "module-codecipher.caesar.decode"], [13, "module-codecipher.caesar.encode"], [14, "module-codecipher.vernam"], [15, "module-codecipher.vernam.decode"], [16, "module-codecipher.vernam.encode"], [17, "module-codecipher.vigenere"], [18, "module-codecipher.vigenere.decode"], [19, "module-codecipher.vigenere.encode"], [20, "module-codecipher.vigenere.key_generator"], [21, "module-codecipher.vigenere.lookup_table"]], "a1z52n62 (class in codecipher.a1z52n62)": [[1, "codecipher.a1z52n62.A1z52N62"]], "codecipher.a1z52n62": [[1, "module-codecipher.a1z52n62"]], "a1z52n62decode (class in codecipher.a1z52n62.decode)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode"]], "_decode_data (codecipher.a1z52n62.decode.a1z52n62decode attribute)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode._decode_data"]], "codecipher.a1z52n62.decode": [[2, "module-codecipher.a1z52n62.decode"]], "decode() (codecipher.a1z52n62.decode.a1z52n62decode method)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode.decode"]], "decode_data (codecipher.a1z52n62.decode.a1z52n62decode property)": [[2, "codecipher.a1z52n62.decode.A1z52N62Decode.decode_data"]], "a1z52n62encode (class in codecipher.a1z52n62.encode)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode"]], "_encode_data (codecipher.a1z52n62.encode.a1z52n62encode attribute)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode._encode_data"]], "codecipher.a1z52n62.encode": [[3, "module-codecipher.a1z52n62.encode"]], "encode() (codecipher.a1z52n62.encode.a1z52n62encode method)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode.encode"]], "encode_data (codecipher.a1z52n62.encode.a1z52n62encode property)": [[3, "codecipher.a1z52n62.encode.A1z52N62Encode.encode_data"]], "alephtawbetshin (class in codecipher.atbs)": [[4, "codecipher.atbs.AlephTawBetShin"]], "codecipher.atbs": [[4, "module-codecipher.atbs"]], "alephtawbetshindecode (class in codecipher.atbs.decode)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode"]], "_decode_data (codecipher.atbs.decode.alephtawbetshindecode attribute)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode._decode_data"]], "codecipher.atbs.decode": [[5, "module-codecipher.atbs.decode"]], "decode() (codecipher.atbs.decode.alephtawbetshindecode method)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode.decode"]], "decode_data (codecipher.atbs.decode.alephtawbetshindecode property)": [[5, "codecipher.atbs.decode.AlephTawBetShinDecode.decode_data"]], "alephtawbetshinencode (class in codecipher.atbs.encode)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode"]], "_encode_data (codecipher.atbs.encode.alephtawbetshinencode attribute)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode._encode_data"]], "codecipher.atbs.encode": [[6, "module-codecipher.atbs.encode"]], "encode() (codecipher.atbs.encode.alephtawbetshinencode method)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode.encode"]], "encode_data (codecipher.atbs.encode.alephtawbetshinencode property)": [[6, "codecipher.atbs.encode.AlephTawBetShinEncode.encode_data"]], "codecipher.atbs.lookup_table": [[7, "module-codecipher.atbs.lookup_table"]], "b64 (class in codecipher.b64)": [[8, "codecipher.b64.B64"]], "codecipher.b64": [[8, "module-codecipher.b64"]], "b64decode (class in codecipher.b64.decode)": [[9, "codecipher.b64.decode.B64Decode"]], "_decode_data (codecipher.b64.decode.b64decode attribute)": [[9, "codecipher.b64.decode.B64Decode._decode_data"]], "codecipher.b64.decode": [[9, "module-codecipher.b64.decode"]], "decode() (codecipher.b64.decode.b64decode method)": [[9, "codecipher.b64.decode.B64Decode.decode"]], "decode_data (codecipher.b64.decode.b64decode property)": [[9, "codecipher.b64.decode.B64Decode.decode_data"]], "b64encode (class in codecipher.b64.encode)": [[10, "codecipher.b64.encode.B64Encode"]], "_encode_data (codecipher.b64.encode.b64encode attribute)": [[10, "codecipher.b64.encode.B64Encode._encode_data"]], "codecipher.b64.encode": [[10, "module-codecipher.b64.encode"]], "encode() (codecipher.b64.encode.b64encode method)": [[10, "codecipher.b64.encode.B64Encode.encode"]], "encode_data (codecipher.b64.encode.b64encode property)": [[10, "codecipher.b64.encode.B64Encode.encode_data"]], "caesar (class in codecipher.caesar)": [[11, "codecipher.caesar.Caesar"]], "codecipher.caesar": [[11, "module-codecipher.caesar"]], "caesardecode (class in codecipher.caesar.decode)": [[12, "codecipher.caesar.decode.CaesarDecode"]], "_decode_data (codecipher.caesar.decode.caesardecode attribute)": [[12, "codecipher.caesar.decode.CaesarDecode._decode_data"]], "codecipher.caesar.decode": [[12, "module-codecipher.caesar.decode"]], "decode() (codecipher.caesar.decode.caesardecode method)": [[12, "codecipher.caesar.decode.CaesarDecode.decode"]], "decode_data (codecipher.caesar.decode.caesardecode property)": [[12, "codecipher.caesar.decode.CaesarDecode.decode_data"]], "caesarencode (class in codecipher.caesar.encode)": [[13, "codecipher.caesar.encode.CaesarEncode"]], "_encode_data (codecipher.caesar.encode.caesarencode attribute)": [[13, "codecipher.caesar.encode.CaesarEncode._encode_data"]], "codecipher.caesar.encode": [[13, "module-codecipher.caesar.encode"]], "encode() (codecipher.caesar.encode.caesarencode method)": [[13, "codecipher.caesar.encode.CaesarEncode.encode"]], "encode_data (codecipher.caesar.encode.caesarencode property)": [[13, "codecipher.caesar.encode.CaesarEncode.encode_data"]], "vernam (class in codecipher.vernam)": [[14, "codecipher.vernam.Vernam"]], "codecipher.vernam": [[14, "module-codecipher.vernam"]], "vernamdecode (class in codecipher.vernam.decode)": [[15, "codecipher.vernam.decode.VernamDecode"]], "_decode_data (codecipher.vernam.decode.vernamdecode attribute)": [[15, "codecipher.vernam.decode.VernamDecode._decode_data"]], "codecipher.vernam.decode": [[15, "module-codecipher.vernam.decode"]], "decode() (codecipher.vernam.decode.vernamdecode method)": [[15, "codecipher.vernam.decode.VernamDecode.decode"]], "decode_data (codecipher.vernam.decode.vernamdecode property)": [[15, "codecipher.vernam.decode.VernamDecode.decode_data"]], "vernamencode (class in codecipher.vernam.encode)": [[16, "codecipher.vernam.encode.VernamEncode"]], "_encode_data (codecipher.vernam.encode.vernamencode attribute)": [[16, "codecipher.vernam.encode.VernamEncode._encode_data"]], "codecipher.vernam.encode": [[16, "module-codecipher.vernam.encode"]], "encode() (codecipher.vernam.encode.vernamencode method)": [[16, "codecipher.vernam.encode.VernamEncode.encode"]], "encode_data (codecipher.vernam.encode.vernamencode property)": [[16, "codecipher.vernam.encode.VernamEncode.encode_data"]], "vigenere (class in codecipher.vigenere)": [[17, "codecipher.vigenere.Vigenere"]], "codecipher.vigenere": [[17, "module-codecipher.vigenere"]], "vigeneredecode (class in codecipher.vigenere.decode)": [[18, "codecipher.vigenere.decode.VigenereDecode"]], "_decode_data (codecipher.vigenere.decode.vigeneredecode attribute)": [[18, "codecipher.vigenere.decode.VigenereDecode._decode_data"]], "_split_data_decode() (codecipher.vigenere.decode.vigeneredecode method)": [[18, "codecipher.vigenere.decode.VigenereDecode._split_data_decode"]], "codecipher.vigenere.decode": [[18, "module-codecipher.vigenere.decode"]], "decode() (codecipher.vigenere.decode.vigeneredecode method)": [[18, "codecipher.vigenere.decode.VigenereDecode.decode"]], "decode_data (codecipher.vigenere.decode.vigeneredecode property)": [[18, "codecipher.vigenere.decode.VigenereDecode.decode_data"]], "vigenereencode (class in codecipher.vigenere.encode)": [[19, "codecipher.vigenere.encode.VigenereEncode"]], "_encode_data (codecipher.vigenere.encode.vigenereencode attribute)": [[19, "codecipher.vigenere.encode.VigenereEncode._encode_data"]], "_split_data_encode() (codecipher.vigenere.encode.vigenereencode method)": [[19, "codecipher.vigenere.encode.VigenereEncode._split_data_encode"]], "codecipher.vigenere.encode": [[19, "module-codecipher.vigenere.encode"]], "encode() (codecipher.vigenere.encode.vigenereencode method)": [[19, "codecipher.vigenere.encode.VigenereEncode.encode"]], "encode_data (codecipher.vigenere.encode.vigenereencode property)": [[19, "codecipher.vigenere.encode.VigenereEncode.encode_data"]], "keygenerator (class in codecipher.vigenere.key_generator)": [[20, "codecipher.vigenere.key_generator.KeyGenerator"]], "_data_len (codecipher.vigenere.key_generator.keygenerator attribute)": [[20, "codecipher.vigenere.key_generator.KeyGenerator._data_len"]], "_key (codecipher.vigenere.key_generator.keygenerator attribute)": [[20, "codecipher.vigenere.key_generator.KeyGenerator._key"]], "codecipher.vigenere.key_generator": [[20, "module-codecipher.vigenere.key_generator"]], "data_len (codecipher.vigenere.key_generator.keygenerator property)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.data_len"]], "generate_key() (codecipher.vigenere.key_generator.keygenerator method)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.generate_key"]], "key (codecipher.vigenere.key_generator.keygenerator property)": [[20, "codecipher.vigenere.key_generator.KeyGenerator.key"]], "alpha (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.ALPHA"]], "alphanum (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.ALPHANUM"]], "index_to_letter (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.INDEX_TO_LETTER"]], "letter_to_index (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.LETTER_TO_INDEX"]], "lookuptable (class in codecipher.vigenere.lookup_table)": [[21, "codecipher.vigenere.lookup_table.LookUpTable"]], "num (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.NUM"]], "white_space (codecipher.vigenere.lookup_table.lookuptable attribute)": [[21, "codecipher.vigenere.lookup_table.LookUpTable.WHITE_SPACE"]], "codecipher.vigenere.lookup_table": [[21, "module-codecipher.vigenere.lookup_table"]]}}) \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index ebdd81c..e82b3ad 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,7 +4,7 @@ Module conf.py Copyright - Copyright (C) 2021-2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -27,9 +27,9 @@ sys.path.insert(0, os.path.abspath('../../')) project: str = 'codecipher' -project_copyright: str = '2024, Vladimir Roncevic ' +project_copyright: str = '2025, Vladimir Roncevic ' author: str = 'Vladimir Roncevic ' -version: str = '1.4.7' +version: str = '1.4.8' release: str = 'https://github.com/electux/codecipher/releases' extensions: List[str] = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] templates_path: List[str] = ['_templates'] diff --git a/docs/source/index.rst b/docs/source/index.rst index 45179ba..f6049b7 100755 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -136,7 +136,7 @@ Copyright and licence .. |license: apache 2.0| image:: https://img.shields.io/badge/license-apache%202.0-blue.svg :target: https://opensource.org/licenses/apache-2.0 -Copyright (C) 2021 - 2024 by `electux.github.io/codecipher `_ +Copyright (C) 2021 - 2025 by `electux.github.io/codecipher `_ **codecipher** is free software; you can redistribute it and/or modify it under the same terms as Python itself, either Python version 3.x or, diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index bc3b797..0000000 --- a/setup.cfg +++ /dev/null @@ -1,44 +0,0 @@ -# -# Module -# setup.cfg -# Copyright -# Copyright (C) 2021 - 2024 Vladimir Roncevic -# codecipher is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# codecipher 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 General Public License for more details. -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# Info -# Defines setup for package codecipher. -# - -[metadata] -name = codecipher -version = 1.4.7 -author = Vladimir Roncevic -author_email = elektron.ronca@gmail.com -description = Python Cipher Utilities -license=GPL 2024 Free software to use and distributed it. -long_description = file: README.md -long_description_content_type = text/markdown -keywords=cipher, encryption, decryption, cryptology, cryptography -platforms = any -url = https://electux.github.io/codecipher -classifiers = - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2) - License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) - License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) - License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) - License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) - Operating System :: OS Independent - -[options] -packages = find: -python_requires = >=3.10 diff --git a/setup.py b/setup.py index 8c42eb8..faa4cea 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ Module setup.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -25,44 +25,37 @@ from os.path import abspath, dirname, join from setuptools import setup -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/main/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' THIS_DIR: str = abspath(dirname(__file__)) long_description: Optional[str] = None with open(join(THIS_DIR, 'README.md'), encoding='utf-8') as readme: long_description = readme.read() PROGRAMMING_LANG: str = 'Programming Language :: Python ::' -VERSIONS: List[str] = ['3.10', '3.11'] +VERSIONS: List[str] = ['3.10', '3.11', '3.12'] SUPPORTED_PY_VERSIONS: List[str] = [ f'{PROGRAMMING_LANG} {VERSION}' for VERSION in VERSIONS ] LICENSE_PREFIX: str = 'License :: OSI Approved ::' LICENSES: List[str] = [ - 'GNU Lesser General Public License v2 (LGPLv2)', - 'GNU Lesser General Public License v2 or later (LGPLv2+)', - 'GNU Lesser General Public License v3 (LGPLv3)', 'GNU Lesser General Public License v3 or later (LGPLv3+)', - 'GNU Library or Lesser General Public License (LGPL)' ] -APPROVED_LICENSES: List[str] = [ - f'{LICENSE_PREFIX} {LICENSE}' for LICENSE in LICENSES -] -PYP_CLASSIFIERS: List[str] = SUPPORTED_PY_VERSIONS + APPROVED_LICENSES +PYP_CLASSIFIERS: List[str] = SUPPORTED_PY_VERSIONS setup( name='codecipher', - version='1.4.7', + version='1.4.8', description='Python Cipher Utilities', author='Vladimir Roncevic', author_email='elektron.ronca@gmail.com', url='https://electux.github.io/codecipher', - license='GPL 2024 Free software to use and distributed it.', + license='GPL-3.0-or-later', long_description=long_description, long_description_content_type='text/markdown', keywords='cipher, encryption, decryption, cryptology, cryptography', diff --git a/tests/.coverage b/tests/.coverage index fd8474b23ab14317620248b1ebad8737554c54a6..d58f3cd9fa421e0663025885d1749f5062a5d6ec 100644 GIT binary patch delta 57 zcmZozz}&Eac>|jQ+XDvvcl-}F3kqD}SKwh{mgUb#ERIhsN-j1KU}Tn-EK4ma&dkp< N*E7>IG+1P?000Hl5n%uT delta 46 zcmZozz}&Eac>|jQ+d~Ha_xukx3kqE2pZq|dPmrIHSz5d-wWv5VKhIpxRL^*k!2$qq CS`Q-t diff --git a/tests/a1z52n62_test.py b/tests/a1z52n62_test.py index 707fbb7..5fee0c4 100644 --- a/tests/a1z52n62_test.py +++ b/tests/a1z52n62_test.py @@ -4,7 +4,7 @@ Module a1z52n62_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class A1z52N62TestCase(unittest.TestCase): diff --git a/tests/atbs_test.py b/tests/atbs_test.py index 2b191cc..47ec2c6 100644 --- a/tests/atbs_test.py +++ b/tests/atbs_test.py @@ -4,7 +4,7 @@ Module atbs_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class AlephTawBetShinTestCase(unittest.TestCase): diff --git a/tests/ats_coverage.py b/tests/ats_coverage.py new file mode 100644 index 0000000..1db4607 --- /dev/null +++ b/tests/ats_coverage.py @@ -0,0 +1,215 @@ +# -*- coding: UTF-8 -*- + +''' +Module + ats_coverage.py +Copyright + Copyright (C) 2025 Vladimir Roncevic + ats_coverage is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + ats_coverage 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 General Public License for more details. + You should have received a copy of the GNU General Public License along + with this program. If not, see . +Info + Defines attribute(s) and method(s) for coverage support. +''' + +import sys +from typing import Any, Dict, List, Optional +from os.path import exists, basename +from json import load +from unittest import TestLoader, TestSuite, TextTestRunner +from argparse import Namespace + +try: + from pathlib import Path + from ats_utilities.checker import ATSChecker + from ats_utilities.console_io.success import success_message + from ats_utilities.console_io.error import error_message + from ats_utilities.option import ATSOptionParser + from ats_utilities.exceptions.ats_type_error import ATSTypeError + from ats_utilities.exceptions.ats_file_error import ATSFileError + from coverage import Coverage +except ImportError as ats_error_message: # pragma: no cover + # Force exit python ####################################################### + sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover + +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://vroncevic.github.io/ats_coverage' +__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] +__license__: str = 'https://github.com/vroncevic/ats_coverage/blob/dev/LICENSE' +__version__: str = '1.0.0' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' + + +def run_coverage(pro_name: str) -> str: + ''' + Runs coverage for project and generates report. + + :param pro_name: Project name + :type pro_name: + :exceptions: ATSTypeError | ATSFileError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([('str:pro_name', pro_name)]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + if not exists(f'../{pro_name}'): + raise ATSFileError(f'missing ../{pro_name}') + cov = Coverage(source=[f'../{pro_name}']) + cov.start() + tests: TestSuite = TestLoader().discover('.', pattern='*_test.py') + test_runner = TextTestRunner(verbosity=2) + test_runner.run(tests) + cov.stop() + cov.save() + report_file_name: str = f'{pro_name}_coverage.json' + cov.json_report(outfile=report_file_name) + success_message([f'\nats_coverage: generated coverage {report_file_name}']) + return report_file_name + + +def load_report(report_file_path: str) -> Dict[str, Any]: + ''' + Loads report from report file. + + :param report_file_path: Report file path + :type report_file_path: + :exceptions: ATSTypeError | ATSFileError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([( + 'str:report_file_path', report_file_path + )]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + if not exists(report_file_path): + raise ATSFileError(f'{report_file_path} does not exist.') + data: Dict[str, Any] = {} + with open(report_file_path, 'r', encoding='utf-8') as loaded_file: + data = load(loaded_file) + return data + + +def find_root_package(module_path: str) -> Optional[Path]: + ''' + Finds root package for project structure. + + :param module_path: Absolute path + :type module_path: + :exceptions: ATSTypeError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([( + 'str:module_path', module_path + )]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + root: Optional[Path] = None + path: Path = Path(module_path).resolve() + while path.parent != path: + if (path / '__init__.py').exists(): + root = path + path = path.parent + return root + + +def update_readme(coverage: Dict[str, Any]) -> None: + ''' + Updates README.md file with code coverage report table. + + :param coverage: Coverage data report + :type coverage: + :exceptions: ATSTypeError + ''' + checker: ATSChecker = ATSChecker() + error_msg: Optional[str] = None + error_id: Optional[int] = None + error_msg, error_id = checker.check_params([('dict:coverage', coverage)]) + if error_id == checker.TYPE_ERROR: + raise ATSTypeError(error_msg) + readme_path: str = '../README.md' + start_marker: str = '### Code coverage' + end_marker: str = '### Docs' + lines: List[str] = [] + with open(readme_path, 'r', encoding='utf-8') as current_file: + lines = current_file.readlines() + new_lines: List[str] = [] + inside_block: bool = False + stmts: str = 'num_statements' + miss: str = 'missing_lines' + cover: str = 'percent_covered_display' + for line in lines: + if start_marker in line: + inside_block = True + new_lines.append(line) + new_lines.append('\n') + new_lines.append('| Name | Stmts | Miss | Cover |\n') + new_lines.append('|------|-------|------|-------|\n') + file_names: List[str] = coverage['files'] + for name in file_names: + root_package: Optional[Path] = find_root_package(name) + module: str = '' + if name.startswith(str(root_package)): + result: str = name[len(str(root_package)):] + result = result.lstrip('/') + module = f'{basename(str(root_package))}/{result}' + file_summary: Dict[str, Any] = coverage['files'][name] + statements: str = file_summary['summary'][stmts] + missing: str = file_summary['summary'][miss] + covered: str = file_summary['summary'][cover] + new_lines.append( + f'| `{module}` | {statements} | {missing} | {covered}%|\n' + ) + total: str = '| **Total** |' + total_statements: str = coverage['totals'][stmts] + total_missing: str = coverage['totals'][miss] + total_covered: str = coverage['totals'][cover] + total += f' {total_statements} |' + total += f' {total_missing} |' + total += f' {total_covered}% |\n' + new_lines.append(total) + continue + elif end_marker in line: + inside_block = False + new_lines.append('\n') + new_lines.append(line) + continue + if not inside_block: + new_lines.append(line) + with open(readme_path, 'w', encoding='utf-8') as update_file: + update_file.writelines(new_lines) + + +if __name__ == "__main__": + cli: ATSOptionParser = ATSOptionParser( + 'ats_coverage 2025', '1.0.0', 'GPLv3', False + ) + cli.add_operation( + '-n', '--name', dest='name', + help='generate coverage report for project (provide name)' + ) + args: Namespace = cli.parse_args(sys.argv) + if not bool(getattr(args, "name")): + error_message(['ats_coverage: missing name argument']) + sys.exit(127) + try: + pro_report_file: str = f'{getattr(args, "name")}_coverage.json' + report_data: Dict[str, Any] = load_report(pro_report_file) + update_readme(report_data) + except (ATSTypeError, ATSFileError) as e: + error_message([f'ats_coverage: {e}']) + sys.exit(128) diff --git a/tests/b64_test.py b/tests/b64_test.py index 6a12627..cb419dd 100644 --- a/tests/b64_test.py +++ b/tests/b64_test.py @@ -4,7 +4,7 @@ Module b64_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class B64TestCase(unittest.TestCase): diff --git a/tests/caesar_test.py b/tests/caesar_test.py index d764bfd..3588751 100644 --- a/tests/caesar_test.py +++ b/tests/caesar_test.py @@ -4,7 +4,7 @@ Module caesar_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class CaesarTestCase(unittest.TestCase): diff --git a/tests/codecipher_coverage.json b/tests/codecipher_coverage.json new file mode 100644 index 0000000..aa2784d --- /dev/null +++ b/tests/codecipher_coverage.json @@ -0,0 +1 @@ +{"meta": {"format": 3, "version": "7.6.10", "timestamp": "2025-11-01T07:55:09.848059", "branch_coverage": false, "show_contexts": false}, "files": {"/data/dev/python/codecipher/github/codecipher/codecipher/__init__.py": {"executed_lines": [3], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [3], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [3], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56, 62], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31], "functions": {"A1z52N62.__init__": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"A1z52N62": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 86, 87, 88, 89, 90, 91, 92, 94, 96, 98, 99], "summary": {"covered_lines": 30, "num_statements": 32, "percent_covered": 93.75, "percent_covered_display": "94", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"A1z52N62Decode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "A1z52N62Decode.decode": {"executed_lines": [86, 87, 88, 89, 90, 91, 92, 94, 96, 98, 99], "summary": {"covered_lines": 11, "num_statements": 11, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"A1z52N62Decode": {"executed_lines": [62, 86, 87, 88, 89, 90, 91, 92, 94, 96, 98, 99], "summary": {"covered_lines": 12, "num_statements": 14, "percent_covered": 85.71428571428571, "percent_covered_display": "86", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 86, 87, 88, 89, 90, 91, 93, 95, 96, 98, 99], "summary": {"covered_lines": 30, "num_statements": 32, "percent_covered": 93.75, "percent_covered_display": "94", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"A1z52N62Encode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "A1z52N62Encode.encode": {"executed_lines": [86, 87, 88, 89, 90, 91, 93, 95, 96, 98, 99], "summary": {"covered_lines": 11, "num_statements": 11, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"A1z52N62Encode": {"executed_lines": [62, 86, 87, 88, 89, 90, 91, 93, 95, 96, 98, 99], "summary": {"covered_lines": 12, "num_statements": 14, "percent_covered": 85.71428571428571, "percent_covered_display": "86", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56, 62], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31], "functions": {"AlephTawBetShin.__init__": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"AlephTawBetShin": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 69, 71, 72, 84, 93, 94, 95, 96, 97], "summary": {"covered_lines": 27, "num_statements": 29, "percent_covered": 93.10344827586206, "percent_covered_display": "93", "missing_lines": 2, "excluded_lines": 2}, "missing_lines": [81, 82], "excluded_lines": [29, 31], "functions": {"AlephTawBetShinDecode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [81, 82], "excluded_lines": []}, "AlephTawBetShinDecode.decode": {"executed_lines": [93, 94, 95, 96, 97], "summary": {"covered_lines": 5, "num_statements": 5, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 71, 72, 84], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"AlephTawBetShinDecode": {"executed_lines": [69, 93, 94, 95, 96, 97], "summary": {"covered_lines": 6, "num_statements": 8, "percent_covered": 75.0, "percent_covered_display": "75", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [81, 82], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 71, 72, 84], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 69, 71, 72, 84, 93, 94, 95, 96, 97], "summary": {"covered_lines": 27, "num_statements": 29, "percent_covered": 93.10344827586206, "percent_covered_display": "93", "missing_lines": 2, "excluded_lines": 2}, "missing_lines": [81, 82], "excluded_lines": [29, 31], "functions": {"AlephTawBetShinEncode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [81, 82], "excluded_lines": []}, "AlephTawBetShinEncode.encode": {"executed_lines": [93, 94, 95, 96, 97], "summary": {"covered_lines": 5, "num_statements": 5, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 71, 72, 84], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"AlephTawBetShinEncode": {"executed_lines": [69, 93, 94, 95, 96, 97], "summary": {"covered_lines": 6, "num_statements": 8, "percent_covered": 75.0, "percent_covered_display": "75", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [81, 82], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 58, 60, 61, 71, 72, 84], "summary": {"covered_lines": 21, "num_statements": 21, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py": {"executed_lines": [3, 22, 24, 25, 26, 27, 28, 29, 30, 31, 33], "summary": {"covered_lines": 10, "num_statements": 10, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [3, 22, 24, 25, 26, 27, 28, 29, 30, 31, 33], "summary": {"covered_lines": 10, "num_statements": 10, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [3, 22, 24, 25, 26, 27, 28, 29, 30, 31, 33], "summary": {"covered_lines": 10, "num_statements": 10, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56, 62], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31], "functions": {"B64.__init__": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"B64": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 63, 65, 66, 78, 87, 88], "summary": {"covered_lines": 22, "num_statements": 24, "percent_covered": 91.66666666666667, "percent_covered_display": "92", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": [], "functions": {"B64Decode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": []}, "B64Decode.decode": {"executed_lines": [87, 88], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 65, 66, 78], "summary": {"covered_lines": 19, "num_statements": 19, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"B64Decode": {"executed_lines": [63, 87, 88], "summary": {"covered_lines": 3, "num_statements": 5, "percent_covered": 60.0, "percent_covered_display": "60", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 65, 66, 78], "summary": {"covered_lines": 19, "num_statements": 19, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 63, 65, 66, 78, 87, 88], "summary": {"covered_lines": 22, "num_statements": 24, "percent_covered": 91.66666666666667, "percent_covered_display": "92", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": [], "functions": {"B64Encode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": []}, "B64Encode.encode": {"executed_lines": [87, 88], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 65, 66, 78], "summary": {"covered_lines": 19, "num_statements": 19, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"B64Encode": {"executed_lines": [63, 87, 88], "summary": {"covered_lines": 3, "num_statements": 5, "percent_covered": 60.0, "percent_covered_display": "60", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [75, 76], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 52, 54, 55, 65, 66, 78], "summary": {"covered_lines": 19, "num_statements": 19, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56, 62], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31], "functions": {"Caesar.__init__": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"Caesar": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 39, "num_statements": 41, "percent_covered": 95.1219512195122, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"CaesarDecode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "CaesarDecode.decode": {"executed_lines": [90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 20, "num_statements": 20, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"CaesarDecode": {"executed_lines": [62, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 21, "num_statements": 23, "percent_covered": 91.30434782608695, "percent_covered_display": "91", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 39, "num_statements": 41, "percent_covered": 95.1219512195122, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"CaesarEncode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "CaesarEncode.encode": {"executed_lines": [90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 20, "num_statements": 20, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"CaesarEncode": {"executed_lines": [62, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 105, 106, 107, 108, 109, 110], "summary": {"covered_lines": 21, "num_statements": 23, "percent_covered": 91.30434782608695, "percent_covered_display": "91", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56, 62], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31], "functions": {"Vernam.__init__": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"Vernam": {"executed_lines": [62], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 56], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 34, "num_statements": 36, "percent_covered": 94.44444444444444, "percent_covered_display": "94", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"VernamDecode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "VernamDecode.decode": {"executed_lines": [88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"VernamDecode": {"executed_lines": [62, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 16, "num_statements": 18, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 62, 64, 65, 77, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 34, "num_statements": 36, "percent_covered": 94.44444444444444, "percent_covered_display": "94", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": [], "functions": {"VernamEncode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "VernamEncode.encode": {"executed_lines": [88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 15, "num_statements": 15, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"VernamEncode": {"executed_lines": [62, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 101, 103, 104], "summary": {"covered_lines": 16, "num_statements": 18, "percent_covered": 88.88888888888889, "percent_covered_display": "89", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [74, 75], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 51, 53, 54, 64, 65, 77], "summary": {"covered_lines": 18, "num_statements": 18, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 57, 63], "summary": {"covered_lines": 17, "num_statements": 17, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [30, 32], "functions": {"Vigenere.__init__": {"executed_lines": [63], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 57], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [30, 32]}}, "classes": {"Vigenere": {"executed_lines": [63], "summary": {"covered_lines": 1, "num_statements": 1, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 57], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [30, 32]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 70, 72, 73, 85, 99, 100, 101, 102, 103, 105, 118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 35, "num_statements": 37, "percent_covered": 94.5945945945946, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 2}, "missing_lines": [82, 83], "excluded_lines": [29, 31], "functions": {"VigenereDecode.decode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [82, 83], "excluded_lines": []}, "VigenereDecode._split_data_decode": {"executed_lines": [99, 100, 101, 102, 103], "summary": {"covered_lines": 5, "num_statements": 5, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "VigenereDecode.decode": {"executed_lines": [118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 7, "num_statements": 7, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 72, 73, 85, 105], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"VigenereDecode": {"executed_lines": [70, 99, 100, 101, 102, 103, 118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 13, "num_statements": 15, "percent_covered": 86.66666666666667, "percent_covered_display": "87", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [82, 83], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 72, 73, 85, 105], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 70, 72, 73, 85, 99, 100, 101, 102, 103, 105, 118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 35, "num_statements": 37, "percent_covered": 94.5945945945946, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 2}, "missing_lines": [82, 83], "excluded_lines": [29, 31], "functions": {"VigenereEncode.encode_data": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [82, 83], "excluded_lines": []}, "VigenereEncode._split_data_encode": {"executed_lines": [99, 100, 101, 102, 103], "summary": {"covered_lines": 5, "num_statements": 5, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "VigenereEncode.encode": {"executed_lines": [118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 7, "num_statements": 7, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 72, 73, 85, 105], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}, "classes": {"VigenereEncode": {"executed_lines": [70, 99, 100, 101, 102, 103, 118, 119, 120, 121, 122, 126, 129], "summary": {"covered_lines": 13, "num_statements": 15, "percent_covered": 86.66666666666667, "percent_covered_display": "87", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [82, 83], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 25, 27, 28, 33, 34, 35, 36, 37, 38, 39, 40, 43, 44, 45, 59, 61, 62, 72, 73, 85, 105], "summary": {"covered_lines": 22, "num_statements": 22, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [29, 31]}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 53, 54, 56, 57, 67, 68, 77, 78, 80, 81, 89, 91, 92, 101, 102, 104, 111, 112, 113, 114, 117, 118, 119], "summary": {"covered_lines": 35, "num_statements": 37, "percent_covered": 94.5945945945946, "percent_covered_display": "95", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [65, 115], "excluded_lines": [], "functions": {"KeyGenerator.data_len": {"executed_lines": [77, 78], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "KeyGenerator.key": {"executed_lines": [101, 102], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "KeyGenerator.generate_key": {"executed_lines": [111, 112, 113, 114, 117, 118, 119], "summary": {"covered_lines": 7, "num_statements": 8, "percent_covered": 87.5, "percent_covered_display": "88", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [115], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 53, 54, 56, 57, 67, 68, 80, 81, 91, 92, 104], "summary": {"covered_lines": 23, "num_statements": 23, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"KeyGenerator": {"executed_lines": [77, 78, 89, 101, 102, 111, 112, 113, 114, 117, 118, 119], "summary": {"covered_lines": 12, "num_statements": 14, "percent_covered": 85.71428571428571, "percent_covered_display": "86", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [65, 115], "excluded_lines": []}, "": {"executed_lines": [3, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 53, 54, 56, 57, 67, 68, 80, 81, 91, 92, 104], "summary": {"covered_lines": 23, "num_statements": 23, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py": {"executed_lines": [3, 23, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 53, 54, 55, 56, 57, 58], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [3, 23, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 53, 54, 55, 56, 57, 58], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"LookUpTable": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [3, 23, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 53, 54, 55, 56, 57, 58], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}}, "totals": {"covered_lines": 532, "num_statements": 558, "percent_covered": 95.3405017921147, "percent_covered_display": "95", "missing_lines": 26, "excluded_lines": 20}} \ No newline at end of file diff --git a/tests/codecipher_coverage.xml b/tests/codecipher_coverage.xml new file mode 100644 index 0000000..8f337c8 --- /dev/null +++ b/tests/codecipher_coverage.xml @@ -0,0 +1,705 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/htmlcov/class_index.html b/tests/htmlcov/class_index.html new file mode 100644 index 0000000..0ddaed4 --- /dev/null +++ b/tests/htmlcov/class_index.html @@ -0,0 +1,443 @@ + + + + + Coverage report + + + + + +
+
+

Coverage report: + 95% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Fileclassstatementsmissingexcludedcoverage
/data/dev/python/codecipher/github/codecipher/codecipher/__init__.py(no class)000100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.pyA1z52N62100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py(no class)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.pyA1z52N62Decode142086%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.pyA1z52N62Encode142086%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.pyAlephTawBetShin100100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py(no class)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.pyAlephTawBetShinDecode82075%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py(no class)2102100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.pyAlephTawBetShinEncode82075%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py(no class)2102100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py(no class)1000100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.pyB64100100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py(no class)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.pyB64Decode52060%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py(no class)1900100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.pyB64Encode52060%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py(no class)1900100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.pyCaesar100100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py(no class)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.pyCaesarDecode232091%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.pyCaesarEncode232091%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.pyVernam100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py(no class)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.pyVernamDecode182089%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.pyVernamEncode182089%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py(no class)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.pyVigenere100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py(no class)1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.pyVigenereDecode152087%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py(no class)2202100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.pyVigenereEncode152087%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py(no class)2202100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator142086%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py(no class)2300100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.pyLookUpTable000100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py(no class)1600100%
Total 558262095%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/coverage_html_cb_6fb7b396.js b/tests/htmlcov/coverage_html_cb_6fb7b396.js new file mode 100644 index 0000000..1face13 --- /dev/null +++ b/tests/htmlcov/coverage_html_cb_6fb7b396.js @@ -0,0 +1,733 @@ +// Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 +// For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt + +// Coverage.py HTML report browser code. +/*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ +/*global coverage: true, document, window, $ */ + +coverage = {}; + +// General helpers +function debounce(callback, wait) { + let timeoutId = null; + return function(...args) { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + callback.apply(this, args); + }, wait); + }; +}; + +function checkVisible(element) { + const rect = element.getBoundingClientRect(); + const viewBottom = Math.max(document.documentElement.clientHeight, window.innerHeight); + const viewTop = 30; + return !(rect.bottom < viewTop || rect.top >= viewBottom); +} + +function on_click(sel, fn) { + const elt = document.querySelector(sel); + if (elt) { + elt.addEventListener("click", fn); + } +} + +// Helpers for table sorting +function getCellValue(row, column = 0) { + const cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (cell.childElementCount == 1) { + var child = cell.firstElementChild; + if (child.tagName === "A") { + child = child.firstElementChild; + } + if (child instanceof HTMLDataElement && child.value) { + return child.value; + } + } + return cell.innerText || cell.textContent; +} + +function rowComparator(rowA, rowB, column = 0) { + let valueA = getCellValue(rowA, column); + let valueB = getCellValue(rowB, column); + if (!isNaN(valueA) && !isNaN(valueB)) { + return valueA - valueB; + } + return valueA.localeCompare(valueB, undefined, {numeric: true}); +} + +function sortColumn(th) { + // Get the current sorting direction of the selected header, + // clear state on other headers and then set the new sorting direction. + const currentSortOrder = th.getAttribute("aria-sort"); + [...th.parentElement.cells].forEach(header => header.setAttribute("aria-sort", "none")); + var direction; + if (currentSortOrder === "none") { + direction = th.dataset.defaultSortOrder || "ascending"; + } + else if (currentSortOrder === "ascending") { + direction = "descending"; + } + else { + direction = "ascending"; + } + th.setAttribute("aria-sort", direction); + + const column = [...th.parentElement.cells].indexOf(th) + + // Sort all rows and afterwards append them in order to move them in the DOM. + Array.from(th.closest("table").querySelectorAll("tbody tr")) + .sort((rowA, rowB) => rowComparator(rowA, rowB, column) * (direction === "ascending" ? 1 : -1)) + .forEach(tr => tr.parentElement.appendChild(tr)); + + // Save the sort order for next time. + if (th.id !== "region") { + let th_id = "file"; // Sort by file if we don't have a column id + let current_direction = direction; + const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE); + if (stored_list) { + ({th_id, direction} = JSON.parse(stored_list)) + } + localStorage.setItem(coverage.INDEX_SORT_STORAGE, JSON.stringify({ + "th_id": th.id, + "direction": current_direction + })); + if (th.id !== th_id || document.getElementById("region")) { + // Sort column has changed, unset sorting by function or class. + localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({ + "by_region": false, + "region_direction": current_direction + })); + } + } + else { + // Sort column has changed to by function or class, remember that. + localStorage.setItem(coverage.SORTED_BY_REGION, JSON.stringify({ + "by_region": true, + "region_direction": direction + })); + } +} + +// Find all the elements with data-shortcut attribute, and use them to assign a shortcut key. +coverage.assign_shortkeys = function () { + document.querySelectorAll("[data-shortcut]").forEach(element => { + document.addEventListener("keypress", event => { + if (event.target.tagName.toLowerCase() === "input") { + return; // ignore keypress from search filter + } + if (event.key === element.dataset.shortcut) { + element.click(); + } + }); + }); +}; + +// Create the events for the filter box. +coverage.wire_up_filter = function () { + // Populate the filter and hide100 inputs if there are saved values for them. + const saved_filter_value = localStorage.getItem(coverage.FILTER_STORAGE); + if (saved_filter_value) { + document.getElementById("filter").value = saved_filter_value; + } + const saved_hide100_value = localStorage.getItem(coverage.HIDE100_STORAGE); + if (saved_hide100_value) { + document.getElementById("hide100").checked = JSON.parse(saved_hide100_value); + } + + // Cache elements. + const table = document.querySelector("table.index"); + const table_body_rows = table.querySelectorAll("tbody tr"); + const no_rows = document.getElementById("no_rows"); + + // Observe filter keyevents. + const filter_handler = (event => { + // Keep running total of each metric, first index contains number of shown rows + const totals = new Array(table.rows[0].cells.length).fill(0); + // Accumulate the percentage as fraction + totals[totals.length - 1] = { "numer": 0, "denom": 0 }; // nosemgrep: eslint.detect-object-injection + + var text = document.getElementById("filter").value; + // Store filter value + localStorage.setItem(coverage.FILTER_STORAGE, text); + const casefold = (text === text.toLowerCase()); + const hide100 = document.getElementById("hide100").checked; + // Store hide value. + localStorage.setItem(coverage.HIDE100_STORAGE, JSON.stringify(hide100)); + + // Hide / show elements. + table_body_rows.forEach(row => { + var show = false; + // Check the text filter. + for (let column = 0; column < totals.length; column++) { + cell = row.cells[column]; + if (cell.classList.contains("name")) { + var celltext = cell.textContent; + if (casefold) { + celltext = celltext.toLowerCase(); + } + if (celltext.includes(text)) { + show = true; + } + } + } + + // Check the "hide covered" filter. + if (show && hide100) { + const [numer, denom] = row.cells[row.cells.length - 1].dataset.ratio.split(" "); + show = (numer !== denom); + } + + if (!show) { + // hide + row.classList.add("hidden"); + return; + } + + // show + row.classList.remove("hidden"); + totals[0]++; + + for (let column = 0; column < totals.length; column++) { + // Accumulate dynamic totals + cell = row.cells[column] // nosemgrep: eslint.detect-object-injection + if (cell.classList.contains("name")) { + continue; + } + if (column === totals.length - 1) { + // Last column contains percentage + const [numer, denom] = cell.dataset.ratio.split(" "); + totals[column]["numer"] += parseInt(numer, 10); // nosemgrep: eslint.detect-object-injection + totals[column]["denom"] += parseInt(denom, 10); // nosemgrep: eslint.detect-object-injection + } + else { + totals[column] += parseInt(cell.textContent, 10); // nosemgrep: eslint.detect-object-injection + } + } + }); + + // Show placeholder if no rows will be displayed. + if (!totals[0]) { + // Show placeholder, hide table. + no_rows.style.display = "block"; + table.style.display = "none"; + return; + } + + // Hide placeholder, show table. + no_rows.style.display = null; + table.style.display = null; + + const footer = table.tFoot.rows[0]; + // Calculate new dynamic sum values based on visible rows. + for (let column = 0; column < totals.length; column++) { + // Get footer cell element. + const cell = footer.cells[column]; // nosemgrep: eslint.detect-object-injection + if (cell.classList.contains("name")) { + continue; + } + + // Set value into dynamic footer cell element. + if (column === totals.length - 1) { + // Percentage column uses the numerator and denominator, + // and adapts to the number of decimal places. + const match = /\.([0-9]+)/.exec(cell.textContent); + const places = match ? match[1].length : 0; + const { numer, denom } = totals[column]; // nosemgrep: eslint.detect-object-injection + cell.dataset.ratio = `${numer} ${denom}`; + // Check denom to prevent NaN if filtered files contain no statements + cell.textContent = denom + ? `${(numer * 100 / denom).toFixed(places)}%` + : `${(100).toFixed(places)}%`; + } + else { + cell.textContent = totals[column]; // nosemgrep: eslint.detect-object-injection + } + } + }); + + document.getElementById("filter").addEventListener("input", debounce(filter_handler)); + document.getElementById("hide100").addEventListener("input", debounce(filter_handler)); + + // Trigger change event on setup, to force filter on page refresh + // (filter value may still be present). + document.getElementById("filter").dispatchEvent(new Event("input")); + document.getElementById("hide100").dispatchEvent(new Event("input")); +}; +coverage.FILTER_STORAGE = "COVERAGE_FILTER_VALUE"; +coverage.HIDE100_STORAGE = "COVERAGE_HIDE100_VALUE"; + +// Set up the click-to-sort columns. +coverage.wire_up_sorting = function () { + document.querySelectorAll("[data-sortable] th[aria-sort]").forEach( + th => th.addEventListener("click", e => sortColumn(e.target)) + ); + + // Look for a localStorage item containing previous sort settings: + let th_id = "file", direction = "ascending"; + const stored_list = localStorage.getItem(coverage.INDEX_SORT_STORAGE); + if (stored_list) { + ({th_id, direction} = JSON.parse(stored_list)); + } + let by_region = false, region_direction = "ascending"; + const sorted_by_region = localStorage.getItem(coverage.SORTED_BY_REGION); + if (sorted_by_region) { + ({ + by_region, + region_direction + } = JSON.parse(sorted_by_region)); + } + + const region_id = "region"; + if (by_region && document.getElementById(region_id)) { + direction = region_direction; + } + // If we are in a page that has a column with id of "region", sort on + // it if the last sort was by function or class. + let th; + if (document.getElementById(region_id)) { + th = document.getElementById(by_region ? region_id : th_id); + } + else { + th = document.getElementById(th_id); + } + th.setAttribute("aria-sort", direction === "ascending" ? "descending" : "ascending"); + th.click() +}; + +coverage.INDEX_SORT_STORAGE = "COVERAGE_INDEX_SORT_2"; +coverage.SORTED_BY_REGION = "COVERAGE_SORT_REGION"; + +// Loaded on index.html +coverage.index_ready = function () { + coverage.assign_shortkeys(); + coverage.wire_up_filter(); + coverage.wire_up_sorting(); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + + on_click(".button_show_hide_help", coverage.show_hide_help); +}; + +// -- pyfile stuff -- + +coverage.LINE_FILTERS_STORAGE = "COVERAGE_LINE_FILTERS"; + +coverage.pyfile_ready = function () { + // If we're directed to a particular line number, highlight the line. + var frag = location.hash; + if (frag.length > 2 && frag[1] === "t") { + document.querySelector(frag).closest(".n").classList.add("highlight"); + coverage.set_sel(parseInt(frag.substr(2), 10)); + } + else { + coverage.set_sel(0); + } + + on_click(".button_toggle_run", coverage.toggle_lines); + on_click(".button_toggle_mis", coverage.toggle_lines); + on_click(".button_toggle_exc", coverage.toggle_lines); + on_click(".button_toggle_par", coverage.toggle_lines); + + on_click(".button_next_chunk", coverage.to_next_chunk_nicely); + on_click(".button_prev_chunk", coverage.to_prev_chunk_nicely); + on_click(".button_top_of_page", coverage.to_top); + on_click(".button_first_chunk", coverage.to_first_chunk); + + on_click(".button_prev_file", coverage.to_prev_file); + on_click(".button_next_file", coverage.to_next_file); + on_click(".button_to_index", coverage.to_index); + + on_click(".button_show_hide_help", coverage.show_hide_help); + + coverage.filters = undefined; + try { + coverage.filters = localStorage.getItem(coverage.LINE_FILTERS_STORAGE); + } catch(err) {} + + if (coverage.filters) { + coverage.filters = JSON.parse(coverage.filters); + } + else { + coverage.filters = {run: false, exc: true, mis: true, par: true}; + } + + for (cls in coverage.filters) { + coverage.set_line_visibilty(cls, coverage.filters[cls]); // nosemgrep: eslint.detect-object-injection + } + + coverage.assign_shortkeys(); + coverage.init_scroll_markers(); + coverage.wire_up_sticky_header(); + + document.querySelectorAll("[id^=ctxs]").forEach( + cbox => cbox.addEventListener("click", coverage.expand_contexts) + ); + + // Rebuild scroll markers when the window height changes. + window.addEventListener("resize", coverage.build_scroll_markers); +}; + +coverage.toggle_lines = function (event) { + const btn = event.target.closest("button"); + const category = btn.value + const show = !btn.classList.contains("show_" + category); + coverage.set_line_visibilty(category, show); + coverage.build_scroll_markers(); + coverage.filters[category] = show; + try { + localStorage.setItem(coverage.LINE_FILTERS_STORAGE, JSON.stringify(coverage.filters)); + } catch(err) {} +}; + +coverage.set_line_visibilty = function (category, should_show) { + const cls = "show_" + category; + const btn = document.querySelector(".button_toggle_" + category); + if (btn) { + if (should_show) { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.add(cls)); + btn.classList.add(cls); + } + else { + document.querySelectorAll("#source ." + category).forEach(e => e.classList.remove(cls)); + btn.classList.remove(cls); + } + } +}; + +// Return the nth line div. +coverage.line_elt = function (n) { + return document.getElementById("t" + n)?.closest("p"); +}; + +// Set the selection. b and e are line numbers. +coverage.set_sel = function (b, e) { + // The first line selected. + coverage.sel_begin = b; + // The next line not selected. + coverage.sel_end = (e === undefined) ? b+1 : e; +}; + +coverage.to_top = function () { + coverage.set_sel(0, 1); + coverage.scroll_window(0); +}; + +coverage.to_first_chunk = function () { + coverage.set_sel(0, 1); + coverage.to_next_chunk(); +}; + +coverage.to_prev_file = function () { + window.location = document.getElementById("prevFileLink").href; +} + +coverage.to_next_file = function () { + window.location = document.getElementById("nextFileLink").href; +} + +coverage.to_index = function () { + location.href = document.getElementById("indexLink").href; +} + +coverage.show_hide_help = function () { + const helpCheck = document.getElementById("help_panel_state") + helpCheck.checked = !helpCheck.checked; +} + +// Return a string indicating what kind of chunk this line belongs to, +// or null if not a chunk. +coverage.chunk_indicator = function (line_elt) { + const classes = line_elt?.className; + if (!classes) { + return null; + } + const match = classes.match(/\bshow_\w+\b/); + if (!match) { + return null; + } + return match[0]; +}; + +coverage.to_next_chunk = function () { + const c = coverage; + + // Find the start of the next colored chunk. + var probe = c.sel_end; + var chunk_indicator, probe_line; + while (true) { + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + if (chunk_indicator) { + break; + } + probe++; + } + + // There's a next chunk, `probe` points to it. + var begin = probe; + + // Find the end of this chunk. + var next_indicator = chunk_indicator; + while (next_indicator === chunk_indicator) { + probe++; + probe_line = c.line_elt(probe); + next_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(begin, probe); + c.show_selection(); +}; + +coverage.to_prev_chunk = function () { + const c = coverage; + + // Find the end of the prev colored chunk. + var probe = c.sel_begin-1; + var probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + var chunk_indicator = c.chunk_indicator(probe_line); + while (probe > 1 && !chunk_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + return; + } + chunk_indicator = c.chunk_indicator(probe_line); + } + + // There's a prev chunk, `probe` points to its last line. + var end = probe+1; + + // Find the beginning of this chunk. + var prev_indicator = chunk_indicator; + while (prev_indicator === chunk_indicator) { + probe--; + if (probe <= 0) { + return; + } + probe_line = c.line_elt(probe); + prev_indicator = c.chunk_indicator(probe_line); + } + c.set_sel(probe+1, end); + c.show_selection(); +}; + +// Returns 0, 1, or 2: how many of the two ends of the selection are on +// the screen right now? +coverage.selection_ends_on_screen = function () { + if (coverage.sel_begin === 0) { + return 0; + } + + const begin = coverage.line_elt(coverage.sel_begin); + const end = coverage.line_elt(coverage.sel_end-1); + + return ( + (checkVisible(begin) ? 1 : 0) + + (checkVisible(end) ? 1 : 0) + ); +}; + +coverage.to_next_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the top line on the screen as selection. + + // This will select the top-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(0, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(1); + } + else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_next_chunk(); +}; + +coverage.to_prev_chunk_nicely = function () { + if (coverage.selection_ends_on_screen() === 0) { + // The selection is entirely off the screen: + // Set the lowest line on the screen as selection. + + // This will select the bottom-left of the viewport + // As this is most likely the span with the line number we take the parent + const line = document.elementFromPoint(document.documentElement.clientHeight-1, 0).parentElement; + if (line.parentElement !== document.getElementById("source")) { + // The element is not a source line but the header or similar + coverage.select_line_or_chunk(coverage.lines_len); + } + else { + // We extract the line number from the id + coverage.select_line_or_chunk(parseInt(line.id.substring(1), 10)); + } + } + coverage.to_prev_chunk(); +}; + +// Select line number lineno, or if it is in a colored chunk, select the +// entire chunk +coverage.select_line_or_chunk = function (lineno) { + var c = coverage; + var probe_line = c.line_elt(lineno); + if (!probe_line) { + return; + } + var the_indicator = c.chunk_indicator(probe_line); + if (the_indicator) { + // The line is in a highlighted chunk. + // Search backward for the first line. + var probe = lineno; + var indicator = the_indicator; + while (probe > 0 && indicator === the_indicator) { + probe--; + probe_line = c.line_elt(probe); + if (!probe_line) { + break; + } + indicator = c.chunk_indicator(probe_line); + } + var begin = probe + 1; + + // Search forward for the last line. + probe = lineno; + indicator = the_indicator; + while (indicator === the_indicator) { + probe++; + probe_line = c.line_elt(probe); + indicator = c.chunk_indicator(probe_line); + } + + coverage.set_sel(begin, probe); + } + else { + coverage.set_sel(lineno); + } +}; + +coverage.show_selection = function () { + // Highlight the lines in the chunk + document.querySelectorAll("#source .highlight").forEach(e => e.classList.remove("highlight")); + for (let probe = coverage.sel_begin; probe < coverage.sel_end; probe++) { + coverage.line_elt(probe).querySelector(".n").classList.add("highlight"); + } + + coverage.scroll_to_selection(); +}; + +coverage.scroll_to_selection = function () { + // Scroll the page if the chunk isn't fully visible. + if (coverage.selection_ends_on_screen() < 2) { + const element = coverage.line_elt(coverage.sel_begin); + coverage.scroll_window(element.offsetTop - 60); + } +}; + +coverage.scroll_window = function (to_pos) { + window.scroll({top: to_pos, behavior: "smooth"}); +}; + +coverage.init_scroll_markers = function () { + // Init some variables + coverage.lines_len = document.querySelectorAll("#source > p").length; + + // Build html + coverage.build_scroll_markers(); +}; + +coverage.build_scroll_markers = function () { + const temp_scroll_marker = document.getElementById("scroll_marker") + if (temp_scroll_marker) temp_scroll_marker.remove(); + // Don't build markers if the window has no scroll bar. + if (document.body.scrollHeight <= window.innerHeight) { + return; + } + + const marker_scale = window.innerHeight / document.body.scrollHeight; + const line_height = Math.min(Math.max(3, window.innerHeight / coverage.lines_len), 10); + + let previous_line = -99, last_mark, last_top; + + const scroll_marker = document.createElement("div"); + scroll_marker.id = "scroll_marker"; + document.getElementById("source").querySelectorAll( + "p.show_run, p.show_mis, p.show_exc, p.show_exc, p.show_par" + ).forEach(element => { + const line_top = Math.floor(element.offsetTop * marker_scale); + const line_number = parseInt(element.querySelector(".n a").id.substr(1)); + + if (line_number === previous_line + 1) { + // If this solid missed block just make previous mark higher. + last_mark.style.height = `${line_top + line_height - last_top}px`; + } + else { + // Add colored line in scroll_marker block. + last_mark = document.createElement("div"); + last_mark.id = `m${line_number}`; + last_mark.classList.add("marker"); + last_mark.style.height = `${line_height}px`; + last_mark.style.top = `${line_top}px`; + scroll_marker.append(last_mark); + last_top = line_top; + } + + previous_line = line_number; + }); + + // Append last to prevent layout calculation + document.body.append(scroll_marker); +}; + +coverage.wire_up_sticky_header = function () { + const header = document.querySelector("header"); + const header_bottom = ( + header.querySelector(".content h2").getBoundingClientRect().top - + header.getBoundingClientRect().top + ); + + function updateHeader() { + if (window.scrollY > header_bottom) { + header.classList.add("sticky"); + } + else { + header.classList.remove("sticky"); + } + } + + window.addEventListener("scroll", updateHeader); + updateHeader(); +}; + +coverage.expand_contexts = function (e) { + var ctxs = e.target.parentNode.querySelector(".ctxs"); + + if (!ctxs.classList.contains("expanded")) { + var ctxs_text = ctxs.textContent; + var width = Number(ctxs_text[0]); + ctxs.textContent = ""; + for (var i = 1; i < ctxs_text.length; i += width) { + key = ctxs_text.substring(i, i + width).trim(); + ctxs.appendChild(document.createTextNode(contexts[key])); + ctxs.appendChild(document.createElement("br")); + } + ctxs.classList.add("expanded"); + } +}; + +document.addEventListener("DOMContentLoaded", () => { + if (document.body.classList.contains("indexfile")) { + coverage.index_ready(); + } + else { + coverage.pyfile_ready(); + } +}); diff --git a/tests/htmlcov/favicon_32_cb_58284776.png b/tests/htmlcov/favicon_32_cb_58284776.png new file mode 100644 index 0000000000000000000000000000000000000000..8649f0475d8d20793b2ec431fe25a186a414cf10 GIT binary patch literal 1732 zcmV;#20QtQP)K2KOkBOVxIZChq#W-v7@TU%U6P(wycKT1hUJUToW3ke1U1ONa4 z000000000000000bb)GRa9mqwR9|UWHy;^RUrt?IT__Y0JUcxmBP0(51q1>E00030 z|NrOz)aw7%8sJzM<5^g%z7^qE`}_Ot|JUUG(NUkWzR|7K?Zo%@_v-8G-1N%N=D$;; zw;keH4dGY$`1t4M=HK_s*zm^0#KgqfwWhe3qO_HtvXYvtjgX>;-~C$L`&k>^R)9)7 zdPh2TL^pCnHC#0+_4D)M`p?qp!pq{jO_{8;$fbaflbx`Tn52n|n}8VFRTA1&ugOP< zPd{uvFjz7t*Vot1&d$l-xWCk}s;sQL&#O(Bskh6gqNJv>#iB=ypG1e3K!K4yc7!~M zfj4S*g^zZ7eP$+_Sl07Z646l;%urinP#D8a6TwRtnLIRcI!r4f@bK~9-`~;E(N?Lv zSEst7s;rcxsi~}{Nsytfz@MtUoR*iFc8!#vvx}Umhm4blk(_~MdVD-@dW&>!Nn~ro z_E~-ESVQAj6Wmn;(olz(O&_{U2*pZBc1aYjMh>Dq3z|6`jW`RDHV=t3I6yRKJ~LOX zz_z!!vbVXPqob#=pj3^VMT?x6t(irRmSKsMo1~LLkB&=#j!=M%NP35mfqim$drWb9 zYIb>no_LUwc!r^NkDzs4YHu@=ZHRzrafWDZd1EhEVq=tGX?tK$pIa)DTh#bkvh!J- z?^%@YS!U*0E8$q$_*aOTQ&)Ra64g>ep;BdcQgvlg8qQHrP*E$;P{-m=A*@axn@$bO zO-Y4JzS&EAi%YG}N?cn?YFS7ivPY=EMV6~YH;+Xxu|tefLS|Aza)Cg6us#)=JW!uH zQa?H>d^j+YHCtyjL^LulF*05|F$RG!AX_OHVI&MtA~_@=5_lU|0000rbW%=J06GH4 z^5LD8b8apw8vNh1ua1mF{{Hy)_U`NA;Nacc+sCpuHXa-V{r&yz?c(9#+}oX+NmiRW z+W-IqK1oDDR5;6GfCDCOP5}iL5fK(cB~ET81`MFgF2kGa9AjhSIk~-E-4&*tPPKdiilQJ11k_J082ZS z>@TvivP!5ZFG?t@{t+GpR3XR&@*hA_VE1|Lo8@L@)l*h(Z@=?c-NS$Fk&&61IzUU9 z*nPqBM=OBZ-6ka1SJgGAS-Us5EN)r#dUX%>wQZLa2ytPCtMKp)Ob z*xcu38Z&d5<-NBS)@jRD+*!W*cf-m_wmxDEqBf?czI%3U0J$Xik;lA`jg}VH?(S(V zE!M3;X2B8w0TnnW&6(8;_Uc)WD;Ms6PKP+s(sFgO!}B!^ES~GDt4qLPxwYB)^7)XA zZwo9zDy-B0B+jT6V=!=bo(zs_8{eBA78gT9GH$(DVhz;4VAYwz+bOIdZ-PNb|I&rl z^XG=vFLF)1{&nT2*0vMz#}7^9hXzzf&ZdKlEj{LihP;|;Ywqn35ajP?H?7t|i-Un% z&&kxee@9B{nwgv1+S-~0)E1{ob1^Wn`F2isurqThKK=3%&;`@{0{!D- z&CSj80t;uPu&FaJFtSXKH#ajgGj}=sEad7US6jP0|Db@0j)?(5@sf<7`~a9>s;wCa zm^)spe{uxGFmrJYI9cOh7s$>8Npkt-5EWB1UKc`{W{y5Ce$1+nM9Cr;);=Ju#N^62OSlJMn7omiUgP&ErsYzT~iGxcW aE(`!K@+CXylaC4j0000 + + + + Coverage report + + + + + +
+
+

Coverage report: + 95% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filefunctionstatementsmissingexcludedcoverage
/data/dev/python/codecipher/github/codecipher/codecipher/__init__.py(no function)000100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.pyA1z52N62.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py(no function)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.pyA1z52N62Decode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.pyA1z52N62Decode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.pyA1z52N62Decode.decode1100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.pyA1z52N62Encode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.pyA1z52N62Encode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.pyA1z52N62Encode.encode1100100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.pyAlephTawBetShin.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py(no function)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.pyAlephTawBetShinDecode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.pyAlephTawBetShinDecode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.pyAlephTawBetShinDecode.decode500100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py(no function)2102100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.pyAlephTawBetShinEncode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.pyAlephTawBetShinEncode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.pyAlephTawBetShinEncode.encode500100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py(no function)2102100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py(no function)1000100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.pyB64.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py(no function)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.pyB64Decode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.pyB64Decode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.pyB64Decode.decode200100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py(no function)1900100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.pyB64Encode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.pyB64Encode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.pyB64Encode.encode200100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py(no function)1900100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.pyCaesar.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py(no function)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.pyCaesarDecode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.pyCaesarDecode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.pyCaesarDecode.decode2000100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.pyCaesarEncode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.pyCaesarEncode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.pyCaesarEncode.encode2000100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.pyVernam.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py(no function)1502100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.pyVernamDecode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.pyVernamDecode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.pyVernamDecode.decode1500100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.pyVernamEncode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.pyVernamEncode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.pyVernamEncode.encode1500100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py(no function)1800100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.pyVigenere.__init__100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py(no function)1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.pyVigenereDecode.decode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.pyVigenereDecode.decode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.pyVigenereDecode._split_data_decode500100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.pyVigenereDecode.decode700100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py(no function)2202100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.pyVigenereEncode.encode_data100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.pyVigenereEncode.encode_data2200%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.pyVigenereEncode._split_data_encode500100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.pyVigenereEncode.encode700100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py(no function)2202100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator.data_len1100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator.data_len200100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator.key100100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator.key200100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.pyKeyGenerator.generate_key81088%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py(no function)2300100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py(no function)1600100%
Total 558262095%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/index.html b/tests/htmlcov/index.html new file mode 100644 index 0000000..7cd5980 --- /dev/null +++ b/tests/htmlcov/index.html @@ -0,0 +1,258 @@ + + + + + Coverage report + + + + + +
+
+

Coverage report: + 95% +

+ +
+ +
+ + +
+
+

+ Files + Functions + Classes +

+

+ coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Filestatementsmissingexcludedcoverage
/data/dev/python/codecipher/github/codecipher/codecipher/__init__.py000100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py322094%
/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py322094%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py292293%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py292293%
/data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py1000100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py242092%
/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py242092%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py412095%
/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py412095%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py1602100%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py362094%
/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py362094%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py1702100%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py372295%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py372295%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py372095%
/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py1600100%
Total558262095%
+

+ No items found using the specified filter. +

+
+ + + diff --git a/tests/htmlcov/keybd_closed_cb_ce680311.png b/tests/htmlcov/keybd_closed_cb_ce680311.png new file mode 100644 index 0000000000000000000000000000000000000000..ba119c47df81ed2bbd27a06988abf700139c4f99 GIT binary patch literal 9004 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 literal 0 HcmV?d00001 diff --git a/tests/htmlcov/status.json b/tests/htmlcov/status.json new file mode 100644 index 0000000..9cd74cb --- /dev/null +++ b/tests/htmlcov/status.json @@ -0,0 +1 @@ +{"note":"This file is an internal implementation detail to speed up HTML report generation. Its format can change at any time. You might be looking for the JSON report: https://coverage.rtfd.io/cmd.html#cmd-json","format":5,"version":"7.6.10","globals":"75472d795e478e2a70f12094bad3d89c","files":{"z_7dc3960ecaf412e4___init___py":{"hash":"f4cac1f1083e129afa20f2f342c23c1e","index":{"url":"z_7dc3960ecaf412e4___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":0,"n_excluded":0,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_96938f9400a5cdf6___init___py":{"hash":"d8331db09f9d8af0d7601a02461b3cb4","index":{"url":"z_96938f9400a5cdf6___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_96938f9400a5cdf6_decode_py":{"hash":"bfe8726156149cfc6855498e771e729c","index":{"url":"z_96938f9400a5cdf6_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":32,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_96938f9400a5cdf6_encode_py":{"hash":"3cb0f5225867225a201978d4e03ef41b","index":{"url":"z_96938f9400a5cdf6_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":32,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_9927f90504198b80___init___py":{"hash":"95ea4f26d546ec4ae5e199099cdea6b5","index":{"url":"z_9927f90504198b80___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_9927f90504198b80_decode_py":{"hash":"4c449b3a90c2c83914072ff597264b2b","index":{"url":"z_9927f90504198b80_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":29,"n_excluded":2,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_9927f90504198b80_encode_py":{"hash":"38120ce683b88295cb0662276032b801","index":{"url":"z_9927f90504198b80_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":29,"n_excluded":2,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_9927f90504198b80_lookup_table_py":{"hash":"e5144183bef94c289bae596618526357","index":{"url":"z_9927f90504198b80_lookup_table_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":10,"n_excluded":0,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_8f54ab6b5b508ca0___init___py":{"hash":"738540ed921a9c045fa43d9dfa559e62","index":{"url":"z_8f54ab6b5b508ca0___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_8f54ab6b5b508ca0_decode_py":{"hash":"ddbb57f6709f86fd5a0a8f0823f65a1e","index":{"url":"z_8f54ab6b5b508ca0_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":24,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_8f54ab6b5b508ca0_encode_py":{"hash":"18688324516b14bb3e62d5c1c9342170","index":{"url":"z_8f54ab6b5b508ca0_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":24,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_094bd7de807a5f14___init___py":{"hash":"91a240027ae1ff550cdb8b36702f36bb","index":{"url":"z_094bd7de807a5f14___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_094bd7de807a5f14_decode_py":{"hash":"848e445f1888e31ef0fcf66fda64b84c","index":{"url":"z_094bd7de807a5f14_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":41,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_094bd7de807a5f14_encode_py":{"hash":"e69615b6838d556d263d9e85784beed4","index":{"url":"z_094bd7de807a5f14_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":41,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_aba196749d301797___init___py":{"hash":"683db5ca8547a390e7435ac5add52681","index":{"url":"z_aba196749d301797___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_aba196749d301797_decode_py":{"hash":"b259df959f65c314809d3717b2412aee","index":{"url":"z_aba196749d301797_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":36,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_aba196749d301797_encode_py":{"hash":"58b395bc286dedac7a74dc2b98d5f1dd","index":{"url":"z_aba196749d301797_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":36,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_75799433d8182c47___init___py":{"hash":"b73e4e6cf58cb5d43a70de2fba4ea55c","index":{"url":"z_75799433d8182c47___init___py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":17,"n_excluded":2,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_75799433d8182c47_decode_py":{"hash":"9b2483a8d9ca801b9479cf5f4448061d","index":{"url":"z_75799433d8182c47_decode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":37,"n_excluded":2,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_75799433d8182c47_encode_py":{"hash":"db543c754da846703542c9f13639789d","index":{"url":"z_75799433d8182c47_encode_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":37,"n_excluded":2,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_75799433d8182c47_key_generator_py":{"hash":"0624230860464585b462816a5f5372fc","index":{"url":"z_75799433d8182c47_key_generator_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":37,"n_excluded":0,"n_missing":2,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}},"z_75799433d8182c47_lookup_table_py":{"hash":"d1650af7cf63ae1b5b7c36c494b29a50","index":{"url":"z_75799433d8182c47_lookup_table_py.html","file":"/data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py","description":"","nums":{"precision":0,"n_files":1,"n_statements":16,"n_excluded":0,"n_missing":0,"n_branches":0,"n_partial_branches":0,"n_missing_branches":0}}}}} \ No newline at end of file diff --git a/tests/htmlcov/style_cb_8e611ae1.css b/tests/htmlcov/style_cb_8e611ae1.css new file mode 100644 index 0000000..3cdaf05 --- /dev/null +++ b/tests/htmlcov/style_cb_8e611ae1.css @@ -0,0 +1,337 @@ +@charset "UTF-8"; +/* Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 */ +/* For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt */ +/* Don't edit this .css file. Edit the .scss file instead! */ +html, body, h1, h2, h3, p, table, td, th { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } + +body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-size: 1em; background: #fff; color: #000; } + +@media (prefers-color-scheme: dark) { body { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { body { color: #eee; } } + +html > body { font-size: 16px; } + +a:active, a:focus { outline: 2px dashed #007acc; } + +p { font-size: .875em; line-height: 1.4em; } + +table { border-collapse: collapse; } + +td { vertical-align: top; } + +table tr.hidden { display: none !important; } + +p#no_rows { display: none; font-size: 1.15em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } + +a.nav { text-decoration: none; color: inherit; } + +a.nav:hover { text-decoration: underline; color: inherit; } + +.hidden { display: none; } + +header { background: #f8f8f8; width: 100%; z-index: 2; border-bottom: 1px solid #ccc; } + +@media (prefers-color-scheme: dark) { header { background: black; } } + +@media (prefers-color-scheme: dark) { header { border-color: #333; } } + +header .content { padding: 1rem 3.5rem; } + +header h2 { margin-top: .5em; font-size: 1em; } + +header h2 a.button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; } + +@media (prefers-color-scheme: dark) { header h2 a.button { background: #333; } } + +@media (prefers-color-scheme: dark) { header h2 a.button { border-color: #444; } } + +header h2 a.button.current { border: 2px solid; background: #fff; border-color: #999; cursor: default; } + +@media (prefers-color-scheme: dark) { header h2 a.button.current { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { header h2 a.button.current { border-color: #777; } } + +header p.text { margin: .5em 0 -.5em; color: #666; font-style: italic; } + +@media (prefers-color-scheme: dark) { header p.text { color: #aaa; } } + +header.sticky { position: fixed; left: 0; right: 0; height: 2.5em; } + +header.sticky .text { display: none; } + +header.sticky h1, header.sticky h2 { font-size: 1em; margin-top: 0; display: inline-block; } + +header.sticky .content { padding: 0.5rem 3.5rem; } + +header.sticky .content p { font-size: 1em; } + +header.sticky ~ #source { padding-top: 6.5em; } + +main { position: relative; z-index: 1; } + +footer { margin: 1rem 3.5rem; } + +footer .content { padding: 0; color: #666; font-style: italic; } + +@media (prefers-color-scheme: dark) { footer .content { color: #aaa; } } + +#index { margin: 1rem 0 0 3.5rem; } + +h1 { font-size: 1.25em; display: inline-block; } + +#filter_container { float: right; margin: 0 2em 0 0; line-height: 1.66em; } + +#filter_container #filter { width: 10em; padding: 0.2em 0.5em; border: 2px solid #ccc; background: #fff; color: #000; } + +@media (prefers-color-scheme: dark) { #filter_container #filter { border-color: #444; } } + +@media (prefers-color-scheme: dark) { #filter_container #filter { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { #filter_container #filter { color: #eee; } } + +#filter_container #filter:focus { border-color: #007acc; } + +#filter_container :disabled ~ label { color: #ccc; } + +@media (prefers-color-scheme: dark) { #filter_container :disabled ~ label { color: #444; } } + +#filter_container label { font-size: .875em; color: #666; } + +@media (prefers-color-scheme: dark) { #filter_container label { color: #aaa; } } + +header button { font-family: inherit; font-size: inherit; border: 1px solid; border-radius: .2em; background: #eee; color: inherit; text-decoration: none; padding: .1em .5em; margin: 1px calc(.1em + 1px); cursor: pointer; border-color: #ccc; } + +@media (prefers-color-scheme: dark) { header button { background: #333; } } + +@media (prefers-color-scheme: dark) { header button { border-color: #444; } } + +header button:active, header button:focus { outline: 2px dashed #007acc; } + +header button.run { background: #eeffee; } + +@media (prefers-color-scheme: dark) { header button.run { background: #373d29; } } + +header button.run.show_run { background: #dfd; border: 2px solid #00dd00; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.run.show_run { background: #373d29; } } + +header button.mis { background: #ffeeee; } + +@media (prefers-color-scheme: dark) { header button.mis { background: #4b1818; } } + +header button.mis.show_mis { background: #fdd; border: 2px solid #ff0000; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.mis.show_mis { background: #4b1818; } } + +header button.exc { background: #f7f7f7; } + +@media (prefers-color-scheme: dark) { header button.exc { background: #333; } } + +header button.exc.show_exc { background: #eee; border: 2px solid #808080; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.exc.show_exc { background: #333; } } + +header button.par { background: #ffffd5; } + +@media (prefers-color-scheme: dark) { header button.par { background: #650; } } + +header button.par.show_par { background: #ffa; border: 2px solid #bbbb00; margin: 0 .1em; } + +@media (prefers-color-scheme: dark) { header button.par.show_par { background: #650; } } + +#help_panel, #source p .annotate.long { display: none; position: absolute; z-index: 999; background: #ffffcc; border: 1px solid #888; border-radius: .2em; color: #333; padding: .25em .5em; } + +#source p .annotate.long { white-space: normal; float: right; top: 1.75em; right: 1em; height: auto; } + +#help_panel_wrapper { float: right; position: relative; } + +#keyboard_icon { margin: 5px; } + +#help_panel_state { display: none; } + +#help_panel { top: 25px; right: 0; padding: .75em; border: 1px solid #883; color: #333; } + +#help_panel .keyhelp p { margin-top: .75em; } + +#help_panel .legend { font-style: italic; margin-bottom: 1em; } + +.indexfile #help_panel { width: 25em; } + +.pyfile #help_panel { width: 18em; } + +#help_panel_state:checked ~ #help_panel { display: block; } + +kbd { border: 1px solid black; border-color: #888 #333 #333 #888; padding: .1em .35em; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-weight: bold; background: #eee; border-radius: 3px; } + +#source { padding: 1em 0 1em 3.5rem; font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; } + +#source p { position: relative; white-space: pre; } + +#source p * { box-sizing: border-box; } + +#source p .n { float: left; text-align: right; width: 3.5rem; box-sizing: border-box; margin-left: -3.5rem; padding-right: 1em; color: #999; user-select: none; } + +@media (prefers-color-scheme: dark) { #source p .n { color: #777; } } + +#source p .n.highlight { background: #ffdd00; } + +#source p .n a { scroll-margin-top: 6em; text-decoration: none; color: #999; } + +@media (prefers-color-scheme: dark) { #source p .n a { color: #777; } } + +#source p .n a:hover { text-decoration: underline; color: #999; } + +@media (prefers-color-scheme: dark) { #source p .n a:hover { color: #777; } } + +#source p .t { display: inline-block; width: 100%; box-sizing: border-box; margin-left: -.5em; padding-left: 0.3em; border-left: 0.2em solid #fff; } + +@media (prefers-color-scheme: dark) { #source p .t { border-color: #1e1e1e; } } + +#source p .t:hover { background: #f2f2f2; } + +@media (prefers-color-scheme: dark) { #source p .t:hover { background: #282828; } } + +#source p .t:hover ~ .r .annotate.long { display: block; } + +#source p .t .com { color: #008000; font-style: italic; line-height: 1px; } + +@media (prefers-color-scheme: dark) { #source p .t .com { color: #6a9955; } } + +#source p .t .key { font-weight: bold; line-height: 1px; } + +#source p .t .str { color: #0451a5; } + +@media (prefers-color-scheme: dark) { #source p .t .str { color: #9cdcfe; } } + +#source p.mis .t { border-left: 0.2em solid #ff0000; } + +#source p.mis.show_mis .t { background: #fdd; } + +@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t { background: #4b1818; } } + +#source p.mis.show_mis .t:hover { background: #f2d2d2; } + +@media (prefers-color-scheme: dark) { #source p.mis.show_mis .t:hover { background: #532323; } } + +#source p.run .t { border-left: 0.2em solid #00dd00; } + +#source p.run.show_run .t { background: #dfd; } + +@media (prefers-color-scheme: dark) { #source p.run.show_run .t { background: #373d29; } } + +#source p.run.show_run .t:hover { background: #d2f2d2; } + +@media (prefers-color-scheme: dark) { #source p.run.show_run .t:hover { background: #404633; } } + +#source p.exc .t { border-left: 0.2em solid #808080; } + +#source p.exc.show_exc .t { background: #eee; } + +@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t { background: #333; } } + +#source p.exc.show_exc .t:hover { background: #e2e2e2; } + +@media (prefers-color-scheme: dark) { #source p.exc.show_exc .t:hover { background: #3c3c3c; } } + +#source p.par .t { border-left: 0.2em solid #bbbb00; } + +#source p.par.show_par .t { background: #ffa; } + +@media (prefers-color-scheme: dark) { #source p.par.show_par .t { background: #650; } } + +#source p.par.show_par .t:hover { background: #f2f2a2; } + +@media (prefers-color-scheme: dark) { #source p.par.show_par .t:hover { background: #6d5d0c; } } + +#source p .r { position: absolute; top: 0; right: 2.5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } + +#source p .annotate { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; color: #666; padding-right: .5em; } + +@media (prefers-color-scheme: dark) { #source p .annotate { color: #ddd; } } + +#source p .annotate.short:hover ~ .long { display: block; } + +#source p .annotate.long { width: 30em; right: 2.5em; } + +#source p input { display: none; } + +#source p input ~ .r label.ctx { cursor: pointer; border-radius: .25em; } + +#source p input ~ .r label.ctx::before { content: "â–¶ "; } + +#source p input ~ .r label.ctx:hover { background: #e8f4ff; color: #666; } + +@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { background: #0f3a42; } } + +@media (prefers-color-scheme: dark) { #source p input ~ .r label.ctx:hover { color: #aaa; } } + +#source p input:checked ~ .r label.ctx { background: #d0e8ff; color: #666; border-radius: .75em .75em 0 0; padding: 0 .5em; margin: -.25em 0; } + +@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { background: #056; } } + +@media (prefers-color-scheme: dark) { #source p input:checked ~ .r label.ctx { color: #aaa; } } + +#source p input:checked ~ .r label.ctx::before { content: "â–¼ "; } + +#source p input:checked ~ .ctxs { padding: .25em .5em; overflow-y: scroll; max-height: 10.5em; } + +#source p label.ctx { color: #999; display: inline-block; padding: 0 .5em; font-size: .8333em; } + +@media (prefers-color-scheme: dark) { #source p label.ctx { color: #777; } } + +#source p .ctxs { display: block; max-height: 0; overflow-y: hidden; transition: all .2s; padding: 0 .5em; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; white-space: nowrap; background: #d0e8ff; border-radius: .25em; margin-right: 1.75em; text-align: right; } + +@media (prefers-color-scheme: dark) { #source p .ctxs { background: #056; } } + +#index { font-family: SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 0.875em; } + +#index table.index { margin-left: -.5em; } + +#index td, #index th { text-align: right; padding: .25em .5em; border-bottom: 1px solid #eee; } + +@media (prefers-color-scheme: dark) { #index td, #index th { border-color: #333; } } + +#index td.name, #index th.name { text-align: left; width: auto; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; min-width: 15em; } + +#index th { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; font-style: italic; color: #333; cursor: pointer; } + +@media (prefers-color-scheme: dark) { #index th { color: #ddd; } } + +#index th:hover { background: #eee; } + +@media (prefers-color-scheme: dark) { #index th:hover { background: #333; } } + +#index th .arrows { color: #666; font-size: 85%; font-family: sans-serif; font-style: normal; pointer-events: none; } + +#index th[aria-sort="ascending"], #index th[aria-sort="descending"] { white-space: nowrap; background: #eee; padding-left: .5em; } + +@media (prefers-color-scheme: dark) { #index th[aria-sort="ascending"], #index th[aria-sort="descending"] { background: #333; } } + +#index th[aria-sort="ascending"] .arrows::after { content: " â–²"; } + +#index th[aria-sort="descending"] .arrows::after { content: " â–¼"; } + +#index td.name { font-size: 1.15em; } + +#index td.name a { text-decoration: none; color: inherit; } + +#index td.name .no-noun { font-style: italic; } + +#index tr.total td, #index tr.total_dynamic td { font-weight: bold; border-top: 1px solid #ccc; border-bottom: none; } + +#index tr.region:hover { background: #eee; } + +@media (prefers-color-scheme: dark) { #index tr.region:hover { background: #333; } } + +#index tr.region:hover td.name { text-decoration: underline; color: inherit; } + +#scroll_marker { position: fixed; z-index: 3; right: 0; top: 0; width: 16px; height: 100%; background: #fff; border-left: 1px solid #eee; will-change: transform; } + +@media (prefers-color-scheme: dark) { #scroll_marker { background: #1e1e1e; } } + +@media (prefers-color-scheme: dark) { #scroll_marker { border-color: #333; } } + +#scroll_marker .marker { background: #ccc; position: absolute; min-height: 3px; width: 100%; } + +@media (prefers-color-scheme: dark) { #scroll_marker .marker { background: #444; } } diff --git a/tests/htmlcov/z_094bd7de807a5f14___init___py.html b/tests/htmlcov/z_094bd7de807a5f14___init___py.html new file mode 100644 index 0000000..2a53b1d --- /dev/null +++ b/tests/htmlcov/z_094bd7de807a5f14___init___py.html @@ -0,0 +1,159 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/__init__.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class Caesar with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.caesar.encode import CaesarEncode 

+

28 from codecipher.caesar.decode import CaesarDecode 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43class Caesar(CaesarEncode, CaesarDecode): 

+

44 ''' 

+

45 Defines class Caesar with attribute(s) and method(s). 

+

46 Creates container class with aggregate backend API. 

+

47 

+

48 It defines: 

+

49 

+

50 :attributes: 

+

51 | None. 

+

52 :methods: 

+

53 | __init__ - Initials Caesar constructor. 

+

54 ''' 

+

55 

+

56 def __init__(self) -> None: 

+

57 ''' 

+

58 Initials Caesar constructor. 

+

59 

+

60 :exceptions: None 

+

61 ''' 

+

62 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_094bd7de807a5f14_decode_py.html b/tests/htmlcov/z_094bd7de807a5f14_decode_py.html new file mode 100644 index 0000000..7218067 --- /dev/null +++ b/tests/htmlcov/z_094bd7de807a5f14_decode_py.html @@ -0,0 +1,207 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py: 95% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/decode.py: + 95% +

+ +

+ 41 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class CaesarDecode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class CaesarDecode: 

+

38 ''' 

+

39 Defines class CaesarDecode with attribute(s) and method(s). 

+

40 Creates decode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _decode_data - Data decode container. 

+

46 :methods: 

+

47 | decode_data - Property methods for decode data. 

+

48 | decode - Decode data from Caesar format. 

+

49 ''' 

+

50 

+

51 _decode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def decode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting decode data. 

+

57 

+

58 :return: Decode data in str format | None 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._decode_data 

+

63 

+

64 @decode_data.setter 

+

65 def decode_data(self, decode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting decode data. 

+

68 

+

69 :param decode_data: Decoded data | None 

+

70 :type decode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(decode_data): 

+

75 self._decode_data = decode_data 

+

76 

+

77 def decode( 

+

78 self, data: Optional[str], shift_counter: Optional[int] 

+

79 ) -> None: 

+

80 ''' 

+

81 Decoding data from Caesar format. 

+

82 

+

83 :param data: Data which should be decoded | None 

+

84 :type data: <Optional[str]> 

+

85 :param shift_counter: Defining the shift count | None 

+

86 :type shift_counter: <Optional[int]> 

+

87 :return: None 

+

88 :exceptions: None 

+

89 ''' 

+

90 if bool(data) and bool(shift_counter): 

+

91 decode_list: List[str] = [] 

+

92 for element in data: 

+

93 if element.isspace() or element.isnumeric(): 

+

94 decode_list.append(element) 

+

95 continue 

+

96 element_index: Optional[int] = None 

+

97 new_index: Optional[int] = None 

+

98 new_unicode: Optional[int] = None 

+

99 new_character: Optional[str] = None 

+

100 if element.isupper(): 

+

101 element_index = ord(element) - ord('A') 

+

102 new_index = (element_index - shift_counter) % 26 

+

103 new_unicode = new_index + ord('A') 

+

104 else: 

+

105 element_index = ord(element) - ord('a') 

+

106 new_index = (element_index - shift_counter) % 26 

+

107 new_unicode = new_index + ord('a') 

+

108 new_character = chr(new_unicode) 

+

109 decode_list.append(new_character) 

+

110 self._decode_data = ''.join(decode_list) 

+
+ + + diff --git a/tests/htmlcov/z_094bd7de807a5f14_encode_py.html b/tests/htmlcov/z_094bd7de807a5f14_encode_py.html new file mode 100644 index 0000000..4619c1c --- /dev/null +++ b/tests/htmlcov/z_094bd7de807a5f14_encode_py.html @@ -0,0 +1,207 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py: 95% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/caesar/encode.py: + 95% +

+ +

+ 41 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class CaesarEncode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class CaesarEncode: 

+

38 ''' 

+

39 Defines class CaesarEncode with attribute(s) and method(s). 

+

40 Creates encode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _encode_data - Data encode container. 

+

46 :methods: 

+

47 | encode_data - Property methods for encode data. 

+

48 | encode - Encode data to Caesar format. 

+

49 ''' 

+

50 

+

51 _encode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def encode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting encode data. 

+

57 

+

58 :return: Encoded data | None 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._encode_data 

+

63 

+

64 @encode_data.setter 

+

65 def encode_data(self, encode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting encode data. 

+

68 

+

69 :param encode_data: Encode data | None 

+

70 :type encode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(encode_data): 

+

75 self._encode_data = encode_data 

+

76 

+

77 def encode( 

+

78 self, data: Optional[str], shift_counter: Optional[int] 

+

79 ) -> None: 

+

80 ''' 

+

81 Encoding data to Caesar format. 

+

82 

+

83 :param data: Data which should be encoded | None 

+

84 :type data: <Optional[str]> 

+

85 :param shift_counter: Defining the shift count | None 

+

86 :type shift_counter: <Optional[int]> 

+

87 :return: None 

+

88 :exceptions: None 

+

89 ''' 

+

90 if bool(data) and bool(shift_counter): 

+

91 encode_list: List[str] = [] 

+

92 for element in data: 

+

93 if element.isspace() or element.isnumeric(): 

+

94 encode_list.append(element) 

+

95 continue 

+

96 element_index: Optional[int] = None 

+

97 new_index: Optional[int] = None 

+

98 new_unicode: Optional[int] = None 

+

99 new_character: Optional[str] = None 

+

100 if element.isupper(): 

+

101 element_index = ord(element) - ord('A') 

+

102 new_index = (element_index + shift_counter) % 26 

+

103 new_unicode = new_index + ord('A') 

+

104 else: 

+

105 element_index = ord(element) - ord('a') 

+

106 new_index = (element_index + shift_counter) % 26 

+

107 new_unicode = new_index + ord('a') 

+

108 new_character = chr(new_unicode) 

+

109 encode_list.append(new_character) 

+

110 self._encode_data = ''.join(encode_list) 

+
+ + + diff --git a/tests/htmlcov/z_75799433d8182c47___init___py.html b/tests/htmlcov/z_75799433d8182c47___init___py.html new file mode 100644 index 0000000..f0c1251 --- /dev/null +++ b/tests/htmlcov/z_75799433d8182c47___init___py.html @@ -0,0 +1,160 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/__init__.py: + 100% +

+ +

+ 17 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class Vigenere with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.vigenere.encode import VigenereEncode 

+

28 from codecipher.vigenere.decode import VigenereDecode 

+

29 from codecipher.vigenere.key_generator import KeyGenerator 

+

30except ImportError as ats_error_message: # pragma: no cover 

+

31 # Force exit python ####################################################### 

+

32 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

33 

+

34__author__: str = 'Vladimir Roncevic' 

+

35__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

36__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

37__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

38__version__: str = '1.4.8' 

+

39__maintainer__: str = 'Vladimir Roncevic' 

+

40__email__: str = 'elektron.ronca@gmail.com' 

+

41__status__: str = 'Updated' 

+

42 

+

43 

+

44class Vigenere(VigenereEncode, VigenereDecode, KeyGenerator): 

+

45 ''' 

+

46 Defines class Vigenere with attribute(s) and method(s). 

+

47 Creates container class with aggregate backend API. 

+

48 

+

49 It defines: 

+

50 

+

51 :attributes: 

+

52 | None. 

+

53 :methods: 

+

54 | __init__ - Initials Vigenere constructor. 

+

55 ''' 

+

56 

+

57 def __init__(self) -> None: 

+

58 ''' 

+

59 Initials Vigenere constructor. 

+

60 

+

61 :exceptions: None 

+

62 ''' 

+

63 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_75799433d8182c47_decode_py.html b/tests/htmlcov/z_75799433d8182c47_decode_py.html new file mode 100644 index 0000000..79a39bd --- /dev/null +++ b/tests/htmlcov/z_75799433d8182c47_decode_py.html @@ -0,0 +1,226 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py: 95% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/decode.py: + 95% +

+ +

+ 37 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class VigenereDecode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from dataclasses import dataclass, field 

+

25from typing import List, Optional 

+

26 

+

27try: 

+

28 from codecipher.vigenere.lookup_table import LookUpTable 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43@dataclass 

+

44class VigenereDecode: 

+

45 ''' 

+

46 Defines class VigenereDecode with attribute(s) and method(s). 

+

47 Creates decode class with backend API. 

+

48 

+

49 It defines: 

+

50 

+

51 :attributes: 

+

52 | _decode_data - Data decode container. 

+

53 :methods: 

+

54 | decode_data - Property methods for decode data. 

+

55 | _split_data - Splitting data for decoding. 

+

56 | decode - Decode data from Vigenere format. 

+

57 ''' 

+

58 

+

59 _decode_data: Optional[str] = field(default=None) 

+

60 

+

61 @property 

+

62 def decode_data(self) -> Optional[str]: 

+

63 ''' 

+

64 Property method for getting decode data. 

+

65 

+

66 :return: Decode data in str format | None 

+

67 :rtype: <Optional[str]> 

+

68 :exceptions: None 

+

69 ''' 

+

70 return self._decode_data 

+

71 

+

72 @decode_data.setter 

+

73 def decode_data(self, decode_data_val: Optional[str]) -> None: 

+

74 ''' 

+

75 Property method for setting decode data. 

+

76 

+

77 :param decode_data_val: Decoded data | None 

+

78 :type decode_data_val: <Optional[str]> 

+

79 :return: None 

+

80 :exceptions: None 

+

81 ''' 

+

82 if bool(decode_data_val): 

+

83 self._decode_data = decode_data_val 

+

84 

+

85 def _split_data_decode( 

+

86 self, data_to_decode: Optional[str], key: Optional[str] 

+

87 ) -> List[str]: 

+

88 ''' 

+

89 Splitting data for decoding. 

+

90 

+

91 :param data_to_decode: Data which should be decoded | None 

+

92 :type data_to_decode: <Optional[str]> 

+

93 :param key: Key for decoding | None 

+

94 :type key: <Optional[str]> 

+

95 :return: List with data for decoding 

+

96 :rtype: <List[str]> 

+

97 :exceptions: None 

+

98 ''' 

+

99 elements: List[str] = [] 

+

100 if bool(data_to_decode) and bool(key): 

+

101 for i in range(0, len(data_to_decode), len(key)): 

+

102 elements.append(data_to_decode[i: i + len(key)]) 

+

103 return elements 

+

104 

+

105 def decode( 

+

106 self, data_to_decode: Optional[str], key: Optional[str] 

+

107 ) -> None: 

+

108 ''' 

+

109 Decoding data from Vigenere format. 

+

110 

+

111 :param data_to_decode: Data which should be decoded 

+

112 :type data_to_decode: <Optional[str]> 

+

113 :param key: Key for decoding 

+

114 :type key: <Optional[str]> 

+

115 :return: None 

+

116 :exceptions: None 

+

117 ''' 

+

118 if bool(data_to_decode) and bool(key): 

+

119 decode_list: List[str] = [] 

+

120 for element in self._split_data_decode(data_to_decode, key): 

+

121 for index, letter in enumerate(element): 

+

122 process_index: int = ( 

+

123 LookUpTable.LETTER_TO_INDEX[letter] - 

+

124 LookUpTable.LETTER_TO_INDEX[key[index]] 

+

125 ) % len(LookUpTable.ALPHANUM) 

+

126 decode_list.append( 

+

127 LookUpTable.INDEX_TO_LETTER[process_index] 

+

128 ) 

+

129 self._decode_data = ''.join(decode_list) 

+
+ + + diff --git a/tests/htmlcov/z_75799433d8182c47_encode_py.html b/tests/htmlcov/z_75799433d8182c47_encode_py.html new file mode 100644 index 0000000..a2cae74 --- /dev/null +++ b/tests/htmlcov/z_75799433d8182c47_encode_py.html @@ -0,0 +1,226 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py: 95% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/encode.py: + 95% +

+ +

+ 37 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class VigenereEncode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from dataclasses import dataclass, field 

+

25from typing import List, Optional 

+

26 

+

27try: 

+

28 from codecipher.vigenere.lookup_table import LookUpTable 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43@dataclass 

+

44class VigenereEncode: 

+

45 ''' 

+

46 Defines class VigenereEncode with attribute(s) and method(s). 

+

47 Creates encode class with backend API. 

+

48 

+

49 It defines: 

+

50 

+

51 :attributes: 

+

52 | _encode_data - Data encode container. 

+

53 :methods: 

+

54 | encode_data - Property methods for encode data. 

+

55 | _split_data - Splitting data for encoding. 

+

56 | encode - Encode data to Vigenere format. 

+

57 ''' 

+

58 

+

59 _encode_data: Optional[str] = field(default=None) 

+

60 

+

61 @property 

+

62 def encode_data(self) -> Optional[str]: 

+

63 ''' 

+

64 Property method for getting encode data. 

+

65 

+

66 :return: Encoded data | None 

+

67 :rtype: <Optional[str]> 

+

68 :exceptions: None 

+

69 ''' 

+

70 return self._encode_data 

+

71 

+

72 @encode_data.setter 

+

73 def encode_data(self, encode_data_val: Optional[str]) -> None: 

+

74 ''' 

+

75 Property method for setting encode data. 

+

76 

+

77 :param encode_data_val: Encode data | None 

+

78 :type encode_data_val: <Optional[str]> 

+

79 :return: None 

+

80 :exceptions: None 

+

81 ''' 

+

82 if bool(encode_data_val): 

+

83 self._encode_data = encode_data_val 

+

84 

+

85 def _split_data_encode( 

+

86 self, data_to_encode: Optional[str], key: Optional[str] 

+

87 ) -> List[str]: 

+

88 ''' 

+

89 Splitting data for encoding. 

+

90 

+

91 :param data_to_encode: Data which should be encoded | None 

+

92 :type data_to_encode: <Optional[str]> 

+

93 :param key: Key for encoding | None 

+

94 :type key: <Optional[str]> 

+

95 :return: List with data for encoding 

+

96 :rtype: <List[str]> 

+

97 :exceptions: None 

+

98 ''' 

+

99 elements: List[str] = [] 

+

100 if bool(data_to_encode) and bool(key): 

+

101 for i in range(0, len(data_to_encode), len(key)): 

+

102 elements.append(data_to_encode[i: i + len(key)]) 

+

103 return elements 

+

104 

+

105 def encode( 

+

106 self, data_to_encode: Optional[str], key: Optional[str] 

+

107 ) -> None: 

+

108 ''' 

+

109 Encoding data to Vigenere format. 

+

110 

+

111 :param data_to_encode: Data which should be encoded | None 

+

112 :type data_to_encode: <Optional[str]> 

+

113 :param key: Key for encoding | None 

+

114 :type key: <Optional[str]> 

+

115 :return: None 

+

116 :exceptions: None 

+

117 ''' 

+

118 if bool(data_to_encode) and bool(key): 

+

119 encode_list: List[str] = [] 

+

120 for element in self._split_data_encode(data_to_encode, key): 

+

121 for index, letter in enumerate(element): 

+

122 process_index: int = ( 

+

123 LookUpTable.LETTER_TO_INDEX[letter] + 

+

124 LookUpTable.LETTER_TO_INDEX[key[index]] 

+

125 ) % len(LookUpTable.ALPHANUM) 

+

126 encode_list.append( 

+

127 LookUpTable.INDEX_TO_LETTER[process_index] 

+

128 ) 

+

129 self._encode_data = ''.join(encode_list) 

+
+ + + diff --git a/tests/htmlcov/z_75799433d8182c47_key_generator_py.html b/tests/htmlcov/z_75799433d8182c47_key_generator_py.html new file mode 100644 index 0000000..ba0771d --- /dev/null +++ b/tests/htmlcov/z_75799433d8182c47_key_generator_py.html @@ -0,0 +1,216 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py: 95% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/key_generator.py: + 95% +

+ +

+ 37 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 key_generator.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class KeyGenerator with attribute(s) and method(s). 

+

20 Creates key generator class for Vigener encoding/decoding. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class KeyGenerator: 

+

38 ''' 

+

39 Defines class KeyGenerator with attribute(s) and method(s). 

+

40 Creates key generator class for Vigener encoding/decoding. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _data_len - Data length. 

+

46 | _key - Key for encoding/decoding. 

+

47 :methods: 

+

48 | data - Property methods for data length. 

+

49 | key - Property methods for key. 

+

50 | generate_key - Generates key for encoding/decoding. 

+

51 ''' 

+

52 

+

53 _data_len: Optional[int] = field(default=None) 

+

54 _key: Optional[str] = field(default=None) 

+

55 

+

56 @property 

+

57 def data_len(self) -> Optional[int]: 

+

58 ''' 

+

59 Property method for getting data length. 

+

60 

+

61 :return: Data length | None 

+

62 :rtype: <Optional[int]> 

+

63 :exceptions: None 

+

64 ''' 

+

65 return self._data_len 

+

66 

+

67 @data_len.setter 

+

68 def data_len(self, data_length: Optional[int]) -> None: 

+

69 ''' 

+

70 Property method for setting data length. 

+

71 

+

72 :param data: Data length | None 

+

73 :type data: <Optional[int]> 

+

74 :return: None 

+

75 :exceptions: None 

+

76 ''' 

+

77 if bool(data_length): 

+

78 self._data_len = data_length 

+

79 

+

80 @property 

+

81 def key(self) -> Optional[str]: 

+

82 ''' 

+

83 Property method for getting key. 

+

84 

+

85 :return: Key for encoding/decoding | None 

+

86 :rtype: <Optional[str]> 

+

87 :exceptions: None 

+

88 ''' 

+

89 return self._key 

+

90 

+

91 @key.setter 

+

92 def key(self, key: Optional[str]) -> None: 

+

93 ''' 

+

94 Property method for setting key. 

+

95 

+

96 :param key: Key for encoding/decoding | None 

+

97 :type key: <Optional[str]> 

+

98 :return: None 

+

99 :exceptions: None 

+

100 ''' 

+

101 if bool(key): 

+

102 self._key = key 

+

103 

+

104 def generate_key(self) -> None: 

+

105 ''' 

+

106 Generates key for encoding/decoding. 

+

107 

+

108 :return: None 

+

109 :exceptions: None 

+

110 ''' 

+

111 if bool(self._key): 

+

112 key_list: List[str] = list(self._key) 

+

113 if bool(key_list) and bool(self._data_len): 

+

114 if self._data_len == len(key_list): 

+

115 pass 

+

116 else: 

+

117 for i in range(self._data_len - len(key_list)): 

+

118 key_list.append(key_list[i % len(key_list)]) 

+

119 self._key = ''. join(key_list) 

+
+ + + diff --git a/tests/htmlcov/z_75799433d8182c47_lookup_table_py.html b/tests/htmlcov/z_75799433d8182c47_lookup_table_py.html new file mode 100644 index 0000000..75d4f03 --- /dev/null +++ b/tests/htmlcov/z_75799433d8182c47_lookup_table_py.html @@ -0,0 +1,155 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vigenere/lookup_table.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 lookup_table.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class LookUpTable with attribute(s). 

+

20 Creates lookup table class with support for encoding/decoding. 

+

21''' 

+

22 

+

23from typing import List, Dict 

+

24 

+

25__author__: str = 'Vladimir Roncevic' 

+

26__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

27__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

28__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

29__version__: str = '1.4.8' 

+

30__maintainer__: str = 'Vladimir Roncevic' 

+

31__email__: str = 'elektron.ronca@gmail.com' 

+

32__status__: str = 'Updated' 

+

33 

+

34 

+

35class LookUpTable: 

+

36 ''' 

+

37 Defines class LookUpTable with attribute(s) and method(s). 

+

38 Creates lookup table class with support for encoding/decoding. 

+

39 

+

40 It defines: 

+

41 

+

42 :attributes: 

+

43 | ALPHA - Define alphabet for encoding/decoding. 

+

44 | NUM - Defines numeric for encoding/decoding. 

+

45 | WHITE_SPACE - Defines white space for encoding/decoding. 

+

46 | ALPHANUM - Aggregated chars for encoding/decoding. 

+

47 | LETTER_TO_INDEX - Indexed letters for encoding/decoding. 

+

48 | INDEX_TO_LETTER - Indexed letters for encoding/decoding. 

+

49 :methods: 

+

50 | None 

+

51 ''' 

+

52 

+

53 ALPHA: str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' 

+

54 NUM: str = '0123456789' 

+

55 WHITE_SPACE: str = ' ' 

+

56 ALPHANUM: str = ''.join([ALPHA, NUM, WHITE_SPACE]) 

+

57 LETTER_TO_INDEX: Dict[str, int] = dict(zip(ALPHANUM, range(len(ALPHANUM)))) 

+

58 INDEX_TO_LETTER: Dict[int, str] = dict(zip(range(len(ALPHANUM)), ALPHANUM)) 

+
+ + + diff --git a/tests/htmlcov/z_7dc3960ecaf412e4___init___py.html b/tests/htmlcov/z_7dc3960ecaf412e4___init___py.html new file mode 100644 index 0000000..917e7f6 --- /dev/null +++ b/tests/htmlcov/z_7dc3960ecaf412e4___init___py.html @@ -0,0 +1,115 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/__init__.py: + 100% +

+ +

+ 0 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18''' 

+
+ + + diff --git a/tests/htmlcov/z_8f54ab6b5b508ca0___init___py.html b/tests/htmlcov/z_8f54ab6b5b508ca0___init___py.html new file mode 100644 index 0000000..4f24da8 --- /dev/null +++ b/tests/htmlcov/z_8f54ab6b5b508ca0___init___py.html @@ -0,0 +1,159 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/__init__.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class B64 with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.b64.encode import B64Encode 

+

28 from codecipher.b64.decode import B64Decode 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43class B64(B64Encode, B64Decode): 

+

44 ''' 

+

45 Defines class B64 with attribute(s) and method(s). 

+

46 Creates container class with aggregate backend API. 

+

47 

+

48 It defines: 

+

49 

+

50 :attributes: 

+

51 | None. 

+

52 :methods: 

+

53 | __init__ - Initials B64 constructor. 

+

54 ''' 

+

55 

+

56 def __init__(self) -> None: 

+

57 ''' 

+

58 Initials B64 constructor. 

+

59 

+

60 :exceptions: None 

+

61 ''' 

+

62 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_8f54ab6b5b508ca0_decode_py.html b/tests/htmlcov/z_8f54ab6b5b508ca0_decode_py.html new file mode 100644 index 0000000..24f7046 --- /dev/null +++ b/tests/htmlcov/z_8f54ab6b5b508ca0_decode_py.html @@ -0,0 +1,185 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py: 92% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/decode.py: + 92% +

+ +

+ 24 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class AlephTawBetShinDecode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from base64 import b64decode 

+

25from typing import List, Optional 

+

26 

+

27__author__: str = 'Vladimir Roncevic' 

+

28__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

29__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

30__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

31__version__: str = '1.4.8' 

+

32__maintainer__: str = 'Vladimir Roncevic' 

+

33__email__: str = 'elektron.ronca@gmail.com' 

+

34__status__: str = 'Updated' 

+

35 

+

36 

+

37@dataclass 

+

38class B64Decode: 

+

39 ''' 

+

40 Defines class AlephTawBetShinDecode with attribute(s) and method(s). 

+

41 Creates decode class with backend API. 

+

42 

+

43 It defines: 

+

44 

+

45 :attributes: 

+

46 | _decode_data - Data decode container. 

+

47 :methods: 

+

48 | decode_data - Property methods for decode data. 

+

49 | decode - Decode data from AlephTawBetShin format. 

+

50 ''' 

+

51 

+

52 _decode_data: Optional[str] = field(default=None) 

+

53 

+

54 @property 

+

55 def decode_data(self) -> Optional[str]: 

+

56 ''' 

+

57 Property method for getting decode data. 

+

58 

+

59 :return: Decode data in str format | None 

+

60 :rtype: <Optional[str]> 

+

61 :exceptions: None 

+

62 ''' 

+

63 return self._decode_data 

+

64 

+

65 @decode_data.setter 

+

66 def decode_data(self, decode_data: Optional[str]) -> None: 

+

67 ''' 

+

68 Property method for setting decode data. 

+

69 

+

70 :param decode_data: Decoded data 

+

71 :type decode_data: <Optional[str]> 

+

72 :return: None 

+

73 :exceptions: None 

+

74 ''' 

+

75 if bool(decode_data): 

+

76 self._decode_data = decode_data 

+

77 

+

78 def decode(self, data: Optional[str]) -> None: 

+

79 ''' 

+

80 Decoding data from AlephTawBetShin format. 

+

81 

+

82 :param data: Data which should be decoded | None 

+

83 :type data: <Optional[str]> 

+

84 :return: None 

+

85 :exceptions: None 

+

86 ''' 

+

87 if bool(data): 

+

88 self._decode_data = b64decode(data).decode() 

+
+ + + diff --git a/tests/htmlcov/z_8f54ab6b5b508ca0_encode_py.html b/tests/htmlcov/z_8f54ab6b5b508ca0_encode_py.html new file mode 100644 index 0000000..bef1331 --- /dev/null +++ b/tests/htmlcov/z_8f54ab6b5b508ca0_encode_py.html @@ -0,0 +1,185 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py: 92% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/b64/encode.py: + 92% +

+ +

+ 24 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class B64Encode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from base64 import b64encode 

+

25from typing import List, Optional 

+

26 

+

27__author__: str = 'Vladimir Roncevic' 

+

28__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

29__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

30__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

31__version__: str = '1.4.8' 

+

32__maintainer__: str = 'Vladimir Roncevic' 

+

33__email__: str = 'elektron.ronca@gmail.com' 

+

34__status__: str = 'Updated' 

+

35 

+

36 

+

37@dataclass 

+

38class B64Encode: 

+

39 ''' 

+

40 Defines class B64Encode with attribute(s) and method(s). 

+

41 Creates encode class with backend API. 

+

42 

+

43 It defines: 

+

44 

+

45 :attributes: 

+

46 | _encode_data - Data encode container. 

+

47 :methods: 

+

48 | encode_data - Property methods for encode data. 

+

49 | encode - Encode data to AlephTawBetShin format. 

+

50 ''' 

+

51 

+

52 _encode_data: Optional[str] = field(default=None) 

+

53 

+

54 @property 

+

55 def encode_data(self) -> Optional[str]: 

+

56 ''' 

+

57 Property method for getting encode data. 

+

58 

+

59 :return: Encoded data | None 

+

60 :rtype: <Optional[str]> 

+

61 :exceptions: None 

+

62 ''' 

+

63 return self._encode_data 

+

64 

+

65 @encode_data.setter 

+

66 def encode_data(self, encode_data: Optional[str]) -> None: 

+

67 ''' 

+

68 Property method for setting encode data. 

+

69 

+

70 :param encode_data: Encode data | None 

+

71 :type encode_data: <Optional[str]> 

+

72 :return: None 

+

73 :exceptions: None 

+

74 ''' 

+

75 if bool(encode_data): 

+

76 self._encode_data = encode_data 

+

77 

+

78 def encode(self, data: Optional[str]) -> None: 

+

79 ''' 

+

80 Encoding data to AlephTawBetShin format. 

+

81 

+

82 :param data: Data which should be encoded | None 

+

83 :type data: <Optional[str]> 

+

84 :return: None 

+

85 :exceptions: None 

+

86 ''' 

+

87 if bool(data): 

+

88 self._encode_data = (b64encode(data.encode())).decode() 

+
+ + + diff --git a/tests/htmlcov/z_96938f9400a5cdf6___init___py.html b/tests/htmlcov/z_96938f9400a5cdf6___init___py.html new file mode 100644 index 0000000..b7d9db0 --- /dev/null +++ b/tests/htmlcov/z_96938f9400a5cdf6___init___py.html @@ -0,0 +1,159 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/__init__.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class A1z52N62 with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.a1z52n62.encode import A1z52N62Encode 

+

28 from codecipher.a1z52n62.decode import A1z52N62Decode 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43class A1z52N62(A1z52N62Encode, A1z52N62Decode): 

+

44 ''' 

+

45 Defines class A1z52N62 with attribute(s) and method(s). 

+

46 Creates container class with aggregate backend API. 

+

47 

+

48 It defines: 

+

49 

+

50 :attributes: 

+

51 | None. 

+

52 :methods: 

+

53 | __init__ - Initials A1z52N62 constructor. 

+

54 ''' 

+

55 

+

56 def __init__(self) -> None: 

+

57 ''' 

+

58 Initials A1z52N62 constructor. 

+

59 

+

60 :exceptions: None 

+

61 ''' 

+

62 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_96938f9400a5cdf6_decode_py.html b/tests/htmlcov/z_96938f9400a5cdf6_decode_py.html new file mode 100644 index 0000000..c22a718 --- /dev/null +++ b/tests/htmlcov/z_96938f9400a5cdf6_decode_py.html @@ -0,0 +1,196 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py: 94% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/decode.py: + 94% +

+ +

+ 32 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class A1z52N62Decode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class A1z52N62Decode: 

+

38 ''' 

+

39 Defines class A1z52N62Decode with attribute(s) and method(s). 

+

40 Creates decode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _decode_data - Data decode container. 

+

46 :methods: 

+

47 | decode_data - Property methods for decode data. 

+

48 | decode - Decode data from A1z52N62 format. 

+

49 ''' 

+

50 

+

51 _decode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def decode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting decode data. 

+

57 

+

58 :return: Decode data in str format | None 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._decode_data 

+

63 

+

64 @decode_data.setter 

+

65 def decode_data(self, decode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting decode data. 

+

68 

+

69 :param decode_data: Decoded data | None 

+

70 :type decode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(decode_data): 

+

75 self._decode_data = decode_data 

+

76 

+

77 def decode(self, data: Optional[str]) -> None: 

+

78 ''' 

+

79 Decoding data from A1z52N62 format. 

+

80 

+

81 :param data: Data which should be decoded | None 

+

82 :type data: <Optional[str]> 

+

83 :return: None 

+

84 :exceptions: None 

+

85 ''' 

+

86 if bool(data): 

+

87 decode_list: List[str] = [] 

+

88 for element in data.split(' - '): 

+

89 if element.isnumeric(): 

+

90 if int(element) <= 52: 

+

91 if int(element) <= 26: 

+

92 decode_list.append(chr(int(element) + 64)) 

+

93 else: 

+

94 decode_list.append(chr(int(element) + 96 - 27)) 

+

95 else: 

+

96 decode_list.append(str(int(element) - 53)) 

+

97 else: 

+

98 decode_list.append(element) 

+

99 self._decode_data = ''.join(decode_list) 

+
+ + + diff --git a/tests/htmlcov/z_96938f9400a5cdf6_encode_py.html b/tests/htmlcov/z_96938f9400a5cdf6_encode_py.html new file mode 100644 index 0000000..1a5791e --- /dev/null +++ b/tests/htmlcov/z_96938f9400a5cdf6_encode_py.html @@ -0,0 +1,196 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py: 94% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/a1z52n62/encode.py: + 94% +

+ +

+ 32 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class A1z52N62Encode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class A1z52N62Encode: 

+

38 ''' 

+

39 Defines class A1z52N62Encode with attribute(s) and method(s). 

+

40 Creates encode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _encode_data - Data encode container. 

+

46 :methods: 

+

47 | encode_data - Property methods for encode data. 

+

48 | encode - Encode data to A1z52N62 format. 

+

49 ''' 

+

50 

+

51 _encode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def encode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting encode data. 

+

57 

+

58 :return: Encoded data 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._encode_data 

+

63 

+

64 @encode_data.setter 

+

65 def encode_data(self, encode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting encode data. 

+

68 

+

69 :param encode_data: Encode data | None 

+

70 :type encode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(encode_data): 

+

75 self._encode_data = encode_data 

+

76 

+

77 def encode(self, data: Optional[str]) -> None: 

+

78 ''' 

+

79 Encoding data to A1z52N62 format. 

+

80 

+

81 :param data: Data which should be encoded | None 

+

82 :type data: <Optional[str]> 

+

83 :return: None 

+

84 :exceptions: None 

+

85 ''' 

+

86 if bool(data): 

+

87 encode_list: List[str] = [] 

+

88 for element in data: 

+

89 if element.isalpha(): 

+

90 if element.isupper(): 

+

91 encode_list.append(str(ord(element) - 64)) 

+

92 else: 

+

93 encode_list.append(str(ord(element) - 96 + 27)) 

+

94 else: 

+

95 if element.isnumeric(): 

+

96 encode_list.append(str(int(element) + 53)) 

+

97 else: 

+

98 encode_list.append(element) 

+

99 self._encode_data = ' - '.join(encode_list) 

+
+ + + diff --git a/tests/htmlcov/z_9927f90504198b80___init___py.html b/tests/htmlcov/z_9927f90504198b80___init___py.html new file mode 100644 index 0000000..db404a7 --- /dev/null +++ b/tests/htmlcov/z_9927f90504198b80___init___py.html @@ -0,0 +1,159 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/__init__.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class AlephTawBetShin with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.atbs.encode import AlephTawBetShinEncode 

+

28 from codecipher.atbs.decode import AlephTawBetShinDecode 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43class AlephTawBetShin(AlephTawBetShinEncode, AlephTawBetShinDecode): 

+

44 ''' 

+

45 Defines class AlephTawBetShin with attribute(s) and method(s). 

+

46 Creates container class with aggregate backend API. 

+

47 

+

48 It defines: 

+

49 

+

50 :attributes: 

+

51 | None. 

+

52 :methods: 

+

53 | __init__ - Initials AlephTawBetShin constructor. 

+

54 ''' 

+

55 

+

56 def __init__(self) -> None: 

+

57 ''' 

+

58 Initials AlephTawBetShin constructor. 

+

59 

+

60 :exceptions: None 

+

61 ''' 

+

62 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_9927f90504198b80_decode_py.html b/tests/htmlcov/z_9927f90504198b80_decode_py.html new file mode 100644 index 0000000..90c1414 --- /dev/null +++ b/tests/htmlcov/z_9927f90504198b80_decode_py.html @@ -0,0 +1,194 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py: 93% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/decode.py: + 93% +

+ +

+ 29 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class AlephTawBetShinDecode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from dataclasses import dataclass, field 

+

25from typing import List, Optional 

+

26 

+

27try: 

+

28 from codecipher.atbs.lookup_table import LOOKUP_TABLE 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43@dataclass 

+

44class AlephTawBetShinDecode: 

+

45 ''' 

+

46 Defines class AlephTawBetShinDecode with attribute(s) and method(s). 

+

47 Creates decode class with backend API. 

+

48 

+

49 It defines: 

+

50 

+

51 :attributes: 

+

52 | _decode_data - Data decode container. 

+

53 :methods: 

+

54 | decode_data - Property methods for decode data. 

+

55 | decode - Decode data from AlephTawBetShin format. 

+

56 ''' 

+

57 

+

58 _decode_data: Optional[str] = field(default=None) 

+

59 

+

60 @property 

+

61 def decode_data(self) -> Optional[str]: 

+

62 ''' 

+

63 Property method for getting decode data. 

+

64 

+

65 :return: Decode data in str format | None 

+

66 :rtype: <Optional[str]> 

+

67 :exceptions: None 

+

68 ''' 

+

69 return self._decode_data 

+

70 

+

71 @decode_data.setter 

+

72 def decode_data(self, decode_data: Optional[str]) -> None: 

+

73 ''' 

+

74 Property method for setting decode data. 

+

75 

+

76 :param decode_data: Decoded data | None 

+

77 :type decode_data: <Optional[str]> 

+

78 :return: None 

+

79 :exceptions: None 

+

80 ''' 

+

81 if bool(decode_data): 

+

82 self._decode_data = decode_data 

+

83 

+

84 def decode(self, data: Optional[str]) -> None: 

+

85 ''' 

+

86 Decoding data from AlephTawBetShin format. 

+

87 

+

88 :param data: Data which should be decoded | None 

+

89 :type data: <Optional[str]> 

+

90 :return: None 

+

91 :exceptions: None 

+

92 ''' 

+

93 if bool(data): 

+

94 decode_list: List[str] = [] 

+

95 for element in data: 

+

96 decode_list.append(LOOKUP_TABLE[element]) 

+

97 self._decode_data = ''.join(decode_list) 

+
+ + + diff --git a/tests/htmlcov/z_9927f90504198b80_encode_py.html b/tests/htmlcov/z_9927f90504198b80_encode_py.html new file mode 100644 index 0000000..eca89be --- /dev/null +++ b/tests/htmlcov/z_9927f90504198b80_encode_py.html @@ -0,0 +1,194 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py: 93% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/encode.py: + 93% +

+ +

+ 29 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class AlephTawBetShinEncode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from dataclasses import dataclass, field 

+

25from typing import List, Optional 

+

26 

+

27try: 

+

28 from codecipher.atbs.lookup_table import LOOKUP_TABLE 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43@dataclass 

+

44class AlephTawBetShinEncode: 

+

45 ''' 

+

46 Defines class AlephTawBetShinEncode with attribute(s) and method(s). 

+

47 Creates encode class with backend API. 

+

48 

+

49 It defines: 

+

50 

+

51 :attributes: 

+

52 | _encode_data - Data encode container. 

+

53 :methods: 

+

54 | encode_data - Property methods for encode data. 

+

55 | encode - Encode data to AlephTawBetShin format. 

+

56 ''' 

+

57 

+

58 _encode_data: Optional[str] = field(default=None) 

+

59 

+

60 @property 

+

61 def encode_data(self) -> Optional[str]: 

+

62 ''' 

+

63 Property method for getting encode data. 

+

64 

+

65 :return: Encoded data | None 

+

66 :rtype: <Optional[str]> 

+

67 :exceptions: None 

+

68 ''' 

+

69 return self._encode_data 

+

70 

+

71 @encode_data.setter 

+

72 def encode_data(self, encode_data: Optional[str]) -> None: 

+

73 ''' 

+

74 Property method for setting encode data. 

+

75 

+

76 :param encode_data: Encode data | None 

+

77 :type encode_data: <Optional[str]> 

+

78 :return: None 

+

79 :exceptions: None 

+

80 ''' 

+

81 if bool(encode_data): 

+

82 self._encode_data = encode_data 

+

83 

+

84 def encode(self, data: Optional[str]) -> None: 

+

85 ''' 

+

86 Encoding data to AlephTawBetShin format. 

+

87 

+

88 :param data: Data which should be encoded | None 

+

89 :type data: <Optional[str]> 

+

90 :return: None 

+

91 :exceptions: None 

+

92 ''' 

+

93 if bool(data): 

+

94 encode_list: List[str] = [] 

+

95 for element in data: 

+

96 encode_list.append(LOOKUP_TABLE[element]) 

+

97 self._encode_data = ''.join(encode_list) 

+
+ + + diff --git a/tests/htmlcov/z_9927f90504198b80_lookup_table_py.html b/tests/htmlcov/z_9927f90504198b80_lookup_table_py.html new file mode 100644 index 0000000..18feee4 --- /dev/null +++ b/tests/htmlcov/z_9927f90504198b80_lookup_table_py.html @@ -0,0 +1,144 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/atbs/lookup_table.py: + 100% +

+ +

+ 10 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 lookup_table.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines dict LOOKUP_TABLE for AlephTawBetShin format. 

+

20''' 

+

21 

+

22from typing import List, Dict 

+

23 

+

24__author__: str = 'Vladimir Roncevic' 

+

25__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

26__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

27__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

28__version__: str = '1.4.8' 

+

29__maintainer__: str = 'Vladimir Roncevic' 

+

30__email__: str = 'elektron.ronca@gmail.com' 

+

31__status__: str = 'Updated' 

+

32 

+

33LOOKUP_TABLE: Dict[str, str] = { 

+

34 'A': 'Z', 'B': 'Y', 'C': 'X', 'D': 'W', 'E': 'V', 

+

35 'F': 'U', 'G': 'T', 'H': 'S', 'I': 'R', 'J': 'Q', 

+

36 'K': 'P', 'L': 'O', 'M': 'N', 'N': 'M', 'O': 'L', 

+

37 'P': 'K', 'Q': 'J', 'R': 'I', 'S': 'H', 'T': 'G', 

+

38 'U': 'F', 'V': 'E', 'W': 'D', 'X': 'C', 'Y': 'B', 

+

39 'Z': 'A', 'a': 'z', 'b': 'y', 'c': 'x', 'd': 'w', 

+

40 'e': 'v', 'f': 'u', 'g': 't', 'h': 's', 'i': 'r', 

+

41 'j': 'q', 'k': 'p', 'l': 'o', 'm': 'n', 'n': 'm', 

+

42 'o': 'l', 'p': 'k', 'q': 'j', 'r': 'i', 's': 'h', 

+

43 't': 'g', 'u': 'f', 'v': 'e', 'w': 'd', 'x': 'c', 

+

44 'y': 'b', 'z': 'a', ' ': ' ', '\n': '\n', '0': '9', 

+

45 '1': '8', '2': '7', '3': '6', '4': '5', '5': '4', 

+

46 '6': '3', '7': '2', '8': '1', '9': '0' 

+

47} 

+
+ + + diff --git a/tests/htmlcov/z_aba196749d301797___init___py.html b/tests/htmlcov/z_aba196749d301797___init___py.html new file mode 100644 index 0000000..faeae56 --- /dev/null +++ b/tests/htmlcov/z_aba196749d301797___init___py.html @@ -0,0 +1,159 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py: 100% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/__init__.py: + 100% +

+ +

+ 16 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 __init__.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class Vernam with attribute(s) and method(s). 

+

20 Creates container class with aggregate backend API. 

+

21''' 

+

22 

+

23import sys 

+

24from typing import List 

+

25 

+

26try: 

+

27 from codecipher.vernam.encode import VernamEncode 

+

28 from codecipher.vernam.decode import VernamDecode 

+

29except ImportError as ats_error_message: # pragma: no cover 

+

30 # Force exit python ####################################################### 

+

31 sys.exit(f'\n{__file__}\n{ats_error_message}\n') # pragma: no cover 

+

32 

+

33__author__: str = 'Vladimir Roncevic' 

+

34__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

35__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

36__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

37__version__: str = '1.4.8' 

+

38__maintainer__: str = 'Vladimir Roncevic' 

+

39__email__: str = 'elektron.ronca@gmail.com' 

+

40__status__: str = 'Updated' 

+

41 

+

42 

+

43class Vernam(VernamEncode, VernamDecode): 

+

44 ''' 

+

45 Defines class Vernam with attribute(s) and method(s). 

+

46 Creates container class with aggregate backend API. 

+

47 

+

48 It defines: 

+

49 

+

50 :attributes: 

+

51 | None. 

+

52 :methods: 

+

53 | __init__ - Initials Vernam constructor. 

+

54 ''' 

+

55 

+

56 def __init__(self) -> None: 

+

57 ''' 

+

58 Initials Vernam constructor. 

+

59 

+

60 :exceptions: None 

+

61 ''' 

+

62 super().__init__() 

+
+ + + diff --git a/tests/htmlcov/z_aba196749d301797_decode_py.html b/tests/htmlcov/z_aba196749d301797_decode_py.html new file mode 100644 index 0000000..e2d844a --- /dev/null +++ b/tests/htmlcov/z_aba196749d301797_decode_py.html @@ -0,0 +1,201 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py: 94% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/decode.py: + 94% +

+ +

+ 36 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 decode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class VernamDecode with attribute(s) and method(s). 

+

20 Creates decode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class VernamDecode: 

+

38 ''' 

+

39 Defines class VernamDecode with attribute(s) and method(s). 

+

40 Creates decode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _decode_data - Data decode container. 

+

46 :methods: 

+

47 | decode_data - Property methods for decode data. 

+

48 | decode - Decode data from Vernam format. 

+

49 ''' 

+

50 

+

51 _decode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def decode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting decode data. 

+

57 

+

58 :return: Decode data in str format | None 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._decode_data 

+

63 

+

64 @decode_data.setter 

+

65 def decode_data(self, decode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting decode data. 

+

68 

+

69 :param decode_data: Decoded data | None 

+

70 :type decode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(decode_data): 

+

75 self._decode_data = decode_data 

+

76 

+

77 def decode(self, data: Optional[str], key: Optional[str]) -> None: 

+

78 ''' 

+

79 Decoding data from Vernam format. 

+

80 

+

81 :param data: Data which should be decoded | None 

+

82 :type data: <Optional[str]> 

+

83 :param key: Key for decoding | None 

+

84 :type key: <Optional[str]> 

+

85 :return: None 

+

86 :exceptions: None 

+

87 ''' 

+

88 if bool(data) and bool(key): 

+

89 decode_list: List[str] = [] 

+

90 key = (key * (len(data) // len(key))) + key[:len(data) % len(key)] 

+

91 for i, element in enumerate(data): 

+

92 if element.isalpha() and key[i].isalpha(): 

+

93 key_code: int = ord(key[i].lower()) - 96 

+

94 code: int = ord(element.lower()) - 96 

+

95 ans: int = code - key_code + 1 

+

96 if ans < 1: 

+

97 ans += 26 

+

98 if element.isupper(): 

+

99 decode_list.append(chr(ans + 96).upper()) 

+

100 else: 

+

101 decode_list.append(chr(ans + 96)) 

+

102 else: 

+

103 decode_list.append(element) 

+

104 self._decode_data = ''.join(decode_list) 

+
+ + + diff --git a/tests/htmlcov/z_aba196749d301797_encode_py.html b/tests/htmlcov/z_aba196749d301797_encode_py.html new file mode 100644 index 0000000..f0cb4aa --- /dev/null +++ b/tests/htmlcov/z_aba196749d301797_encode_py.html @@ -0,0 +1,201 @@ + + + + + Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py: 94% + + + + + +
+
+

+ Coverage for /data/dev/python/codecipher/github/codecipher/codecipher/vernam/encode.py: + 94% +

+ +

+ 36 statements   + + + +

+

+ « prev     + ^ index     + » next +       + coverage.py v7.6.10, + created at 2025-11-01 07:55 +0100 +

+ +
+
+
+

1# -*- coding: UTF-8 -*- 

+

2 

+

3''' 

+

4Module 

+

5 encode.py 

+

6Copyright 

+

7 Copyright (C) 2021 - 2025 Vladimir Roncevic <elektron.ronca@gmail.com> 

+

8 codecipher is free software: you can redistribute it and/or modify it 

+

9 under the terms of the GNU General Public License as published by the 

+

10 Free Software Foundation, either version 3 of the License, or 

+

11 (at your option) any later version. 

+

12 codecipher is distributed in the hope that it will be useful, but 

+

13 WITHOUT ANY WARRANTY; without even the implied warranty of 

+

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

+

15 See the GNU General Public License for more details. 

+

16 You should have received a copy of the GNU General Public License along 

+

17 with this program. If not, see <http://www.gnu.org/licenses/>. 

+

18Info 

+

19 Defines class VernamEncode with attribute(s) and method(s). 

+

20 Creates encode class with backend API. 

+

21''' 

+

22 

+

23from dataclasses import dataclass, field 

+

24from typing import List, Optional 

+

25 

+

26__author__: str = 'Vladimir Roncevic' 

+

27__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' 

+

28__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] 

+

29__license__: str = 'https://github.com/electux/codecipher/blob/main/LICENSE' 

+

30__version__: str = '1.4.8' 

+

31__maintainer__: str = 'Vladimir Roncevic' 

+

32__email__: str = 'elektron.ronca@gmail.com' 

+

33__status__: str = 'Updated' 

+

34 

+

35 

+

36@dataclass 

+

37class VernamEncode: 

+

38 ''' 

+

39 Defines class VernamEncode with attribute(s) and method(s). 

+

40 Creates encode class with backend API. 

+

41 

+

42 It defines: 

+

43 

+

44 :attributes: 

+

45 | _encode_data - Data encode container. 

+

46 :methods: 

+

47 | encode_data - Property methods for encode data. 

+

48 | encode - Encode data to Vernam format. 

+

49 ''' 

+

50 

+

51 _encode_data: Optional[str] = field(default=None) 

+

52 

+

53 @property 

+

54 def encode_data(self) -> Optional[str]: 

+

55 ''' 

+

56 Property method for getting encode data. 

+

57 

+

58 :return: Encoded data | None 

+

59 :rtype: <Optional[str]> 

+

60 :exceptions: None 

+

61 ''' 

+

62 return self._encode_data 

+

63 

+

64 @encode_data.setter 

+

65 def encode_data(self, encode_data: Optional[str]) -> None: 

+

66 ''' 

+

67 Property method for setting encode data. 

+

68 

+

69 :param encode_data: Encode data | None 

+

70 :type encode_data: <Optional[str]> 

+

71 :return: None 

+

72 :exceptions: None 

+

73 ''' 

+

74 if bool(encode_data): 

+

75 self._encode_data = encode_data 

+

76 

+

77 def encode(self, data: Optional[str], key: Optional[str]) -> None: 

+

78 ''' 

+

79 Encoding data to Vernam format. 

+

80 

+

81 :param data: Data which should be encoded | None 

+

82 :type data: <Optional[str]> 

+

83 :param key: Key for encoding | None 

+

84 :type key: <Optional[str]> 

+

85 :return: None 

+

86 :exceptions: None 

+

87 ''' 

+

88 if bool(data) and bool(key): 

+

89 encode_list: List[str] = [] 

+

90 key = (key * (len(data) // len(key))) + key[:len(data) % len(key)] 

+

91 for i, element in enumerate(data): 

+

92 if element.isalpha() and key[i].isalpha(): 

+

93 key_code: int = ord(key[i].lower()) - 96 

+

94 text_code: int = ord(element.lower()) - 96 

+

95 ans: int = text_code + key_code - 1 

+

96 if ans > 26: 

+

97 ans -= 26 

+

98 if element.isupper(): 

+

99 encode_list.append(chr(ans + 96).upper()) 

+

100 else: 

+

101 encode_list.append(chr(ans + 96)) 

+

102 else: 

+

103 encode_list.append(element) 

+

104 self._encode_data = ''.join(encode_list) 

+
+ + + diff --git a/tests/run_coverage.sh b/tests/run_coverage.sh index a2ccf66..bd38487 100755 --- a/tests/run_coverage.sh +++ b/tests/run_coverage.sh @@ -7,5 +7,11 @@ # @author Vladimir Roncevic # +rm -rf htmlcov codecipher_coverage.xml codecipher_coverage.json .coverage python3 -m coverage run -m --source=../codecipher unittest discover -s ./ -p '*_test.py' -vvv -python3 -m coverage html +python3 -m coverage html -d htmlcov +python3 -m coverage xml -o codecipher_coverage.xml +python3 -m coverage json -o codecipher_coverage.json +python3 -m coverage report --format=markdown -m +python3 ats_coverage.py -n codecipher +echo "Done" diff --git a/tests/vernam_test.py b/tests/vernam_test.py index b2bfef8..17d4fab 100644 --- a/tests/vernam_test.py +++ b/tests/vernam_test.py @@ -4,7 +4,7 @@ Module vernam_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class VernamTestCase(unittest.TestCase): diff --git a/tests/vigenere_test.py b/tests/vigenere_test.py index 1e4bafb..5d0e125 100644 --- a/tests/vigenere_test.py +++ b/tests/vigenere_test.py @@ -4,7 +4,7 @@ Module vigenere_test.py Copyright - Copyright (C) 2021 - 2024 Vladimir Roncevic + Copyright (C) 2021 - 2025 Vladimir Roncevic codecipher is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -32,14 +32,14 @@ # Force close python test ################################################# sys.exit(f'\n{__file__}\n{test_error_message}\n') -__author__ = 'Vladimir Roncevic' -__copyright__ = '(C) 2024, https://electux.github.io/codecipher' +__author__: str = 'Vladimir Roncevic' +__copyright__: str = '(C) 2025, https://electux.github.io/codecipher' __credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation'] -__license__ = 'https://github.com/electux/codecipher/blob/dev/LICENSE' -__version__ = '1.4.7' -__maintainer__ = 'Vladimir Roncevic' -__email__ = 'elektron.ronca@gmail.com' -__status__ = 'Updated' +__license__: str = 'https://github.com/electux/codecipher/blob/dev/LICENSE' +__version__: str = '1.4.8' +__maintainer__: str = 'Vladimir Roncevic' +__email__: str = 'elektron.ronca@gmail.com' +__status__: str = 'Updated' class VigenereTestCase(unittest.TestCase):