Name | pjy JSON |
Version |
0.14.0
JSON |
| download |
home_page | |
Summary | pjy - command-line JSON processor |
upload_time | 2023-08-11 11:12:14 |
maintainer | |
docs_url | None |
author | |
requires_python | >=3 |
license | |
keywords |
filter
jq
json
processor
query
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
pjy - JSON Python processor
===========================
``pjy`` is a command-line tool to process JSON data and execute queries on it.
It is a bit like `jq <https://stedolan.github.io/jq/>`_ but with a Python syntax for queries.
Install
+++++++
From `PyPI <https://pypi.org/project/pjy/>`_::
pip install pjy
Usage
+++++
pjy [EXPR] [FILES]
``pjy`` will read JSON data from ``FILES`` and print the evaluation result of the Python expression ``EXPR``.
If ``FILES`` is missing or is "``-``", pjy will use stdin.
The simplest expression to use, which outputs the input unchanged is "``d``" (for data).
It's possible to use multiple input files.
Examples
++++++++
In ``pjy``, expressions are also called "filters", as in ``jq``.
Just pretty-print
-----------------
``d`` (short for "data") is the most basic filter, it represents the whole input::
pjy 'd'
{"foo":"bar","baz":[1,2,3]}
Prints::
{
"foo": "bar",
"baz": [
1,
2,
3
]
}
Select a dict key
-----------------
The filters are Python expressions, hence we can select a dict key::
pjy 'd["baz"]'
{"foo":"bar","baz":[1,2,3]}
Alternatively, in ``pjy``, dicts keys are also attributes::
pjy 'd.baz'
{"foo":"bar","baz":[1,2,3]}
Both filters will print::
[
1,
2,
3
]
In case a key has a reserved name, like ``import`` (keyword) or ``keys`` (dict method), simply use the bracket form.
Non-existent keys
-----------------
Non-existent keys::
pjy 'd.baz'
{"foo":"bar"}
will return ``None``::
null
Same for out-of-bounds indices::
pjy 'd[3]'
[1, 2]
Do a basic operation
--------------------
It's possible to use everything that a Python expression can contain::
pjy '[i + 1 for i in d["baz"]]'
{"foo":"bar","baz":[1,2,3]}
Prints::
[
2,
3,
4
]
Lambda-placeholder
------------------
A special identifier, ``_`` can be used to create lambdas. This identifier will absorb most operations done to it and return a lambda applying them.
Then, the returned lambda can be applied::
pjy 'map(_ + 1, d.baz)'
{"foo":"bar","baz":[1,2,3]}
Is equivalent to::
pjy 'map((lambda x: x + 1), d.baz)'
{"foo":"bar","baz":[1,2,3]}
Which will print::
[
2,
3,
4
]
The lambda-placeholder will absorb chained operations::
pjy 'map((_ + 1) * 2, d.baz)'
{"foo":"bar","baz":[1,2,3]}
Will result in::
[
4,
6,
8
]
And::
pjy 'map(_[1:3] * 2, d)'
{"foo":"bar","baz":[1,2,3]}
Will return::
{
"foo": "arar",
"baz": [
2,
3,
2,
3
]
}
Pipe-like iteration
-------------------
The pipe (``|``) can be used to iterate on a list, it accepts a function as right operand::
pjy 'd.baz | _ + 1'
{"foo":"bar","baz":[1,2,3]}
Which prints::
[
2,
3,
4
]
It also operates on a dict's values, and returns a dict::
pjy 'd | (lambda x: repr(x))'
{"foo":"bar","baz":[1,2,3]}
The values are replaced by the right operand value, the keys are unchanged::
{
"foo": "'bar'",
"baz": "[1, 2, 3]"
}
Ampersand for filtering
-----------------------
Similar to the pipe, the ampersand (``&``) is used on a list and a function, but its purpose is to filter::
pjy 'd & (_ % 2 == 0)'
[0, 1, 2, 3]
outputs::
[
0,
2
]
Which is equivalent to running::
pjy 'filter(_ % 2 == 0, d)'
[0, 1, 2, 3]
Like the pipe, it works on a dict, and the filter is applied on the dict values.
Partial placeholder
-------------------
It's not possible to call a function on a placeholder, for example, ``len(_)`` will not work.
However, it's possible to use the ``partial`` helper to prepare the function call::
pjy 'd | partial(len, _)'
{"foo":"bar","baz":[1,2,3]}
Prints::
{
"foo": 3,
"baz": 3
}
``partial`` ressembles the ``functools.partial`` function: it returns a function wrapping the function passed as first argument.
The returned function will call the original function with the fixed arguments passed.
The difference is that lambda-placeholders can be passed, and they will be replaced by the wrapper's argument.
``p`` is a short alias for the ``partial`` function which can be used in pjy expressions.
Imports
-------
It's possible to import modules with the ``imp`` function::
pjy 'filter(p(imp("fnmatch").fnmatch, _, "f*"), d.keys())'
{"foo":"bar","baz":[1,2,3]}
Will print::
[
"foo"
]
The ``math`` and ``re`` modules are already imported and available directly without having to call ``imp``.
Multiple inputs
---------------
In ``pjy``, an ``inputs`` variable exists, which is a list containing the JSON data of each input file passed on the command line.
The ``d`` variable is simply an alias to ``inputs[0]``.
For example::
pjy 'filter(_[0] != _[1], zip(inputs[0], inputs[1]))' before.json after.json
will read 2 files ``before.json`` and ``after.json``, which consist in a list of objects, and ``pjy`` will compare each zipped-pair of objects together.
Then it will print the list of differing pairs.
Options
+++++++
Input options
-------------
``--null-input``
Don't read any input, act as if the input was only ``null``.
``--arg VAR VALUE``
Inject a variable named VAR with a VALUE in the expression.
Output options
--------------
``--monochrome-output``
Force no colors even if output is a TTY. Can also set ``NO_COLOR`` environment variable to do the same.
``--ascii-output``
When outputting non-ASCII strings, use ``\uXXXX`` notation instead of directly Unicode characters by default.
``--tab``
Indent output with tabs instead of 2 spaces.
``--indent N``
Indent output with N spaces instead of 2 spaces.
``--compact-output``
Don't indent output and don't add extra whitespace between key/values and list elements.
Environment variables
+++++++++++++++++++++
``NO_COLOR``: set it to disable colors even if output is a TTY.
``CLICOLOR_FORCE``: set it to enable colors even if output is not a TTY.
Security
++++++++
``pjy`` by itself does not write files (except stdout/stderr) or sockets, or run external commands.
However, ``pjy`` runs the given expressions passed as argument, in the Python interpreter, without a sandbox.
Hence, do NOT pass dangerous or untrusted Python expressions to ``pjy``.
Dependencies
++++++++++++
``pjy`` is written in Python 3. Its ``setup.py`` requires ``setuptools``.
If ``pygments`` is installed, ``pjy``'s output will be colorized, but it's entirely optional.
Version and license
+++++++++++++++++++
.. $version
``pjy`` is at version 0.13.0, it uses `semantic versioning <https://semver.org/>`_.
It is licensed under the WTFPLv2, see COPYING.WTFPL for license text.
Raw data
{
"_id": null,
"home_page": "",
"name": "pjy",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3",
"maintainer_email": "",
"keywords": "filter,jq,json,processor,query",
"author": "",
"author_email": "Hg <dev@indigo.re>",
"download_url": "https://files.pythonhosted.org/packages/80/9c/ef3ee5adc09c0ccccbd045d9763704fbfbacb651a4b1399ee860ae863e34/pjy-0.14.0.tar.gz",
"platform": null,
"description": "pjy - JSON Python processor\n===========================\n\n``pjy`` is a command-line tool to process JSON data and execute queries on it.\nIt is a bit like `jq <https://stedolan.github.io/jq/>`_ but with a Python syntax for queries.\n\nInstall\n+++++++\n\nFrom `PyPI <https://pypi.org/project/pjy/>`_::\n\n pip install pjy\n\nUsage\n+++++\n\n pjy [EXPR] [FILES]\n\n``pjy`` will read JSON data from ``FILES`` and print the evaluation result of the Python expression ``EXPR``.\n\nIf ``FILES`` is missing or is \"``-``\", pjy will use stdin.\n\nThe simplest expression to use, which outputs the input unchanged is \"``d``\" (for data).\n\nIt's possible to use multiple input files.\n\nExamples\n++++++++\n\nIn ``pjy``, expressions are also called \"filters\", as in ``jq``.\n\nJust pretty-print\n-----------------\n\n``d`` (short for \"data\") is the most basic filter, it represents the whole input::\n\n pjy 'd'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nPrints::\n\n {\n \"foo\": \"bar\",\n \"baz\": [\n 1,\n 2,\n 3\n ]\n }\n\nSelect a dict key\n-----------------\n\nThe filters are Python expressions, hence we can select a dict key::\n\n pjy 'd[\"baz\"]'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nAlternatively, in ``pjy``, dicts keys are also attributes::\n\n pjy 'd.baz'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nBoth filters will print::\n\n [\n 1,\n 2,\n 3\n ]\n\nIn case a key has a reserved name, like ``import`` (keyword) or ``keys`` (dict method), simply use the bracket form.\n\nNon-existent keys\n-----------------\n\nNon-existent keys::\n\n pjy 'd.baz'\n {\"foo\":\"bar\"}\n\nwill return ``None``::\n\n null\n\nSame for out-of-bounds indices::\n\n pjy 'd[3]'\n [1, 2]\n\nDo a basic operation\n--------------------\n\nIt's possible to use everything that a Python expression can contain::\n\n pjy '[i + 1 for i in d[\"baz\"]]'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nPrints::\n\n [\n 2,\n 3,\n 4\n ]\n\nLambda-placeholder\n------------------\n\nA special identifier, ``_`` can be used to create lambdas. This identifier will absorb most operations done to it and return a lambda applying them.\nThen, the returned lambda can be applied::\n\n pjy 'map(_ + 1, d.baz)'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nIs equivalent to::\n\n pjy 'map((lambda x: x + 1), d.baz)'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nWhich will print::\n\n [\n 2,\n 3,\n 4\n ]\n\nThe lambda-placeholder will absorb chained operations::\n\n pjy 'map((_ + 1) * 2, d.baz)'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\n\nWill result in::\n\n [\n 4,\n 6,\n 8\n ]\n\nAnd::\n\n pjy 'map(_[1:3] * 2, d)'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nWill return::\n\n {\n \"foo\": \"arar\",\n \"baz\": [\n 2,\n 3,\n 2,\n 3\n ]\n }\n\nPipe-like iteration\n-------------------\n\nThe pipe (``|``) can be used to iterate on a list, it accepts a function as right operand::\n\n pjy 'd.baz | _ + 1'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nWhich prints::\n\n [\n 2,\n 3,\n 4\n ]\n\nIt also operates on a dict's values, and returns a dict::\n\n pjy 'd | (lambda x: repr(x))'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nThe values are replaced by the right operand value, the keys are unchanged::\n\n {\n \"foo\": \"'bar'\",\n \"baz\": \"[1, 2, 3]\"\n }\n\nAmpersand for filtering\n-----------------------\n\nSimilar to the pipe, the ampersand (``&``) is used on a list and a function, but its purpose is to filter::\n\n pjy 'd & (_ % 2 == 0)'\n [0, 1, 2, 3]\n\noutputs::\n\n [\n 0,\n 2\n ]\n\nWhich is equivalent to running::\n\n pjy 'filter(_ % 2 == 0, d)'\n [0, 1, 2, 3]\n\nLike the pipe, it works on a dict, and the filter is applied on the dict values.\n\nPartial placeholder\n-------------------\n\nIt's not possible to call a function on a placeholder, for example, ``len(_)`` will not work.\nHowever, it's possible to use the ``partial`` helper to prepare the function call::\n\n pjy 'd | partial(len, _)'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nPrints::\n\n {\n \"foo\": 3,\n \"baz\": 3\n }\n\n``partial`` ressembles the ``functools.partial`` function: it returns a function wrapping the function passed as first argument.\nThe returned function will call the original function with the fixed arguments passed.\nThe difference is that lambda-placeholders can be passed, and they will be replaced by the wrapper's argument.\n\n``p`` is a short alias for the ``partial`` function which can be used in pjy expressions.\n\nImports\n-------\n\nIt's possible to import modules with the ``imp`` function::\n\n pjy 'filter(p(imp(\"fnmatch\").fnmatch, _, \"f*\"), d.keys())'\n {\"foo\":\"bar\",\"baz\":[1,2,3]}\n\nWill print::\n\n [\n \"foo\"\n ]\n\nThe ``math`` and ``re`` modules are already imported and available directly without having to call ``imp``.\n\nMultiple inputs\n---------------\n\nIn ``pjy``, an ``inputs`` variable exists, which is a list containing the JSON data of each input file passed on the command line.\nThe ``d`` variable is simply an alias to ``inputs[0]``.\n\nFor example::\n\n pjy 'filter(_[0] != _[1], zip(inputs[0], inputs[1]))' before.json after.json\n\nwill read 2 files ``before.json`` and ``after.json``, which consist in a list of objects, and ``pjy`` will compare each zipped-pair of objects together.\nThen it will print the list of differing pairs.\n\nOptions\n+++++++\n\nInput options\n-------------\n\n\t``--null-input``\n\nDon't read any input, act as if the input was only ``null``.\n\n\t``--arg VAR VALUE``\n\nInject a variable named VAR with a VALUE in the expression.\n\nOutput options\n--------------\n\n\t``--monochrome-output``\n\nForce no colors even if output is a TTY. Can also set ``NO_COLOR`` environment variable to do the same.\n\n\t``--ascii-output``\n\nWhen outputting non-ASCII strings, use ``\\uXXXX`` notation instead of directly Unicode characters by default.\n\n\t``--tab``\n\nIndent output with tabs instead of 2 spaces.\n\n\t``--indent N``\n\nIndent output with N spaces instead of 2 spaces.\n\n\t``--compact-output``\n\nDon't indent output and don't add extra whitespace between key/values and list elements.\n\n\nEnvironment variables\n+++++++++++++++++++++\n\n``NO_COLOR``: set it to disable colors even if output is a TTY.\n\n``CLICOLOR_FORCE``: set it to enable colors even if output is not a TTY.\n\n\nSecurity\n++++++++\n\n``pjy`` by itself does not write files (except stdout/stderr) or sockets, or run external commands.\nHowever, ``pjy`` runs the given expressions passed as argument, in the Python interpreter, without a sandbox.\nHence, do NOT pass dangerous or untrusted Python expressions to ``pjy``.\n\nDependencies\n++++++++++++\n\n``pjy`` is written in Python 3. Its ``setup.py`` requires ``setuptools``.\n\nIf ``pygments`` is installed, ``pjy``'s output will be colorized, but it's entirely optional.\n\nVersion and license\n+++++++++++++++++++\n\n.. $version\n\n``pjy`` is at version 0.13.0, it uses `semantic versioning <https://semver.org/>`_.\nIt is licensed under the WTFPLv2, see COPYING.WTFPL for license text.\n",
"bugtrack_url": null,
"license": "",
"summary": "pjy - command-line JSON processor",
"version": "0.14.0",
"project_urls": {
"Project": "https://gitlab.com/hydrargyrum/pjy"
},
"split_keywords": [
"filter",
"jq",
"json",
"processor",
"query"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "bdabb49c67a2afff234c6ec35be013d9320f792b1519fdf89e135c03cabd7753",
"md5": "a6252b385a65c7a54f57c2dd90babe3c",
"sha256": "f582c406c511d3e319eb64731fb6911bc20ded66b9e5ec7bd23ea65ae7470ab5"
},
"downloads": -1,
"filename": "pjy-0.14.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a6252b385a65c7a54f57c2dd90babe3c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3",
"size": 10801,
"upload_time": "2023-08-11T11:12:12",
"upload_time_iso_8601": "2023-08-11T11:12:12.744755Z",
"url": "https://files.pythonhosted.org/packages/bd/ab/b49c67a2afff234c6ec35be013d9320f792b1519fdf89e135c03cabd7753/pjy-0.14.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "809cef3ee5adc09c0ccccbd045d9763704fbfbacb651a4b1399ee860ae863e34",
"md5": "bfa6261935591ce91f1ad497e18786de",
"sha256": "0236e4978ab8fec5089311ef8e6e3ef045adc6fe76bbbbe6dac3aaa81170c496"
},
"downloads": -1,
"filename": "pjy-0.14.0.tar.gz",
"has_sig": false,
"md5_digest": "bfa6261935591ce91f1ad497e18786de",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3",
"size": 7246,
"upload_time": "2023-08-11T11:12:14",
"upload_time_iso_8601": "2023-08-11T11:12:14.508767Z",
"url": "https://files.pythonhosted.org/packages/80/9c/ef3ee5adc09c0ccccbd045d9763704fbfbacb651a4b1399ee860ae863e34/pjy-0.14.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-11 11:12:14",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "hydrargyrum",
"gitlab_project": "pjy",
"lcname": "pjy"
}