Skip to content

Commit 0583986

Browse files
committed
Migrate to pyproject.toml
1 parent f3643ad commit 0583986

File tree

16 files changed

+412
-189
lines changed

16 files changed

+412
-189
lines changed

.github/workflows/test.yaml

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,16 @@ jobs:
1919
with:
2020
ref: ${{ github.ref }}
2121

22-
- name: Set up Python 3.12
23-
uses: actions/setup-python@v5
22+
- name: "Setup Python, Poetry and Dependencies"
23+
uses: dsoftwareinc/setup-python-poetry-action@v1
2424
with:
25-
python-version: 3.12
26-
allow-prereleases: true
27-
- name: Install dependencies
28-
run: |
29-
python -m pip install --upgrade pip
30-
pip install flake8
25+
python-version: "3.12"
26+
poetry-version: "1.8.3"
27+
3128
- name: Run flake8
3229
shell: bash
3330
run: |
34-
flake8
31+
poetry run flake8
3532
3633
test:
3734
needs: [ lint ]
@@ -40,19 +37,43 @@ jobs:
4037
fail-fast: false
4138
matrix:
4239
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12" ]
40+
poetry-version: [ "1.8.3" ]
41+
42+
exclude:
43+
- python-version: "3.7"
44+
poetry-version: "1.8.3"
45+
include:
46+
- python-version: "3.7"
47+
poetry-version: "1.5.1"
4348

4449
steps:
4550
- uses: actions/checkout@v4
46-
- name: Set up Python ${{ matrix.python-version }}
47-
uses: actions/setup-python@v5
51+
52+
- name: "Setup Python, Poetry and Dependencies"
53+
uses: dsoftwareinc/setup-python-poetry-action@v1
4854
with:
4955
python-version: ${{ matrix.python-version }}
50-
allow-prereleases: true
51-
- name: Install dependencies
56+
poetry-version: ${{ matrix.poetry-version }}
57+
58+
- name: Test
5259
run: |
53-
python -m pip install --upgrade pip
54-
pip install -r requirements-dev.txt
60+
poetry install --no-interaction
61+
poetry run python -m unittest
62+
63+
test-with-coverage:
64+
needs: [ test ]
65+
runs-on: ubuntu-latest
66+
steps:
67+
- uses: actions/checkout@v4
68+
69+
- name: "Setup Python, Poetry and Dependencies"
70+
uses: dsoftwareinc/setup-python-poetry-action@v1
71+
with:
72+
python-version: "3.12"
73+
poetry-version: "1.8.3"
5574

5675
- name: Test
5776
run: |
58-
make coverage
77+
poetry install --no-interaction
78+
poetry run coverage run -m unittest
79+
poetry run coverage report -m

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ dist
77
doc/_build
88
*.egg-info
99
.idea
10+
.venv

AUTHORS

Lines changed: 0 additions & 3 deletions
This file was deleted.

LICENSE.txt renamed to LICENSE

File renamed without changes.

MANIFEST.in

