Accepting request 691614 from devel:languages:python
OBS-URL: https://build.opensuse.org/request/show/691614 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-jmespath?expand=0&rev=15
This commit is contained in:
commit
2539fe4dfb
@ -5,6 +5,15 @@ Tue Mar 26 14:43:27 UTC 2019 - Tomáš Chvátal <tchvatal@suse.com>
|
||||
* Fix min_by/max_by with empty lists (`issue 151)
|
||||
* Fix reverse type for null type (issue 145)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 18 06:06:26 UTC 2019 - John Vandenberg <jayvdb@gmail.com>
|
||||
|
||||
- Add extra testing with hypothesis
|
||||
- Remove unnecessary dependency on python-base
|
||||
- Update to v0.9.4
|
||||
* Fix min_by/max_by with empty lists
|
||||
* Fix reverse type for null type
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Dec 4 12:49:31 UTC 2018 - Matej Cepl <mcepl@suse.com>
|
||||
|
||||
|
@ -23,16 +23,17 @@ Release: 0
|
||||
Summary: Python module for declarative JSON document element extraction
|
||||
License: MIT
|
||||
Group: Development/Languages/Python
|
||||
URL: https://github.com/boto/jmespath
|
||||
URL: https://github.com/jmespath/jmespath.py
|
||||
Source: https://files.pythonhosted.org/packages/source/j/jmespath/jmespath-%{version}.tar.gz
|
||||
Source1: https://raw.githubusercontent.com/jmespath/jmespath.py/develop/extra/test_hypothesis.py
|
||||
# Testing
|
||||
BuildRequires: %{python_module hypothesis}
|
||||
BuildRequires: %{python_module nose}
|
||||
BuildRequires: %{python_module ply >= 3.4}
|
||||
BuildRequires: %{python_module setuptools}
|
||||
BuildRequires: %{python_module simplejson}
|
||||
BuildRequires: fdupes
|
||||
BuildRequires: python-rpm-macros
|
||||
Requires: python-base
|
||||
Requires: python-ply >= 3.4
|
||||
Requires: python-simplejson
|
||||
Requires(post): update-alternatives
|
||||
@ -73,6 +74,7 @@ The expression: foo.*.name will return ["one", "two"].
|
||||
|
||||
%prep
|
||||
%setup -q -n jmespath-%{version}
|
||||
cp %{SOURCE1} .
|
||||
|
||||
%build
|
||||
%python_build
|
||||
@ -84,7 +86,9 @@ mv %{buildroot}%{_bindir}/jp.py %{buildroot}%{_bindir}/jp
|
||||
%python_expand %fdupes %{buildroot}%{$python_sitelib}
|
||||
|
||||
%check
|
||||
%python_expand nosetests-%{$python_bin_suffix} tests
|
||||
%{python_expand $python setup.py test
|
||||
$python test_hypothesis.py
|
||||
}
|
||||
|
||||
%post
|
||||
%python_install_alternative jp
|
||||
|
140
test_hypothesis.py
Normal file
140
test_hypothesis.py
Normal file
@ -0,0 +1,140 @@
|
||||
# Test suite using hypothesis to generate test cases.
|
||||
# This is in a standalone module so that these tests
|
||||
# can a) be run separately and b) allow for customization
|
||||
# via env var for longer runs in travis.
|
||||
import os
|
||||
import sys
|
||||
import numbers
|
||||
|
||||
from nose.plugins.skip import SkipTest
|
||||
from hypothesis import given, settings, assume, HealthCheck
|
||||
import hypothesis.strategies as st
|
||||
|
||||
from jmespath import lexer
|
||||
from jmespath import parser
|
||||
from jmespath import exceptions
|
||||
from jmespath.functions import Functions
|
||||
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
raise RuntimeError("Hypothesis tests are not supported on python2.6. "
|
||||
"Use python2.7, or python3.3 and greater.")
|
||||
|
||||
|
||||
JSON_NUMBERS = (st.integers() | st.floats(allow_nan=False,
|
||||
allow_infinity=False))
|
||||
|
||||
RANDOM_JSON = st.recursive(
|
||||
JSON_NUMBERS | st.booleans() | st.text() | st.none(),
|
||||
lambda children: st.lists(children) | st.dictionaries(st.text(), children)
|
||||
)
|
||||
|
||||
MAX_EXAMPLES = int(os.environ.get('JP_MAX_EXAMPLES', 1000))
|
||||
BASE_SETTINGS = {
|
||||
'max_examples': MAX_EXAMPLES,
|
||||
'suppress_health_check': [HealthCheck.too_slow],
|
||||
}
|
||||
|
||||
|
||||
# For all of these tests they verify these properties:
|
||||
# either the operation succeeds or it raises a JMESPathError.
|
||||
# If any other exception is raised then we error out.
|
||||
@settings(**BASE_SETTINGS)
|
||||
@given(st.text())
|
||||
def test_lexer_api(expr):
|
||||
try:
|
||||
tokens = list(lexer.Lexer().tokenize(expr))
|
||||
except exceptions.EmptyExpressionError:
|
||||
return
|
||||
except exceptions.LexerError as e:
|
||||
assert e.lex_position >= 0, e.lex_position
|
||||
assert e.lex_position < len(expr), e.lex_position
|
||||
if expr:
|
||||
assert expr[e.lex_position] == e.token_value[0], (
|
||||
"Lex position does not match first token char.\n"
|
||||
"Expression: %s\n%s != %s" % (expr, expr[e.lex_position],
|
||||
e.token_value[0])
|
||||
)
|
||||
return
|
||||
except Exception as e:
|
||||
raise AssertionError("Non JMESPathError raised: %s" % e)
|
||||
assert isinstance(tokens, list)
|
||||
# Token starting positions must be unique, can't have two
|
||||
# tokens with the same start position.
|
||||
start_locations = [t['start'] for t in tokens]
|
||||
assert len(set(start_locations)) == len(start_locations), (
|
||||
"Tokens must have unique starting locations.")
|
||||
# Starting positions must be increasing (i.e sorted).
|
||||
assert sorted(start_locations) == start_locations, (
|
||||
"Tokens must have increasing start locations.")
|
||||
# Last token is always EOF.
|
||||
assert tokens[-1]['type'] == 'eof'
|
||||
|
||||
|
||||
@settings(**BASE_SETTINGS)
|
||||
@given(st.text())
|
||||
def test_parser_api_from_str(expr):
|
||||
# Same a lexer above with the assumption that we're parsing
|
||||
# a valid sequence of tokens.
|
||||
try:
|
||||
list(lexer.Lexer().tokenize(expr))
|
||||
except exceptions.JMESPathError as e:
|
||||
# We want to try to parse things that tokenize
|
||||
# properly.
|
||||
assume(False)
|
||||
try:
|
||||
ast = parser.Parser().parse(expr)
|
||||
except exceptions.JMESPathError as e:
|
||||
return
|
||||
except Exception as e:
|
||||
raise AssertionError("Non JMESPathError raised: %s" % e)
|
||||
assert isinstance(ast.parsed, dict)
|
||||
assert 'type' in ast.parsed
|
||||
assert 'children' in ast.parsed
|
||||
assert isinstance(ast.parsed['children'], list)
|
||||
|
||||
|
||||
@settings(**BASE_SETTINGS)
|
||||
@given(expr=st.text(), data=RANDOM_JSON)
|
||||
def test_search_api(expr, data):
|
||||
try:
|
||||
ast = parser.Parser().parse(expr)
|
||||
except exceptions.JMESPathError as e:
|
||||
# We want to try to parse things that tokenize
|
||||
# properly.
|
||||
assume(False)
|
||||
try:
|
||||
ast.search(data)
|
||||
except exceptions.JMESPathError as e:
|
||||
return
|
||||
except Exception as e:
|
||||
raise AssertionError("Non JMESPathError raised: %s" % e)
|
||||
|
||||
|
||||
# Additional property tests for functions.
|
||||
|
||||
@given(arg=JSON_NUMBERS)
|
||||
def test_abs(arg):
|
||||
assert Functions().call_function('abs', [arg]) >= 0
|
||||
|
||||
|
||||
@given(arg=st.lists(JSON_NUMBERS))
|
||||
def test_avg(arg):
|
||||
result = Functions().call_function('avg', [arg])
|
||||
if result is not None:
|
||||
assert isinstance(result, numbers.Number)
|
||||
|
||||
|
||||
@given(arg=st.lists(st.floats() | st.booleans() | st.text() | st.none(),
|
||||
min_size=1))
|
||||
def test_not_null(arg):
|
||||
result = Functions().call_function('not_null', arg)
|
||||
if result is not None:
|
||||
assert result in arg
|
||||
|
||||
|
||||
@given(arg=RANDOM_JSON)
|
||||
def test_to_number(arg):
|
||||
result = Functions().call_function('to_number', [arg])
|
||||
if result is not None:
|
||||
assert isinstance(result, numbers.Number)
|
Loading…
Reference in New Issue
Block a user