├── tests ├── __init__.py ├── test_hebrew_package.py ├── test_grapheme_string.py ├── test_gematria.py ├── test_chars.py ├── test_hebrew.py └── test_numerical_conversion.py ├── docs ├── CNAME ├── index.md ├── license.md ├── changelog.md ├── contributing.md ├── code_reference │ ├── gematria.md │ ├── hebrew.md │ ├── grapheme_string.md │ ├── numerical_conversions │ │ ├── convert.md │ │ └── substitute.md │ └── chars │ │ ├── classes_and_functions.md │ │ └── constants.md ├── css │ ├── material.css │ ├── mkdocstrings.css │ └── style.css └── img │ ├── bad_character_display.png │ └── good_character_display.png ├── .coveragerc ├── hebrew ├── numerical_conversion │ ├── __init__.py │ ├── mappings.py │ ├── substitute.py │ └── convert.py ├── __init__.py ├── grapheme_string.py ├── gematria.py ├── hebrew_obj.py └── chars.py ├── requirements.txt ├── .flake8 ├── pull_request_template.md ├── .github └── workflows │ ├── ci.yml │ ├── codecov.yml │ ├── test.yml │ └── codeql-analysis.yml ├── LICENSE ├── mkdocs.yml ├── pyproject.toml ├── CONTRIBUTING.md ├── .gitignore ├── CHANGELOG.md └── README.md /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | hebrew.aviperl.me -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | {! README.md !} -------------------------------------------------------------------------------- /docs/license.md: -------------------------------------------------------------------------------- 1 | {! LICENSE !} -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source=hebrew -------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | {! CHANGELOG.md !} -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | {! CONTRIBUTING.md !} -------------------------------------------------------------------------------- /hebrew/numerical_conversion/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | grapheme==0.6.0 2 | toml==0.10.2 -------------------------------------------------------------------------------- /docs/code_reference/gematria.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.gematria -------------------------------------------------------------------------------- /docs/code_reference/hebrew.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.hebrew_obj -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 88 3 | extend-ignore = E203 -------------------------------------------------------------------------------- /docs/code_reference/grapheme_string.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.grapheme_string -------------------------------------------------------------------------------- /docs/code_reference/numerical_conversions/convert.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.numerical_conversion.convert -------------------------------------------------------------------------------- /docs/code_reference/numerical_conversions/substitute.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.numerical_conversion.substitute -------------------------------------------------------------------------------- /hebrew/__init__.py: -------------------------------------------------------------------------------- 1 | from .grapheme_string import * 2 | from .hebrew_obj import * 3 | 4 | __version__ = "0.8.1" 5 | -------------------------------------------------------------------------------- /docs/code_reference/chars/classes_and_functions.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.chars 2 | selection: 3 | filters: ["!^[A-Z_0-9]*$"] -------------------------------------------------------------------------------- /docs/code_reference/chars/constants.md: -------------------------------------------------------------------------------- 1 | ::: hebrew.chars 2 | selection: 3 | filters: ["!.*", "^[A-Z_0-9]*$", "!^_"] -------------------------------------------------------------------------------- /docs/css/material.css: -------------------------------------------------------------------------------- 1 | /* More space at the bottom of the page. */ 2 | .md-main__inner { 3 | margin-bottom: 1.5rem; 4 | } -------------------------------------------------------------------------------- /docs/img/bad_character_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avi-perl/Hebrew/HEAD/docs/img/bad_character_display.png -------------------------------------------------------------------------------- /docs/img/good_character_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avi-perl/Hebrew/HEAD/docs/img/good_character_display.png -------------------------------------------------------------------------------- /docs/css/mkdocstrings.css: -------------------------------------------------------------------------------- 1 | /* Indentation. */ 2 | div.doc-contents:not(.first) { 3 | padding-left: 25px; 4 | border-left: 4px solid rgba(230, 230, 230); 5 | margin-bottom: 80px; 6 | } 7 | 8 | /* Avoid breaking parameters name, etc. in table cells. */ 9 | td code { 10 | word-break: normal !important; 11 | } 12 | 13 | .headerlink { 14 | 15 | } -------------------------------------------------------------------------------- /tests/test_hebrew_package.py: -------------------------------------------------------------------------------- 1 | import toml 2 | from pathlib import Path 3 | 4 | from hebrew import __version__ 5 | 6 | 7 | def test_versions_are_in_sync(): 8 | """Checks if the pyproject.toml and package.__init__.py __version__ are in sync.""" 9 | 10 | path = Path(__file__).resolve().parents[1] / "pyproject.toml" 11 | pyproject = toml.loads(open(str(path)).read()) 12 | pyproject_version = pyproject["tool"]["poetry"]["version"] 13 | 14 | package_init_version = __version__ 15 | 16 | assert package_init_version == pyproject_version 17 | -------------------------------------------------------------------------------- /pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Type of changes 2 | 3 | - [ ] 🐛 Bug fix 4 | - [ ] 🎁 New feature 5 | - [ ] 📄 Documentation / docstrings 6 | - [ ] 🧪 Tests 7 | - [ ] Other 8 | 9 | ## Checklist 10 | 11 | - [ ] 💻 I've run the latest [black](https://github.com/psf/black) with default args on new code. 12 | - [ ] 🧪 I've added tests for new code. 13 | - [ ] ✔️ I ran pytest with the `--codeblocks` flag to ensure that my changes are compatible with the codeblocks 14 | found in the documentation. 15 | - [ ] 🕵️ I accept that @avi-perl may be pedantic _(just a little)_ in the code review. 16 | 17 | ## Description 18 | 19 | Please describe your changes here. If this fixes a bug, please link to the issue, if possible. 20 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: actions/setup-python@v2 12 | with: 13 | python-version: 3.x 14 | - run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV 15 | - run: pip install mkdocs-material 16 | - run: pip install mdx-include 17 | - run: pip install mkdocstrings[python] 18 | - run: | 19 | python -m pip install --upgrade pip 20 | pip install flake8 pytest 21 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 22 | - run: mkdocs gh-deploy --force -------------------------------------------------------------------------------- /docs/css/style.css: -------------------------------------------------------------------------------- 1 | /* Mark external links as such (also in nav) */ 2 | a.external:hover::after, a.md-nav__link[href^="https:"]:hover::after { 3 | /* https://primer.style/octicons/link-external-16 */ 4 | background-image: url('data:image/svg+xml,'); 5 | height: 0.8em; 6 | width: 0.8em; 7 | margin-left: 0.2em; 8 | content: ' '; 9 | display: inline-block; 10 | } 11 | 12 | /* More space at the bottom of the page */ 13 | .md-main__inner { 14 | margin-bottom: 1.5rem; 15 | } -------------------------------------------------------------------------------- /.github/workflows/codecov.yml: -------------------------------------------------------------------------------- 1 | name: Codecov 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | jobs: 8 | run: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest, windows-latest] 13 | env: 14 | OS: ${{ matrix.os }} 15 | PYTHON: '3.9' 16 | steps: 17 | - uses: actions/checkout@master 18 | - name: Setup Python 19 | uses: actions/setup-python@master 20 | with: 21 | python-version: 3.9 22 | - name: Generate coverage report 23 | run: | 24 | pip install pytest 25 | pip install pytest-cov 26 | pip install poetry 27 | poetry install 28 | poetry run pytest --cov=./ --cov-report=xml --codeblocks 29 | - name: Upload coverage to Codecov 30 | uses: codecov/codecov-action@v2 31 | with: 32 | flags: unittests 33 | verbose: true -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Avrohom Perl 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /hebrew/numerical_conversion/mappings.py: -------------------------------------------------------------------------------- 1 | _STANDARD_HEBREW_LETTERS = [ 2 | "א", 3 | "ב", 4 | "ג", 5 | "ד", 6 | "ה", 7 | "ו", 8 | "ז", 9 | "ח", 10 | "ט", 11 | "י", 12 | "כ", 13 | "ל", 14 | "מ", 15 | "נ", 16 | "ס", 17 | "ע", 18 | "פ", 19 | "צ", 20 | "ק", 21 | "ר", 22 | "ש", 23 | "ת", 24 | ] 25 | "All the Hebrew letters that are used to represent numbers. Does not include final letters." 26 | 27 | _STANDARD_HEBREW_LETTERS_VALUES = [ 28 | 1, 29 | 2, 30 | 3, 31 | 4, 32 | 5, 33 | 6, 34 | 7, 35 | 8, 36 | 9, 37 | 10, 38 | 20, 39 | 30, 40 | 40, 41 | 50, 42 | 60, 43 | 70, 44 | 80, 45 | 90, 46 | 100, 47 | 200, 48 | 300, 49 | 400, 50 | ] 51 | "Values of the standard Hebrew letters, in order." 52 | 53 | STANDARD_HEBREW_LETTERS_VALUES_REVERSED = _STANDARD_HEBREW_LETTERS_VALUES[::-1] 54 | "Values of the standard Hebrew letters, in reverse order." 55 | 56 | "Dictionary mapping standard Hebrew letters to their values." 57 | HEBREW_LETTER_TO_VALUE_MAPPINGS = dict( 58 | zip(_STANDARD_HEBREW_LETTERS_VALUES, _STANDARD_HEBREW_LETTERS) 59 | ) 60 | "Dictionary mapping standard Hebrew letters to their values." 61 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Hebrew Documentation 2 | site_description: A python package with methods to handle the complexities of Hebrew text, calculate Gematria, and more. 3 | site_url: https://hebrew.aviperl.me/ 4 | repo_name: avi-perl/Hebrew 5 | repo_url: https://github.com/avi-perl/Hebrew 6 | 7 | theme: 8 | name: material 9 | palette: 10 | - scheme: default 11 | toggle: 12 | icon: material/toggle-switch-off-outline 13 | name: Switch to dark mode 14 | - scheme: slate 15 | toggle: 16 | icon: material/toggle-switch 17 | name: Switch to light mode 18 | 19 | plugins: 20 | - search 21 | - mkdocstrings: 22 | handlers: 23 | python: 24 | paths: hebrew/ 25 | options: 26 | docstring_style: sphinx 27 | docstring_section_style: list 28 | group_by_category: true 29 | show_source: true 30 | filters: 31 | - "!^_" 32 | 33 | extra_css: 34 | - css/style.css 35 | - css/material.css 36 | - css/mkdocstrings.css 37 | 38 | markdown_extensions: 39 | - mdx_include 40 | - toc: 41 | permalink: "ל" # Heh 42 | 43 | 44 | extra: 45 | social: 46 | - icon: fontawesome/brands/twitter 47 | link: https://twitter.com/__aviperl__ 48 | - icon: fontawesome/brands/github 49 | link: https://github.com/avi-perl 50 | - icon: fontawesome/brands/linkedin 51 | link: https://www.linkedin.com/in/avrohomperl/ -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "hebrew" 3 | version = "0.8.1" 4 | description = "A python package with methods to handle the complexities of Hebrew text, calculate Gematria, and more." 5 | authors = ["Avi Perl "] 6 | license = "MIT" 7 | readme = "README.md" 8 | repository = "https://github.com/avi-perl/hebrew" 9 | documentation = "https://hebrew.aviperl.me/" 10 | keywords = ["hebrew", "gematria", "grapheme", "ivrit", "yiddish", "taamim", "ta'amim", "kabbalah"] 11 | classifiers = [ 12 | "Development Status :: 4 - Beta", 13 | "Intended Audience :: Developers", 14 | "Operating System :: Microsoft :: Windows", 15 | "Operating System :: MacOS", 16 | "Operating System :: POSIX :: Linux", 17 | "Programming Language :: Python :: 3.8", 18 | "Programming Language :: Python :: 3.9", 19 | "Programming Language :: Python :: 3.10", 20 | "Programming Language :: Python :: 3.11", 21 | "Programming Language :: Python :: 3.12", 22 | "Typing :: Typed", 23 | ] 24 | 25 | [tool.poetry.dependencies] 26 | python = "^3.8.0" 27 | grapheme = "^0.6.0" 28 | 29 | [tool.poetry.dev-dependencies] 30 | pytest = "^8.3.2" 31 | black = "^24.4.2" 32 | coverage = "^7.6.0" 33 | pytest-cov = "^5.0.0" 34 | toml = "^0.10.2" 35 | mkdocs-material = "^9.5.30" 36 | mdx-include = "^1.4.2" 37 | mkdocstrings = {extras = ["python"], version = "^0.25.2"} 38 | pytest-codeblocks = "^0.17.0" 39 | 40 | [build-system] 41 | requires = ["poetry-core>=1.0.0"] 42 | build-backend = "poetry.core.masonry.api" 43 | -------------------------------------------------------------------------------- /hebrew/numerical_conversion/substitute.py: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import Callable 3 | 4 | 5 | def yud_hey_to_tes_vav(value: str) -> str: 6 | """Used to substitute 'יה' for 'טו' in a string""" 7 | return re.sub(r"יה$", "טו", value) 8 | 9 | 10 | def yud_vav_to_tes_zayen(value: str) -> str: 11 | """Used to substitute 'יו' for 'טז' in a string""" 12 | return re.sub(r"יו$", "טז", value) 13 | 14 | 15 | def _get_word_substitution_func(bad: str, good: str) -> Callable[[str], str]: 16 | def word_substitution_func(value: str) -> str: 17 | """Substitute the first word for the second word""" 18 | return re.sub(bad, good, value) 19 | 20 | return word_substitution_func 21 | 22 | 23 | POLITE_WORD_MAP = { 24 | r"רע$": "ער", 25 | r"רעב$": "ערב", 26 | r"^רעה$": "ערה", 27 | r"רצח$": "רחצ", 28 | r"^שד$": "דש", 29 | r"שמד$": "שדמ", 30 | } 31 | 'Map of "impolite" words, and their polite equivalents.' 32 | 33 | _BASIC_FUNCTIONS = (yud_hey_to_tes_vav, yud_vav_to_tes_zayen) 34 | 35 | 36 | class Substitutions: 37 | """ 38 | Constants containing sets of functions for use in substitution_functions. 39 | """ 40 | 41 | DEFAULT = _BASIC_FUNCTIONS 42 | "The default set of substitutions; 'טו' and 'טז'" 43 | 44 | ALL = ( 45 | tuple(_get_word_substitution_func(w[0], w[1]) for w in POLITE_WORD_MAP.items()) 46 | + _BASIC_FUNCTIONS 47 | ) 48 | 49 | "All available substitution functions. See `POLITE_WORD_MAP` and `DEFAULT`; 'טו' and 'טז'" 50 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `Hebrew` 2 | 3 | This project welcomes contributions in the form of Pull Requests. 4 | For clear bug-fixes / typos etc. just submit a PR. 5 | For new features or if there is any doubt in how to fix a bug, you might want 6 | to open an issue prior to starting work. 7 | 8 | ## Development Environment 9 | 10 | Hebrew uses [poetry](https://python-poetry.org/docs/) for packaging and 11 | dependency management. To start developing with Hebrew, install Poetry 12 | using the [recommended method](https://python-poetry.org/docs/#installation) or run: 13 | 14 | ```bash 15 | pip install poetry 16 | ``` 17 | 18 | Once Poetry is installed, install the dependencies with the following command: 19 | 20 | ```bash 21 | poetry install --with=dev 22 | ``` 23 | 24 | ### Tests 25 | 26 | Run tests with the following command: 27 | 28 | ```bash 29 | poetry run pytest --codeblocks 30 | ``` 31 | 32 | _The `--codeblocks` flag runs tests on the python code blocks found in markdown files and is critical to testing!_ 33 | 34 | New code should ideally have tests and not break existing tests. 35 | 36 | If you are not familiar with writing tests but still want to contribute to this package, 37 | please feel free to submit your pull request, and I will work on tests. 🙂 38 | 39 | ### Type Checking 40 | 41 | Please add type annotations for all new code. 42 | 43 | ### Code Formatting 44 | 45 | This repo uses [`black`](https://github.com/psf/black) for code formatting. 46 | I recommend setting up black in your editor to format on save. 47 | 48 | To run black from the command line: 49 | 50 | ```bash 51 | black 52 | ``` -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Test 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: ["3.12", "3.11", "3.10", 3.9, 3.8] 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Set up Python ${{ matrix.python-version }} 21 | uses: actions/setup-python@v2 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install flake8 pytest pytest-codeblocks 28 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 29 | - name: Set PYTHONPATH 30 | run: | 31 | echo "PYTHONPATH=$PWD" >> $GITHUB_ENV 32 | - name: Lint with flake8 33 | run: | 34 | # stop the build if there are Python syntax errors or undefined names 35 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 36 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 37 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 38 | - name: Test with pytest 39 | run: | 40 | pytest --codeblocks 41 | - name: Build docs 42 | run: | 43 | pip install mkdocs-material 44 | pip install mdx-include 45 | pip install mkdocstrings[python] 46 | mkdocs build -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ master ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ master ] 20 | schedule: 21 | - cron: '45 16 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ 139 | 140 | #PyCharm 141 | .idea -------------------------------------------------------------------------------- /hebrew/numerical_conversion/convert.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Callable, Tuple 2 | 3 | from hebrew.numerical_conversion.substitute import Substitutions 4 | from hebrew.numerical_conversion.mappings import ( 5 | HEBREW_LETTER_TO_VALUE_MAPPINGS, 6 | STANDARD_HEBREW_LETTERS_VALUES_REVERSED, 7 | ) 8 | 9 | 10 | def number_to_hebrew_string( 11 | number: int, 12 | punctuate: bool = True, 13 | geresh: bool = True, 14 | substitution_functions: Optional[ 15 | Tuple[Callable[[str], str], ...] 16 | ] = Substitutions.DEFAULT, 17 | ) -> str: 18 | """ 19 | Convert a number into its Hebrew letter form. 20 | 21 | :param number: The number to convert to Hebrew letters. Must be greater than 0. 22 | :param punctuate: Whether to add punctuation in the appropriate places. 23 | :param geresh: If punctuate is true, whether to use the unicode geresh or an apostrophe. 24 | :param substitution_functions: A tuple of functions that replaces some hebrew values in the result with an 25 | appropriate equivalent. By default, "יה" and "יו" are replaced with "טו" and "טז" respectively. To replace all 26 | values such as שמד ,רע, and others, use `Substitutions.ALL`. 27 | :return: 28 | """ 29 | # Handle 0 30 | if number < 1: 31 | raise ValueError("Number must be greater than 0") 32 | 33 | reversed_result = "" 34 | 35 | # Prepare the numbers 36 | ones_value = _ones_column_value(number) 37 | if ones_value > 0: 38 | reversed_result += HEBREW_LETTER_TO_VALUE_MAPPINGS[ones_value] 39 | tens_value = _tens_column_value(number) 40 | if tens_value > 0: 41 | reversed_result += HEBREW_LETTER_TO_VALUE_MAPPINGS[tens_value] 42 | hundreds_value = _hundreds_and_above_column_value(number) 43 | if hundreds_value > 0: 44 | reversed_result += _hundreds_to_letters(hundreds_value) 45 | 46 | # Reverse the string 47 | result = reversed_result[::-1] 48 | 49 | # Substitute flags 50 | if substitution_functions: 51 | for func in substitution_functions: 52 | result = func(result) 53 | 54 | # Add Punctuation 55 | if punctuate: 56 | if len(result) > 1: 57 | punctuation = "״" if geresh else '"' 58 | result = result[:-1] + punctuation + result[-1] 59 | else: 60 | punctuation = "׳" if geresh else "'" 61 | result += punctuation 62 | 63 | return result 64 | 65 | 66 | def _ones_column_value(number: int): 67 | """ 68 | Return the value of the ones column of a number. 69 | """ 70 | return number % 10 71 | 72 | 73 | def _tens_column_value(number: int): 74 | """ 75 | Return the value of the tens column of a number. 76 | """ 77 | if number < 10: 78 | return 0 79 | return ((number % 100) // 10) * 10 80 | 81 | 82 | def _hundreds_and_above_column_value(number: int): 83 | """ 84 | Returns the value of all columns of a number above the ten's column. 85 | """ 86 | return (number // 100) * 100 87 | 88 | 89 | def _hundreds_to_letters(number: int) -> str: 90 | """ 91 | Given a single digit number over 0 and a power of ten, return the Hebrew letters that represent that number. 92 | 93 | :param number: The digit to convert to Hebrew letters. 94 | :return: The Hebrew letters that represent the number. 95 | """ 96 | 97 | # Check if the number maps directly to a letter 98 | if number in HEBREW_LETTER_TO_VALUE_MAPPINGS: 99 | return HEBREW_LETTER_TO_VALUE_MAPPINGS[number] 100 | else: 101 | # Get the largest letter and value that is less or equal to the number 102 | max_letter_value = next( 103 | i for i in STANDARD_HEBREW_LETTERS_VALUES_REVERSED if i <= number 104 | ) 105 | max_letter = HEBREW_LETTER_TO_VALUE_MAPPINGS[max_letter_value] 106 | 107 | # Calculate the number of times the letter goes into the number 108 | letter_count, remainder = divmod(number, max_letter_value) 109 | 110 | # If the remainder is 0, we can just return the letter times the letter count 111 | if remainder == 0: 112 | return max_letter * letter_count 113 | else: 114 | # Otherwise we need to further break down the remainder 115 | remainder_letters = _hundreds_to_letters(remainder) 116 | return remainder_letters + max_letter * letter_count 117 | -------------------------------------------------------------------------------- /tests/test_grapheme_string.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Hashable 2 | 3 | import pytest 4 | 5 | from hebrew import GraphemeString 6 | 7 | 8 | @pytest.fixture 9 | def hebrew_grapheme_string(): 10 | return GraphemeString( 11 | "וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֙הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם" 12 | ) 13 | 14 | 15 | @pytest.fixture 16 | def hebrew_no_nikkud(): 17 | return "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 18 | 19 | 20 | def test_graphemes(hebrew_grapheme_string): 21 | graphemes = hebrew_grapheme_string.graphemes 22 | assert hasattr(graphemes, "__iter__") 23 | assert list(hebrew_grapheme_string.graphemes) == [ 24 | "וְ", 25 | "הָ", 26 | "אָ֗", 27 | "רֶ", 28 | "ץ", 29 | " ", 30 | "הָ", 31 | "יְ", 32 | "תָ֥", 33 | "ה", 34 | " ", 35 | "תֹ֙", 36 | "ה", 37 | "וּ֙", 38 | " ", 39 | "וָ", 40 | "בֹ֔", 41 | "ה", 42 | "וּ", 43 | " ", 44 | "וְ", 45 | "חֹ֖", 46 | "שֶׁ", 47 | "ךְ", 48 | " ", 49 | "עַ", 50 | "ל", 51 | "־", 52 | "פְּ", 53 | "נֵ֣", 54 | "י", 55 | " ", 56 | "תְ", 57 | "ה֑", 58 | "וֹ", 59 | "ם", 60 | " ", 61 | "וְ", 62 | "ר֣", 63 | "וּ", 64 | "חַ", 65 | " ", 66 | "אֱ", 67 | "לֹ", 68 | "הִ֔", 69 | "י", 70 | "ם", 71 | " ", 72 | "מְ", 73 | "רַ", 74 | "חֶ֖", 75 | "פֶ", 76 | "ת", 77 | " ", 78 | "עַ", 79 | "ל", 80 | "־", 81 | "פְּ", 82 | "נֵ֥", 83 | "י", 84 | " ", 85 | "הַ", 86 | "מָּֽ", 87 | "יִ", 88 | "ם", 89 | ] 90 | 91 | 92 | def test_length(hebrew_grapheme_string, hebrew_no_nikkud): 93 | assert hebrew_grapheme_string.length == len(hebrew_no_nikkud) 94 | 95 | 96 | def test_get_length(hebrew_grapheme_string): 97 | assert hebrew_grapheme_string.get_length(5) == 5 98 | 99 | 100 | def test_grapheme_lengths(hebrew_grapheme_string): 101 | graphemes_length = hebrew_grapheme_string.grapheme_lengths 102 | assert hasattr(graphemes_length, "__iter__") 103 | assert list(graphemes_length) == [ 104 | 2, 105 | 2, 106 | 3, 107 | 2, 108 | 1, 109 | 1, 110 | 2, 111 | 2, 112 | 3, 113 | 1, 114 | 1, 115 | 3, 116 | 1, 117 | 3, 118 | 1, 119 | 2, 120 | 3, 121 | 1, 122 | 2, 123 | 1, 124 | 2, 125 | 3, 126 | 3, 127 | 2, 128 | 1, 129 | 2, 130 | 1, 131 | 1, 132 | 3, 133 | 3, 134 | 1, 135 | 1, 136 | 2, 137 | 2, 138 | 2, 139 | 1, 140 | 1, 141 | 2, 142 | 2, 143 | 2, 144 | 2, 145 | 1, 146 | 2, 147 | 2, 148 | 3, 149 | 1, 150 | 1, 151 | 1, 152 | 2, 153 | 2, 154 | 3, 155 | 2, 156 | 1, 157 | 1, 158 | 2, 159 | 1, 160 | 1, 161 | 3, 162 | 3, 163 | 1, 164 | 1, 165 | 2, 166 | 4, 167 | 2, 168 | 1, 169 | ] 170 | 171 | 172 | def test_slice(hebrew_grapheme_string): 173 | assert hebrew_grapheme_string.slice(start=0, end=5) == "וְהָאָ֗רֶץ" 174 | assert hebrew_grapheme_string.slice(start=6, end=10) == "הָיְתָ֥ה" 175 | 176 | 177 | def test_contains(hebrew_grapheme_string): 178 | assert "ו" in str(hebrew_grapheme_string) # Assert that test case is valid 179 | assert not hebrew_grapheme_string.contains("ו") 180 | 181 | 182 | def test_safe_split_index(hebrew_grapheme_string): 183 | assert hebrew_grapheme_string.safe_split_index(12) == 11 184 | 185 | 186 | def test_startswith(hebrew_grapheme_string): 187 | assert hebrew_grapheme_string.string.startswith( 188 | "ו" 189 | ) # Assert that test case is valid 190 | assert not hebrew_grapheme_string.startswith("ו") 191 | 192 | 193 | def test_endswith(): 194 | assert GraphemeString("וְ").string.endswith("ְ") # Assert that test case is valid 195 | assert not GraphemeString("וְ").endswith("ְ") 196 | 197 | 198 | def test_string_repr(hebrew_grapheme_string): 199 | assert isinstance(hebrew_grapheme_string.string, str) 200 | assert hebrew_grapheme_string.__str__() == hebrew_grapheme_string.string 201 | assert hebrew_grapheme_string.__repr__() == hebrew_grapheme_string.string 202 | 203 | 204 | def test_add(): 205 | full = GraphemeString( 206 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 207 | ) 208 | start = GraphemeString("והארץ היתה תהו ובהו") 209 | end = GraphemeString("וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים") 210 | new = start + " " + end 211 | assert new.string == full.string 212 | 213 | 214 | def test_equality(): 215 | one = GraphemeString( 216 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 217 | ) 218 | two = GraphemeString( 219 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 220 | ) 221 | assert one == two 222 | 223 | 224 | def test_equality_unequal_type(): 225 | one = GraphemeString( 226 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 227 | ) 228 | two = GraphemeString( 229 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 230 | ) 231 | assert one != str(two) 232 | 233 | 234 | def test_not_equality(): 235 | one = GraphemeString( 236 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 237 | ) 238 | two = GraphemeString("והארץ") 239 | assert one != two 240 | 241 | 242 | def test_hashable(): 243 | one = GraphemeString( 244 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 245 | ) 246 | two = GraphemeString( 247 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים" 248 | ) 249 | assert isinstance(one, Hashable) 250 | assert one.__hash__() == two.__hash__() 251 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres 6 | to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [0.8.1] - 2023-12-11 9 | 10 | ### Fixed 11 | 12 | - Corrected an issue with subclasses of `BaseHebrewChar` where use of `__eq__` would break when the type for the 13 | comparison was not the same as itself. 14 | 15 | ## [0.8.0] - 2023-12-10 16 | 17 | ### Added 18 | 19 | - Added `Hebrew.normalize`, a function for normalizing the hebrew characters in a string. This is typically needed with 20 | text includes special hebrew characters. 21 | 22 | Hidden among hebrew text can be special characters that are visually identical humans, but are made up of different 23 | unicode characters. However, this can cause issues with presentation when there is no support for these characters. 24 | 25 | ![bad_character_display.png](docs/img/bad_character_display.png) 26 | 27 | In this case, the first letter is made up of 2 unicode characters, [sin with a dot](https://en.wiktionary.org/wiki/%D7%A9%D7%82) 28 | and [qamatz](https://en.wiktionary.org/wiki/%D6%B8). The issue here is the sin. By normalizing the sin with a dot to 2 unicode 29 | characters, [ש](https://en.wiktionary.org/wiki/%D7%A9) and the [dot](https://en.wiktionary.org/wiki/%D7%82), the display 30 | will look right! 31 | 32 | ![good_character_display.png](docs/img/good_character_display.png) 33 | 34 | To normalize content, use the `Hebrew.normalize` function: 35 | ```python 36 | from hebrew import Hebrew 37 | 38 | hs = Hebrew('שָׂחַקְתִּי כְּמוֹ') 39 | 40 | assert len(hs.string) == 14 41 | assert len(hs.normalize().string) == 18 42 | ``` 43 | 44 | ### Normalizing Yiddish 45 | 46 | By default, special yiddish characters such as [ײ](https://en.wiktionary.org/wiki/%D7%B2) (double Yod) are _not_ normalized. 47 | However, [ײַ](https://en.wiktionary.org/wiki/%EF%AC%9F) (double Yod with a Patah) will be converted to [ײַ](https://en.wiktionary.org/wiki/%D7%B2%D6%B7). 48 | 49 | To fully "normalize" yiddish characters, pass `True` to `normalize`. 50 | 51 | 52 | ## [0.7.0] - 2023-12-10 53 | 54 | ### Added 55 | 56 | - New function `Hebrew.from_number` converts an int into its hebrew form 57 | 58 | ### Example: 59 | 60 | ``` python 61 | from hebrew import Hebrew 62 | 63 | hs1 = Hebrew.from_number(2) 64 | print(hs1) # ב׳ 65 | 66 | # Do not add punctuation 67 | hs2 = Hebrew.from_number(2, geresh=False) 68 | print(hs2) # ב 69 | ``` 70 | 71 | ## [0.6.2] - 2023-12-08 72 | 73 | ### Changed 74 | 75 | - Added 3.12 as a supported version 76 | - Updated project dependencies. 77 | 78 | ### Removed 79 | - Removed 3.11 as a supported version 80 | 81 | ## [0.6.1] - 2022-10-28 82 | 83 | ### Changed 84 | 85 | - Added 3.11 as a supported version 86 | 87 | ## [0.6.0] - 2022-04-19 88 | 89 | ### Added 90 | 91 | - Added the remaining missing Gematria methods. The complete list of supported methods is: 92 | - `ACHAS_BETA` 93 | - `ALBAM` 94 | - `ATBASH` 95 | - `AVGAD` 96 | - `AYAK_BACHAR` 97 | - `MISPAR_BONEEH` 98 | - `MISPAR_GADOL` 99 | - `MISPAR_HAACHOR` 100 | - `MISPAR_HAMERUBAH_HAKLALI` 101 | - `MISPAR_HECHRACHI` 102 | - `MISPAR_KATAN` 103 | - `MISPAR_KATAN_MISPARI` 104 | - `MISPAR_KIDMI` 105 | - `MISPAR_KOLEL` 106 | - `MISPAR_MESHULASH` 107 | - `MISPAR_MISPARI` 108 | - `MISPAR_MUSAFI` 109 | - `MISPAR_NEELAM` 110 | - `MISPAR_PERATI` 111 | - `MISPAR_SHEMI_MILUI` 112 | - `MISPAR_SIDURI` 113 | - `OFANIM` 114 | - `REVERSE_AVGAD` 115 | 116 | ### Example: 117 | ```python 118 | from hebrew import Hebrew 119 | from hebrew import GematriaTypes 120 | 121 | hs = Hebrew('בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃') 122 | 123 | print(hs.gematria()) # 2701 124 | print(hs.gematria(GematriaTypes.MISPAR_GADOL)) # 4631 125 | ``` 126 | 127 | ## [0.5.8] - 2022-04-18 128 | 129 | ### Added 130 | 131 | - Added Gematria methods `MISPAR_MUSAFI`. This is the first of the complex Gematria types that goes deeper than just 132 | adding up values assigned to each letter, necessitating internal changes to the `Hebrew` class. 133 | 134 | ## [0.5.7] - 2022-04-18 135 | 136 | ### Added 137 | 138 | - Added Gematria methods `MISPAR_KATAN`, `MISPAR_PERATI`, `ATBASH`, `ALBAM`, `MISPAR_MESHULASH`. 139 | 140 | ## [0.5.6] - 2022-04-18 141 | 142 | ### Added 143 | 144 | - Added a new gematria method, `MISPAR_SIDURI`. 145 | 146 | ## [0.5.5] - 2021-11-22 147 | 148 | ### Added 149 | 150 | - Added a new gematria method, `MISPAR_GADOL`. A contribution by [Taber Andrew Bain](https://github.com/taber) 151 | 152 | ## [0.5.4] - 2021-11-21 153 | 154 | ### Fixed 155 | 156 | - Fixed an issue where `Hebrew.gematria` would through an error if the input string had no hebrew characters. 157 | In this case, we now return a value of 0. 158 | 159 | ## [0.5.3] - 2021-11-15 160 | 161 | ### Changed 162 | 163 | - Split the `PunctuationChar` type chars into `TaamimChar` and `OtherChar` types in `hebrew.char`. 164 | - Renamed the `no_punctuation` method of `Hebrew` to `no_taamim`. 165 | 166 | ## [0.5.0] - 2021-11-14 167 | 168 | ### Added 169 | 170 | - Added the method `Hebrew.gematria` method for calculating the gematria of a string. 171 | - Added `mispar_hechrachi` as a supported gematria type. 172 | 173 | ``` python 174 | >>> from hebrew import Hebrew 175 | >>> from hebrew.gematria import GematriaTypes 176 | 177 | >>> Hebrew("בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָרֶץ׃").gematria(GematriaTypes.MISPAR_HECHRACHI) 178 | 2701 179 | ``` 180 | 181 | ## [0.4.0] - 2021-11-14 182 | 183 | ### Added 184 | 185 | - Added `hebrew.chars` with constants for Hebrew characters and classes to represent each letter. 186 | - Moved constants out of `Hebrew` and into `hebrew.chars`. 187 | - Constant values, previously strings, are now instances of a class with metadata for each letter. 188 | 189 | ### Removed 190 | 191 | - Support for Python 3.6 was removed because we are now using `@dataclasse`. It is possible to make this work with 192 | 3.6 but I am choosing not to at this time. If this is a problem for you, feel free to open an issue. 193 | 194 | ## [0.3.0] - 2021-11-08 195 | 196 | ### Changed 197 | 198 | - Renamed the python package from `hebrewstring` to `hebrew`. 199 | 200 | ## [0.2.0] - 2021-11-07 201 | 202 | ### Added 203 | 204 | - Added the `__eq__` method to the `GraphemeString` object. 205 | 206 | This is to support the `==` operator when comparing two `GraphemeString` objects. 207 | 208 | - Added the `__add__` method to the `GraphemeString` object. 209 | 210 | This is to support the `+` operator when adding two `GraphemeString` objects together. 211 | 212 | - Added the `__hash__` method to the `GraphemeString` object. 213 | 214 | This is to support the `hash()` function for a `GraphemeString` instance and allows it (as an example) to be used as 215 | a `dict` key. 216 | 217 | ## [0.1.2] - 2021-11-07 218 | 219 | ### Added 220 | 221 | - Added base code, tests, and examples for the first release. -------------------------------------------------------------------------------- /tests/test_gematria.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from hebrew import Hebrew 4 | from hebrew.gematria import GematriaTypes 5 | 6 | # Test inputs and their expected values for each method type. 7 | # Add new test cases here! 8 | test_values = { 9 | "אבגדהוזחטיכךלמםנןסעפףצץקרשת": { 10 | GematriaTypes.ALBAM: 1913, 11 | GematriaTypes.ATBASH: 1555, 12 | GematriaTypes.MISPAR_GADOL: 4995, 13 | GematriaTypes.MISPAR_HECHRACHI: 1775, 14 | GematriaTypes.MISPAR_KATAN: 128, 15 | GematriaTypes.MISPAR_MESHULASH: 103_465_025, 16 | GematriaTypes.MISPAR_MUSAFI: 1802, 17 | GematriaTypes.MISPAR_PERATI: 347_785, 18 | GematriaTypes.MISPAR_SIDURI: 378, 19 | GematriaTypes.MISPAR_BONEEH: 9915, 20 | GematriaTypes.MISPAR_HAMERUBAH_HAKLALI: 3_150_625, 21 | GematriaTypes.MISPAR_HAACHOR: 39_785, 22 | GematriaTypes.MISPAR_KATAN_MISPARI: 2, 23 | GematriaTypes.MISPAR_KOLEL: 1776, 24 | GematriaTypes.MISPAR_KIDMI: 7515, 25 | GematriaTypes.MISPAR_NEELAM: 2925, 26 | GematriaTypes.MISPAR_MISPARI: 14_095, 27 | GematriaTypes.AYAK_BACHAR: 4995, 28 | GematriaTypes.AYAK_BAKAR: 4995, 29 | GematriaTypes.OFANIM: 2643, 30 | GematriaTypes.ACHAS_BETA: 2092, 31 | GematriaTypes.AVGAD: 1825, 32 | GematriaTypes.REVERSE_AVGAD: 1725, 33 | GematriaTypes.MISPAR_SHEMI_MILUI: 4700, 34 | }, 35 | "בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃": { 36 | GematriaTypes.ALBAM: 1571, 37 | GematriaTypes.ATBASH: 3541, 38 | GematriaTypes.MISPAR_GADOL: 4631, 39 | GematriaTypes.MISPAR_HECHRACHI: 2701, 40 | GematriaTypes.MISPAR_KATAN: 82, 41 | GematriaTypes.MISPAR_MESHULASH: 270_951_613, 42 | GematriaTypes.MISPAR_MUSAFI: 2729, 43 | GematriaTypes.MISPAR_PERATI: 794_225, 44 | GematriaTypes.MISPAR_SIDURI: 329, 45 | GematriaTypes.MISPAR_BONEEH: 40_035, 46 | GematriaTypes.MISPAR_HAMERUBAH_HAKLALI: 7_295_401, 47 | GematriaTypes.MISPAR_HAACHOR: 38_294, 48 | GematriaTypes.MISPAR_KATAN_MISPARI: 1, 49 | GematriaTypes.MISPAR_KOLEL: 2708, 50 | GematriaTypes.MISPAR_KIDMI: 10_338, 51 | GematriaTypes.MISPAR_NEELAM: 2745, 52 | GematriaTypes.MISPAR_MISPARI: 13_256, 53 | GematriaTypes.AYAK_BACHAR: 1355, 54 | GematriaTypes.AYAK_BAKAR: 1355, 55 | GematriaTypes.OFANIM: 2453, 56 | GematriaTypes.ACHAS_BETA: 2372, 57 | GematriaTypes.AVGAD: 2096, 58 | GematriaTypes.REVERSE_AVGAD: 4236, 59 | GematriaTypes.MISPAR_SHEMI_MILUI: 5446, 60 | }, 61 | } 62 | 63 | # Prepare the test inputs for the pytest parametrize function 64 | params = ["hebrew_text,gematria_method,expected_val", []] 65 | for text, tests in test_values.items(): 66 | for method, val in tests.items(): 67 | params[1].append((text, method, val)) 68 | 69 | 70 | @pytest.mark.parametrize(*params) 71 | def test_gematria_values( 72 | hebrew_text: str, gematria_method: GematriaTypes, expected_val: str 73 | ): 74 | assert Hebrew(hebrew_text).gematria(gematria_method) == expected_val 75 | assert Hebrew(hebrew_text).text_only().gematria(gematria_method) == expected_val 76 | assert ( 77 | Hebrew(hebrew_text + " Add english letters").gematria(gematria_method) 78 | == expected_val 79 | ) 80 | 81 | 82 | def test_mispar_shemi_milui_change_spelling(): 83 | hebrew_text = "בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃" 84 | spellings = { 85 | "ב": "בת", 86 | "ג": "גמל", 87 | "ד": "דלית", 88 | "ה": "הי", 89 | "ו": "ויו", 90 | "ח": "חת", 91 | "ט": "טת", 92 | "פ": "פי", 93 | "צ": "צדיק", 94 | "ר": "רש", 95 | "ש": "שין", 96 | "ת": "תיו", 97 | } 98 | assert ( 99 | Hebrew(hebrew_text).gematria( 100 | GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings 101 | ) 102 | == 5583 103 | ) 104 | assert ( 105 | Hebrew(hebrew_text) 106 | .text_only() 107 | .gematria(GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings) 108 | == 5583 109 | ) 110 | assert ( 111 | Hebrew(hebrew_text + " Add english letters").gematria( 112 | GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings 113 | ) 114 | == 5583 115 | ) 116 | hebrew_text = "אבגדהוזחטיכךלמםנןסעפףצץקרשת" 117 | spellings = { 118 | "ה": "הה", 119 | "ו": "ואו", 120 | "פ": "פה", 121 | "ת": "תאו", 122 | } 123 | assert ( 124 | Hebrew(hebrew_text).gematria( 125 | GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings 126 | ) 127 | == 4714 128 | ) 129 | assert ( 130 | Hebrew(hebrew_text) 131 | .text_only() 132 | .gematria(GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings) 133 | == 4714 134 | ) 135 | assert ( 136 | Hebrew(hebrew_text + " Add english letters").gematria( 137 | GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings 138 | ) 139 | == 4714 140 | ) 141 | 142 | 143 | def test_mispar_shemi_milui_bad_spelling(): 144 | hebrew_text = "בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃" 145 | spellings = { 146 | "ב": "בתבתבתבת", # bad name that does not exist for this letter 147 | } 148 | with pytest.raises(ValueError): 149 | Hebrew(hebrew_text).gematria( 150 | GematriaTypes.MISPAR_SHEMI_MILUI, alt_letter_name_spelling=spellings 151 | ) 152 | 153 | 154 | def test_mispar_neelam_change_spelling(): 155 | hebrew_text = "בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ׃" 156 | spellings = { 157 | "ב": "בת", 158 | "ג": "גמל", 159 | "ד": "דלית", 160 | "ה": "הי", 161 | "ו": "ויו", 162 | "ח": "חת", 163 | "ט": "טת", 164 | "פ": "פי", 165 | "צ": "צדיק", 166 | "ר": "רש", 167 | "ש": "שין", 168 | "ת": "תיו", 169 | } 170 | assert ( 171 | Hebrew(hebrew_text).gematria( 172 | GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings 173 | ) 174 | == 2882 175 | ) 176 | assert ( 177 | Hebrew(hebrew_text) 178 | .text_only() 179 | .gematria(GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings) 180 | == 2882 181 | ) 182 | assert ( 183 | Hebrew(hebrew_text + " Add english letters").gematria( 184 | GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings 185 | ) 186 | == 2882 187 | ) 188 | hebrew_text = "אבגדהוזחטיכךלמםנןסעפףצץקרשת" 189 | spellings = { 190 | "ה": "הה", 191 | "ו": "ואו", 192 | "פ": "פה", 193 | "ת": "תאו", 194 | } 195 | assert ( 196 | Hebrew(hebrew_text).gematria( 197 | GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings 198 | ) 199 | == 2939 200 | ) 201 | assert ( 202 | Hebrew(hebrew_text) 203 | .text_only() 204 | .gematria(GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings) 205 | == 2939 206 | ) 207 | assert ( 208 | Hebrew(hebrew_text + " Add english letters").gematria( 209 | GematriaTypes.MISPAR_NEELAM, alt_letter_name_spelling=spellings 210 | ) 211 | == 2939 212 | ) 213 | 214 | 215 | def test_bad_input(): 216 | for t in GematriaTypes: 217 | assert ( 218 | Hebrew("Testing a string that contains no hebrew").gematria(t) == 0 219 | ), "gematria should return 0 when the input text is not hebrew" 220 | 221 | 222 | def test_mixed_input(): 223 | for t in GematriaTypes: 224 | assert ( 225 | Hebrew("Both hebrew: 'שָׁלוֹם' and English: 'Hello dev!'").gematria(t) > 0 226 | ), "gematria should always have a value > 0 when there is any hebrew text in a string" 227 | -------------------------------------------------------------------------------- /hebrew/grapheme_string.py: -------------------------------------------------------------------------------- 1 | from typing import Iterator, TypeVar 2 | 3 | import grapheme 4 | from grapheme.finder import GraphemeIterator 5 | 6 | GraphemeStringT = TypeVar("GraphemeStringT", bound="GraphemeString") 7 | 8 | 9 | class GraphemeString: 10 | """ 11 | An object that unifies the functions available from the grapheme library under an object. 12 | Functions all work as they do in the grapheme library, this is simply an interface. 13 | """ 14 | 15 | UNICODE_VERSION: str = grapheme.UNICODE_VERSION 16 | 17 | def __init__(self, string: str): 18 | self.string = string 19 | 20 | @property 21 | def graphemes(self) -> Iterator[GraphemeIterator]: 22 | """ 23 | Returns an iterator of all graphemes of given string. 24 | 25 | ``` python 26 | >>> rainbow_flag = "🏳️‍🌈" 27 | >>> [codepoint for codepoint in rainbow_flag] 28 | ['🏳', '️', '\u200d', '🌈'] 29 | >>> list(GraphemeString("multi codepoint grapheme: " + rainbow_flag).graphemes) 30 | ['m', 'u', 'l', 't', 'i', ' ', 'c', 'o', 'd', 'e', 'p', 'o', 'i', 'n', 't', ' ', 'g', 'r', 'a', 'p', 'h', 'e', 'm', 'e', ':', ' ', '🏳️‍🌈'] 31 | ``` 32 | """ 33 | return grapheme.graphemes(self.string) 34 | 35 | @property 36 | def length(self) -> int: 37 | """ 38 | Returns the number of graphemes in the string. 39 | 40 | Note that this functions needs to traverse the full string to calculate the length, 41 | unlike `len(string)` and it's time consumption is linear to the length of the string 42 | (up to the `until` value). 43 | 44 | Only counts up to the `until` argument, if given. This is useful when testing 45 | the length of a string against some limit and the excess length is not interesting. 46 | 47 | ``` python 48 | >>> rainbow_flag = "🏳️‍🌈" 49 | >>> len(rainbow_flag) 50 | 4 51 | >>> GraphemeString(rainbow_flag).length 52 | 1 53 | ``` 54 | """ 55 | return grapheme.length(self.string) 56 | 57 | def get_length(self, until: int) -> int: 58 | """ 59 | Returns the number of graphemes in the string. 60 | 61 | Note that this functions needs to traverse the full string to calculate the length, 62 | unlike `len(string)` and it's time consumption is linear to the length of the string 63 | (up to the `until` value). 64 | 65 | Only counts up to the `until` argument, if given. This is useful when testing 66 | the length of a string against some limit and the excess length is not interesting. 67 | 68 | ``` python 69 | >>> rainbow_flag = "🏳️‍🌈" 70 | >>> len(rainbow_flag) 71 | 4 72 | >>> GraphemeString(rainbow_flag).length 73 | 1 74 | >>> GraphemeString("".join(str(i) for i in range(100))).get_length(30) 75 | 30 76 | ``` 77 | """ 78 | return grapheme.length(self.string, until) 79 | 80 | @property 81 | def grapheme_lengths(self) -> Iterator[int]: 82 | """ 83 | Returns an iterator of number of code points in each grapheme of the string. 84 | """ 85 | return grapheme.grapheme_lengths(self.string) 86 | 87 | def slice(self, start: int = None, end: int = None) -> str: 88 | """ 89 | Returns a substring of the given string, counting graphemes instead of codepoints. 90 | 91 | Negative indices is currently not supported. 92 | 93 | ``` python 94 | >>> string = "tamil நி (ni)" 95 | 96 | >>> string[:7] 97 | 'tamil ந' 98 | >>> GraphemeString(string).slice(end=7) 99 | 'tamil நி' 100 | >>> string[7:] 101 | 'ி (ni)' 102 | >>> GraphemeString(string).slice(start=7) 103 | ' (ni)' 104 | ``` 105 | """ 106 | return grapheme.slice(self.string, start, end) 107 | 108 | def contains(self, substring: str) -> bool: 109 | """ 110 | Returns true if the sequence of graphemes in substring is also present in string. 111 | 112 | This differs from the normal python `in` operator, since the python operator will return 113 | true if the sequence of codepoints are withing the other string without considering 114 | grapheme boundaries. 115 | 116 | Performance notes: Very fast if `substring not in string`, since that also means that 117 | the same graphemes can not be in the two strings. Otherwise this function has linear time 118 | complexity in relation to the string length. It will traverse the sequence of graphemes until 119 | a match is found, so it will generally perform better for grapheme sequences that match early. 120 | 121 | ``` python 122 | >>> "🇸🇪" in "🇪🇸🇪🇪" 123 | True 124 | >>> GraphemeString("🇪🇸🇪🇪").contains("🇸🇪") 125 | False 126 | ``` 127 | """ 128 | return grapheme.contains(self.string, substring) 129 | 130 | def safe_split_index(self, max_length: int) -> int: 131 | """ 132 | Returns the highest index up to `max_len` at which the given string can be sliced, without breaking a grapheme. 133 | 134 | This is useful for when you want to split or take a substring from a string, and don't really care about 135 | the exact grapheme length, but don't want to risk breaking existing graphemes. 136 | 137 | This function does normally not traverse the full grapheme sequence up to the given length, so it can be used 138 | for arbitrarily long strings and high `max_len`s. However, some grapheme boundaries depend on the previous state, 139 | so the worst case performance is O(n). In practice, it's only very long non-broken sequences of country flags 140 | (represented as Regional Indicators) that will perform badly. 141 | 142 | The return value will always be between `0` and `len(string)`. 143 | 144 | ``` python 145 | >>> string = "tamil நி (ni)" 146 | >>> i = GraphemeString(string).safe_split_index(7) 147 | >>> i 148 | 6 149 | >>> string[:i] 150 | 'tamil ' 151 | >>> string[i:] 152 | 'நி (ni)' 153 | ``` 154 | """ 155 | return grapheme.safe_split_index(self.string, max_length) 156 | 157 | def startswith(self, prefix: str) -> bool: 158 | """ 159 | Like str.startswith, but also checks that the string starts with the given prefixes sequence of graphemes. 160 | 161 | str.startswith may return true for a prefix that is not visually represented as a prefix if a grapheme cluster 162 | is continued after the prefix ends. 163 | 164 | ``` python 165 | >>> GraphemeString("✊🏾").startswith("✊") 166 | False 167 | >>> "✊🏾".startswith("✊") 168 | True 169 | ``` 170 | """ 171 | return grapheme.startswith(self.string, prefix) 172 | 173 | def endswith(self, suffix: str) -> bool: 174 | """ 175 | Like str.endswith, but also checks that the string ends with the given prefixes sequence of graphemes. 176 | 177 | str.endswith may return true for a suffix that is not visually represented as a suffix if a grapheme cluster 178 | is initiated before the suffix starts. 179 | 180 | ``` python 181 | >>> GraphemeString("🏳️‍🌈").endswith("🌈") 182 | False 183 | >>> "🏳️‍🌈".endswith("🌈") 184 | True 185 | ``` 186 | """ 187 | return grapheme.endswith(self.string, suffix) 188 | 189 | def __str__(self) -> str: 190 | return self.string 191 | 192 | def __repr__(self) -> str: 193 | return self.__str__() 194 | 195 | def __add__(self, other) -> GraphemeStringT: 196 | return GraphemeString(self.string + str(other)) 197 | 198 | def __key(self) -> str: 199 | return self.string 200 | 201 | def __eq__(self, other) -> bool: 202 | if isinstance(other, GraphemeString): 203 | return self.__key() == other.__key() 204 | return False 205 | 206 | def __hash__(self): 207 | return hash(self.__key()) 208 | -------------------------------------------------------------------------------- /tests/test_chars.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | from hebrew.chars import * 4 | 5 | 6 | def test_all_hebrew_letters_represented(): 7 | all_unicode_chars_defined = [c.char for c in ALL_CHARS if len(c.char) == 1] 8 | all_unicode_chars = [ 9 | "֑", 10 | "֒", 11 | "֓", 12 | "֔", 13 | "֕", 14 | "֖", 15 | "֗", 16 | "֘", 17 | "֙", 18 | "֚", 19 | "֛", 20 | "֜", 21 | "֝", 22 | "֞", 23 | "֟", 24 | "֠", 25 | "֡", 26 | "֢", 27 | "֣", 28 | "֤", 29 | "֥", 30 | "֦", 31 | "֧", 32 | "֨", 33 | "֩", 34 | "֪", 35 | "֫", 36 | "֬", 37 | "֭", 38 | "֮", 39 | "֯", 40 | "ְ", 41 | "ֱ", 42 | "ֲ", 43 | "ֳ", 44 | "ִ", 45 | "ֵ", 46 | "ֶ", 47 | "ַ", 48 | "ָ", 49 | "ֹ", 50 | "ֺ", 51 | "ֻ", 52 | "ּ", 53 | "ֽ", 54 | "־", 55 | "ֿ", 56 | "׀", 57 | "ׁ", 58 | "ׂ", 59 | "׃", 60 | "ׄ", 61 | "ׅ", 62 | "׆", 63 | "ׇ", 64 | "א", 65 | "ב", 66 | "ג", 67 | "ד", 68 | "ה", 69 | "ו", 70 | "ז", 71 | "ח", 72 | "ט", 73 | "י", 74 | "ך", 75 | "כ", 76 | "ל", 77 | "ם", 78 | "מ", 79 | "ן", 80 | "נ", 81 | "ס", 82 | "ע", 83 | "ף", 84 | "פ", 85 | "ץ", 86 | "צ", 87 | "ק", 88 | "ר", 89 | "ש", 90 | "ת", 91 | "ׯ", 92 | "װ", 93 | "ױ", 94 | "ײ", 95 | "׳", 96 | "״", 97 | "ℵ", 98 | "ℶ", 99 | "ℷ", 100 | "ℸ", 101 | "יִ", 102 | "ﬞ", 103 | "ײַ", 104 | "ﬠ", 105 | "ﬡ", 106 | "ﬢ", 107 | "ﬣ", 108 | "ﬤ", 109 | "ﬥ", 110 | "ﬦ", 111 | "ﬧ", 112 | "ﬨ", 113 | "﬩", 114 | "שׁ", 115 | "שׂ", 116 | "שּׁ", 117 | "שּׂ", 118 | "אַ", 119 | "אָ", 120 | "אּ", 121 | "בּ", 122 | "גּ", 123 | "דּ", 124 | "הּ", 125 | "וּ", 126 | "זּ", 127 | "טּ", 128 | "יּ", 129 | "ךּ", 130 | "כּ", 131 | "לּ", 132 | "מּ", 133 | "נּ", 134 | "סּ", 135 | "ףּ", 136 | "פּ", 137 | "צּ", 138 | "קּ", 139 | "רּ", 140 | "שּ", 141 | "תּ", 142 | "וֹ", 143 | "בֿ", 144 | "כֿ", 145 | "פֿ", 146 | "ﭏ", 147 | ] 148 | 149 | assert len(all_unicode_chars) == len( 150 | set(all_unicode_chars) 151 | ), "There are duplicate values in all_unicode_chars" 152 | for char in all_unicode_chars: 153 | assert ( 154 | len(char) == 1 155 | ), f"all_unicode_chars contains a char that is not a single character: {char}" 156 | assert sorted(all_unicode_chars_defined) == sorted(all_unicode_chars), ( 157 | f"The following hebrew related chars are missing from `hebrew.chars`: " 158 | f"{[c for c in all_unicode_chars if c not in all_unicode_chars_defined]}" 159 | ) 160 | 161 | 162 | def test_hebrew_char_hebrew_names(): 163 | tsadi_sofit = HebrewChar( 164 | char="ץ", 165 | name="Tsadi Sofit", 166 | final_letter=True, 167 | hebrew_name="צַדִי סוֹפִית", 168 | hebrew_name_alts=["צדיק סופית"], 169 | ) 170 | assert sorted(tsadi_sofit.hebrew_names) == sorted(["צַדִי סוֹפִית", "צדיק סופית"]) 171 | 172 | 173 | def test_hebrew_char_names(): 174 | aleph = HebrewChar(char="א", name="Aleph", hebrew_name="אָלֶף", name_alts=["Alef"]) 175 | assert sorted(aleph.names) == sorted(["Aleph", "Alef"]) 176 | 177 | 178 | def test_hebrew_char_str(): 179 | aleph = HebrewChar(char="א", name="Aleph", hebrew_name="אָלֶף", name_alts=["Alef"]) 180 | assert str(aleph) == "א" 181 | 182 | 183 | def test_base_letter(): 184 | bet_with_dot = HebrewChar(char="בּ", name="Bet") 185 | assert bet_with_dot.base_letter.char == "ב" 186 | 187 | 188 | def test_final_letters(): 189 | final_chars = ["ץ", "ף", "ן", "ם", "ך"] 190 | assert len(final_chars) == len(FINAL_LETTERS) 191 | for char in final_chars: 192 | assert char in [c.char for c in FINAL_LETTERS] 193 | 194 | 195 | def test_hebrew_chars(): 196 | assert len(HEBREW_CHARS) > 0 197 | for char in HEBREW_CHARS: 198 | assert type(char) == HebrewChar 199 | 200 | 201 | def test_yiddish_chars(): 202 | yiddish_letters = ["ױ", "װ", "ײ"] 203 | assert len(yiddish_letters) == len(YIDDISH_CHARS) 204 | for char in yiddish_letters: 205 | assert char in [c.char for c in YIDDISH_CHARS] 206 | 207 | 208 | def test_niqqud_chars(): 209 | assert len(NIQQUD_CHARS) > 0 210 | for char in NIQQUD_CHARS: 211 | assert type(char) == NiqqudChar 212 | 213 | 214 | def test_taamim_chars(): 215 | assert len(TAAMIM_CHARS) > 0 216 | for char in TAAMIM_CHARS: 217 | assert type(char) == TaamimChar 218 | 219 | 220 | def test_other_chars(): 221 | assert len(OTHER_CHARS) > 0 222 | for char in OTHER_CHARS: 223 | assert type(char) == OtherChar 224 | 225 | 226 | def test_char_dict(): 227 | assert len(CHARS) == len( 228 | ALL_CHARS 229 | ), "The _ALL_CHARS array may contain values with duplicate char values" 230 | 231 | 232 | def test_char_search(): 233 | assert isinstance( 234 | char_search("Aleph"), HebrewChar 235 | ), "HebrewChar.search should return a HebrewChar instance" 236 | assert isinstance(char_search("aLEPH"), HebrewChar), "Should be case insensitive" 237 | assert char_search("Bad Value") is None 238 | 239 | 240 | def test_char_search_use_alt_names(): 241 | search_result = char_search("Hei") 242 | assert isinstance(search_result, HebrewChar) 243 | assert search_result.char == "ה" 244 | assert search_result.name != "Hei" 245 | 246 | 247 | def test_char_search_use_char_list(): 248 | assert char_search("Aleph") == ALEPH 249 | assert char_search("Alef", NIQQUD_CHARS) is None 250 | assert char_search("Kumatz", NIQQUD_CHARS) == KUMATZ 251 | 252 | 253 | def test_hebrew_char_search(): 254 | assert HebrewChar.search("Aleph") == ALEPH 255 | assert HebrewChar.search("Double Vav") is None 256 | 257 | 258 | def test_yiddish_char_search(): 259 | assert YiddishChar.search("Double Vav") == DOUBLE_VAV 260 | assert YiddishChar.search("Aleph") is None 261 | 262 | 263 | def test_niqqud_char_search(): 264 | assert NiqqudChar.search("Kumatz") == KUMATZ 265 | assert NiqqudChar.search("Double Vav") is None 266 | 267 | 268 | def test_taamim_char_search(): 269 | assert TaamimChar.search("Shalshelet") == SHALSHELET 270 | assert TaamimChar.search("Kumatz") is None 271 | 272 | 273 | def test_other_char_search(): 274 | assert OtherChar.search("Geresh") == GERESH 275 | assert OtherChar.search("Kumatz") is None 276 | 277 | 278 | def test_hebrew_char_hashable(): 279 | assert hash( 280 | HebrewChar(char="א", name="Aleph", hebrew_name="אָלֶף", name_alts=["Alef"]) 281 | ) 282 | 283 | 284 | def test_yiddish_char_hashable(): 285 | assert hash(YiddishChar(char="ײ", name="Double Yod", name_alts=["Saf"])) 286 | 287 | 288 | def test_taamim_char_hashable(): 289 | assert hash(TaamimChar(char="֧", name="Darga")) 290 | 291 | 292 | def test_niqqud_char_hashable(): 293 | assert hash(NiqqudChar(char="ׂ", name="Sin Dot")) 294 | 295 | 296 | def test_other_char_hashable(): 297 | assert hash(OtherChar(char="׃", name="Sof Passuk")) 298 | 299 | 300 | def test_hebrew_char_eq(): 301 | hebrew_one = HebrewChar( 302 | char="א", name="Aleph", hebrew_name="אָלֶף", name_alts=["Alef"] 303 | ) 304 | hebrew_two = HebrewChar( 305 | char="בּ", name="Bet", hebrew_name="בֵּית", hebrew_name_alts=["בת"] 306 | ) 307 | assert hebrew_one == hebrew_one 308 | assert hebrew_one != hebrew_two 309 | assert hebrew_one != 5 310 | 311 | 312 | def test_yiddish_char_eq(): 313 | yiddish_one = YiddishChar(char="ױ", name="Vav Yod") 314 | yiddish_two = YiddishChar( 315 | char="װ", 316 | name="Double Vav", 317 | name_alts=["Double Vuv"], 318 | ) 319 | assert yiddish_one == yiddish_one 320 | assert yiddish_one != yiddish_two 321 | assert yiddish_one != 5 322 | 323 | 324 | def test_niqqud_char_eq(): 325 | niqqud_one = NiqqudChar(char="ׂ", name="Sin Dot") 326 | niqqud_two = NiqqudChar(char="ׁ", name="Shin Dot") 327 | assert niqqud_one == niqqud_one 328 | assert niqqud_one != niqqud_two 329 | assert niqqud_one != 5 330 | 331 | 332 | def test_taamim_char_eq(): 333 | taamim_one = TaamimChar(char="֙", name="Pashta") 334 | taamim_two = TaamimChar(char="֚", name="Yetiv") 335 | assert taamim_one == taamim_one 336 | assert taamim_one != taamim_two 337 | assert taamim_one != 5 338 | 339 | 340 | def test_other_char_eq(): 341 | other_one = OtherChar(char="־", name="Maqaf") 342 | other_two = OtherChar(char="׀", name="Paseq") 343 | assert other_one == other_one 344 | assert other_one != other_two 345 | assert other_one != 5 346 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Hebrew("בְּרֵאשִׁ֖ית")

