{ "info": { "author": "Taylor C. Richberger", "author_email": "", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Topic :: Utilities" ], "description": "pyjawk\n######\n\nPython-based stream editor for json files. It is a simple setup that\neffectively works as a json-parsing ``awk``, similar to jq, but allowing\nin-place editing and output of json documents as well, and using Python as the\nworking language. It supports colorized output.\n\n.. contents::\n\nMotivation\n----------\n\nThis program exists for fairly minor convenience, and mostly for my own use.\nWhenever I end up needing to quickly edit some json, I find myself opening a\nPython REPL, writing a bunch of obvious loading code to load in the json, work\non it a little bit, and then dump it back out to the relevant file. Also,\nwhenever I end up needing to inspect json from a web page, I either curl it to a\nfile and then do the same, or use requests or something to pull it directly in\na Python REPL so I can properly inspect it, or I pipe it through Python's\n``json.tool`` and ``less``.\n\nThis is meant to supplant those use cases entirely for my own uses. If you find\nit inconvenient to repeatedly undergo the busy work associated with working with\nor inspecting json data, and especially if you are most familiar and comfortable\nwith the stream-editing way of doing things or spending time in a REPL, this\ntool might make things a little more convenient for you. It is also useful for\ninspecting and converting between formats, such as between msgpack and json.\n\nWhy not jq?\n^^^^^^^^^^^\n\n`jq `_ is a really great tool for a lot of what\nyou would use this. I wrote this because jq doesn't provide the user with a\nREPL to mangle data, and because Python is a much more powerful and flexible\nlanguage for the modification process, especially if you want to access the\nfilesystem or other I/O.\n\njq is a powerful program with a lot of development, active maintenence,\nmaintainers, and its own filter language. If that's what you want, use that.\nIf you want a simple tool for loading json and working on it with python in\neither a stream or REPL fashion, this is probably a better fit.\n\nInstallation\n------------\n\n.. code-block:: shell\n\n pip3 install --user pyjawk\n\nNote that pyjawk is Python 3 only.\n\nUse\n---\n\nDisplay the help text with ``-h``.\n\nIn all evaluated python, ``data`` represents the parsed input data.\n\nThe program is passed an input string either through stdin or a ``-i`` argument,\nand an output through ``-o`` or stdout. ``-f`` arguments may pass in script\nfiles that are run first. The ``data`` object is then serialized and output.\n``-e`` arguments are similar to ``-f``, but run afterward and run as python\nsource text. ``-c`` may be used to enable compact output and may be specified\nmultiple times for some output formats. A positional parameter, if present, is\nevaluated as a python expression and used to replace the data object.\n\n``-I`` and ``-O`` may be used to set the input and output formats, respectively.\n\n``-n`` and ``-N`` disable input and output respectively.\n\nIf ``-r`` / ``--repl`` is specified, instead of writing output after processing,\nthe function to write to the output is registered in the environment as\n``write``, the arguments structure is registered as ``args``, and a ``ptpython``\nREPL is started up with the same environment.\n\nMultiple command line tools are available, but they all only set the default\ninput and output formats.\n\nFormats\n-------\n\n* ``json``\n\n * Available as the command line tool ``pyjawk``\n * Supports 3 levels of compactness.\n * Outputs trailing newline except on highest compaction.\n * Supports colorized output.\n\n* ``yaml``\n\n * Available as the command line tool ``pyyawk``\n * Supports 3 levels of compactness.\n * Outputs trailing newline\n * Supports colorized output.\n\n* ``xml``\n\n * Available as the command line tool ``pyxawk``\n * Parses into a ``xml.etree.ElementTree.Element`` object and dumps as xml\n text. Uses ``xml.etree.ElementTree.tostring`` to dump. and if uncompacted,\n uses ``xml.dom.minidom`` to prettify.\n * Supports 2 levels of compactness.\n * Outputs trailing newline\n * Supports colorized output.\n\n* ``python``\n\n * Available as the command line tool ``pypawk``\n * Uses ``eval`` to pull in objects, and either ``pprint`` or ``repr`` to dump,\n depending on compactness.\n * Supports 3 levels of compactness.\n * Outputs trailing newline.\n * Supports colorized output.\n\n* ``msgpack``\n\n * Available as the command line tool ``pymawk``\n\n* ``string``\n\n * Available as the command line tool ``pysawk``\n * Simply reads input into a string and outputs data as a string, using ``str``\n on it before dumping.\n * Outputs trailing newline except when compaction is requested.\n\n* ``bytes``\n\n * Available as the command line tool ``pybawk``\n * Simply reads input into bytes and outputs data as bytes.\n\nThe ``data`` object\n-------------------\n\nThe ``data`` object is much like the ones that are normally imported from the\nlibraries, except all dictionaries for ``json``, ``yaml``, and ``msgpack`` are\nsubstituted for a subclass of ``dict`` that maintains order and gives attribute\naccess to the dictionary storage. All of the following are equivalent:\n\n.. code-block:: python\n\n data[\"foo\"][\"bar\"][0][\"baz\"] = \"spam\"\n data.foo.bar[0].baz = \"spam\"\n data.foo.bar[0][\"baz\"] = \"spam\"\n data[\"foo\"][\"bar\"][0].baz = \"spam\"\n\nNote that constructing a ``dict`` explicitly will not automatically construct\nthis subclass. You can do that by importing ``pyjawk.attrdict.AttrDict``:\n\n.. code-block:: python\n\n data.foo = {\n \"bar\": [{\"baz\": \"spam\"}],\n }\n # This will not work.\n data.foo.bar[0].baz = \"alot\"\n\n # The dicts are still ordinary dicts, so this will work\n data.foo[\"bar\"][0][\"baz\"] = \"alot\"\n\n from pyjawk.attrdict import AttrDict as d\n\n data.foo = d(\n bar=[d(baz=\"spam\")],\n )\n # Now this will work\n data.foo.bar[0].baz = \"alot\"\n\nDetails on IO and arguments in the REPL\n---------------------------------------\n\nIn the REPL, the program's own argument namespace is available as ``args``.\nChanging some of them is obvious (such as ``args.output``, which is just a\nstring, or ``args.no_input`` which is just a boolean), and some others are\nperhaps non-obvious (``args.compact`` is an integer specifying the number of\ntimes it was present). Some of the arguments don't make any sense to work with\n(such as ``args.input`` and ``args.input_format``, because those are already\nfinished by the time the REPL starts up).\n\nThe REPL does not write the output by default. To write the output with the\nREPL, the ``write()`` function must be called explicitly.\n\nWhen you wish to use the REPL, stdin and stdout must be attached to a terminal.\nThis means that you need to be taking input from a file, not a pipe, and the\nprogram may not be piped to anything else. This is necessary because ptpython\nneeds stdin to be communicated with and stdout to communicate back to the user.\nIf you wish to pipe something into pyjawk for REPL use, you'll have to use a\nfifo, a temp file, or a process substitution as follows:\n\n.. code-block:: shell\n\n # With process redirection\n pyjawk -ri <(curl 'https://httpbin.org/get?foo=bar&spam=spam')\n\n # With a temp file\n curl 'https://httpbin.org/get?foo=bar&spam=spam' > curltemp.json\n pyjawk -ri curltemp.json\n\n # With a fifo\n mkfifo curl.fifo\n curl 'https://httpbin.org/get?foo=bar&spam=spam' > curl.fifo &\n pyjawk -ri curl.fifo\n\nIn every case, the data in the repl is:\n\n.. code-block:: python\n\n >>> from pprint import pprint\n >>> pprint(data)\n {'args': {'foo': 'bar', 'spam': 'spam'},\n 'headers': {'Accept': '*/*',\n 'Host': 'httpbin.org',\n 'User-Agent': 'curl/7.65.0'},\n 'origin': '73.169.51.67, 73.169.51.67',\n 'url': 'https://httpbin.org/get?foo=bar&spam=spam'}\n\nExamples\n--------\n\nDumping some data to past.ee\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo '{\"a\": \"1\", \"b\": null, \"c\": true, \"d\": false, \"e\": 7, \"f\": 8.5, \"g\": {\"h\": [1, 2, 3]}}' \\\n | pyjawk '{\"sections\": [{\"contents\": str(data)}]}' \\\n | curl -H 'Content-Type: application/json' -H 'X-Auth-Token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -XPOST --data-binary '@-' https://api.paste.ee/v1/pastes\n\n {\"id\":\"umXKr\",\"link\":\"https:\\/\\/paste.ee\\/p\\/umXKr\",\"success\":true}\n\nWith this, you can also do any arbitrary string data, and also extract the link\nfrom the output if you like:\n\n.. code-block:: shell\n\n $ echo this is some test data \\\n | pyjawk -Istring '{\"sections\": [{\"contents\": data}]}' \\\n | curl -H 'Content-Type: application/json' -H 'X-Auth-Token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' -XPOST --data-binary '@-' https://api.paste.ee/v1/pastes \\\n | pyjawk -Ostring 'data.link'\n\n https://paste.ee/p/iomJR\n\nConverting data between formats\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo '{\"foo\": \"bar\", \"baz\": [\"spam\", \"Spam\", {\"SPAM?\": \"SPAM!\"}]}' \\\n | pyjawk -Oyaml\n\n baz:\n - spam\n - Spam\n - SPAM?: SPAM!\n foo: bar\n\nSelecting a part of a data-structure with evals\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo '{\"foo\": \"bar\", \"baz\": [\"spam\", \"Spam\", {\"SPAM?\": \"SPAM!\"}]}' \\\n | pyjawk -c 'data.baz[2]'\n\n {\"SPAM?\": \"SPAM!\"}\n\nExtracting a value as a string\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo '{\"foo\": \"bar\", \"baz\": [\"spam\", \"Spam\", {\"SPAM?\": \"SPAM!\"}]}' \\\n | pyjawk -Ostring 'data.baz[1]'\n\n Spam\n\nEasily embedding string data from stdin into a json structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo 'this is a test string' \\\n | pyjawk -Istring -Ojson -c '{\"foo\": data}'\n\n {\"foo\": \"this is a test string\\n\"}\n\nRelocating an xml child\n^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ echo 'first' \\\n | pyxawk -e 'foo = list(data)[0]; bar = list(foo)[0]; baz = list(data)[1]; baz.append(bar); foo.remove(bar)'\n\n.. code-block:: xml\n\n \n \n \n \n first\n \n \n\nThe ``-e`` can also be specified separately:\n\n.. code-block:: shell\n\n $ echo 'first' \\\n | pyxawk -e 'foo = list(data)[0]' -e 'bar = list(foo)[0]' -e 'baz = list(data)[1]' -e 'baz.append(bar)' -e 'foo.remove(bar)'\n\nOr just as a script file:\n\n.. code-block:: shell\n\n $ echo 'first' \\\n | pyxawk -f relocate.py\n\n.. code-block:: python\n\n foo = list(data)[0]\n bar = list(foo)[0]\n baz = list(data)[1]\n baz.append(bar)\n foo.remove(bar)\n\nExploring a structure in a REPL\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. code-block:: shell\n\n $ pyjawk -i<(echo '{\"foo\": \"bar\", \"baz\": [\"spam\", \"Spam\", {\"SPAM?\": \"SPAM!\"}]}') -r\n\n.. code-block:: python\n\n >>> data\n {'foo': 'bar', 'baz': ['spam', 'Spam', {'SPAM?': 'SPAM!'}]}\n\n >>> write()\n {\n \"foo\": \"bar\",\n \"baz\": [\n \"spam\",\n \"Spam\",\n {\n \"SPAM?\": \"SPAM!\"\n }\n ]\n }\n\n >>> data = data.baz\n\n >>> write()\n [\n \"spam\",\n \"Spam\",\n {\n \"SPAM?\": \"SPAM!\"\n }\n ]\n\nFixing Retroarch Playlists\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIf you had an issue with the way that RetroArch generates its playlist files for\nthe Playstation (by default, it searches for .cue files, but not .bin), and\nhad something like this in /tmp/Roms/psx, all Sony PlayStation games::\n\n Alpha.bin\n Alpha.cue\n Bravo.bin\n Charlie.bin\n Delta.bin\n Delta.cue\n\nYou might end up with a playlist file like this:\n\n.. code-block:: json\n\n {\n \"version\": \"1.2\",\n \"default_core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"default_core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"label_display_mode\": 0,\n \"right_thumbnail_mode\": 0,\n \"left_thumbnail_mode\": 0,\n \"items\": [\n {\n \"path\": \"/tmp/Roms/psx/Alpha.cue\",\n \"label\": \"Alpha\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n },\n {\n \"path\": \"/tmp/Roms/psx/Delta.cue\",\n \"label\": \"Delta\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n }\n ]\n }\n\nIf you want the file to just have the bins, you can easily scan the directory\nfor these files and modify the json using this tool with this:\n\n.. code-block:: shell\n\n $ pyjawk -i 'Sony - PlayStation.lpl' -o 'Sony - PlayStation.lpl' -e 'from pathlib import Path' -e 'data.items = [{\"path\": str(path), \"label\": path.stem, \"core_path\": data.default_core_path, \"core_name\": data.default_core_name, \"crc32\": \"00000000|crc\", \"db_name\": \"Sony - PlayStation.lpl\"} for path in (Path(\"/tmp\") / \"Roms\" / \"psx\").iterdir() if path.suffix == \".bin\"]'\n\nMaking the output\n\n.. code-block:: json\n\n {\n \"version\": \"1.2\",\n \"default_core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"default_core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"label_display_mode\": 0,\n \"right_thumbnail_mode\": 0,\n \"left_thumbnail_mode\": 0,\n \"items\": [\n {\n \"path\": \"/tmp/Roms/psx/Delta.bin\",\n \"label\": \"Delta\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n },\n {\n \"path\": \"/tmp/Roms/psx/Charlie.bin\",\n \"label\": \"Charlie\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n },\n {\n \"path\": \"/tmp/Roms/psx/Bravo.bin\",\n \"label\": \"Bravo\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n },\n {\n \"path\": \"/tmp/Roms/psx/Alpha.bin\",\n \"label\": \"Alpha\",\n \"core_path\": \"/tmp/retroarch/cores/pcsx_rearmed_libretro.so\",\n \"core_name\": \"Sony - PlayStation (PCSX ReARMed)\",\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\"\n }\n ]\n }\n\nThat might look heavy up-front, but you can rewrite it as a script file with\nsimpler structure:\n\n.. code-block:: python\n\n from pathlib import Path\n\n data.items = []\n\n for path in (Path('/tmp') / 'Roms' / 'psx').iterdir():\n if path.suffix == '.bin':\n data.items.append({\n \"path\": str(path),\n \"label\": path.stem,\n \"core_path\": data.default_core_path,\n \"core_name\": data.default_core_name,\n \"crc32\": \"00000000|crc\",\n \"db_name\": \"Sony - PlayStation.lpl\",\n })\n\nand run it with pyjawk as so:\n\n.. code-block:: shell\n\n pyjawk -i 'Sony - PlayStation.lpl' -o 'Sony - PlayStation.lpl' -f script.py\n\nOr instead load it into a repl to work on it in real time with this:\n\n.. code-block:: shell\n\n pyjawk -i 'Sony - PlayStation.lpl' -o 'Sony - PlayStation.lpl' -r\n\n.. code-block:: python\n\n >>> from pathlib import Path\n\n >>> data.items = []\n\n >>> for path in (Path('/tmp') / 'Roms' / 'psx').iterdir():\n ... if path.suffix == '.bin':\n ... data.items.append({\n ... \"path\": str(path),\n ... \"label\": path.stem,\n ... \"core_path\": data.default_core_path,\n ... \"core_name\": data.default_core_name,\n ... \"crc32\": \"00000000|crc\",\n ... \"db_name\": \"Sony - PlayStation.lpl\",\n ... })\n\n >>> write()\n\n >>> exit()\n\nJust make sure you call ``write()`` in the repl, or nothing will be written.\n\nPlans\n-----\n\nI don't plan to add too much to this, as I want it to be useful but also as lean\nand manageable as it possibly can be. Things like HTTP input and output are\nbest left to other programs that can do it better, like curl, especially given\nthat this program can operate in a streamable fashion.\n\nThis program needs some regression tests set up.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://gitlab.com/Taywee/pyjawk", "keywords": "utility", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "pyjawk", "package_url": "https://pypi.org/project/pyjawk/", "platform": "", "project_url": "https://pypi.org/project/pyjawk/", "project_urls": { "Homepage": "https://gitlab.com/Taywee/pyjawk" }, "release_url": "https://pypi.org/project/pyjawk/1.2.0/", "requires_dist": [ "appdirs", "msgpack", "packaging", "ptpython", "pygments", "ruamel.yaml" ], "requires_python": "", "summary": "A Python-based stream editor for json documents", "version": "1.2.0" }, "last_serial": 5779285, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "cb20caf008e47e3576825633a150910b", "sha256": "62fc9650921890306bc8849eea720dcc7b69a472ab6c6be93e492d0eaa93908e" }, "downloads": -1, "filename": "pyjawk-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "cb20caf008e47e3576825633a150910b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 9761, "upload_time": "2019-08-29T19:12:36", "url": "https://files.pythonhosted.org/packages/18/9a/624c5420d4297db1ec1ec0ed2fe600339496b2be4496f7476dd13c3f4411/pyjawk-0.1.0-py3-none-any.whl" } ], "1.0.0": [ { "comment_text": "", "digests": { "md5": "286ef0d0178ca235c5176123a39d6265", "sha256": "3182fc2020bebdb3c765114d06380b8b4cdc32d2f3aa43a908190e6219af2451" }, "downloads": -1, "filename": "pyjawk-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "286ef0d0178ca235c5176123a39d6265", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13112, "upload_time": "2019-08-30T00:11:35", "url": "https://files.pythonhosted.org/packages/0d/13/ebcdf78760c1810ef311fed9ab434c302ff8afd2f61b045969f7441ac463/pyjawk-1.0.0-py3-none-any.whl" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "99e6adaf0da254872b5f9fac0dda2a93", "sha256": "84047e819f48689cadf85439d5e32a344a3a08ab2df96ddbf5febaeb45ab7257" }, "downloads": -1, "filename": "pyjawk-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "99e6adaf0da254872b5f9fac0dda2a93", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13072, "upload_time": "2019-08-30T00:14:42", "url": "https://files.pythonhosted.org/packages/f1/2f/c9f858a6ee994f62a1d11e88dbe97f42137af459e991e1d536f2e294a0e0/pyjawk-1.0.1-py3-none-any.whl" } ], "1.1.0": [ { "comment_text": "", "digests": { "md5": "dc9ec9327fb345990518ce7cf5afdd53", "sha256": "97af761e668646907553282480864d09f69aa95967017856ae56d0efb4718d74" }, "downloads": -1, "filename": "pyjawk-1.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "dc9ec9327fb345990518ce7cf5afdd53", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16807, "upload_time": "2019-08-30T19:52:39", "url": "https://files.pythonhosted.org/packages/fc/61/0ae59bf93c5475a6e7627b82bde9f3e0ca4bb24d4ef0ed3b6d78b97b0bf5/pyjawk-1.1.0-py3-none-any.whl" } ], "1.1.1": [ { "comment_text": "", "digests": { "md5": "f3383c811153e09b128b6763cd8371d1", "sha256": "dd73a751c9f188c8f940864f18698c475913f1a7d2dee8c68f3d01f956e644b8" }, "downloads": -1, "filename": "pyjawk-1.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "f3383c811153e09b128b6763cd8371d1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 16814, "upload_time": "2019-08-30T19:58:09", "url": "https://files.pythonhosted.org/packages/09/0f/cc9e4e33ff69fbb506ea47b61c404ce83f9f7898fcaa3432e38c8bc04049/pyjawk-1.1.1-py3-none-any.whl" } ], "1.1.2": [ { "comment_text": "", "digests": { "md5": "d4b11b48fedd3239bcc74bebf922ff4c", "sha256": "a24aec78d7f8259afef2abd82c129f751f7d8b99d9df311c4ceb05569d32430c" }, "downloads": -1, "filename": "pyjawk-1.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "d4b11b48fedd3239bcc74bebf922ff4c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 17049, "upload_time": "2019-09-02T19:14:18", "url": "https://files.pythonhosted.org/packages/3c/d8/323b0c2290a5766b72bc6a1982313d17c4460c06d2bfc7e7dbc894c88721/pyjawk-1.1.2-py3-none-any.whl" } ], "1.1.3": [ { "comment_text": "", "digests": { "md5": "98f150a9c5735fd7cca59a74e790a7d1", "sha256": "56f01a66b71e848d7f1957df0ca317e528804fee72b6c4afebabdd84b21a9bdb" }, "downloads": -1, "filename": "pyjawk-1.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "98f150a9c5735fd7cca59a74e790a7d1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 18453, "upload_time": "2019-09-03T22:26:07", "url": "https://files.pythonhosted.org/packages/5a/3e/dd9bc8ae23e77c5997d4e785dbb2cd5841bd82b5749f13217ba3575a1965/pyjawk-1.1.3-py3-none-any.whl" } ], "1.1.4": [ { "comment_text": "", "digests": { "md5": "d67dd23514cc0d328411cb35f54e57fd", "sha256": "603c00a0063c760541062dee35cc08273862d227204a0af16361fe3acbaf7b3a" }, "downloads": -1, "filename": "pyjawk-1.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "d67dd23514cc0d328411cb35f54e57fd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 18505, "upload_time": "2019-09-03T22:37:38", "url": "https://files.pythonhosted.org/packages/43/42/881991d284927a134786eddd5ac3d106b75fb51166a9109ba3f8e9c4a7f1/pyjawk-1.1.4-py3-none-any.whl" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "f9925905d4f0a048db817b6c19cccc0a", "sha256": "7613ea83378da7f859b1ebfeb1661c524a4fac4b074cfc3471aa4289a6e3d6dd" }, "downloads": -1, "filename": "pyjawk-1.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f9925905d4f0a048db817b6c19cccc0a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20272, "upload_time": "2019-09-04T04:58:35", "url": "https://files.pythonhosted.org/packages/2f/dc/08490147c4761dccdfb99b56bc07a329176dea7ede4563a63f6a474106f2/pyjawk-1.2.0-py3-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f9925905d4f0a048db817b6c19cccc0a", "sha256": "7613ea83378da7f859b1ebfeb1661c524a4fac4b074cfc3471aa4289a6e3d6dd" }, "downloads": -1, "filename": "pyjawk-1.2.0-py3-none-any.whl", "has_sig": false, "md5_digest": "f9925905d4f0a048db817b6c19cccc0a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 20272, "upload_time": "2019-09-04T04:58:35", "url": "https://files.pythonhosted.org/packages/2f/dc/08490147c4761dccdfb99b56bc07a329176dea7ede4563a63f6a474106f2/pyjawk-1.2.0-py3-none-any.whl" } ] }