From 6b2c95dad7710156d8b3522b316103911a83694b Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:23:09 -0400 Subject: [PATCH 1/8] !feat:remove python 2.7 support --- .github/workflows/test.yaml | 12 ++++++------ bin/jsonpointer | 10 ++++------ jsonpointer.py | 31 +++++++++++-------------------- requirements-dev.txt | 5 +++-- setup.py | 4 +--- tests.py | 27 +++++++++++---------------- 6 files changed, 36 insertions(+), 53 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 554c462..92afae6 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,6 +1,6 @@ name: Python package -on: [push] +on: [ push ] jobs: build: @@ -9,12 +9,12 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11", "3.12" ] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -23,12 +23,12 @@ jobs: python -m pip install --upgrade pip pip install flake8 pytest pip install coveralls -# - name: Lint with flake8 -# run: | + # - name: Lint with flake8 + # run: | # stop the build if there are Python syntax errors or undefined names # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test run: | make coverage diff --git a/bin/jsonpointer b/bin/jsonpointer index d577d01..ba2117c 100755 --- a/bin/jsonpointer +++ b/bin/jsonpointer @@ -1,14 +1,12 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from __future__ import print_function -import sys -import os.path -import json -import jsonpointer import argparse +import json +import sys +import jsonpointer parser = argparse.ArgumentParser( description='Resolve a JSON pointer on JSON files') @@ -20,7 +18,7 @@ ptr_group.add_argument('-f', '--pointer-file', type=argparse.FileType('r'), nargs='?', help='File containing a JSON pointer expression') -ptr_group.add_argument('POINTER', type=str, nargs='?', +ptr_group.add_argument('POINTER', type=str, nargs='?', help='A JSON pointer expression') parser.add_argument('FILE', type=argparse.FileType('r'), nargs='+', diff --git a/jsonpointer.py b/jsonpointer.py index 47d90ad..8e878cd 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -32,22 +32,14 @@ """ Identify specific nodes in a JSON document (RFC 6901) """ -from __future__ import unicode_literals # Will be parsed by setup.py to determine package metadata __author__ = 'Stefan Kögl ' -__version__ = '2.4' +__version__ = '3.0.0' __website__ = 'https://github.com/stefankoegl/python-json-pointer' __license__ = 'Modified BSD License' -try: - from itertools import izip - str = unicode - encode_str = lambda u: u.encode("raw_unicode_escape") -except ImportError: # Python 3 - izip = zip - encode_str = lambda u: u try: from collections.abc import Mapping, Sequence @@ -58,7 +50,6 @@ import re import copy - _nothing = object() @@ -145,7 +136,7 @@ def pairwise(iterable): a, b = tee(iterable) for _ in b: break - return izip(a, b) + return zip(a, b) class JsonPointerException(Exception): @@ -259,12 +250,11 @@ def get_part(cls, doc, part): else: raise JsonPointerException("Document '%s' does not support indexing, " "must be mapping/sequence or support __getitem__" % type(doc)) - + def get_parts(self): """Returns the list of the parts. For example, JsonPointer('/a/b').get_parts() == ['a', 'b']""" - - return self.parts + return self.parts def walk(self, doc, part): """ Walks one step in doc and returns the referenced part """ @@ -281,7 +271,7 @@ def walk(self, doc, part): return doc[part] except IndexError: - raise JsonPointerException("index '%s' is out of bounds" % (part, )) + raise JsonPointerException("index '%s' is out of bounds" % (part,)) # Else the object is a mapping or supports __getitem__(so assume custom indexing) try: @@ -290,7 +280,6 @@ def walk(self, doc, part): except KeyError: raise JsonPointerException("member '%s' not found in %s" % (part, doc)) - def contains(self, ptr): """ Returns True if self contains the given ptr """ return self.parts[:len(ptr.parts)] == ptr.parts @@ -312,9 +301,10 @@ def join(self, suffix): except: raise JsonPointerException("Invalid suffix") - def __truediv__(self, suffix): # Python 3 + def __truediv__(self, suffix): # Python 3 return self.join(suffix) - __div__ = __truediv__ # Python 2 + + __div__ = __truediv__ # Python 2 @property def path(self): @@ -342,10 +332,10 @@ def __hash__(self): return hash(tuple(self.parts)) def __str__(self): - return encode_str(self.path) + return self.path def __repr__(self): - return "JsonPointer(" + repr(self.path) + ")" + return type(self).__name__ + "(" + repr(self.path) + ")" @classmethod def from_parts(cls, parts): @@ -362,5 +352,6 @@ def from_parts(cls, parts): def escape(s): return s.replace('~', '~0').replace('/', '~1') + def unescape(s): return s.replace('~1', '/').replace('~0', '~') diff --git a/requirements-dev.txt b/requirements-dev.txt index 9fcb076..6476efe 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ wheel -twine>=1.11.0 -setuptools>=38.6.0 +twine>=5.1.0 +setuptools>=70 +coverage diff --git a/setup.py b/setup.py index 37d3657..2ab2d38 100644 --- a/setup.py +++ b/setup.py @@ -38,8 +38,6 @@ 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', @@ -65,5 +63,5 @@ py_modules=MODULES, scripts=['bin/jsonpointer'], classifiers=CLASSIFIERS, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*', + python_requires='>=3.7', ) diff --git a/tests.py b/tests.py index 6b4b8cc..7b1cdac 100755 --- a/tests.py +++ b/tests.py @@ -3,20 +3,21 @@ from __future__ import unicode_literals +import copy import doctest -import unittest import sys -import copy +import unittest + import jsonpointer from jsonpointer import resolve_pointer, EndOfList, JsonPointerException, \ - JsonPointer, set_pointer + JsonPointer, set_pointer class SpecificationTests(unittest.TestCase): """ Tests all examples from the JSON Pointer specification """ def test_example(self): - doc = { + doc = { "foo": ["bar", "baz"], "": 0, "a/b": 1, @@ -42,7 +43,6 @@ def test_example(self): self.assertEqual(resolve_pointer(doc, "/ "), 7) self.assertEqual(resolve_pointer(doc, "/m~0n"), 8) - def test_eol(self): doc = { "foo": ["bar", "baz"] @@ -165,19 +165,16 @@ def test_eq_hash(self): self.assertFalse(p1 == "/something/1/b") def test_contains(self): - self.assertTrue(self.ptr1.contains(self.ptr2)) self.assertTrue(self.ptr1.contains(self.ptr1)) self.assertFalse(self.ptr1.contains(self.ptr3)) def test_contains_magic(self): - self.assertTrue(self.ptr2 in self.ptr1) self.assertTrue(self.ptr1 in self.ptr1) self.assertFalse(self.ptr3 in self.ptr1) def test_join(self): - ptr12a = self.ptr1.join(self.ptr2) self.assertEqual(ptr12a.path, "/a/b/c/a/b") @@ -196,7 +193,6 @@ def test_join(self): self.assertRaises(JsonPointerException, self.ptr1.join, 0) def test_join_magic(self): - ptr12a = self.ptr1 / self.ptr2 self.assertEqual(ptr12a.path, "/a/b/c/a/b") @@ -212,6 +208,7 @@ def test_join_magic(self): ptr12e = self.ptr1 / ["a", "b"] self.assertEqual(ptr12e.path, "/a/b/c/a/b") + class WrongInputTests(unittest.TestCase): def test_no_start_slash(self): @@ -244,7 +241,6 @@ def test_empty_path(self): self.assertEqual(doc, last) self.assertTrue(nxt is None) - def test_path(self): doc = {'a': [{'b': 1, 'c': 2}, 5]} ptr = JsonPointer('/a/0/b') @@ -256,7 +252,7 @@ def test_path(self): class SetTests(unittest.TestCase): def test_set(self): - doc = { + doc = { "foo": ["bar", "baz"], "": 0, "a/b": 1, @@ -285,7 +281,7 @@ def test_set(self): newdoc = set_pointer(doc, "/fud", {}, inplace=False) newdoc = set_pointer(newdoc, "/fud/gaw", [1, 2, 3], inplace=False) - self.assertEqual(resolve_pointer(newdoc, "/fud"), {'gaw' : [1, 2, 3]}) + self.assertEqual(resolve_pointer(newdoc, "/fud"), {'gaw': [1, 2, 3]}) newdoc = set_pointer(doc, "", 9, inplace=False) self.assertEqual(newdoc, 9) @@ -307,14 +303,13 @@ def test_set(self): self.assertRaises(JsonPointerException, set_pointer, doc, "/fud/gaw", 9) set_pointer(doc, "/fud", {}) - set_pointer(doc, "/fud/gaw", [1, 2, 3] ) - self.assertEqual(resolve_pointer(doc, "/fud"), {'gaw' : [1, 2, 3]}) + set_pointer(doc, "/fud/gaw", [1, 2, 3]) + self.assertEqual(resolve_pointer(doc, "/fud"), {'gaw': [1, 2, 3]}) self.assertRaises(JsonPointerException, set_pointer, doc, "", 9) class AltTypesTests(unittest.TestCase): - class Node(object): def __init__(self, name, parent=None): self.name = name @@ -349,13 +344,13 @@ def __setitem__(self, key, val): class mdict(object): def __init__(self, d): self._d = d + def __getitem__(self, item): return self._d[item] mdict = mdict({'root': {'1': {'2': '3'}}}) Node = Node - def test_alttypes(self): Node = self.Node From 4601845016595bbf6f71ca962d9cf27412db4be4 Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:35:57 -0400 Subject: [PATCH 2/8] fix:github action --- .github/workflows/test.yaml | 41 ++++++++++++++++++++++++++++--------- jsonpointer.py | 9 +++----- requirements-dev.txt | 1 + setup.cfg | 4 ++++ setup.py | 13 ++++++------ 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 92afae6..693e81d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,10 +1,37 @@ name: Python package -on: [ push ] +on: + push: + branches: + - master + pull_request: + branches: + - master jobs: - build: + lint: + name: "flake8 on code" + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.ref }} + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: 3.12 + allow-prereleases: true + + - name: Run flake8 + shell: bash + run: | + flake8 + + test: + needs: [ lint ] runs-on: ubuntu-latest strategy: fail-fast: false @@ -21,14 +48,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 pytest - pip install coveralls - # - name: Lint with flake8 - # run: | - # stop the build if there are Python syntax errors or undefined names - # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + pip install -r requirements-dev.txt + - name: Test run: | make coverage diff --git a/jsonpointer.py b/jsonpointer.py index 8e878cd..f04804a 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -32,23 +32,20 @@ """ Identify specific nodes in a JSON document (RFC 6901) """ - # Will be parsed by setup.py to determine package metadata __author__ = 'Stefan Kögl ' __version__ = '3.0.0' __website__ = 'https://github.com/stefankoegl/python-json-pointer' __license__ = 'Modified BSD License' - - try: from collections.abc import Mapping, Sequence except ImportError: # Python 3 from collections import Mapping, Sequence -from itertools import tee, chain -import re import copy +import re +from itertools import tee, chain _nothing = object() @@ -298,7 +295,7 @@ def join(self, suffix): suffix_parts = suffix try: return JsonPointer.from_parts(chain(self.parts, suffix_parts)) - except: + except: # noqa E722 raise JsonPointerException("Invalid suffix") def __truediv__(self, suffix): # Python 3 diff --git a/requirements-dev.txt b/requirements-dev.txt index 6476efe..f06e81a 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,3 +2,4 @@ wheel twine>=5.1.0 setuptools>=70 coverage +flake8==7.0.0 diff --git a/setup.cfg b/setup.cfg index 2a9acf1..ab8f354 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,6 @@ [bdist_wheel] universal = 1 + +[flake8] +max-line-length = 120 +exclude = .git,.tox,dist,doc,*egg,build,.venv \ No newline at end of file diff --git a/setup.py b/setup.py index 2ab2d38..3e87a4c 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,10 @@ #!/usr/bin/env python -from setuptools import setup -import re import io import os.path +import re + +from setuptools import setup dirname = os.path.dirname(os.path.abspath(__file__)) filename = os.path.join(dirname, 'jsonpointer.py') @@ -14,7 +15,7 @@ PACKAGE = 'jsonpointer' MODULES = ( - 'jsonpointer', + 'jsonpointer', ) AUTHOR_EMAIL = metadata['author'] @@ -26,10 +27,8 @@ # Extract name and e-mail ("Firstname Lastname ") AUTHOR, EMAIL = re.match(r'(.*) <(.*)>', AUTHOR_EMAIL).groups() - with open('README.md') as readme: - long_description = readme.read() - + long_description = readme.read() CLASSIFIERS = [ 'Development Status :: 5 - Production/Stable', @@ -64,4 +63,4 @@ scripts=['bin/jsonpointer'], classifiers=CLASSIFIERS, python_requires='>=3.7', -) + ) From abad7950685c81bd03c1758fc321ec58b7010c8e Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:36:26 -0400 Subject: [PATCH 3/8] maint:add .idea to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ce09cfb..861d6b2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist *.swp doc/_build *.egg-info +.idea From 386646d765211430fcf4ffcf269f3b87ee25918c Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:38:04 -0400 Subject: [PATCH 4/8] fix:install flake8 --- .github/workflows/test.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 693e81d..fa172c1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -24,7 +24,10 @@ jobs: with: python-version: 3.12 allow-prereleases: true - + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 - name: Run flake8 shell: bash run: | From a9ae88093ec183bfd53becf847b1e31742898da5 Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:40:35 -0400 Subject: [PATCH 5/8] remove twine --- requirements-dev.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index f06e81a..7c98cef 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,4 @@ wheel -twine>=5.1.0 setuptools>=70 coverage flake8==7.0.0 From 0bc72c83915c75718b05daac9f128a4db3161fde Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:42:43 -0400 Subject: [PATCH 6/8] remove twine --- jsonpointer.py | 2 +- requirements-dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jsonpointer.py b/jsonpointer.py index f04804a..0a03ddd 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -51,7 +51,7 @@ def set_pointer(doc, pointer, value, inplace=True): - """Resolves pointer against doc and sets the value of the target within doc. + """Resolves a pointer against doc and sets the value of the target within doc. With inplace set to true, doc is modified as long as pointer is not the root. diff --git a/requirements-dev.txt b/requirements-dev.txt index 7c98cef..cff99fa 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ wheel -setuptools>=70 +setuptools>=38.6.0 coverage flake8==7.0.0 From c06953431785ca9c7b951869b9792ea3cdd4a73c Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 28 May 2024 09:43:55 -0400 Subject: [PATCH 7/8] remove twine --- requirements-dev.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index cff99fa..239fcca 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,4 @@ wheel -setuptools>=38.6.0 +setuptools coverage -flake8==7.0.0 +flake8 From cce7ed2513e4b4383f76ea300422a5a2287daf4e Mon Sep 17 00:00:00 2001 From: Daniel Moran Date: Tue, 28 May 2024 15:57:26 -0400 Subject: [PATCH 8/8] address comments --- jsonpointer.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/jsonpointer.py b/jsonpointer.py index 0a03ddd..3e97add 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -38,13 +38,9 @@ __website__ = 'https://github.com/stefankoegl/python-json-pointer' __license__ = 'Modified BSD License' -try: - from collections.abc import Mapping, Sequence -except ImportError: # Python 3 - from collections import Mapping, Sequence - import copy import re +from collections.abc import Mapping, Sequence from itertools import tee, chain _nothing = object() @@ -301,8 +297,6 @@ def join(self, suffix): def __truediv__(self, suffix): # Python 3 return self.join(suffix) - __div__ = __truediv__ # Python 2 - @property def path(self): """Returns the string representation of the pointer