|
| 1 | +from collections import defaultdict |
1 | 2 | from typing import Any, NamedTuple |
2 | 3 |
|
3 | 4 | import pytest |
4 | 5 |
|
5 | 6 | from filterpath import get |
| 7 | +from filterpath._exceptions import NotPathLikeError |
6 | 8 |
|
7 | 9 |
|
8 | 10 | class SomeNamedTuple(NamedTuple): |
@@ -43,11 +45,9 @@ def __init__(self, **attrs): |
43 | 45 | ({"one": ["two", {"three": [4, 5]}]}, (["one", 1, "three", 1],), 5), |
44 | 46 | ({"one": ["two", {"three": [4, 5]}]}, ("one.1.three.1",), 5), |
45 | 47 | ({"one": ["two", {"three": [4, 5]}]}, ("one.1.three",), [4, 5]), |
46 | | - ({"one": ["two", {"three": [4, 5]}]}, ("one.1.three.1",), 5), |
47 | 48 | (["one", {"two": {"three": [4, 5]}}], ("1.two.three.0",), 4), |
48 | 49 | (["one", {"two": {"three": [4, [{"four": [5]}]]}}], ("1.two.three.1.0.four.0",), 5), |
49 | 50 | (["one", {"two": {"three[1]": [4, [{"four": [5]}]]}}], ("1.two.three[1].0",), 4), |
50 | | - (["one", {"two": {"three": [4, [{"four": [5]}]]}}], ("1.two.three.1.0.four.0",), 5), |
51 | 51 | (["one", {"two": {"three": [4, [{"four": [5]}], 6]}}], ("1.two.three.-2.0.four.0",), 5), |
52 | 52 | (range(50), ("42",), 42), |
53 | 53 | (range(50), ("-1",), 49), |
@@ -97,3 +97,82 @@ def __init__(self, **attrs): |
97 | 97 | ) |
98 | 98 | def test_get(obj, args, expected): |
99 | 99 | assert get(obj, *args) == expected |
| 100 | + |
| 101 | + |
| 102 | +@pytest.mark.parametrize( |
| 103 | + ("path", "expected"), |
| 104 | + [ |
| 105 | + ("a", [1, 2, {"b": [3, 4]}, {"b": [5, 6]}]), |
| 106 | + ("0", "c"), |
| 107 | + ("a.0", 1), |
| 108 | + ("a\\.0", 11), |
| 109 | + ("a\\\\\\.0", 12), |
| 110 | + ("a\\\\.0", 13), |
| 111 | + ("\\[0]", 9), |
| 112 | + ("\\\\[0]", 10), |
| 113 | + ("a.[]", [1, 2, {"b": [3, 4]}, {"b": [5, 6]}]), |
| 114 | + ("a.b", None), |
| 115 | + ("a.[b]", []), |
| 116 | + ("a.[4]", []), |
| 117 | + ("a.4", None), |
| 118 | + ("a.[z]", []), |
| 119 | + ("a.z", None), |
| 120 | + ("a.b.[]", None), |
| 121 | + ("[]", [[1, 2, {"b": [3, 4]}, {"b": [5, 6]}], "c", 9, 10, 11, 12, [13], {":0": 99}]), |
| 122 | + ("[].[]", [1, 2, {"b": [3, 4]}, {"b": [5, 6]}, 13, 99]), |
| 123 | + ("[].[].[]", [[3, 4], [5, 6]]), |
| 124 | + ("[].[].[].[]", [3, 4, 5, 6]), |
| 125 | + ("[].[].[].[].[]", []), |
| 126 | + ("a.[0]", [1]), |
| 127 | + ("a.[].0", []), |
| 128 | + ("a.b.0", None), |
| 129 | + ("a.2.b.0", 3), |
| 130 | + ("a.3.b.0", 5), |
| 131 | + ("a.[].b", [[3, 4], [5, 6]]), |
| 132 | + ("a.[].b.0", [3, 5]), |
| 133 | + ("a.[].b.[]", [3, 4, 5, 6]), |
| 134 | + ], |
| 135 | +) |
| 136 | +def test_get_enhanced(path, expected): |
| 137 | + obj = { |
| 138 | + "a": [1, 2, {"b": [3, 4]}, {"b": [5, 6]}], |
| 139 | + 0: "c", |
| 140 | + "[0]": 9, |
| 141 | + "\\[0]": 10, |
| 142 | + "a.0": 11, |
| 143 | + "a\\.0": 12, |
| 144 | + "a\\": [13], |
| 145 | + "x": {":0": 99}, |
| 146 | + } |
| 147 | + assert get(obj, path) == expected |
| 148 | + |
| 149 | + |
| 150 | +def test_get__should_not_populate_defaultdict(): |
| 151 | + data = defaultdict(list) |
| 152 | + get(data, "a") |
| 153 | + assert data == {} |
| 154 | + |
| 155 | + |
| 156 | +@pytest.mark.parametrize( |
| 157 | + ("obj", "path"), |
| 158 | + [ |
| 159 | + (Object(), 1), |
| 160 | + (Object(), Object()), |
| 161 | + ], |
| 162 | +) |
| 163 | +def test_get__raises_type_error_for_non_pathlike(obj, path): |
| 164 | + with pytest.raises(TypeError, match="path argument must be one of 'str | list | tuple', not '.*'"): |
| 165 | + get(obj, path) |
| 166 | + |
| 167 | + |
| 168 | +@pytest.mark.parametrize( |
| 169 | + ("obj", "path"), |
| 170 | + [ |
| 171 | + ({"one": {"two": {"three": 4}}}, "one.four"), |
| 172 | + ({"one": {"two": {"three": 4}}}, "one.four.three"), |
| 173 | + ({"one": {"two": {"three": [{"a": 1}]}}}, "one.four.three.0.a"), |
| 174 | + ], |
| 175 | +) |
| 176 | +def test_get__raises_key_error_for_unfound(obj, path): |
| 177 | + with pytest.raises(KeyError, match=".* does not contain path '.*'"): |
| 178 | + get(obj, path, raise_if_unfound=True) |
0 commit comments