Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
01678a0
Clean up broken, outdated and redundant bits across the project
claude Nov 10, 2026
e18bde6
Use SPDX identifier for __license__
claude Nov 10, 2026
7cab829
Deprecate pairwise() in favour of itertools.pairwise()
claude Nov 10, 2026
4358bbb
Keep the original error when join() rejects a suffix
claude Nov 10, 2026
4f85568
Pin Sphinx for reproducible documentation builds
claude Nov 10, 2026
9217f51
Trim the Sphinx configuration to the settings in use
claude Nov 10, 2026
47ad3bc
Ship everything needed to test and build docs from the sdist
claude Nov 10, 2026
c4cded9
Update the tested Python versions
claude Nov 10, 2026
a6dff9e
Update GitHub Actions to current major versions
claude Nov 10, 2026
ba24926
Exit with status 130 when the CLI is interrupted
claude Nov 10, 2026
0c35027
Fix the Ctrl-C exit status test
claude Nov 10, 2026
725fd75
Stop using the deprecated argparse.FileType in the CLI
claude Nov 10, 2026
90d9737
Merge pull request #125 from stefankoegl/claude/cli-drop-filetype
stefankoegl Nov 11, 2026
570ffe1
Merge pull request #119 from stefankoegl/claude/trim-sphinx-conf
stefankoegl Nov 11, 2026
2efaee5
Merge pull request #118 from stefankoegl/claude/pin-sphinx
stefankoegl Nov 11, 2026
a3774ae
Merge pull request #115 from stefankoegl/claude/license-spdx
stefankoegl Nov 11, 2026
0ba465a
Merge pull request #116 from stefankoegl/claude/deprecate-pairwise
stefankoegl Nov 11, 2026
0a2fb51
Merge pull request #120 from stefankoegl/claude/sdist-contents
stefankoegl Nov 11, 2026
de8f0c5
Merge pull request #122 from stefankoegl/claude/bump-actions
stefankoegl Nov 11, 2026
94b337a
Merge pull request #121 from stefankoegl/claude/python-matrix
stefankoegl Nov 11, 2026
e085b8f
Merge pull request #124 from stefankoegl/claude/cli-sigint-exit-status
stefankoegl Nov 11, 2026
a4b3fb4
Merge pull request #117 from stefankoegl/claude/join-exception-chain
stefankoegl Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: "3.13"

