├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── scripts │ └── decrypt_secrets.sh └── workflows │ ├── build.yml │ └── codeql-analysis.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── _config.yml ├── docs ├── apininjas.md └── wordnik.md ├── poetry.lock ├── pyproject.toml ├── random_word ├── __init__.py ├── config.yml.gpg ├── database │ └── words.json ├── random_word.py ├── services │ ├── __init__.py │ ├── apininjas.py │ ├── local.py │ └── wordnik.py ├── tests │ ├── __init__.py │ ├── test_apininjas.py │ ├── test_random_word.py │ └── test_wordnik.py └── utils │ ├── __init__.py │ ├── retry_generator.py │ └── utils.py └── tox.ini /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: vaibhavsingh97 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Call function '....' 14 | 3. See error 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Environment (please complete the following information):** 23 | - OS: [e.g. MacOS, Linux, Windows] 24 | - Python [e.g. 2.7, 3.6, 3.7] 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/scripts/decrypt_secrets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Decrypt the file 4 | mkdir "$HOME/secrets" 5 | # --batch to prevent interactive command 6 | # --yes to assume "yes" for questions 7 | echo 'Directory structure' 8 | ls -la 9 | gpg --quiet --batch --yes --decrypt --passphrase="$SECRET_PASSPHRASE" \ 10 | --output "$HOME/secrets/config.yml" "random_word/config.yml.gpg" 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | schedule: 5 | - cron: "0 12 * * SUN" 6 | push: 7 | branches: 8 | - master 9 | pull_request_target: 10 | branches: [ master ] 11 | 12 | 13 | jobs: 14 | build: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | python-version: ['3.8', '3.13'] 19 | os: [ubuntu-latest, macos-latest] 20 | environment: 21 | name: random word ci 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Decrypt large secret 25 | run: ./.github/scripts/decrypt_secrets.sh 26 | env: 27 | SECRET_PASSPHRASE: ${{ secrets.SECRET_PASSPHRASE }} 28 | 29 | - name: Copying Config.yml to random_word folder 30 | run: cp $HOME/secrets/config.yml random_word/ 31 | 32 | - name: Print Directory Structure of random_word 33 | run: ls -la random_word 34 | 35 | - name: Setup Python 36 | uses: actions/setup-python@v2 37 | with: 38 | python-version: ${{ matrix.python-version }} 39 | architecture: x64 40 | 41 | - name: Install packages 42 | run: | 43 | make init 44 | 45 | - name: Python Lint 46 | run: | 47 | make lint 48 | 49 | - name: Run tests 50 | run: | 51 | make test 52 | -------------------------------------------------------------------------------- /.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: '27 18 * * 3' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | 28 | strategy: 29 | fail-fast: false 30 | matrix: 31 | language: [ 'python' ] 32 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 33 | # Learn more: 34 | # 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 35 | 36 | steps: 37 | - name: Checkout repository 38 | uses: actions/checkout@v2 39 | 40 | # Initializes the CodeQL tools for scanning. 41 | - name: Initialize CodeQL 42 | uses: github/codeql-action/init@v1 43 | with: 44 | languages: ${{ matrix.language }} 45 | # If you wish to specify custom queries, you can do so here or in a config file. 46 | # By default, queries listed here will override any specified in a config file. 47 | # Prefix the list here with "+" to use these queries and those in the config file. 48 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 49 | 50 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 51 | # If this step fails, then you should remove it and run the build manually (see below) 52 | - name: Autobuild 53 | uses: github/codeql-action/autobuild@v1 54 | 55 | # ℹ️ Command-line programs to run using the OS shell. 56 | # 📚 https://git.io/JvXDl 57 | 58 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 59 | # and modify them (or add more) to build your code if your project 60 | # uses a compiled language 61 | 62 | #- run: | 63 | # make bootstrap 64 | # make release 65 | 66 | - name: Perform CodeQL Analysis 67 | uses: github/codeql-action/analyze@v1 68 | -------------------------------------------------------------------------------- /.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 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | .vscode 106 | config.py 107 | .DS_Store 108 | config.yml 109 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at vaibhav.singh.14cse@bml.edu.in. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Vaibhav Singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include random_word/config.yml 2 | include random_word/database/words.json 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | help: 2 | @echo ' init' 3 | @echo ' install poetry and all project dependencies' 4 | @echo ' test' 5 | @echo ' run all tests' 6 | @echo ' build' 7 | @echo ' package for distributing in pypi repository' 8 | @echo ' test_upload' 9 | @echo ' package for distributing in test pypi repository' 10 | @echo ' upload' 11 | @echo ' upload package to pypi (You will require credentials)' 12 | @echo ' clean' 13 | @echo ' clean temporary files created during build' 14 | @echo ' lint' 15 | @echo ' lint all the python files' 16 | 17 | 18 | init: 19 | @echo 'Install python dependencies' 20 | pip install poetry 21 | poetry install 22 | poetry shell 23 | 24 | test: 25 | @echo 'Run all tests' 26 | pytest 27 | 28 | build: 29 | poetry build 30 | 31 | test_upload: 32 | python -m twine upload -r testpypi dist/* 33 | 34 | upload: 35 | poetry publish 36 | 37 | clean: 38 | find . -name '*.pyc' -exec rm -f {} + 39 | find . -name '*.pyo' -exec rm -f {} + 40 | find . -type d -name __pycache__ -exec rm -r {} \+ 41 | rm -rf build/ 42 | rm -rf dist/ 43 | find . -name '*.egg-info' -exec rm -rf {} + 44 | rm -rf .tox 45 | rm -rf .pytest_cache .coverage 46 | rm -rf .eggs 47 | 48 | lint: 49 | autopep8 random_word --recursive --in-place --pep8-passes 2000 --verbose 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # random-word 2 | 3 | ![Build](https://github.com/vaibhavsingh97/random-word/workflows/Build/badge.svg) 4 | [![PyPI version](https://badge.fury.io/py/Random-Word.svg)](https://badge.fury.io/py/Random-Word) 5 | [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Django.svg)](https://pypi.org/project/random-word/) 6 | [![PyPI - Status](https://img.shields.io/pypi/status/Django.svg)](https://pypi.org/project/random-word/) 7 | [![Downloads](https://pepy.tech/badge/random-word)](https://pepy.tech/project/random-word) 8 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://vaibhavsingh97.mit-license.org/) 9 | 10 | This is a simple python package to generate random English words. 11 | If you need help after reading the below, please find me on Twitter at [@vaibhavsingh97](https://twitter.com/vaibhavsingh97). 12 | 13 | If you love the package, please :star2: the repo. 14 | 15 | ## Installation 16 | 17 | You should be able to install using `easy_install` or `pip` in the usual ways: 18 | 19 | ```sh 20 | $ easy_install random-word 21 | $ pip install random-word 22 | ``` 23 | 24 | Or clone this repository and run: 25 | 26 | ```sh 27 | $ python3 setup.py install 28 | ``` 29 | 30 | Or place the `random-word` folder that you downloaded somewhere where your scripts can access it. 31 | 32 | ## Basic Usage 33 | 34 | > 👋 This package will now, by default, fetch the random word from local [database](https://github.com/vaibhavsingh97/random-word/blob/master/random_word/database/words.json) 35 | 36 | ```python 37 | from random_word import RandomWords 38 | r = RandomWords() 39 | 40 | # Return a single random word 41 | r.get_random_word() 42 | ``` 43 | 44 | Different services are available as a part of the random word package, which fetches random words from various API providers. Please check the `Services` section for more details. 45 | 46 | ## Services 47 | 48 | - [Wordnik][wordnikDocLink] 49 | - [API Ninjas][apiNinjasDocLink] 50 | 51 | ## Development 52 | 53 | Assuming that you have [`Python`](https://www.python.org/) and [`pipenv`](https://docs.pipenv.org) installed, set up your environment and install the required dependencies like this instead of the `pip install random-word` defined above: 54 | 55 | ```sh 56 | $ git clone https://github.com/vaibhavsingh97/random-word.git 57 | $ cd random-word 58 | $ make init 59 | ``` 60 | 61 | Add API Key in `random_word` directory defining API Key in `config.yml`. If you don't have an API key, then request your API key [here][wornikWebsiteLink] 62 | 63 | ```sh 64 | API_KEY = "" 65 | ``` 66 | 67 | To check your desired changes, you can install your package locally. 68 | 69 | ```sh 70 | $ pip install -e . 71 | ``` 72 | 73 | ## Issues 74 | 75 | You can report the bugs at the [issue tracker](https://github.com/vaibhavsingh97/random-word/issues) 76 | 77 | ## License 78 | 79 | Built with ♥ by Vaibhav Singh([@vaibhavsingh97](https://github.com/vaibhavsingh97)) under [MIT License](https://vaibhavsingh97.mit-license.org/) 80 | 81 | You can find a copy of the License at 82 | 83 | [wordnikDocLink]:https://github.com/vaibhavsingh97/random-word/blob/master/docs/wordnik.md 84 | [apiNinjasDocLink]:https://github.com/vaibhavsingh97/random-word/blob/master/docs/apininjas.md 85 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/apininjas.md: -------------------------------------------------------------------------------- 1 | # API Ninjas Service 2 | 3 | ## Overview 4 | 5 | API service provider which provides different APIs to build side projects 6 | 7 | ## Simple Usage 8 | 9 | ```python 10 | from random_word import ApiNinjas 11 | api_ninjas_service = ApiNinjas() 12 | 13 | # Return a single random word 14 | api_ninjas_service.get_random_word() 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/wordnik.md: -------------------------------------------------------------------------------- 1 | # Wordnik Service 2 | 3 | ## Overview 4 | 5 | Wordnik is the world's biggest online English dictionary, by number of words. 6 | 7 | 8 | ## Simple Usage 9 | 10 | ```python 11 | from random_word import Wordnik 12 | wordnik_service = Wordnik() 13 | 14 | # Return a single random word 15 | wordnik_service.get_random_word() 16 | # Return list of Random words 17 | wordnik_service.get_random_words() 18 | # Return Word of the day 19 | wordnik_service.word_of_the_day() 20 | ``` 21 | 22 | User can specify their own [api key][wornikWebsiteLink] 23 | ```python 24 | r = Wordnik(api_key="") 25 | ``` 26 | 27 | 28 | ## Advance Usage 29 | 30 | 1. To generate single random word we can use these optional parameters 31 | 32 | - `hasDictionaryDef (string)` - Only return words with dictionary definitions (optional) 33 | - `includePartOfSpeech (string)` - CSV part-of-speech values to include (optional) 34 | - `excludePartOfSpeech (string)` - CSV part-of-speech values to exclude (optional) 35 | - `minCorpusCount (integer)` - Minimum corpus frequency for terms (optional) 36 | - `maxCorpusCount (integer)` - Maximum corpus frequency for terms (optional) 37 | - `minDictionaryCount (integer)` - Minimum dictionary count (optional) 38 | - `maxDictionaryCount (integer)` - Maximum dictionary count (optional) 39 | - `minLength (integer)` - Minimum word length (optional) 40 | - `maxLength (integer)` - Maximum word length (optional) 41 | 42 | ```python 43 | r.get_random_word(hasDictionaryDef="true", includePartOfSpeech="noun,verb", minCorpusCount=1, maxCorpusCount=10, minDictionaryCount=1, maxDictionaryCount=10, minLength=5, maxLength=10) 44 | 45 | # Output: pediophobia 46 | ``` 47 | 48 | 2. To generate list of random word we can use these optional parameters 49 | 50 | - `hasDictionaryDef (string)` - Only return words with dictionary definitions (optional) 51 | - `includePartOfSpeech (string)` - CSV part-of-speech values to include (optional) 52 | - `excludePartOfSpeech (string)` - CSV part-of-speech values to exclude (optional) 53 | - `minCorpusCount (integer)` - Minimum corpus frequency for terms (optional) 54 | - `maxCorpusCount (integer)` - Maximum corpus frequency for terms (optional) 55 | - `minDictionaryCount (integer)` - Minimum dictionary count (optional) 56 | - `maxDictionaryCount (integer)` - Maximum dictionary count (optional) 57 | - `minLength (integer)` - Minimum word length (optional) 58 | - `maxLength (integer)` - Maximum word length (optional) 59 | - `sortBy (string)` - Attribute to sort by `alpha` or `count` (optional) 60 | - `sortOrder (string)` - Sort direction by `asc` or `desc` (optional) 61 | - `limit (integer)` - Maximum number of results to return (optional) 62 | 63 | ```python 64 | r.get_random_words(hasDictionaryDef="true", includePartOfSpeech="noun,verb", minCorpusCount=1, maxCorpusCount=10, minDictionaryCount=1, maxDictionaryCount=10, minLength=5, maxLength=10, sortBy="alpha", sortOrder="asc", limit=15) 65 | 66 | # Output: ['ambivert', 'calcspar', 'deaness', 'entrete', 'gades', 'monkeydom', 'outclimbed', 'outdared', 'pistoleers', 'redbugs', 'snake-line', 'subrules', 'subtrends', 'torenia', 'unhides'] 67 | ``` 68 | 69 | 3. To get word of the day we can use these optional parameters 70 | 71 | - `date (string)` - Fetches by date in yyyy-MM-dd (optional) 72 | 73 | ```python 74 | r.word_of_the_day(date="2018-01-01") 75 | 76 | # Output: {"word": "qualtagh", "definations": [{"text": "The first person one encounters, either after leaving one\'s home or (sometimes) outside one\'s home, especially on New Year\'s Day.", "source": "wiktionary", "partOfSpeech": "noun"}, {"text": "A Christmas or New Year\'s ceremony, in the Isle of Man; one who takes part in the ceremony. See the first extract.", "source": "century", "partOfSpeech": "noun"}]} 77 | ``` 78 | 79 | [wornikWebsiteLink]:https://developer.wordnik.com 80 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "autopep8" 5 | version = "2.3.1" 6 | description = "A tool that automatically formats Python code to conform to the PEP 8 style guide" 7 | optional = false 8 | python-versions = ">=3.8" 9 | files = [ 10 | {file = "autopep8-2.3.1-py2.py3-none-any.whl", hash = "sha256:a203fe0fcad7939987422140ab17a930f684763bf7335bdb6709991dd7ef6c2d"}, 11 | {file = "autopep8-2.3.1.tar.gz", hash = "sha256:8d6c87eba648fdcfc83e29b788910b8643171c395d9c4bcf115ece035b9c9dda"}, 12 | ] 13 | 14 | [package.dependencies] 15 | pycodestyle = ">=2.12.0" 16 | tomli = {version = "*", markers = "python_version < \"3.11\""} 17 | 18 | [[package]] 19 | name = "certifi" 20 | version = "2024.8.30" 21 | description = "Python package for providing Mozilla's CA Bundle." 22 | optional = false 23 | python-versions = ">=3.6" 24 | files = [ 25 | {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, 26 | {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, 27 | ] 28 | 29 | [[package]] 30 | name = "charset-normalizer" 31 | version = "3.4.0" 32 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 33 | optional = false 34 | python-versions = ">=3.7.0" 35 | files = [ 36 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, 37 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, 38 | {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, 39 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, 40 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, 41 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, 42 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, 43 | {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, 44 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, 45 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, 46 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, 47 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, 48 | {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, 49 | {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, 50 | {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, 51 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, 52 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, 53 | {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, 54 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, 55 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, 56 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, 57 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, 58 | {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, 59 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, 60 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, 61 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, 62 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, 63 | {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, 64 | {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, 65 | {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, 66 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, 67 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, 68 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, 69 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, 70 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, 71 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, 72 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, 73 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, 74 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, 75 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, 76 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, 77 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, 78 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, 79 | {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, 80 | {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, 81 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, 82 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, 83 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, 84 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, 85 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, 86 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, 87 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, 88 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, 89 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, 90 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, 91 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, 92 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, 93 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, 94 | {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, 95 | {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, 96 | {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, 97 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, 98 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, 99 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, 100 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, 101 | {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, 102 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, 103 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, 104 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, 105 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, 106 | {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, 107 | {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, 108 | {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, 109 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, 110 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, 111 | {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, 112 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, 113 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, 114 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, 115 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, 116 | {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, 117 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, 118 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, 119 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, 120 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, 121 | {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, 122 | {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, 123 | {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, 124 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, 125 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, 126 | {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, 127 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, 128 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, 129 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, 130 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, 131 | {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, 132 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, 133 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, 134 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, 135 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, 136 | {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, 137 | {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, 138 | {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, 139 | {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, 140 | {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, 141 | ] 142 | 143 | [[package]] 144 | name = "colorama" 145 | version = "0.4.6" 146 | description = "Cross-platform colored terminal text." 147 | optional = false 148 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 149 | files = [ 150 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 151 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 152 | ] 153 | 154 | [[package]] 155 | name = "exceptiongroup" 156 | version = "1.2.2" 157 | description = "Backport of PEP 654 (exception groups)" 158 | optional = false 159 | python-versions = ">=3.7" 160 | files = [ 161 | {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, 162 | {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, 163 | ] 164 | 165 | [package.extras] 166 | test = ["pytest (>=6)"] 167 | 168 | [[package]] 169 | name = "idna" 170 | version = "3.10" 171 | description = "Internationalized Domain Names in Applications (IDNA)" 172 | optional = false 173 | python-versions = ">=3.6" 174 | files = [ 175 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, 176 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, 177 | ] 178 | 179 | [package.extras] 180 | all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] 181 | 182 | [[package]] 183 | name = "iniconfig" 184 | version = "2.0.0" 185 | description = "brain-dead simple config-ini parsing" 186 | optional = false 187 | python-versions = ">=3.7" 188 | files = [ 189 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, 190 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, 191 | ] 192 | 193 | [[package]] 194 | name = "packaging" 195 | version = "24.2" 196 | description = "Core utilities for Python packages" 197 | optional = false 198 | python-versions = ">=3.8" 199 | files = [ 200 | {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, 201 | {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, 202 | ] 203 | 204 | [[package]] 205 | name = "pluggy" 206 | version = "1.5.0" 207 | description = "plugin and hook calling mechanisms for python" 208 | optional = false 209 | python-versions = ">=3.8" 210 | files = [ 211 | {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, 212 | {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, 213 | ] 214 | 215 | [package.extras] 216 | dev = ["pre-commit", "tox"] 217 | testing = ["pytest", "pytest-benchmark"] 218 | 219 | [[package]] 220 | name = "pycodestyle" 221 | version = "2.12.1" 222 | description = "Python style guide checker" 223 | optional = false 224 | python-versions = ">=3.8" 225 | files = [ 226 | {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"}, 227 | {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"}, 228 | ] 229 | 230 | [[package]] 231 | name = "pytest" 232 | version = "8.3.3" 233 | description = "pytest: simple powerful testing with Python" 234 | optional = false 235 | python-versions = ">=3.8" 236 | files = [ 237 | {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, 238 | {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, 239 | ] 240 | 241 | [package.dependencies] 242 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 243 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 244 | iniconfig = "*" 245 | packaging = "*" 246 | pluggy = ">=1.5,<2" 247 | tomli = {version = ">=1", markers = "python_version < \"3.11\""} 248 | 249 | [package.extras] 250 | dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] 251 | 252 | [[package]] 253 | name = "pyyaml" 254 | version = "6.0.2" 255 | description = "YAML parser and emitter for Python" 256 | optional = false 257 | python-versions = ">=3.8" 258 | files = [ 259 | {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, 260 | {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, 261 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, 262 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, 263 | {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, 264 | {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, 265 | {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, 266 | {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, 267 | {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, 268 | {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, 269 | {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, 270 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, 271 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, 272 | {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, 273 | {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, 274 | {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, 275 | {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, 276 | {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, 277 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, 278 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, 279 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, 280 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, 281 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, 282 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, 283 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, 284 | {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, 285 | {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, 286 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, 287 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, 288 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, 289 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, 290 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, 291 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, 292 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, 293 | {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, 294 | {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, 295 | {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, 296 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, 297 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, 298 | {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, 299 | {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, 300 | {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, 301 | {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, 302 | {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, 303 | {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, 304 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, 305 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, 306 | {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, 307 | {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, 308 | {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, 309 | {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, 310 | {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, 311 | {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, 312 | ] 313 | 314 | [[package]] 315 | name = "requests" 316 | version = "2.32.3" 317 | description = "Python HTTP for Humans." 318 | optional = false 319 | python-versions = ">=3.8" 320 | files = [ 321 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, 322 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, 323 | ] 324 | 325 | [package.dependencies] 326 | certifi = ">=2017.4.17" 327 | charset-normalizer = ">=2,<4" 328 | idna = ">=2.5,<4" 329 | urllib3 = ">=1.21.1,<3" 330 | 331 | [package.extras] 332 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 333 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 334 | 335 | [[package]] 336 | name = "tomli" 337 | version = "2.1.0" 338 | description = "A lil' TOML parser" 339 | optional = false 340 | python-versions = ">=3.8" 341 | files = [ 342 | {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"}, 343 | {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"}, 344 | ] 345 | 346 | [[package]] 347 | name = "urllib3" 348 | version = "2.2.3" 349 | description = "HTTP library with thread-safe connection pooling, file post, and more." 350 | optional = false 351 | python-versions = ">=3.8" 352 | files = [ 353 | {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, 354 | {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, 355 | ] 356 | 357 | [package.extras] 358 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 359 | h2 = ["h2 (>=4,<5)"] 360 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 361 | zstd = ["zstandard (>=0.18.0)"] 362 | 363 | [metadata] 364 | lock-version = "2.0" 365 | python-versions = "^3.8.0" 366 | content-hash = "a4116d02266d41e60ca38f81e96061355f5ffa2f5e78852919785e898c306053" 367 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["poetry-core>=1.0.0"] 3 | build-backend = "poetry.core.masonry.api" 4 | 5 | 6 | [tool.poetry] 7 | name="random_word" 8 | version="1.0.13" 9 | authors = ["Vaibhav Singh "] 10 | description="This is a simple python package to generate random english words" 11 | license="MIT" 12 | readme = "README.md" 13 | keywords=["package", "random words", "word of the day", "random word generator"] 14 | classifiers=[ 15 | "Programming Language :: Python", 16 | "Programming Language :: Python :: 3", 17 | "Programming Language :: Python :: 3.1", 18 | "Programming Language :: Python :: 3.2", 19 | "Programming Language :: Python :: 3.3", 20 | "Programming Language :: Python :: 3.4", 21 | "Programming Language :: Python :: 3.5", 22 | "Programming Language :: Python :: 3.6", 23 | "Programming Language :: Python :: 3.7", 24 | "Programming Language :: Python :: 3.8", 25 | "Programming Language :: Python :: 3.9", 26 | "Programming Language :: Python :: 3.10", 27 | "License :: OSI Approved :: MIT License", 28 | "Intended Audience :: Developers", 29 | "Operating System :: OS Independent", 30 | ] 31 | package-mode = true 32 | include = [ 33 | "random_word/config.yml" 34 | ] 35 | 36 | [tool.poetry.dependencies] 37 | python = "^3.8.0" 38 | requests = "^2.32.3" 39 | pytest = "^8.3.3" 40 | pyyaml = "^6.0.2" 41 | autopep8 = "^2.3.1" 42 | -------------------------------------------------------------------------------- /random_word/__init__.py: -------------------------------------------------------------------------------- 1 | from random_word.random_word import RandomWords 2 | from random_word.services.apininjas import ApiNinjas 3 | from random_word.services.wordnik import Wordnik 4 | 5 | __all__ = ["Wordnik", "ApiNinjas", "RandomWords"] 6 | __name__ = "Random Word" 7 | __author__ = "Vaibhav Singh " 8 | __version__ = "1.0.11" 9 | -------------------------------------------------------------------------------- /random_word/config.yml.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vaibhavsingh97/random-word/6fc6b6c524222706b3ed1ab3ddb8bf24cea299bd/random_word/config.yml.gpg -------------------------------------------------------------------------------- /random_word/random_word.py: -------------------------------------------------------------------------------- 1 | from random_word.services.local import Local 2 | 3 | 4 | class RandomWords(object): 5 | 6 | """Class for generating random words""" 7 | 8 | def __init__(self): 9 | self.service = Local() 10 | 11 | def get_random_word(self): 12 | return self.service.get_random_word() 13 | -------------------------------------------------------------------------------- /random_word/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vaibhavsingh97/random-word/6fc6b6c524222706b3ed1ab3ddb8bf24cea299bd/random_word/services/__init__.py -------------------------------------------------------------------------------- /random_word/services/apininjas.py: -------------------------------------------------------------------------------- 1 | from json import load 2 | 3 | from random_word.utils.utils import request_url 4 | 5 | 6 | class ApiNinjas(object): 7 | def __init__(self, api_key=None): 8 | self.api_key = api_key 9 | self.url = "https://api.api-ninjas.com/v1/randomword" 10 | 11 | def get_random_word(self): 12 | if self.api_key != None: 13 | response = request_url(self.url, headers={"X-Api-Key": self.api_key}) 14 | if response.status_code == 200: 15 | result = response.json() 16 | return result["word"] 17 | else: 18 | print("Error:", response.status_code, response.text) 19 | else: 20 | response = request_url(self.url) 21 | result = response.json() 22 | if response.status_code == 200: 23 | return result["word"] 24 | else: 25 | print("could not find the word") 26 | -------------------------------------------------------------------------------- /random_word/services/local.py: -------------------------------------------------------------------------------- 1 | import secrets 2 | from json import load 3 | from os.path import abspath, dirname, join 4 | 5 | 6 | class Local(object): 7 | def __init__(self): 8 | self.source = join(dirname(__file__), "..", "database", "words.json") 9 | with open(self.source) as word_database: 10 | self.valid_words = load(word_database) 11 | 12 | def get_random_word(self): 13 | return secrets.choice(list(self.valid_words.keys())) 14 | -------------------------------------------------------------------------------- /random_word/services/wordnik.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import json 3 | from os.path import abspath, dirname, join 4 | from urllib.parse import quote_plus, urlencode 5 | 6 | from random_word.utils.retry_generator import Retry 7 | from random_word.utils.utils import ( 8 | check_payload_items, 9 | get_api_keys, 10 | get_random_api_key, 11 | request_url, 12 | ) 13 | 14 | ROOT_DIR = dirname(dirname(abspath(__file__))) 15 | CONFIG_PATH = join(ROOT_DIR, "config.yml") 16 | 17 | API_KEYS_LIST = get_api_keys(CONFIG_PATH)["API_KEY"] 18 | API_KEY = get_random_api_key(API_KEYS_LIST) 19 | 20 | 21 | class Wordnik(object): 22 | """Class for Wordnik API Service""" 23 | 24 | def __init__(self, api_key=None): 25 | if api_key: 26 | self.__api_key = api_key 27 | else: 28 | self.__api_key = API_KEY 29 | self.issue_url = "https://github.com/vaibhavsingh97/random-word/issues" 30 | if self.__api_key == "" or self.__api_key is None: 31 | raise Exception("API key not found") 32 | 33 | @Retry(3) 34 | def get_random_word(self, **kwargs): 35 | """Returns a single random word 36 | 37 | Args: 38 | hasDictionaryDef, str: Only return words with dictionary definitions (optional) 39 | includePartOfSpeech, str: CSV part-of-speech values to include (optional) 40 | excludePartOfSpeech, str: CSV part-of-speech values to exclude (optional) 41 | minCorpusCount, int: Minimum corpus frequency for terms (optional) 42 | maxCorpusCount, int: Maximum corpus frequency for terms (optional) 43 | minDictionaryCount, int: Minimum dictionary count (optional) 44 | maxDictionaryCount, int: Maximum dictionary count (optional) 45 | minLength, int: Minimum word length (optional) 46 | maxLength, int: Maximum word length (optional) 47 | 48 | Returns: String, Random words 49 | """ 50 | url = "https://api.wordnik.com/v4/words.json/randomWord?" 51 | allParams = [ 52 | "hasDictionaryDef", 53 | "includePartOfSpeech", 54 | "excludePartOfSpeech", 55 | "minCorpusCount", 56 | "maxCorpusCount", 57 | "minDictionaryCount", 58 | "maxDictionaryCount", 59 | "minLength", 60 | "maxLength", 61 | ] 62 | params = locals() 63 | payload = params["kwargs"] 64 | check_payload_items(payload, allParams) 65 | payload["api_key"] = self.__api_key 66 | del params["kwargs"] 67 | try: 68 | url += urlencode(payload, quote_via=quote_plus) 69 | except TypeError: 70 | url += urlencode(payload) 71 | response = request_url(url) 72 | result = response.json() 73 | if response.status_code == 200: 74 | return result["word"] 75 | else: 76 | if len(API_KEYS_LIST) == 0: 77 | raise Exception( 78 | "Error occured, No result found. If you think this was a mistake than raise issue at {}".format( 79 | self.issue_url 80 | ) 81 | ) 82 | else: 83 | if self.__api_key in API_KEYS_LIST: 84 | API_KEYS_LIST.remove(self.__api_key) 85 | self.__api_key = get_random_api_key(API_KEYS_LIST) 86 | 87 | @Retry(3) 88 | def get_random_words(self, **kwargs): 89 | """Returns a list of random words 90 | 91 | Args: 92 | includePartOfSpeech, str: CSV part-of-speech values to include (optional) 93 | excludePartOfSpeech, str: CSV part-of-speech values to exclude (optional) 94 | hasDictionaryDef, str: Only return words with dictionary definitions (optional) 95 | minCorpusCount, int: Minimum corpus frequency for terms (optional) 96 | maxCorpusCount, int: Maximum corpus frequency for terms (optional) 97 | minDictionaryCount, int: Minimum dictionary count (optional) 98 | maxDictionaryCount, int: Maximum dictionary count (optional) 99 | minLength, int: Minimum word length (optional) 100 | maxLength, int: Maximum word length (optional) 101 | sortBy, str: Attribute to sort by (optional) 102 | sortOrder, str: Sort direction (optional) 103 | limit, int: Maximum number of results to return (optional) 104 | 105 | Returns: list[Random Words] 106 | """ 107 | url = "https://api.wordnik.com/v4/words.json/randomWords?" 108 | allParams = [ 109 | "hasDictionaryDef", 110 | "includePartOfSpeech", 111 | "excludePartOfSpeech", 112 | "minCorpusCount", 113 | "maxCorpusCount", 114 | "minDictionaryCount", 115 | "maxDictionaryCount", 116 | "minLength", 117 | "maxLength", 118 | "sortBy", 119 | "sortOrder", 120 | "limit", 121 | ] 122 | params = locals() 123 | payload = params["kwargs"] 124 | check_payload_items(payload, allParams) 125 | payload["api_key"] = self.__api_key 126 | del params["kwargs"] 127 | if "sortBy" in payload: 128 | value = ["alpha", "count"] 129 | if payload["sortBy"] not in value: 130 | raise ValueError("Got an unexpected value to argument sortBy") 131 | if "sortOrder" in payload: 132 | value = ["asc", "desc"] 133 | if payload["sortOrder"] not in value: 134 | raise ValueError("Got an unexpected value to argument sortOrder") 135 | try: 136 | url += urlencode(payload, quote_via=quote_plus) 137 | except TypeError: 138 | url += urlencode(payload) 139 | response = request_url(url) 140 | result = response.json() 141 | word_list = [] 142 | if response.status_code == 200: 143 | for word in result: 144 | word_list.append(word["word"]) 145 | return word_list 146 | else: 147 | if len(API_KEYS_LIST) == 0: 148 | raise Exception( 149 | "Error occured, No result found. If you think this was a mistake than raise issue at {}".format( 150 | self.issue_url 151 | ) 152 | ) 153 | else: 154 | if self.__api_key in API_KEYS_LIST: 155 | API_KEYS_LIST.remove(self.__api_key) 156 | self.__api_key = get_random_api_key(API_KEYS_LIST) 157 | 158 | @Retry(3) 159 | def word_of_the_day(self, **kwargs): 160 | """Returns a specific WordOfTheDay 161 | Args: 162 | date, str: Fetches by date in yyyy-MM-dd (optional) 163 | 164 | Returns: Json(WordOfTheDay) 165 | """ 166 | url = "https://api.wordnik.com/v4/words.json/wordOfTheDay?" 167 | allParams = ["date"] 168 | params = locals() 169 | payload = params["kwargs"] 170 | check_payload_items(payload, allParams) 171 | payload["api_key"] = self.__api_key 172 | del params["kwargs"] 173 | if "date" in payload: 174 | try: 175 | datetime.datetime.strptime(payload["date"], "%Y-%m-%d") 176 | except ValueError: 177 | raise ValueError("Incorrect data format, should be YYYY-MM-DD") 178 | try: 179 | url += urlencode(payload, quote_via=quote_plus) 180 | except TypeError: 181 | url += urlencode(payload) 182 | response = request_url(url) 183 | result = response.json() 184 | if response.status_code == 200: 185 | word = result["word"] 186 | definitions = result["definitions"] 187 | return json.dumps({"word": word, "definitions": definitions}) 188 | else: 189 | if len(API_KEYS_LIST) == 0: 190 | raise Exception( 191 | "Error occured, No result found. If you think this was a mistake than raise issue at {}".format( 192 | self.issue_url 193 | ) 194 | ) 195 | else: 196 | if self.__api_key in API_KEYS_LIST: 197 | API_KEYS_LIST.remove(self.__api_key) 198 | self.__api_key = get_random_api_key(API_KEYS_LIST) 199 | -------------------------------------------------------------------------------- /random_word/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vaibhavsingh97/random-word/6fc6b6c524222706b3ed1ab3ddb8bf24cea299bd/random_word/tests/__init__.py -------------------------------------------------------------------------------- /random_word/tests/test_apininjas.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | from random_word import ApiNinjas 3 | 4 | 5 | class TestRandomWord(TestCase): 6 | # using single instance for all tests 7 | r = ApiNinjas() 8 | 9 | def test_random_word(self): 10 | return self.r.get_random_word() 11 | 12 | 13 | if __name__ == "__main__": 14 | main() 15 | -------------------------------------------------------------------------------- /random_word/tests/test_random_word.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | from random_word import RandomWords 3 | 4 | 5 | class TestRandomWord(TestCase): 6 | # using single instance for all tests 7 | r = RandomWords() 8 | 9 | def test_random_word(self): 10 | word = self.r.get_random_word() 11 | self.assertIsInstance(word, str) 12 | 13 | 14 | if __name__ == "__main__": 15 | main() 16 | -------------------------------------------------------------------------------- /random_word/tests/test_wordnik.py: -------------------------------------------------------------------------------- 1 | from os.path import abspath, dirname, join 2 | from unittest import TestCase, main 3 | 4 | from random_word import Wordnik 5 | from random_word.utils.utils import get_api_keys, get_random_api_key 6 | 7 | ROOT_DIR = dirname(dirname(abspath(__file__))) 8 | CONFIG_PATH = join(ROOT_DIR, "config.yml") 9 | 10 | # Ensure that the config.yml file contains valid API keys 11 | API_KEYS_LIST = get_api_keys(CONFIG_PATH)["API_KEY"] 12 | API_KEY = get_random_api_key(API_KEYS_LIST) 13 | 14 | 15 | class TestRandomWord(TestCase): 16 | # using single instance for all tests 17 | r = Wordnik(api_key=API_KEY) 18 | 19 | def test_random_word(self): 20 | word = self.r.get_random_word() 21 | self.assertIsNotNone(word) 22 | 23 | def test_random_words(self): 24 | words = self.r.get_random_words() 25 | self.assertIsInstance(words, list) 26 | 27 | def test_word_of_the_day(self): 28 | word_of_the_day = self.r.word_of_the_day() 29 | self.assertIsNotNone(word_of_the_day) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /random_word/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vaibhavsingh97/random-word/6fc6b6c524222706b3ed1ab3ddb8bf24cea299bd/random_word/utils/__init__.py -------------------------------------------------------------------------------- /random_word/utils/retry_generator.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class Retry(object): 5 | def __init__(self, tries, delay=0): 6 | """ 7 | Decorator for retrying function if exception occurs 8 | 9 | tries -- no of retries 10 | delay -- wait between retries 11 | """ 12 | self.tries = tries 13 | self.delay = delay 14 | 15 | def __call__(self, f): 16 | def fn(*args, **kwargs): 17 | exception = None 18 | for _ in range(self.tries): 19 | try: 20 | return f(*args, **kwargs) 21 | except Exception as e: 22 | print("Retry, exception: " + str(e)) 23 | time.sleep(self.delay) 24 | exception = e 25 | raise exception 26 | 27 | return fn 28 | -------------------------------------------------------------------------------- /random_word/utils/utils.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import yaml 3 | import secrets 4 | import requests 5 | 6 | 7 | def request_url(url, headers={}): 8 | try: 9 | response = requests.get(url, headers=headers) 10 | except Exception as e: 11 | e = sys.exc_info()[0] 12 | raise e 13 | return response 14 | 15 | 16 | def check_payload_items(payload, allParams): 17 | if payload: 18 | for (key, val) in payload.items(): 19 | if key not in allParams: 20 | raise TypeError( 21 | "Got an unexpected keyword argument '%s' to method get_random_word" 22 | % key 23 | ) 24 | 25 | 26 | def get_api_keys(filepath): 27 | yaml_config = "" 28 | with open(filepath, "r") as stream: 29 | try: 30 | yaml_config = yaml.safe_load(stream) 31 | except yaml.YAMLError as exc: 32 | print("Error in configuration file:", exc) 33 | return yaml_config 34 | 35 | 36 | def get_random_api_key(api_key_arr): 37 | return secrets.choice(api_key_arr) 38 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [flake8] 2 | ignore = E501 3 | --------------------------------------------------------------------------------