|
3 | 3 | import sys |
4 | 4 | from dataclasses import dataclass |
5 | 5 | from datetime import datetime |
6 | | -from typing import Any, Dict, Mapping, Union |
| 6 | +from typing import Any, Dict, List, Mapping, Union |
7 | 7 |
|
8 | 8 | import pytest |
9 | 9 | from dirty_equals import FunctionCheck, HasRepr, IsStr |
@@ -1192,13 +1192,55 @@ class MyDataclass: |
1192 | 1192 | } |
1193 | 1193 | ) |
1194 | 1194 |
|
1195 | | - assert v.validate_python(Foobar()) == ({'a': 1, 'b': 2, 'c': 'ham'}, {'a', 'b', 'c'}) |
1196 | | - assert v.validate_python(MyDataclass()) == ({'a': 1, 'b': 2, 'c': 'ham'}, {'a', 'b', 'c'}) |
1197 | | - assert v.validate_python(Cls(a=1, b=2, c='ham')) == ({'a': 1, 'b': 2, 'c': 'ham'}, {'a', 'b', 'c'}) |
1198 | | - assert v.validate_python(Cls(a=1, b=datetime(2000, 1, 1))) == ({'a': 1, 'b': datetime(2000, 1, 1)}, {'a', 'b'}) |
| 1195 | + assert v.validate_python(Foobar()) == ({'a': 1}, {'a'}) |
| 1196 | + assert v.validate_python(MyDataclass()) == ({'a': 1}, {'a'}) |
| 1197 | + assert v.validate_python(Cls(a=1, b=2, c='ham')) == ({'a': 1}, {'a'}) |
| 1198 | + assert v.validate_python(Cls(a=1, b=datetime(2000, 1, 1))) == ({'a': 1}, {'a'}) |
1199 | 1199 | assert v.validate_python(Cls(a=1, b=datetime.now, c=lambda: 42)) == ({'a': 1}, {'a'}) |
1200 | 1200 |
|
1201 | 1201 |
|
| 1202 | +def test_from_attributes_extra_ignore_no_attributes_accessed() -> None: |
| 1203 | + v = SchemaValidator( |
| 1204 | + { |
| 1205 | + 'type': 'typed-dict', |
| 1206 | + 'fields': {'a': {'type': 'typed-dict-field', 'schema': {'type': 'int'}}}, |
| 1207 | + 'from_attributes': True, |
| 1208 | + 'extra_behavior': 'ignore', |
| 1209 | + } |
| 1210 | + ) |
| 1211 | + |
| 1212 | + accessed: List[str] = [] |
| 1213 | + |
| 1214 | + class Source: |
| 1215 | + a = 1 |
| 1216 | + b = 2 |
| 1217 | + |
| 1218 | + def __getattribute__(self, __name: str) -> Any: |
| 1219 | + accessed.append(__name) |
| 1220 | + return super().__getattribute__(__name) |
| 1221 | + |
| 1222 | + assert v.validate_python(Source()) == {'a': 1} |
| 1223 | + assert 'a' in accessed and 'b' not in accessed |
| 1224 | + |
| 1225 | + |
| 1226 | +def test_from_attributes_extra_forbid() -> None: |
| 1227 | + class Source: |
| 1228 | + a = 1 |
| 1229 | + b = 2 |
| 1230 | + |
| 1231 | + v = SchemaValidator( |
| 1232 | + { |
| 1233 | + 'type': 'typed-dict', |
| 1234 | + 'return_fields_set': True, |
| 1235 | + 'fields': {'a': {'type': 'typed-dict-field', 'schema': {'type': 'int'}}}, |
| 1236 | + 'from_attributes': True, |
| 1237 | + 'extra_behavior': 'forbid', |
| 1238 | + } |
| 1239 | + ) |
| 1240 | + |
| 1241 | + assert v.validate_python(Source()) == ({'a': 1}, {'a'}) |
| 1242 | + |
| 1243 | + |
1202 | 1244 | def foobar(): |
1203 | 1245 | pass |
1204 | 1246 |
|
|
0 commit comments