Lines changed: 0 additions & 4 deletions
This file was deleted.

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,24 @@ python-json-pointer
55
[![Supported Python versions](https://img.shields.io/pypi/pyversions/jsonpointer.svg)](https://pypi.python.org/pypi/jsonpointer/)
66
[![Coverage Status](https://coveralls.io/repos/stefankoegl/python-json-pointer/badge.svg?branch=master)](https://coveralls.io/r/stefankoegl/python-json-pointer?branch=master)
77

8-
9-
Resolve JSON Pointers in Python
10-
-------------------------------
8+
# Resolve JSON Pointers in Python
119

1210
Library to resolve JSON Pointers according to
1311
[RFC 6901](http://tools.ietf.org/html/rfc6901)
1412

1513
See source code for examples
14+
1615
* Website: https://github.com/stefankoegl/python-json-pointer
1716
* Repository: https://github.com/stefankoegl/python-json-pointer.git
1817
* Documentation: https://python-json-pointer.readthedocs.org/
1918
* PyPI: https://pypi.python.org/pypi/jsonpointer
2019
* Travis CI: https://travis-ci.org/stefankoegl/python-json-pointer
2120
* Coveralls: https://coveralls.io/r/stefankoegl/python-json-pointer
21+
22+
# Installation
23+
24+
Using pip:
25+
26+
```bash
27+
pip install jsonpointer
28+
```

jsonpointer/__init__.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# python-json-pointer - An implementation of the JSON Pointer syntax
4+
# https://github.com/stefankoegl/python-json-pointer
5+
#
6+
# Copyright (c) 2011 Stefan Kögl <[email protected]>
7+
# All rights reserved.
8+
#
9+
# Redistribution and use in source and binary forms, with or without
10+
# modification, are permitted provided that the following conditions
11+
# are met:
12+
#
13+
# 1. Redistributions of source code must retain the above copyright
14+
# notice, this list of conditions and the following disclaimer.
15+
# 2. Redistributions in binary form must reproduce the above copyright
16+
# notice, this list of conditions and the following disclaimer in the
17+
# documentation and/or other materials provided with the distribution.
18+
# 3. The name of the author may not be used to endorse or promote products
19+
# derived from this software without specific prior written permission.
20+
#
21+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23+
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24+
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26+
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30+
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
#
32+
33+
""" Identify specific nodes in a JSON document (RFC 6901) """
34+
from .jsonpointer import JsonPointerException, JsonPointer, resolve_pointer, set_pointer, EndOfList
35+
36+
try:
37+
from importlib import metadata
38+
except ImportError: # for Python < 3.8
39+
import importlib_metadata as metadata # type: ignore
40+
41+
# Will be parsed by setup.py to determine package metadata
42+
jsonpointer_metadata = metadata.metadata("jsonpointer")
43+
__author__ = jsonpointer_metadata["Author"]
44+
__version__ = metadata.version("jsonpointer")
45+
__website__ = jsonpointer_metadata["Home-page"]
46+
__license__ = jsonpointer_metadata["License"]
47+
48+
__all__ = [
49+
"resolve_pointer",
50+
"set_pointer",
51+
"JsonPointerException",
52+
"JsonPointer",
53+
"EndOfList",
54+
"__author__",
55+
"__version__",
56+
"__website__",
57+
"__license__",
58+
]

jsonpointer.py renamed to jsonpointer/jsonpointer.py

Lines changed: 30 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
#
3-
# python-json-pointer - An implementation of the JSON Pointer syntax
4-
# https://github.com/stefankoegl/python-json-pointer
5-
#
6-
# Copyright (c) 2011 Stefan Kögl <[email protected]>
7-
# All rights reserved.
8-
#
9-
# Redistribution and use in source and binary forms, with or without
10-
# modification, are permitted provided that the following conditions
11-
# are met:
12-
#
13-
# 1. Redistributions of source code must retain the above copyright
14-
# notice, this list of conditions and the following disclaimer.
15-
# 2. Redistributions in binary form must reproduce the above copyright
16-
# notice, this list of conditions and the following disclaimer in the
17-
# documentation and/or other materials provided with the distribution.
18-
# 3. The name of the author may not be used to endorse or promote products
19-
# derived from this software without specific prior written permission.
20-
#
21-
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22-
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23-
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24-
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26-
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27-
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28-
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29-
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30-
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31-
#
32-
33-
""" Identify specific nodes in a JSON document (RFC 6901) """
34-
35-
# Will be parsed by setup.py to determine package metadata
36-
__author__ = 'Stefan Kögl <[email protected]>'
37-
__version__ = '3.0.0'
38-
__website__ = 'https://github.com/stefankoegl/python-json-pointer'
39-
__license__ = 'Modified BSD License'
40-
411
import copy
422
import re
433
from collections.abc import Mapping, Sequence
@@ -73,7 +33,7 @@ def set_pointer(doc, pointer, value, inplace=True):
7333

7434

7535
def resolve_pointer(doc, pointer, default=_nothing):
76-
""" Resolves pointer against doc and returns the referenced object
36+
"""Resolves pointer against doc and returns the referenced object
7737
7838
>>> obj = {'foo': {'anArray': [ {'prop': 44}], 'another prop': {'baz': 'A string' }}, 'a%20b': 1, 'c d': 2}
7939
@@ -113,7 +73,7 @@ def resolve_pointer(doc, pointer, default=_nothing):
11373

11474

11575
def pairwise(iterable):
116-
""" Transforms a list to a list of tuples of adjacent items
76+
"""Transforms a list to a list of tuples of adjacent items
11777
11878
s -> (s0,s1), (s1,s2), (s2, s3), ...
11979
@@ -143,29 +103,29 @@ def __init__(self, list_):
143103
self.list_ = list_
144104

145105
def __repr__(self):
146-
return '{cls}({lst})'.format(cls=self.__class__.__name__,
147-
lst=repr(self.list_))
106+
return "{cls}({lst})".format(cls=self.__class__.__name__, lst=repr(self.list_))
148107

149108

150109
class JsonPointer(object):
151110
"""A JSON Pointer that can reference parts of a JSON document"""
152111

153112
# Array indices must not contain:
154113
# leading zeros, signs, spaces, decimals, etc
155-
_RE_ARRAY_INDEX = re.compile('0|[1-9][0-9]*$')
156-
_RE_INVALID_ESCAPE = re.compile('(~[^01]|~$)')
114+
_RE_ARRAY_INDEX = re.compile("0|[1-9][0-9]*$")
115+
_RE_INVALID_ESCAPE = re.compile("(~[^01]|~$)")
157116

158117
def __init__(self, pointer):
159118

160119
# validate escapes
161120
invalid_escape = self._RE_INVALID_ESCAPE.search(pointer)
162121
if invalid_escape:
163-
raise JsonPointerException('Found invalid escape {}'.format(
164-
invalid_escape.group()))
122+
raise JsonPointerException(
123+
"Found invalid escape {}".format(invalid_escape.group())
124+
)
165125

166-
parts = pointer.split('/')
167-
if parts.pop(0) != '':
168-
raise JsonPointerException('Location must start with /')
126+
parts = pointer.split("/")
127+
if parts.pop(0) != "":
128+
raise JsonPointerException("Location must start with /")
169129

170130
parts = [unescape(part) for part in parts]
171131
self.parts = parts
@@ -203,15 +163,15 @@ def set(self, doc, value, inplace=True):
203163

204164
if len(self.parts) == 0:
205165
if inplace:
206-
raise JsonPointerException('Cannot set root in place')
166+
raise JsonPointerException("Cannot set root in place")
207167
return value
208168

209169
if not inplace:
210170
doc = copy.deepcopy(doc)
211171

212172
(parent, part) = self.to_last(doc)
213173

214-
if isinstance(parent, Sequence) and part == '-':
174+
if isinstance(parent, Sequence) and part == "-":
215175
parent.append(value)
216176
else:
217177
parent[part] = value
@@ -227,37 +187,39 @@ def get_part(cls, doc, part):
227187

228188
elif isinstance(doc, Sequence):
229189

230-
if part == '-':
190+
if part == "-":
231191
return part
232192

233193
if not JsonPointer._RE_ARRAY_INDEX.match(str(part)):
234194
raise JsonPointerException("'%s' is not a valid sequence index" % part)
235195

236196
return int(part)
237197

238-
elif hasattr(doc, '__getitem__'):
198+
elif hasattr(doc, "__getitem__"):
239199
# Allow indexing via ducktyping
240200
# if the target has defined __getitem__
241201
return part
242202

243203
else:
244-
raise JsonPointerException("Document '%s' does not support indexing, "
245-
"must be mapping/sequence or support __getitem__" % type(doc))
204+
raise JsonPointerException(
205+
"Document '%s' does not support indexing, "
206+
"must be mapping/sequence or support __getitem__" % type(doc)
207+
)
246208

247209
def get_parts(self):
248210
"""Returns the list of the parts. For example, JsonPointer('/a/b').get_parts() == ['a', 'b']"""
249211

250212
return self.parts
251213

252214
def walk(self, doc, part):
253-
""" Walks one step in doc and returns the referenced part """
215+
"""Walks one step in doc and returns the referenced part"""
254216

255217
part = JsonPointer.get_part(doc, part)
256218

257-
assert hasattr(doc, '__getitem__'), "invalid document type %s" % (type(doc),)
219+
assert hasattr(doc, "__getitem__"), "invalid document type %s" % (type(doc),)
258220

259221
if isinstance(doc, Sequence):
260-
if part == '-':
222+
if part == "-":
261223
return EndOfList(doc)
262224

263225
try:
@@ -274,15 +236,15 @@ def walk(self, doc, part):
274236
raise JsonPointerException("member '%s' not found in %s" % (part, doc))
275237

276238
def contains(self, ptr):
277-
""" Returns True if self contains the given ptr """
278-
return self.parts[:len(ptr.parts)] == ptr.parts
239+
"""Returns True if self contains the given ptr"""
240+
return self.parts[: len(ptr.parts)] == ptr.parts
279241

280242
def __contains__(self, item):
281-
""" Returns True if self contains the given ptr """
243+
"""Returns True if self contains the given ptr"""
282244
return self.contains(item)
283245

284246
def join(self, suffix):
285-
""" Returns a new JsonPointer with the given suffix append to this ptr """
247+
"""Returns a new JsonPointer with the given suffix append to this ptr"""
286248
if isinstance(suffix, JsonPointer):
287249
suffix_parts = suffix.parts
288250
elif isinstance(suffix, str):
@@ -304,7 +266,7 @@ def path(self):
304266
>>> ptr = JsonPointer('/~0/0/~1').path == '/~0/0/~1'
305267
"""
306268
parts = [escape(part) for part in self.parts]
307-
return ''.join('/' + part for part in parts)
269+
return "".join("/" + part for part in parts)
308270

309271
def __eq__(self, other):
310272
"""Compares a pointer to another object
@@ -336,13 +298,13 @@ def from_parts(cls, parts):
336298
True
337299
"""
338300
parts = [escape(str(part)) for part in parts]
339-
ptr = cls(''.join('/' + part for part in parts))
301+
ptr = cls("".join("/" + part for part in parts))
340302
return ptr
341303

342304

343305
def escape(s):
344-
return s.replace('~', '~0').replace('/', '~1')
306+
return s.replace("~", "~0").replace("/", "~1")
345307

346308

347309
def unescape(s):
348-
return s.replace('~1', '/').replace('~0', '~')
310+
return s.replace("~1", "/").replace("~0", "~")

0 commit comments

Comments
 (0)