├── .gitignore ├── LICENSE ├── README.md ├── poetry.lock ├── pycatj ├── __init__.py ├── cmd.py └── pycatj.py ├── pyproject.toml ├── setup.cfg └── tests └── data ├── test_1.json └── test_1.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /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 [yyyy] [name of copyright owner] 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pycatj 2 | 3 | Flattens json/yaml files into python compatible paths 4 | 5 | ## Installation 6 | 7 | ``` 8 | pip install git+https://github.com/dbarrosop/pycatj.git 9 | ``` 10 | 11 | ## Usage 12 | 13 | ``` 14 | $ pycatj -h 15 | usage: pycatj [-h] [--format {json,yaml}] filepath 16 | 17 | Displays JSON files in a flat format (inspired by mattleibow/catj) 18 | 19 | positional arguments: 20 | filepath File to process 21 | 22 | optional arguments: 23 | -h, --help show this help message and exit 24 | --format {json,yaml} Format of the file 25 | --root ROOT This is the root of your path, the var where you will 26 | load your data 27 | 28 | $ cat tests/data/test_1.json 29 | { 30 | "somekey": "somevalue", 31 | "somenumber": 123, 32 | "a_dict": { 33 | "asd": "123", 34 | "qwe": [1, 2, 3], 35 | "nested_dict": { 36 | "das": 31, 37 | "qwe": "asd" 38 | } 39 | } 40 | } 41 | 42 | $ pycatj --root my_var tests/data/test_1.json 43 | my_var["somekey"] = "somevalue" 44 | my_var["somenumber"] = 123 45 | my_var["a_dict"]["asd"] = "123" 46 | my_var["a_dict"]["qwe"][0] = 1 47 | my_var["a_dict"]["qwe"][1] = 2 48 | my_var["a_dict"]["qwe"][2] = 3 49 | my_var["a_dict"]["nested_dict"]["das"] = 31 50 | my_var["a_dict"]["nested_dict"]["qwe"] = "asd" 51 | 52 | $ cat tests/data/test_1.yaml 53 | --- 54 | "somekey": "somevalue" 55 | "somenumber": 123 56 | "a_dict": 57 | "asd": "123" 58 | "qwe": 59 | - 1 60 | - 2 61 | - 3 62 | "nested_dict": 63 | "das": 31 64 | "qwe": "asd" 65 | 66 | $ pycatj --root my_var tests/data/test_1.yaml 67 | my_var["somekey"] = "somevalue" 68 | my_var["somenumber"] = 123 69 | my_var["a_dict"]["asd"] = "123" 70 | my_var["a_dict"]["qwe"][0] = 1 71 | my_var["a_dict"]["qwe"][1] = 2 72 | my_var["a_dict"]["qwe"][2] = 3 73 | my_var["a_dict"]["nested_dict"]["das"] = 31 74 | my_var["a_dict"]["nested_dict"]["qwe"] = "asd" 75 | ``` 76 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | category = "dev" 3 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 4 | name = "appdirs" 5 | optional = false 6 | python-versions = "*" 7 | version = "1.4.3" 8 | 9 | [[package]] 10 | category = "dev" 11 | description = "Atomic file writes." 12 | name = "atomicwrites" 13 | optional = false 14 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 15 | version = "1.3.0" 16 | 17 | [[package]] 18 | category = "dev" 19 | description = "Classes Without Boilerplate" 20 | name = "attrs" 21 | optional = false 22 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 23 | version = "19.1.0" 24 | 25 | [[package]] 26 | category = "dev" 27 | description = "The uncompromising code formatter." 28 | name = "black" 29 | optional = false 30 | python-versions = ">=3.6" 31 | version = "19.3b0" 32 | 33 | [package.dependencies] 34 | appdirs = "*" 35 | attrs = ">=18.1.0" 36 | click = ">=6.5" 37 | toml = ">=0.9.4" 38 | 39 | [[package]] 40 | category = "dev" 41 | description = "Composable command line interface toolkit" 42 | name = "click" 43 | optional = false 44 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 45 | version = "7.0" 46 | 47 | [[package]] 48 | category = "dev" 49 | description = "Cross-platform colored terminal text." 50 | marker = "sys_platform == \"win32\"" 51 | name = "colorama" 52 | optional = false 53 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 54 | version = "0.4.1" 55 | 56 | [[package]] 57 | category = "dev" 58 | description = "Code coverage measurement for Python" 59 | name = "coverage" 60 | optional = false 61 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" 62 | version = "4.5.3" 63 | 64 | [[package]] 65 | category = "dev" 66 | description = "Flake8 and pylama plugin that checks the ordering of import statements." 67 | name = "flake8-import-order" 68 | optional = false 69 | python-versions = "*" 70 | version = "0.18.1" 71 | 72 | [package.dependencies] 73 | pycodestyle = "*" 74 | setuptools = "*" 75 | 76 | [[package]] 77 | category = "dev" 78 | description = "Read metadata from Python packages" 79 | name = "importlib-metadata" 80 | optional = false 81 | python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3" 82 | version = "0.18" 83 | 84 | [package.dependencies] 85 | zipp = ">=0.5" 86 | 87 | [[package]] 88 | category = "dev" 89 | description = "McCabe checker, plugin for flake8" 90 | name = "mccabe" 91 | optional = false 92 | python-versions = "*" 93 | version = "0.6.1" 94 | 95 | [[package]] 96 | category = "dev" 97 | description = "More routines for operating on iterables, beyond itertools" 98 | marker = "python_version > \"2.7\"" 99 | name = "more-itertools" 100 | optional = false 101 | python-versions = ">=3.4" 102 | version = "7.0.0" 103 | 104 | [[package]] 105 | category = "dev" 106 | description = "Optional static typing for Python" 107 | name = "mypy" 108 | optional = false 109 | python-versions = "*" 110 | version = "0.711" 111 | 112 | [package.dependencies] 113 | mypy-extensions = ">=0.4.0,<0.5.0" 114 | typed-ast = ">=1.4.0,<1.5.0" 115 | 116 | [[package]] 117 | category = "dev" 118 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 119 | name = "mypy-extensions" 120 | optional = false 121 | python-versions = "*" 122 | version = "0.4.1" 123 | 124 | [[package]] 125 | category = "dev" 126 | description = "Core utilities for Python packages" 127 | name = "packaging" 128 | optional = false 129 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 130 | version = "19.0" 131 | 132 | [package.dependencies] 133 | pyparsing = ">=2.0.2" 134 | six = "*" 135 | 136 | [[package]] 137 | category = "dev" 138 | description = "plugin and hook calling mechanisms for python" 139 | name = "pluggy" 140 | optional = false 141 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 142 | version = "0.12.0" 143 | 144 | [package.dependencies] 145 | importlib-metadata = ">=0.12" 146 | 147 | [[package]] 148 | category = "dev" 149 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 150 | name = "py" 151 | optional = false 152 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 153 | version = "1.8.0" 154 | 155 | [[package]] 156 | category = "dev" 157 | description = "Python style guide checker" 158 | name = "pycodestyle" 159 | optional = false 160 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 161 | version = "2.5.0" 162 | 163 | [[package]] 164 | category = "dev" 165 | description = "Python docstring style checker" 166 | name = "pydocstyle" 167 | optional = false 168 | python-versions = "*" 169 | version = "3.0.0" 170 | 171 | [package.dependencies] 172 | six = "*" 173 | snowballstemmer = "*" 174 | 175 | [[package]] 176 | category = "dev" 177 | description = "passive checker of Python programs" 178 | name = "pyflakes" 179 | optional = false 180 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 181 | version = "2.1.1" 182 | 183 | [[package]] 184 | category = "dev" 185 | description = "pylama -- Code audit tool for python" 186 | name = "pylama" 187 | optional = false 188 | python-versions = "*" 189 | version = "7.7.1" 190 | 191 | [package.dependencies] 192 | mccabe = ">=0.5.2" 193 | pycodestyle = ">=2.3.1" 194 | pydocstyle = ">=2.0.0" 195 | pyflakes = ">=1.5.0" 196 | 197 | [[package]] 198 | category = "dev" 199 | description = "Python parsing module" 200 | name = "pyparsing" 201 | optional = false 202 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 203 | version = "2.4.0" 204 | 205 | [[package]] 206 | category = "dev" 207 | description = "pytest: simple powerful testing with Python" 208 | name = "pytest" 209 | optional = false 210 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 211 | version = "4.6.3" 212 | 213 | [package.dependencies] 214 | atomicwrites = ">=1.0" 215 | attrs = ">=17.4.0" 216 | colorama = "*" 217 | importlib-metadata = ">=0.12" 218 | packaging = "*" 219 | pluggy = ">=0.12,<1.0" 220 | py = ">=1.5.0" 221 | six = ">=1.10.0" 222 | wcwidth = "*" 223 | 224 | [package.dependencies.more-itertools] 225 | python = ">=2.8" 226 | version = ">=4.0.0" 227 | 228 | [[package]] 229 | category = "dev" 230 | description = "Pytest plugin for measuring coverage." 231 | name = "pytest-cov" 232 | optional = false 233 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 234 | version = "2.7.1" 235 | 236 | [package.dependencies] 237 | coverage = ">=4.4" 238 | pytest = ">=3.6" 239 | 240 | [[package]] 241 | category = "main" 242 | description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" 243 | name = "ruamel.yaml" 244 | optional = false 245 | python-versions = "*" 246 | version = "0.15.97" 247 | 248 | [[package]] 249 | category = "dev" 250 | description = "Python 2 and 3 compatibility utilities" 251 | name = "six" 252 | optional = false 253 | python-versions = ">=2.6, !=3.0.*, !=3.1.*" 254 | version = "1.12.0" 255 | 256 | [[package]] 257 | category = "dev" 258 | description = "This package provides 16 stemmer algorithms (15 + Poerter English stemmer) generated from Snowball algorithms." 259 | name = "snowballstemmer" 260 | optional = false 261 | python-versions = "*" 262 | version = "1.2.1" 263 | 264 | [[package]] 265 | category = "dev" 266 | description = "Python Library for Tom's Obvious, Minimal Language" 267 | name = "toml" 268 | optional = false 269 | python-versions = "*" 270 | version = "0.10.0" 271 | 272 | [[package]] 273 | category = "dev" 274 | description = "a fork of Python 2 and 3 ast modules with type comment support" 275 | name = "typed-ast" 276 | optional = false 277 | python-versions = "*" 278 | version = "1.4.0" 279 | 280 | [[package]] 281 | category = "dev" 282 | description = "Measures number of Terminal column cells of wide-character codes" 283 | name = "wcwidth" 284 | optional = false 285 | python-versions = "*" 286 | version = "0.1.7" 287 | 288 | [[package]] 289 | category = "dev" 290 | description = "Backport of pathlib-compatible object wrapper for zip files" 291 | name = "zipp" 292 | optional = false 293 | python-versions = ">=2.7" 294 | version = "0.5.1" 295 | 296 | [metadata] 297 | content-hash = "7693919e8deec02f00423aa7a7dbe7a24f4422de6fe0a451e5466a4d3d675956" 298 | python-versions = "^3.6" 299 | 300 | [metadata.hashes] 301 | appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"] 302 | atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"] 303 | attrs = ["69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", "f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"] 304 | black = ["09a9dcb7c46ed496a9850b76e4e825d6049ecd38b611f1224857a79bd985a8cf", "68950ffd4d9169716bcb8719a56c07a2f4485354fec061cdd5910aa07369731c"] 305 | click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] 306 | colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"] 307 | coverage = ["0c5fe441b9cfdab64719f24e9684502a59432df7570521563d7b1aff27ac755f", "2b412abc4c7d6e019ce7c27cbc229783035eef6d5401695dccba80f481be4eb3", "3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", "39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", "3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", "42692db854d13c6c5e9541b6ffe0fe921fe16c9c446358d642ccae1462582d3b", "465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", "48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", "4ec30ade438d1711562f3786bea33a9da6107414aed60a5daa974d50a8c2c351", "5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", "5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", "6899797ac384b239ce1926f3cb86ffc19996f6fa3a1efbb23cb49e0c12d8c18c", "68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", "6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", "7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", "7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", "839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", "8e679d1bde5e2de4a909efb071f14b472a678b788904440779d2c449c0355b27", "8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", "932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", "93f965415cc51604f571e491f280cff0f5be35895b4eb5e55b47ae90c02a497b", "988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", "998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", "9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", "9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", "a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", "a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", "a9abc8c480e103dc05d9b332c6cc9fb1586330356fc14f1aa9c0ca5745097d19", "aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", "bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", "bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", "c22ab9f96cbaff05c6a84e20ec856383d27eae09e511d3e6ac4479489195861d", "c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", "c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", "c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", "ca58eba39c68010d7e87a823f22a081b5290e3e3c64714aac3c91481d8b34d22", "df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", "f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", "f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", "f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", "fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"] 308 | flake8-import-order = ["90a80e46886259b9c396b578d75c749801a41ee969a235e163cfe1be7afd2543", "a28dc39545ea4606c1ac3c24e9d05c849c6e5444a50fb7e9cdd430fc94de6e92"] 309 | importlib-metadata = ["6dfd58dfe281e8d240937776065dd3624ad5469c835248219bd16cf2e12dbeb7", "cb6ee23b46173539939964df59d3d72c3e0c1b5d54b84f1d8a7e912fe43612db"] 310 | mccabe = ["ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", "dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"] 311 | more-itertools = ["2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7", "c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"] 312 | mypy = ["12d18bd7fc642c5d54b1bb62dde813a7e2ab79b32ee11ff206ac387c68fc2ad4", "23e24bc1683a36f39dee67d8ac74ea414654642eee26d420bada95b8ee8c9095", "2b38e64c52a8968df4ebcae0ddba4a54eb94d184695dd4e54e14509a9389b78c", "3d4f551466a76e278187ec3a5b26cfb50f72f6760b749aa00ac69a6f9c99898d", "53d5dacb8d844e50be698830509aa592b093547e7ab90aee63eb23db61109007", "56f981d246010ba21cac6b2455eaecfaf68fc8a5663d865b26c8e579c36f751d", "8c57f6f59f1e8479d9fc6e1bf034353e54626ed64e32394c613afc493a441dc1", "bbed4a593d87476b592d52867ef86da2155ccd0becf0c4c02e6567d842e43368", "d6ff850e2ba18b2db7704897c8f2f1384478e3b75ad292ec06196bf7794f3a40", "e13b1bb8785d7f785e0b88873f1c21cda58ceba9ce1153b58cbfa24b09a111d5", "e2b9ee6f648ce72d6741925a47c88c2391168ef973b6f74f17969450c5b1ffdd"] 313 | mypy-extensions = ["37e0e956f41369209a3d5f34580150bcacfabaa57b33a15c0b25f4b5725e0812", "b16cabe759f55e3409a7d231ebd2841378fb0c27a5d1994719e340e4f429ac3e"] 314 | packaging = ["0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af", "9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"] 315 | pluggy = ["0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc", "b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c"] 316 | py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"] 317 | pycodestyle = ["95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56", "e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"] 318 | pydocstyle = ["2258f9b0df68b97bf3a6c29003edc5238ff8879f1efb6f1999988d934e432bd8", "5741c85e408f9e0ddf873611085e819b809fca90b619f5fd7f34bd4959da3dd4", "ed79d4ec5e92655eccc21eb0c6cf512e69512b4a97d215ace46d17e4990f2039"] 319 | pyflakes = ["17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0", "d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"] 320 | pylama = ["9bae53ef9c1a431371d6a8dca406816a60d547147b60a4934721898f553b7d8f", "fd61c11872d6256b019ef1235be37b77c922ef37ac9797df6bd489996dddeb15"] 321 | pyparsing = ["1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a", "9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"] 322 | pytest = ["4a784f1d4f2ef198fe9b7aef793e9fa1a3b2f84e822d9b3a64a181293a572d45", "926855726d8ae8371803f7b2e6ec0a69953d9c6311fa7c3b6c1b929ff92d27da"] 323 | pytest-cov = ["2b097cde81a302e1047331b48cadacf23577e431b61e9c6f49a1170bbe3d3da6", "e00ea4fdde970725482f1f35630d12f074e121a23801aabf2ae154ec6bdd343a"] 324 | "ruamel.yaml" = ["17dbf6b7362e7aee8494f7a0f5cffd44902a6331fe89ef0853b855a7930ab845", "23731c9efb79f3f5609dedffeb6c5c47a68125fd3d4b157d9fc71b1cd49076a9", "2bbdd598ae57bac20968cf9028cc67d37d83bdb7942a94b9478110bc72193148", "34586084cdd60845a3e1bece2b58f0a889be25450db8cc0ea143ddf0f40557a2", "35957fedbb287b01313bb5c556ffdc70c0277c3500213b5e73dfd8716f748d77", "414cb87a40974a575830b406ffab4ab8c6cbd82eeb73abd2a9d1397c1f0223e1", "428775be75db68d908b17e4e8dda424c410222f170dc173246aa63e972d094b3", "514f670f7d36519bda504d507edfe63e3c20489f86c86d42bc4d9a6dbdf82c7b", "5cb962c1ac6887c5da29138fbbe3b4b7705372eb54e599907fa63d4cd743246d", "5f6e30282cf70fb7754e1a5f101e27b5240009766376e131b31ab49f14fe81be", "86f8e010af6af0b4f42de2d0d9b19cb441e61d3416082186f9dd03c8552d13ad", "8d47ed1e557d546bd2dfe54f504d7274274602ff7a0652cde84c258ad6c2d96d", "98668876720bce1ac08562d8b93a564a80e3397e442c7ea19cebdcdf73da7f74", "9e1f0ddc18d8355dcf5586a5d90417df56074f237812b8682a93b62cca9d2043", "a7bc812a72a79d6b7dbb96fa5bee3950464b65ec055d3abc4db6572f2373a95c", "b72e13f9f206ee103247b07afd5a39c8b1aa98e8eba80ddba184d030337220ba", "bcff8ea9d916789e85e24beed8830c157fb8bc7c313e554733a8151540e66c01", "c76e78b3bab652069b8d6f7889b0e72f3455c2b854b2e0a8818393d149ad0a0d"] 325 | six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"] 326 | snowballstemmer = ["919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128", "9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"] 327 | toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] 328 | typed-ast = ["18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", "262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", "2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", "354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", "4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", "630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", "66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", "71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", "95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", "bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", "cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", "d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", "d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", "d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", "ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"] 329 | wcwidth = ["3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", "f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"] 330 | zipp = ["8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d", "ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3"] 331 | -------------------------------------------------------------------------------- /pycatj/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dbarrosop/pycatj/1edfc66a234844ec82be9a2bc96f388e1ab32982/pycatj/__init__.py -------------------------------------------------------------------------------- /pycatj/cmd.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import pathlib 3 | 4 | from pycatj import pycatj 5 | 6 | 7 | def main() -> None: 8 | parser = argparse.ArgumentParser( 9 | description="Displays JSON files in a flat format (inspired by mattleibow/catj)" 10 | ) 11 | parser.add_argument("filepath", type=str, help="File to process") 12 | parser.add_argument( 13 | "--format", 14 | dest="file_format", 15 | choices=["json", "yaml"], 16 | help="Format of the file", 17 | ) 18 | parser.add_argument( 19 | "--root", 20 | dest="root", 21 | default="root", 22 | help="This is the root of your path, the var where you will load your data", 23 | ) 24 | args = parser.parse_args() 25 | 26 | filepath = pathlib.Path(args.filepath) 27 | file_format = args.file_format 28 | if not file_format: 29 | file_format = filepath.suffix[1:] 30 | print(pycatj.process_file(filepath, file_format, args.root)) 31 | 32 | 33 | if __name__ == "__main__": 34 | main() 35 | -------------------------------------------------------------------------------- /pycatj/pycatj.py: -------------------------------------------------------------------------------- 1 | import io 2 | import json 3 | import pathlib 4 | from typing import Any, Dict, List, Union 5 | 6 | import ruamel.yaml 7 | 8 | 9 | def process_element( 10 | data: Union[bool, str, int], path: str, result: io.StringIO 11 | ) -> None: 12 | if isinstance(data, str): 13 | result.write(f'{path} = "{data}"\n') 14 | else: 15 | result.write(f"{path} = {data}\n") 16 | 17 | 18 | def process_list(data: List[Any], path: str, result: io.StringIO) -> None: 19 | for i, v in enumerate(data): 20 | new_path = f"{path}[{i}]" 21 | if isinstance(v, dict): 22 | process_dict(v, new_path, result) 23 | elif isinstance(v, list): 24 | process_list(v, new_path, result) 25 | else: 26 | process_element(v, new_path, result) 27 | 28 | 29 | def process_dict(data: Dict[str, Any], path: str, result: io.StringIO) -> None: 30 | for k, v in data.items(): 31 | new_path = f'{path}["{k}"]' 32 | if isinstance(v, dict): 33 | process_dict(v, new_path, result) 34 | elif isinstance(v, list): 35 | process_list(v, new_path, result) 36 | else: 37 | process_element(v, new_path, result) 38 | 39 | 40 | def process_file(filepath: pathlib.Path, mode: str, root: str) -> str: 41 | result = io.StringIO() 42 | 43 | if mode == "json": 44 | loader = json.load 45 | elif mode == "yaml": 46 | loader = ruamel.yaml.safe_load 47 | else: 48 | raise ValueError(f"don't know what format {mode} is. Supported: json, yaml") 49 | 50 | with open(filepath, "r") as f: 51 | data = loader(f) 52 | 53 | process_dict(data, root, result) 54 | return result.getvalue() 55 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "pycatj" 3 | version = "0.1.0" 4 | description = "Displays JSON and YAML files in a flat format (inspired by mattleibow/catj)" 5 | authors = ["David Barroso "] 6 | 7 | [tool.poetry.scripts] 8 | pycatj = 'pycatj.cmd:main' 9 | 10 | [tool.poetry.dependencies] 11 | python = "^3.6" 12 | "ruamel.yaml" = "^0.15.97" 13 | 14 | [tool.poetry.dev-dependencies] 15 | pytest = "*" 16 | pytest-cov = "*" 17 | pylama = "*" 18 | flake8-import-order = "*" 19 | black = {version = "^19.3b0",allows-prereleases = true} 20 | mypy = "*" 21 | 22 | [build-system] 23 | requires = ["poetry>=0.12"] 24 | build-backend = "poetry.masonry.api" 25 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [pylama] 2 | linters = mccabe,pep8,pyflakes,import_order 3 | ignore = D203,C901 4 | skip = .tox/*,.venv/* 5 | 6 | [pylama:pep8] 7 | max_line_length = 100 8 | 9 | [pycodestyle] 10 | ignore = D203,C901 11 | exclude = .git,__pycache__,build,dist 12 | max-complexity = 10 13 | max-line-length = 100 14 | 15 | [tool:pytest] 16 | #addopts = --cov=pycatj --cov-report=term-missing -vs 17 | python_paths = ./ 18 | 19 | [mypy] 20 | # The mypy configurations: http://bit.ly/2zEl9WI 21 | python_version = 3.6 22 | check_untyped_defs = True 23 | disallow_any_generics = True 24 | disallow_untyped_calls = True 25 | disallow_untyped_defs = True 26 | disallow_incomplete_defs = True 27 | disallow_untyped_decorators = True 28 | ignore_errors = False 29 | ignore_missing_imports = True 30 | strict_optional = True 31 | warn_unused_configs = True 32 | warn_unused_ignores = True 33 | warn_return_any = True 34 | warn_redundant_casts = True 35 | -------------------------------------------------------------------------------- /tests/data/test_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "somekey": "somevalue", 3 | "somenumber": 123, 4 | "a_dict": { 5 | "asd": "123", 6 | "qwe": [1, 2, 3], 7 | "nested_dict": { 8 | "das": 31, 9 | "qwe": "asd" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/data/test_1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | "somekey": "somevalue" 3 | "somenumber": 123 4 | "a_dict": 5 | "asd": "123" 6 | "qwe": 7 | - 1 8 | - 2 9 | - 3 10 | "nested_dict": 11 | "das": 31 12 | "qwe": "asd" 13 | --------------------------------------------------------------------------------