|
20 | 20 |
|
21 | 21 | from abc import ABC |
22 | 22 | from collections.abc import Iterable |
23 | | -from typing import TYPE_CHECKING, Any, Literal, Optional |
| 23 | +from typing import TYPE_CHECKING, Literal, Optional, Union, overload |
24 | 24 |
|
25 | 25 | from ..exception import MissingOptionalDependencyException |
26 | 26 | from ..schema import OutputFormat |
@@ -54,35 +54,46 @@ def __init__(self, schema_version: 'SchemaVersion') -> None: |
54 | 54 | # this is the def that is used for generating the documentation |
55 | 55 | super().__init__(schema_version) |
56 | 56 |
|
| 57 | + # region typing-relevant copy from parent class - needed for mypy and doc tools |
| 58 | + |
| 59 | + @overload |
| 60 | + def validate_str(self, data: str, *, all_errors: Literal[False] = ...) -> Optional[ValidationError]: |
| 61 | + ... # pragma: no cover |
| 62 | + |
| 63 | + @overload |
| 64 | + def validate_str(self, data: str, *, all_errors: Literal[True]) -> Optional[Iterable[ValidationError]]: |
| 65 | + ... # pragma: no cover |
| 66 | + |
| 67 | + def validate_str( |
| 68 | + self, data: str, *, all_errors: bool = False |
| 69 | + ) -> Union[None, ValidationError, Iterable[ValidationError]]: |
| 70 | + ... # pragma: no cover |
| 71 | + |
| 72 | + # endregion typing-relevant |
| 73 | + |
57 | 74 | if _missing_deps_error: # noqa:C901 |
58 | 75 | __MDERROR = _missing_deps_error |
59 | 76 |
|
60 | | - def validate_str(self, data: str) -> Optional[ValidationError]: |
| 77 | + def validate_str( # type:ignore[no-redef] # noqa:F811 # typing-relevant headers go first |
| 78 | + self, data: str, *, all_errors: bool = False |
| 79 | + ) -> Union[None, ValidationError, Iterable[ValidationError]]: |
61 | 80 | raise self.__MDERROR[0] from self.__MDERROR[1] |
62 | 81 |
|
63 | | - def iterate_errors(self, data: str) -> Iterable[ValidationError]: |
64 | | - raise self.__MDERROR[0] from self.__MDERROR[1] |
65 | 82 | else: |
66 | | - def iterate_errors(self, data: str) -> Iterable[ValidationError]: |
67 | | - xml_data = xml_fromstring( # nosec B320 |
68 | | - bytes(data, encoding='utf8'), |
69 | | - parser=self.__xml_parser) |
| 83 | + def validate_str( # type:ignore[no-redef] # noqa:F811 # typing-relevant headers go first |
| 84 | + self, data: str, *, all_errors: bool = False |
| 85 | + ) -> Union[None, ValidationError, Iterable[ValidationError]]: |
70 | 86 | validator = self._validator # may throw on error that MUST NOT be caught |
71 | | - validator.validate(xml_data) |
72 | | - for error in validator.error_log: |
73 | | - yield ValidationError(error) |
74 | | - |
75 | | - def validate_str(self, data: str) -> Optional[ValidationError]: |
76 | | - return self._validate_data( |
77 | | - xml_fromstring( # nosec B320 |
| 87 | + valid = validator.validate( |
| 88 | + xml_fromstring( # nosec B320 -- we use a custom prepared safe parser |
78 | 89 | bytes(data, encoding='utf8'), |
79 | 90 | parser=self.__xml_parser)) |
80 | | - |
81 | | - def _validate_data(self, data: Any) -> Optional[ValidationError]: |
82 | | - validator = self._validator # may throw on error that MUST NOT be caught |
83 | | - if not validator.validate(data): |
84 | | - return ValidationError(validator.error_log.last_error) |
85 | | - return None |
| 91 | + if valid: |
| 92 | + return None |
| 93 | + errors = validator.error_log |
| 94 | + return map(ValidationError, errors) \ |
| 95 | + if all_errors \ |
| 96 | + else ValidationError(errors.last_error) |
86 | 97 |
|
87 | 98 | __validator: Optional['XMLSchema'] = None |
88 | 99 |
|
|
0 commit comments