From 6eb59b5aed2dcea6a53632c5edba839bd11c7183 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Sun, 16 Feb 2025 11:01:25 -0700 Subject: [PATCH 1/4] ci: py 3.12 + 3.12 test runs --- .github/workflows/run-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d3ed162..69f7c89 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,12 +9,12 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11-dev"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.12", "3.13"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From 8eeff110209d5c5c179d268c6c18e086342dee9e Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Fri, 18 Jul 2025 10:38:43 -0600 Subject: [PATCH 2/4] Add support for Python 3.12-14 and remove support for Python 3.7-8 --- .github/workflows/run-tests.yml | 2 +- setup.py | 7 ++++--- tox.ini | 16 +++------------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 69f7c89..efe53ce 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14-dev"] steps: - uses: actions/checkout@v4 diff --git a/setup.py b/setup.py index 2b2f1ef..d12f4d6 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ scripts=['bin/jp.py'], packages=find_packages(exclude=['tests']), license='MIT', - python_requires='>=3.7', + python_requires='>=3.9', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', @@ -24,11 +24,12 @@ 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', ], diff --git a/tox.ini b/tox.ini index 3184836..1a73dab 100644 --- a/tox.ini +++ b/tox.ini @@ -1,17 +1,7 @@ [tox] -envlist = py26,py27,py33,py34,py35,py36,py37,pypy +envlist = py39,py310,py311,py312,py313,py314 [testenv] -commands = nosetests +commands = python -m pytest tests deps = - nose - mock - -[testenv:py26] -commands = nosetests -deps = - nose - mock - unittest2 - ordereddict - simplejson + pytest From 8d5d19390454f4d31ae41098caabf82fa8a02965 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Fri, 18 Jul 2025 10:50:14 -0600 Subject: [PATCH 3/4] Update testing/dependencies to support Python 3.12+ --- .github/workflows/run-tests.yml | 7 ++++--- requirements.txt | 13 ++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index efe53ce..2672165 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -7,6 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [ubuntu-latest] python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14-dev"] @@ -19,10 +20,10 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - pip install pip==20.0.2 + pip install pip==25.1.0 pip install -r requirements.txt - python setup.py bdist_wheel + python -m build --wheel pip install dist/*.whl - name: Test with pytest run: | - cd tests/ && py.test --cov jmespath --cov-report term-missing + cd tests/ && python -m pytest --cov jmespath --cov-report term-missing diff --git a/requirements.txt b/requirements.txt index bd50c2a..105cf68 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,9 @@ -wheel==0.38.1 -pytest==6.2.5 +wheel==0.45.1 +pytest==8.4.1 pytest-cov==3.0.0 -hypothesis==3.1.0 ; python_version < '3.8' -hypothesis==5.5.4 ; python_version == '3.8' -hypothesis==5.35.4 ; python_version == '3.9' +hypothesis==5.35.4 + +# Setuptools is no longer provided by default in Python 3.12+ +setuptools==71.1.0 ; python_version >= '3.12' +packaging==24.1 ; python_version >= '3.12' +build==1.2.2.post1 From 900dd00c8504d3f6bced4ff545ea5d953e736f10 Mon Sep 17 00:00:00 2001 From: Nate Prewitt Date: Fri, 18 Jul 2025 12:03:22 -0600 Subject: [PATCH 4/4] Add lock for cache eviction --- jmespath/parser.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/jmespath/parser.py b/jmespath/parser.py index 4706688..faebf8d 100644 --- a/jmespath/parser.py +++ b/jmespath/parser.py @@ -26,6 +26,7 @@ """ import random +import threading from jmespath import lexer from jmespath.compat import with_repr_method @@ -74,6 +75,7 @@ class Parser(object): # _CACHE dict. _CACHE = {} _MAX_SIZE = 128 + _CACHE_LOCK = threading.Lock() def __init__(self, lookahead=2): self.tokenizer = None @@ -87,7 +89,7 @@ def parse(self, expression): return cached parsed_result = self._do_parse(expression) self._CACHE[expression] = parsed_result - if len(self._CACHE) > self._MAX_SIZE: + if self._is_cache_full(): self._free_cache_entries() return parsed_result @@ -488,9 +490,15 @@ def _raise_parse_error_maybe_eof(self, expected_type, token): raise exceptions.ParseError( lex_position, actual_value, actual_type, message) + def _is_cache_full(self): + return len(self._CACHE) > self._MAX_SIZE + def _free_cache_entries(self): - for key in random.sample(list(self._CACHE.keys()), int(self._MAX_SIZE / 2)): - self._CACHE.pop(key, None) + with self._CACHE_LOCK: + if self._is_cache_full(): + cache_keys = list(self._CACHE.keys()) + for key in random.sample(cache_keys, int(len(cache_keys)/2)): + self._CACHE.pop(key, None) @classmethod def purge(cls):