(context: Any, key: str, value: Any)
| 28 | |
| 29 | |
| 30 | def interpret(context: Any, key: str, value: Any) -> Any: |
| 31 | cursor = context |
| 32 | paths = list(parse(key)) |
| 33 | paths.append(Path(PathAction.SET, value)) |
| 34 | |
| 35 | # noinspection PyShadowingNames |
| 36 | def type_check(index: int, path: Path, expected_type: JSONType): |
| 37 | if not isinstance(cursor, expected_type): |
| 38 | if path.tokens: |
| 39 | pseudo_token = Token( |
| 40 | kind=TokenKind.PSEUDO, |
| 41 | value='', |
| 42 | start=path.tokens[0].start, |
| 43 | end=path.tokens[-1].end, |
| 44 | ) |
| 45 | else: |
| 46 | pseudo_token = None |
| 47 | cursor_type = JSON_TYPE_MAPPING.get(type(cursor), type(cursor).__name__) |
| 48 | required_type = JSON_TYPE_MAPPING[expected_type] |
| 49 | message = f'Cannot perform {path.kind.to_string()!r} based access on ' |
| 50 | message += repr(''.join(path.reconstruct() for path in paths[:index])) |
| 51 | message += f' which has a type of {cursor_type!r} but this operation' |
| 52 | message += f' requires a type of {required_type!r}.' |
| 53 | raise NestedJSONSyntaxError( |
| 54 | source=key, |
| 55 | token=pseudo_token, |
| 56 | message=message, |
| 57 | message_kind='Type', |
| 58 | ) |
| 59 | |
| 60 | def object_for(kind: PathAction) -> Any: |
| 61 | if kind is PathAction.KEY: |
| 62 | return {} |
| 63 | elif kind in {PathAction.INDEX, PathAction.APPEND}: |
| 64 | return [] |
| 65 | else: |
| 66 | assert_cant_happen() |
| 67 | |
| 68 | for index, (path, next_path) in enumerate(zip(paths, paths[1:])): |
| 69 | # If there is no context yet, set it. |
| 70 | if cursor is None: |
| 71 | context = cursor = object_for(path.kind) |
| 72 | if path.kind is PathAction.KEY: |
| 73 | type_check(index, path, dict) |
| 74 | if next_path.kind is PathAction.SET: |
| 75 | cursor[path.accessor] = next_path.accessor |
| 76 | break |
| 77 | cursor = cursor.setdefault(path.accessor, object_for(next_path.kind)) |
| 78 | elif path.kind is PathAction.INDEX: |
| 79 | type_check(index, path, list) |
| 80 | if path.accessor < 0: |
| 81 | raise NestedJSONSyntaxError( |
| 82 | source=key, |
| 83 | token=path.tokens[1], |
| 84 | message='Negative indexes are not supported.', |
| 85 | message_kind='Value', |
| 86 | ) |
| 87 | cursor.extend([None] * (path.accessor - len(cursor) + 1)) |
no test coverage detected