2 |

3 | A python package with methods to handle the complexities of Hebrew text, calculate Gematria, and more. 4 |

5 |

6 | 7 | PyPI version 8 | 9 | 10 | Supported Python Versions 11 | 12 | 13 | Test 14 | 15 | 16 | 17 | 18 | 󠀠󠀠 19 | 20 | Twitter 21 | 22 |

23 | 24 | --- 25 | 26 | **Documentation**: [https://hebrew.aviperl.me/](https://hebrew.aviperl.me/) 27 | 28 | **Repository**: [https://github.com/avi-perl/hebrew](https://github.com/avi-perl/hebrew) 29 | 30 | --- 31 | 32 | # Installation 33 | 34 | 35 | 36 | ```bash 37 | $ pip install hebrew 38 | ``` 39 | 40 | # Example 41 | 42 | `Hebrew` assists in working with Hebrew text by providing methods to handle the text according to user-perceived 43 | characteristics. Additionally, methods for common Hebrew text processing are provided. 44 | 45 | ```python 46 | from hebrew import Hebrew 47 | from hebrew.chars import HebrewChar, ALEPH 48 | 49 | hs = Hebrew('בְּרֵאשִׁ֖ית') 50 | print(list(hs.graphemes)) # ['בְּ', 'רֵ', 'א', 'שִׁ֖', 'י', 'ת'] 51 | print(hs.text_only()) # בראשית 52 | 53 | print(ALEPH) # HebrewChar(char='א', name='Aleph', hebrew_name='אָלֶף', name_alts=['Alef'], hebrew_name_alts=None, final_letter=False) 54 | 55 | print(HebrewChar.search('bet')) # HebrewChar(char='בּ', name='Bet', hebrew_name='בֵּית', name_alts=None, hebrew_name_alts=None, final_letter=False) 56 | ``` 57 | 58 | ## Gematria 59 | 60 | The `Hebrew` class includes a `gematria` function that can return a value for _23_ different variations of Gematria! 61 | 62 | ```python 63 | from hebrew import Hebrew 64 | from hebrew import GematriaTypes 65 | 66 | hs = Hebrew(':מוֹדֶה אֲנִי לְפָנֶֽיךָ מֶֽלֶךְ חַי וְקַיָּם שֶׁהֶחֱזַֽרְתָּ בִּי נִשְׁמָתִי בְּחֶמְלָה, רַבָּה אֱמוּנָתֶֽךָ') 67 | 68 | assert hs.gematria() == 3111 69 | assert hs.gematria(GematriaTypes.MISPAR_GADOL) == 5111 70 | ``` 71 | 72 | Messy inputs, such as strings with english text mixed in, is supported. However, do be careful to work with sanitized 73 | strings as much as possible. 74 | 75 | ```python 76 | from hebrew import Hebrew 77 | 78 | hs1 = Hebrew( 79 | ''' 80 | Text: ":מוֹדֶה אֲנִי לְפָנֶֽיךָ מֶֽלֶךְ חַי וְקַיָּם שֶׁהֶחֱזַֽרְתָּ בִּי נִשְׁמָתִי בְּחֶמְלָה, רַבָּה אֱמוּנָתֶֽךָ" 81 | Translation: "I give thanks to You living and everlasting King for You have restored my soul with mercy. Great is Your faithfulness." 82 | ''' 83 | ) 84 | hs2 = Hebrew(':מוֹדֶה אֲנִי לְפָנֶֽיךָ מֶֽלֶךְ חַי וְקַיָּם שֶׁהֶחֱזַֽרְתָּ בִּי נִשְׁמָתִי בְּחֶמְלָה, רַבָּה אֱמוּנָתֶֽךָ') 85 | 86 | assert hs1.gematria() == hs2.gematria() # 2701 87 | ``` 88 | 89 | Major kudos goes to [TorahCalc](https://www.torahcalc.com/gematria/) whose calculator and explanations were critical to 90 | the development of this feature. 91 | 92 | ## Numerical Conversions 93 | 94 | You can create a Hebrew object that represents a number using the `from_number` method. This is handy for displaying numbers in Hebrew form. 95 | 96 | ```python 97 | from hebrew import Hebrew 98 | 99 | hs1 = Hebrew.from_number(2) 100 | assert hs1.string == "ב׳" 101 | 102 | # Add an apostrophe instead of the unicode geresh 103 | hs2 = Hebrew.from_number(2, geresh=False) 104 | assert hs2.string == "ב'" 105 | 106 | # Do not add punctuation 107 | hs2 = Hebrew.from_number(2, punctuate=False) 108 | assert hs2.string == 'ב' 109 | ``` 110 | 111 | ## Character Normalization 112 | Hidden among hebrew text can be special characters that are visually identical humans, but are made up of different 113 | unicode characters. However, this can cause issues with presentation when there is no support for these characters. 114 | 115 | ![bad_character_display.png](docs/img/bad_character_display.png) 116 | 117 | In this case, the first letter is made up of 2 unicode characters, [sin with a dot](https://en.wiktionary.org/wiki/%D7%A9%D7%82) 118 | and [qamatz](https://en.wiktionary.org/wiki/%D6%B8). The issue here is the sin. By normalizing the sin with a dot to 2 unicode 119 | characters, [ש](https://en.wiktionary.org/wiki/%D7%A9) and the [dot](https://en.wiktionary.org/wiki/%D7%82), the display 120 | will look right! 121 | 122 | ![good_character_display.png](docs/img/good_character_display.png) 123 | 124 | To normalize content, use the `Hebrew.normalize` function: 125 | ```python 126 | from hebrew import Hebrew 127 | 128 | hs = Hebrew('שָׂחַקְתִּי כְּמוֹ') 129 | 130 | assert len(hs.string) == 14 131 | assert len(hs.normalize().string) == 18 132 | ``` 133 | 134 | ### Normalizing Yiddish 135 | 136 | By default, special yiddish characters such as [ײ](https://en.wiktionary.org/wiki/%D7%B2) (double Yod) are _not_ normalized. 137 | However, [ײַ](https://en.wiktionary.org/wiki/%EF%AC%9F) (double Yod with a Patah) will be converted to [ײַ](https://en.wiktionary.org/wiki/%D7%B2%D6%B7). 138 | 139 | To fully "normalize" yiddish characters, pass `True` to `normalize`. 140 | 141 | 142 | ## Grapheme Characters 143 | 144 | Hebrew text comes in different forms, depending on the context. Hebrew text may appear with Niqqudot 145 | "a system of diacritical signs used to represent vowels or distinguish between alternative pronunciations of letters 146 | of the Hebrew alphabet". [^1] Additionally, Hebrew text may appear with extensive punctuation characters that connect 147 | words, separate them, and cantillation marks "used as a guide for chanting the text, either from the printed text or, 148 | in the case of the public reading of the Torah" [^2]. 149 | 150 | Because of the above, from the perspective of a hebrew reader, the following 3 words are the same: 151 | 152 | 1. **בְּרֵאשִׁ֖ית** 153 | 2. **בְּרֵאשִׁית** 154 | 3. **בראשית** 155 | 156 | However, as a unicode string, they are entirely different because of the additional characters. 157 | 158 | ```python 159 | assert len("בְּרֵאשִׁ֖ית") == 12 160 | assert len("בְּרֵאשִׁית") == 11 161 | assert len("בראשית") == 6 162 | ``` 163 | 164 | This impacts the user is a number of other ways. For example, if I want to get the root of this hebrew word using a slice: 165 | _Expected: `רֵאשִׁ֖ית`_ 166 | 167 | ```python 168 | he = "בְּרֵאשִׁ֖ית" 169 | assert he[-5:] == 'ִׁ֖ית' 170 | ``` 171 | 172 | The solution to this is to handle the unicode string as a list of grapheme[^3] characters, where each letter and its 173 | accompanying characters are treated as a single unit. 174 | 175 | ### Working with Grapheme Characters 176 | 177 | Using the [grapheme](https://github.com/alvinlindstam/grapheme) library for python, we can work with the grapheme 178 | characters as units. This allows us to get the right number of characters, slice the string correctly, and more. 179 | 180 | ```python 181 | import grapheme 182 | 183 | assert grapheme.length("בְּרֵאשִׁ֖ית") == 6 184 | assert grapheme.slice("בְּרֵאשִׁ֖ית", start=1, end=6) == 'רֵאשִׁ֖ית' 185 | ``` 186 | 187 | This library includes 2 classes. `GraphemeString` is a class that supports all the functions made available by `grapheme`. 188 | The 2nd class `Hebrew` subclasses `GraphemeString` and adds methods for handling Hebrew text. This allows us to 189 | interact with the text like so: 190 | 191 | ```python 192 | from hebrew import Hebrew 193 | 194 | v2 = Hebrew('מוֹדֶה אֲנִי לְפָנֶֽיךָ') 195 | print(v2.no_taamim()) 196 | assert v2.no_taamim().string == 'מוֹדֶה אֲנִי לְפָנֶיךָ' 197 | assert v2.text_only().string == 'מודה אני לפניך' 198 | 199 | assert v2.length == 14 200 | assert v2.words() == [Hebrew('מוֹדֶה'), Hebrew('אֲנִי'), Hebrew('לְפָנֶֽיךָ')] 201 | ``` 202 | 203 | The text in these examples and used in testing were sourced from [Sefaria](https://github.com/Sefaria/Sefaria-Export). 204 | 205 | ## `hebrew.chars` and Character Constants 206 | 207 | `hebrew.Chars` contains constants for every letter as well as lists by character category's. 208 | Each value is an instance of a class that represents a character in the Hebrew character set with relevant properties. 209 | Since this library seeks to support the use of the Hebrew language in the way it is used, characters such as "בּ" can be 210 | located (`BET`) even though, strictly speaking, "בּ" is not part of the hebrew alphabet; it is a Hebrew letter plus a dot. 211 | 212 | ```python 213 | from hebrew.chars import FINAL_LETTERS, YIDDISH_CHARS, TSADI 214 | 215 | print(TSADI) # HebrewChar(char='צ', name='Tsadi', hebrew_name='צַדִי', name_alts=['Tzadik'], hebrew_name_alts=['צדיק'], final_letter=False) 216 | 217 | assert {c.name: c.char for c in FINAL_LETTERS} == {'Chaf Sofit': 'ך', 'Mem Sofit': 'ם', 'Nun Sofit': 'ן', 'Fe Sofit': 'ף', 'Tsadi Sofit': 'ץ'} 218 | 219 | assert [c.char for c in YIDDISH_CHARS] == ['ײ', 'װ', 'ױ'] 220 | ``` 221 | 222 | A letter can be retrieved using the `CHARS` dict; A dict of all instances of all supported Char types where the key is 223 | the char and the value is an instance of BaseHebrewChar. 224 | 225 | ```python 226 | from hebrew.chars import CHARS 227 | 228 | print(CHARS.get('בּ')) # HebrewChar(char='בּ', name='Bet', hebrew_name='בֵּית', name_alts=None, hebrew_name_alts=None, final_letter=False) 229 | ``` 230 | 231 | Search is also supported so that letters can be retrieved by their name. 232 | 233 | ```python 234 | from hebrew.chars import HebrewChar 235 | 236 | print(HebrewChar.search('bet')) # HebrewChar(char='בּ', name='Bet', hebrew_name='בֵּית', name_alts=None, hebrew_name_alts=None, final_letter=False) 237 | ``` 238 | 239 | ## Contributing 240 | 241 | Contributions in the form of pull requests are very welcome! I'm sure many more helpful methods related to hebrew text 242 | could be helpful. More information and instructions for contributing can be found [here](CONTRIBUTING). 243 | 244 | [^1]: [https://en.wikipedia.org/wiki/Niqqud](https://en.wikipedia.org/wiki/Niqqud) 245 | [^2]: [https://en.wikipedia.org/wiki/Hebrew_cantillation](https://en.wikipedia.org/wiki/Hebrew_cantillation) 246 | [^3]: [https://en.wikipedia.org/wiki/Grapheme](https://en.wikipedia.org/wiki/Grapheme) 247 | -------------------------------------------------------------------------------- /hebrew/gematria.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Dict 3 | 4 | 5 | class GematriaTypes(Enum): 6 | """ 7 | Types of Gematria supported in this library. 8 | """ 9 | 10 | # Simple methods where the value is calculated off of a value map to each letter 11 | MISPAR_HECHRACHI = "mispar_hechrachi" 12 | MISPAR_GADOL = "mispar_gadol" 13 | MISPAR_SIDURI = "mispar_siduri" 14 | MISPAR_KATAN = "mispar_katan" 15 | MISPAR_PERATI = "mispar_perati" 16 | ATBASH = "atbash" 17 | ALBAM = "albam" 18 | MISPAR_MESHULASH = "mispar_meshulash" 19 | MISPAR_KIDMI = "mispar_kidmi" 20 | MISPAR_MISPARI = "mispar_mispari" 21 | AYAK_BACHAR = "ayak_bachar" 22 | AYAK_BAKAR = AYAK_BACHAR 23 | OFANIM = "ofanim" 24 | ACHAS_BETA = "achas_beta" 25 | AVGAD = "avgad" 26 | REVERSE_AVGAD = "reverse_avgad" 27 | 28 | # Complex methods involving logic on top of MISPAR_HECHRACHI 29 | MISPAR_MUSAFI = "mispar_musafi" 30 | MISPAR_BONEEH = "mispar_boneeh" 31 | MISPAR_HAMERUBAH_HAKLALI = "mispar_hamerubah_haklali" 32 | MISPAR_HAACHOR = "mispar_haachor" 33 | MISPAR_KATAN_MISPARI = "mispar_katan_mispari" 34 | MISPAR_KOLEL = "mispar_kolel" 35 | MISPAR_SHEMI_MILUI = "mispar_shemi_milui" 36 | MISPAR_NEELAM = "mispar_neelam" 37 | 38 | 39 | """ 40 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the mispar_hechrachi 41 | gematria method as its value. 42 | """ 43 | MISPAR_HECHRACHI: Dict[str, int] = { 44 | "א": 1, 45 | "ב": 2, 46 | "ג": 3, 47 | "ד": 4, 48 | "ה": 5, 49 | "ו": 6, 50 | "ז": 7, 51 | "ח": 8, 52 | "ט": 9, 53 | "י": 10, 54 | "כ": 20, 55 | "ך": 20, 56 | "ל": 30, 57 | "מ": 40, 58 | "ם": 40, 59 | "נ": 50, 60 | "ן": 50, 61 | "ס": 60, 62 | "ע": 70, 63 | "פ": 80, 64 | "ף": 80, 65 | "צ": 90, 66 | "ץ": 90, 67 | "ק": 100, 68 | "ר": 200, 69 | "ש": 300, 70 | "ת": 400, 71 | } 72 | 73 | """ 74 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the mispar_gadol 75 | gematria method as its value. Non-final letter values are all the same, but final kaf/chaf, mem, nun, pe/fe are 76 | moved to the end of the alphabet and continue on from where tav left off 77 | """ 78 | MISPAR_GADOL: Dict[str, int] = { 79 | "א": 1, 80 | "ב": 2, 81 | "ג": 3, 82 | "ד": 4, 83 | "ה": 5, 84 | "ו": 6, 85 | "ז": 7, 86 | "ח": 8, 87 | "ט": 9, 88 | "י": 10, 89 | "כ": 20, 90 | "ך": 500, 91 | "ל": 30, 92 | "מ": 40, 93 | "ם": 600, 94 | "נ": 50, 95 | "ן": 700, 96 | "ס": 60, 97 | "ע": 70, 98 | "פ": 80, 99 | "ף": 800, 100 | "צ": 90, 101 | "ץ": 900, 102 | "ק": 100, 103 | "ר": 200, 104 | "ש": 300, 105 | "ת": 400, 106 | } 107 | 108 | """ 109 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the mispar_siduri 110 | gematria method as its value. This method assigns each letter a number from 1 to 22 in the order of the alphabet. 111 | """ 112 | MISPAR_SIDURI: Dict[str, int] = { 113 | "א": 1, 114 | "ב": 2, 115 | "ג": 3, 116 | "ד": 4, 117 | "ה": 5, 118 | "ו": 6, 119 | "ז": 7, 120 | "ח": 8, 121 | "ט": 9, 122 | "י": 10, 123 | "כ": 11, 124 | "ך": 23, 125 | "ל": 12, 126 | "מ": 13, 127 | "ם": 24, 128 | "נ": 14, 129 | "ן": 25, 130 | "ס": 15, 131 | "ע": 16, 132 | "פ": 17, 133 | "ף": 26, 134 | "צ": 18, 135 | "ץ": 27, 136 | "ק": 19, 137 | "ר": 20, 138 | "ש": 21, 139 | "ת": 22, 140 | } 141 | 142 | """ 143 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the mispar_katan 144 | gematria method as its value. This method uses the value of the letters but without the zeros after large numbers. 145 | (ex. "Yud" is 1 instead of 10, "Tav" is 4 instead of 400). 146 | """ 147 | MISPAR_KATAN: Dict[str, int] = { 148 | "א": 1, 149 | "ב": 2, 150 | "ג": 3, 151 | "ד": 4, 152 | "ה": 5, 153 | "ו": 6, 154 | "ז": 7, 155 | "ח": 8, 156 | "ט": 9, 157 | "י": 1, 158 | "כ": 2, 159 | "ך": 2, 160 | "ל": 3, 161 | "מ": 4, 162 | "ם": 4, 163 | "נ": 5, 164 | "ן": 5, 165 | "ס": 6, 166 | "ע": 7, 167 | "פ": 8, 168 | "ף": 8, 169 | "צ": 9, 170 | "ץ": 9, 171 | "ק": 1, 172 | "ר": 2, 173 | "ש": 3, 174 | "ת": 4, 175 | } 176 | 177 | """ 178 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the mispar_perati 179 | gematria method as its value. This method assigns each letter its standard value squared. (ex. "Aleph" = 1 x 1 = 1, "Beis" = 2 x 2 = 4). 180 | """ 181 | MISPAR_PERATI: Dict[str, int] = { 182 | "א": 1, 183 | "ב": 4, 184 | "ג": 9, 185 | "ד": 16, 186 | "ה": 25, 187 | "ו": 36, 188 | "ז": 49, 189 | "ח": 64, 190 | "ט": 81, 191 | "י": 100, 192 | "כ": 400, 193 | "ך": 400, 194 | "ל": 900, 195 | "מ": 1_600, 196 | "ם": 1_600, 197 | "נ": 2_500, 198 | "ן": 2_500, 199 | "ס": 3_600, 200 | "ע": 4_900, 201 | "פ": 6_400, 202 | "ף": 6_400, 203 | "צ": 8_100, 204 | "ץ": 8_100, 205 | "ק": 10_000, 206 | "ר": 40_000, 207 | "ש": 90_000, 208 | "ת": 160_000, 209 | } 210 | 211 | """ 212 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the AtBash 213 | gematria method as its value. This method exchanges each letter's value for its opposite letter's value. 214 | (ex. "Aleph" switches values with "Tav", "Beis" switches values with "Shin"). 215 | """ 216 | ATBASH: Dict[str, int] = { 217 | "א": 400, 218 | "ב": 300, 219 | "ג": 200, 220 | "ד": 100, 221 | "ה": 90, 222 | "ו": 80, 223 | "ז": 70, 224 | "ח": 60, 225 | "ט": 50, 226 | "י": 40, 227 | "כ": 30, 228 | "ך": 30, 229 | "ל": 20, 230 | "מ": 10, 231 | "ם": 10, 232 | "נ": 9, 233 | "ן": 9, 234 | "ס": 8, 235 | "ע": 7, 236 | "פ": 6, 237 | "ף": 6, 238 | "צ": 5, 239 | "ץ": 5, 240 | "ק": 4, 241 | "ר": 3, 242 | "ש": 2, 243 | "ת": 1, 244 | } 245 | 246 | """ 247 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the AlBam 248 | gematria method as its value. This method splits the alphabet in half and letters from the first half switch 249 | values with letters from the second half. (ex. "Aleph" switches values with "Lamed", "Beis" switches values with "Mem"). 250 | """ 251 | ALBAM: Dict[str, int] = { 252 | "א": 30, 253 | "ב": 40, 254 | "ג": 50, 255 | "ד": 60, 256 | "ה": 70, 257 | "ו": 80, 258 | "ז": 90, 259 | "ח": 100, 260 | "ט": 200, 261 | "י": 300, 262 | "כ": 400, 263 | "ך": 400, 264 | "ל": 1, 265 | "מ": 2, 266 | "ם": 2, 267 | "נ": 3, 268 | "ן": 3, 269 | "ס": 4, 270 | "ע": 5, 271 | "פ": 6, 272 | "ף": 6, 273 | "צ": 7, 274 | "ץ": 7, 275 | "ק": 8, 276 | "ר": 9, 277 | "ש": 10, 278 | "ת": 20, 279 | } 280 | 281 | """ 282 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the AtBash 283 | gematria method as its value. This method splits the alphabet in half and letters from the first half switch 284 | values with letters from the second half. (ex. "Aleph" switches values with "Lamed", "Beis" switches values with "Mem"). 285 | """ 286 | MISPAR_MESHULASH: Dict[str, int] = { 287 | "א": 1, 288 | "ב": 8, 289 | "ג": 27, 290 | "ד": 64, 291 | "ה": 125, 292 | "ו": 216, 293 | "ז": 343, 294 | "ח": 512, 295 | "ט": 729, 296 | "י": 1_000, 297 | "כ": 8_000, 298 | "ך": 8_000, 299 | "ל": 27_000, 300 | "מ": 64_000, 301 | "ם": 64_000, 302 | "נ": 125_000, 303 | "ן": 125_000, 304 | "ס": 216_000, 305 | "ע": 343_000, 306 | "פ": 512_000, 307 | "ף": 512_000, 308 | "צ": 729_000, 309 | "ץ": 729_000, 310 | "ק": 1_000_000, 311 | "ר": 8_000_000, 312 | "ש": 27_000_000, 313 | "ת": 64_000_000, 314 | } 315 | 316 | """ 317 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Mispar Kidmi 318 | gematria method as its value. This method adds the value of all preceding letters in the alphabet to each 319 | letter's value. (ex. "Aleph" = 1, "Beis" = 1 + 2 = 3, "Gimmel" = 1 + 2 + 3 = 6). 320 | """ 321 | MISPAR_KIDMI: Dict[str, int] = { 322 | "א": 1, 323 | "ב": 3, 324 | "ג": 6, 325 | "ד": 10, 326 | "ה": 15, 327 | "ו": 21, 328 | "ז": 28, 329 | "ח": 36, 330 | "ט": 45, 331 | "י": 55, 332 | "כ": 75, 333 | "ך": 75, 334 | "ל": 105, 335 | "מ": 145, 336 | "ם": 145, 337 | "נ": 195, 338 | "ן": 195, 339 | "ס": 255, 340 | "ע": 325, 341 | "פ": 405, 342 | "ף": 405, 343 | "צ": 495, 344 | "ץ": 495, 345 | "ק": 595, 346 | "ר": 795, 347 | "ש": 1095, 348 | "ת": 1495, 349 | } 350 | 351 | """ 352 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Mispar Mispari 353 | gematria method as its value. This method spells out the Hebrew name of each of the letter's standard values and adds 354 | up their values. (ex. "Aleph" = one (Echad) = 1 + 8 + 4 = 13). 355 | """ 356 | MISPAR_MISPARI: Dict[str, int] = { 357 | "א": 13, 358 | "ב": 760, 359 | "ג": 636, 360 | "ד": 273, 361 | "ה": 348, 362 | "ו": 600, 363 | "ז": 372, 364 | "ח": 401, 365 | "ט": 770, 366 | "י": 570, 367 | "כ": 620, 368 | "ך": 620, 369 | "ל": 686, 370 | "מ": 323, 371 | "ם": 323, 372 | "נ": 408, 373 | "ן": 408, 374 | "ס": 660, 375 | "ע": 422, 376 | "פ": 446, 377 | "ף": 446, 378 | "צ": 820, 379 | "ץ": 820, 380 | "ק": 46, 381 | "ר": 501, 382 | "ש": 1083, 383 | "ת": 720, 384 | } 385 | 386 | """ 387 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Ayak Bachar 388 | (or Ayak Bakar) gematria method as its value. This method splits the alphabet into three groups of nine with the final 389 | (sofit) letters at the end. The letters in the first group replace the ones in the second group, the letters in the 390 | second group replace the ones in the third group, and the letters in the third group replace the ones in 391 | the first group. (ex. "Aleph" takes the place of "Yud", "Yud" takes the place of "Kuf", 392 | "Kuf" takes the place of "Aleph", "Beis" takes the place of "Chaf" etc.). 393 | """ 394 | AYAK_BACHAR: Dict[str, int] = { 395 | "א": 10, 396 | "ב": 20, 397 | "ג": 30, 398 | "ד": 40, 399 | "ה": 50, 400 | "ו": 60, 401 | "ז": 70, 402 | "ח": 80, 403 | "ט": 90, 404 | "י": 100, 405 | "כ": 200, 406 | "ך": 5, 407 | "ל": 300, 408 | "מ": 400, 409 | "ם": 6, 410 | "נ": 500, 411 | "ן": 7, 412 | "ס": 600, 413 | "ע": 700, 414 | "פ": 800, 415 | "ף": 8, 416 | "צ": 900, 417 | "ץ": 9, 418 | "ק": 1, 419 | "ר": 2, 420 | "ש": 3, 421 | "ת": 4, 422 | } 423 | 424 | """ 425 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Ofanim 426 | gematria method as its value. This method replaces each letter with the last letter of its name. (ex. "Aleph" becomes 427 | "Fey", "Beis" becomes "Tav"). 428 | """ 429 | OFANIM: Dict[str, int] = { 430 | "א": 80, 431 | "ב": 400, 432 | "ג": 30, 433 | "ד": 400, 434 | "ה": 1, 435 | "ו": 6, 436 | "ז": 50, 437 | "ח": 400, 438 | "ט": 400, 439 | "י": 4, 440 | "כ": 80, 441 | "ך": 80, 442 | "ל": 4, 443 | "מ": 40, 444 | "ם": 40, 445 | "נ": 50, 446 | "ן": 50, 447 | "ס": 20, 448 | "ע": 50, 449 | "פ": 1, 450 | "ף": 1, 451 | "צ": 10, 452 | "ץ": 10, 453 | "ק": 80, 454 | "ר": 300, 455 | "ש": 50, 456 | "ת": 6, 457 | } 458 | 459 | """ 460 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Ofanim 461 | gematria method as its value. This method splits the alphabet into groups of 7, 7, and 8 letters. 462 | The letters in the first group replace the ones in the second group, the letters in the second group replace 463 | the ones in the third group, and the letters in the third group replace the ones in the first group. The letter "Tav" 464 | does not change. 465 | """ 466 | ACHAS_BETA: Dict[str, int] = { 467 | "א": 8, 468 | "ב": 9, 469 | "ג": 10, 470 | "ד": 20, 471 | "ה": 30, 472 | "ו": 40, 473 | "ז": 50, 474 | "ח": 60, 475 | "ט": 70, 476 | "י": 80, 477 | "כ": 90, 478 | "ך": 90, 479 | "ל": 100, 480 | "מ": 200, 481 | "ם": 200, 482 | "נ": 300, 483 | "ן": 300, 484 | "ס": 1, 485 | "ע": 2, 486 | "פ": 3, 487 | "ף": 3, 488 | "צ": 4, 489 | "ץ": 4, 490 | "ק": 5, 491 | "ר": 6, 492 | "ש": 7, 493 | "ת": 400, 494 | } 495 | 496 | """ 497 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Avgad 498 | gematria method as its value. This method replaces each letter with the next one. (ex. "Aleph" becomes "Beis", "Beis" 499 | becomes "Gimmel", "Tav" becomes "Aleph"). 500 | """ 501 | AVGAD: Dict[str, int] = { 502 | "א": 2, 503 | "ב": 3, 504 | "ג": 4, 505 | "ד": 5, 506 | "ה": 6, 507 | "ו": 7, 508 | "ז": 8, 509 | "ח": 9, 510 | "ט": 10, 511 | "י": 20, 512 | "כ": 30, 513 | "ך": 30, 514 | "ל": 40, 515 | "מ": 50, 516 | "ם": 50, 517 | "נ": 60, 518 | "ן": 60, 519 | "ס": 70, 520 | "ע": 80, 521 | "פ": 90, 522 | "ף": 90, 523 | "צ": 100, 524 | "ץ": 100, 525 | "ק": 200, 526 | "ר": 300, 527 | "ש": 400, 528 | "ת": 1, 529 | } 530 | 531 | """ 532 | A dictionary of values with each letter of the alphabet as a key, and the numerical value used in the Reverse Avgad 533 | gematria method as its value. This method replaces each letter with the previous one. (ex. "Beis" becomes "Aleph", 534 | "Gimmel" becomes "Beis", "Aleph" becomes "Tav"). 535 | """ 536 | REVERSE_AVGAD: Dict[str, int] = { 537 | "א": 400, 538 | "ב": 1, 539 | "ג": 2, 540 | "ד": 3, 541 | "ה": 4, 542 | "ו": 5, 543 | "ז": 6, 544 | "ח": 7, 545 | "ט": 8, 546 | "י": 9, 547 | "כ": 10, 548 | "ך": 10, 549 | "ל": 20, 550 | "מ": 30, 551 | "ם": 30, 552 | "נ": 40, 553 | "ן": 40, 554 | "ס": 50, 555 | "ע": 60, 556 | "פ": 70, 557 | "ף": 70, 558 | "צ": 80, 559 | "ץ": 80, 560 | "ק": 90, 561 | "ר": 100, 562 | "ש": 200, 563 | "ת": 300, 564 | } 565 | -------------------------------------------------------------------------------- /hebrew/hebrew_obj.py: -------------------------------------------------------------------------------- 1 | import unicodedata 2 | from functools import reduce 3 | from typing import List, Optional, TypeVar, Dict, Callable, Tuple 4 | from operator import add 5 | 6 | from hebrew.numerical_conversion.substitute import Substitutions 7 | 8 | from .grapheme_string import GraphemeString 9 | from .chars import ( 10 | MAQAF, 11 | NIQQUD_CHARS, 12 | TAAMIM_CHARS, 13 | PASEQ, 14 | SOF_PASSUK, 15 | _NON_LETTER_CHARS, 16 | CHARS, 17 | HEBREW_CHARS, 18 | FINAL_MINOR_LETTER_MAPPINGS, 19 | HebrewChar, 20 | SPECIAL_CHARACTER_NORMALIZED_MAPPING, 21 | YiddishChar, 22 | ) 23 | from .numerical_conversion.convert import number_to_hebrew_string 24 | from hebrew.gematria import GematriaTypes 25 | 26 | HebrewT = TypeVar("HebrewT", bound="Hebrew") 27 | 28 | 29 | def get_hebrew_name(letter: HebrewChar, name_dict) -> str: 30 | """ 31 | Helper function to get the letters name from the library definition 32 | or from the alts provided by the user. 33 | 34 | The name value passed *must* be a name that is defined in the characters `HebrewChar` instance or a 35 | ValueError will be thrown. This is done to make sure that only valid naming is used. 36 | """ 37 | if not name_dict: 38 | name_dict = {} 39 | 40 | if name_dict and letter.char in name_dict.keys(): 41 | name = name_dict.get(letter.char) 42 | clean_name = Hebrew(name).text_only() 43 | if clean_name not in [Hebrew(nm).text_only() for nm in letter.hebrew_names]: 44 | raise ValueError(f"{name} is not a valid name for {letter}") 45 | return clean_name.string 46 | else: 47 | return letter.hebrew_name 48 | 49 | 50 | class Hebrew(GraphemeString): 51 | """ 52 | A class representing a Hebrew String. 53 | 54 | A `Hebrew` string can contain pure Hebrew letters, or can be composed of any additional characters. 55 | """ 56 | 57 | def __init__(self, string: str): 58 | super().__init__(string) 59 | 60 | def __str__(self) -> str: 61 | return self.string 62 | 63 | def __repr__(self) -> str: 64 | return self.__str__() 65 | 66 | def no_maqaf(self) -> HebrewT: 67 | """ 68 | Replaces all maqafs with spaces. 69 | 70 | This is useful for splitting a string into words when you want words connected by maqafs to be considered as one word. 71 | Example: You may think of "עַל־פְּנֵ֥י" as one word in some cases but want to split it into "עַל" and "פְּנֵי" in other cases. 72 | 73 | :return: 74 | """ 75 | return Hebrew(self.string.replace(MAQAF.char, " ")) 76 | 77 | def no_sof_passuk(self) -> HebrewT: 78 | """ 79 | Removes all sof_passuk chars. 80 | 81 | :return: 82 | """ 83 | return Hebrew(self.string.replace(SOF_PASSUK.char, "")) 84 | 85 | def words(self, split_maqaf: bool = False) -> List[HebrewT]: 86 | """ 87 | Splits the string into a list of words. 88 | 89 | :param split_maqaf: Whether to split a single word such as "עַל־פְּנֵ֥י" into "עַל" and "פְּנֵי" when a maqaf is encountered. 90 | :return: 91 | """ 92 | string = self.string if not split_maqaf else self.no_maqaf().string 93 | return [Hebrew(s) for s in string.split()] 94 | 95 | def text_only(self, remove_maqaf: bool = False) -> HebrewT: 96 | """ 97 | Returns a string with all non-letter characters removed. 98 | This will remove both niqqud and punctuation. 99 | 100 | :param remove_maqaf: Whether to remove the maqaf characters if they are encountered 101 | :return: 102 | """ 103 | string = self.no_maqaf().string if remove_maqaf else self.string 104 | chars_to_remove = [c.char for c in _NON_LETTER_CHARS if c not in (MAQAF, PASEQ)] 105 | string = string.replace( 106 | f" {PASEQ.char} ", " " 107 | ) # Handled separately to avoid double spaces. 108 | for char in chars_to_remove: 109 | string = string.replace(char, "") 110 | return Hebrew(string) 111 | 112 | def no_niqqud(self) -> HebrewT: 113 | """ 114 | Removes all niqqud characters. 115 | This may be useful to practice reading from the torah. 116 | 117 | :return: 118 | """ 119 | string = self.string 120 | for char in [c.char for c in NIQQUD_CHARS]: 121 | string = string.replace(char, "") 122 | return Hebrew(string) 123 | 124 | def normalize(self, normalize_yiddish: bool = False) -> HebrewT: 125 | """ 126 | Replaces all non-standard hebrew characters with their equivalent values 127 | using normal hebrew letters and symbols. This is important when using hebrew fonts. Some fonts may not 128 | support these special characters, normalization helps by changing all the characters to be ones that would be 129 | supported. 130 | 131 | :param normalize_yiddish: By default, yiddish characters are left alone since they are typically desired. 132 | :return: 133 | """ 134 | normalized = unicodedata.normalize("NFC", self.string) 135 | # normalized = self.string 136 | special_chars: dict = ( 137 | SPECIAL_CHARACTER_NORMALIZED_MAPPING 138 | if normalize_yiddish 139 | else { 140 | k: v 141 | for k, v in SPECIAL_CHARACTER_NORMALIZED_MAPPING.items() 142 | if not isinstance(k, YiddishChar) 143 | } 144 | ) 145 | special_chars = { 146 | k.char: "".join([val.char for val in v]) if isinstance(v, list) else v.char 147 | for k, v in special_chars.items() 148 | } 149 | if any(char in normalized for char in special_chars): 150 | for k, v in special_chars.items(): 151 | normalized = normalized.replace(k, v) 152 | self.string = normalized 153 | return self 154 | 155 | def no_taamim( 156 | self, remove_maqaf: bool = False, remove_sof_passuk: bool = False 157 | ) -> HebrewT: 158 | """ 159 | Removes all [Ta'amim](https://en.wikipedia.org/wiki/Hebrew_cantillation) characters. 160 | Result is a string with just letters and Niqqud characters. 161 | 162 | :param remove_maqaf: Whether to remove the maqaf characters if they are encountered. 163 | :param remove_sof_passuk: Whether to remove the remove_sof_passuk character if they are encountered. 164 | :return: 165 | """ 166 | string = self.no_maqaf().string if remove_maqaf else self.string 167 | string = Hebrew(string).no_sof_passuk().string if remove_sof_passuk else string 168 | chars_to_remove = [ 169 | p.char for p in TAAMIM_CHARS if p not in (MAQAF, PASEQ, SOF_PASSUK) 170 | ] 171 | string = string.replace( 172 | f" {PASEQ.char} ", " " 173 | ) # Handled separately to avoid double spaces. 174 | for char in chars_to_remove: 175 | string = string.replace(char, "") 176 | return Hebrew(string) 177 | 178 | def gematria( 179 | self, 180 | method: GematriaTypes = GematriaTypes.MISPAR_HECHRACHI, 181 | alt_letter_name_spelling: Dict[str, str] = None, 182 | ) -> int: 183 | """ 184 | Returns the gematria of the string. 185 | 186 | If the contains no hebrew characters, the value returned is 0. Mixing hebrew and english characters is ok! 187 | 188 | :param method: The method to use for calculating the gematria. 189 | :param alt_letter_name_spelling: Used only with MISPAR_SHEMI_MILUI: A dict of alternate spellings for a letter 190 | that should be used to make the calculation. Eg: `{"ו": "ואו"}`. 191 | :return: 192 | """ 193 | # Remove non hebrew characters 194 | cleaned_string: str = "".join( 195 | [c for c in self.string if c in [x.char for x in HEBREW_CHARS] or c == " "] 196 | ) 197 | 198 | if method == GematriaTypes.MISPAR_MUSAFI: 199 | # Mispar Musafi (Heb: מספר מוספי) adds the number of letters in the word or phrase to the value. 200 | value = self.__calculate_simple_gematria(cleaned_string) 201 | hebrew_letters = [c for c in cleaned_string if c != " "] 202 | return value + len(hebrew_letters) 203 | 204 | elif method == GematriaTypes.MISPAR_KOLEL: 205 | # Mispar Kolel (Heb: מספר כלל) is the value plus the number of words in the phrase. 206 | value = self.__calculate_simple_gematria(cleaned_string) 207 | hebrew_words = cleaned_string.split() 208 | return value + len(hebrew_words) 209 | 210 | elif method == GematriaTypes.MISPAR_BONEEH: 211 | # Mispar Bone'eh (building value) (Heb: מספר בונה) adds the value of all previous letters in the word to the 212 | # value of the current letter as the word is calculated. (ex. Echad is 1 + (1 + 8) + (1 + 8 + 4) = 23). 213 | values = [ 214 | self.__calculate_simple_gematria(c) 215 | for c in [x for x in cleaned_string if x != " "] 216 | ] 217 | total = 0 218 | for i, n in enumerate(values): 219 | total += sum(values[:i]) + n 220 | return total 221 | 222 | elif method == GematriaTypes.MISPAR_HAMERUBAH_HAKLALI: 223 | # Mispar HaMerubah HaKlali (Heb: מספר המרובע הכללי) is the standard value squared. 224 | return self.__calculate_simple_gematria(cleaned_string) ** 2 225 | 226 | elif method == GematriaTypes.MISPAR_HAACHOR: 227 | # Mispar Ha'achor (sometimes called Mispar Meshulash, triangular value) (Heb: מספר האחור) values each letter 228 | # as its value multiplied by the position of the letter in the word or phrase. 229 | values = [ 230 | self.__calculate_simple_gematria(c) 231 | for c in [x for x in cleaned_string if x != " "] 232 | ] 233 | total = 0 234 | for i, n in enumerate(values): 235 | total += n * (i + 1) 236 | return total 237 | 238 | elif method == GematriaTypes.MISPAR_KATAN_MISPARI: 239 | # Mispar Katan Mispari (integral reduced value) (Heb: מספר קטן מספרי) is the digital root of the standard 240 | # value which is obtained by adding all the digits in the number until the number is a single digit. 241 | # (ex. Echad (13) --> 1 + 3 --> 4). 242 | calculated_value = self.__calculate_simple_gematria(cleaned_string) 243 | while calculated_value > 9: 244 | calculated_value = sum([int(x) for x in str(calculated_value)]) 245 | return calculated_value 246 | 247 | elif method == GematriaTypes.MISPAR_SHEMI_MILUI: 248 | # Mispar Shemi (Milui, full name value) (Heb: מספר שמי\מילוי) values each letter as the value of the 249 | # letter's name. (ex. "Aleph" = Aleph + Lamed + Fey = 1 + 30 + 80 = 111). 250 | # [Note: There is more than one way to spell certain letters.] 251 | 252 | # Get list of HebrewChar instances for each letter in string 253 | chars: List[HebrewChar] = [ 254 | CHARS[c] for c in [x for x in cleaned_string if x != " "] 255 | ] 256 | 257 | # Convert final letters to non-final since our internal lib naming for final letters 258 | # will ruin the calculation. 259 | replaced_final_letters = [ 260 | CHARS[FINAL_MINOR_LETTER_MAPPINGS.get(c.char)] if c.final_letter else c 261 | for c in chars 262 | ] 263 | 264 | # Get internal or user supplied names, and calculate value off them. 265 | values = [ 266 | self.__calculate_simple_gematria( 267 | get_hebrew_name(c, alt_letter_name_spelling) 268 | ) 269 | for c in replaced_final_letters 270 | ] 271 | return sum(values) 272 | 273 | elif method == GematriaTypes.MISPAR_NEELAM: 274 | # Mispar Ne'elam (hidden value) (Heb: מספר נעלם) values each letter as the value of the letter's name 275 | # without the letter itself. (ex. "Aleph" = Lamed + Fey = 30 + 80 = 110). 276 | 277 | # Get list of HebrewChar instances for each letter in string 278 | chars: List[HebrewChar] = [ 279 | CHARS[c] for c in [x for x in cleaned_string if x != " "] 280 | ] 281 | 282 | # Convert final letters to non-final since our internal lib naming for final letters 283 | # will ruin the calculation. 284 | replaced_final_letters = [ 285 | CHARS[FINAL_MINOR_LETTER_MAPPINGS.get(c.char)] if c.final_letter else c 286 | for c in chars 287 | ] 288 | 289 | # Get internal or user supplied names. 290 | names = [ 291 | get_hebrew_name(c, alt_letter_name_spelling) 292 | for c in replaced_final_letters 293 | ] 294 | 295 | # Remove letter from name and calculate value 296 | values = [self.__calculate_simple_gematria(c[1:]) for c in names] 297 | return sum(values) 298 | 299 | else: 300 | # Simple gematria that can be calculated by simply adding each letters value up to a final number. 301 | return self.__calculate_simple_gematria(self.string, method) 302 | 303 | @classmethod 304 | def from_number( 305 | cls, 306 | number: int, 307 | punctuate: bool = True, 308 | geresh: bool = True, 309 | substitution_functions: Optional[ 310 | Tuple[Callable[[str], str], ...] 311 | ] = Substitutions.DEFAULT, 312 | ): 313 | """ 314 | Convert a number into its Hebrew letter form, returning it as an instance of Hebrew. 315 | 316 | :param number: The number to convert to Hebrew letters. Must be greater than 0... 317 | :param punctuate: Whether to add punctuation in the appropriate places. 318 | :param geresh: If punctuate is true, whether to use the unicode geresh or an apostrophe. 319 | :param substitution_functions: A tuple of functions that replaces some hebrew values in the result with an 320 | appropriate equivalent. By default, "יה" and "יו" are replaced with "טו" and "טז" respectively. To replace all 321 | values such as שמד ,רע, and others, use `Substitutions.ALL`. 322 | :return: 323 | """ 324 | return cls( 325 | number_to_hebrew_string(number, punctuate, geresh, substitution_functions) 326 | ) 327 | 328 | @staticmethod 329 | def __calculate_simple_gematria( 330 | string: str, method: GematriaTypes = GematriaTypes.MISPAR_HECHRACHI 331 | ) -> int: 332 | """Calculate Gematria for simple Gematria that use a value map for each letter.""" 333 | chars = [ 334 | CHARS[c] for c in string if CHARS.get(c) and hasattr(CHARS[c], method.value) 335 | ] 336 | if len(chars) == 0: 337 | # The list will be 0 if there are no letters in the string or if the letters are not hebrew. 338 | return 0 339 | else: 340 | return reduce(add, [getattr(c, method.value) for c in chars]) 341 | -------------------------------------------------------------------------------- /tests/test_hebrew.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from hebrew import Hebrew 4 | from hebrew.chars import * 5 | 6 | taamei_hamikra = [ 7 | "בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָרֶץ׃", 8 | "וְהָאָ֗רֶץ הָיְתָ֥ה תֹ֙הוּ֙ וָבֹ֔הוּ וְחֹ֖שֶׁךְ עַל־פְּנֵ֣י תְה֑וֹם וְר֣וּחַ אֱלֹהִ֔ים מְרַחֶ֖פֶת עַל־פְּנֵ֥י הַמָּֽיִם׃", 9 | "וַיֹּ֥אמֶר אֱלֹהִ֖ים יְהִ֣י א֑וֹר וַֽיְהִי־אֽוֹר׃", 10 | "וַיַּ֧רְא אֱלֹהִ֛ים אֶת־הָא֖וֹר כִּי־ט֑וֹב וַיַּבְדֵּ֣ל אֱלֹהִ֔ים בֵּ֥ין הָא֖וֹר וּבֵ֥ין הַחֹֽשֶׁךְ׃", 11 | "וַיִּקְרָ֨א אֱלֹהִ֤ים ׀ לָאוֹר֙ י֔וֹם וְלַחֹ֖שֶׁךְ קָ֣רָא לָ֑יְלָה וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם אֶחָֽד׃", 12 | "וַיֹּ֣אמֶר אֱלֹהִ֔ים יְהִ֥י רָקִ֖יעַ בְּת֣וֹךְ הַמָּ֑יִם וִיהִ֣י מַבְדִּ֔יל בֵּ֥ין מַ֖יִם לָמָֽיִם׃", 13 | "וַיַּ֣עַשׂ אֱלֹהִים֮ אֶת־הָרָקִיעַ֒ וַיַּבְדֵּ֗ל בֵּ֤ין הַמַּ֙יִם֙ אֲשֶׁר֙ מִתַּ֣חַת לָרָקִ֔יעַ וּבֵ֣ין הַמַּ֔יִם אֲשֶׁ֖ר מֵעַ֣ל לָרָקִ֑יעַ וַֽיְהִי־כֵֽן׃", 14 | "וַיִּקְרָ֧א אֱלֹהִ֛ים לָֽרָקִ֖יעַ שָׁמָ֑יִם וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם שֵׁנִֽי׃", 15 | "וַיֹּ֣אמֶר אֱלֹהִ֗ים יִקָּו֨וּ הַמַּ֜יִם מִתַּ֤חַת הַשָּׁמַ֙יִם֙ אֶל־מָק֣וֹם אֶחָ֔ד וְתֵרָאֶ֖ה הַיַּבָּשָׁ֑ה וַֽיְהִי־כֵֽן׃", 16 | "וַיִּקְרָ֨א אֱלֹהִ֤ים ׀ לַיַּבָּשָׁה֙ אֶ֔רֶץ וּלְמִקְוֵ֥ה הַמַּ֖יִם קָרָ֣א יַמִּ֑ים וַיַּ֥רְא אֱלֹהִ֖ים כִּי־טֽוֹב׃", 17 | "וַיֹּ֣אמֶר אֱלֹהִ֗ים תַּֽדְשֵׁ֤א הָאָ֙רֶץ֙ דֶּ֔שֶׁא עֵ֚שֶׂב מַזְרִ֣יעַ זֶ֔רַע עֵ֣ץ פְּרִ֞י עֹ֤שֶׂה פְּרִי֙ לְמִינ֔וֹ אֲשֶׁ֥ר זַרְעוֹ־ב֖וֹ עַל־הָאָ֑רֶץ וַֽיְהִי־כֵֽן׃", 18 | "וַתּוֹצֵ֨א הָאָ֜רֶץ דֶּ֠שֶׁא עֵ֣שֶׂב מַזְרִ֤יעַ זֶ֙רַע֙ לְמִינֵ֔הוּ וְעֵ֧ץ עֹֽשֶׂה־פְּרִ֛י אֲשֶׁ֥ר זַרְעוֹ־ב֖וֹ לְמִינֵ֑הוּ וַיַּ֥רְא אֱלֹהִ֖ים כִּי־טֽוֹב׃", 19 | "וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם שְׁלִישִֽׁי׃", 20 | "וַיֹּ֣אמֶר אֱלֹהִ֗ים יְהִ֤י מְאֹרֹת֙ בִּרְקִ֣יעַ הַשָּׁמַ֔יִם לְהַבְדִּ֕יל בֵּ֥ין הַיּ֖וֹם וּבֵ֣ין הַלָּ֑יְלָה וְהָי֤וּ לְאֹתֹת֙ וּלְמ֣וֹעֲדִ֔ים וּלְיָמִ֖ים וְשָׁנִֽים׃", 21 | "וְהָי֤וּ לִמְאוֹרֹת֙ בִּרְקִ֣יעַ הַשָּׁמַ֔יִם לְהָאִ֖יר עַל־הָאָ֑רֶץ וַֽיְהִי־כֵֽן׃", 22 | "וַיַּ֣עַשׂ אֱלֹהִ֔ים אֶת־שְׁנֵ֥י הַמְּאֹרֹ֖ת הַגְּדֹלִ֑ים אֶת־הַמָּא֤וֹר הַגָּדֹל֙ לְמֶמְשֶׁ֣לֶת הַיּ֔וֹם וְאֶת־הַמָּא֤וֹר הַקָּטֹן֙ לְמֶמְשֶׁ֣לֶת הַלַּ֔יְלָה וְאֵ֖ת הַכּוֹכָבִֽים׃", 23 | "וַיִּתֵּ֥ן אֹתָ֛ם אֱלֹהִ֖ים בִּרְקִ֣יעַ הַשָּׁמָ֑יִם לְהָאִ֖יר עַל־הָאָֽרֶץ׃", 24 | "וְלִמְשֹׁל֙ בַּיּ֣וֹם וּבַלַּ֔יְלָה וּֽלֲהַבְדִּ֔יל בֵּ֥ין הָא֖וֹר וּבֵ֣ין הַחֹ֑שֶׁךְ וַיַּ֥רְא אֱלֹהִ֖ים כִּי־טֽוֹב׃", 25 | "וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם רְבִיעִֽי׃", 26 | "וַיֹּ֣אמֶר אֱלֹהִ֔ים יִשְׁרְצ֣וּ הַמַּ֔יִם שֶׁ֖רֶץ נֶ֣פֶשׁ חַיָּ֑ה וְעוֹף֙ יְעוֹפֵ֣ף עַל־הָאָ֔רֶץ עַל־פְּנֵ֖י רְקִ֥יעַ הַשָּׁמָֽיִם׃", 27 | "וַיִּבְרָ֣א אֱלֹהִ֔ים אֶת־הַתַּנִּינִ֖ם הַגְּדֹלִ֑ים וְאֵ֣ת כָּל־נֶ֣פֶשׁ הַֽחַיָּ֣ה ׀ הָֽרֹמֶ֡שֶׂת אֲשֶׁר֩ שָׁרְצ֨וּ הַמַּ֜יִם לְמִֽינֵהֶ֗ם וְאֵ֨ת כָּל־ע֤וֹף כָּנָף֙ לְמִינֵ֔הוּ וַיַּ֥רְא אֱלֹהִ֖ים כִּי־טֽוֹב׃", 28 | "וַיְבָ֧רֶךְ אֹתָ֛ם אֱלֹהִ֖ים לֵאמֹ֑ר פְּר֣וּ וּרְב֗וּ וּמִלְא֤וּ אֶת־הַמַּ֙יִם֙ בַּיַּמִּ֔ים וְהָע֖וֹף יִ֥רֶב בָּאָֽרֶץ׃", 29 | "וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם חֲמִישִֽׁי׃", 30 | "וַיֹּ֣אמֶר אֱלֹהִ֗ים תּוֹצֵ֨א הָאָ֜רֶץ נֶ֤פֶשׁ חַיָּה֙ לְמִינָ֔הּ בְּהֵמָ֥ה וָרֶ֛מֶשׂ וְחַֽיְתוֹ־אֶ֖רֶץ לְמִינָ֑הּ וַֽיְהִי־כֵֽן׃", 31 | "וַיַּ֣עַשׂ אֱלֹהִים֩ אֶת־חַיַּ֨ת הָאָ֜רֶץ לְמִינָ֗הּ וְאֶת־הַבְּהֵמָה֙ לְמִינָ֔הּ וְאֵ֛ת כָּל־רֶ֥מֶשׂ הָֽאֲדָמָ֖ה לְמִינֵ֑הוּ וַיַּ֥רְא אֱלֹהִ֖ים כִּי־טֽוֹב׃", 32 | "וַיֹּ֣אמֶר אֱלֹהִ֔ים נַֽעֲשֶׂ֥ה אָדָ֛ם בְּצַלְמֵ֖נוּ כִּדְמוּתֵ֑נוּ וְיִרְדּוּ֩ בִדְגַ֨ת הַיָּ֜ם וּבְע֣וֹף הַשָּׁמַ֗יִם וּבַבְּהֵמָה֙ וּבְכָל־הָאָ֔רֶץ וּבְכָל־הָרֶ֖מֶשׂ הָֽרֹמֵ֥שׂ עַל־הָאָֽרֶץ׃", 33 | "וַיִּבְרָ֨א אֱלֹהִ֤ים ׀ אֶת־הָֽאָדָם֙ בְּצַלְמ֔וֹ בְּצֶ֥לֶם אֱלֹהִ֖ים בָּרָ֣א אֹת֑וֹ זָכָ֥ר וּנְקֵבָ֖ה בָּרָ֥א אֹתָֽם׃", 34 | "וַיְבָ֣רֶךְ אֹתָם֮ אֱלֹהִים֒ וַיֹּ֨אמֶר לָהֶ֜ם אֱלֹהִ֗ים פְּר֥וּ וּרְב֛וּ וּמִלְא֥וּ אֶת־הָאָ֖רֶץ וְכִבְשֻׁ֑הָ וּרְד֞וּ בִּדְגַ֤ת הַיָּם֙ וּבְע֣וֹף הַשָּׁמַ֔יִם וּבְכָל־חַיָּ֖ה הָֽרֹמֶ֥שֶׂת עַל־הָאָֽרֶץ׃", 35 | "וַיֹּ֣אמֶר אֱלֹהִ֗ים הִנֵּה֩ נָתַ֨תִּי לָכֶ֜ם אֶת־כָּל־עֵ֣שֶׂב ׀ זֹרֵ֣עַ זֶ֗רַע אֲשֶׁר֙ עַל־פְּנֵ֣י כָל־הָאָ֔רֶץ וְאֶת־כָּל־הָעֵ֛ץ אֲשֶׁר־בּ֥וֹ פְרִי־עֵ֖ץ זֹרֵ֣עַ זָ֑רַע לָכֶ֥ם יִֽהְיֶ֖ה לְאָכְלָֽה׃", 36 | "וּֽלְכָל־חַיַּ֣ת הָ֠אָרֶץ וּלְכָל־ע֨וֹף הַשָּׁמַ֜יִם וּלְכֹ֣ל ׀ רוֹמֵ֣שׂ עַל־הָאָ֗רֶץ אֲשֶׁר־בּוֹ֙ נֶ֣פֶשׁ חַיָּ֔ה אֶת־כָּל־יֶ֥רֶק עֵ֖שֶׂב לְאָכְלָ֑ה וַֽיְהִי־כֵֽן׃", 37 | "וַיַּ֤רְא אֱלֹהִים֙ אֶת־כָּל־אֲשֶׁ֣ר עָשָׂ֔ה וְהִנֵּה־ט֖וֹב מְאֹ֑ד וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם הַשִּׁשִּֽׁי׃", 38 | ] 39 | 40 | nikkud = [ 41 | "בְּרֵאשִׁית בָּרָא אֱלֹהִים אֵת הַשָּׁמַיִם וְאֵת הָאָרֶץ׃", 42 | "וְהָאָרֶץ הָיְתָה תֹהוּ וָבֹהוּ וְחֹשֶׁךְ עַל־פְּנֵי תְהוֹם וְרוּחַ אֱלֹהִים מְרַחֶפֶת עַל־פְּנֵי הַמָּיִם׃", 43 | "וַיֹּאמֶר אֱלֹהִים יְהִי אוֹר וַיְהִי־אוֹר׃", 44 | "וַיַּרְא אֱלֹהִים אֶת־הָאוֹר כִּי־טוֹב וַיַּבְדֵּל אֱלֹהִים בֵּין הָאוֹר וּבֵין הַחֹשֶׁךְ׃", 45 | "וַיִּקְרָא אֱלֹהִים לָאוֹר יוֹם וְלַחֹשֶׁךְ קָרָא לָיְלָה וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם אֶחָד׃", 46 | "וַיֹּאמֶר אֱלֹהִים יְהִי רָקִיעַ בְּתוֹךְ הַמָּיִם וִיהִי מַבְדִּיל בֵּין מַיִם לָמָיִם׃", 47 | "וַיַּעַשׂ אֱלֹהִים אֶת־הָרָקִיעַ וַיַּבְדֵּל בֵּין הַמַּיִם אֲשֶׁר מִתַּחַת לָרָקִיעַ וּבֵין הַמַּיִם אֲשֶׁר מֵעַל לָרָקִיעַ וַיְהִי־כֵן׃", 48 | "וַיִּקְרָא אֱלֹהִים לָרָקִיעַ שָׁמָיִם וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם שֵׁנִי׃", 49 | "וַיֹּאמֶר אֱלֹהִים יִקָּווּ הַמַּיִם מִתַּחַת הַשָּׁמַיִם אֶל־מָקוֹם אֶחָד וְתֵרָאֶה הַיַּבָּשָׁה וַיְהִי־כֵן׃", 50 | "וַיִּקְרָא אֱלֹהִים לַיַּבָּשָׁה אֶרֶץ וּלְמִקְוֵה הַמַּיִם קָרָא יַמִּים וַיַּרְא אֱלֹהִים כִּי־טוֹב׃", 51 | "וַיֹּאמֶר אֱלֹהִים תַּדְשֵׁא הָאָרֶץ דֶּשֶׁא עֵשֶׂב מַזְרִיעַ זֶרַע עֵץ פְּרִי עֹשֶׂה פְּרִי לְמִינוֹ אֲשֶׁר זַרְעוֹ־בוֹ עַל־הָאָרֶץ וַיְהִי־כֵן׃", 52 | "וַתּוֹצֵא הָאָרֶץ דֶּשֶׁא עֵשֶׂב מַזְרִיעַ זֶרַע לְמִינֵהוּ וְעֵץ עֹשֶׂה־פְּרִי אֲשֶׁר זַרְעוֹ־בוֹ לְמִינֵהוּ וַיַּרְא אֱלֹהִים כִּי־טוֹב׃", 53 | "וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם שְׁלִישִׁי׃", 54 | "וַיֹּאמֶר אֱלֹהִים יְהִי מְאֹרֹת בִּרְקִיעַ הַשָּׁמַיִם לְהַבְדִּיל בֵּין הַיּוֹם וּבֵין הַלָּיְלָה וְהָיוּ לְאֹתֹת וּלְמוֹעֲדִים וּלְיָמִים וְשָׁנִים׃", 55 | "וְהָיוּ לִמְאוֹרֹת בִּרְקִיעַ הַשָּׁמַיִם לְהָאִיר עַל־הָאָרֶץ וַיְהִי־כֵן׃", 56 | "וַיַּעַשׂ אֱלֹהִים אֶת־שְׁנֵי הַמְּאֹרֹת הַגְּדֹלִים אֶת־הַמָּאוֹר הַגָּדֹל לְמֶמְשֶׁלֶת הַיּוֹם וְאֶת־הַמָּאוֹר הַקָּטֹן לְמֶמְשֶׁלֶת הַלַּיְלָה וְאֵת הַכּוֹכָבִים׃", 57 | "וַיִּתֵּן אֹתָם אֱלֹהִים בִּרְקִיעַ הַשָּׁמָיִם לְהָאִיר עַל־הָאָרֶץ׃", 58 | "וְלִמְשֹׁל בַּיּוֹם וּבַלַּיְלָה וּלֲהַבְדִּיל בֵּין הָאוֹר וּבֵין הַחֹשֶׁךְ וַיַּרְא אֱלֹהִים כִּי־טוֹב׃", 59 | "וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם רְבִיעִי׃", 60 | "וַיֹּאמֶר אֱלֹהִים יִשְׁרְצוּ הַמַּיִם שֶׁרֶץ נֶפֶשׁ חַיָּה וְעוֹף יְעוֹפֵף עַל־הָאָרֶץ עַל־פְּנֵי רְקִיעַ הַשָּׁמָיִם׃", 61 | "וַיִּבְרָא אֱלֹהִים אֶת־הַתַּנִּינִם הַגְּדֹלִים וְאֵת כָּל־נֶפֶשׁ הַחַיָּה הָרֹמֶשֶׂת אֲשֶׁר שָׁרְצוּ הַמַּיִם לְמִינֵהֶם וְאֵת כָּל־עוֹף כָּנָף לְמִינֵהוּ וַיַּרְא אֱלֹהִים כִּי־טוֹב׃", 62 | "וַיְבָרֶךְ אֹתָם אֱלֹהִים לֵאמֹר פְּרוּ וּרְבוּ וּמִלְאוּ אֶת־הַמַּיִם בַּיַּמִּים וְהָעוֹף יִרֶב בָּאָרֶץ׃", 63 | "וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם חֲמִישִׁי׃", 64 | "וַיֹּאמֶר אֱלֹהִים תּוֹצֵא הָאָרֶץ נֶפֶשׁ חַיָּה לְמִינָהּ בְּהֵמָה וָרֶמֶשׂ וְחַיְתוֹ־אֶרֶץ לְמִינָהּ וַיְהִי־כֵן׃", 65 | "וַיַּעַשׂ אֱלֹהִים אֶת־חַיַּת הָאָרֶץ לְמִינָהּ וְאֶת־הַבְּהֵמָה לְמִינָהּ וְאֵת כָּל־רֶמֶשׂ הָאֲדָמָה לְמִינֵהוּ וַיַּרְא אֱלֹהִים כִּי־טוֹב׃", 66 | "וַיֹּאמֶר אֱלֹהִים נַעֲשֶׂה אָדָם בְּצַלְמֵנוּ כִּדְמוּתֵנוּ וְיִרְדּוּ בִדְגַת הַיָּם וּבְעוֹף הַשָּׁמַיִם וּבַבְּהֵמָה וּבְכָל־הָאָרֶץ וּבְכָל־הָרֶמֶשׂ הָרֹמֵשׂ עַל־הָאָרֶץ׃", 67 | "וַיִּבְרָא אֱלֹהִים אֶת־הָאָדָם בְּצַלְמוֹ בְּצֶלֶם אֱלֹהִים בָּרָא אֹתוֹ זָכָר וּנְקֵבָה בָּרָא אֹתָם׃", 68 | "וַיְבָרֶךְ אֹתָם אֱלֹהִים וַיֹּאמֶר לָהֶם אֱלֹהִים פְּרוּ וּרְבוּ וּמִלְאוּ אֶת־הָאָרֶץ וְכִבְשֻׁהָ וּרְדוּ בִּדְגַת הַיָּם וּבְעוֹף הַשָּׁמַיִם וּבְכָל־חַיָּה הָרֹמֶשֶׂת עַל־הָאָרֶץ׃", 69 | "וַיֹּאמֶר אֱלֹהִים הִנֵּה נָתַתִּי לָכֶם אֶת־כָּל־עֵשֶׂב זֹרֵעַ זֶרַע אֲשֶׁר עַל־פְּנֵי כָל־הָאָרֶץ וְאֶת־כָּל־הָעֵץ אֲשֶׁר־בּוֹ פְרִי־עֵץ זֹרֵעַ זָרַע לָכֶם יִהְיֶה לְאָכְלָה׃", 70 | "וּלְכָל־חַיַּת הָאָרֶץ וּלְכָל־עוֹף הַשָּׁמַיִם וּלְכֹל רוֹמֵשׂ עַל־הָאָרֶץ אֲשֶׁר־בּוֹ נֶפֶשׁ חַיָּה אֶת־כָּל־יֶרֶק עֵשֶׂב לְאָכְלָה וַיְהִי־כֵן׃", 71 | "וַיַּרְא אֱלֹהִים אֶת־כָּל־אֲשֶׁר עָשָׂה וְהִנֵּה־טוֹב מְאֹד וַיְהִי־עֶרֶב וַיְהִי־בֹקֶר יוֹם הַשִּׁשִּׁי׃", 72 | ] 73 | 74 | text_only = [ 75 | "בראשית ברא אלהים את השמים ואת הארץ", 76 | "והארץ היתה תהו ובהו וחשך על־פני תהום ורוח אלהים מרחפת על־פני המים", 77 | "ויאמר אלהים יהי אור ויהי־אור", 78 | "וירא אלהים את־האור כי־טוב ויבדל אלהים בין האור ובין החשך", 79 | "ויקרא אלהים לאור יום ולחשך קרא לילה ויהי־ערב ויהי־בקר יום אחד", 80 | "ויאמר אלהים יהי רקיע בתוך המים ויהי מבדיל בין מים למים", 81 | "ויעש אלהים את־הרקיע ויבדל בין המים אשר מתחת לרקיע ובין המים אשר מעל לרקיע ויהי־כן", 82 | "ויקרא אלהים לרקיע שמים ויהי־ערב ויהי־בקר יום שני", 83 | "ויאמר אלהים יקוו המים מתחת השמים אל־מקום אחד ותראה היבשה ויהי־כן", 84 | "ויקרא אלהים ליבשה ארץ ולמקוה המים קרא ימים וירא אלהים כי־טוב", 85 | "ויאמר אלהים תדשא הארץ דשא עשב מזריע זרע עץ פרי עשה פרי למינו אשר זרעו־בו על־הארץ ויהי־כן", 86 | "ותוצא הארץ דשא עשב מזריע זרע למינהו ועץ עשה־פרי אשר זרעו־בו למינהו וירא אלהים כי־טוב", 87 | "ויהי־ערב ויהי־בקר יום שלישי", 88 | "ויאמר אלהים יהי מארת ברקיע השמים להבדיל בין היום ובין הלילה והיו לאתת ולמועדים ולימים ושנים", 89 | "והיו למאורת ברקיע השמים להאיר על־הארץ ויהי־כן", 90 | "ויעש אלהים את־שני המארת הגדלים את־המאור הגדל לממשלת היום ואת־המאור הקטן לממשלת הלילה ואת הכוכבים", 91 | "ויתן אתם אלהים ברקיע השמים להאיר על־הארץ", 92 | "ולמשל ביום ובלילה ולהבדיל בין האור ובין החשך וירא אלהים כי־טוב", 93 | "ויהי־ערב ויהי־בקר יום רביעי", 94 | "ויאמר אלהים ישרצו המים שרץ נפש חיה ועוף יעופף על־הארץ על־פני רקיע השמים", 95 | "ויברא אלהים את־התנינם הגדלים ואת כל־נפש החיה הרמשת אשר שרצו המים למינהם ואת כל־עוף כנף למינהו וירא אלהים כי־טוב", 96 | "ויברך אתם אלהים לאמר פרו ורבו ומלאו את־המים בימים והעוף ירב בארץ", 97 | "ויהי־ערב ויהי־בקר יום חמישי", 98 | "ויאמר אלהים תוצא הארץ נפש חיה למינה בהמה ורמש וחיתו־ארץ למינה ויהי־כן", 99 | "ויעש אלהים את־חית הארץ למינה ואת־הבהמה למינה ואת כל־רמש האדמה למינהו וירא אלהים כי־טוב", 100 | "ויאמר אלהים נעשה אדם בצלמנו כדמותנו וירדו בדגת הים ובעוף השמים ובבהמה ובכל־הארץ ובכל־הרמש הרמש על־הארץ", 101 | "ויברא אלהים את־האדם בצלמו בצלם אלהים ברא אתו זכר ונקבה ברא אתם", 102 | "ויברך אתם אלהים ויאמר להם אלהים פרו ורבו ומלאו את־הארץ וכבשה ורדו בדגת הים ובעוף השמים ובכל־חיה הרמשת על־הארץ", 103 | "ויאמר אלהים הנה נתתי לכם את־כל־עשב זרע זרע אשר על־פני כל־הארץ ואת־כל־העץ אשר־בו פרי־עץ זרע זרע לכם יהיה לאכלה", 104 | "ולכל־חית הארץ ולכל־עוף השמים ולכל רומש על־הארץ אשר־בו נפש חיה את־כל־ירק עשב לאכלה ויהי־כן", 105 | "וירא אלהים את־כל־אשר עשה והנה־טוב מאד ויהי־ערב ויהי־בקר יום הששי", 106 | ] 107 | 108 | 109 | def test_str(): 110 | hs = Hebrew("בְּרֵאשִׁ֖ית") 111 | assert hs.__str__() == "בְּרֵאשִׁ֖ית" 112 | 113 | 114 | def test_repr(): 115 | hs = Hebrew("בְּרֵאשִׁ֖ית") 116 | assert hs.__repr__() == "בְּרֵאשִׁ֖ית" 117 | 118 | 119 | @pytest.mark.parametrize("pasuk", [(p) for p in taamei_hamikra]) 120 | def test_as_str(pasuk): 121 | hs = Hebrew(pasuk) 122 | assert hs.string == pasuk 123 | 124 | 125 | @pytest.mark.parametrize("pasuk", [(p) for p in taamei_hamikra]) 126 | def test_no_maqaf(pasuk): 127 | assert Hebrew(pasuk).no_maqaf().string == pasuk.replace(MAQAF.char, " ") 128 | 129 | 130 | @pytest.mark.parametrize("pasuk", [(p) for p in taamei_hamikra]) 131 | def test_no_sof_passuk(pasuk): 132 | assert Hebrew(pasuk).no_sof_passuk().string == pasuk.replace(SOF_PASSUK.char, "") 133 | 134 | 135 | @pytest.mark.parametrize( 136 | "pasuk,pasuk_text_only", [p for p in zip(taamei_hamikra, text_only)] 137 | ) 138 | def test_text_only(pasuk, pasuk_text_only): 139 | hs = Hebrew(pasuk) 140 | assert hs.text_only(remove_maqaf=False).string == pasuk_text_only 141 | assert hs.text_only(remove_maqaf=True).string == pasuk_text_only.replace( 142 | MAQAF.char, " " 143 | ) 144 | 145 | 146 | def test_text_only_with_other_chars(): 147 | hs = Hebrew( 148 | "In the beginning of this text is english followed by בְּרֵאשִׁ֖ית\tCool, eh? 😊" 149 | ) 150 | assert ( 151 | hs.text_only().string 152 | == "In the beginning of this text is english followed by בראשית\tCool, eh? 😊" 153 | ) 154 | 155 | 156 | def test_words(): 157 | pasuk = Hebrew(taamei_hamikra[1]) 158 | assert len(pasuk.words(split_maqaf=False)) == 12 159 | assert len(pasuk.words(split_maqaf=True)) == 14 160 | 161 | 162 | def test_no_niqqud(): 163 | hs = Hebrew("וַֽיְהִי־עֶ֥רֶב וַֽיְהִי־בֹ֖קֶר י֥וֹם רְבִיעִֽי׃") 164 | assert hs.no_niqqud().string == "וֽיהי־ע֥רב וֽיהי־ב֖קר י֥ום רביעֽי׃" 165 | 166 | 167 | def test_no_taamim(): 168 | hs = Hebrew(taamei_hamikra[1]) 169 | assert hs.no_taamim(remove_maqaf=False, remove_sof_passuk=False).string == nikkud[1] 170 | assert hs.no_taamim(remove_maqaf=False, remove_sof_passuk=True).string == nikkud[ 171 | 1 172 | ].replace(SOF_PASSUK.char, "") 173 | assert hs.no_taamim(remove_maqaf=True, remove_sof_passuk=False).string == nikkud[ 174 | 1 175 | ].replace(MAQAF.char, " ") 176 | 177 | 178 | def test_normalize_single_char(): 179 | assert Hebrew("ℵ").normalize().string == "א" 180 | assert Hebrew("ℶ").normalize().string == "ב" 181 | assert Hebrew("ℷ").normalize().string == "ג" 182 | assert Hebrew("ℸ").normalize().string == "ד" 183 | assert Hebrew("יִ").normalize().string == "יִ" 184 | assert Hebrew("ﬠ").normalize().string == "ע" 185 | assert Hebrew("ﬡ").normalize().string == "א" 186 | assert Hebrew("ﬢ").normalize().string == "ד" 187 | assert Hebrew("ﬣ").normalize().string == "ה" 188 | assert Hebrew("ﬤ").normalize().string == "כ" 189 | assert Hebrew("ﬥ").normalize().string == "ל" 190 | assert Hebrew("ﬦ").normalize().string == "ם" 191 | assert Hebrew("ﬧ").normalize().string == "ר" 192 | assert Hebrew("ﬨ").normalize().string == "ת" 193 | assert Hebrew("שׁ").normalize().string == "שׁ" 194 | assert Hebrew("שׂ").normalize().string == "שׂ" 195 | assert Hebrew("שּׁ").normalize().string == "שּׁ" 196 | assert Hebrew("אַ").normalize().string == "אַ" 197 | assert Hebrew("אָ").normalize().string == "אָ" 198 | assert Hebrew("אּ").normalize().string == "אּ" 199 | assert Hebrew("בּ").normalize().string == "בּ" 200 | assert Hebrew("גּ").normalize().string == "גּ" 201 | assert Hebrew("דּ").normalize().string == "דּ" 202 | assert Hebrew("הּ").normalize().string == "הּ" 203 | assert Hebrew("וּ").normalize().string == "וּ" 204 | assert Hebrew("זּ").normalize().string == "זּ" 205 | assert Hebrew("טּ").normalize().string == "טּ" 206 | assert Hebrew("יּ").normalize().string == "יּ" 207 | assert Hebrew("ךּ").normalize().string == "ךּ" 208 | assert Hebrew("כּ").normalize().string == "כּ" 209 | assert Hebrew("לּ").normalize().string == "לּ" 210 | assert Hebrew("מּ").normalize().string == "מּ" 211 | assert Hebrew("נּ").normalize().string == "נּ" 212 | assert Hebrew("סּ").normalize().string == "סּ" 213 | assert Hebrew("ףּ").normalize().string == "ףּ" 214 | assert Hebrew("פּ").normalize().string == "פּ" 215 | assert Hebrew("צּ").normalize().string == "צּ" 216 | assert Hebrew("קּ").normalize().string == "קּ" 217 | assert Hebrew("רּ").normalize().string == "רּ" 218 | assert Hebrew("שּ").normalize().string == "שּ" 219 | assert Hebrew("תּ").normalize().string == "תּ" 220 | assert Hebrew("וֹ").normalize().string == "וֹ" 221 | assert Hebrew("בֿ").normalize().string == "בֿ" 222 | assert Hebrew("כֿ").normalize().string == "כֿ" 223 | assert Hebrew("פֿ").normalize().string == "פֿ" 224 | assert Hebrew("ﭏ").normalize().string == "אל" 225 | 226 | 227 | def test_normalize_yiddish_char(): 228 | assert Hebrew("ײַ").normalize(True).string == "יַי" 229 | assert Hebrew("ײ").normalize(True).string == "יי" 230 | assert Hebrew("װ").normalize(True).string == "וו" 231 | assert Hebrew("ױ").normalize(True).string == "יו" 232 | assert Hebrew("ײַ").normalize().string == "ײַ" 233 | assert Hebrew("ײ").normalize().string == "ײ" 234 | assert Hebrew("װ").normalize().string == "װ" 235 | assert Hebrew("ױ").normalize().string == "ױ" 236 | 237 | 238 | def test_normalize_multiple_abnormal_chars(): 239 | assert Hebrew("זּטּ").normalize().string == "זּטּ" 240 | 241 | 242 | def test_normalize_mixed_chars(): 243 | assert Hebrew("אזּטּ").normalize().string == "אזּטּ" 244 | -------------------------------------------------------------------------------- /hebrew/chars.py: -------------------------------------------------------------------------------- 1 | """ 2 | Constants for each Hebrew character and classes to represent them, and metadata about them. 3 | """ 4 | 5 | from dataclasses import dataclass 6 | from typing import Optional, List, Dict, Union 7 | 8 | from hebrew.gematria import ( 9 | MISPAR_HECHRACHI, 10 | MISPAR_GADOL, 11 | MISPAR_KATAN, 12 | MISPAR_SIDURI, 13 | MISPAR_PERATI, 14 | ATBASH, 15 | ALBAM, 16 | MISPAR_MESHULASH, 17 | MISPAR_KIDMI, 18 | MISPAR_MISPARI, 19 | AYAK_BACHAR, 20 | OFANIM, 21 | ACHAS_BETA, 22 | AVGAD, 23 | REVERSE_AVGAD, 24 | ) 25 | 26 | 27 | # TODO: Future properties: 28 | # - Number/order of the char in aleph bes if the letter is HebrewCharTypes.Letter. 29 | # - Maybe a reference to a minor/final letter when applicable. 30 | # - Gematria value of the letter for future use in `Hebrew` methods such as 31 | # `Hebrew.get_gematria_value(type=Gematria.MisparGadol)`. 32 | # - This is a bit tricky because the gematria value of a letter is not a single value, there are different values 33 | # used by different systems. 34 | @dataclass 35 | class BaseHebrewChar: 36 | """ 37 | Base class with the metadata that all Hebrew characters share. 38 | This class should be used internally by `hebrew.Chars` only. 39 | """ 40 | 41 | char: str 42 | """Unicode character(s) for this class instance.""" 43 | 44 | name: str 45 | """Primary name of the character in English.""" 46 | 47 | hebrew_name: Optional[str] = None 48 | """ 49 | Primary name of the character in Hebrew. 50 | 51 | The choice of primary name is non trivial as it is used as the primary spelling 52 | for the Mispar Shemi Gematria method. 53 | """ 54 | 55 | name_alts: Optional[List[str]] = None 56 | """Alternative names of the character in English.""" 57 | 58 | hebrew_name_alts: Optional[List[str]] = None 59 | """Alternative names of the character in Hebrew.""" 60 | 61 | @property 62 | def hebrew_names(self) -> List[str]: 63 | """ 64 | All Hebrew names for this character. 65 | :return: A list of all Hebrew names for this character made up of the `hebrew_name` and `hebrew_name_alts`. 66 | """ 67 | return [self.hebrew_name] + (self.hebrew_name_alts or []) 68 | 69 | @property 70 | def names(self) -> List[str]: 71 | """ 72 | All english names for this character. 73 | :return: A list of all english names for this character made up of the `name` and `name_alts`. 74 | """ 75 | return [self.name] + (self.name_alts or []) 76 | 77 | def __str__(self): 78 | return self.char 79 | 80 | 81 | @dataclass 82 | class HebrewChar(BaseHebrewChar): 83 | """ 84 | A class representing characters that are part of the Hebrew alphabet (to the exclusion of Nekuds, etc). 85 | """ 86 | 87 | final_letter: bool = False 88 | """Whether or not the letter is a "final" or "Sofit" letter.""" 89 | 90 | @property 91 | def base_letter(self) -> "HebrewChar": 92 | """ 93 | Returns the base letter of the character. 94 | 95 | This library provides HebrewChar values for both standard Hebrew letters and user-perceived letters such as "בּ". 96 | This property will always return the base letter of the HebrewChar instance, in the above example, "ב". 97 | 98 | :return: An instance of `HebrewChar` representing a single unicode character; the base letter of 99 | this instance of `HebrewChar`. 100 | """ 101 | return CHARS[self.char[0]] 102 | 103 | @property 104 | def mispar_hechrachi(self) -> int: 105 | """ 106 | :return: The value of the character for use in the mispar_hechrachi method of gematria. 107 | """ 108 | return MISPAR_HECHRACHI.get(self.base_letter.char) 109 | 110 | @property 111 | def mispar_gadol(self) -> int: 112 | """ 113 | :return: The value of the character for use in the mispar_gadol method of gematria. 114 | """ 115 | return MISPAR_GADOL.get(self.base_letter.char) 116 | 117 | @property 118 | def mispar_siduri(self) -> int: 119 | """ 120 | :return: The value of the character for use in the mispar_siduri method of gematria. 121 | """ 122 | return MISPAR_SIDURI.get(self.base_letter.char) 123 | 124 | @property 125 | def mispar_katan(self) -> int: 126 | """ 127 | :return: The value of the character for use in the mispar_katan method of gematria. 128 | """ 129 | return MISPAR_KATAN.get(self.base_letter.char) 130 | 131 | @property 132 | def mispar_perati(self) -> int: 133 | """ 134 | :return: The value of the character for use in the mispar_perati method of gematria. 135 | """ 136 | return MISPAR_PERATI.get(self.base_letter.char) 137 | 138 | @property 139 | def atbash(self) -> int: 140 | """ 141 | :return: The value of the character for use in the AtBash method of gematria. 142 | """ 143 | return ATBASH.get(self.base_letter.char) 144 | 145 | @property 146 | def albam(self) -> int: 147 | """ 148 | :return: The value of the character for use in the AtBash method of gematria. 149 | """ 150 | return ALBAM.get(self.base_letter.char) 151 | 152 | @property 153 | def mispar_meshulash(self) -> int: 154 | """ 155 | :return: The value of the character for use in the AtBash method of gematria. 156 | """ 157 | return MISPAR_MESHULASH.get(self.base_letter.char) 158 | 159 | @property 160 | def mispar_kidmi(self) -> int: 161 | """ 162 | :return: The value of the character for use in the mispar_kidmi method of gematria. 163 | """ 164 | return MISPAR_KIDMI.get(self.base_letter.char) 165 | 166 | @property 167 | def mispar_mispari(self) -> int: 168 | """ 169 | :return: The value of the character for use in the mispar_mispari method of gematria. 170 | """ 171 | return MISPAR_MISPARI.get(self.base_letter.char) 172 | 173 | @property 174 | def ayak_bachar(self) -> int: 175 | """ 176 | :return: The value of the character for use in the ayak_bachar method of gematria. 177 | """ 178 | return AYAK_BACHAR.get(self.base_letter.char) 179 | 180 | @property 181 | def ofanim(self) -> int: 182 | """ 183 | :return: The value of the character for use in the ofanim method of gematria. 184 | """ 185 | return OFANIM.get(self.base_letter.char) 186 | 187 | @property 188 | def achas_beta(self) -> int: 189 | """ 190 | :return: The value of the character for use in the achas_beta method of gematria. 191 | """ 192 | return ACHAS_BETA.get(self.base_letter.char) 193 | 194 | @property 195 | def avgad(self) -> int: 196 | """ 197 | :return: The value of the character for use in the avgad method of gematria. 198 | """ 199 | return AVGAD.get(self.base_letter.char) 200 | 201 | @property 202 | def reverse_avgad(self) -> int: 203 | """ 204 | :return: The value of the character for use in the reverse_avgad method of gematria. 205 | """ 206 | return REVERSE_AVGAD.get(self.base_letter.char) 207 | 208 | @classmethod 209 | def search(cls, char_name: str) -> Optional["HebrewChar"]: 210 | """ 211 | Searches for an instance of `HebrewChar` by name. 212 | The search input is case insensitive and is compared to `names` list for this search. 213 | 214 | To search for any Hebrew character, use `hebrew.chars.char_search`. 215 | 216 | :param char_name: A single string representing the name of the character to search for. 217 | :return: An instance of `HebrewChar` representing the character with the given name, or `None` if no 218 | character is found. 219 | """ 220 | return char_search(char_name, HEBREW_CHARS) 221 | 222 | def __hash__(self): 223 | return hash(self.char) 224 | 225 | 226 | @dataclass 227 | class YiddishChar(BaseHebrewChar): 228 | """ 229 | A class representing special characters used in Yiddish text. 230 | """ 231 | 232 | @classmethod 233 | def search(cls, char_name: str) -> Optional["YiddishChar"]: 234 | """ 235 | Searches for an instance of `YiddishChar` by name. 236 | The search input is case insensitive and is compared to `names` list for this search. 237 | 238 | To search for any Hebrew character, use `hebrew.chars.char_search`. 239 | 240 | :param char_name: A single string representing the name of the character to search for. 241 | :return: An instance of `YiddishChar` representing the character with the given name, or `None` if no 242 | character is found. 243 | """ 244 | return char_search(char_name, YIDDISH_CHARS) 245 | 246 | def __hash__(self): 247 | return hash(self.char) 248 | 249 | 250 | @dataclass 251 | class NiqqudChar(BaseHebrewChar): 252 | """ 253 | A class representing Niqqud characters used in Hebrew and Yiddish text. 254 | """ 255 | 256 | @classmethod 257 | def search(cls, char_name: str) -> Optional["NiqqudChar"]: 258 | """ 259 | Searches for an instance of `NiqqudChar` by name. 260 | The search input is case insensitive and is compared to `names` list for this search. 261 | 262 | To search for any Hebrew character, use `hebrew.chars.char_search`. 263 | 264 | :param char_name: A single string representing the name of the character to search for. 265 | :return: An instance of `NiqqudChar` representing the character with the given name, or `None` if no 266 | character is found. 267 | """ 268 | return char_search(char_name, NIQQUD_CHARS) 269 | 270 | def __hash__(self): 271 | return hash(self.char) 272 | 273 | 274 | @dataclass 275 | class TaamimChar(BaseHebrewChar): 276 | """ 277 | A class representing the "Trup" or [Hebrew cantillation](https://en.wikipedia.org/wiki/Hebrew_cantillation) 278 | characters used alongside Hebrew letters. 279 | """ 280 | 281 | @classmethod 282 | def search(cls, char_name: str) -> Optional["TaamimChar"]: 283 | """ 284 | Searches for an instance of `TaamimChar` by name. 285 | The search input is case insensitive and is compared to `names` list for this search. 286 | 287 | To search for any Hebrew character, use `hebrew.chars.char_search`. 288 | 289 | :param char_name: A single string representing the name of the character to search for. 290 | :return: An instance of `TaamimChar` representing the character with the given name, or `None` if no 291 | character is found. 292 | """ 293 | return char_search(char_name, TAAMIM_CHARS) 294 | 295 | def __hash__(self): 296 | return hash(self.char) 297 | 298 | 299 | @dataclass 300 | class OtherChar(BaseHebrewChar): 301 | """ 302 | A class representing the "other" or "uncharacterized" characters used in Hebrew (and Yiddish) text. 303 | """ 304 | 305 | @classmethod 306 | def search(cls, char_name: str) -> Optional["OtherChar"]: 307 | """ 308 | Searches for an instance of `TaamimChar` by name. 309 | The search input is case insensitive and is compared to `names` list for this search. 310 | 311 | To search for any Hebrew character, use `hebrew.chars.char_search`. 312 | 313 | :param char_name: A single string representing the name of the character to search for. 314 | :return: An instance of `OtherChar` representing the character with the given name, or `None` if no 315 | character is found. 316 | """ 317 | return char_search(char_name, OTHER_CHARS) 318 | 319 | def __hash__(self): 320 | return hash(self.char) 321 | 322 | 323 | # TODO: 324 | # - Populate the alt hebrew and english names with additional spellings, this is helpful for the 325 | # `HebrewGlyph.search()` method. 326 | # - Add the rest of the hebrew unicode characters as `HebrewChar` instances instead of plain strings` 327 | 328 | 329 | ALEPH = HebrewChar(char="א", name="Aleph", hebrew_name="אָלֶף", name_alts=["Alef"]) 330 | """An instance of `HebrewChar` representing the letter `'א'`""" 331 | 332 | BET = HebrewChar(char="בּ", name="Bet", hebrew_name="בֵּית", hebrew_name_alts=["בת"]) 333 | """ 334 | An instance of `HebrewChar` representing the letter **`'בּ'`**. 335 | *This is not strictly a letter, but is included because it is often treated as one.* 336 | """ 337 | 338 | BES = BET 339 | """Simple pointer to `BET`.""" 340 | 341 | VET = HebrewChar(char="ב", name="Vet", hebrew_name="בֵית", hebrew_name_alts=["בת"]) 342 | """An instance of `HebrewChar` representing the letter **`'ב'`**.""" 343 | 344 | GIMEL = HebrewChar( 345 | char="ג", name="Gimel", hebrew_name="גִימֵל", hebrew_name_alts=["גמל"] 346 | ) 347 | """An instance of `HebrewChar` representing the letter **`'ג'`**.""" 348 | 349 | DALET = HebrewChar( 350 | char="ד", 351 | name="Dalet", 352 | hebrew_name="דָלֶת", 353 | hebrew_name_alts=["דלית"], 354 | name_alts=["Daled"], 355 | ) 356 | """An instance of `HebrewChar` representing the letter **`'ד'`**.""" 357 | 358 | DALED = DALET 359 | """Simple pointer to `DALET`.""" 360 | 361 | HE = HebrewChar( 362 | char="ה", 363 | name="He", 364 | hebrew_name="הֵא", 365 | hebrew_name_alts=["הי", "הה"], 366 | name_alts=["Hei", "Hey"], 367 | ) 368 | """An instance of `HebrewChar` representing the letter **`'ה'`**.""" 369 | 370 | HEI = HEY = HE 371 | """Simple pointer to `HE`.""" 372 | 373 | VAV = HebrewChar( 374 | char="ו", 375 | name="Vav", 376 | hebrew_name="וָו", 377 | hebrew_name_alts=["ויו", "ואו"], 378 | name_alts=["Vuv"], 379 | ) 380 | """An instance of `HebrewChar` representing the letter **`'ו'`**.""" 381 | 382 | VUV = VAV 383 | """Simple pointer to `VAV`.""" 384 | 385 | ZAYIN = HebrewChar(char="ז", name="Zayin", hebrew_name="זַיִן") 386 | """An instance of `HebrewChar` representing the letter **`'ז'`**.""" 387 | 388 | CHET = HebrewChar( 389 | char="ח", 390 | name="Chet", 391 | hebrew_name="חֵית", 392 | hebrew_name_alts=["חת"], 393 | name_alts=["Het", "Ches"], 394 | ) 395 | """An instance of `HebrewChar` representing the letter **`'ז'`**.""" 396 | 397 | HET = CHES = CHET 398 | """Simple pointer to `CHET`.""" 399 | 400 | TET = HebrewChar( 401 | char="ט", name="Tet", hebrew_name="טֵית", hebrew_name_alts=["טת"], name_alts=["Tes"] 402 | ) 403 | """An instance of `HebrewChar` representing the letter **`'ט'`**.""" 404 | 405 | TES = TET 406 | """Simple pointer to `TET`.""" 407 | 408 | YOD = HebrewChar(char="י", name="Yod", hebrew_name="יוֹד", name_alts=["Yud"]) 409 | """An instance of `HebrewChar` representing the letter **`'י'`**.""" 410 | 411 | YUD = YOD 412 | """Simple pointer to `YOD`.""" 413 | 414 | CAF = HebrewChar(char="כּ", name="Kaf", hebrew_name="כַּף") 415 | """ 416 | An instance of `HebrewChar` representing the letter **`'כּ'`**. 417 | *This is not strictly a letter, but is included because it is often treated as one.* 418 | """ 419 | 420 | KAF_SOFIT = HebrewChar( 421 | char="ךּ", 422 | name="Kaf Sofit", 423 | final_letter=True, 424 | hebrew_name="כַּף סוֹפִית", 425 | name_alts=["Final Kaf"], 426 | ) 427 | """ 428 | An instance of `HebrewChar` representing the letter **`'ךּ'`**. 429 | *This is not strictly a letter, but is included because it is often treated as one.* 430 | """ 431 | 432 | FINAL_KAF = KAF_SOFIT 433 | """Simple pointer to `KAF_SOFIT`.""" 434 | 435 | CHAF = HebrewChar(char="כ", name="Chaf", hebrew_name="כַף") 436 | """An instance of `HebrewChar` representing the letter **`'כ'`**.""" 437 | 438 | CHAF_SOFIT = HebrewChar( 439 | char="ך", 440 | name="Chaf Sofit", 441 | final_letter=True, 442 | hebrew_name="כַף סוֹפִית", 443 | name_alts=["Final Chaf"], 444 | ) 445 | """An instance of `HebrewChar` representing the letter **`'ך'`**.""" 446 | 447 | FINAL_CHAF = CHAF_SOFIT 448 | """Simple pointer to `CHAF_SOFIT`.""" 449 | 450 | LAMED = HebrewChar( 451 | char="ל", 452 | name="Lamed", 453 | hebrew_name="לָמֶד", 454 | name_alts=["Lamid"], 455 | ) 456 | """An instance of `HebrewChar` representing the letter **`'ל'`**.""" 457 | 458 | LAMID = LAMED 459 | """Simple pointer to `LAMED`.""" 460 | 461 | MEM = HebrewChar(char="מ", name="Mem", hebrew_name="מֵם") 462 | """An instance of `HebrewChar` representing the letter **`'מ'`**.""" 463 | 464 | MEM_SOFIT = HebrewChar( 465 | char="ם", 466 | name="Mem Sofit", 467 | final_letter=True, 468 | hebrew_name="מֵם סוֹפִית", 469 | name_alts=["Final Mem"], 470 | ) 471 | """An instance of `HebrewChar` representing the letter **`'ם'`**.""" 472 | 473 | FINAL_MEM = MEM_SOFIT 474 | """Simple pointer to `MEM_SOFIT`.""" 475 | 476 | NUN = HebrewChar(char="נ", name="Nun", hebrew_name="נוּן") 477 | """An instance of `HebrewChar` representing the letter **`'נ'`**.""" 478 | 479 | NUN_SOFIT = HebrewChar( 480 | char="ן", 481 | name="Nun Sofit", 482 | final_letter=True, 483 | hebrew_name="נוּן סוֹפִית", 484 | name_alts=["Final Nun"], 485 | ) 486 | """An instance of `HebrewChar` representing the letter **`'ן'`**.""" 487 | 488 | FINAL_NUN = NUN_SOFIT 489 | """Simple pointer to `NUN_SOFIT`.""" 490 | 491 | SAMEKH = HebrewChar( 492 | char="ס", 493 | name="Samekh", 494 | hebrew_name="סָמֶך", 495 | name_alts=["Samach"], 496 | ) 497 | """An instance of `HebrewChar` representing the letter **`'ס'`**.""" 498 | 499 | SAMACH = SAMEKH 500 | """Simple pointer to `SAMEKH`.""" 501 | 502 | AYIN = HebrewChar(char="ע", name="Ayin", hebrew_name="עַיִן") 503 | """An instance of `HebrewChar` representing the letter **`'ע'`**.""" 504 | 505 | PE = HebrewChar(char="פּ", name="Pe", hebrew_name_alts=["פי", "פה"]) 506 | """ 507 | An instance of `HebrewChar` representing the letter **`'פּ'`**. 508 | *This is not strictly a letter, but is included because it is often treated as one.* 509 | """ 510 | 511 | FE = HebrewChar(char="פ", name="Fe", hebrew_name="פֵא", hebrew_name_alts=["פי", "פה"]) 512 | """An instance of `HebrewChar` representing the letter **`'פ'`**.""" 513 | 514 | PE_SOFIT = HebrewChar( 515 | char="ףּ", 516 | name="Fe Sofit", 517 | final_letter=True, 518 | hebrew_name="פֵּא סוֹפִית", 519 | name_alts=["Final Pe"], 520 | ) 521 | """ 522 | An instance of `HebrewChar` representing the letter **`'ףּ'`**. 523 | *This is not strictly a letter, but is included because it is often treated as one.* 524 | """ 525 | 526 | FINAL_PE = PE_SOFIT 527 | """Simple pointer to `PE_SOFIT`.""" 528 | 529 | FE_SOFIT = HebrewChar( 530 | char="ף", 531 | name="Fe Sofit", 532 | final_letter=True, 533 | hebrew_name="פֵא סוֹפִית", 534 | name_alts=["Final Fe"], 535 | ) 536 | """An instance of `HebrewChar` representing the letter **`'ף'`**.""" 537 | 538 | FINAL_FE = FE_SOFIT 539 | """Simple pointer to `FE_SOFIT`.""" 540 | 541 | TSADI = HebrewChar( 542 | char="צ", 543 | name="Tsadi", 544 | hebrew_name="צַדִי", 545 | hebrew_name_alts=["צדיק"], 546 | name_alts=["Tzadik"], 547 | ) 548 | """An instance of `HebrewChar` representing the letter **`'צ'`**.""" 549 | 550 | TZADIK = TSADI 551 | """Simple pointer to `TSADI`.""" 552 | 553 | TSADI_SOFIT = HebrewChar( 554 | char="ץ", 555 | name="Tsadi Sofit", 556 | final_letter=True, 557 | hebrew_name="צַדִי סוֹפִית", 558 | hebrew_name_alts=["צדיק סופית"], 559 | ) 560 | """An instance of `HebrewChar` representing the letter **`'ץ'`**.""" 561 | 562 | FINAL_TSADI = TZADIK_SOFIT = FINAL_TZADIK = TSADI_SOFIT 563 | """Simple pointer to `TSADI_SOFIT`.""" 564 | 565 | QOF = HebrewChar(char="ק", name="Qof", hebrew_name="קוֹף", name_alts=["Kuf"]) 566 | """An instance of `HebrewChar` representing the letter **`'ק'`**.""" 567 | 568 | KUF = QOF 569 | """Simple pointer to `TSADI_SOFIT`.""" 570 | 571 | RESH = HebrewChar(char="ר", name="Resh", hebrew_name="רֵישׁ", hebrew_name_alts=["רש"]) 572 | """An instance of `HebrewChar` representing the letter **`'ר'`**.""" 573 | 574 | # TODO: The naming here might need help. We should definitely support all 3 versions as this is likely to be found 575 | # in text, but the naming might be unexpected. 576 | SHIN = HebrewChar( 577 | char="שׁ", name="Shin", hebrew_name="שִׁן", hebrew_name_alts=["שִׁין"] 578 | ) 579 | """ 580 | An instance of `HebrewChar` representing the letter **`'שׁ'`**. 581 | *This is not strictly a letter, but is included because it is often treated as one.* 582 | """ 583 | 584 | SIN = HebrewChar(char="שׂ", name="Sin", hebrew_name="שִׂן", hebrew_name_alts=["שִׂין"]) 585 | """ 586 | An instance of `HebrewChar` representing the letter **`'שׂ'`**. 587 | *This is not strictly a letter, but is included because it is often treated as one.* 588 | """ 589 | 590 | PLAIN_SIN = HebrewChar( 591 | char="ש", name="Plain Sin", hebrew_name="שִׂן", hebrew_name_alts=["שִׂין"] 592 | ) 593 | """An instance of `HebrewChar` representing the letter **`'ש'`**.""" 594 | 595 | TAV = HebrewChar( 596 | char="תּ", 597 | name="Tav", 598 | hebrew_name="תּו", 599 | hebrew_name_alts=["תיו", "תאו"], 600 | name_alts=["Taf"], 601 | ) 602 | """ 603 | An instance of `HebrewChar` representing the letter **`'תּ'`**. 604 | *This is not strictly a letter, but is included because it is often treated as one.* 605 | """ 606 | 607 | TAF = TAV 608 | """Simple pointer to `TAV`.""" 609 | 610 | SAV = HebrewChar( 611 | char="ת", 612 | name="Sav", 613 | hebrew_name="תָו", 614 | name_alts=["Saf"], 615 | hebrew_name_alts=["תיו", "תאו"], 616 | ) 617 | """An instance of `HebrewChar` representing the letter **`'ת'`**.""" 618 | 619 | ALEPH_SYMBOL = HebrewChar("ℵ", name="Aleph Symbol") 620 | """An instance of `HebrewChar` representing the letter **`'ℵ'`**. This is a rarely used special character.""" 621 | BET_SYMBOL = HebrewChar("ℶ", name="Bet Symbol") 622 | """An instance of `HebrewChar` representing the letter **`'ℶ'`**. This is a rarely used special character.""" 623 | GIMEL_SYMBOL = HebrewChar("ℷ", name="Gimel Symbol") 624 | """An instance of `HebrewChar` representing the letter **`'ℷ'`**. This is a rarely used special character.""" 625 | DALET_SYMBOL = HebrewChar("ℸ", name="Dalet Symbol") 626 | """An instance of `HebrewChar` representing the letter **`'ℸ'`**. This is a rarely used special character.""" 627 | YOD_HIRIQ = HebrewChar("יִ", name="Yod with Hiriq") 628 | """An instance of `HebrewChar` representing the letter **`'יִ'`**. This is a rarely used special character.""" 629 | YOD_YOD_PATAH = YiddishChar("ײַ", name="Yod Yod Patah") 630 | """An instance of `YiddishChar` representing the letter **`'ײַ'`**. This is a rarely used special character.""" 631 | YOD_YOD_PATAH2 = YiddishChar("ײַ", name="Yod Yod Patah") 632 | """An instance of `YiddishChar` representing the letters **`'ײַ'`**. This is a variation of YOD_YOD_PATAH made up of a double Yud, and a Patah.""" 633 | AYIN_ALT = HebrewChar("ﬠ", name="Alternative Ayin") 634 | """An instance of `HebrewChar` representing the letter **`'ﬠ'`**. This is a rarely used special character.""" 635 | ALEF_WIDE = HebrewChar("ﬡ", name="Wide Alef") 636 | """An instance of `HebrewChar` representing the letter **`'ﬡ'`**. This is a rarely used special character.""" 637 | DALET_WIDE = HebrewChar("ﬢ", name="Wide Dalet") 638 | """An instance of `HebrewChar` representing the letter **`'ﬢ'`**. This is a rarely used special character.""" 639 | HE_WIDE = HebrewChar("ﬣ", name="Wide He") 640 | """An instance of `HebrewChar` representing the letter **`'ﬣ'`**. This is a rarely used special character.""" 641 | KAF_WIDE = HebrewChar("ﬤ", name="Wide Kaf") 642 | """An instance of `HebrewChar` representing the letter **`'ﬤ'`**. This is a rarely used special character.""" 643 | LAMED_WIDE = HebrewChar("ﬥ", name="Wide Lamed") 644 | """An instance of `HebrewChar` representing the letter **`'ﬥ'`**. This is a rarely used special character.""" 645 | FINAL_MEM_WIDE = HebrewChar("ﬦ", name="Wide Final Mem") 646 | """An instance of `HebrewChar` representing the letter **`'ﬦ'`**. This is a rarely used special character.""" 647 | RESH_WIDE = HebrewChar("ﬧ", name="Wide Resh") 648 | """An instance of `HebrewChar` representing the letter **`'ﬧ'`**. This is a rarely used special character.""" 649 | TAV_WIDE = HebrewChar("ﬨ", name="Wide Tav") 650 | """An instance of `HebrewChar` representing the letter **`'ﬨ'`**. This is a rarely used special character.""" 651 | SHIN_SHIN_DOT = HebrewChar("שׁ", name="Shin with Shin Dot") 652 | """An instance of `HebrewChar` representing the letter **`'שׁ'`**. This is a rarely used special character.""" 653 | SHIN_SIN_DOT = HebrewChar("שׂ", name="Shin with Sin Dot") 654 | """An instance of `HebrewChar` representing the letter **`'שׂ'`**. This is a rarely used special character.""" 655 | SHIN_DAGESH_SHIN_DOT = HebrewChar("שּׁ", name="Shin with Dagesh and Shin Dot") 656 | """An instance of `HebrewChar` representing the letter **`'שּׁ'`**. This is a rarely used special character.""" 657 | SHIN_DAGESH_SIN_DOT = HebrewChar("שּׂ", name="Shin with Dagesh and Sin Dot") 658 | """An instance of `HebrewChar` representing the letter **`'שּׂ'`**. This is a rarely used special character.""" 659 | ALEF_PATAH = HebrewChar("אַ", name="Alef with Patah") 660 | """An instance of `HebrewChar` representing the letter **`'אַ'`**. This is a rarely used special character.""" 661 | ALEF_QAMATZ = HebrewChar("אָ", name="Alef with Qamats") 662 | """An instance of `HebrewChar` representing the letter **`'אָ'`**. This is a rarely used special character.""" 663 | ALEF_MAPIQ = HebrewChar("אּ", name="Alef with Mapiq") 664 | """An instance of `HebrewChar` representing the letter **`'אּ'`**. This is a rarely used special character.""" 665 | BET_DAGESH = HebrewChar("בּ", name="Bet with Dagesh") 666 | """An instance of `HebrewChar` representing the letter **`'בּ'`**. This is a rarely used special character.""" 667 | GIMEL_DAGESH = HebrewChar("גּ", name="Gimel with Dagesh") 668 | """An instance of `HebrewChar` representing the letter **`'גּ'`**. This is a rarely used special character.""" 669 | DALET_DAGESH = HebrewChar("דּ", name="Dalet with Dagesh") 670 | """An instance of `HebrewChar` representing the letter **`'דּ'`**. This is a rarely used special character.""" 671 | HE_MAPIQ = HebrewChar("הּ", name="He with Mapiq") 672 | """An instance of `HebrewChar` representing the letter **`'הּ'`**. This is a rarely used special character.""" 673 | VAV_DAGESH = HebrewChar("וּ", name="Vav with Dagesh") 674 | """An instance of `HebrewChar` representing the letter **`'וּ'`**. This is a rarely used special character.""" 675 | ZAYIN_DAGESH = HebrewChar("זּ", name="Zayin with Dagesh") 676 | """An instance of `HebrewChar` representing the letter **`'זּ'`**. This is a rarely used special character.""" 677 | TET_DAGESH = HebrewChar("טּ", name="Tet with Dagesh") 678 | """An instance of `HebrewChar` representing the letter **`'טּ'`**. This is a rarely used special character.""" 679 | YOD_DAGESH = HebrewChar("יּ", name="Yod with Dagesh") 680 | """An instance of `HebrewChar` representing the letter **`'יּ'`**. This is a rarely used special character.""" 681 | FINAL_KAF_DAGESH = HebrewChar("ךּ", name="Final Kaf with Dagesh") 682 | """An instance of `HebrewChar` representing the letter **`'ךּ'`**. This is a rarely used special character.""" 683 | KAF_DAGESH = HebrewChar("כּ", name="Kaf with Dagesh") 684 | """An instance of `HebrewChar` representing the letter **`'כּ'`**. This is a rarely used special character.""" 685 | LAMED_DAGESH = HebrewChar("לּ", name="Lamed with Dagesh") 686 | """An instance of `HebrewChar` representing the letter **`'לּ'`**. This is a rarely used special character.""" 687 | MEM_DAGESH = HebrewChar("מּ", name="Mem with Dagesh") 688 | """An instance of `HebrewChar` representing the letter **`'מּ'`**. This is a rarely used special character.""" 689 | NUN_DAGESH = HebrewChar("נּ", name="Nun with Dagesh") 690 | """An instance of `HebrewChar` representing the letter **`'נּ'`**. This is a rarely used special character.""" 691 | SAMEKH_DAGESH = HebrewChar("סּ", name="Samekh with Dagesh") 692 | """An instance of `HebrewChar` representing the letter **`'סּ'`**. This is a rarely used special character.""" 693 | FINAL_PE_DAGESH = HebrewChar("ףּ", name="Final Pe with Dagesh") 694 | """An instance of `HebrewChar` representing the letter **`'ףּ'`**. This is a rarely used special character.""" 695 | PE_DAGESH = HebrewChar("פּ", name="Pe with Dagesh") 696 | """An instance of `HebrewChar` representing the letter **`'פּ'`**. This is a rarely used special character.""" 697 | TSADI_DAGESH = HebrewChar("צּ", name="Tsadi with Dagesh") 698 | """An instance of `HebrewChar` representing the letter **`'צּ'`**. This is a rarely used special character.""" 699 | QOF_DAGESH = HebrewChar("קּ", name="Qof with Dagesh") 700 | """An instance of `HebrewChar` representing the letter **`'קּ'`**. This is a rarely used special character.""" 701 | RESH_DAGESH = HebrewChar("רּ", name="Resh with Dagesh") 702 | """An instance of `HebrewChar` representing the letter **`'רּ'`**. This is a rarely used special character.""" 703 | SHIN_DAGESH = HebrewChar("שּ", name="Shin with Dagesh") 704 | """An instance of `HebrewChar` representing the letter **`'שּ'`**. This is a rarely used special character.""" 705 | TAV_DAGESH = HebrewChar("תּ", name="Tav with Dagesh") 706 | """An instance of `HebrewChar` representing the letter **`'תּ'`**. This is a rarely used special character.""" 707 | VAV_HOLAM = HebrewChar("וֹ", name="Vav with Holam") 708 | """An instance of `HebrewChar` representing the letter **`'וֹ'`**. This is a rarely used special character.""" 709 | BET_RAFE = HebrewChar("בֿ", name="Bet with Rafe") 710 | """An instance of `HebrewChar` representing the letter **`'בֿ'`**. This is a rarely used special character.""" 711 | KAF_RAFE = HebrewChar("כֿ", name="Kaf with Rafe") 712 | """An instance of `HebrewChar` representing the letter **`'כֿ'`**. This is a rarely used special character.""" 713 | PE_RAFE = HebrewChar("פֿ", name="Pe with Rafe") 714 | """An instance of `HebrewChar` representing the letter **`'פֿ'`**. This is a rarely used special character.""" 715 | ALEPH_LAMED = HebrewChar("ﭏ", name="Alef Lamed") 716 | """An instance of `HebrewChar` representing the letter **`'ﭏ'`**. This is a rarely used special character.""" 717 | 718 | SAF = SAV 719 | """Simple pointer to `SAV`.""" 720 | 721 | DOUBLE_YOD = YiddishChar( 722 | char="ײ", 723 | name="Double Yod", 724 | name_alts=["Saf"], 725 | ) 726 | """An instance of `YiddishChar` representing the letter **`'ײ'`**.""" 727 | 728 | DOUBLE_YUD = DOUBLE_YOD 729 | """Simple pointer to `DOUBLE_YOD`.""" 730 | 731 | DOUBLE_VAV = YiddishChar( 732 | char="װ", 733 | name="Double Vav", 734 | name_alts=["Double Vuv"], 735 | ) 736 | """An instance of `YiddishChar` representing the letter **`'װ'`**.""" 737 | 738 | DOUBLE_VUV = DOUBLE_VAV 739 | """Simple pointer to `DOUBLE_VAV`.""" 740 | 741 | VAV_YOD = YiddishChar(char="ױ", name="Vav Yod") 742 | """An instance of `YiddishChar` representing the letter **`'ױ'`**.""" 743 | 744 | VAV_YUD = VUV_YOD = VUV_YUD = VAV_YOD 745 | """Simple pointer to `VAV_YOD`.""" 746 | 747 | YOD_TRIANGLE = HebrewChar(char="ׯ", name="Yod Triangle", name_alts=["Yud Triangle"]) 748 | """An instance of `HebrewChar` representing the letter **`'ׯ'`**.""" 749 | 750 | YUD_TRIANGLE = YOD_TRIANGLE 751 | """Simple pointer to `YOD_TRIANGLE`.""" 752 | 753 | # Niqqudot or Vowel characters 754 | SIN_DOT = NiqqudChar(char="ׂ", name="Sin Dot") 755 | """An instance of `NiqqudChar` representing the Niqqud **`'ׂ'`**.""" 756 | SHIN_DOT = NiqqudChar(char="ׁ", name="Shin Dot") 757 | """An instance of `NiqqudChar` representing the Niqqud **`'ׁ'`**.""" 758 | DAGESH = NiqqudChar(char="ּ", name="Dagesh") 759 | """An instance of `NiqqudChar` representing the Niqqud **`'ּ'`**.""" 760 | QUBUTS = NiqqudChar(char="ֻ", name="Qubuts", name_alts=["Kubutz"]) 761 | """An instance of `NiqqudChar` representing the Niqqud **`'ֻ'`**.""" 762 | KUBUTZ = QUBUTS 763 | """Simple pointer to `QUBUTS`""" 764 | SHURUK = NiqqudChar(char="וּ", name="Shuruk") 765 | """An instance of `NiqqudChar` representing the Niqqud **`'וּ'`**.""" 766 | HOLAM = NiqqudChar(char="ֹ", name="Holam") 767 | """An instance of `NiqqudChar` representing the Niqqud **`'ֹ'`**.""" 768 | QAMATS = NiqqudChar(char="ָ", name="Qamats", name_alts=["Kumatz"]) 769 | """An instance of `NiqqudChar` representing the Niqqud **`'ָ'`**.""" 770 | KUMATZ = QAMATS 771 | """Simple pointer to `QAMATS`""" 772 | QAMATS_KATAN = NiqqudChar(char="ׇ", name="Qamats Qatan", name_alts=["Kumatz Katan"]) 773 | """An instance of `NiqqudChar` representing the Niqqud **`'ׇ'`**.""" 774 | PATAH = NiqqudChar(char="ַ", name="Patah", name_alts=["Patach"]) 775 | """An instance of `NiqqudChar` representing the Niqqud **`'ַ'`**.""" 776 | PATACH = PATAH 777 | """Simple pointer to `PATAH`""" 778 | SEGOL = NiqqudChar(char="ֶ", name="Segol") 779 | """An instance of `NiqqudChar` representing the Niqqud **`'ֶ'`**.""" 780 | TSERE = NiqqudChar(char="ֵ", name="Tsere") 781 | """An instance of `NiqqudChar` representing the Niqqud **`'ֵ'`**.""" 782 | HIRIQ = NiqqudChar(char="ִ", name="Hiriq", name_alts=["Chirik"]) 783 | """An instance of `NiqqudChar` representing the Niqqud **`'ִ'`**.""" 784 | CHIRIK = HIRIQ 785 | """Simple pointer to `HIRIQ`""" 786 | HATAF_QAMATS = NiqqudChar(char="ֳ", name="Hataf Qamatz", name_alts=["Hataf Kumatz"]) 787 | """An instance of `NiqqudChar` representing the Niqqud **`'ֳ'`**.""" 788 | HATAF_PATAH = NiqqudChar(char="ֲ", name="Hataf Patah", name_alts=["Hataf Patach"]) 789 | """An instance of `NiqqudChar` representing the Niqqud **`'ֲ'`**.""" 790 | HATAF_SEGOL = NiqqudChar(char="ֱ", name="Hataf Segol") 791 | """An instance of `NiqqudChar` representing the Niqqud **`'ֱ'`**.""" 792 | SHEVA = NiqqudChar(char="ְ", name="Sheva", name_alts=["Shivah"]) 793 | """An instance of `NiqqudChar` representing the Niqqud **`'ְ'`**.""" 794 | SHIVAH = SHEVA 795 | """Simple pointer to `SHEVA`""" 796 | UPPER_DOT = NiqqudChar(char="ׄ", name="Upper Dot") 797 | """An instance of `NiqqudChar` representing the Niqqud **`'ׄ'`**.""" 798 | HOLAM_HASER = NiqqudChar(char="ֺ", name="Holam Haser") 799 | """An instance of `NiqqudChar` representing the Niqqud **`'ֺ'`**.""" 800 | LOWER_DOT = NiqqudChar(char="ׅ", name="Lower Dot") 801 | """An instance of `NiqqudChar` representing the Niqqud **`'ׅ'`**.""" 802 | 803 | # Other characters 804 | MAQAF = OtherChar(char="־", name="Maqaf") 805 | """An instance of `TaamimChar` representing the character **`'־'`**.""" 806 | PASEQ = OtherChar(char="׀", name="Paseq") 807 | """An instance of `TaamimChar` representing the character **`'׀'`**.""" 808 | SOF_PASSUK = OtherChar(char="׃", name="Sof Passuk") 809 | """An instance of `TaamimChar` representing the character **`'׃'`**.""" 810 | GERSHAYIM = OtherChar(char="״", name="Gershayim") 811 | """An instance of `OtherChar` representing the character **`'״'`**.""" 812 | GERESH = OtherChar(char="׳", name="Geresh") 813 | """An instance of `OtherChar` representing the character **`'׳'`**.""" 814 | ALTERNATIVE_PLUS_SIGN = OtherChar(char="﬩", name="Alternative Plus Sign") 815 | """An instance of `OtherChar` representing the character **`'﬩'`**.""" 816 | INVERTED_NUN = OtherChar( 817 | char="׆", name="Inverted Nun", hebrew_name='נו"ן מנוזרת', name_alts=["Nun Hafukha"] 818 | ) 819 | """An instance of `OtherChar` representing the letter **`'׆'`**. This is a rarely used special character.""" 820 | 821 | NUN_HAFUKHA = INVERTED_NUN 822 | """Simple pointer to `INVERTED_NUN`.""" 823 | 824 | # Taamim characters 825 | ETNAHTA = TaamimChar(char="֑", name="Etnahta") 826 | """An instance of `TaamimChar` representing the Ta'amim **`'֑'`**.""" 827 | SEGOL_TOP = TaamimChar(char="֒", name="Segol Top") 828 | """An instance of `TaamimChar` representing the Ta'amim **`'֒'`**.""" 829 | SHALSHELET = TaamimChar(char="֓", name="Shalshelet") 830 | """An instance of `TaamimChar` representing the Ta'amim **`'֓'`**.""" 831 | ZAQEF_QATAN = TaamimChar(char="֔", name="Zaqef Qatan") 832 | """An instance of `TaamimChar` representing the Ta'amim **`'֔'`**.""" 833 | ZAQEF_GADOL = TaamimChar(char="֕", name="Zaqef Gadol") 834 | """An instance of `TaamimChar` representing the Ta'amim **`'֕'`**.""" 835 | TIFCHA = TaamimChar(char="֖", name="Tifcha") 836 | """An instance of `TaamimChar` representing the Ta'amim **`'֖'`**.""" 837 | REVIA = TaamimChar(char="֗", name="Revia") 838 | """An instance of `TaamimChar` representing the Ta'amim **`'֗'`**.""" 839 | ZINOR = TaamimChar(char="֮", name="Zinor") 840 | """An instance of `TaamimChar` representing the Ta'amim **`'֮'`**.""" 841 | PASHTA = TaamimChar(char="֙", name="Pashta") 842 | """An instance of `TaamimChar` representing the Ta'amim **`'֙'`**.""" 843 | PASHTA_2 = TaamimChar(char="֨", name="Pashta 2", name_alts=["Qadma"]) 844 | """An instance of `TaamimChar` representing the Ta'amim **`'֨'`**.""" 845 | QADMA = PASHTA_2 846 | """Simple pointer to `PASHTA_2` since they share the same Unicode character.""" 847 | YETIV = TaamimChar(char="֚", name="Yetiv") 848 | """An instance of `TaamimChar` representing the Ta'amim **`'֚'`**.""" 849 | TEVIR = TaamimChar(char="֛", name="Tevir") 850 | """An instance of `TaamimChar` representing the Ta'amim **`'֛'`**.""" 851 | PAZER = TaamimChar(char="֡", name="Pazer") 852 | """An instance of `TaamimChar` representing the Ta'amim **`'֡'`**.""" 853 | TELISHA_GEDOLA = TaamimChar(char="֠", name="Telisha Gedola") 854 | """An instance of `TaamimChar` representing the Ta'amim **`'֠'`**.""" 855 | TELISHA_KETANNAH = TaamimChar(char="֩", name="Telisha Ketannah") 856 | """An instance of `TaamimChar` representing the Ta'amim **`'֩'`**.""" 857 | AZLA_GERESH = TaamimChar(char="֜", name="Azla Geresh") 858 | """An instance of `TaamimChar` representing the Ta'amim **`'֜'`**.""" 859 | GERSHAYIM_2 = TaamimChar(char="֞", name="Gershayim 2") 860 | """An instance of `TaamimChar` representing the Ta'amim **`'֞'`**.""" 861 | MERCHA = TaamimChar(char="֥", name="Mercha") 862 | """An instance of `TaamimChar` representing the Ta'amim **`'֥'`**.""" 863 | MUNACH = TaamimChar(char="֣", name="Munach") 864 | """An instance of `TaamimChar` representing the Ta'amim **`'֣'`**.""" 865 | MAHPACH = TaamimChar(char="֤", name="Mahpach") 866 | """An instance of `TaamimChar` representing the Ta'amim **`'֤'`**.""" 867 | DARGA = TaamimChar(char="֧", name="Darga") 868 | """An instance of `TaamimChar` representing the Ta'amim **`'֧'`**.""" 869 | MERCHA_KEFULA = TaamimChar(char="֦", name="Mercha Kefula") 870 | """An instance of `TaamimChar` representing the Ta'amim **`'֦'`**.""" 871 | YERACH_BEN_YOMO = TaamimChar(char="֪", name="Yerach Ben Yomo") 872 | """An instance of `TaamimChar` representing the Ta'amim **`'֪'`**.""" 873 | MASORA = TaamimChar(char="֯", name="Masora") 874 | """An instance of `TaamimChar` representing the Ta'amim **`'֯'`**.""" 875 | DEHI = TaamimChar(char="֭", name="Dehi") 876 | """An instance of `TaamimChar` representing the Ta'amim **`'֭'`**.""" 877 | ZARQA = TaamimChar(char="֘", name="Zarqa") 878 | """An instance of `TaamimChar` representing the Ta'amim **`'֘'`**.""" 879 | GERESH_MUQDAM = TaamimChar(char="֝", name="Geresh Muqdam") 880 | """An instance of `TaamimChar` representing the Ta'amim **`'֝'`**.""" 881 | QARNEY_PARA = TaamimChar(char="֟", name="Qarney Para", name_alts=["Pazer Gadol"]) 882 | """An instance of `TaamimChar` representing the Ta'amim **`'֟'`**.""" 883 | PAZER_GADOL = QARNEY_PARA 884 | """Simple pointer to `QARNEY_PARA` since they share the same Unicode character.""" 885 | OLA = TaamimChar(char="֫", name="Ola") 886 | """An instance of `TaamimChar` representing the Ta'amim **`'֫'`**.""" 887 | ILUY = TaamimChar(char="֬", name="Iluy") 888 | """An instance of `TaamimChar` representing the Ta'amim **`'֬'`**.""" 889 | RAFE = TaamimChar(char="ֿ", name="Rafe") 890 | """An instance of `TaamimChar` representing the Ta'amim **`'ֿ'`**.""" 891 | METEG = TaamimChar(char="ֽ", name="Meteg") 892 | """An instance of `TaamimChar` representing the Ta'amim **`'ֽ'`**.""" 893 | JUDEO_SPANISH_VARIKA = TaamimChar(char="ﬞ", name="Judeo-Spanish Varika") 894 | """An instance of `TaamimChar` representing the Ta'amim **`'ﬞ'`**.""" 895 | ATNAH_HAFUKH = TaamimChar(char="֢", name="Atnah Hafukh") 896 | """An instance of `TaamimChar` representing the Ta'amim **`'֢'`**.""" 897 | 898 | ALL_CHARS: List[Union[HebrewChar, YiddishChar, NiqqudChar, TaamimChar, OtherChar]] = [ 899 | ALEPH, 900 | BET, 901 | VET, 902 | GIMEL, 903 | DALET, 904 | HE, 905 | VAV, 906 | ZAYIN, 907 | CHET, 908 | TET, 909 | YOD, 910 | CAF, 911 | KAF_SOFIT, 912 | CHAF, 913 | CHAF_SOFIT, 914 | LAMED, 915 | MEM, 916 | MEM_SOFIT, 917 | NUN, 918 | NUN_SOFIT, 919 | SAMEKH, 920 | AYIN, 921 | PE, 922 | FE, 923 | PE_SOFIT, 924 | FE_SOFIT, 925 | TSADI, 926 | TSADI_SOFIT, 927 | QOF, 928 | RESH, 929 | SHIN, 930 | SIN, 931 | PLAIN_SIN, 932 | TAV, 933 | SAV, 934 | DOUBLE_YOD, 935 | DOUBLE_VAV, 936 | VAV_YOD, 937 | SIN_DOT, 938 | SHIN_DOT, 939 | DAGESH, 940 | QUBUTS, 941 | SHURUK, 942 | HOLAM, 943 | QAMATS, 944 | PATAH, 945 | SEGOL, 946 | TSERE, 947 | HIRIQ, 948 | HATAF_QAMATS, 949 | HATAF_PATAH, 950 | HATAF_SEGOL, 951 | SHEVA, 952 | UPPER_DOT, 953 | MAQAF, 954 | PASEQ, 955 | SOF_PASSUK, 956 | ETNAHTA, 957 | SEGOL_TOP, 958 | SHALSHELET, 959 | ZAQEF_QATAN, 960 | ZAQEF_GADOL, 961 | TIFCHA, 962 | REVIA, 963 | ZINOR, 964 | PASHTA, 965 | PASHTA_2, 966 | YETIV, 967 | TEVIR, 968 | PAZER, 969 | TELISHA_GEDOLA, 970 | TELISHA_KETANNAH, 971 | GERESH, 972 | AZLA_GERESH, 973 | GERSHAYIM, 974 | GERSHAYIM_2, 975 | MERCHA, 976 | MUNACH, 977 | MAHPACH, 978 | DARGA, 979 | MERCHA_KEFULA, 980 | YERACH_BEN_YOMO, 981 | MASORA, 982 | DEHI, 983 | ZARQA, 984 | GERESH_MUQDAM, 985 | QARNEY_PARA, 986 | OLA, 987 | ILUY, 988 | RAFE, 989 | METEG, 990 | ATNAH_HAFUKH, 991 | HOLAM_HASER, 992 | LOWER_DOT, 993 | INVERTED_NUN, 994 | ALEPH_SYMBOL, 995 | BET_SYMBOL, 996 | GIMEL_SYMBOL, 997 | DALET_SYMBOL, 998 | YOD_HIRIQ, 999 | YOD_YOD_PATAH, 1000 | YOD_YOD_PATAH2, 1001 | AYIN_ALT, 1002 | ALEF_WIDE, 1003 | DALET_WIDE, 1004 | HE_WIDE, 1005 | KAF_WIDE, 1006 | LAMED_WIDE, 1007 | FINAL_MEM_WIDE, 1008 | RESH_WIDE, 1009 | TAV_WIDE, 1010 | SHIN_SHIN_DOT, 1011 | SHIN_SIN_DOT, 1012 | SHIN_DAGESH_SHIN_DOT, 1013 | SHIN_DAGESH_SIN_DOT, 1014 | ALEF_PATAH, 1015 | ALEF_QAMATZ, 1016 | ALEF_MAPIQ, 1017 | BET_DAGESH, 1018 | GIMEL_DAGESH, 1019 | DALET_DAGESH, 1020 | HE_MAPIQ, 1021 | VAV_DAGESH, 1022 | ZAYIN_DAGESH, 1023 | TET_DAGESH, 1024 | YOD_DAGESH, 1025 | FINAL_KAF_DAGESH, 1026 | KAF_DAGESH, 1027 | LAMED_DAGESH, 1028 | MEM_DAGESH, 1029 | NUN_DAGESH, 1030 | SAMEKH_DAGESH, 1031 | FINAL_PE_DAGESH, 1032 | PE_DAGESH, 1033 | TSADI_DAGESH, 1034 | QOF_DAGESH, 1035 | RESH_DAGESH, 1036 | SHIN_DAGESH, 1037 | TAV_DAGESH, 1038 | VAV_HOLAM, 1039 | BET_RAFE, 1040 | KAF_RAFE, 1041 | PE_RAFE, 1042 | ALEPH_LAMED, 1043 | QAMATS_KATAN, 1044 | YOD_TRIANGLE, 1045 | JUDEO_SPANISH_VARIKA, 1046 | ALTERNATIVE_PLUS_SIGN, 1047 | ] 1048 | """ 1049 | Every instance of a character class. 1050 | This is used for defining collections with list comprehensions based on the Chars metadata. 1051 | It can be relied on as being a complete list of Unicode characters used in Hebrew (and Yiddish etc). 1052 | """ 1053 | 1054 | CHARS: Dict[str, Union[HebrewChar, YiddishChar, NiqqudChar, TaamimChar, OtherChar]] = { 1055 | c.char: c for c in ALL_CHARS 1056 | } 1057 | """ 1058 | A dict of all instances of all supported Char types where the key is the char 1059 | and the value is an instance of BaseHebrewChar. 1060 | This is useful for when you have a hebrew char and want to get its metadata class. 1061 | 1062 | ``` python 1063 | assert CHARS['א'] == ALEPH 1064 | ``` 1065 | """ 1066 | 1067 | FINAL_LETTERS: List[HebrewChar] = [ 1068 | c 1069 | for c in ALL_CHARS 1070 | if isinstance(c, HebrewChar) and c.final_letter and len(c.char) == 1 1071 | ] 1072 | """ 1073 | A list of all Hebrew characters that are final letters. 1074 | While we do have letters like 'ףּ' defined, they do not return in this array; it contains only the plain final letters. 1075 | """ 1076 | 1077 | HEBREW_CHARS: List[HebrewChar] = [ 1078 | c 1079 | for c in ALL_CHARS 1080 | if isinstance(c, HebrewChar) and c.char in "אבגדהוזחטיכךלמםנןסעפףצץקרשת" 1081 | ] 1082 | """A List of all instances of `HebrewChar`. This will include letters like 'ףּ'""" 1083 | 1084 | YIDDISH_CHARS: List[YiddishChar] = [ 1085 | c for c in ALL_CHARS if isinstance(c, YiddishChar) and c.char in ["ױ", "װ", "ײ"] 1086 | ] 1087 | """A List of all instances of `YiddishChar`.""" 1088 | 1089 | NIQQUD_CHARS: List[NiqqudChar] = [c for c in ALL_CHARS if isinstance(c, NiqqudChar)] 1090 | """A List of all instances of `NiqqudChar`.""" 1091 | 1092 | TAAMIM_CHARS: List[TaamimChar] = [c for c in ALL_CHARS if isinstance(c, TaamimChar)] 1093 | """A List of all instances of `TaamimChar`.""" 1094 | 1095 | OTHER_CHARS: List[OtherChar] = [c for c in ALL_CHARS if isinstance(c, OtherChar)] 1096 | """A List of all instances of `OtherChar`.""" 1097 | 1098 | _NON_LETTER_CHARS: List[Union[NiqqudChar, TaamimChar, OtherChar]] = [ 1099 | c 1100 | for c in ALL_CHARS 1101 | if not isinstance(c, HebrewChar) and not isinstance(c, YiddishChar) 1102 | ] 1103 | """A List of all chars that are not letters. Used internally for filtering non letter chars.""" 1104 | 1105 | FINAL_MINOR_LETTER_MAPPINGS: Dict[str, str] = { 1106 | "כ": "ך", 1107 | "ך": "כ", 1108 | "מ": "ם", 1109 | "ם": "מ", 1110 | "נ": "ן", 1111 | "ן": "נ", 1112 | "פ": "ף", 1113 | "ף": "פ", 1114 | "צ": "ץ", 1115 | "ץ": "צ", 1116 | } 1117 | """A map of final letters to their regular counterparts, and vice versa.""" 1118 | 1119 | SPECIAL_CHARACTER_NORMALIZED_MAPPING: Dict[ 1120 | BaseHebrewChar, Union[BaseHebrewChar, List[BaseHebrewChar]] 1121 | ] = { 1122 | ALEPH_SYMBOL: ALEPH, 1123 | BET_SYMBOL: VET, 1124 | GIMEL_SYMBOL: GIMEL, 1125 | DALET_SYMBOL: DALET, 1126 | YOD_YOD_PATAH: [YOD, PATAH, YOD], 1127 | YOD_YOD_PATAH2: [YOD, PATAH, YOD], 1128 | AYIN_ALT: AYIN, 1129 | ALEF_WIDE: ALEPH, 1130 | DALET_WIDE: DALET, 1131 | HE_WIDE: HE, 1132 | KAF_WIDE: CHAF, 1133 | LAMED_WIDE: LAMED, 1134 | FINAL_MEM_WIDE: FINAL_MEM, 1135 | RESH_WIDE: RESH, 1136 | TAV_WIDE: SAV, 1137 | SHIN_SIN_DOT: SIN, 1138 | SHIN_DAGESH_SHIN_DOT: [SHIN, DAGESH], 1139 | SHIN_DAGESH_SIN_DOT: [SIN, DAGESH], 1140 | ALEPH_LAMED: [ALEPH, LAMED], 1141 | DOUBLE_YOD: [YOD, YOD], 1142 | DOUBLE_VAV: [VAV, VAV], 1143 | VAV_YOD: [YOD, VAV], 1144 | } 1145 | """A map of special characters to their normal spelled out equivalent. For example, ﭏ becomes אל""" 1146 | 1147 | 1148 | def char_search( 1149 | char_name: str, 1150 | char_list: Optional[ 1151 | List[Union[HebrewChar, YiddishChar, NiqqudChar, TaamimChar, OtherChar]] 1152 | ] = None, 1153 | ) -> Optional[Union[HebrewChar, YiddishChar, NiqqudChar, TaamimChar, OtherChar]]: 1154 | """ 1155 | Search for a character by its name. 1156 | 1157 | Character classes contain alternate names which are supported by this function! 1158 | Currently, only english names are supported. 1159 | TODO: Support search in hebrew, which will need to support hebrew text with or without nikud. 1160 | 1161 | :param char_name: A string containing the name of the character to search for. 1162 | :param char_list: A list of `BaseHebrewChar` characters to use for this search. 1163 | When None, defaults to all characters (ALL_CHARS). 1164 | :return: 1165 | """ 1166 | char_list = char_list if char_list else ALL_CHARS 1167 | for char in char_list: 1168 | if char_name.lower() in [n.lower() for n in char.names]: 1169 | return CHARS[char.char] 1170 | return None 1171 | -------------------------------------------------------------------------------- /tests/test_numerical_conversion.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from hebrew.numerical_conversion.convert import number_to_hebrew_string 4 | from hebrew.hebrew_obj import Hebrew 5 | from hebrew.numerical_conversion.substitute import Substitutions 6 | 7 | 8 | WITH_GERESH = { 9 | 1: "א׳", 10 | 2: "ב׳", 11 | 3: "ג׳", 12 | 4: "ד׳", 13 | 5: "ה׳", 14 | 6: "ו׳", 15 | 7: "ז׳", 16 | 8: "ח׳", 17 | 9: "ט׳", 18 | 10: "י׳", 19 | 11: "י״א", 20 | 12: "י״ב", 21 | 13: "י״ג", 22 | 14: "י״ד", 23 | 15: "ט״ו", 24 | 16: "ט״ז", 25 | 17: "י״ז", 26 | 18: "י״ח", 27 | 19: "י״ט", 28 | 20: "כ׳", 29 | 21: "כ״א", 30 | 22: "כ״ב", 31 | 23: "כ״ג", 32 | 24: "כ״ד", 33 | 25: "כ״ה", 34 | 26: "כ״ו", 35 | 27: "כ״ז", 36 | 28: "כ״ח", 37 | 29: "כ״ט", 38 | 30: "ל׳", 39 | 31: "ל״א", 40 | 32: "ל״ב", 41 | 33: "ל״ג", 42 | 34: "ל״ד", 43 | 35: "ל״ה", 44 | 36: "ל״ו", 45 | 37: "ל״ז", 46 | 38: "ל״ח", 47 | 39: "ל״ט", 48 | 40: "מ׳", 49 | 41: "מ״א", 50 | 42: "מ״ב", 51 | 43: "מ״ג", 52 | 44: "מ״ד", 53 | 45: "מ״ה", 54 | 46: "מ״ו", 55 | 47: "מ״ז", 56 | 48: "מ״ח", 57 | 49: "מ״ט", 58 | 50: "נ׳", 59 | 51: "נ״א", 60 | 52: "נ״ב", 61 | 53: "נ״ג", 62 | 54: "נ״ד", 63 | 55: "נ״ה", 64 | 56: "נ״ו", 65 | 57: "נ״ז", 66 | 58: "נ״ח", 67 | 59: "נ״ט", 68 | 60: "ס׳", 69 | 61: "ס״א", 70 | 62: "ס״ב", 71 | 63: "ס״ג", 72 | 64: "ס״ד", 73 | 65: "ס״ה", 74 | 66: "ס״ו", 75 | 67: "ס״ז", 76 | 68: "ס״ח", 77 | 69: "ס״ט", 78 | 70: "ע׳", 79 | 71: "ע״א", 80 | 72: "ע״ב", 81 | 73: "ע״ג", 82 | 74: "ע״ד", 83 | 75: "ע״ה", 84 | 76: "ע״ו", 85 | 77: "ע״ז", 86 | 78: "ע״ח", 87 | 79: "ע״ט", 88 | 80: "פ׳", 89 | 81: "פ״א", 90 | 82: "פ״ב", 91 | 83: "פ״ג", 92 | 84: "פ״ד", 93 | 85: "פ״ה", 94 | 86: "פ״ו", 95 | 87: "פ״ז", 96 | 88: "פ״ח", 97 | 89: "פ״ט", 98 | 90: "צ׳", 99 | 91: "צ״א", 100 | 92: "צ״ב", 101 | 93: "צ״ג", 102 | 94: "צ״ד", 103 | 95: "צ״ה", 104 | 96: "צ״ו", 105 | 97: "צ״ז", 106 | 98: "צ״ח", 107 | 99: "צ״ט", 108 | 100: "ק׳", 109 | 101: "ק״א", 110 | 102: "ק״ב", 111 | 103: "ק״ג", 112 | 104: "ק״ד", 113 | 105: "ק״ה", 114 | 106: "ק״ו", 115 | 107: "ק״ז", 116 | 108: "ק״ח", 117 | 109: "ק״ט", 118 | 110: "ק״י", 119 | 111: "קי״א", 120 | 112: "קי״ב", 121 | 113: "קי״ג", 122 | 114: "קי״ד", 123 | 115: "קט״ו", 124 | 116: "קט״ז", 125 | 117: "קי״ז", 126 | 118: "קי״ח", 127 | 119: "קי״ט", 128 | 120: "ק״כ", 129 | 121: "קכ״א", 130 | 122: "קכ״ב", 131 | 123: "קכ״ג", 132 | 124: "קכ״ד", 133 | 125: "קכ״ה", 134 | 126: "קכ״ו", 135 | 127: "קכ״ז", 136 | 128: "קכ״ח", 137 | 129: "קכ״ט", 138 | 130: "ק״ל", 139 | 131: "קל״א", 140 | 132: "קל״ב", 141 | 133: "קל״ג", 142 | 134: "קל״ד", 143 | 135: "קל״ה", 144 | 136: "קל״ו", 145 | 137: "קל״ז", 146 | 138: "קל״ח", 147 | 139: "קל״ט", 148 | 140: "ק״מ", 149 | 141: "קמ״א", 150 | 142: "קמ״ב", 151 | 143: "קמ״ג", 152 | 144: "קמ״ד", 153 | 145: "קמ״ה", 154 | 146: "קמ״ו", 155 | 147: "קמ״ז", 156 | 148: "קמ״ח", 157 | 149: "קמ״ט", 158 | 150: "ק״נ", 159 | 151: "קנ״א", 160 | 152: "קנ״ב", 161 | 153: "קנ״ג", 162 | 154: "קנ״ד", 163 | 155: "קנ״ה", 164 | 156: "קנ״ו", 165 | 157: "קנ״ז", 166 | 158: "קנ״ח", 167 | 159: "קנ״ט", 168 | 160: "ק״ס", 169 | 161: "קס״א", 170 | 162: "קס״ב", 171 | 163: "קס״ג", 172 | 164: "קס״ד", 173 | 165: "קס״ה", 174 | 166: "קס״ו", 175 | 167: "קס״ז", 176 | 168: "קס״ח", 177 | 169: "קס״ט", 178 | 170: "ק״ע", 179 | 171: "קע״א", 180 | 172: "קע״ב", 181 | 173: "קע״ג", 182 | 174: "קע״ד", 183 | 175: "קע״ה", 184 | 176: "קע״ו", 185 | 177: "קע״ז", 186 | 178: "קע״ח", 187 | 179: "קע״ט", 188 | 180: "ק״פ", 189 | 181: "קפ״א", 190 | 182: "קפ״ב", 191 | 183: "קפ״ג", 192 | 184: "קפ״ד", 193 | 185: "קפ״ה", 194 | 186: "קפ״ו", 195 | 187: "קפ״ז", 196 | 188: "קפ״ח", 197 | 189: "קפ״ט", 198 | 190: "ק״צ", 199 | 191: "קצ״א", 200 | 192: "קצ״ב", 201 | 193: "קצ״ג", 202 | 194: "קצ״ד", 203 | 195: "קצ״ה", 204 | 196: "קצ״ו", 205 | 197: "קצ״ז", 206 | 198: "קצ״ח", 207 | 199: "קצ״ט", 208 | 200: "ר׳", 209 | 201: "ר״א", 210 | 202: "ר״ב", 211 | 203: "ר״ג", 212 | 204: "ר״ד", 213 | 205: "ר״ה", 214 | 206: "ר״ו", 215 | 207: "ר״ז", 216 | 208: "ר״ח", 217 | 209: "ר״ט", 218 | 210: "ר״י", 219 | 211: "רי״א", 220 | 212: "רי״ב", 221 | 213: "רי״ג", 222 | 214: "רי״ד", 223 | 215: "רט״ו", 224 | 216: "רט״ז", 225 | 217: "רי״ז", 226 | 218: "רי״ח", 227 | 219: "רי״ט", 228 | 220: "ר״כ", 229 | 221: "רכ״א", 230 | 222: "רכ״ב", 231 | 223: "רכ״ג", 232 | 224: "רכ״ד", 233 | 225: "רכ״ה", 234 | 226: "רכ״ו", 235 | 227: "רכ״ז", 236 | 228: "רכ״ח", 237 | 229: "רכ״ט", 238 | 230: "ר״ל", 239 | 231: "רל״א", 240 | 232: "רל״ב", 241 | 233: "רל״ג", 242 | 234: "רל״ד", 243 | 235: "רל״ה", 244 | 236: "רל״ו", 245 | 237: "רל״ז", 246 | 238: "רל״ח", 247 | 239: "רל״ט", 248 | 240: "ר״מ", 249 | 241: "רמ״א", 250 | 242: "רמ״ב", 251 | 243: "רמ״ג", 252 | 244: "רמ״ד", 253 | 245: "רמ״ה", 254 | 246: "רמ״ו", 255 | 247: "רמ״ז", 256 | 248: "רמ״ח", 257 | 249: "רמ״ט", 258 | 250: "ר״נ", 259 | 251: "רנ״א", 260 | 252: "רנ״ב", 261 | 253: "רנ״ג", 262 | 254: "רנ״ד", 263 | 255: "רנ״ה", 264 | 256: "רנ״ו", 265 | 257: "רנ״ז", 266 | 258: "רנ״ח", 267 | 259: "רנ״ט", 268 | 260: "ר״ס", 269 | 261: "רס״א", 270 | 262: "רס״ב", 271 | 263: "רס״ג", 272 | 264: "רס״ד", 273 | 265: "רס״ה", 274 | 266: "רס״ו", 275 | 267: "רס״ז", 276 | 268: "רס״ח", 277 | 269: "רס״ט", 278 | 270: "ר״ע", 279 | 271: "רע״א", 280 | 272: "רע״ב", 281 | 273: "רע״ג", 282 | 274: "רע״ד", 283 | 275: "רע״ה", 284 | 276: "רע״ו", 285 | 277: "רע״ז", 286 | 278: "רע״ח", 287 | 279: "רע״ט", 288 | 280: "ר״פ", 289 | 281: "רפ״א", 290 | 282: "רפ״ב", 291 | 283: "רפ״ג", 292 | 284: "רפ״ד", 293 | 285: "רפ״ה", 294 | 286: "רפ״ו", 295 | 287: "רפ״ז", 296 | 288: "רפ״ח", 297 | 289: "רפ״ט", 298 | 290: "ר״צ", 299 | 291: "רצ״א", 300 | 292: "רצ״ב", 301 | 293: "רצ״ג", 302 | 294: "רצ״ד", 303 | 295: "רצ״ה", 304 | 296: "רצ״ו", 305 | 297: "רצ״ז", 306 | 298: "רצ״ח", 307 | 299: "רצ״ט", 308 | 300: "ש׳", 309 | 301: "ש״א", 310 | 302: "ש״ב", 311 | 303: "ש״ג", 312 | 304: "ש״ד", 313 | 305: "ש״ה", 314 | 306: "ש״ו", 315 | 307: "ש״ז", 316 | 308: "ש״ח", 317 | 309: "ש״ט", 318 | 310: "ש״י", 319 | 311: "שי״א", 320 | 312: "שי״ב", 321 | 313: "שי״ג", 322 | 314: "שי״ד", 323 | 315: "שט״ו", 324 | 316: "שט״ז", 325 | 317: "שי״ז", 326 | 318: "שי״ח", 327 | 319: "שי״ט", 328 | 320: "ש״כ", 329 | 321: "שכ״א", 330 | 322: "שכ״ב", 331 | 323: "שכ״ג", 332 | 324: "שכ״ד", 333 | 325: "שכ״ה", 334 | 326: "שכ״ו", 335 | 327: "שכ״ז", 336 | 328: "שכ״ח", 337 | 329: "שכ״ט", 338 | 330: "ש״ל", 339 | 331: "של״א", 340 | 332: "של״ב", 341 | 333: "של״ג", 342 | 334: "של״ד", 343 | 335: "של״ה", 344 | 336: "של״ו", 345 | 337: "של״ז", 346 | 338: "של״ח", 347 | 339: "של״ט", 348 | 340: "ש״מ", 349 | 341: "שמ״א", 350 | 342: "שמ״ב", 351 | 343: "שמ״ג", 352 | 344: "שמ״ד", 353 | 345: "שמ״ה", 354 | 346: "שמ״ו", 355 | 347: "שמ״ז", 356 | 348: "שמ״ח", 357 | 349: "שמ״ט", 358 | 350: "ש״נ", 359 | 351: "שנ״א", 360 | 352: "שנ״ב", 361 | 353: "שנ״ג", 362 | 354: "שנ״ד", 363 | 355: "שנ״ה", 364 | 356: "שנ״ו", 365 | 357: "שנ״ז", 366 | 358: "שנ״ח", 367 | 359: "שנ״ט", 368 | 360: "ש״ס", 369 | 361: "שס״א", 370 | 362: "שס״ב", 371 | 363: "שס״ג", 372 | 364: "שס״ד", 373 | 365: "שס״ה", 374 | 366: "שס״ו", 375 | 367: "שס״ז", 376 | 368: "שס״ח", 377 | 369: "שס״ט", 378 | 370: "ש״ע", 379 | 371: "שע״א", 380 | 372: "שע״ב", 381 | 373: "שע״ג", 382 | 374: "שע״ד", 383 | 375: "שע״ה", 384 | 376: "שע״ו", 385 | 377: "שע״ז", 386 | 378: "שע״ח", 387 | 379: "שע״ט", 388 | 380: "ש״פ", 389 | 381: "שפ״א", 390 | 382: "שפ״ב", 391 | 383: "שפ״ג", 392 | 384: "שפ״ד", 393 | 385: "שפ״ה", 394 | 386: "שפ״ו", 395 | 387: "שפ״ז", 396 | 388: "שפ״ח", 397 | 389: "שפ״ט", 398 | 390: "ש״צ", 399 | 391: "שצ״א", 400 | 392: "שצ״ב", 401 | 393: "שצ״ג", 402 | 394: "שצ״ד", 403 | 395: "שצ״ה", 404 | 396: "שצ״ו", 405 | 397: "שצ״ז", 406 | 398: "שצ״ח", 407 | 399: "שצ״ט", 408 | 400: "ת׳", 409 | 401: "ת״א", 410 | 402: "ת״ב", 411 | 403: "ת״ג", 412 | 404: "ת״ד", 413 | 405: "ת״ה", 414 | 406: "ת״ו", 415 | 407: "ת״ז", 416 | 408: "ת״ח", 417 | 409: "ת״ט", 418 | 410: "ת״י", 419 | 411: "תי״א", 420 | 412: "תי״ב", 421 | 413: "תי״ג", 422 | 414: "תי״ד", 423 | 415: "תט״ו", 424 | 416: "תט״ז", 425 | 417: "תי״ז", 426 | 418: "תי״ח", 427 | 419: "תי״ט", 428 | 420: "ת״כ", 429 | 421: "תכ״א", 430 | 422: "תכ״ב", 431 | 423: "תכ״ג", 432 | 424: "תכ״ד", 433 | 425: "תכ״ה", 434 | 426: "תכ״ו", 435 | 427: "תכ״ז", 436 | 428: "תכ״ח", 437 | 429: "תכ״ט", 438 | 430: "ת״ל", 439 | 431: "תל״א", 440 | 432: "תל״ב", 441 | 433: "תל״ג", 442 | 434: "תל״ד", 443 | 435: "תל״ה", 444 | 436: "תל״ו", 445 | 437: "תל״ז", 446 | 438: "תל״ח", 447 | 439: "תל״ט", 448 | 440: "ת״מ", 449 | 441: "תמ״א", 450 | 442: "תמ״ב", 451 | 443: "תמ״ג", 452 | 444: "תמ״ד", 453 | 445: "תמ״ה", 454 | 446: "תמ״ו", 455 | 447: "תמ״ז", 456 | 448: "תמ״ח", 457 | 449: "תמ״ט", 458 | 450: "ת״נ", 459 | 451: "תנ״א", 460 | 452: "תנ״ב", 461 | 453: "תנ״ג", 462 | 454: "תנ״ד", 463 | 455: "תנ״ה", 464 | 456: "תנ״ו", 465 | 457: "תנ״ז", 466 | 458: "תנ״ח", 467 | 459: "תנ״ט", 468 | 460: "ת״ס", 469 | 461: "תס״א", 470 | 462: "תס״ב", 471 | 463: "תס״ג", 472 | 464: "תס״ד", 473 | 465: "תס״ה", 474 | 466: "תס״ו", 475 | 467: "תס״ז", 476 | 468: "תס״ח", 477 | 469: "תס״ט", 478 | 470: "ת״ע", 479 | 471: "תע״א", 480 | 472: "תע״ב", 481 | 473: "תע״ג", 482 | 474: "תע״ד", 483 | 475: "תע״ה", 484 | 476: "תע״ו", 485 | 477: "תע״ז", 486 | 478: "תע״ח", 487 | 479: "תע״ט", 488 | 480: "ת״פ", 489 | 481: "תפ״א", 490 | 482: "תפ״ב", 491 | 483: "תפ״ג", 492 | 484: "תפ״ד", 493 | 485: "תפ״ה", 494 | 486: "תפ״ו", 495 | 487: "תפ״ז", 496 | 488: "תפ״ח", 497 | 489: "תפ״ט", 498 | 490: "ת״צ", 499 | 491: "תצ״א", 500 | 492: "תצ״ב", 501 | 493: "תצ״ג", 502 | 494: "תצ״ד", 503 | 495: "תצ״ה", 504 | 496: "תצ״ו", 505 | 497: "תצ״ז", 506 | 498: "תצ״ח", 507 | 499: "תצ״ט", 508 | 500: "ת״ק", 509 | 501: "תק״א", 510 | 502: "תק״ב", 511 | 503: "תק״ג", 512 | 504: "תק״ד", 513 | 505: "תק״ה", 514 | 506: "תק״ו", 515 | 507: "תק״ז", 516 | 508: "תק״ח", 517 | 509: "תק״ט", 518 | 510: "תק״י", 519 | 511: "תקי״א", 520 | 512: "תקי״ב", 521 | 513: "תקי״ג", 522 | 514: "תקי״ד", 523 | 515: "תקט״ו", 524 | 516: "תקט״ז", 525 | 517: "תקי״ז", 526 | 518: "תקי״ח", 527 | 519: "תקי״ט", 528 | 520: "תק״כ", 529 | 521: "תקכ״א", 530 | 522: "תקכ״ב", 531 | 523: "תקכ״ג", 532 | 524: "תקכ״ד", 533 | 525: "תקכ״ה", 534 | 526: "תקכ״ו", 535 | 527: "תקכ״ז", 536 | 528: "תקכ״ח", 537 | 529: "תקכ״ט", 538 | 530: "תק״ל", 539 | 531: "תקל״א", 540 | 532: "תקל״ב", 541 | 533: "תקל״ג", 542 | 534: "תקל״ד", 543 | 535: "תקל״ה", 544 | 536: "תקל״ו", 545 | 537: "תקל״ז", 546 | 538: "תקל״ח", 547 | 539: "תקל״ט", 548 | 540: "תק״מ", 549 | 541: "תקמ״א", 550 | 542: "תקמ״ב", 551 | 543: "תקמ״ג", 552 | 544: "תקמ״ד", 553 | 545: "תקמ״ה", 554 | 546: "תקמ״ו", 555 | 547: "תקמ״ז", 556 | 548: "תקמ״ח", 557 | 549: "תקמ״ט", 558 | 550: "תק״נ", 559 | 551: "תקנ״א", 560 | 552: "תקנ״ב", 561 | 553: "תקנ״ג", 562 | 554: "תקנ״ד", 563 | 555: "תקנ״ה", 564 | 556: "תקנ״ו", 565 | 557: "תקנ״ז", 566 | 558: "תקנ״ח", 567 | 559: "תקנ״ט", 568 | 560: "תק״ס", 569 | 561: "תקס״א", 570 | 562: "תקס״ב", 571 | 563: "תקס״ג", 572 | 564: "תקס״ד", 573 | 565: "תקס״ה", 574 | 566: "תקס״ו", 575 | 567: "תקס״ז", 576 | 568: "תקס״ח", 577 | 569: "תקס״ט", 578 | 570: "תק״ע", 579 | 571: "תקע״א", 580 | 572: "תקע״ב", 581 | 573: "תקע״ג", 582 | 574: "תקע״ד", 583 | 575: "תקע״ה", 584 | 576: "תקע״ו", 585 | 577: "תקע״ז", 586 | 578: "תקע״ח", 587 | 579: "תקע״ט", 588 | 580: "תק״פ", 589 | 581: "תקפ״א", 590 | 582: "תקפ״ב", 591 | 583: "תקפ״ג", 592 | 584: "תקפ״ד", 593 | 585: "תקפ״ה", 594 | 586: "תקפ״ו", 595 | 587: "תקפ״ז", 596 | 588: "תקפ״ח", 597 | 589: "תקפ״ט", 598 | 590: "תק״צ", 599 | 591: "תקצ״א", 600 | 592: "תקצ״ב", 601 | 593: "תקצ״ג", 602 | 594: "תקצ״ד", 603 | 595: "תקצ״ה", 604 | 596: "תקצ״ו", 605 | 597: "תקצ״ז", 606 | 598: "תקצ״ח", 607 | 599: "תקצ״ט", 608 | 600: "ת״ר", 609 | 601: "תר״א", 610 | 602: "תר״ב", 611 | 603: "תר״ג", 612 | 604: "תר״ד", 613 | 605: "תר״ה", 614 | 606: "תר״ו", 615 | 607: "תר״ז", 616 | 608: "תר״ח", 617 | 609: "תר״ט", 618 | 610: "תר״י", 619 | 611: "תרי״א", 620 | 612: "תרי״ב", 621 | 613: "תרי״ג", 622 | 614: "תרי״ד", 623 | 615: "תרט״ו", 624 | 616: "תרט״ז", 625 | 617: "תרי״ז", 626 | 618: "תרי״ח", 627 | 619: "תרי״ט", 628 | 620: "תר״כ", 629 | 621: "תרכ״א", 630 | 622: "תרכ״ב", 631 | 623: "תרכ״ג", 632 | 624: "תרכ״ד", 633 | 625: "תרכ״ה", 634 | 626: "תרכ״ו", 635 | 627: "תרכ״ז", 636 | 628: "תרכ״ח", 637 | 629: "תרכ״ט", 638 | 630: "תר״ל", 639 | 631: "תרל״א", 640 | 632: "תרל״ב", 641 | 633: "תרל״ג", 642 | 634: "תרל״ד", 643 | 635: "תרל״ה", 644 | 636: "תרל״ו", 645 | 637: "תרל״ז", 646 | 638: "תרל״ח", 647 | 639: "תרל״ט", 648 | 640: "תר״מ", 649 | 641: "תרמ״א", 650 | 642: "תרמ״ב", 651 | 643: "תרמ״ג", 652 | 644: "תרמ״ד", 653 | 645: "תרמ״ה", 654 | 646: "תרמ״ו", 655 | 647: "תרמ״ז", 656 | 648: "תרמ״ח", 657 | 649: "תרמ״ט", 658 | 650: "תר״נ", 659 | 651: "תרנ״א", 660 | 652: "תרנ״ב", 661 | 653: "תרנ״ג", 662 | 654: "תרנ״ד", 663 | 655: "תרנ״ה", 664 | 656: "תרנ״ו", 665 | 657: "תרנ״ז", 666 | 658: "תרנ״ח", 667 | 659: "תרנ״ט", 668 | 660: "תר״ס", 669 | 661: "תרס״א", 670 | 662: "תרס״ב", 671 | 663: "תרס״ג", 672 | 664: "תרס״ד", 673 | 665: "תרס״ה", 674 | 666: "תרס״ו", 675 | 667: "תרס״ז", 676 | 668: "תרס״ח", 677 | 669: "תרס״ט", 678 | 670: "תר״ע", 679 | 671: "תרע״א", 680 | 672: "תרע״ב", 681 | 673: "תרע״ג", 682 | 674: "תרע״ד", 683 | 675: "תרע״ה", 684 | 676: "תרע״ו", 685 | 677: "תרע״ז", 686 | 678: "תרע״ח", 687 | 679: "תרע״ט", 688 | 680: "תר״פ", 689 | 681: "תרפ״א", 690 | 682: "תרפ״ב", 691 | 683: "תרפ״ג", 692 | 684: "תרפ״ד", 693 | 685: "תרפ״ה", 694 | 686: "תרפ״ו", 695 | 687: "תרפ״ז", 696 | 688: "תרפ״ח", 697 | 689: "תרפ״ט", 698 | 690: "תר״צ", 699 | 691: "תרצ״א", 700 | 692: "תרצ״ב", 701 | 693: "תרצ״ג", 702 | 694: "תרצ״ד", 703 | 695: "תרצ״ה", 704 | 696: "תרצ״ו", 705 | 697: "תרצ״ז", 706 | 698: "תרצ״ח", 707 | 699: "תרצ״ט", 708 | 700: "ת״ש", 709 | 701: "תש״א", 710 | 702: "תש״ב", 711 | 703: "תש״ג", 712 | 704: "תש״ד", 713 | 705: "תש״ה", 714 | 706: "תש״ו", 715 | 707: "תש״ז", 716 | 708: "תש״ח", 717 | 709: "תש״ט", 718 | 710: "תש״י", 719 | 711: "תשי״א", 720 | 712: "תשי״ב", 721 | 713: "תשי״ג", 722 | 714: "תשי״ד", 723 | 715: "תשט״ו", 724 | 716: "תשט״ז", 725 | 717: "תשי״ז", 726 | 718: "תשי״ח", 727 | 719: "תשי״ט", 728 | 720: "תש״כ", 729 | 721: "תשכ״א", 730 | 722: "תשכ״ב", 731 | 723: "תשכ״ג", 732 | 724: "תשכ״ד", 733 | 725: "תשכ״ה", 734 | 726: "תשכ״ו", 735 | 727: "תשכ״ז", 736 | 728: "תשכ״ח", 737 | 729: "תשכ״ט", 738 | 730: "תש״ל", 739 | 731: "תשל״א", 740 | 732: "תשל״ב", 741 | 733: "תשל״ג", 742 | 734: "תשל״ד", 743 | 735: "תשל״ה", 744 | 736: "תשל״ו", 745 | 737: "תשל״ז", 746 | 738: "תשל״ח", 747 | 739: "תשל״ט", 748 | 740: "תש״מ", 749 | 741: "תשמ״א", 750 | 742: "תשמ״ב", 751 | 743: "תשמ״ג", 752 | 744: "תשמ״ד", 753 | 745: "תשמ״ה", 754 | 746: "תשמ״ו", 755 | 747: "תשמ״ז", 756 | 748: "תשמ״ח", 757 | 749: "תשמ״ט", 758 | 750: "תש״נ", 759 | 751: "תשנ״א", 760 | 752: "תשנ״ב", 761 | 753: "תשנ״ג", 762 | 754: "תשנ״ד", 763 | 755: "תשנ״ה", 764 | 756: "תשנ״ו", 765 | 757: "תשנ״ז", 766 | 758: "תשנ״ח", 767 | 759: "תשנ״ט", 768 | 760: "תש״ס", 769 | 761: "תשס״א", 770 | 762: "תשס״ב", 771 | 763: "תשס״ג", 772 | 764: "תשס״ד", 773 | 765: "תשס״ה", 774 | 766: "תשס״ו", 775 | 767: "תשס״ז", 776 | 768: "תשס״ח", 777 | 769: "תשס״ט", 778 | 770: "תש״ע", 779 | 771: "תשע״א", 780 | 772: "תשע״ב", 781 | 773: "תשע״ג", 782 | 774: "תשע״ד", 783 | 775: "תשע״ה", 784 | 776: "תשע״ו", 785 | 777: "תשע״ז", 786 | 778: "תשע״ח", 787 | 779: "תשע״ט", 788 | 780: "תש״פ", 789 | 781: "תשפ״א", 790 | 782: "תשפ״ב", 791 | 783: "תשפ״ג", 792 | 784: "תשפ״ד", 793 | 785: "תשפ״ה", 794 | 786: "תשפ״ו", 795 | 787: "תשפ״ז", 796 | 788: "תשפ״ח", 797 | 789: "תשפ״ט", 798 | 790: "תש״צ", 799 | 791: "תשצ״א", 800 | 792: "תשצ״ב", 801 | 793: "תשצ״ג", 802 | 794: "תשצ״ד", 803 | 795: "תשצ״ה", 804 | 796: "תשצ״ו", 805 | 797: "תשצ״ז", 806 | 798: "תשצ״ח", 807 | 799: "תשצ״ט", 808 | 800: "ת״ת", 809 | 801: "תת״א", 810 | 802: "תת״ב", 811 | 803: "תת״ג", 812 | 804: "תת״ד", 813 | 805: "תת״ה", 814 | 806: "תת״ו", 815 | 807: "תת״ז", 816 | 808: "תת״ח", 817 | 809: "תת״ט", 818 | 810: "תת״י", 819 | 811: "תתי״א", 820 | 812: "תתי״ב", 821 | 813: "תתי״ג", 822 | 814: "תתי״ד", 823 | 815: "תתט״ו", 824 | 816: "תתט״ז", 825 | 817: "תתי״ז", 826 | 818: "תתי״ח", 827 | 819: "תתי״ט", 828 | 820: "תת״כ", 829 | 821: "תתכ״א", 830 | 822: "תתכ״ב", 831 | 823: "תתכ״ג", 832 | 824: "תתכ״ד", 833 | 825: "תתכ״ה", 834 | 826: "תתכ״ו", 835 | 827: "תתכ״ז", 836 | 828: "תתכ״ח", 837 | 829: "תתכ״ט", 838 | 830: "תת״ל", 839 | 831: "תתל״א", 840 | 832: "תתל״ב", 841 | 833: "תתל״ג", 842 | 834: "תתל״ד", 843 | 835: "תתל״ה", 844 | 836: "תתל״ו", 845 | 837: "תתל״ז", 846 | 838: "תתל״ח", 847 | 839: "תתל״ט", 848 | 840: "תת״מ", 849 | 841: "תתמ״א", 850 | 842: "תתמ״ב", 851 | 843: "תתמ״ג", 852 | 844: "תתמ״ד", 853 | 845: "תתמ״ה", 854 | 846: "תתמ״ו", 855 | 847: "תתמ״ז", 856 | 848: "תתמ״ח", 857 | 849: "תתמ״ט", 858 | 850: "תת״נ", 859 | 851: "תתנ״א", 860 | 852: "תתנ״ב", 861 | 853: "תתנ״ג", 862 | 854: "תתנ״ד", 863 | 855: "תתנ״ה", 864 | 856: "תתנ״ו", 865 | 857: "תתנ״ז", 866 | 858: "תתנ״ח", 867 | 859: "תתנ״ט", 868 | 860: "תת״ס", 869 | 861: "תתס״א", 870 | 862: "תתס״ב", 871 | 863: "תתס״ג", 872 | 864: "תתס״ד", 873 | 865: "תתס״ה", 874 | 866: "תתס״ו", 875 | 867: "תתס״ז", 876 | 868: "תתס״ח", 877 | 869: "תתס״ט", 878 | 870: "תת״ע", 879 | 871: "תתע״א", 880 | 872: "תתע״ב", 881 | 873: "תתע״ג", 882 | 874: "תתע״ד", 883 | 875: "תתע״ה", 884 | 876: "תתע״ו", 885 | 877: "תתע״ז", 886 | 878: "תתע״ח", 887 | 879: "תתע״ט", 888 | 880: "תת״פ", 889 | 881: "תתפ״א", 890 | 882: "תתפ״ב", 891 | 883: "תתפ״ג", 892 | 884: "תתפ״ד", 893 | 885: "תתפ״ה", 894 | 886: "תתפ״ו", 895 | 887: "תתפ״ז", 896 | 888: "תתפ״ח", 897 | 889: "תתפ״ט", 898 | 890: "תת״צ", 899 | 891: "תתצ״א", 900 | 892: "תתצ״ב", 901 | 893: "תתצ״ג", 902 | 894: "תתצ״ד", 903 | 895: "תתצ״ה", 904 | 896: "תתצ״ו", 905 | 897: "תתצ״ז", 906 | 898: "תתצ״ח", 907 | 899: "תתצ״ט", 908 | 900: "תת״ק", 909 | 901: "תתק״א", 910 | 902: "תתק״ב", 911 | 903: "תתק״ג", 912 | 904: "תתק״ד", 913 | 905: "תתק״ה", 914 | 906: "תתק״ו", 915 | 907: "תתק״ז", 916 | 908: "תתק״ח", 917 | 909: "תתק״ט", 918 | 910: "תתק״י", 919 | 911: "תתקי״א", 920 | 912: "תתקי״ב", 921 | 913: "תתקי״ג", 922 | 914: "תתקי״ד", 923 | 915: "תתקט״ו", 924 | 916: "תתקט״ז", 925 | 917: "תתקי״ז", 926 | 918: "תתקי״ח", 927 | 919: "תתקי״ט", 928 | 920: "תתק״כ", 929 | 921: "תתקכ״א", 930 | 922: "תתקכ״ב", 931 | 923: "תתקכ״ג", 932 | 924: "תתקכ״ד", 933 | 925: "תתקכ״ה", 934 | 926: "תתקכ״ו", 935 | 927: "תתקכ״ז", 936 | 928: "תתקכ״ח", 937 | 929: "תתקכ״ט", 938 | 930: "תתק״ל", 939 | 931: "תתקל״א", 940 | 932: "תתקל״ב", 941 | 933: "תתקל״ג", 942 | 934: "תתקל״ד", 943 | 935: "תתקל״ה", 944 | 936: "תתקל״ו", 945 | 937: "תתקל״ז", 946 | 938: "תתקל״ח", 947 | 939: "תתקל״ט", 948 | 940: "תתק״מ", 949 | 941: "תתקמ״א", 950 | 942: "תתקמ״ב", 951 | 943: "תתקמ״ג", 952 | 944: "תתקמ״ד", 953 | 945: "תתקמ״ה", 954 | 946: "תתקמ״ו", 955 | 947: "תתקמ״ז", 956 | 948: "תתקמ״ח", 957 | 949: "תתקמ״ט", 958 | 950: "תתק״נ", 959 | 951: "תתקנ״א", 960 | 952: "תתקנ״ב", 961 | 953: "תתקנ״ג", 962 | 954: "תתקנ״ד", 963 | 955: "תתקנ״ה", 964 | 956: "תתקנ״ו", 965 | 957: "תתקנ״ז", 966 | 958: "תתקנ״ח", 967 | 959: "תתקנ״ט", 968 | 960: "תתק״ס", 969 | 961: "תתקס״א", 970 | 962: "תתקס״ב", 971 | 963: "תתקס״ג", 972 | 964: "תתקס״ד", 973 | 965: "תתקס״ה", 974 | 966: "תתקס״ו", 975 | 967: "תתקס״ז", 976 | 968: "תתקס״ח", 977 | 969: "תתקס״ט", 978 | 970: "תתק״ע", 979 | 971: "תתקע״א", 980 | 972: "תתקע״ב", 981 | 973: "תתקע״ג", 982 | 974: "תתקע״ד", 983 | 975: "תתקע״ה", 984 | 976: "תתקע״ו", 985 | 977: "תתקע״ז", 986 | 978: "תתקע״ח", 987 | 979: "תתקע״ט", 988 | 980: "תתק״פ", 989 | 981: "תתקפ״א", 990 | 982: "תתקפ״ב", 991 | 983: "תתקפ״ג", 992 | 984: "תתקפ״ד", 993 | 985: "תתקפ״ה", 994 | 986: "תתקפ״ו", 995 | 987: "תתקפ״ז", 996 | 988: "תתקפ״ח", 997 | 989: "תתקפ״ט", 998 | 990: "תתק״צ", 999 | 991: "תתקצ״א", 1000 | 992: "תתקצ״ב", 1001 | 993: "תתקצ״ג", 1002 | 994: "תתקצ״ד", 1003 | 995: "תתקצ״ה", 1004 | 996: "תתקצ״ו", 1005 | 997: "תתקצ״ז", 1006 | 998: "תתקצ״ח", 1007 | 999: "תתקצ״ט", 1008 | 1000: "תת״ר", 1009 | 1001: "תתר״א", 1010 | 1002: "תתר״ב", 1011 | 1003: "תתר״ג", 1012 | 1004: "תתר״ד", 1013 | 1005: "תתר״ה", 1014 | 1006: "תתר״ו", 1015 | 1007: "תתר״ז", 1016 | 1008: "תתר״ח", 1017 | 1009: "תתר״ט", 1018 | 1010: "תתר״י", 1019 | 1011: "תתרי״א", 1020 | 1012: "תתרי״ב", 1021 | 1013: "תתרי״ג", 1022 | 1014: "תתרי״ד", 1023 | 1015: "תתרט״ו", 1024 | 1016: "תתרט״ז", 1025 | 1017: "תתרי״ז", 1026 | 1018: "תתרי״ח", 1027 | 1019: "תתרי״ט", 1028 | 1020: "תתר״כ", 1029 | 1021: "תתרכ״א", 1030 | 1022: "תתרכ״ב", 1031 | 1023: "תתרכ״ג", 1032 | 1024: "תתרכ״ד", 1033 | 1025: "תתרכ״ה", 1034 | 1026: "תתרכ״ו", 1035 | 1027: "תתרכ״ז", 1036 | 1028: "תתרכ״ח", 1037 | 1029: "תתרכ״ט", 1038 | 1030: "תתר״ל", 1039 | 1031: "תתרל״א", 1040 | 1032: "תתרל״ב", 1041 | 1033: "תתרל״ג", 1042 | 1034: "תתרל״ד", 1043 | 1035: "תתרל״ה", 1044 | 1036: "תתרל״ו", 1045 | 1037: "תתרל״ז", 1046 | 1038: "תתרל״ח", 1047 | 1039: "תתרל״ט", 1048 | 1040: "תתר״מ", 1049 | 1041: "תתרמ״א", 1050 | 1042: "תתרמ״ב", 1051 | 1043: "תתרמ״ג", 1052 | 1044: "תתרמ״ד", 1053 | 1045: "תתרמ״ה", 1054 | 1046: "תתרמ״ו", 1055 | 1047: "תתרמ״ז", 1056 | 1048: "תתרמ״ח", 1057 | 1049: "תתרמ״ט", 1058 | 1050: "תתר״נ", 1059 | 1051: "תתרנ״א", 1060 | 1052: "תתרנ״ב", 1061 | 1053: "תתרנ״ג", 1062 | 1054: "תתרנ״ד", 1063 | 1055: "תתרנ״ה", 1064 | 1056: "תתרנ״ו", 1065 | 1057: "תתרנ״ז", 1066 | 1058: "תתרנ״ח", 1067 | 1059: "תתרנ״ט", 1068 | 1060: "תתר״ס", 1069 | 1061: "תתרס״א", 1070 | 1062: "תתרס״ב", 1071 | 1063: "תתרס״ג", 1072 | 1064: "תתרס״ד", 1073 | 1065: "תתרס״ה", 1074 | 1066: "תתרס״ו", 1075 | 1067: "תתרס״ז", 1076 | 1068: "תתרס״ח", 1077 | 1069: "תתרס״ט", 1078 | 1070: "תתר״ע", 1079 | 1071: "תתרע״א", 1080 | 1072: "תתרע״ב", 1081 | 1073: "תתרע״ג", 1082 | 1074: "תתרע״ד", 1083 | 1075: "תתרע״ה", 1084 | 1076: "תתרע״ו", 1085 | 1077: "תתרע״ז", 1086 | 1078: "תתרע״ח", 1087 | 1079: "תתרע״ט", 1088 | 1080: "תתר״פ", 1089 | 1081: "תתרפ״א", 1090 | 1082: "תתרפ״ב", 1091 | 1083: "תתרפ״ג", 1092 | 1084: "תתרפ״ד", 1093 | 1085: "תתרפ״ה", 1094 | 1086: "תתרפ״ו", 1095 | 1087: "תתרפ״ז", 1096 | 1088: "תתרפ״ח", 1097 | 1089: "תתרפ״ט", 1098 | 1090: "תתר״צ", 1099 | 1091: "תתרצ״א", 1100 | 1092: "תתרצ״ב", 1101 | 1093: "תתרצ״ג", 1102 | 1094: "תתרצ״ד", 1103 | 1095: "תתרצ״ה", 1104 | 1096: "תתרצ״ו", 1105 | 1097: "תתרצ״ז", 1106 | 1098: "תתרצ״ח", 1107 | 1099: "תתרצ״ט", 1108 | 1100: "תת״ש", 1109 | 1101: "תתש״א", 1110 | 1102: "תתש״ב", 1111 | 1103: "תתש״ג", 1112 | 1104: "תתש״ד", 1113 | 1105: "תתש״ה", 1114 | 1106: "תתש״ו", 1115 | 1107: "תתש״ז", 1116 | 1108: "תתש״ח", 1117 | 1109: "תתש״ט", 1118 | 1110: "תתש״י", 1119 | 1111: "תתשי״א", 1120 | 1112: "תתשי״ב", 1121 | 1113: "תתשי״ג", 1122 | 1114: "תתשי״ד", 1123 | 1115: "תתשט״ו", 1124 | 1116: "תתשט״ז", 1125 | 1117: "תתשי״ז", 1126 | 1118: "תתשי״ח", 1127 | 1119: "תתשי״ט", 1128 | 1120: "תתש״כ", 1129 | 1121: "תתשכ״א", 1130 | 1122: "תתשכ״ב", 1131 | 1123: "תתשכ״ג", 1132 | 1124: "תתשכ״ד", 1133 | 1125: "תתשכ״ה", 1134 | 1126: "תתשכ״ו", 1135 | 1127: "תתשכ״ז", 1136 | 1128: "תתשכ״ח", 1137 | 1129: "תתשכ״ט", 1138 | 1130: "תתש״ל", 1139 | 1131: "תתשל״א", 1140 | 1132: "תתשל״ב", 1141 | 1133: "תתשל״ג", 1142 | 1134: "תתשל״ד", 1143 | 1135: "תתשל״ה", 1144 | 1136: "תתשל״ו", 1145 | 1137: "תתשל״ז", 1146 | 1138: "תתשל״ח", 1147 | 1139: "תתשל״ט", 1148 | 1140: "תתש״מ", 1149 | 1141: "תתשמ״א", 1150 | 1142: "תתשמ״ב", 1151 | 1143: "תתשמ״ג", 1152 | 1144: "תתשמ״ד", 1153 | 1145: "תתשמ״ה", 1154 | 1146: "תתשמ״ו", 1155 | 1147: "תתשמ״ז", 1156 | 1148: "תתשמ״ח", 1157 | 1149: "תתשמ״ט", 1158 | 1150: "תתש״נ", 1159 | 1151: "תתשנ״א", 1160 | 1152: "תתשנ״ב", 1161 | 1153: "תתשנ״ג", 1162 | 1154: "תתשנ״ד", 1163 | 1155: "תתשנ״ה", 1164 | 1156: "תתשנ״ו", 1165 | 1157: "תתשנ״ז", 1166 | 1158: "תתשנ״ח", 1167 | 1159: "תתשנ״ט", 1168 | 1160: "תתש״ס", 1169 | 1161: "תתשס״א", 1170 | 1162: "תתשס״ב", 1171 | 1163: "תתשס״ג", 1172 | 1164: "תתשס״ד", 1173 | 1165: "תתשס״ה", 1174 | 1166: "תתשס״ו", 1175 | 1167: "תתשס״ז", 1176 | 1168: "תתשס״ח", 1177 | 1169: "תתשס״ט", 1178 | 1170: "תתש״ע", 1179 | 1171: "תתשע״א", 1180 | 1172: "תתשע״ב", 1181 | 1173: "תתשע״ג", 1182 | 1174: "תתשע״ד", 1183 | 1175: "תתשע״ה", 1184 | 1176: "תתשע״ו", 1185 | 1177: "תתשע״ז", 1186 | 1178: "תתשע״ח", 1187 | 1179: "תתשע״ט", 1188 | 1180: "תתש״פ", 1189 | 1181: "תתשפ״א", 1190 | 1182: "תתשפ״ב", 1191 | 1183: "תתשפ״ג", 1192 | 1184: "תתשפ״ד", 1193 | 1185: "תתשפ״ה", 1194 | 1186: "תתשפ״ו", 1195 | 1187: "תתשפ״ז", 1196 | 1188: "תתשפ״ח", 1197 | 1189: "תתשפ״ט", 1198 | 1190: "תתש״צ", 1199 | 1191: "תתשצ״א", 1200 | 1192: "תתשצ״ב", 1201 | 1193: "תתשצ״ג", 1202 | 1194: "תתשצ״ד", 1203 | 1195: "תתשצ״ה", 1204 | 1196: "תתשצ״ו", 1205 | 1197: "תתשצ״ז", 1206 | 1198: "תתשצ״ח", 1207 | 1199: "תתשצ״ט", 1208 | 4567: "תתתתתתתתתתתקס״ז", 1209 | } 1210 | NO_PUNCTUATION = { 1211 | 1: "א", 1212 | 2: "ב", 1213 | 3: "ג", 1214 | 4: "ד", 1215 | 5: "ה", 1216 | 6: "ו", 1217 | 7: "ז", 1218 | 8: "ח", 1219 | 9: "ט", 1220 | 10: "י", 1221 | 11: "יא", 1222 | 12: "יב", 1223 | 13: "יג", 1224 | 14: "יד", 1225 | 15: "טו", 1226 | 16: "טז", 1227 | 17: "יז", 1228 | 18: "יח", 1229 | 19: "יט", 1230 | 20: "כ", 1231 | 21: "כא", 1232 | 22: "כב", 1233 | 23: "כג", 1234 | 24: "כד", 1235 | 25: "כה", 1236 | 26: "כו", 1237 | 27: "כז", 1238 | 28: "כח", 1239 | 29: "כט", 1240 | 30: "ל", 1241 | 31: "לא", 1242 | 32: "לב", 1243 | 33: "לג", 1244 | 34: "לד", 1245 | 35: "לה", 1246 | 36: "לו", 1247 | 37: "לז", 1248 | 38: "לח", 1249 | 39: "לט", 1250 | 40: "מ", 1251 | 41: "מא", 1252 | 42: "מב", 1253 | 43: "מג", 1254 | 44: "מד", 1255 | 45: "מה", 1256 | 46: "מו", 1257 | 47: "מז", 1258 | 48: "מח", 1259 | 49: "מט", 1260 | 50: "נ", 1261 | 51: "נא", 1262 | 52: "נב", 1263 | 53: "נג", 1264 | 54: "נד", 1265 | 55: "נה", 1266 | 56: "נו", 1267 | 57: "נז", 1268 | 58: "נח", 1269 | 59: "נט", 1270 | 60: "ס", 1271 | 61: "סא", 1272 | 62: "סב", 1273 | 63: "סג", 1274 | 64: "סד", 1275 | 65: "סה", 1276 | 66: "סו", 1277 | 67: "סז", 1278 | 68: "סח", 1279 | 69: "סט", 1280 | 70: "ע", 1281 | 71: "עא", 1282 | 72: "עב", 1283 | 73: "עג", 1284 | 74: "עד", 1285 | 75: "עה", 1286 | 76: "עו", 1287 | 77: "עז", 1288 | 78: "עח", 1289 | 79: "עט", 1290 | 80: "פ", 1291 | 81: "פא", 1292 | 82: "פב", 1293 | 83: "פג", 1294 | 84: "פד", 1295 | 85: "פה", 1296 | 86: "פו", 1297 | 87: "פז", 1298 | 88: "פח", 1299 | 89: "פט", 1300 | 90: "צ", 1301 | 91: "צא", 1302 | 92: "צב", 1303 | 93: "צג", 1304 | 94: "צד", 1305 | 95: "צה", 1306 | 96: "צו", 1307 | 97: "צז", 1308 | 98: "צח", 1309 | 99: "צט", 1310 | 100: "ק", 1311 | 101: "קא", 1312 | 102: "קב", 1313 | 103: "קג", 1314 | 104: "קד", 1315 | 105: "קה", 1316 | 106: "קו", 1317 | 107: "קז", 1318 | 108: "קח", 1319 | 109: "קט", 1320 | 110: "קי", 1321 | 111: "קיא", 1322 | 112: "קיב", 1323 | 113: "קיג", 1324 | 114: "קיד", 1325 | 115: "קטו", 1326 | 116: "קטז", 1327 | 117: "קיז", 1328 | 118: "קיח", 1329 | 119: "קיט", 1330 | 120: "קכ", 1331 | 121: "קכא", 1332 | 122: "קכב", 1333 | 123: "קכג", 1334 | 124: "קכד", 1335 | 125: "קכה", 1336 | 126: "קכו", 1337 | 127: "קכז", 1338 | 128: "קכח", 1339 | 129: "קכט", 1340 | 130: "קל", 1341 | 131: "קלא", 1342 | 132: "קלב", 1343 | 133: "קלג", 1344 | 134: "קלד", 1345 | 135: "קלה", 1346 | 136: "קלו", 1347 | 137: "קלז", 1348 | 138: "קלח", 1349 | 139: "קלט", 1350 | 140: "קמ", 1351 | 141: "קמא", 1352 | 142: "קמב", 1353 | 143: "קמג", 1354 | 144: "קמד", 1355 | 145: "קמה", 1356 | 146: "קמו", 1357 | 147: "קמז", 1358 | 148: "קמח", 1359 | 149: "קמט", 1360 | 150: "קנ", 1361 | 151: "קנא", 1362 | 152: "קנב", 1363 | 153: "קנג", 1364 | 154: "קנד", 1365 | 155: "קנה", 1366 | 156: "קנו", 1367 | 157: "קנז", 1368 | 158: "קנח", 1369 | 159: "קנט", 1370 | 160: "קס", 1371 | 161: "קסא", 1372 | 162: "קסב", 1373 | 163: "קסג", 1374 | 164: "קסד", 1375 | 165: "קסה", 1376 | 166: "קסו", 1377 | 167: "קסז", 1378 | 168: "קסח", 1379 | 169: "קסט", 1380 | 170: "קע", 1381 | 171: "קעא", 1382 | 172: "קעב", 1383 | 173: "קעג", 1384 | 174: "קעד", 1385 | 175: "קעה", 1386 | 176: "קעו", 1387 | 177: "קעז", 1388 | 178: "קעח", 1389 | 179: "קעט", 1390 | 180: "קפ", 1391 | 181: "קפא", 1392 | 182: "קפב", 1393 | 183: "קפג", 1394 | 184: "קפד", 1395 | 185: "קפה", 1396 | 186: "קפו", 1397 | 187: "קפז", 1398 | 188: "קפח", 1399 | 189: "קפט", 1400 | 190: "קצ", 1401 | 191: "קצא", 1402 | 192: "קצב", 1403 | 193: "קצג", 1404 | 194: "קצד", 1405 | 195: "קצה", 1406 | 196: "קצו", 1407 | 197: "קצז", 1408 | 198: "קצח", 1409 | 199: "קצט", 1410 | 200: "ר", 1411 | 201: "רא", 1412 | 202: "רב", 1413 | 203: "רג", 1414 | 204: "רד", 1415 | 205: "רה", 1416 | 206: "רו", 1417 | 207: "רז", 1418 | 208: "רח", 1419 | 209: "רט", 1420 | 210: "רי", 1421 | 211: "ריא", 1422 | 212: "ריב", 1423 | 213: "ריג", 1424 | 214: "ריד", 1425 | 215: "רטו", 1426 | 216: "רטז", 1427 | 217: "ריז", 1428 | 218: "ריח", 1429 | 219: "ריט", 1430 | 220: "רכ", 1431 | 221: "רכא", 1432 | 222: "רכב", 1433 | 223: "רכג", 1434 | 224: "רכד", 1435 | 225: "רכה", 1436 | 226: "רכו", 1437 | 227: "רכז", 1438 | 228: "רכח", 1439 | 229: "רכט", 1440 | 230: "רל", 1441 | 231: "רלא", 1442 | 232: "רלב", 1443 | 233: "רלג", 1444 | 234: "רלד", 1445 | 235: "רלה", 1446 | 236: "רלו", 1447 | 237: "רלז", 1448 | 238: "רלח", 1449 | 239: "רלט", 1450 | 240: "רמ", 1451 | 241: "רמא", 1452 | 242: "רמב", 1453 | 243: "רמג", 1454 | 244: "רמד", 1455 | 245: "רמה", 1456 | 246: "רמו", 1457 | 247: "רמז", 1458 | 248: "רמח", 1459 | 249: "רמט", 1460 | 250: "רנ", 1461 | 251: "רנא", 1462 | 252: "רנב", 1463 | 253: "רנג", 1464 | 254: "רנד", 1465 | 255: "רנה", 1466 | 256: "רנו", 1467 | 257: "רנז", 1468 | 258: "רנח", 1469 | 259: "רנט", 1470 | 260: "רס", 1471 | 261: "רסא", 1472 | 262: "רסב", 1473 | 263: "רסג", 1474 | 264: "רסד", 1475 | 265: "רסה", 1476 | 266: "רסו", 1477 | 267: "רסז", 1478 | 268: "רסח", 1479 | 269: "רסט", 1480 | 270: "רע", 1481 | 271: "רעא", 1482 | 272: "רעב", 1483 | 273: "רעג", 1484 | 274: "רעד", 1485 | 275: "רעה", 1486 | 276: "רעו", 1487 | 277: "רעז", 1488 | 278: "רעח", 1489 | 279: "רעט", 1490 | 280: "רפ", 1491 | 281: "רפא", 1492 | 282: "רפב", 1493 | 283: "רפג", 1494 | 284: "רפד", 1495 | 285: "רפה", 1496 | 286: "רפו", 1497 | 287: "רפז", 1498 | 288: "רפח", 1499 | 289: "רפט", 1500 | 290: "רצ", 1501 | 291: "רצא", 1502 | 292: "רצב", 1503 | 293: "רצג", 1504 | 294: "רצד", 1505 | 295: "רצה", 1506 | 296: "רצו", 1507 | 297: "רצז", 1508 | 298: "רצח", 1509 | 299: "רצט", 1510 | 300: "ש", 1511 | 301: "שא", 1512 | 302: "שב", 1513 | 303: "שג", 1514 | 304: "שד", 1515 | 305: "שה", 1516 | 306: "שו", 1517 | 307: "שז", 1518 | 308: "שח", 1519 | 309: "שט", 1520 | 310: "שי", 1521 | 311: "שיא", 1522 | 312: "שיב", 1523 | 313: "שיג", 1524 | 314: "שיד", 1525 | 315: "שטו", 1526 | 316: "שטז", 1527 | 317: "שיז", 1528 | 318: "שיח", 1529 | 319: "שיט", 1530 | 320: "שכ", 1531 | 321: "שכא", 1532 | 322: "שכב", 1533 | 323: "שכג", 1534 | 324: "שכד", 1535 | 325: "שכה", 1536 | 326: "שכו", 1537 | 327: "שכז", 1538 | 328: "שכח", 1539 | 329: "שכט", 1540 | 330: "של", 1541 | 331: "שלא", 1542 | 332: "שלב", 1543 | 333: "שלג", 1544 | 334: "שלד", 1545 | 335: "שלה", 1546 | 336: "שלו", 1547 | 337: "שלז", 1548 | 338: "שלח", 1549 | 339: "שלט", 1550 | 340: "שמ", 1551 | 341: "שמא", 1552 | 342: "שמב", 1553 | 343: "שמג", 1554 | 344: "שמד", 1555 | 345: "שמה", 1556 | 346: "שמו", 1557 | 347: "שמז", 1558 | 348: "שמח", 1559 | 349: "שמט", 1560 | 350: "שנ", 1561 | 351: "שנא", 1562 | 352: "שנב", 1563 | 353: "שנג", 1564 | 354: "שנד", 1565 | 355: "שנה", 1566 | 356: "שנו", 1567 | 357: "שנז", 1568 | 358: "שנח", 1569 | 359: "שנט", 1570 | 360: "שס", 1571 | 361: "שסא", 1572 | 362: "שסב", 1573 | 363: "שסג", 1574 | 364: "שסד", 1575 | 365: "שסה", 1576 | 366: "שסו", 1577 | 367: "שסז", 1578 | 368: "שסח", 1579 | 369: "שסט", 1580 | 370: "שע", 1581 | 371: "שעא", 1582 | 372: "שעב", 1583 | 373: "שעג", 1584 | 374: "שעד", 1585 | 375: "שעה", 1586 | 376: "שעו", 1587 | 377: "שעז", 1588 | 378: "שעח", 1589 | 379: "שעט", 1590 | 380: "שפ", 1591 | 381: "שפא", 1592 | 382: "שפב", 1593 | 383: "שפג", 1594 | 384: "שפד", 1595 | 385: "שפה", 1596 | 386: "שפו", 1597 | 387: "שפז", 1598 | 388: "שפח", 1599 | 389: "שפט", 1600 | 390: "שצ", 1601 | 391: "שצא", 1602 | 392: "שצב", 1603 | 393: "שצג", 1604 | 394: "שצד", 1605 | 395: "שצה", 1606 | 396: "שצו", 1607 | 397: "שצז", 1608 | 398: "שצח", 1609 | 399: "שצט", 1610 | 400: "ת", 1611 | 401: "תא", 1612 | 402: "תב", 1613 | 403: "תג", 1614 | 404: "תד", 1615 | 405: "תה", 1616 | 406: "תו", 1617 | 407: "תז", 1618 | 408: "תח", 1619 | 409: "תט", 1620 | 410: "תי", 1621 | 411: "תיא", 1622 | 412: "תיב", 1623 | 413: "תיג", 1624 | 414: "תיד", 1625 | 415: "תטו", 1626 | 416: "תטז", 1627 | 417: "תיז", 1628 | 418: "תיח", 1629 | 419: "תיט", 1630 | 420: "תכ", 1631 | 421: "תכא", 1632 | 422: "תכב", 1633 | 423: "תכג", 1634 | 424: "תכד", 1635 | 425: "תכה", 1636 | 426: "תכו", 1637 | 427: "תכז", 1638 | 428: "תכח", 1639 | 429: "תכט", 1640 | 430: "תל", 1641 | 431: "תלא", 1642 | 432: "תלב", 1643 | 433: "תלג", 1644 | 434: "תלד", 1645 | 435: "תלה", 1646 | 436: "תלו", 1647 | 437: "תלז", 1648 | 438: "תלח", 1649 | 439: "תלט", 1650 | 440: "תמ", 1651 | 441: "תמא", 1652 | 442: "תמב", 1653 | 443: "תמג", 1654 | 444: "תמד", 1655 | 445: "תמה", 1656 | 446: "תמו", 1657 | 447: "תמז", 1658 | 448: "תמח", 1659 | 449: "תמט", 1660 | 450: "תנ", 1661 | 451: "תנא", 1662 | 452: "תנב", 1663 | 453: "תנג", 1664 | 454: "תנד", 1665 | 455: "תנה", 1666 | 456: "תנו", 1667 | 457: "תנז", 1668 | 458: "תנח", 1669 | 459: "תנט", 1670 | 460: "תס", 1671 | 461: "תסא", 1672 | 462: "תסב", 1673 | 463: "תסג", 1674 | 464: "תסד", 1675 | 465: "תסה", 1676 | 466: "תסו", 1677 | 467: "תסז", 1678 | 468: "תסח", 1679 | 469: "תסט", 1680 | 470: "תע", 1681 | 471: "תעא", 1682 | 472: "תעב", 1683 | 473: "תעג", 1684 | 474: "תעד", 1685 | 475: "תעה", 1686 | 476: "תעו", 1687 | 477: "תעז", 1688 | 478: "תעח", 1689 | 479: "תעט", 1690 | 480: "תפ", 1691 | 481: "תפא", 1692 | 482: "תפב", 1693 | 483: "תפג", 1694 | 484: "תפד", 1695 | 485: "תפה", 1696 | 486: "תפו", 1697 | 487: "תפז", 1698 | 488: "תפח", 1699 | 489: "תפט", 1700 | 490: "תצ", 1701 | 491: "תצא", 1702 | 492: "תצב", 1703 | 493: "תצג", 1704 | 494: "תצד", 1705 | 495: "תצה", 1706 | 496: "תצו", 1707 | 497: "תצז", 1708 | 498: "תצח", 1709 | 499: "תצט", 1710 | 500: "תק", 1711 | 501: "תקא", 1712 | 502: "תקב", 1713 | 503: "תקג", 1714 | 504: "תקד", 1715 | 505: "תקה", 1716 | 506: "תקו", 1717 | 507: "תקז", 1718 | 508: "תקח", 1719 | 509: "תקט", 1720 | 510: "תקי", 1721 | 511: "תקיא", 1722 | 512: "תקיב", 1723 | 513: "תקיג", 1724 | 514: "תקיד", 1725 | 515: "תקטו", 1726 | 516: "תקטז", 1727 | 517: "תקיז", 1728 | 518: "תקיח", 1729 | 519: "תקיט", 1730 | 520: "תקכ", 1731 | 521: "תקכא", 1732 | 522: "תקכב", 1733 | 523: "תקכג", 1734 | 524: "תקכד", 1735 | 525: "תקכה", 1736 | 526: "תקכו", 1737 | 527: "תקכז", 1738 | 528: "תקכח", 1739 | 529: "תקכט", 1740 | 530: "תקל", 1741 | 531: "תקלא", 1742 | 532: "תקלב", 1743 | 533: "תקלג", 1744 | 534: "תקלד", 1745 | 535: "תקלה", 1746 | 536: "תקלו", 1747 | 537: "תקלז", 1748 | 538: "תקלח", 1749 | 539: "תקלט", 1750 | 540: "תקמ", 1751 | 541: "תקמא", 1752 | 542: "תקמב", 1753 | 543: "תקמג", 1754 | 544: "תקמד", 1755 | 545: "תקמה", 1756 | 546: "תקמו", 1757 | 547: "תקמז", 1758 | 548: "תקמח", 1759 | 549: "תקמט", 1760 | 550: "תקנ", 1761 | 551: "תקנא", 1762 | 552: "תקנב", 1763 | 553: "תקנג", 1764 | 554: "תקנד", 1765 | 555: "תקנה", 1766 | 556: "תקנו", 1767 | 557: "תקנז", 1768 | 558: "תקנח", 1769 | 559: "תקנט", 1770 | 560: "תקס", 1771 | 561: "תקסא", 1772 | 562: "תקסב", 1773 | 563: "תקסג", 1774 | 564: "תקסד", 1775 | 565: "תקסה", 1776 | 566: "תקסו", 1777 | 567: "תקסז", 1778 | 568: "תקסח", 1779 | 569: "תקסט", 1780 | 570: "תקע", 1781 | 571: "תקעא", 1782 | 572: "תקעב", 1783 | 573: "תקעג", 1784 | 574: "תקעד", 1785 | 575: "תקעה", 1786 | 576: "תקעו", 1787 | 577: "תקעז", 1788 | 578: "תקעח", 1789 | 579: "תקעט", 1790 | 580: "תקפ", 1791 | 581: "תקפא", 1792 | 582: "תקפב", 1793 | 583: "תקפג", 1794 | 584: "תקפד", 1795 | 585: "תקפה", 1796 | 586: "תקפו", 1797 | 587: "תקפז", 1798 | 588: "תקפח", 1799 | 589: "תקפט", 1800 | 590: "תקצ", 1801 | 591: "תקצא", 1802 | 592: "תקצב", 1803 | 593: "תקצג", 1804 | 594: "תקצד", 1805 | 595: "תקצה", 1806 | 596: "תקצו", 1807 | 597: "תקצז", 1808 | 598: "תקצח", 1809 | 599: "תקצט", 1810 | 600: "תר", 1811 | 601: "תרא", 1812 | 602: "תרב", 1813 | 603: "תרג", 1814 | 604: "תרד", 1815 | 605: "תרה", 1816 | 606: "תרו", 1817 | 607: "תרז", 1818 | 608: "תרח", 1819 | 609: "תרט", 1820 | 610: "תרי", 1821 | 611: "תריא", 1822 | 612: "תריב", 1823 | 613: "תריג", 1824 | 614: "תריד", 1825 | 615: "תרטו", 1826 | 616: "תרטז", 1827 | 617: "תריז", 1828 | 618: "תריח", 1829 | 619: "תריט", 1830 | 620: "תרכ", 1831 | 621: "תרכא", 1832 | 622: "תרכב", 1833 | 623: "תרכג", 1834 | 624: "תרכד", 1835 | 625: "תרכה", 1836 | 626: "תרכו", 1837 | 627: "תרכז", 1838 | 628: "תרכח", 1839 | 629: "תרכט", 1840 | 630: "תרל", 1841 | 631: "תרלא", 1842 | 632: "תרלב", 1843 | 633: "תרלג", 1844 | 634: "תרלד", 1845 | 635: "תרלה", 1846 | 636: "תרלו", 1847 | 637: "תרלז", 1848 | 638: "תרלח", 1849 | 639: "תרלט", 1850 | 640: "תרמ", 1851 | 641: "תרמא", 1852 | 642: "תרמב", 1853 | 643: "תרמג", 1854 | 644: "תרמד", 1855 | 645: "תרמה", 1856 | 646: "תרמו", 1857 | 647: "תרמז", 1858 | 648: "תרמח", 1859 | 649: "תרמט", 1860 | 650: "תרנ", 1861 | 651: "תרנא", 1862 | 652: "תרנב", 1863 | 653: "תרנג", 1864 | 654: "תרנד", 1865 | 655: "תרנה", 1866 | 656: "תרנו", 1867 | 657: "תרנז", 1868 | 658: "תרנח", 1869 | 659: "תרנט", 1870 | 660: "תרס", 1871 | 661: "תרסא", 1872 | 662: "תרסב", 1873 | 663: "תרסג", 1874 | 664: "תרסד", 1875 | 665: "תרסה", 1876 | 666: "תרסו", 1877 | 667: "תרסז", 1878 | 668: "תרסח", 1879 | 669: "תרסט", 1880 | 670: "תרע", 1881 | 671: "תרעא", 1882 | 672: "תרעב", 1883 | 673: "תרעג", 1884 | 674: "תרעד", 1885 | 675: "תרעה", 1886 | 676: "תרעו", 1887 | 677: "תרעז", 1888 | 678: "תרעח", 1889 | 679: "תרעט", 1890 | 680: "תרפ", 1891 | 681: "תרפא", 1892 | 682: "תרפב", 1893 | 683: "תרפג", 1894 | 684: "תרפד", 1895 | 685: "תרפה", 1896 | 686: "תרפו", 1897 | 687: "תרפז", 1898 | 688: "תרפח", 1899 | 689: "תרפט", 1900 | 690: "תרצ", 1901 | 691: "תרצא", 1902 | 692: "תרצב", 1903 | 693: "תרצג", 1904 | 694: "תרצד", 1905 | 695: "תרצה", 1906 | 696: "תרצו", 1907 | 697: "תרצז", 1908 | 698: "תרצח", 1909 | 699: "תרצט", 1910 | 700: "תש", 1911 | 701: "תשא", 1912 | 702: "תשב", 1913 | 703: "תשג", 1914 | 704: "תשד", 1915 | 705: "תשה", 1916 | 706: "תשו", 1917 | 707: "תשז", 1918 | 708: "תשח", 1919 | 709: "תשט", 1920 | 710: "תשי", 1921 | 711: "תשיא", 1922 | 712: "תשיב", 1923 | 713: "תשיג", 1924 | 714: "תשיד", 1925 | 715: "תשטו", 1926 | 716: "תשטז", 1927 | 717: "תשיז", 1928 | 718: "תשיח", 1929 | 719: "תשיט", 1930 | 720: "תשכ", 1931 | 721: "תשכא", 1932 | 722: "תשכב", 1933 | 723: "תשכג", 1934 | 724: "תשכד", 1935 | 725: "תשכה", 1936 | 726: "תשכו", 1937 | 727: "תשכז", 1938 | 728: "תשכח", 1939 | 729: "תשכט", 1940 | 730: "תשל", 1941 | 731: "תשלא", 1942 | 732: "תשלב", 1943 | 733: "תשלג", 1944 | 734: "תשלד", 1945 | 735: "תשלה", 1946 | 736: "תשלו", 1947 | 737: "תשלז", 1948 | 738: "תשלח", 1949 | 739: "תשלט", 1950 | 740: "תשמ", 1951 | 741: "תשמא", 1952 | 742: "תשמב", 1953 | 743: "תשמג", 1954 | 744: "תשמד", 1955 | 745: "תשמה", 1956 | 746: "תשמו", 1957 | 747: "תשמז", 1958 | 748: "תשמח", 1959 | 749: "תשמט", 1960 | 750: "תשנ", 1961 | 751: "תשנא", 1962 | 752: "תשנב", 1963 | 753: "תשנג", 1964 | 754: "תשנד", 1965 | 755: "תשנה", 1966 | 756: "תשנו", 1967 | 757: "תשנז", 1968 | 758: "תשנח", 1969 | 759: "תשנט", 1970 | 760: "תשס", 1971 | 761: "תשסא", 1972 | 762: "תשסב", 1973 | 763: "תשסג", 1974 | 764: "תשסד", 1975 | 765: "תשסה", 1976 | 766: "תשסו", 1977 | 767: "תשסז", 1978 | 768: "תשסח", 1979 | 769: "תשסט", 1980 | 770: "תשע", 1981 | 771: "תשעא", 1982 | 772: "תשעב", 1983 | 773: "תשעג", 1984 | 774: "תשעד", 1985 | 775: "תשעה", 1986 | 776: "תשעו", 1987 | 777: "תשעז", 1988 | 778: "תשעח", 1989 | 779: "תשעט", 1990 | 780: "תשפ", 1991 | 781: "תשפא", 1992 | 782: "תשפב", 1993 | 783: "תשפג", 1994 | 784: "תשפד", 1995 | 785: "תשפה", 1996 | 786: "תשפו", 1997 | 787: "תשפז", 1998 | 788: "תשפח", 1999 | 789: "תשפט", 2000 | 790: "תשצ", 2001 | 791: "תשצא", 2002 | 792: "תשצב", 2003 | 793: "תשצג", 2004 | 794: "תשצד", 2005 | 795: "תשצה", 2006 | 796: "תשצו", 2007 | 797: "תשצז", 2008 | 798: "תשצח", 2009 | 799: "תשצט", 2010 | 800: "תת", 2011 | 801: "תתא", 2012 | 802: "תתב", 2013 | 803: "תתג", 2014 | 804: "תתד", 2015 | 805: "תתה", 2016 | 806: "תתו", 2017 | 807: "תתז", 2018 | 808: "תתח", 2019 | 809: "תתט", 2020 | 810: "תתי", 2021 | 811: "תתיא", 2022 | 812: "תתיב", 2023 | 813: "תתיג", 2024 | 814: "תתיד", 2025 | 815: "תתטו", 2026 | 816: "תתטז", 2027 | 817: "תתיז", 2028 | 818: "תתיח", 2029 | 819: "תתיט", 2030 | 820: "תתכ", 2031 | 821: "תתכא", 2032 | 822: "תתכב", 2033 | 823: "תתכג", 2034 | 824: "תתכד", 2035 | 825: "תתכה", 2036 | 826: "תתכו", 2037 | 827: "תתכז", 2038 | 828: "תתכח", 2039 | 829: "תתכט", 2040 | 830: "תתל", 2041 | 831: "תתלא", 2042 | 832: "תתלב", 2043 | 833: "תתלג", 2044 | 834: "תתלד", 2045 | 835: "תתלה", 2046 | 836: "תתלו", 2047 | 837: "תתלז", 2048 | 838: "תתלח", 2049 | 839: "תתלט", 2050 | 840: "תתמ", 2051 | 841: "תתמא", 2052 | 842: "תתמב", 2053 | 843: "תתמג", 2054 | 844: "תתמד", 2055 | 845: "תתמה", 2056 | 846: "תתמו", 2057 | 847: "תתמז", 2058 | 848: "תתמח", 2059 | 849: "תתמט", 2060 | 850: "תתנ", 2061 | 851: "תתנא", 2062 | 852: "תתנב", 2063 | 853: "תתנג", 2064 | 854: "תתנד", 2065 | 855: "תתנה", 2066 | 856: "תתנו", 2067 | 857: "תתנז", 2068 | 858: "תתנח", 2069 | 859: "תתנט", 2070 | 860: "תתס", 2071 | 861: "תתסא", 2072 | 862: "תתסב", 2073 | 863: "תתסג", 2074 | 864: "תתסד", 2075 | 865: "תתסה", 2076 | 866: "תתסו", 2077 | 867: "תתסז", 2078 | 868: "תתסח", 2079 | 869: "תתסט", 2080 | 870: "תתע", 2081 | 871: "תתעא", 2082 | 872: "תתעב", 2083 | 873: "תתעג", 2084 | 874: "תתעד", 2085 | 875: "תתעה", 2086 | 876: "תתעו", 2087 | 877: "תתעז", 2088 | 878: "תתעח", 2089 | 879: "תתעט", 2090 | 880: "תתפ", 2091 | 881: "תתפא", 2092 | 882: "תתפב", 2093 | 883: "תתפג", 2094 | 884: "תתפד", 2095 | 885: "תתפה", 2096 | 886: "תתפו", 2097 | 887: "תתפז", 2098 | 888: "תתפח", 2099 | 889: "תתפט", 2100 | 890: "תתצ", 2101 | 891: "תתצא", 2102 | 892: "תתצב", 2103 | 893: "תתצג", 2104 | 894: "תתצד", 2105 | 895: "תתצה", 2106 | 896: "תתצו", 2107 | 897: "תתצז", 2108 | 898: "תתצח", 2109 | 899: "תתצט", 2110 | 900: "תתק", 2111 | 901: "תתקא", 2112 | 902: "תתקב", 2113 | 903: "תתקג", 2114 | 904: "תתקד", 2115 | 905: "תתקה", 2116 | 906: "תתקו", 2117 | 907: "תתקז", 2118 | 908: "תתקח", 2119 | 909: "תתקט", 2120 | 910: "תתקי", 2121 | 911: "תתקיא", 2122 | 912: "תתקיב", 2123 | 913: "תתקיג", 2124 | 914: "תתקיד", 2125 | 915: "תתקטו", 2126 | 916: "תתקטז", 2127 | 917: "תתקיז", 2128 | 918: "תתקיח", 2129 | 919: "תתקיט", 2130 | 920: "תתקכ", 2131 | 921: "תתקכא", 2132 | 922: "תתקכב", 2133 | 923: "תתקכג", 2134 | 924: "תתקכד", 2135 | 925: "תתקכה", 2136 | 926: "תתקכו", 2137 | 927: "תתקכז", 2138 | 928: "תתקכח", 2139 | 929: "תתקכט", 2140 | 930: "תתקל", 2141 | 931: "תתקלא", 2142 | 932: "תתקלב", 2143 | 933: "תתקלג", 2144 | 934: "תתקלד", 2145 | 935: "תתקלה", 2146 | 936: "תתקלו", 2147 | 937: "תתקלז", 2148 | 938: "תתקלח", 2149 | 939: "תתקלט", 2150 | 940: "תתקמ", 2151 | 941: "תתקמא", 2152 | 942: "תתקמב", 2153 | 943: "תתקמג", 2154 | 944: "תתקמד", 2155 | 945: "תתקמה", 2156 | 946: "תתקמו", 2157 | 947: "תתקמז", 2158 | 948: "תתקמח", 2159 | 949: "תתקמט", 2160 | 950: "תתקנ", 2161 | 951: "תתקנא", 2162 | 952: "תתקנב", 2163 | 953: "תתקנג", 2164 | 954: "תתקנד", 2165 | 955: "תתקנה", 2166 | 956: "תתקנו", 2167 | 957: "תתקנז", 2168 | 958: "תתקנח", 2169 | 959: "תתקנט", 2170 | 960: "תתקס", 2171 | 961: "תתקסא", 2172 | 962: "תתקסב", 2173 | 963: "תתקסג", 2174 | 964: "תתקסד", 2175 | 965: "תתקסה", 2176 | 966: "תתקסו", 2177 | 967: "תתקסז", 2178 | 968: "תתקסח", 2179 | 969: "תתקסט", 2180 | 970: "תתקע", 2181 | 971: "תתקעא", 2182 | 972: "תתקעב", 2183 | 973: "תתקעג", 2184 | 974: "תתקעד", 2185 | 975: "תתקעה", 2186 | 976: "תתקעו", 2187 | 977: "תתקעז", 2188 | 978: "תתקעח", 2189 | 979: "תתקעט", 2190 | 980: "תתקפ", 2191 | 981: "תתקפא", 2192 | 982: "תתקפב", 2193 | 983: "תתקפג", 2194 | 984: "תתקפד", 2195 | 985: "תתקפה", 2196 | 986: "תתקפו", 2197 | 987: "תתקפז", 2198 | 988: "תתקפח", 2199 | 989: "תתקפט", 2200 | 990: "תתקצ", 2201 | 991: "תתקצא", 2202 | 992: "תתקצב", 2203 | 993: "תתקצג", 2204 | 994: "תתקצד", 2205 | 995: "תתקצה", 2206 | 996: "תתקצו", 2207 | 997: "תתקצז", 2208 | 998: "תתקצח", 2209 | 999: "תתקצט", 2210 | 1000: "תתר", 2211 | 1001: "תתרא", 2212 | 1002: "תתרב", 2213 | 1003: "תתרג", 2214 | 1004: "תתרד", 2215 | 1005: "תתרה", 2216 | 1006: "תתרו", 2217 | 1007: "תתרז", 2218 | 1008: "תתרח", 2219 | 1009: "תתרט", 2220 | 1010: "תתרי", 2221 | 1011: "תתריא", 2222 | 1012: "תתריב", 2223 | 1013: "תתריג", 2224 | 1014: "תתריד", 2225 | 1015: "תתרטו", 2226 | 1016: "תתרטז", 2227 | 1017: "תתריז", 2228 | 1018: "תתריח", 2229 | 1019: "תתריט", 2230 | 1020: "תתרכ", 2231 | 1021: "תתרכא", 2232 | 1022: "תתרכב", 2233 | 1023: "תתרכג", 2234 | 1024: "תתרכד", 2235 | 1025: "תתרכה", 2236 | 1026: "תתרכו", 2237 | 1027: "תתרכז", 2238 | 1028: "תתרכח", 2239 | 1029: "תתרכט", 2240 | 1030: "תתרל", 2241 | 1031: "תתרלא", 2242 | 1032: "תתרלב", 2243 | 1033: "תתרלג", 2244 | 1034: "תתרלד", 2245 | 1035: "תתרלה", 2246 | 1036: "תתרלו", 2247 | 1037: "תתרלז", 2248 | 1038: "תתרלח", 2249 | 1039: "תתרלט", 2250 | 1040: "תתרמ", 2251 | 1041: "תתרמא", 2252 | 1042: "תתרמב", 2253 | 1043: "תתרמג", 2254 | 1044: "תתרמד", 2255 | 1045: "תתרמה", 2256 | 1046: "תתרמו", 2257 | 1047: "תתרמז", 2258 | 1048: "תתרמח", 2259 | 1049: "תתרמט", 2260 | 1050: "תתרנ", 2261 | 1051: "תתרנא", 2262 | 1052: "תתרנב", 2263 | 1053: "תתרנג", 2264 | 1054: "תתרנד", 2265 | 1055: "תתרנה", 2266 | 1056: "תתרנו", 2267 | 1057: "תתרנז", 2268 | 1058: "תתרנח", 2269 | 1059: "תתרנט", 2270 | 1060: "תתרס", 2271 | 1061: "תתרסא", 2272 | 1062: "תתרסב", 2273 | 1063: "תתרסג", 2274 | 1064: "תתרסד", 2275 | 1065: "תתרסה", 2276 | 1066: "תתרסו", 2277 | 1067: "תתרסז", 2278 | 1068: "תתרסח", 2279 | 1069: "תתרסט", 2280 | 1070: "תתרע", 2281 | 1071: "תתרעא", 2282 | 1072: "תתרעב", 2283 | 1073: "תתרעג", 2284 | 1074: "תתרעד", 2285 | 1075: "תתרעה", 2286 | 1076: "תתרעו", 2287 | 1077: "תתרעז", 2288 | 1078: "תתרעח", 2289 | 1079: "תתרעט", 2290 | 1080: "תתרפ", 2291 | 1081: "תתרפא", 2292 | 1082: "תתרפב", 2293 | 1083: "תתרפג", 2294 | 1084: "תתרפד", 2295 | 1085: "תתרפה", 2296 | 1086: "תתרפו", 2297 | 1087: "תתרפז", 2298 | 1088: "תתרפח", 2299 | 1089: "תתרפט", 2300 | 1090: "תתרצ", 2301 | 1091: "תתרצא", 2302 | 1092: "תתרצב", 2303 | 1093: "תתרצג", 2304 | 1094: "תתרצד", 2305 | 1095: "תתרצה", 2306 | 1096: "תתרצו", 2307 | 1097: "תתרצז", 2308 | 1098: "תתרצח", 2309 | 1099: "תתרצט", 2310 | 1100: "תתש", 2311 | 1101: "תתשא", 2312 | 1102: "תתשב", 2313 | 1103: "תתשג", 2314 | 1104: "תתשד", 2315 | 1105: "תתשה", 2316 | 1106: "תתשו", 2317 | 1107: "תתשז", 2318 | 1108: "תתשח", 2319 | 1109: "תתשט", 2320 | 1110: "תתשי", 2321 | 1111: "תתשיא", 2322 | 1112: "תתשיב", 2323 | 1113: "תתשיג", 2324 | 1114: "תתשיד", 2325 | 1115: "תתשטו", 2326 | 1116: "תתשטז", 2327 | 1117: "תתשיז", 2328 | 1118: "תתשיח", 2329 | 1119: "תתשיט", 2330 | 1120: "תתשכ", 2331 | 1121: "תתשכא", 2332 | 1122: "תתשכב", 2333 | 1123: "תתשכג", 2334 | 1124: "תתשכד", 2335 | 1125: "תתשכה", 2336 | 1126: "תתשכו", 2337 | 1127: "תתשכז", 2338 | 1128: "תתשכח", 2339 | 1129: "תתשכט", 2340 | 1130: "תתשל", 2341 | 1131: "תתשלא", 2342 | 1132: "תתשלב", 2343 | 1133: "תתשלג", 2344 | 1134: "תתשלד", 2345 | 1135: "תתשלה", 2346 | 1136: "תתשלו", 2347 | 1137: "תתשלז", 2348 | 1138: "תתשלח", 2349 | 1139: "תתשלט", 2350 | 1140: "תתשמ", 2351 | 1141: "תתשמא", 2352 | 1142: "תתשמב", 2353 | 1143: "תתשמג", 2354 | 1144: "תתשמד", 2355 | 1145: "תתשמה", 2356 | 1146: "תתשמו", 2357 | 1147: "תתשמז", 2358 | 1148: "תתשמח", 2359 | 1149: "תתשמט", 2360 | 1150: "תתשנ", 2361 | 1151: "תתשנא", 2362 | 1152: "תתשנב", 2363 | 1153: "תתשנג", 2364 | 1154: "תתשנד", 2365 | 1155: "תתשנה", 2366 | 1156: "תתשנו", 2367 | 1157: "תתשנז", 2368 | 1158: "תתשנח", 2369 | 1159: "תתשנט", 2370 | 1160: "תתשס", 2371 | 1161: "תתשסא", 2372 | 1162: "תתשסב", 2373 | 1163: "תתשסג", 2374 | 1164: "תתשסד", 2375 | 1165: "תתשסה", 2376 | 1166: "תתשסו", 2377 | 1167: "תתשסז", 2378 | 1168: "תתשסח", 2379 | 1169: "תתשסט", 2380 | 1170: "תתשע", 2381 | 1171: "תתשעא", 2382 | 1172: "תתשעב", 2383 | 1173: "תתשעג", 2384 | 1174: "תתשעד", 2385 | 1175: "תתשעה", 2386 | 1176: "תתשעו", 2387 | 1177: "תתשעז", 2388 | 1178: "תתשעח", 2389 | 1179: "תתשעט", 2390 | 1180: "תתשפ", 2391 | 1181: "תתשפא", 2392 | 1182: "תתשפב", 2393 | 1183: "תתשפג", 2394 | 1184: "תתשפד", 2395 | 1185: "תתשפה", 2396 | 1186: "תתשפו", 2397 | 1187: "תתשפז", 2398 | 1188: "תתשפח", 2399 | 1189: "תתשפט", 2400 | 1190: "תתשצ", 2401 | 1191: "תתשצא", 2402 | 1192: "תתשצב", 2403 | 1193: "תתשצג", 2404 | 1194: "תתשצד", 2405 | 1195: "תתשצה", 2406 | 1196: "תתשצו", 2407 | 1197: "תתשצז", 2408 | 1198: "תתשצח", 2409 | 1199: "תתשצט", 2410 | } 2411 | NO_SUBSTITUTION = { 2412 | 15: "י״ה", 2413 | 16: "י״ו", 2414 | 115: "קי״ה", 2415 | 116: "קי״ו", 2416 | 215: "רי״ה", 2417 | 216: "רי״ו", 2418 | 315: "שי״ה", 2419 | 316: "שי״ו", 2420 | 415: "תי״ה", 2421 | 416: "תי״ו", 2422 | 515: "תקי״ה", 2423 | 516: "תקי״ו", 2424 | 615: "תרי״ה", 2425 | 616: "תרי״ו", 2426 | 715: "תשי״ה", 2427 | 716: "תשי״ו", 2428 | 815: "תתי״ה", 2429 | 816: "תתי״ו", 2430 | 915: "תתקי״ה", 2431 | 916: "תתקי״ו", 2432 | 1015: "תתרי״ה", 2433 | 1016: "תתרי״ו", 2434 | 1115: "תתשי״ה", 2435 | 1116: "תתשי״ו", 2436 | } 2437 | POLITE_SUBSTITUTION = { 2438 | **NO_PUNCTUATION, 2439 | 270: "ער", 2440 | 272: "ערב", 2441 | 275: "ערה", 2442 | 298: "רחצ", 2443 | 304: "דש", 2444 | 344: "שדמ", 2445 | 670: "תער", 2446 | 672: "תערב", 2447 | 698: "תרחצ", 2448 | 744: "תשדמ", 2449 | 1070: "תתער", 2450 | 1072: "תתערב", 2451 | 1098: "תתרחצ", 2452 | 1144: "תתשדמ", 2453 | } 2454 | 2455 | 2456 | def test_no_0_input(): 2457 | with pytest.raises(ValueError): 2458 | Hebrew.from_number(0) 2459 | with pytest.raises(ValueError): 2460 | number_to_hebrew_string(0) 2461 | 2462 | 2463 | def test_no_negative_input(): 2464 | with pytest.raises(ValueError): 2465 | Hebrew.from_number(-1) 2466 | with pytest.raises(ValueError): 2467 | number_to_hebrew_string(-1) 2468 | 2469 | 2470 | @pytest.mark.parametrize("number, expected_output", NO_SUBSTITUTION.items()) 2471 | def test_no_substitutions(number, expected_output): 2472 | assert Hebrew.from_number( 2473 | number, True, True, substitution_functions=None 2474 | ) == Hebrew(expected_output) 2475 | 2476 | 2477 | @pytest.mark.parametrize("number, expected_output", POLITE_SUBSTITUTION.items()) 2478 | def test_polite_substitutions(number, expected_output): 2479 | assert Hebrew.from_number( 2480 | number, False, substitution_functions=Substitutions.ALL 2481 | ) == Hebrew(expected_output) 2482 | assert ( 2483 | number_to_hebrew_string(number, False, substitution_functions=Substitutions.ALL) 2484 | == expected_output 2485 | ) 2486 | 2487 | 2488 | @pytest.mark.parametrize("number, expected_output", WITH_GERESH.items()) 2489 | def test_with_geresh(number, expected_output): 2490 | assert Hebrew.from_number(number, True, True) == Hebrew(expected_output) 2491 | assert number_to_hebrew_string(number, True, True) == expected_output 2492 | 2493 | 2494 | @pytest.mark.parametrize( 2495 | "number, expected_output", 2496 | [(i[0], i[1].replace("׳", "'").replace("״", '"')) for i in WITH_GERESH.items()], 2497 | ) 2498 | def test_with_english_quote(number, expected_output): 2499 | assert Hebrew.from_number(number, True, False) == Hebrew(expected_output) 2500 | assert number_to_hebrew_string(number, True, False) == expected_output 2501 | 2502 | 2503 | @pytest.mark.parametrize( 2504 | "number, expected_output", 2505 | [(i[0], i[1].replace("׳", "").replace("״", "")) for i in WITH_GERESH.items()], 2506 | ) 2507 | def test_with_no_punctuation(number, expected_output): 2508 | assert Hebrew.from_number(number, False) == Hebrew(expected_output) 2509 | assert number_to_hebrew_string(number, False) == expected_output 2510 | --------------------------------------------------------------------------------