def test_a_k_k_a_k_k_k_a_multiple_has(a_k_k_a_k_k_k_a): expected_trace_messages = [ " at $[0] got {'x': {'x': [{'x': {...", " has .x got {'x': [{'x': {'x': {...", " has .x.x got [{'x': {'x': {'x': [...", " has .x.x[1] got {'x': {'x': {'x': ['...", " at $[0][has($.x.x[1])] got {'x': {'x': [{'x': {...", " at $[0].y got {'x': [{'x': {'x': {...", " at $[0].y.y got [{'x': {'x': {'x': [...", " at $[0].y.y[0] got {'x': {'x': {'x': ['...", " has .x got {'x': {'x': ['973', ...", " has .x.x got {'x': ['973', '974',...", " has .z got ['979', '980', '981'...", " has .x.x[has($.z)] got {'x': ['973', '974',...", " has .x.x.x got ['973', '974', '975'...", " has .x.x.x[1] got '974'", " at $[0].y.y[0][has($.x.x[has($.z)].x[1])] got {'x': {'x': {'x': ['...", " at $[0].y.y[0].y got {'x': {'x': ['1000',...", " at $[0].y.y[0].y.y got {'x': ['1009', '1010...", " at $[0].y.y[0].y.y.y got ['1012', '1013', '10...", " at $[0].y.y[0].y.y.y[0] got '1012'" ] actual_trace_messages = [] def mock_print(message): actual_trace_messages.append(message) a = get(path[0][has(path.x.x[1])].y.y[0][has(path.x.x[has( path.z)].x[1])].y.y.y[0], a_k_k_a_k_k_k_a, trace=log_to(mock_print)) assert a == '1012' assert actual_trace_messages == expected_trace_messages
def test_PathSyntaxError_validate_message(keys): expected = "PathSyntaxError(Invalid path [<class 'int'>] argument. Expecting PathBuilderPredicate, " \ f"PathPredicate, or Callable[[Match], Any]])" with pytest.raises(PathSyntaxError) as exc_info: has(1) assert repr(exc_info.value) == expected
def test_path_has_filter_type_conversion(solar_system): """### has filter type conversion""" # Sometimes the value is the wrong type for the comparison operator. In this example the attribute # "Number of Moons" is str type. planets = [planet for planet in find(path.rec[has(path["Number of Moons"] > "5")].name, solar_system)] assert planets == ['Jupiter', 'Saturn'] # This is how to convert the type to an int before applying the comparison operator. planets = [planet for planet in find(path.rec[has(path["Number of Moons"] > 5, int)].name, solar_system)] assert planets == ['Jupiter', 'Saturn', 'Uranus', 'Neptune']
def test_set_a_to_1_predicate(): actual = {"a": 0, "x": 2} expected_return = 1 expected = {"a": 1, "x": 2} actual_return = set_(path[has(path.a == 0)].a, 1, actual) assert actual == expected assert actual_return == expected_return
def test_pop_match_0_predicate(): actual = [1, 2] expected_return = '$[0]=1' expected = [2] actual_return = pop_match(path[has(path[0] == 1)][0], actual) assert actual == expected assert repr(actual_return) == expected_return
def test_pop_match_a_predicate(): actual = {"a": 0, "x": 2} expected_return = '$.a=0' expected = {"x": 2} actual_return = pop_match(path[has(path.a == 0)].a, actual) assert actual == expected assert repr(actual_return) == expected_return
def test_pop_0_predicate_default(): actual = [1, 2] expected_return = 0 expected = [1, 2] actual_return = pop(path[has(path.a == 1)].a, actual, default=0) assert actual == expected assert actual_return == expected_return
def test_pop_a_predicate_default(): actual = {"a": 0, "x": 2} expected_return = 0 expected = {"a": 0, "x": 2} actual_return = pop(path[has(path.a == 1)].a, actual, default=0) assert actual == expected assert actual_return == expected_return
def test_pop_0_predicate(): actual = [1, 2] expected_return = 1 expected = [2] actual_return = pop(path[has(path[0] == 1)][0], actual) assert actual == expected assert actual_return == expected_return
def test_root_a_has_b_three_func(): expected = f"$.a[has($.b, {test_root_a_has_b_three_func}, " \ f"{test_root_a_has_b_three_func}, " \ f"{test_root_a_has_b_three_func})]" actual = str(path.a[has(path.b, test_root_a_has_b_three_func, test_root_a_has_b_three_func, test_root_a_has_b_three_func)]) assert actual == expected
def test_pop_a_predicate_match_not_found(): actual = {"a": 0, "x": 2} expected_error_message = 'MatchNotFoundError(No get_match occurred on path: $[has($.a == 1)].a)' expected = {"a": 0, "x": 2} with pytest.raises(MatchNotFoundError) as exc_info: pop(path[has(path.a == 1)].a, actual) assert actual == expected assert repr(exc_info.value) == expected_error_message
def test_3d_list_match_all_all_has_1(three_dimensional_list): exp_iter = find_matches(path.rec[has(path[1])], three_dimensional_list) count = 0 for expected_path, expected_value in gen_test_data(three_dimensional_list, yria, yaia, yaia): count += 1 actual = next(exp_iter) assert repr(actual) == f"{expected_path}={expected_value}" assert count == 13 assert_done_iterating(exp_iter)
def my_neighbor_is_earth(match: Match): i_am_planet = get_match(path.parent.parent.parent.planets, match, must_match=False) if not i_am_planet: return False index_before_planet = match.data_name - 1 before_planet = get_match(path[index_before_planet][has(path.name == "Earth")], match.parent, must_match=False) if before_planet: return True index_after_planet = match.data_name + 1 before_planet = get_match(path[index_after_planet][has(path.name == "Earth")], match.parent, must_match=False) if before_planet: return True return False
def test_keys_match_all_all_has_x(keys): exp_iter = find_matches(path.rec[has(path.x)], keys) count = 0 for expected_path, expected_value in gen_test_data(keys, yria, yaia, yaia): count += 1 actual = next(exp_iter) assert repr(actual) == f"{expected_path}={expected_value}" assert count == 13 assert_done_iterating(exp_iter)
def test_path_has_filter(solar_system): """### has filter""" # The **has** function is a filter that evaluates a branched off path relative to its parent path. This example # finds all celestial bodies that have planets. sun = get(path.rec[has(path.planets)].name, solar_system) assert sun == "Sun" # This search finds all celestial bodies that have a has-moons attribute. all_celestial_bodies_moon_attribute = [planet for planet in find(path.rec[has(pathd.has_moons)].name, solar_system)] assert all_celestial_bodies_moon_attribute == ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] # This search finds all celestial bodies that have moons. Note the **operator.truth** is used to exclude planets # that don't have moons. all_celestial_bodies_moon_attribute = [planet for planet in find(path.rec[has(pathd.has_moons, operator.truth)].name, solar_system)] assert all_celestial_bodies_moon_attribute == ['Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
def test_path_root(solar_system): """## The root""" # The **path** point to root of the tree. match = get_match(path, solar_system) assert match.data == solar_system # In a filter path point to the current element. match = get_match(path.star.name[has(path == 'Sun')], solar_system) assert match.data == 'Sun'
def test_3d_list_match_all_all_has_1_eq_1(three_dimensional_list): exp_iter = find_matches(path.rec[1][has(path.rec[1] == 14)], three_dimensional_list) actual = next(exp_iter) expected = get_match(path[1], three_dimensional_list) assert repr(actual) == repr(expected) actual = next(exp_iter) expected = get_match(path[1][1], three_dimensional_list) assert repr(actual) == repr(expected) assert_done_iterating(exp_iter)
def test_keys_match_all_all_has_x_eq_1(keys): exp_iter = find_matches(path.rec.x[has(path.rec.x == "1")], keys) actual = next(exp_iter) expected = get_match(path.x, keys) assert repr(actual) == repr(expected) actual = next(exp_iter) expected = get_match(path.x.x, keys) assert repr(actual) == repr(expected) assert_done_iterating(exp_iter)
def test_path_has_filter_operators_as_single_argument_functions(solar_system): """### has filter comparison operators as single argument functions""" # A filter operator can be specified as a single argument function. Here an example that searches for planets that # have the same diameter as earth. earths_diameter = partial(operator.eq, 12756) earth = [planet for planet in find(path.rec[has(path.diameter, earths_diameter)].name, solar_system)] assert earth == ['Earth'] # Any single argument function can be used as an operator. This example uses a Regular Expression to finds # planets that end with s. name_ends_with_s = re.compile(r"\w+s").match earth = [planet for planet in find(path.rec[has(path.name, name_ends_with_s)].name, solar_system)] assert earth == ['Venus', 'Mars', 'Uranus'] # This example uses a closure to find planets that have the same diameter as earth. def smaller_than_earth(value): return value < 12756 earth = [planet for planet in find(path.rec[has(path.diameter, smaller_than_earth)].name, solar_system)] assert earth == ['Mercury', 'Venus', 'Mars']
def test_keys_find_z_y_has_a_then_no_match_trace(keys): expected_trace_messages = [ " at $.z got {'x': {'x': '19', 'y...", " at $.z.y got {'x': '22', 'y': '23...", ' has .a got no match', ' at $.z.y[has($.a)] got no match' ] actual_trace_messages = [] def mock_print(message): actual_trace_messages.append(message) for _ in find(path.z.y[has(path.a)].x, keys, trace=log_to(mock_print)): pass assert actual_trace_messages == expected_trace_messages
def test_keys_find_z_y_has_z_then_x_trace(keys): expected_trace_messages = [ " at $.z got {'x': {'x': '19', 'y...", " at $.z.y got {'x': '22', 'y': '23...", " has .z got '24'", " at $.z.y[has($.z)] got {'x': '22', 'y': '23...", " at $.z.y.x got '22'" ] actual_trace_messages = [] def mock_print(message): actual_trace_messages.append(message) for _ in find(path.z.y[has(path.z)].x, keys, trace=log_to(mock_print)): pass assert actual_trace_messages == expected_trace_messages
def test_keys_find_x_has_x_eq_1_and_has_y_trace(keys): expected_trace_messages = [ " at $.x got {'x': {'x': '1', 'y'...", " has .z got {'x': '7', 'y': '8',...", " at $.x[has($.z)] got {'x': {'x': '1', 'y'...", " at $.x.x got {'x': '1', 'y': '2',...", " has .x got '1'", " has .y got '2'", " at $.x.x[has($.x == 1, <class 'int'>), has($.y)] got {'x': '1', 'y': " "'2',...", " at $.x.x.x got '1'" ] actual_trace_messages = [] def mock_print(message): actual_trace_messages.append(message) @has.these((path.x == 1, int), path.y) def predicate(parent_match: Match, x, y) -> Any: return x(parent_match) and y(parent_match) compiled_one = path.x[has(path.z)].x[predicate].x get(compiled_one, keys, trace=log_to(mock_print)) assert actual_trace_messages == expected_trace_messages
def test_path_has_filter_comparison_operators(solar_system): """### has filter comparison operators""" # Filters can be specified with a comparison operator. earth = [planet for planet in find(path.rec[has(path.diameter == 12756)].name, solar_system)] assert earth == ['Earth'] earth = [planet for planet in find(path.rec[has(path.diameter != 12756)].name, solar_system)] assert earth == ['Sun', 'Mercury', 'Venus', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] earth = [planet for planet in find(path.rec[has(path.diameter > 12756)].name, solar_system)] assert earth == ['Sun', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] earth = [planet for planet in find(path.rec[has(path.diameter >= 12756)].name, solar_system)] assert earth == ['Sun', 'Earth', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] earth = [planet for planet in find(path.rec[has(path.diameter < 12756)].name, solar_system)] assert earth == ['Mercury', 'Venus', 'Mars'] earth = [planet for planet in find(path.rec[has(path.diameter <= 12756)].name, solar_system)] assert earth == ['Mercury', 'Venus', 'Earth', 'Mars']
def test_root_a_has_b_two_func(): expected = f"$.a[has($.b, {float}, {float})]" actual = str(path.a[has(path.b, float, float)]) assert actual == expected
def get_planet_by_name(name: str, the_solar_system): return get( path.star.planets.wc[wc][has(path.name == name)], the_solar_system, default=None )
def test_query_examples_list_planets_smaller_than_earth(solar_system): planets_smaller_than_earth = [p for p in find(path.star.planets.inner[wc][has(path.diameter < 12756)], solar_system)] assert planets_smaller_than_earth == [solar_system["star"]["planets"]["inner"][0], solar_system["star"]["planets"]["inner"][1], solar_system["star"]["planets"]["inner"][3]]
def test_query_examples_list_celestial_bodies_that_have_planets(solar_system): sun = [p for p in find(path.rec[has(path.planets)].name, solar_system)] assert sun == ['Sun']
def test_root_a_has_b_ge(): expected = "$.a[has($.b >= 1)]" actual = str(path.a[has(path.b >= 1)]) assert actual == expected
def test_keys_eq(keys): expected = ["14"] actual = [v for v in find(path.wc.wc.wc[has(path == 14, int)], keys)] assert actual == expected
def test_root_a_has_b_eq_one_func(): expected = f"$.a[has($.b == 1, {int})]" actual = str(path.a[has(path.b == 1, int)]) assert actual == expected