├── .coveragerc ├── .deepsource.toml ├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md └── workflows │ ├── publish.yml │ └── unit-tests.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── docs ├── apireference.rst ├── changelog.rst ├── conf.py ├── getting-started.rst ├── guide │ ├── index.rst │ └── installing.rst └── index.rst ├── examples ├── hcl.hcl ├── ini.ini ├── json.json ├── toml.toml ├── xml.xml └── yaml.yaml ├── poetry.lock ├── pyproject.toml ├── tests ├── __init__.py ├── test_hcl.py ├── test_ini.py ├── test_json.py ├── test_toml.py ├── test_wild.py ├── test_xml.py ├── test_yaml.py └── tests.sh └── wildq ├── __init__.py ├── __main__.py ├── _wildq_version.py ├── cli.py └── filetypes ├── __init__.py ├── hcl_type.py ├── ini_type.py ├── json_type.py ├── toml_type.py ├── xml_type.py └── yaml_type.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = wildq 4 | omit = 5 | wildq/__main__.py 6 | wildq/_wildq_version.py 7 | tests/data/* 8 | */site-packages/* 9 | 10 | [report] 11 | exclude_lines = 12 | if __name__ == .__main__.: 13 | 14 | [html] 15 | directory = html 16 | -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "shell" 5 | 6 | [[analyzers]] 7 | name = "python" 8 | 9 | [analyzers.meta] 10 | runtime_version = "3.x.x" -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | insert_final_newline = true 7 | charset = utf-8 8 | indent_style = space 9 | indent_size = 4 10 | 11 | [Makefile] 12 | indent_style = tab 13 | 14 | 15 | [*.yml] 16 | indent_size = 2 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Hi there, 2 | 3 | Thank you for opening an issue. Please note that we try to keep the Wildq issue tracker reserved for bug reports and feature requests. 4 | 5 | ### Wildq Version 6 | Run `wildq --version` to show the version. If you are not running the latest version of Wildq, please upgrade because your issue may have already been fixed. 7 | 8 | ### Affected FileType(s) 9 | Please list the filetypes as a list, for example: 10 | - json 11 | - toml 12 | 13 | If this issue appears to affect multiple filetypes, it may be an issue with Wildq's core and not third-parties, so please mention this. 14 | 15 | ### Debug Output 16 | Please provider a link to a GitHub Gist containing the complete output. Please do NOT paste the debug output in the issue; just paste a link to the Gist. 17 | 18 | ### Panic Output 19 | If wildq produced a stacktrace, please provide a link to a GitHub Gist containing the output. 20 | 21 | ### Expected Behavior 22 | What should have happened? 23 | 24 | ### Actual Behavior 25 | What actually happened? 26 | 27 | ### Steps to Reproduce 28 | Please list the steps required to reproduce the issue, for example: 29 | 1. `wildq -i ...` 30 | 31 | ### References 32 | Are there any other GitHub issues (open or closed) or Pull Requests that should be linked here? For example: 33 | - GH-1234 34 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish packages 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | assets: 10 | name: Release packages 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: 16 | - macos-latest 17 | - ubuntu-latest 18 | steps: 19 | - name: Check out src from Git 20 | uses: actions/checkout@v2 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Set up Python 3.6 25 | uses: actions/setup-python@v1 26 | if: matrix.os == 'macos-latest' 27 | with: 28 | python-version: 3.6 29 | 30 | # Lower version of glibc is always compatible with greater version 31 | # So the binary will we runnable on probably all linux stable/LTS distros 32 | # https://pyinstaller.readthedocs.io/en/stable/usage.html#making-gnu-linux-apps-forward-compatible 33 | # So I use a custom python image with pyinstaller on centos7 (glibc 2.17) 34 | - name: Build package for GNU/Linux 35 | if: matrix.os == 'ubuntu-latest' 36 | uses: ahmet2mir/docker-python@master 37 | with: 38 | make_args: init_pip test build binary-linux binary-tests archive-linux package-rpm package-deb 39 | 40 | - name: Build package for OSX 41 | if: matrix.os == 'macos-latest' 42 | run: | 43 | brew install gnu-tar 44 | brew install coreutils 45 | gem install --user --no-document fpm 46 | make init_pip test build binary-macos binary-tests archive-macos package-brew 47 | 48 | - name: Upload Release Asset 49 | uses: ahmet2mir/softprops-action-gh-release@v1 50 | with: 51 | files: | 52 | ./artifacts/archives/*.tar.gz 53 | ./artifacts/rpm/*.rpm 54 | ./artifacts/deb/*.deb 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | 58 | - name: Publish distribution to PyPI 59 | uses: ahmet2mir/pypa-gh-action-pypi-publish@master 60 | if: matrix.os == 'ubuntu-latest' 61 | with: 62 | password: ${{ secrets.GH_ACTIONS_WILD }} 63 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests.yml: -------------------------------------------------------------------------------- 1 | name: Unit Tests 2 | on: 3 | push: 4 | branches: 5 | - '*' 6 | pull_request: 7 | branches: 8 | - '*' 9 | 10 | jobs: 11 | test: 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | python-version: [3.6, 3.7, 3.8] 17 | os: [ubuntu-latest] 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 | make init_pip 27 | - name: Syntax 28 | run: | 29 | make syntax 30 | - name: Test 31 | run: | 32 | make test 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | 3 | #####=== Python ===##### 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | .eggs 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | 56 | # Sphinx documentation 57 | docs/_build/ 58 | 59 | # PyBuilder 60 | target/ 61 | 62 | #### joe made this: http://goel.io/joe 63 | 64 | #####=== Python ===##### 65 | 66 | # Byte-compiled / optimized / DLL files 67 | __pycache__/ 68 | *.py[cod] 69 | 70 | # C extensions 71 | *.so 72 | 73 | # Distribution / packaging 74 | .Python 75 | env/ 76 | build/ 77 | develop-eggs/ 78 | dist/ 79 | downloads/ 80 | eggs/ 81 | lib/ 82 | lib64/ 83 | parts/ 84 | sdist/ 85 | var/ 86 | *.egg-info/ 87 | .installed.cfg 88 | *.egg 89 | 90 | # PyInstaller 91 | # Usually these files are written by a python script from a template 92 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 93 | *.manifest 94 | *.spec 95 | 96 | # Installer logs 97 | pip-log.txt 98 | pip-delete-this-directory.txt 99 | 100 | # Unit test / coverage reports 101 | htmlcov/ 102 | .tox/ 103 | .coverage 104 | .cache 105 | nosetests.xml 106 | coverage.xml 107 | 108 | # Translations 109 | *.mo 110 | *.pot 111 | 112 | # Django stuff: 113 | *.log 114 | 115 | # Sphinx documentation 116 | docs/_build/ 117 | 118 | # PyBuilder 119 | target/ 120 | 121 | #### joe made this: http://goel.io/joe 122 | 123 | #####=== Python ===##### 124 | 125 | # Byte-compiled / optimized / DLL files 126 | __pycache__/ 127 | *.py[cod] 128 | 129 | # C extensions 130 | *.so 131 | 132 | # Distribution / packaging 133 | .Python 134 | env/ 135 | build/ 136 | develop-eggs/ 137 | dist/ 138 | downloads/ 139 | eggs/ 140 | lib/ 141 | lib64/ 142 | parts/ 143 | sdist/ 144 | var/ 145 | *.egg-info/ 146 | .installed.cfg 147 | *.egg 148 | 149 | # PyInstaller 150 | # Usually these files are written by a python script from a template 151 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 152 | *.manifest 153 | *.spec 154 | 155 | # Installer logs 156 | pip-log.txt 157 | pip-delete-this-directory.txt 158 | 159 | # Unit test / coverage reports 160 | htmlcov/ 161 | .tox/ 162 | .coverage 163 | .cache 164 | nosetests.xml 165 | coverage.xml 166 | 167 | # Translations 168 | *.mo 169 | *.pot 170 | 171 | # Django stuff: 172 | *.log 173 | 174 | # Sphinx documentation 175 | docs/_build/ 176 | 177 | # PyBuilder 178 | target/ 179 | 180 | # Not Joe 181 | 182 | .sass-cache/ 183 | ignore/ 184 | .venv 185 | trash/ 186 | result.json 187 | .DS_Store 188 | .vscode 189 | pip-wheel-metadata/ 190 | # wildq/_wildq_version.py 191 | .idea 192 | *.swp 193 | Pipfile.lock 194 | artifacts/ 195 | dev.py 196 | upx/ 197 | init 198 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2020 Ahmet Demir 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PYTHON_CMD ?= python 2 | PIP_CMD ?= pip 3 | 4 | all: init_pipx test build binary-linux binary-tests archive-linux package-rpm package-deb 5 | 6 | # lists all available targets 7 | list: 8 | @sh -c "$(MAKE) -p no_targets__ | \ 9 | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {\ 10 | split(\$$1,A,/ /);for(i in A)print A[i]\ 11 | }' | grep -v '__\$$' | grep -v 'make\[1\]' | grep -v 'Makefile' | sort" 12 | 13 | # required for list 14 | no_targets__: 15 | 16 | init_pip: 17 | @echo "Target init_pip" 18 | $(PIP_CMD) show -q poetry || $(PIP_CMD) install poetry 19 | $(PIP_CMD) show -q poetry-dynamic-versioning || $(PIP_CMD) install poetry-dynamic-versioning 20 | poetry install 21 | poetry version --no-ansi 22 | poetry update --dry-run 23 | touch init_pip 24 | 25 | init_pipx: 26 | @echo "Target init_pipx" 27 | $(PIP_CMD) show -q pipx || $(PIP_CMD) install pipx 28 | $(PYTHON_CMD) -m pipx ensurepath 29 | pipx runpip poetry show -q poetry || pipx install poetry 30 | pipx runpip poetry show -q poetry-dynamic-versioning || pipx inject poetry poetry-dynamic-versioning 31 | poetry install 32 | poetry version --no-ansi 33 | poetry update --dry-run 34 | touch init_pipx 35 | 36 | fmt: 37 | @echo "Target fmt" 38 | poetry run black wildq tests 39 | 40 | poetry.lock: 41 | @echo "Target poetry.lock" 42 | poetry lock 43 | poetry version --no-ansi 44 | 45 | docs: poetry.lock 46 | @echo "Target docs" 47 | poetry run sphinx-build -b html docs docs/_build/html 48 | 49 | test: poetry.lock 50 | @echo "Target test" 51 | poetry run coverage run -m unittest discover 52 | poetry run coverage report -m 53 | 54 | syntax: poetry.lock 55 | @echo "Target syntax" 56 | poetry run flake8 wildq --count --exit-zero --statistics 57 | poetry run bandit -r wildq 58 | 59 | # upx: 60 | # @echo "Target upx" 61 | # curl -sL https://github.com/upx/upx/releases/download/v3.96/upx-3.96-amd64_linux.tar.xz | tar -xJ -C . 62 | # mv ./upx-3.96-amd64_linux upx 63 | 64 | build: poetry.lock 65 | @echo "Target build" 66 | poetry version --no-ansi 67 | cat wildq/_wildq_version.py 68 | mkdir -p artifacts/archives 69 | mkdir -p artifacts/binaries 70 | mkdir -p artifacts/brew 71 | mkdir -p artifacts/deb 72 | mkdir -p artifacts/rpm 73 | poetry build 74 | 75 | binary-linux: build 76 | @echo "Target binary-linux" 77 | poetry run pyinstaller --distpath artifacts/binaries --clean --onefile --name wildq wildq/__main__.py 78 | 79 | binary-macos: build 80 | @echo "Target binary-macos" 81 | poetry run pyinstaller --distpath artifacts/binaries --clean --onefile --name wildq wildq/__main__.py 82 | 83 | binary-copy: 84 | chmod +x artifacts/binaries/wildq 85 | cp artifacts/binaries/wildq artifacts/binaries/wq 86 | cp README.md LICENSE artifacts/binaries 87 | du -hs ./artifacts/binaries/wildq 88 | du -hs ./artifacts/binaries/wq 89 | 90 | binary-tests: binary-copy 91 | @echo "Target binary-tests" 92 | sh -e ./tests/tests.sh 93 | 94 | archive-linux: binary-copy 95 | @echo "Target archive-linux" 96 | tar cfz artifacts/archives/wildq-$(shell poetry version --no-ansi --short)-linux-x86_64.tar.gz -C artifacts/binaries wq wildq README.md LICENSE 97 | sha256sum artifacts/archives/wildq-$(shell poetry version --no-ansi --short)-linux-x86_64.tar.gz 98 | 99 | archive-macos: binary-copy 100 | @echo "Target archive-macos" 101 | tar cfz artifacts/archives/wildq-$(shell poetry version --no-ansi --short)-darwin-x86_64.tar.gz -C artifacts/binaries wq wildq README.md LICENSE 102 | sha256sum artifacts/archives/wildq-$(shell poetry version --no-ansi --short)-darwin-x86_64.tar.gz 103 | 104 | package-rpm: archive-linux 105 | @echo "Target package-rpm" 106 | mkdir -p artifacts/rpm/usr/bin/ 107 | cp artifacts/binaries/wildq artifacts/rpm/usr/bin/wildq 108 | cp artifacts/binaries/wildq artifacts/rpm/usr/bin/wq 109 | cd artifacts/rpm/; fpm \ 110 | --input-type dir \ 111 | --output-type rpm \ 112 | --version $(shell poetry version --no-ansi --short) \ 113 | --iteration 1 \ 114 | --prefix / \ 115 | --name wildq \ 116 | --rpm-user root \ 117 | --rpm-attr "755,root,root:/usr/bin/wildq" \ 118 | --rpm-attr "755,root,root:/usr/bin/wq" \ 119 | . 120 | 121 | package-deb: archive-linux 122 | @echo "Target archive-linux" 123 | mkdir -p artifacts/deb/usr/bin/ 124 | cp artifacts/binaries/wildq artifacts/deb/usr/bin/wildq 125 | cp artifacts/binaries/wildq artifacts/deb/usr/bin/wq 126 | cd artifacts/deb/; fpm \ 127 | --input-type dir \ 128 | --output-type deb \ 129 | --version $(shell poetry version --no-ansi --short) \ 130 | --iteration 1 \ 131 | --prefix / \ 132 | --name wildq \ 133 | --deb-user root \ 134 | . 135 | 136 | package-brew: archive-macos 137 | @echo "Target package-brew" 138 | echo "FIXME: auto update my homebrew-tap repo" 139 | 140 | pypi: 141 | @echo "Target pypi" 142 | poetry publish 143 | 144 | clean: 145 | @echo "Target clean" 146 | git clean -fdx 147 | 148 | clean-venv: 149 | @echo "Target clean-venv" 150 | @poetry env remove $$(poetry env list --no-ansi | tail -n 1 | cut -d' ' -f1) 151 | 152 | .PHONY: all archive-linux archive-macos binary binary-linux binary-macos binary-copy binary-tests build clean clean-venv docs fmt list package-brew package-deb package-rpm pypi syntax test 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wildq - Command-line TOML/JSON/INI/YAML/XML/HCL processor using jq c bindings 2 | 3 | ![GitHub](https://img.shields.io/github/license/ahmet2mir/wildq.svg) 4 | [![image](https://img.shields.io/pypi/pyversions/wildq.svg)](https://python.org/pypi/wildq) 5 | [![Build Status](https://github.com/ahmet2mir/wildq/workflows/Unit%20Tests/badge.svg)](https://github.com/ahmet2mir/wildq/actions) 6 | 7 | Purpose of this package is to provide a simple wrapper arround jq for different formats. 8 | I'm tired of searching a package doing yaml jq, toml jq, ini jq etc. mainly used for scripting. 9 | 10 | This script uses: 11 | * @mwilliamson [Python bindings](https://github.com/mwilliamson/jq.py) on top of @stedolan famous [jq](https://github.com/stedolan/jq/) lib 12 | * swiss knife for coloration [pygments](https://github.com/pygments/pygments) 13 | * binary built with [pyinstaller](https://github.com/pyinstaller/pyinstaller) 14 | * easy CLI with [click](https://github.com/pallets/click) 15 | * for supported types sources, check table `Supported file types` 16 | 17 | # Installation 18 | 19 | You could install via pipx, pip, brew, deb, rpm or fallback to binary version. 20 | 21 | ## Pipx 22 | 23 | `pipx` install and run python applications in isolated environments 24 | 25 | ```sh 26 | pipx install wildq 27 | ``` 28 | 29 | ## Pip 30 | 31 | ```sh 32 | pip install wildq 33 | ``` 34 | 35 | ## MacOS 36 | 37 | ``` 38 | brew install ahmet2mir/tap/wildq 39 | brew install ahmet2mir/tap/wq 40 | ``` 41 | 42 | ## Debian (no gpg signature) >= 10 43 | 44 | ``` 45 | VERSION=$(curl -s "https://api.github.com/repos/ahmet2mir/wildq/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') 46 | curl -sL https://github.com/ahmet2mir/wildq/releases/download/v${VERSION}/wildq_${VERSION}-1_amd64.deb -o wildq_${VERSION}-1_amd64.deb 47 | sudo dpkg -i wildq_${VERSION}-1_amd64.deb 48 | 49 | wq --help 50 | wildq --help 51 | ``` 52 | 53 | ## Centos (no gpg singature) >= 7 54 | 55 | ``` 56 | VERSION=$(curl -s "https://api.github.com/repos/ahmet2mir/wildq/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') 57 | curl -sL https://github.com/ahmet2mir/wildq/releases/download/v${VERSION}/wildq-${VERSION}-1.x86_64.rpm -o wildq-${VERSION}-1.x86_64.rpm 58 | sudo yum install -y ./wildq-${VERSION}-1.x86_64.rpm 59 | 60 | wq --help 61 | wildq --help 62 | ``` 63 | 64 | ## Gentoo 65 | 66 | [@zmedico](https://github.com/zmedico) did a portage on [app-misc](https://packages.gentoo.org/packages/app-misc/wildq) 67 | 68 | ``` 69 | emerge -av app-misc/wildq 70 | ``` 71 | 72 | ## GNU/Linux Binary 73 | 74 | Compiled using glibc 2.17, it should work on lot of stable/LTS distros. 75 | 76 | ``` 77 | mkdir -p ~/bin/ 78 | VERSION=$(curl -s "https://api.github.com/repos/ahmet2mir/wildq/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') 79 | curl -sL https://github.com/ahmet2mir/wildq/releases/download/v${VERSION}/wildq-${VERSION}-linux-x86_64.tar.gz -o wildq-${VERSION}-linux-x86_64.tar.gz 80 | tar xvfz wildq-${VERSION}-linux-x86_64.tar.gz -C ~/bin 81 | export PATH="~/bin:$PATH" 82 | 83 | wq --help 84 | wildq --help 85 | ``` 86 | 87 | ## Windows 88 | 89 | Wildq use [jq.py](https://github.com/mwilliamson/jq.py) and it's not yet available on windows platforms. 90 | I tried to compile it without windows machine and I failed, and I don't had the time to try to understand how Windows / C binding / Python works. 91 | If anybody would contribute, there is an [open issue](https://github.com/mwilliamson/jq.py/issues/20) (jq and onigurama are 'compilable' on Windows so I think that someone confortable with that OS could make it); 92 | 93 | 94 | # Supported file types 95 | 96 | | type | color | ordering | output | source | 97 | |------|-------|----------|--------|---------------------------------------------------------------------| 98 | | hcl | json | no | json | [pyhcl](https://github.com/virtuald/pyhcl) by @virtuald | 99 | | ini | yes | no | yes | [ConfigParser](https://docs.python.org/3/library/configparser.html) | 100 | | json | yes | yes | yes | [json](https://docs.python.org/3/library/json.html) | 101 | | toml | yes | no | yes | [toml](https://github.com/uiri/toml) by @uiri | 102 | | xml | yes | no | yes | [xmldict](https://github.com/martinblech/xmltodict) by @martinblech | 103 | | yaml | yes | yes | yes | [pyyaml](https://github.com/yaml/pyyaml) | 104 | 105 | # Usage 106 | 107 | ``` 108 | $ wildq --help 109 | Usage: wildq [OPTIONS] JQ_FILTER [FILE] 110 | 111 | Options: 112 | -c, --compact-output compact instead of pretty-printed output 113 | -r, --raw output raw strings, not content texts 114 | -C, --color-output colorize content (default), mutally 115 | exclusive with --monochrome-output 116 | 117 | -M, --monochrome-output monochrome (don't colorize content), mutally 118 | exclusive with --color-output 119 | 120 | --hcl Combine --input hcl --output json, mutally 121 | exclusive with other Combined options 122 | 123 | --ini Combine --input ini --output json, mutally 124 | exclusive with other Combined options 125 | 126 | --json Combine --input json --output json, mutally 127 | exclusive with other Combined options 128 | 129 | --toml Combine --input toml --output json, mutally 130 | exclusive with other Combined options 131 | 132 | --xml Combine --input xml --output json, mutally 133 | exclusive with other Combined options 134 | 135 | --yaml Combine --input yaml --output json, mutally 136 | exclusive with other Combined options 137 | 138 | -i, --input [hcl|ini|json|toml|xml|yaml] 139 | Define the content type of file, mutally 140 | exclusive with Combined option 141 | 142 | -o, --output [hcl|ini|json|toml|xml|yaml] 143 | Define the content type of printed output, 144 | mutally exclusive with Combined option 145 | (default input format) 146 | 147 | --version Show the version and exit. 148 | --help Show this message and exit. 149 | ``` 150 | 151 | > For backward compatibility in previous version only `--[yaml|json|toml|ini|xml|hcl]` was possible with default to json output. 152 | We still keep Monochrome, raw and json output with thoses options. 153 | Output was similar to `jq -MCr` (no color, no compact and no quote on single value) 154 | 155 | But now, by default it's colorized, not raw and if you specify input using `-i` or `--input` output will be the same format. 156 | 157 | There is also a shorter command `wq` comming with the package. 158 | 159 | Like `jq cli`, wildq supports both of stdin and file to the function 160 | 161 | See examples to get some example. 162 | 163 | Content of `examples/json.json` 164 | 165 | ``` 166 | { 167 | "general": { 168 | "user": "admin" 169 | }, 170 | "keys": [ 171 | {"key": "value1"}, 172 | {"key": "value2"}, 173 | "alone" 174 | ] 175 | } 176 | ``` 177 | 178 | ```sh 179 | cat examples/json.json | wildq -i json ".keys[]" 180 | { 181 | "key": "value1" 182 | } 183 | { 184 | "key": "value2" 185 | } 186 | alone 187 | ``` 188 | 189 | or 190 | 191 | ```sh 192 | wildq -i json ".keys[]" examples/json.json 193 | { 194 | "key": "value1" 195 | } 196 | { 197 | "key": "value2" 198 | } 199 | alone 200 | ``` 201 | or 202 | 203 | ```sh 204 | wq -i json ".keys[]" examples/json.json 205 | { 206 | "key": "value1" 207 | } 208 | { 209 | "key": "value2" 210 | } 211 | alone 212 | ``` 213 | 214 | For TOML 215 | ```sh 216 | cat examples/toml.toml | wildq -i toml ".keys[]" 217 | { 218 | "key": "value1" 219 | } 220 | { 221 | "key": "value2" 222 | } 223 | alone 224 | ``` 225 | 226 | For INI (no array) 227 | ```sh 228 | cat examples/ini.ini | wildq -i ini ".keys" 229 | { 230 | "key1": "value1", 231 | "key2": "value2" 232 | } 233 | ``` 234 | 235 | For XML 236 | ```sh 237 | cat examples/xml.xml | wildq -i xml "." 238 | { 239 | "root": { 240 | "general": { 241 | "user": "admin" 242 | }, 243 | "keys": { 244 | "element": [ 245 | { 246 | "key": "value1" 247 | }, 248 | { 249 | "key": "value2" 250 | }, 251 | "alone" 252 | ] 253 | } 254 | } 255 | } 256 | ``` 257 | 258 | For YAML 259 | ```sh 260 | cat examples/yaml.yaml | wildq -i yaml ".keys[]" 261 | { 262 | "key1": "value1" 263 | } 264 | { 265 | "key2": "value2" 266 | } 267 | alone 268 | ``` 269 | 270 | For HCL 271 | ```sh 272 | cat examples/hcl.hcl | wildq -i hcl ".keys[]" 273 | { 274 | "key": "value1" 275 | } 276 | { 277 | "key": "value2" 278 | } 279 | ``` 280 | 281 | ## Tips and tricks 282 | 283 | Loop on keys in bash without creating a subshell 284 | 285 | ```sh 286 | wildq -i toml "keys[]" examples/toml.toml | while read -r key 287 | do 288 | echo "Getting key ${key}" 289 | done 290 | ``` 291 | 292 | You could also found some examples on some blogs/websites: 293 | 294 | * a complete guide with advanced examples on how to read/update files with differents processing tools [(Original Japanese)](https://yujiorama.hatenablog.com/entry/2021/03/21/113425) [(Translate EN)](https://translate.google.com/translate?sl=auto&tl=en&u=https://yujiorama.hatenablog.com/entry/2021/03/21/113425) 295 | 296 | * an example of INI manipulation made by AWS ParallelCluster Workshop [(workshop)](https://containers-on-pcluster.workshop.aws/setup/pcluster.html) [(example 1)](https://containers-on-pcluster.workshop.aws/setup/pcluster/pcluster-cfg/refine.html) [(example 2)](https://containers-on-pcluster.workshop.aws/setup/pcluster/pcluster-cnt/create-x86.html) 297 | 298 | ## TODO 299 | 300 | - [x] add tests... 301 | - [x] add more control over filters and files 302 | - [x] use click for the CLI 303 | - [x] support different output 304 | - [ ] detect automagically filetype 305 | - [ ] support all jq types 306 | - [ ] ordering 307 | 308 | ## Contributing 309 | 310 | Merge requests are welcome :) 311 | 312 | 313 | ## License 314 | 315 | Licensed under the terms of the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 316 | 317 | 318 | ## Repository URL 319 | 320 | https://github.com/ahmet2mir/wildq 321 | -------------------------------------------------------------------------------- /docs/apireference.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | API Reference 3 | ============= 4 | 5 | FileTypes 6 | ========= 7 | 8 | .. py:module:: wildq.filetypes 9 | 10 | .. automodule:: wildq.filetypes.hcl_type 11 | :members: 12 | 13 | .. automodule:: wildq.filetypes.ini_type 14 | :members: 15 | 16 | .. automodule:: wildq.filetypes.json_type 17 | :members: 18 | 19 | .. automodule:: wildq.filetypes.toml_type 20 | :members: 21 | 22 | .. automodule:: wildq.filetypes.xml_type 23 | :members: 24 | 25 | .. automodule:: wildq.filetypes.yaml_type 26 | :members: 27 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | Changelog 3 | ========= 4 | 5 | v1.1.7 - 25/10/2020 6 | =================== 7 | 8 | - Adding version output 9 | 10 | v1.1.6 - 25/10/2020 11 | =================== 12 | 13 | - Move to poetry and reduce binary with upx 14 | - Fix du cmd and refactor binary 15 | 16 | v1.1.5 - 20/10/2020 17 | =================== 18 | 19 | - Compile using glibc 2.17 to get compatibility with lot of GNU/Linux distros 20 | - fix release actions 21 | 22 | v1.1.4 - 12/10/2020 23 | =================== 24 | 25 | - fix osx binary path 26 | 27 | v1.1.3 - 12/10/2020 28 | =================== 29 | 30 | - fix package brew 31 | - tempfix remove RPM (must be build on centos) 32 | - tempfix remove binary (must be build with lower version of glibc) 33 | 34 | v1.1.2 - 12/10/2020 35 | =================== 36 | 37 | - add packages debian, rpm, brew 38 | 39 | v1.1.0 - 12/10/2020 40 | =================== 41 | 42 | - use click for CLI 43 | - add input and output format (close #GH-1) 44 | - colorize output 45 | - add tests and doc 46 | - move from travis to github actions 47 | - build using pyinstaller for linux and macos 48 | 49 | 50 | v1.0.6 - 26/05/2020 51 | =================== 52 | - First release 53 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # standard 16 | import os 17 | import sys 18 | import datetime 19 | 20 | # third 21 | import sphinx_rtd_theme 22 | 23 | sys.path.insert(0, os.path.abspath(".")) 24 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 25 | 26 | # local 27 | from wildq._wildq_version import version as release 28 | 29 | # -- Project information ----------------------------------------------------- 30 | 31 | year = datetime.datetime.now().year 32 | project = "wildq - Command-line processor using jq c bindings" 33 | copyright = "%d Ahmet Demir" % year 34 | author = "Ahmet Demir (ahmet2mir)" 35 | 36 | # The short X.Y version 37 | version = "" 38 | 39 | # -- General configuration --------------------------------------------------- 40 | 41 | # If your documentation needs a minimal Sphinx version, state it here. 42 | # 43 | # needs_sphinx = '1.0' 44 | 45 | # Add any Sphinx extension module names here, as strings. They can be 46 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 47 | # ones. 48 | extensions = ["sphinx.ext.autodoc", "sphinx.ext.todo", "sphinx.ext.napoleon"] 49 | 50 | # Add any paths that contain templates here, relative to this directory. 51 | templates_path = ["_templates"] 52 | 53 | # The suffix(es) of source filenames. 54 | # You can specify multiple suffix as a list of string: 55 | # 56 | # source_suffix = ['.rst', '.md'] 57 | source_suffix = ".rst" 58 | 59 | # The master toctree document. 60 | master_doc = "index" 61 | 62 | # The language for content autogenerated by Sphinx. Refer to documentation 63 | # for a list of supported languages. 64 | # 65 | # This is also used if you do content translation via gettext catalogs. 66 | # Usually you set "language" from the command line for these cases. 67 | language = None 68 | 69 | # List of patterns, relative to source directory, that match files and 70 | # directories to ignore when looking for source files. 71 | # This pattern also affects html_static_path and html_extra_path. 72 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 73 | 74 | # The name of the Pygments (syntax highlighting) style to use. 75 | pygments_style = "sphinx" 76 | 77 | 78 | # -- Options for HTML output ------------------------------------------------- 79 | 80 | # The theme to use for HTML and HTML Help pages. See the documentation for 81 | # a list of builtin themes. 82 | # 83 | html_theme = "sphinx_rtd_theme" 84 | 85 | # Theme options are theme-specific and customize the look and feel of a theme 86 | # further. For a list of options available for each theme, see the 87 | # documentation. 88 | # 89 | # html_theme_options = {} 90 | 91 | # Add any paths that contain custom static files (such as style sheets) here, 92 | # relative to this directory. They are copied after the builtin static files, 93 | # so a file named "default.css" will overwrite the builtin "default.css". 94 | html_static_path = ["_static"] 95 | 96 | # Custom sidebar templates, must be a dictionary that maps document names 97 | # to template names. 98 | # 99 | # The default sidebars (for documents that don't match any pattern) are 100 | # defined by theme itself. Builtin themes are using these templates by 101 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 102 | # 'searchbox.html']``. 103 | # 104 | # html_sidebars = {} 105 | 106 | 107 | # -- Options for HTMLHelp output --------------------------------------------- 108 | 109 | # Output file base name for HTML help builder. 110 | htmlhelp_basename = "wildqdoc" 111 | 112 | 113 | # -- Options for LaTeX output ------------------------------------------------ 114 | 115 | latex_elements = { 116 | # The paper size ('letterpaper' or 'a4paper'). 117 | # 118 | # 'papersize': 'letterpaper', 119 | # The font size ('10pt', '11pt' or '12pt'). 120 | # 121 | # 'pointsize': '10pt', 122 | # Additional stuff for the LaTeX preamble. 123 | # 124 | # 'preamble': '', 125 | # Latex figure (float) alignment 126 | # 127 | # 'figure_align': 'htbp', 128 | } 129 | 130 | # Grouping the document tree into LaTeX files. List of tuples 131 | # (source start file, target name, title, 132 | # author, documentclass [howto, manual, or own class]). 133 | latex_documents = [ 134 | (master_doc, "wildq.tex", "wildq Documentation", "Ahmet Demir", "manual") 135 | ] 136 | 137 | 138 | # -- Options for manual page output ------------------------------------------ 139 | 140 | # One entry per manual page. List of tuples 141 | # (source start file, name, description, authors, manual section). 142 | man_pages = [(master_doc, "wildq", "wildq Documentation", [author], 1)] 143 | 144 | 145 | # -- Options for Texinfo output ---------------------------------------------- 146 | 147 | # Grouping the document tree into Texinfo files. List of tuples 148 | # (source start file, target name, title, author, 149 | # dir menu entry, description, category) 150 | texinfo_documents = [ 151 | ( 152 | master_doc, 153 | "wildq", 154 | "wildq Documentation", 155 | author, 156 | "wildq", 157 | "One line description of project.", 158 | "Miscellaneous", 159 | ) 160 | ] 161 | 162 | 163 | # -- Options for Epub output ------------------------------------------------- 164 | 165 | # Bibliographic Dublin Core info. 166 | epub_title = project 167 | 168 | # The unique identifier of the text. This can be a ISBN number 169 | # or the project homepage. 170 | # 171 | # epub_identifier = '' 172 | 173 | # A unique identification for the text. 174 | # 175 | # epub_uid = '' 176 | 177 | # A list of files that should not be packed into the epub file. 178 | epub_exclude_files = ["search.html"] 179 | 180 | 181 | # -- Extension configuration ------------------------------------------------- 182 | 183 | # -- Options for todo extension ---------------------------------------------- 184 | 185 | # If true, `todo` and `todoList` produce output, else they produce nothing. 186 | todo_include_todos = True 187 | 188 | # enable google docstring 189 | napoleon_google_docstring = True 190 | napoleon_numpy_docstring = False 191 | -------------------------------------------------------------------------------- /docs/getting-started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | For backward compatibility in previous version only `--[yaml|json|toml|ini|xml|hcl]` was possible with default to json output. 5 | We still keep Monochrome, raw and json output with thoses options. 6 | Output was similar to `jq -MCr` (no color, no compact and no quote on single value) 7 | 8 | But now, by default it's colorized, not raw and if you specify input using `-i` or `--input` output will be the same format. 9 | 10 | There is also a shorter command `wq` comming with the package. 11 | 12 | Like `jq cli`, wildq supports both of stdin and file to the function 13 | 14 | See examples to get some example. 15 | -------------------------------------------------------------------------------- /docs/guide/index.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | User Guide 3 | ========== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | installing 9 | -------------------------------------------------------------------------------- /docs/guide/installing.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | Installing wildq 3 | ====================== 4 | 5 | wildq is available on PyPI, so you can use :program:`pip`: 6 | 7 | .. code-block:: console 8 | 9 | $ pip install wildq 10 | 11 | Alternatively, if you don't have setuptools installed, `download it from PyPi 12 | `_ and run 13 | 14 | .. code-block:: console 15 | 16 | $ python setup.py install 17 | 18 | To use the bleeding-edge version of wildq, you can get the source from 19 | `GitHub `_ and install it as above: 20 | 21 | .. code-block:: console 22 | 23 | $ git clone git://github.com/ahmet2mir/wildq 24 | $ cd wildq 25 | $ python setup.py install 26 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ============================== 2 | Wildq User Documentation 3 | ============================== 4 | 5 | Purpose of this package is to provide a simple wrapper arround jq for different formats. I'm tired of searching a package doing yaml jq, toml jq, ini jq etc. mainly used for scripting. 6 | 7 | 8 | The latest stable version `is available on PyPI `_. 9 | 10 | .. code-block:: console 11 | 12 | pip install -U wildq 13 | 14 | :doc:`getting-started` 15 | wildq's getting-started! 16 | 17 | :doc:`guide/index` 18 | All detailed guide for wildq. 19 | 20 | :doc:`apireference` 21 | The complete API documentation 22 | 23 | Community 24 | --------- 25 | 26 | To get help with using wildq, create an issue on `GitHub Issues `_. 27 | 28 | Contributing 29 | ------------ 30 | 31 | **Yes please!** We are always looking for contributions, additions and improvements. 32 | 33 | The source is available on `GitHub `_ 34 | and contributions are always encouraged. Contributions can be as simple as 35 | minor tweaks to this documentation, the website or the core. 36 | 37 | To contribute, fork the project on `GitHub `_ 38 | and send a pull request. 39 | 40 | Changes 41 | ------- 42 | 43 | See the :doc:`changelog` for a full list of changes to wildq. 44 | 45 | Offline Reading 46 | --------------- 47 | 48 | Download the docs in `pdf `_ 49 | or `epub `_ 50 | formats for offline reading. 51 | 52 | 53 | .. toctree:: 54 | :maxdepth: 1 55 | :numbered: 56 | :hidden: 57 | 58 | getting-started 59 | guide/index 60 | apireference 61 | changelog 62 | 63 | Indices and tables 64 | ------------------ 65 | 66 | * :ref:`genindex` 67 | * :ref:`modindex` 68 | * :ref:`search` 69 | 70 | 71 | Licence 72 | ------- 73 | 74 | Copyright 2020 - Ahmet Demir 75 | 76 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at 77 | 78 | `http://www.apache.org/licenses/LICENSE-2.0 `_ 79 | 80 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 81 | -------------------------------------------------------------------------------- /examples/hcl.hcl: -------------------------------------------------------------------------------- 1 | general { 2 | user = "admin" 3 | } 4 | 5 | keys { 6 | key = "value1" 7 | } 8 | 9 | keys { 10 | key = "value2" 11 | } 12 | -------------------------------------------------------------------------------- /examples/ini.ini: -------------------------------------------------------------------------------- 1 | [general] 2 | user = admin 3 | 4 | [keys] 5 | key1 = value1 6 | key2 = value2 7 | -------------------------------------------------------------------------------- /examples/json.json: -------------------------------------------------------------------------------- 1 | { 2 | "general": { 3 | "user": "admin" 4 | }, 5 | "keys": [ 6 | {"key": "value1"}, 7 | {"key": "value2"}, 8 | "alone" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /examples/toml.toml: -------------------------------------------------------------------------------- 1 | 2 | # keys = [ "alone" ] # produce an error on dump only 3 | 4 | [[keys]] 5 | key = "value1" 6 | 7 | [[keys]] 8 | key = "value2" 9 | 10 | [general] 11 | user = "admin" 12 | -------------------------------------------------------------------------------- /examples/xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | admin 5 | 6 | 7 | 8 | value1 9 | 10 | 11 | value2 12 | 13 | alone 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/yaml.yaml: -------------------------------------------------------------------------------- 1 | general: 2 | user: "admin" 3 | keys: 4 | - key1: value1 5 | - key2: value2 6 | - alone 7 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "alabaster" 3 | version = "0.7.12" 4 | description = "A configurable sidebar-enabled Sphinx theme" 5 | category = "dev" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "altgraph" 11 | version = "0.17" 12 | description = "Python graph (network) package" 13 | category = "dev" 14 | optional = false 15 | python-versions = "*" 16 | 17 | [[package]] 18 | name = "appdirs" 19 | version = "1.4.4" 20 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 21 | category = "dev" 22 | optional = false 23 | python-versions = "*" 24 | 25 | [[package]] 26 | name = "attrs" 27 | version = "20.3.0" 28 | description = "Classes Without Boilerplate" 29 | category = "dev" 30 | optional = false 31 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 32 | 33 | [package.extras] 34 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] 35 | docs = ["furo", "sphinx", "zope.interface"] 36 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] 37 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] 38 | 39 | [[package]] 40 | name = "babel" 41 | version = "2.9.0" 42 | description = "Internationalization utilities" 43 | category = "dev" 44 | optional = false 45 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 46 | 47 | [package.dependencies] 48 | pytz = ">=2015.7" 49 | 50 | [[package]] 51 | name = "bandit" 52 | version = "1.7.0" 53 | description = "Security oriented static analyser for python code." 54 | category = "dev" 55 | optional = false 56 | python-versions = ">=3.5" 57 | 58 | [package.dependencies] 59 | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} 60 | GitPython = ">=1.0.1" 61 | PyYAML = ">=5.3.1" 62 | six = ">=1.10.0" 63 | stevedore = ">=1.20.0" 64 | 65 | [[package]] 66 | name = "black" 67 | version = "20.8b1" 68 | description = "The uncompromising code formatter." 69 | category = "dev" 70 | optional = false 71 | python-versions = ">=3.6" 72 | 73 | [package.dependencies] 74 | appdirs = "*" 75 | click = ">=7.1.2" 76 | dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} 77 | mypy-extensions = ">=0.4.3" 78 | pathspec = ">=0.6,<1" 79 | regex = ">=2020.1.8" 80 | toml = ">=0.10.1" 81 | typed-ast = ">=1.4.0" 82 | typing-extensions = ">=3.7.4" 83 | 84 | [package.extras] 85 | colorama = ["colorama (>=0.4.3)"] 86 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] 87 | 88 | [[package]] 89 | name = "certifi" 90 | version = "2020.12.5" 91 | description = "Python package for providing Mozilla's CA Bundle." 92 | category = "dev" 93 | optional = false 94 | python-versions = "*" 95 | 96 | [[package]] 97 | name = "chardet" 98 | version = "4.0.0" 99 | description = "Universal encoding detector for Python 2 and 3" 100 | category = "dev" 101 | optional = false 102 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 103 | 104 | [[package]] 105 | name = "click" 106 | version = "7.1.2" 107 | description = "Composable command line interface toolkit" 108 | category = "main" 109 | optional = false 110 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 111 | 112 | [[package]] 113 | name = "colorama" 114 | version = "0.4.4" 115 | description = "Cross-platform colored terminal text." 116 | category = "dev" 117 | optional = false 118 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 119 | 120 | [[package]] 121 | name = "coverage" 122 | version = "5.5" 123 | description = "Code coverage measurement for Python" 124 | category = "dev" 125 | optional = false 126 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 127 | 128 | [package.extras] 129 | toml = ["toml"] 130 | 131 | [[package]] 132 | name = "dataclasses" 133 | version = "0.8" 134 | description = "A backport of the dataclasses module for Python 3.6" 135 | category = "dev" 136 | optional = false 137 | python-versions = ">=3.6, <3.7" 138 | 139 | [[package]] 140 | name = "docutils" 141 | version = "0.16" 142 | description = "Docutils -- Python Documentation Utilities" 143 | category = "dev" 144 | optional = false 145 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 146 | 147 | [[package]] 148 | name = "flake8" 149 | version = "3.9.0" 150 | description = "the modular source code checker: pep8 pyflakes and co" 151 | category = "dev" 152 | optional = false 153 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 154 | 155 | [package.dependencies] 156 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 157 | mccabe = ">=0.6.0,<0.7.0" 158 | pycodestyle = ">=2.7.0,<2.8.0" 159 | pyflakes = ">=2.3.0,<2.4.0" 160 | 161 | [[package]] 162 | name = "flake8-bugbear" 163 | version = "20.11.1" 164 | description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." 165 | category = "dev" 166 | optional = false 167 | python-versions = ">=3.6" 168 | 169 | [package.dependencies] 170 | attrs = ">=19.2.0" 171 | flake8 = ">=3.0.0" 172 | 173 | [package.extras] 174 | dev = ["coverage", "black", "hypothesis", "hypothesmith"] 175 | 176 | [[package]] 177 | name = "future" 178 | version = "0.18.2" 179 | description = "Clean single-source support for Python 3 and 2" 180 | category = "dev" 181 | optional = false 182 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 183 | 184 | [[package]] 185 | name = "gitdb" 186 | version = "4.0.7" 187 | description = "Git Object Database" 188 | category = "dev" 189 | optional = false 190 | python-versions = ">=3.4" 191 | 192 | [package.dependencies] 193 | smmap = ">=3.0.1,<5" 194 | 195 | [[package]] 196 | name = "gitpython" 197 | version = "3.1.14" 198 | description = "Python Git Library" 199 | category = "dev" 200 | optional = false 201 | python-versions = ">=3.4" 202 | 203 | [package.dependencies] 204 | gitdb = ">=4.0.1,<5" 205 | 206 | [[package]] 207 | name = "idna" 208 | version = "2.10" 209 | description = "Internationalized Domain Names in Applications (IDNA)" 210 | category = "dev" 211 | optional = false 212 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 213 | 214 | [[package]] 215 | name = "imagesize" 216 | version = "1.2.0" 217 | description = "Getting image size from png/jpeg/jpeg2000/gif file" 218 | category = "dev" 219 | optional = false 220 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 221 | 222 | [[package]] 223 | name = "importlib-metadata" 224 | version = "3.10.1" 225 | description = "Read metadata from Python packages" 226 | category = "dev" 227 | optional = false 228 | python-versions = ">=3.6" 229 | 230 | [package.dependencies] 231 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} 232 | zipp = ">=0.5" 233 | 234 | [package.extras] 235 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 236 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] 237 | 238 | [[package]] 239 | name = "isort" 240 | version = "5.8.0" 241 | description = "A Python utility / library to sort Python imports." 242 | category = "dev" 243 | optional = false 244 | python-versions = ">=3.6,<4.0" 245 | 246 | [package.extras] 247 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 248 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 249 | colors = ["colorama (>=0.4.3,<0.5.0)"] 250 | 251 | [[package]] 252 | name = "jinja2" 253 | version = "2.11.3" 254 | description = "A very fast and expressive template engine." 255 | category = "dev" 256 | optional = false 257 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 258 | 259 | [package.dependencies] 260 | MarkupSafe = ">=0.23" 261 | 262 | [package.extras] 263 | i18n = ["Babel (>=0.8)"] 264 | 265 | [[package]] 266 | name = "jq" 267 | version = "1.1.2" 268 | description = "jq is a lightweight and flexible JSON processor." 269 | category = "main" 270 | optional = false 271 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 272 | 273 | [[package]] 274 | name = "macholib" 275 | version = "1.14" 276 | description = "Mach-O header analysis and editing" 277 | category = "dev" 278 | optional = false 279 | python-versions = "*" 280 | 281 | [package.dependencies] 282 | altgraph = ">=0.15" 283 | 284 | [[package]] 285 | name = "markupsafe" 286 | version = "1.1.1" 287 | description = "Safely add untrusted strings to HTML/XML markup." 288 | category = "dev" 289 | optional = false 290 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" 291 | 292 | [[package]] 293 | name = "mccabe" 294 | version = "0.6.1" 295 | description = "McCabe checker, plugin for flake8" 296 | category = "dev" 297 | optional = false 298 | python-versions = "*" 299 | 300 | [[package]] 301 | name = "mypy-extensions" 302 | version = "0.4.3" 303 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 304 | category = "dev" 305 | optional = false 306 | python-versions = "*" 307 | 308 | [[package]] 309 | name = "packaging" 310 | version = "20.9" 311 | description = "Core utilities for Python packages" 312 | category = "dev" 313 | optional = false 314 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 315 | 316 | [package.dependencies] 317 | pyparsing = ">=2.0.2" 318 | 319 | [[package]] 320 | name = "pathspec" 321 | version = "0.8.1" 322 | description = "Utility library for gitignore style pattern matching of file paths." 323 | category = "dev" 324 | optional = false 325 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 326 | 327 | [[package]] 328 | name = "pbr" 329 | version = "5.5.1" 330 | description = "Python Build Reasonableness" 331 | category = "dev" 332 | optional = false 333 | python-versions = ">=2.6" 334 | 335 | [[package]] 336 | name = "pefile" 337 | version = "2019.4.18" 338 | description = "Python PE parsing module" 339 | category = "dev" 340 | optional = false 341 | python-versions = "*" 342 | 343 | [package.dependencies] 344 | future = "*" 345 | 346 | [[package]] 347 | name = "pycodestyle" 348 | version = "2.7.0" 349 | description = "Python style guide checker" 350 | category = "dev" 351 | optional = false 352 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 353 | 354 | [[package]] 355 | name = "pyflakes" 356 | version = "2.3.1" 357 | description = "passive checker of Python programs" 358 | category = "dev" 359 | optional = false 360 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 361 | 362 | [[package]] 363 | name = "pygments" 364 | version = "2.8.1" 365 | description = "Pygments is a syntax highlighting package written in Python." 366 | category = "main" 367 | optional = false 368 | python-versions = ">=3.5" 369 | 370 | [[package]] 371 | name = "pyhcl" 372 | version = "0.4.4" 373 | description = "HCL configuration parser for python" 374 | category = "main" 375 | optional = false 376 | python-versions = "*" 377 | 378 | [[package]] 379 | name = "pyinstaller" 380 | version = "4.2" 381 | description = "PyInstaller bundles a Python application and all its dependencies into a single package." 382 | category = "dev" 383 | optional = false 384 | python-versions = ">=3.5" 385 | 386 | [package.dependencies] 387 | altgraph = "*" 388 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} 389 | macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} 390 | pefile = {version = ">=2017.8.1", markers = "sys_platform == \"win32\""} 391 | pyinstaller-hooks-contrib = ">=2020.6" 392 | pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} 393 | 394 | [package.extras] 395 | encryption = ["tinyaes (>=1.0.0)"] 396 | hook_testing = ["pytest (>=2.7.3)", "execnet (>=1.5.0)", "psutil"] 397 | 398 | [[package]] 399 | name = "pyinstaller-hooks-contrib" 400 | version = "2021.1" 401 | description = "Community maintained hooks for PyInstaller" 402 | category = "dev" 403 | optional = false 404 | python-versions = "*" 405 | 406 | [[package]] 407 | name = "pyparsing" 408 | version = "2.4.7" 409 | description = "Python parsing module" 410 | category = "dev" 411 | optional = false 412 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 413 | 414 | [[package]] 415 | name = "pytz" 416 | version = "2021.1" 417 | description = "World timezone definitions, modern and historical" 418 | category = "dev" 419 | optional = false 420 | python-versions = "*" 421 | 422 | [[package]] 423 | name = "pywin32-ctypes" 424 | version = "0.2.0" 425 | description = "" 426 | category = "dev" 427 | optional = false 428 | python-versions = "*" 429 | 430 | [[package]] 431 | name = "pyyaml" 432 | version = "5.4.1" 433 | description = "YAML parser and emitter for Python" 434 | category = "main" 435 | optional = false 436 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 437 | 438 | [[package]] 439 | name = "regex" 440 | version = "2021.4.4" 441 | description = "Alternative regular expression module, to replace re." 442 | category = "dev" 443 | optional = false 444 | python-versions = "*" 445 | 446 | [[package]] 447 | name = "requests" 448 | version = "2.25.1" 449 | description = "Python HTTP for Humans." 450 | category = "dev" 451 | optional = false 452 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 453 | 454 | [package.dependencies] 455 | certifi = ">=2017.4.17" 456 | chardet = ">=3.0.2,<5" 457 | idna = ">=2.5,<3" 458 | urllib3 = ">=1.21.1,<1.27" 459 | 460 | [package.extras] 461 | security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] 462 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 463 | 464 | [[package]] 465 | name = "six" 466 | version = "1.15.0" 467 | description = "Python 2 and 3 compatibility utilities" 468 | category = "dev" 469 | optional = false 470 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 471 | 472 | [[package]] 473 | name = "smmap" 474 | version = "4.0.0" 475 | description = "A pure Python implementation of a sliding window memory map manager" 476 | category = "dev" 477 | optional = false 478 | python-versions = ">=3.5" 479 | 480 | [[package]] 481 | name = "snowballstemmer" 482 | version = "2.1.0" 483 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." 484 | category = "dev" 485 | optional = false 486 | python-versions = "*" 487 | 488 | [[package]] 489 | name = "sphinx" 490 | version = "3.5.4" 491 | description = "Python documentation generator" 492 | category = "dev" 493 | optional = false 494 | python-versions = ">=3.5" 495 | 496 | [package.dependencies] 497 | alabaster = ">=0.7,<0.8" 498 | babel = ">=1.3" 499 | colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} 500 | docutils = ">=0.12,<0.17" 501 | imagesize = "*" 502 | Jinja2 = ">=2.3" 503 | packaging = "*" 504 | Pygments = ">=2.0" 505 | requests = ">=2.5.0" 506 | snowballstemmer = ">=1.1" 507 | sphinxcontrib-applehelp = "*" 508 | sphinxcontrib-devhelp = "*" 509 | sphinxcontrib-htmlhelp = "*" 510 | sphinxcontrib-jsmath = "*" 511 | sphinxcontrib-qthelp = "*" 512 | sphinxcontrib-serializinghtml = "*" 513 | 514 | [package.extras] 515 | docs = ["sphinxcontrib-websupport"] 516 | lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.800)", "docutils-stubs"] 517 | test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] 518 | 519 | [[package]] 520 | name = "sphinx-rtd-theme" 521 | version = "0.5.2" 522 | description = "Read the Docs theme for Sphinx" 523 | category = "dev" 524 | optional = false 525 | python-versions = "*" 526 | 527 | [package.dependencies] 528 | docutils = "<0.17" 529 | sphinx = "*" 530 | 531 | [package.extras] 532 | dev = ["transifex-client", "sphinxcontrib-httpdomain", "bump2version"] 533 | 534 | [[package]] 535 | name = "sphinxcontrib-applehelp" 536 | version = "1.0.2" 537 | description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" 538 | category = "dev" 539 | optional = false 540 | python-versions = ">=3.5" 541 | 542 | [package.extras] 543 | lint = ["flake8", "mypy", "docutils-stubs"] 544 | test = ["pytest"] 545 | 546 | [[package]] 547 | name = "sphinxcontrib-devhelp" 548 | version = "1.0.2" 549 | description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." 550 | category = "dev" 551 | optional = false 552 | python-versions = ">=3.5" 553 | 554 | [package.extras] 555 | lint = ["flake8", "mypy", "docutils-stubs"] 556 | test = ["pytest"] 557 | 558 | [[package]] 559 | name = "sphinxcontrib-htmlhelp" 560 | version = "1.0.3" 561 | description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" 562 | category = "dev" 563 | optional = false 564 | python-versions = ">=3.5" 565 | 566 | [package.extras] 567 | lint = ["flake8", "mypy", "docutils-stubs"] 568 | test = ["pytest", "html5lib"] 569 | 570 | [[package]] 571 | name = "sphinxcontrib-jsmath" 572 | version = "1.0.1" 573 | description = "A sphinx extension which renders display math in HTML via JavaScript" 574 | category = "dev" 575 | optional = false 576 | python-versions = ">=3.5" 577 | 578 | [package.extras] 579 | test = ["pytest", "flake8", "mypy"] 580 | 581 | [[package]] 582 | name = "sphinxcontrib-qthelp" 583 | version = "1.0.3" 584 | description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." 585 | category = "dev" 586 | optional = false 587 | python-versions = ">=3.5" 588 | 589 | [package.extras] 590 | lint = ["flake8", "mypy", "docutils-stubs"] 591 | test = ["pytest"] 592 | 593 | [[package]] 594 | name = "sphinxcontrib-serializinghtml" 595 | version = "1.1.4" 596 | description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." 597 | category = "dev" 598 | optional = false 599 | python-versions = ">=3.5" 600 | 601 | [package.extras] 602 | lint = ["flake8", "mypy", "docutils-stubs"] 603 | test = ["pytest"] 604 | 605 | [[package]] 606 | name = "stevedore" 607 | version = "3.3.0" 608 | description = "Manage dynamic plugins for Python applications" 609 | category = "dev" 610 | optional = false 611 | python-versions = ">=3.6" 612 | 613 | [package.dependencies] 614 | importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} 615 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 616 | 617 | [[package]] 618 | name = "toml" 619 | version = "0.10.2" 620 | description = "Python Library for Tom's Obvious, Minimal Language" 621 | category = "main" 622 | optional = false 623 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 624 | 625 | [[package]] 626 | name = "typed-ast" 627 | version = "1.4.3" 628 | description = "a fork of Python 2 and 3 ast modules with type comment support" 629 | category = "dev" 630 | optional = false 631 | python-versions = "*" 632 | 633 | [[package]] 634 | name = "typing-extensions" 635 | version = "3.7.4.3" 636 | description = "Backported and Experimental Type Hints for Python 3.5+" 637 | category = "dev" 638 | optional = false 639 | python-versions = "*" 640 | 641 | [[package]] 642 | name = "urllib3" 643 | version = "1.26.4" 644 | description = "HTTP library with thread-safe connection pooling, file post, and more." 645 | category = "dev" 646 | optional = false 647 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 648 | 649 | [package.extras] 650 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 651 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 652 | brotli = ["brotlipy (>=0.6.0)"] 653 | 654 | [[package]] 655 | name = "xmltodict" 656 | version = "0.12.0" 657 | description = "Makes working with XML feel like you are working with JSON" 658 | category = "main" 659 | optional = false 660 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 661 | 662 | [[package]] 663 | name = "zipp" 664 | version = "3.4.1" 665 | description = "Backport of pathlib-compatible object wrapper for zip files" 666 | category = "dev" 667 | optional = false 668 | python-versions = ">=3.6" 669 | 670 | [package.extras] 671 | docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] 672 | testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] 673 | 674 | [metadata] 675 | lock-version = "1.1" 676 | python-versions = ">=3.6,<4.0" 677 | content-hash = "d5908516c8fd12173960824cb2a5d2d32661b0bd6cca65b65f8f1a45f5ca169a" 678 | 679 | [metadata.files] 680 | alabaster = [ 681 | {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, 682 | {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, 683 | ] 684 | altgraph = [ 685 | {file = "altgraph-0.17-py2.py3-none-any.whl", hash = "sha256:c623e5f3408ca61d4016f23a681b9adb100802ca3e3da5e718915a9e4052cebe"}, 686 | {file = "altgraph-0.17.tar.gz", hash = "sha256:1f05a47122542f97028caf78775a095fbe6a2699b5089de8477eb583167d69aa"}, 687 | ] 688 | appdirs = [ 689 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, 690 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, 691 | ] 692 | attrs = [ 693 | {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, 694 | {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, 695 | ] 696 | babel = [ 697 | {file = "Babel-2.9.0-py2.py3-none-any.whl", hash = "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5"}, 698 | {file = "Babel-2.9.0.tar.gz", hash = "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"}, 699 | ] 700 | bandit = [ 701 | {file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"}, 702 | {file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"}, 703 | ] 704 | black = [ 705 | {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, 706 | ] 707 | certifi = [ 708 | {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, 709 | {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, 710 | ] 711 | chardet = [ 712 | {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, 713 | {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, 714 | ] 715 | click = [ 716 | {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, 717 | {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, 718 | ] 719 | colorama = [ 720 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 721 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 722 | ] 723 | coverage = [ 724 | {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, 725 | {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, 726 | {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"}, 727 | {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"}, 728 | {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"}, 729 | {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"}, 730 | {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"}, 731 | {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"}, 732 | {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"}, 733 | {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"}, 734 | {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"}, 735 | {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"}, 736 | {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"}, 737 | {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"}, 738 | {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"}, 739 | {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"}, 740 | {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"}, 741 | {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"}, 742 | {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"}, 743 | {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"}, 744 | {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"}, 745 | {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"}, 746 | {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"}, 747 | {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"}, 748 | {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"}, 749 | {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"}, 750 | {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"}, 751 | {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"}, 752 | {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"}, 753 | {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"}, 754 | {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"}, 755 | {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"}, 756 | {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"}, 757 | {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"}, 758 | {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"}, 759 | {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"}, 760 | {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"}, 761 | {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"}, 762 | {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"}, 763 | {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"}, 764 | {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"}, 765 | {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"}, 766 | {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"}, 767 | {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"}, 768 | {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"}, 769 | {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"}, 770 | {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"}, 771 | {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"}, 772 | {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"}, 773 | {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"}, 774 | {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, 775 | {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, 776 | ] 777 | dataclasses = [ 778 | {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, 779 | {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, 780 | ] 781 | docutils = [ 782 | {file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, 783 | {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, 784 | ] 785 | flake8 = [ 786 | {file = "flake8-3.9.0-py2.py3-none-any.whl", hash = "sha256:12d05ab02614b6aee8df7c36b97d1a3b2372761222b19b58621355e82acddcff"}, 787 | {file = "flake8-3.9.0.tar.gz", hash = "sha256:78873e372b12b093da7b5e5ed302e8ad9e988b38b063b61ad937f26ca58fc5f0"}, 788 | ] 789 | flake8-bugbear = [ 790 | {file = "flake8-bugbear-20.11.1.tar.gz", hash = "sha256:528020129fea2dea33a466b9d64ab650aa3e5f9ffc788b70ea4bc6cf18283538"}, 791 | {file = "flake8_bugbear-20.11.1-py36.py37.py38-none-any.whl", hash = "sha256:f35b8135ece7a014bc0aee5b5d485334ac30a6da48494998cc1fabf7ec70d703"}, 792 | ] 793 | future = [ 794 | {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, 795 | ] 796 | gitdb = [ 797 | {file = "gitdb-4.0.7-py3-none-any.whl", hash = "sha256:6c4cc71933456991da20917998acbe6cf4fb41eeaab7d6d67fbc05ecd4c865b0"}, 798 | {file = "gitdb-4.0.7.tar.gz", hash = "sha256:96bf5c08b157a666fec41129e6d327235284cca4c81e92109260f353ba138005"}, 799 | ] 800 | gitpython = [ 801 | {file = "GitPython-3.1.14-py3-none-any.whl", hash = "sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b"}, 802 | {file = "GitPython-3.1.14.tar.gz", hash = "sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61"}, 803 | ] 804 | idna = [ 805 | {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, 806 | {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, 807 | ] 808 | imagesize = [ 809 | {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, 810 | {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, 811 | ] 812 | importlib-metadata = [ 813 | {file = "importlib_metadata-3.10.1-py3-none-any.whl", hash = "sha256:2ec0faae539743ae6aaa84b49a169670a465f7f5d64e6add98388cc29fd1f2f6"}, 814 | {file = "importlib_metadata-3.10.1.tar.gz", hash = "sha256:c9356b657de65c53744046fa8f7358afe0714a1af7d570c00c3835c2d724a7c1"}, 815 | ] 816 | isort = [ 817 | {file = "isort-5.8.0-py3-none-any.whl", hash = "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"}, 818 | {file = "isort-5.8.0.tar.gz", hash = "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6"}, 819 | ] 820 | jinja2 = [ 821 | {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, 822 | {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, 823 | ] 824 | jq = [ 825 | {file = "jq-1.1.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b20372020c3f54ebdf6758bc536df8fb459041a65b9a1c31e1d22ee36f18106"}, 826 | {file = "jq-1.1.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b32ee82ca68b2775a9de70f64a95f513e27b52c540fccf57d163cba7f287c8da"}, 827 | {file = "jq-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d4798c4633ae400bbb65bcc116a0064764855fefdf4ee8f8b6407041114ef1e3"}, 828 | {file = "jq-1.1.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:2656c8483b17dcb41d4dd2fbfeef7e8cbb3df9faa6256f38c1552f19d929cc1d"}, 829 | {file = "jq-1.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:16c940382719a3402b9f18927c84be0300686398a633fe67b40990ed4f468dbb"}, 830 | {file = "jq-1.1.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ccf2356c5da3f7fff9caec515ab5cf117dd1b56502e844fbdf9fcac583531556"}, 831 | {file = "jq-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:47d81d79d4dde10c5e3e5bc1cc68769f71cd1a46d07612e9ec17953423ac77a8"}, 832 | {file = "jq-1.1.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:b5d84542402397f4f6ca9d0d2ef5bd4b22706aeb2a683647bdba495591f299a6"}, 833 | {file = "jq-1.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:bb252829ecc95159a413212023aed74b88096aa0b7fc8331886077dc1fbacfa2"}, 834 | {file = "jq-1.1.2-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:7188814b485dce586ea435e5b24f75977598267800485c0c70940428b5b753a5"}, 835 | {file = "jq-1.1.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2a6dabf4e90765f470b17b746c86d6864ff4f6f2bc76b941315b66499f5ef1d2"}, 836 | {file = "jq-1.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:0835a1c61dd30f7e90c97bab12ec4be03635b59367151157edfd178da057acf0"}, 837 | {file = "jq-1.1.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:31555b7db049134774de95e429b90b23469802af88bcd9d28bd03e95d7902f1a"}, 838 | {file = "jq-1.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:52a9a5d1db62442ca4ef0d0655b17698b58caf02531c77a27a1a91e4bfef5094"}, 839 | {file = "jq-1.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c4bce315e05518d39961c11d54d1f694ee83bbeff9fa6cf724835729d817e5a0"}, 840 | {file = "jq-1.1.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c075fc02fabe70f395ef7d156c712e2d619970735706de79c8432d573e242ea3"}, 841 | {file = "jq-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1e3a635135a69b4ac3b872da6365a43dd239a874a4c8286ccd5ee98d25ba3777"}, 842 | {file = "jq-1.1.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:b24d6dfc42a6c58debd85303b2cbb778da02d7564dc9364488eff3fac047d9bb"}, 843 | {file = "jq-1.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:28565916cf2001a363f41981de1dd0729b23332df9f3d7e5b50a8b9735ee7fd0"}, 844 | {file = "jq-1.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e84127ef60d2f0c779c63d5707c8d05e84db8b5076109c252899a8ecdac1c63e"}, 845 | {file = "jq-1.1.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:189eaccad7f9fa24ae54a466de7e5a697502d3d1e62086deeeda55c7d6e269a4"}, 846 | {file = "jq-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3b8f7e765e46a42df93bea3b95c38f17eeba6744f78cb503bc551f5aabaee1e3"}, 847 | {file = "jq-1.1.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:0619bda153ba8e2e6dbb4c903254177505b9d3eb4698e300f2853acaac344a82"}, 848 | {file = "jq-1.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:037a787ebb9c54cbb72623644566127eddca0147cb05c6ee08ed3e0e453b8864"}, 849 | {file = "jq-1.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79af00d1158324fb005abc5ff72df8343d152c782c7a27bd4b4b09ba05cdcd58"}, 850 | {file = "jq-1.1.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:30d0c0593f01e97a15218323936144e6fc564fe21c1314844a633c4b04c4753d"}, 851 | {file = "jq-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8fc766f4aecf3f65beffaf88d3721a5ad0117d719adcde142ea56ae93cd8f3f3"}, 852 | {file = "jq-1.1.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:f90818aac65d91506656d2313cbc03181d7c44f9ee446ac2153b046755d82265"}, 853 | {file = "jq-1.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:7e976797e3c977a3c2b695aea640b8548a702989212ac1e5b08677a4cd4932d0"}, 854 | {file = "jq-1.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b44b536296831f7d8c40ad24c53104e9f18b54907810753e38032a837035b69e"}, 855 | {file = "jq-1.1.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b709a76d42033ede948c1e0322dde6e876e8613fd2a9a9ca02ac2fdccf6c1d3"}, 856 | {file = "jq-1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:573e45773ff17438105bb2c0f264290c712838bae68c9468d979a261e102d9be"}, 857 | {file = "jq-1.1.2-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:93fddfa1750499840fc6b14f9ae48243fc28827845ae667259b7fd0f0296eab1"}, 858 | {file = "jq-1.1.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:0986754c900afd0e18c039e5844b92446ed48052885d2983fc1d11f748221527"}, 859 | {file = "jq-1.1.2-pp27-pypy_73-macosx_10_7_x86_64.whl", hash = "sha256:d81443acb22cbf958011734f56816c2df8166bfed2b02035adf37bcfd0bbce2c"}, 860 | {file = "jq-1.1.2-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:a0ee347ed72472a03bb3731686a86d5e6ab4999cefc55f69046ef9e352b754d4"}, 861 | {file = "jq-1.1.2-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:1d3801b89e9102ee2d97ce2e98e175e2b1c555e7b14faea87faadf936e640973"}, 862 | {file = "jq-1.1.2-pp36-pypy36_pp73-macosx_10_7_x86_64.whl", hash = "sha256:825d5a1ee80923a15ca35c84e91ee27ea2ab0d5155eaea6e93f7c9943b126e27"}, 863 | {file = "jq-1.1.2-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:ff825949c9505a998a9a98b63658c8ed53dfdb095fe5cc62538ef77cb71121d4"}, 864 | {file = "jq-1.1.2-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:265fd43f5ae91ca342edaf33da09d37057229679040233d0f1b6ef101b937b16"}, 865 | {file = "jq-1.1.2-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:27eee5fb0b3f180f39960bdd8d8563141caa454b9c6fc5c04c1dc1a6ea5ccfeb"}, 866 | {file = "jq-1.1.2-pp37-pypy37_pp73-manylinux1_x86_64.whl", hash = "sha256:5553d4f51f28fe4be463ce78ecbd3546ba100715baaa6194ae04a5f94aa22844"}, 867 | {file = "jq-1.1.2-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:09e235c5d17d9cd8b19aa81da2e01cb2c30c700ff55ae43e72e609504bfbffff"}, 868 | {file = "jq-1.1.2.tar.gz", hash = "sha256:77e747c6ad10ce65479f5f9064ab036483bf307bf71fdd7d6235ef895fcc506e"}, 869 | ] 870 | macholib = [ 871 | {file = "macholib-1.14-py2.py3-none-any.whl", hash = "sha256:c500f02867515e6c60a27875b408920d18332ddf96b4035ef03beddd782d4281"}, 872 | {file = "macholib-1.14.tar.gz", hash = "sha256:0c436bc847e7b1d9bda0560351bf76d7caf930fb585a828d13608839ef42c432"}, 873 | ] 874 | markupsafe = [ 875 | {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, 876 | {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, 877 | {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, 878 | {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, 879 | {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, 880 | {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, 881 | {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, 882 | {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, 883 | {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, 884 | {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, 885 | {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, 886 | {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, 887 | {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, 888 | {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, 889 | {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, 890 | {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, 891 | {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, 892 | {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, 893 | {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"}, 894 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, 895 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, 896 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"}, 897 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"}, 898 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"}, 899 | {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, 900 | {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, 901 | {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, 902 | {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"}, 903 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, 904 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, 905 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"}, 906 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"}, 907 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"}, 908 | {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, 909 | {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, 910 | {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, 911 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, 912 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, 913 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"}, 914 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"}, 915 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"}, 916 | {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, 917 | {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, 918 | {file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"}, 919 | {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"}, 920 | {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"}, 921 | {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"}, 922 | {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"}, 923 | {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"}, 924 | {file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"}, 925 | {file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"}, 926 | {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, 927 | ] 928 | mccabe = [ 929 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 930 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 931 | ] 932 | mypy-extensions = [ 933 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 934 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 935 | ] 936 | packaging = [ 937 | {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, 938 | {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, 939 | ] 940 | pathspec = [ 941 | {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, 942 | {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, 943 | ] 944 | pbr = [ 945 | {file = "pbr-5.5.1-py2.py3-none-any.whl", hash = "sha256:b236cde0ac9a6aedd5e3c34517b423cd4fd97ef723849da6b0d2231142d89c00"}, 946 | {file = "pbr-5.5.1.tar.gz", hash = "sha256:5fad80b613c402d5b7df7bd84812548b2a61e9977387a80a5fc5c396492b13c9"}, 947 | ] 948 | pefile = [ 949 | {file = "pefile-2019.4.18.tar.gz", hash = "sha256:a5d6e8305c6b210849b47a6174ddf9c452b2888340b8177874b862ba6c207645"}, 950 | ] 951 | pycodestyle = [ 952 | {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, 953 | {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, 954 | ] 955 | pyflakes = [ 956 | {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, 957 | {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, 958 | ] 959 | pygments = [ 960 | {file = "Pygments-2.8.1-py3-none-any.whl", hash = "sha256:534ef71d539ae97d4c3a4cf7d6f110f214b0e687e92f9cb9d2a3b0d3101289c8"}, 961 | {file = "Pygments-2.8.1.tar.gz", hash = "sha256:2656e1a6edcdabf4275f9a3640db59fd5de107d88e8663c5d4e9a0fa62f77f94"}, 962 | ] 963 | pyhcl = [ 964 | {file = "pyhcl-0.4.4.tar.gz", hash = "sha256:2d9b9dcdf1023d812bfed561ba72c99104c5b3f52e558d595130a44ce081b003"}, 965 | ] 966 | pyinstaller = [ 967 | {file = "pyinstaller-4.2.tar.gz", hash = "sha256:f5c0eeb2aa663cce9a5404292c0195011fa500a6501c873a466b2e8cad3c950c"}, 968 | ] 969 | pyinstaller-hooks-contrib = [ 970 | {file = "pyinstaller-hooks-contrib-2021.1.tar.gz", hash = "sha256:892310e6363655838485ee748bf1c5e5cade7963686d9af8650ee218a3e0b031"}, 971 | {file = "pyinstaller_hooks_contrib-2021.1-py2.py3-none-any.whl", hash = "sha256:27558072021857d89524c42136feaa2ffe4f003f1bdf0278f9b24f6902c1759c"}, 972 | ] 973 | pyparsing = [ 974 | {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, 975 | {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, 976 | ] 977 | pytz = [ 978 | {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, 979 | {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, 980 | ] 981 | pywin32-ctypes = [ 982 | {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, 983 | {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, 984 | ] 985 | pyyaml = [ 986 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 987 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 988 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 989 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 990 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 991 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 992 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, 993 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, 994 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 995 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 996 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 997 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 998 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, 999 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, 1000 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 1001 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 1002 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 1003 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 1004 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, 1005 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, 1006 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 1007 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 1008 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 1009 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 1010 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, 1011 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, 1012 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 1013 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 1014 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 1015 | ] 1016 | regex = [ 1017 | {file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000"}, 1018 | {file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711"}, 1019 | {file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11"}, 1020 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968"}, 1021 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0"}, 1022 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4"}, 1023 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a"}, 1024 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7"}, 1025 | {file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29"}, 1026 | {file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79"}, 1027 | {file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8"}, 1028 | {file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31"}, 1029 | {file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a"}, 1030 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5"}, 1031 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82"}, 1032 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765"}, 1033 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e"}, 1034 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439"}, 1035 | {file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d"}, 1036 | {file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3"}, 1037 | {file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500"}, 1038 | {file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14"}, 1039 | {file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480"}, 1040 | {file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc"}, 1041 | {file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093"}, 1042 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10"}, 1043 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f"}, 1044 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87"}, 1045 | {file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac"}, 1046 | {file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2"}, 1047 | {file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17"}, 1048 | {file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605"}, 1049 | {file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9"}, 1050 | {file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7"}, 1051 | {file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8"}, 1052 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed"}, 1053 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c"}, 1054 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"}, 1055 | {file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6"}, 1056 | {file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07"}, 1057 | {file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"}, 1058 | ] 1059 | requests = [ 1060 | {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, 1061 | {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, 1062 | ] 1063 | six = [ 1064 | {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, 1065 | {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, 1066 | ] 1067 | smmap = [ 1068 | {file = "smmap-4.0.0-py2.py3-none-any.whl", hash = "sha256:a9a7479e4c572e2e775c404dcd3080c8dc49f39918c2cf74913d30c4c478e3c2"}, 1069 | {file = "smmap-4.0.0.tar.gz", hash = "sha256:7e65386bd122d45405ddf795637b7f7d2b532e7e401d46bbe3fb49b9986d5182"}, 1070 | ] 1071 | snowballstemmer = [ 1072 | {file = "snowballstemmer-2.1.0-py2.py3-none-any.whl", hash = "sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2"}, 1073 | {file = "snowballstemmer-2.1.0.tar.gz", hash = "sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914"}, 1074 | ] 1075 | sphinx = [ 1076 | {file = "Sphinx-3.5.4-py3-none-any.whl", hash = "sha256:2320d4e994a191f4b4be27da514e46b3d6b420f2ff895d064f52415d342461e8"}, 1077 | {file = "Sphinx-3.5.4.tar.gz", hash = "sha256:19010b7b9fa0dc7756a6e105b2aacd3a80f798af3c25c273be64d7beeb482cb1"}, 1078 | ] 1079 | sphinx-rtd-theme = [ 1080 | {file = "sphinx_rtd_theme-0.5.2-py2.py3-none-any.whl", hash = "sha256:4a05bdbe8b1446d77a01e20a23ebc6777c74f43237035e76be89699308987d6f"}, 1081 | {file = "sphinx_rtd_theme-0.5.2.tar.gz", hash = "sha256:32bd3b5d13dc8186d7a42fc816a23d32e83a4827d7d9882948e7b837c232da5a"}, 1082 | ] 1083 | sphinxcontrib-applehelp = [ 1084 | {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, 1085 | {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, 1086 | ] 1087 | sphinxcontrib-devhelp = [ 1088 | {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, 1089 | {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, 1090 | ] 1091 | sphinxcontrib-htmlhelp = [ 1092 | {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, 1093 | {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, 1094 | ] 1095 | sphinxcontrib-jsmath = [ 1096 | {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, 1097 | {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, 1098 | ] 1099 | sphinxcontrib-qthelp = [ 1100 | {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, 1101 | {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, 1102 | ] 1103 | sphinxcontrib-serializinghtml = [ 1104 | {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, 1105 | {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, 1106 | ] 1107 | stevedore = [ 1108 | {file = "stevedore-3.3.0-py3-none-any.whl", hash = "sha256:50d7b78fbaf0d04cd62411188fa7eedcb03eb7f4c4b37005615ceebe582aa82a"}, 1109 | {file = "stevedore-3.3.0.tar.gz", hash = "sha256:3a5bbd0652bf552748871eaa73a4a8dc2899786bc497a2aa1fcb4dcdb0debeee"}, 1110 | ] 1111 | toml = [ 1112 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 1113 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 1114 | ] 1115 | typed-ast = [ 1116 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, 1117 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, 1118 | {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, 1119 | {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, 1120 | {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, 1121 | {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, 1122 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, 1123 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, 1124 | {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, 1125 | {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, 1126 | {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, 1127 | {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, 1128 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, 1129 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, 1130 | {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, 1131 | {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, 1132 | {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, 1133 | {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, 1134 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, 1135 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, 1136 | {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, 1137 | {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, 1138 | {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, 1139 | {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, 1140 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, 1141 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, 1142 | {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, 1143 | {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, 1144 | {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, 1145 | {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, 1146 | ] 1147 | typing-extensions = [ 1148 | {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"}, 1149 | {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, 1150 | {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, 1151 | ] 1152 | urllib3 = [ 1153 | {file = "urllib3-1.26.4-py2.py3-none-any.whl", hash = "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df"}, 1154 | {file = "urllib3-1.26.4.tar.gz", hash = "sha256:e7b021f7241115872f92f43c6508082facffbd1c048e3c6e2bb9c2a157e28937"}, 1155 | ] 1156 | xmltodict = [ 1157 | {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"}, 1158 | {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"}, 1159 | ] 1160 | zipp = [ 1161 | {file = "zipp-3.4.1-py3-none-any.whl", hash = "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098"}, 1162 | {file = "zipp-3.4.1.tar.gz", hash = "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76"}, 1163 | ] 1164 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # NOTE: you have to use single-quoted strings in TOML for regular expressions. 2 | # It's the equivalent of r-strings in Python. Multiline strings are treated as 3 | # verbose regular expressions by Black. Use [ ] to denote a significant space 4 | # character. 5 | [build-system] 6 | requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning"] 7 | build-backend = "poetry.core.masonry.api" 8 | 9 | [tool] 10 | 11 | [tool.poetry] 12 | name = "wildq" 13 | version = "0.0.0" # managed by poetry-dynamic-versioning 14 | description = "Command-line TOML/JSON/INI/YAML/XML processor using jq c bindings." 15 | license = "Apache 2.0" 16 | keywords = [ 17 | "wildq", 18 | "jq", 19 | "yaml", 20 | "json", 21 | "toml", 22 | "xml", 23 | "ini", 24 | "parser", 25 | "shell", 26 | "hcl", 27 | "color", 28 | "highlight", 29 | ] 30 | classifiers = [ 31 | "Development Status :: 4 - Beta", 32 | "Environment :: Console", 33 | "Intended Audience :: Developers", 34 | "License :: OSI Approved :: Apache Software License", 35 | "Operating System :: OS Independent", 36 | "Programming Language :: Python", 37 | "Programming Language :: Python :: 3.6", 38 | "Programming Language :: Python :: 3.7", 39 | "Programming Language :: Python :: 3.8", 40 | "Programming Language :: Python :: 3 :: Only", 41 | "Topic :: Software Development :: Libraries :: Python Modules", 42 | "Topic :: Software Development :: Build Tools", 43 | ] 44 | authors = ["Ahmet Demir "] 45 | readme = "README.md" 46 | documentation = "https://wildq.readthedocs.io/en/latest" 47 | homepage = "https://github.com/ahmet2mir/wildq" 48 | repository = "https://github.com/ahmet2mir/wildq.git" 49 | 50 | [tool.poetry-dynamic-versioning] 51 | enable = true 52 | vcs = "git" 53 | format-jinja = """ 54 | {%- if distance == 0 -%} 55 | {{ serialize_pep440(base) }} 56 | {%- elif revision is not none -%} 57 | {{ serialize_pep440(base, stage, revision + 1, dev=distance, metadata=[commit]) }} 58 | {%- else -%} 59 | {{ serialize_pep440(bump_version(base), stage, revision, dev=distance, metadata=[commit]) }} 60 | {%- endif -%} 61 | """ 62 | 63 | [tool.poetry.scripts] 64 | wildq = 'wildq.__main__:main' 65 | wq = 'wildq.__main__:main' 66 | 67 | [tool.poetry.urls] 68 | Changelog = "https://github.com/ahmet2mir/wildq/issues" 69 | 70 | [tool.poetry-dynamic-versioning.substitution] 71 | files = ["wildq/_wildq_version.py"] 72 | 73 | [tool.black] 74 | line-length = 80 75 | target-version = ['py36', 'py37', 'py38'] 76 | include = '\.pyi?$' 77 | exclude = ''' 78 | /( 79 | \.eggs 80 | | \.git 81 | | \.hg 82 | | \.mypy_cache 83 | | \.tox 84 | | \.venv 85 | | _build 86 | | buck-out 87 | | build 88 | | dist 89 | | tests/data 90 | )/ 91 | ''' 92 | 93 | [tool.isort] 94 | profile = "black" 95 | force_single_line = true 96 | atomic = true 97 | include_trailing_comma = true 98 | lines_after_imports = 2 99 | lines_between_types = 1 100 | use_parentheses = true 101 | src_paths = ["poetry", "tests"] 102 | skip_glob = ["*/setup.py"] 103 | filter_files = true 104 | known_first_party = "poetry" 105 | 106 | [tool.poetry.dependencies] 107 | python = ">=3.6,<4.0" 108 | toml = "^0.10.1" 109 | PyYAML = "^5.3.1" 110 | xmltodict = "^0.12.0" 111 | jq = "^1.1.1" 112 | pyhcl = "^0.4.4" 113 | click = "^7.1.2" 114 | Pygments = "^2.7.2" 115 | 116 | [tool.poetry.dev-dependencies] 117 | bandit = "^1.6.2" 118 | black = "^20.8b1" 119 | coverage = "^5.3" 120 | flake8 = "^3.8.4" 121 | flake8-bugbear = "^20.1.4" 122 | pyinstaller = "^4.0" 123 | Sphinx = "^3.2.1" 124 | sphinx-rtd-theme = "^0.5.0" 125 | isort = "^5.6.4" 126 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmet2mir/wildq/c6e9535829cf6b4d0c2df2de5f8938d249602d08/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_hcl.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.hcl_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeHCL(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | general { 10 | user = "admin" 11 | } 12 | 13 | keys { 14 | key = "value1" 15 | } 16 | 17 | keys { 18 | key = "value2" 19 | } 20 | """ 21 | 22 | def test_loader(self): 23 | assert loader(self.data)["general"]["user"] == "admin" 24 | 25 | def test_dumper(self): 26 | dumped = dumper({"general": {"user": "admin"}}) 27 | assert loader(dumped)["general"]["user"] == "admin" 28 | 29 | 30 | if __name__ == "__main__": 31 | main(module="test_hcl") 32 | -------------------------------------------------------------------------------- /tests/test_ini.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.ini_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeINI(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | [general] 10 | user = admin 11 | 12 | [keys] 13 | key1 = value1 14 | key2 = value2 15 | """ 16 | 17 | def test_loader(self): 18 | assert loader(self.data)["general"]["user"] == "admin" 19 | 20 | def test_dumper(self): 21 | dumped = dumper({"general": {"user": "admin"}}) 22 | assert loader(dumped)["general"]["user"] == "admin" 23 | 24 | 25 | if __name__ == "__main__": 26 | main(module="test_ini") 27 | -------------------------------------------------------------------------------- /tests/test_json.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.json_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeJSON(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | { 10 | "general": { 11 | "user": "admin" 12 | }, 13 | "keys": [ 14 | {"key": "value1"}, 15 | {"key": "value2"}, 16 | "alone" 17 | ] 18 | } 19 | """ 20 | 21 | def test_loader(self): 22 | assert loader(self.data)["general"]["user"] == "admin" 23 | 24 | def test_dumper(self): 25 | dumped = dumper({"general": {"user": "admin"}}) 26 | assert loader(dumped)["general"]["user"] == "admin" 27 | 28 | 29 | if __name__ == "__main__": 30 | main(module="test_json") 31 | -------------------------------------------------------------------------------- /tests/test_toml.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.toml_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeTOML(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | [[keys]] 10 | key = "value2" 11 | 12 | [[keys]] 13 | key = "value1" 14 | 15 | [general] 16 | user = "admin" 17 | """ 18 | 19 | def test_loader(self): 20 | assert loader(self.data)["general"]["user"] == "admin" 21 | 22 | def test_dumper(self): 23 | dumped = dumper({"general": {"user": "admin"}}) 24 | assert loader(dumped)["general"]["user"] == "admin" 25 | 26 | 27 | if __name__ == "__main__": 28 | main(module="test_toml") 29 | -------------------------------------------------------------------------------- /tests/test_wild.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmet2mir/wildq/c6e9535829cf6b4d0c2df2de5f8938d249602d08/tests/test_wild.py -------------------------------------------------------------------------------- /tests/test_xml.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.xml_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeXML(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | 10 | 11 | admin 12 | 13 | 14 | 15 | value1 16 | 17 | 18 | value2 19 | 20 | alone 21 | 22 | 23 | """ 24 | 25 | def test_loader(self): 26 | assert loader(self.data)["root"]["general"]["user"] == "admin" 27 | 28 | def test_dumper(self): 29 | dumped = dumper({"general": {"user": "admin"}}) 30 | assert loader(dumped)["general"]["user"] == "admin" 31 | 32 | dumped = dumper({"general": {"user": "admin"}, "otherroot": 1}) 33 | assert loader(dumped)["virtualroot"]["general"]["user"] == "admin" 34 | 35 | 36 | if __name__ == "__main__": 37 | main(module="test_xml") 38 | -------------------------------------------------------------------------------- /tests/test_yaml.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase, main 2 | 3 | from wildq.filetypes.yaml_type import loader, dumper, colorizer 4 | 5 | 6 | class TestFiletypeYAML(TestCase): 7 | def setUp(self): 8 | self.data = """ 9 | --- 10 | keys: 11 | - key1: value1 12 | - key2: value2 13 | - alone 14 | general: 15 | user: "admin" 16 | """ 17 | 18 | def test_loader(self): 19 | assert loader(self.data)["general"]["user"] == "admin" 20 | 21 | def test_dumper(self): 22 | dumped = dumper({"general": {"user": "admin"}}) 23 | assert loader(dumped)["general"]["user"] == "admin" 24 | 25 | 26 | if __name__ == "__main__": 27 | main(module="test_yaml") 28 | -------------------------------------------------------------------------------- /tests/tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Query with old format" 4 | ./artifacts/binaries/wildq --hcl . examples/hcl.hcl | ./artifacts/binaries/wildq -i json . 5 | ./artifacts/binaries/wildq --ini . examples/ini.ini | ./artifacts/binaries/wildq -i json . 6 | ./artifacts/binaries/wildq --json . examples/json.json | ./artifacts/binaries/wildq -i json . 7 | ./artifacts/binaries/wildq --toml . examples/toml.toml | ./artifacts/binaries/wildq -i json . 8 | ./artifacts/binaries/wildq --xml . examples/xml.xml | ./artifacts/binaries/wildq -i json . 9 | ./artifacts/binaries/wildq --yaml . examples/yaml.yaml | ./artifacts/binaries/wildq -i json . 10 | 11 | echo "Query with same in and out" 12 | ./artifacts/binaries/wildq -i hcl . examples/hcl.hcl 13 | ./artifacts/binaries/wildq -i ini . examples/ini.ini 14 | ./artifacts/binaries/wildq -i json . examples/json.json 15 | ./artifacts/binaries/wildq -i toml . examples/toml.toml 16 | ./artifacts/binaries/wildq -i xml . examples/xml.xml 17 | ./artifacts/binaries/wildq -i yaml . examples/yaml.yaml 18 | 19 | echo "Query with json out" 20 | ./artifacts/binaries/wildq -i hcl -o json . examples/hcl.hcl 21 | ./artifacts/binaries/wildq -i ini -o json . examples/ini.ini 22 | ./artifacts/binaries/wildq -i json -o json . examples/json.json 23 | ./artifacts/binaries/wildq -i toml -o json . examples/toml.toml 24 | ./artifacts/binaries/wildq -i xml -o json . examples/xml.xml 25 | ./artifacts/binaries/wildq -i yaml -o json . examples/yaml.yaml 26 | 27 | echo "Query with yaml out" 28 | ./artifacts/binaries/wildq -i hcl -o yaml . examples/hcl.hcl 29 | ./artifacts/binaries/wildq -i ini -o yaml . examples/ini.ini 30 | ./artifacts/binaries/wildq -i json -o yaml . examples/json.json 31 | ./artifacts/binaries/wildq -i toml -o yaml . examples/toml.toml 32 | ./artifacts/binaries/wildq -i xml -o yaml . examples/xml.xml 33 | ./artifacts/binaries/wildq -i yaml -o yaml . examples/yaml.yaml 34 | -------------------------------------------------------------------------------- /wildq/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ahmet2mir/wildq/c6e9535829cf6b4d0c2df2de5f8938d249602d08/wildq/__init__.py -------------------------------------------------------------------------------- /wildq/__main__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | import sys 4 | from wildq.cli import cli 5 | 6 | 7 | def main(): 8 | return cli() 9 | 10 | 11 | if __name__ == "__main__": 12 | sys.exit(cli()) 13 | -------------------------------------------------------------------------------- /wildq/_wildq_version.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.0" # managed by poetry-dynamic-versioning 2 | -------------------------------------------------------------------------------- /wildq/cli.py: -------------------------------------------------------------------------------- 1 | # standard 2 | import sys 3 | 4 | # third 5 | import jq 6 | import click 7 | 8 | # local 9 | import wildq.filetypes 10 | from wildq._wildq_version import __version__ 11 | 12 | 13 | class Config: 14 | pass 15 | 16 | 17 | # could be replaced by importlib / getattr but explicit is better than implicit 18 | SUPPORTED_FILETYPES = { 19 | "hcl": wildq.filetypes.hcl_type, 20 | "ini": wildq.filetypes.ini_type, 21 | "json": wildq.filetypes.json_type, 22 | "toml": wildq.filetypes.toml_type, 23 | "xml": wildq.filetypes.xml_type, 24 | "yaml": wildq.filetypes.yaml_type, 25 | } 26 | 27 | PASS_CONFIG = click.make_pass_decorator(Config, ensure=True) 28 | 29 | 30 | def compiler(jq_filter, data): 31 | return jq.compile(jq_filter).input(data) 32 | 33 | 34 | @click.command() 35 | # @click.option('--input', help='compose file to work with', type=click.File('r'), default=sys.stdin) 36 | # @click.option('--output', help='compose file to work with', type=click.File('r'), default=sys.stdin) 37 | @click.option( 38 | "-c", 39 | "--compact-output", 40 | is_flag=True, 41 | default=False, 42 | help="compact instead of pretty-printed output", 43 | ) 44 | @click.option( 45 | "-r", 46 | "--raw", 47 | is_flag=True, 48 | default=False, 49 | help="output raw strings, not content texts", 50 | ) 51 | @click.option( 52 | "-C", 53 | "--color-output", 54 | is_flag=True, 55 | default=False, 56 | help="colorize content (default), mutally exclusive with --monochrome-output", 57 | ) 58 | @click.option( 59 | "-M", 60 | "--monochrome-output", 61 | is_flag=True, 62 | default=False, 63 | help="monochrome (don't colorize content), mutally exclusive with --color-output", 64 | ) 65 | # @click.option('-S', '--sort', is_flag=True, default=False, help="sort keys of objects on output") 66 | @click.option( 67 | "--hcl", 68 | is_flag=True, 69 | default=False, 70 | help="Combine --input hcl --output json, mutally exclusive with other Combined options", 71 | ) 72 | @click.option( 73 | "--ini", 74 | is_flag=True, 75 | default=False, 76 | help="Combine --input ini --output json, mutally exclusive with other Combined options", 77 | ) 78 | @click.option( 79 | "--json", 80 | is_flag=True, 81 | default=False, 82 | help="Combine --input json --output json, mutally exclusive with other Combined options", 83 | ) 84 | @click.option( 85 | "--toml", 86 | is_flag=True, 87 | default=False, 88 | help="Combine --input toml --output json, mutally exclusive with other Combined options", 89 | ) 90 | @click.option( 91 | "--xml", 92 | is_flag=True, 93 | default=False, 94 | help="Combine --input xml --output json, mutally exclusive with other Combined options", 95 | ) 96 | @click.option( 97 | "--yaml", 98 | is_flag=True, 99 | default=False, 100 | help="Combine --input yaml --output json, mutally exclusive with other Combined options", 101 | ) 102 | @click.option( 103 | "-i", 104 | "--input", 105 | type=click.Choice(list(SUPPORTED_FILETYPES.keys())), 106 | help="Define the content type of file, mutally exclusive with Combined option", 107 | ) 108 | @click.option( 109 | "-o", 110 | "--output", 111 | type=click.Choice(list(SUPPORTED_FILETYPES.keys())), 112 | default=None, 113 | show_default=False, 114 | help="Define the content type of printed output, mutally exclusive with Combined option (default input format)", 115 | ) 116 | @click.argument("jq_filter") 117 | @click.argument("file", type=click.File("r"), default=sys.stdin) 118 | @click.version_option(version=__version__) 119 | def cli(*args, **kwargs): 120 | from pprint import pprint 121 | 122 | if (kwargs["input"] or kwargs["output"]) and any( 123 | [True for x in list(SUPPORTED_FILETYPES.keys()) if kwargs[x]] 124 | ): 125 | print( 126 | "When using combined option you can't use --input or --output, please use them explictly" 127 | ) 128 | sys.exit(1) 129 | 130 | if kwargs["color_output"] and kwargs["monochrome_output"]: 131 | print( 132 | "--color-output and --monochrome-output are mutally exclusive, select one" 133 | ) 134 | sys.exit(1) 135 | 136 | colorized = False 137 | if not kwargs["color_output"] and not kwargs["monochrome_output"]: 138 | colorized = True 139 | 140 | if kwargs["color_output"]: 141 | colorized = True 142 | 143 | if kwargs["monochrome_output"]: 144 | colorized = False 145 | 146 | input_fmt = None 147 | output_fmt = None 148 | 149 | raw = kwargs["raw"] 150 | 151 | # backward compatibility, if a type is specified without -i, output to json 152 | # enforce colorize to false and raw to true like first release of wq 153 | for spt in list(SUPPORTED_FILETYPES.keys()): 154 | if kwargs[spt]: 155 | input_fmt = spt 156 | output_fmt = "json" 157 | colorized = False 158 | raw = True 159 | 160 | # user specified input otherwise raise 161 | if not input_fmt: 162 | input_fmt = kwargs["input"] 163 | 164 | # if user specify input but not output, use default input format 165 | if not output_fmt: 166 | if kwargs.get("output") is None: 167 | output_fmt = input_fmt 168 | else: 169 | output_fmt = kwargs["output"] 170 | 171 | if not input_fmt or not output_fmt: 172 | if input_fmt is None: 173 | print("input option is empty") 174 | if output_fmt is None: 175 | print("output option is empty") 176 | print( 177 | "Issue when resolving input and output, getting confiuration %s", 178 | str(kwargs), 179 | ) 180 | sys.exit(1) 181 | 182 | module_in = SUPPORTED_FILETYPES[input_fmt] 183 | module_out = SUPPORTED_FILETYPES[output_fmt] 184 | 185 | content = module_in.loader(kwargs["file"].read()) 186 | 187 | # skip silently if content is empty 188 | if not content: 189 | return 0 190 | 191 | compiled = compiler(kwargs["jq_filter"], content) 192 | 193 | for line in compiled: 194 | if not isinstance(line, dict) and not isinstance(line, list): 195 | if raw and not line is None: 196 | print(line.strip('"')) 197 | else: 198 | print(line) 199 | continue 200 | 201 | dumped = module_out.dumper(line) 202 | 203 | if colorized: 204 | print(module_out.colorizer(dumped)) 205 | else: 206 | print(dumped) 207 | -------------------------------------------------------------------------------- /wildq/filetypes/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from wildq.filetypes import hcl_type 3 | from wildq.filetypes import ini_type 4 | from wildq.filetypes import json_type 5 | from wildq.filetypes import toml_type 6 | from wildq.filetypes import xml_type 7 | from wildq.filetypes import yaml_type 8 | 9 | # Auto Doc 10 | for ft in [hcl_type, ini_type, json_type, toml_type, xml_type, yaml_type]: 11 | ft.loader.__doc__ = f"""Pass data as string to {ft.FILETYPE_NAME} loader. 12 | 13 | Args: 14 | data_string (str): String content to load, usually a file content. 15 | 16 | Returns: 17 | Loaded content. Return type depends on content format, 18 | should be dict, list, string etc. 19 | 20 | Examples: 21 | >>> from wildq.filetypes import {ft.FILETYPE_NAME.lower()}_type 22 | >>> with open("examples/{ft.FILETYPE_NAME.lower()}.{ft.FILETYPE_NAME.lower()}", "r") as fd: 23 | ... data_string = fd.read() 24 | >>> data = {ft.FILETYPE_NAME.lower()}_type.loader(data_string) 25 | {ft.FILETYPE_EXAMPLE_LOADER} 26 | """ 27 | 28 | ft.dumper.__doc__ = f"""Pass loaded data to {ft.FILETYPE_NAME} dumper. 29 | 30 | Args: 31 | data: Should be dict, list, string etc. 32 | 33 | Returns: 34 | str: Dumped data. 35 | 36 | Examples: 37 | >>> from wildq.filetypes import {ft.FILETYPE_NAME.lower()}_type 38 | >>> data = {ft.FILETYPE_NAME.lower()}_type.dumper(data_string) 39 | {ft.FILETYPE_EXAMPLE_DUMPER} 40 | """ 41 | 42 | ft.colorizer.__doc__ = f"""Pass dumped data to {ft.FILETYPE_NAME} colorize. 43 | 44 | Args: 45 | content (str): string representation of data, usually a dumped data. 46 | 47 | Returns: 48 | str: Colorized data. 49 | 50 | Examples: 51 | >>> from wildq.filetypes import {ft.FILETYPE_NAME.lower()}_type 52 | >>> data = {ft.FILETYPE_NAME.lower()}_type.colorizer(data_string) 53 | ... 54 | """ 55 | -------------------------------------------------------------------------------- /wildq/filetypes/hcl_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """HCL type""" 3 | 4 | # standard 5 | import json 6 | from collections import OrderedDict 7 | 8 | # third 9 | import hcl 10 | from pygments import highlight, lexers, formatters 11 | 12 | FILETYPE_NAME = "HCL" 13 | FILETYPE_EXAMPLE_LOADER = """{ 14 | 'general': { 15 | 'user': 'admin' 16 | }, 17 | 'keys': [ 18 | {'key': 'value1'}, 19 | {'key': 'value2'} 20 | ] 21 | } 22 | """ 23 | FILETYPE_EXAMPLE_DUMPER = """general { 24 | user = "admin" 25 | } 26 | keys { 27 | key = "value1" 28 | } 29 | keys { 30 | key = "value2" 31 | } 32 | """ 33 | 34 | 35 | def loader(data_string): 36 | return hcl.loads(data_string) 37 | 38 | 39 | def dumper(data): 40 | return json.dumps(data, indent=4) 41 | 42 | 43 | def colorizer(content): 44 | # dump to hcl is not supported, so fallback to json 45 | return highlight( 46 | content, 47 | lexers.JsonLexer(), # lexers.TerraformLexer() 48 | formatters.TerminalFormatter(), 49 | ) 50 | -------------------------------------------------------------------------------- /wildq/filetypes/ini_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """INI type""" 3 | 4 | # standard 5 | import io 6 | import sys 7 | import configparser 8 | from collections import OrderedDict 9 | 10 | # third 11 | from pygments import highlight, lexers, formatters 12 | 13 | FILETYPE_NAME = "INI" 14 | FILETYPE_EXAMPLE_LOADER = """OrderedDict([ 15 | ('general', OrderedDict([ 16 | ('user', 'admin') 17 | ])), 18 | ('keys', OrderedDict([ 19 | ('key1', 'value1'), 20 | ('key2', 'value2') 21 | ])) 22 | ]) 23 | """ 24 | FILETYPE_EXAMPLE_DUMPER = """[general] 25 | user = admin 26 | [keys] 27 | key1 = value1 28 | key2 = value2 29 | """ 30 | 31 | 32 | def loader(data_string): 33 | config = configparser.ConfigParser() 34 | config.read_string(data_string) 35 | return config._sections 36 | 37 | 38 | def dumper(data): 39 | parser = configparser.ConfigParser() 40 | parser.read_dict(data) 41 | 42 | buf = io.StringIO() 43 | parser.write(buf) 44 | 45 | return buf.getvalue() 46 | 47 | 48 | def colorizer(content): 49 | return highlight(content, lexers.IniLexer(), formatters.TerminalFormatter()) 50 | -------------------------------------------------------------------------------- /wildq/filetypes/json_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """JSON type""" 3 | 4 | # standard 5 | import json 6 | from collections import OrderedDict 7 | 8 | # third 9 | from pygments import highlight, lexers, formatters 10 | 11 | FILETYPE_NAME = "JSON" 12 | FILETYPE_EXAMPLE_LOADER = """{ 13 | 'general': { 14 | 'user': 'admin' 15 | }, 16 | 'keys': [ 17 | {'key': 'value1'}, 18 | {'key': 'value2'}, 19 | 'alone' 20 | ] 21 | } 22 | """ 23 | FILETYPE_EXAMPLE_DUMPER = """{ 24 | "general": { 25 | "user": "admin" 26 | }, 27 | "keys": [ 28 | {"key": "value1"}, 29 | {"key": "value2"}, 30 | "alone" 31 | ] 32 | } 33 | """ 34 | 35 | 36 | def loader(data_string): 37 | return json.loads(data_string) 38 | 39 | 40 | def dumper(data): 41 | return json.dumps(data, indent=4) 42 | 43 | 44 | def colorizer(content): 45 | return highlight( 46 | content, lexers.JsonLexer(), formatters.TerminalFormatter() 47 | ) 48 | -------------------------------------------------------------------------------- /wildq/filetypes/toml_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """TOML type""" 3 | 4 | # standard 5 | from collections import OrderedDict 6 | 7 | # third 8 | import toml 9 | from pygments import highlight, lexers, formatters 10 | 11 | FILETYPE_NAME = "TOML" 12 | FILETYPE_EXAMPLE_LOADER = """{ 13 | 'general': { 14 | 'user': 'admin' 15 | }, 16 | 'keys': [ 17 | {'key': 'value1'}, 18 | {'key': 'value2'} 19 | ] 20 | } 21 | """ 22 | FILETYPE_EXAMPLE_DUMPER = """# keys = [ "alone" ] # produce an error on dump only 23 | [[keys]] 24 | key = "value1" 25 | [[keys]] 26 | key = "value2" 27 | [general] 28 | user = "admin" 29 | """ 30 | 31 | 32 | def loader(data_string): 33 | return toml.loads(data_string) 34 | 35 | 36 | def dumper(data): 37 | return toml.dumps(data) 38 | 39 | 40 | def colorizer(content): 41 | return highlight( 42 | content, lexers.TOMLLexer(), formatters.TerminalFormatter() 43 | ) 44 | -------------------------------------------------------------------------------- /wildq/filetypes/xml_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """XML type""" 3 | 4 | import json 5 | from collections import OrderedDict 6 | 7 | import xmltodict 8 | from pygments import highlight, lexers, formatters 9 | 10 | FILETYPE_NAME = "XML" 11 | FILETYPE_EXAMPLE_LOADER = """OrderedDict([ 12 | ('root', OrderedDict([ 13 | ('general', OrderedDict([ 14 | ('user', 'admin') 15 | ])), 16 | ('keys', OrderedDict([ 17 | ('element', [ 18 | OrderedDict([('key', 'value1')]), 19 | OrderedDict([('key', 'value2')]), 20 | 'alone' 21 | ]) 22 | ])) 23 | ])) 24 | ]) 25 | """ 26 | FILETYPE_EXAMPLE_DUMPER = """ 27 | 28 | 29 | admin 30 | 31 | 32 | 33 | value1 34 | 35 | 36 | value2 37 | 38 | alone 39 | 40 | 41 | """ 42 | 43 | 44 | # local 45 | 46 | 47 | def loader(data_string): 48 | return xmltodict.parse(data_string) 49 | 50 | 51 | def dumper(data): 52 | if isinstance(data, dict) and len(data.keys()) == 1: 53 | return xmltodict.unparse(data, pretty=True, indent=" ") 54 | else: 55 | return xmltodict.unparse( 56 | {"virtualroot": data}, pretty=True, indent=" " 57 | ) 58 | 59 | 60 | def colorizer(content): 61 | return highlight(content, lexers.XmlLexer(), formatters.TerminalFormatter()) 62 | -------------------------------------------------------------------------------- /wildq/filetypes/yaml_type.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | """YAML type""" 3 | 4 | # standard 5 | from collections import OrderedDict 6 | 7 | # third 8 | import yaml 9 | from pygments import highlight, lexers, formatters 10 | 11 | FILETYPE_NAME = "YAML" 12 | FILETYPE_EXAMPLE_LOADER = """{ 13 | 'general': { 14 | 'user': 'admin' 15 | }, 16 | 'keys': [ 17 | {'key': 'value1'}, 18 | {'key': 'value2'}, 19 | 'alone' 20 | ] 21 | } 22 | """ 23 | FILETYPE_EXAMPLE_DUMPER = """general: 24 | user: "admin" 25 | keys: 26 | - key1: value1 27 | - key2: value2 28 | - alone 29 | """ 30 | 31 | 32 | def loader(data_string): 33 | return yaml.safe_load(data_string) 34 | 35 | 36 | def dumper(data): 37 | # Dump YAML thanks to https://github.com/dale3h/python-lovelace. 38 | def ordered_dump(content, stream=None, Dumper=yaml.Dumper, **kwargs): 39 | """YAML dumper for OrderedDict.""" 40 | 41 | class OrderedDumper(Dumper): 42 | """Wrapper class for YAML dumper.""" 43 | 44 | def ignore_aliases(self, content): 45 | """Disable aliases in YAML dump.""" 46 | return True 47 | 48 | def increase_indent(self, flow=False, indentless=False): 49 | """Increase indent on YAML lists.""" 50 | return super(OrderedDumper, self).increase_indent(flow, False) 51 | 52 | def _dict_representer(dumper, content): 53 | """Function to represent OrderDict and derivitives.""" 54 | return dumper.represent_mapping( 55 | yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, content.items() 56 | ) 57 | 58 | OrderedDumper.add_multi_representer(OrderedDict, _dict_representer) 59 | 60 | OrderedDumper.add_representer( 61 | str, yaml.representer.SafeRepresenter.represent_str 62 | ) 63 | 64 | return yaml.dump(content, stream, OrderedDumper, **kwargs) 65 | 66 | return ordered_dump( 67 | content=data, Dumper=yaml.SafeDumper, default_flow_style=False 68 | ) 69 | 70 | 71 | def colorizer(content): 72 | return highlight( 73 | content, lexers.YamlLexer(), formatters.TerminalFormatter() 74 | ) 75 | --------------------------------------------------------------------------------