|
6 | 6 | # >> IMPORTS
|
7 | 7 | # =============================================================================
|
8 | 8 | # Python Imports
|
| 9 | +# Codecs |
| 10 | +import codecs |
9 | 11 | # Collections
|
10 | 12 | from collections import defaultdict
|
| 13 | +# Contextlib |
| 14 | +from contextlib import contextmanager |
11 | 15 | # Inspect
|
12 | 16 | from inspect import getmodule
|
13 | 17 | from inspect import stack
|
|
33 | 37 | from paths import GAME_PATH
|
34 | 38 |
|
35 | 39 |
|
| 40 | + |
36 | 41 | # =============================================================================
|
37 | 42 | # >> FORWARD IMPORTS
|
38 | 43 | # =============================================================================
|
|
57 | 62 | 'console_message',
|
58 | 63 | 'echo_console',
|
59 | 64 | 'get_interface',
|
| 65 | + 'ignore_unicode_errors', |
60 | 66 | )
|
61 | 67 |
|
62 | 68 |
|
@@ -156,3 +162,44 @@ def echo_console(text):
|
156 | 162 | """
|
157 | 163 | for line in text.split('\n'):
|
158 | 164 | console_message(line + '\n')
|
| 165 | + |
| 166 | +@contextmanager |
| 167 | +def ignore_unicode_errors(errors='ignore'): |
| 168 | + """Overwrite the ``strict`` codecs error handler temporarily. |
| 169 | +
|
| 170 | + This is useful e.g. if the engine truncates a string, which results in a |
| 171 | + string that contains a splitted multi-byte character at the end of the |
| 172 | + string. |
| 173 | +
|
| 174 | + :param str errors: |
| 175 | + Error handler that will be looked up via :func:`codecs.lookup_error`. |
| 176 | + :raise LookupError: |
| 177 | + Raised if the error handler was not found. |
| 178 | +
|
| 179 | + Example: |
| 180 | +
|
| 181 | + .. code:: python |
| 182 | +
|
| 183 | + import memory |
| 184 | +
|
| 185 | + # Allocate four bytes to create an erroneous string |
| 186 | + ptr = memory.alloc(4) |
| 187 | +
|
| 188 | + # Write data to the memory that will usually result in a |
| 189 | + # UnicodeDecodeError |
| 190 | + ptr.set_uchar(ord('a'), 0) |
| 191 | + ptr.set_uchar(ord('b'), 1) |
| 192 | + ptr.set_uchar(226, 2) # Add the invalid byte |
| 193 | + ptr.set_uchar(0, 3) # Indicate the end of the string |
| 194 | +
|
| 195 | + with ignore_unicode_errors(): |
| 196 | + # Read the data as a string. Now, it will only print 'ab', because |
| 197 | + # the invalid byte has been removed/ignored. |
| 198 | + print(ptr.get_string_array()) |
| 199 | + """ |
| 200 | + old_handler = codecs.lookup_error('strict') |
| 201 | + codecs.register_error('strict', codecs.lookup_error(errors)) |
| 202 | + try: |
| 203 | + yield |
| 204 | + finally: |
| 205 | + codecs.register_error('strict', old_handler) |
0 commit comments