Expand All @@ -58,7 +58,7 @@ jobs:
- name: Check distributions
run: twine check --strict dist/*

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: dist
path: dist/
Expand All @@ -74,13 +74,13 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
name: dist
path: dist/

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3

publish-testpypi:
name: Publish to TestPyPI
Expand All @@ -93,12 +93,12 @@ jobs:
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
name: dist
path: dist/

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
with:
repository-url: https://test.pypi.org/legacy/
36 changes: 19 additions & 17 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,12 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
- uses: actions/checkout@v7

- name: Set up Python 3.13
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: 3.13
allow-prereleases: true
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand All @@ -39,10 +36,10 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Set up Python 3.13
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: "3.13"
- name: Install build tools
Expand All @@ -60,10 +57,10 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Set up Python 3.13
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: "3.13"
- name: Install dependencies
Expand All @@ -81,10 +78,10 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7

- name: Set up Python 3.13
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: "3.13"
- name: Install dependencies
Expand All @@ -97,21 +94,26 @@ jobs:
test:
needs: [ lint ]
runs-on: ${{ matrix.os }}
# Pre-release Pythons may fail for reasons unrelated to this package
continue-on-error: ${{ matrix.experimental || false }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "pypy3.10", "pypy3.11" ]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15", "pypy3.11" ]
include:
- os: windows-latest
python-version: "3.13"
python-version: "3.15"
- os: macos-latest
python-version: "3.13"
python-version: "3.15"
- os: ubuntu-latest
python-version: "3.16"
experimental: true

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ build:
tools:
python: "3.13"

# Build documentation in the docs/ directory with Sphinx
# Build documentation in the doc/ directory with Sphinx
sphinx:
configuration: doc/conf.py

Expand Down
7 changes: 6 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
include AUTHORS
include LICENSE.txt
include README.md
include makefile
include requirements-dev.txt
include .coveragerc
include tests.py
include doc/*.rst
include doc/conf.py
include doc/Makefile
include doc/requirements.txt
recursive-include jsonpointer-stubs *.pyi
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
python-json-pointer
===================

[![PyPI version](https://img.shields.io/pypi/v/jsonpointer.svg)](https://pypi.python.org/pypi/jsonpointer/)
[![Supported Python versions](https://img.shields.io/pypi/pyversions/jsonpointer.svg)](https://pypi.python.org/pypi/jsonpointer/)
[![PyPI version](https://img.shields.io/pypi/v/jsonpointer.svg)](https://pypi.org/project/jsonpointer/)
[![Supported Python versions](https://img.shields.io/pypi/pyversions/jsonpointer.svg)](https://pypi.org/project/jsonpointer/)
[![Tests](https://github.com/stefankoegl/python-json-pointer/actions/workflows/test.yaml/badge.svg?branch=master)](https://github.com/stefankoegl/python-json-pointer/actions/workflows/test.yaml)
[![Coverage Status](https://coveralls.io/repos/github/stefankoegl/python-json-pointer/badge.svg?branch=master)](https://coveralls.io/github/stefankoegl/python-json-pointer?branch=master)

Expand All @@ -11,12 +11,13 @@ Resolve JSON Pointers in Python
-------------------------------

Library to resolve JSON Pointers according to
[RFC 6901](http://tools.ietf.org/html/rfc6901)
[RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)

See the documentation for examples.

See source code for examples
* Website: https://github.com/stefankoegl/python-json-pointer
* Repository: https://github.com/stefankoegl/python-json-pointer.git
* Documentation: https://python-json-pointer.readthedocs.org/
* PyPI: https://pypi.python.org/pypi/jsonpointer
* Documentation: https://python-json-pointer.readthedocs.io/
* PyPI: https://pypi.org/project/jsonpointer/
* GitHub Actions: https://github.com/stefankoegl/python-json-pointer/actions
* Coveralls: https://coveralls.io/github/stefankoegl/python-json-pointer
43 changes: 28 additions & 15 deletions bin/jsonpointer
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ parser = argparse.ArgumentParser(
# Accept pointer as option, as file or as first positional argument
ptr_group = parser.add_mutually_exclusive_group()

ptr_group.add_argument('-f', '--pointer-file', type=argparse.FileType('r', encoding='utf-8'),
ptr_group.add_argument('-f', '--pointer-file', type=str,
help='File containing a JSON pointer expression')

ptr_group.add_argument('-p', '--pointer', type=str,
Expand All @@ -37,14 +37,28 @@ def main():
try:
ok = resolve_files()
except KeyboardInterrupt:
sys.exit(1)
# Conventional status for termination by SIGINT (128 + 2)
sys.exit(130)

if not ok:
sys.exit(1)


def open_input(name):
""" Open a UTF-8 input file, or return stdin for "-"

Exits with a usage error if the file cannot be opened. """
if name == '-':
return sys.stdin

try:
return open(name, encoding='utf-8')
except OSError as e:
parser.error("can't open '%s': %s" % (name, e))


def parse_pointer(args):
""" Return the pointer and the list of files to resolve it on
""" Return the parsed pointer and the list of files to resolve it on

If the pointer is given via -f or -p, a POINTER positional argument is
actually the first file. """
Expand All @@ -57,14 +71,16 @@ def parse_pointer(args):
if args.pointer is not None:
ptr = args.pointer
else:
# 2026-10-11: Trim file line endings without changing member names.
# Strip only the trailing line ending; other whitespace may be
# part of a member name.
pointer_file = open_input(args.pointer_file)
try:
ptr = args.pointer_file.read().rstrip("\r\n")
ptr = pointer_file.read().rstrip("\r\n")
except UnicodeDecodeError as e:
parser.error('could not decode pointer file: %s' % e)
finally:
if args.pointer_file is not sys.stdin:
args.pointer_file.close()
if pointer_file is not sys.stdin:
pointer_file.close()

elif args.POINTER is not None:
ptr = args.POINTER
Expand All @@ -75,11 +91,11 @@ def parse_pointer(args):
# Catches e.g. `jsonpointer a.json b.json`, where the pointer was omitted
# and the first file would otherwise be used as the pointer
try:
jsonpointer.JsonPointer(ptr)
pointer = jsonpointer.JsonPointer(ptr)
except jsonpointer.JsonPointerException as e:
parser.error('invalid JSON pointer %r: %s' % (ptr, e))

return ptr, files
return pointer, files


def resolve_files():
Expand All @@ -89,14 +105,11 @@ def resolve_files():
or if --continue-on-error skipped a JSON or text decoding error. """
args = parser.parse_args()

ptr, files = parse_pointer(args)
pointer, files = parse_pointer(args)
ok = True

for name in files:
try:
f = argparse.FileType('r', encoding='utf-8')(name)
except argparse.ArgumentTypeError as e:
parser.error(str(e))
f = open_input(name)

try:
doc = json.load(f)
Expand All @@ -112,7 +125,7 @@ def resolve_files():
f.close()

try:
result = jsonpointer.resolve_pointer(doc, ptr)
result = pointer.resolve(doc)
if isinstance(result, jsonpointer.EndOfList):
raise jsonpointer.JsonPointerException(
"'-' does not reference an existing array element")
Expand Down
Empty file removed doc/_static/.empty
Empty file.
10 changes: 5 additions & 5 deletions doc/commandline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ The ``jsonpointer`` commandline utility
=======================================

The JSON pointer package also installs a ``jsonpointer`` commandline utility
that can be used to resolve a JSON pointers on JSON files.
that can be used to resolve a JSON pointer on JSON files.

The program has the following usage ::

Expand All @@ -19,9 +19,9 @@ The program has the following usage ::

options:
-h, --help show this help message and exit
-f POINTER_FILE, --pointer-file POINTER_FILE
-f, --pointer-file POINTER_FILE
File containing a JSON pointer expression
-p POINTER, --pointer POINTER
-p, --pointer POINTER
A JSON pointer expression
--indent INDENT Indent output by n spaces
--continue-on-error Continue with remaining files after JSON or text
Expand All @@ -35,8 +35,8 @@ JSON input files and pointer files are read as UTF-8.

The exit status is 0 if the pointer could be resolved on all files, 1 if it
could not be resolved on at least one file (the remaining files are still
processed) and 2 on usage errors, such as an invalid pointer or a missing
file.
processed), 2 on usage errors, such as an invalid pointer or a missing
file, and 130 if interrupted with Ctrl-C.

By default, invalid JSON or a text decoding error stops processing. With
``--continue-on-error``, these errors are reported on standard error with
Expand Down
Loading
Loading