|
30 | 30 | from types import CodeType, EllipsisType |
31 | 31 | from typing import Optional |
32 | 32 |
|
33 | | -from xdis.codetype import Code2, Code3 |
| 33 | +from xdis.codetype import Code2, Code3, Code15 |
34 | 34 | from xdis.unmarshal import long |
35 | 35 | from xdis.version_info import PYTHON3, PYTHON_VERSION_TRIPLE, version_tuple_to_str |
36 | 36 |
|
@@ -92,7 +92,7 @@ def Ord(c): |
92 | 92 |
|
93 | 93 | class _Marshaller: |
94 | 94 | """Python marshalling routine that runs in Python 2 and Python 3. |
95 | | - We also extend to allow for xdis Code2 and Code3 types and instances. |
| 95 | + We also extend to allow for xdis Code15, Code2, and Code3 types and instances. |
96 | 96 | """ |
97 | 97 |
|
98 | 98 | dispatch = {} |
@@ -122,6 +122,9 @@ def dump(self, x) -> None: |
122 | 122 | elif isinstance(x, Code2): |
123 | 123 | self.dispatch[Code2](self, x) |
124 | 124 | return |
| 125 | + elif isinstance(x, Code15): |
| 126 | + self.dispatch[Code15](self, x) |
| 127 | + return |
125 | 128 | else: |
126 | 129 | for tp in type(x).mro(): |
127 | 130 | func = self.dispatch.get(tp) |
@@ -260,16 +263,12 @@ def dump_string(self, x) -> None: |
260 | 263 | self.w_long(len(x)) |
261 | 264 | self._write(x) |
262 | 265 |
|
263 | | - if PYTHON_VERSION_TRIPLE > (2, 5): |
264 | | - dispatch[bytes] = dump_string |
265 | | - dispatch[bytearray] = dump_string |
| 266 | + dispatch[bytes] = dump_string |
| 267 | + dispatch[bytearray] = dump_string |
266 | 268 |
|
267 | | - def dump_unicode(self, x) -> None: |
268 | | - self._write(TYPE_UNICODE) |
269 | | - if not PYTHON3 and self.python_version < (3, 0): |
270 | | - s = x.encode("utf8") |
271 | | - else: |
272 | | - s = x |
| 269 | + def dump_unicode(self, s) -> None: |
| 270 | + type_code = TYPE_STRING if self.python_version < (2, 0) else TYPE_UNICODE |
| 271 | + self._write(type_code) |
273 | 272 | self.w_long(len(s)) |
274 | 273 | self._write(s) |
275 | 274 |
|
@@ -315,6 +314,43 @@ def dump_dict(self, x) -> None: |
315 | 314 |
|
316 | 315 | dispatch[dict] = dump_dict |
317 | 316 |
|
| 317 | + def dump_code15(self, x) -> None: |
| 318 | + # Careful here: many Python 2 code objects are strings, |
| 319 | + # but Python 3 marshaling, by default, will dump strings as |
| 320 | + # unicode. Force marsaling this type as string. |
| 321 | + |
| 322 | + self._write(TYPE_CODE) |
| 323 | + self.w_short(x.co_argcount) |
| 324 | + self.w_short(x.co_nlocals) |
| 325 | + self.w_short(x.co_stacksize) |
| 326 | + self.w_short(x.co_flags) |
| 327 | + self.dump_string(x.co_code) |
| 328 | + |
| 329 | + # If running in a Python3 interpreter, some constants will get |
| 330 | + # converted from string to unicode. For now, let's see if |
| 331 | + # that's okay. |
| 332 | + self.dump(x.co_consts) |
| 333 | + |
| 334 | + # The tuple "names" in Python 1.x must have string entries |
| 335 | + self._write(TYPE_TUPLE) |
| 336 | + self.w_long(len(x.co_names)) |
| 337 | + for name in x.co_names: |
| 338 | + self.dump_string(name) |
| 339 | + |
| 340 | + # The tuple "varnames" in Python 1.x also must have string entries |
| 341 | + self._write(TYPE_TUPLE) |
| 342 | + self.w_long(len(x.co_varnames)) |
| 343 | + for name in x.co_varnames: |
| 344 | + self.dump_string(name) |
| 345 | + |
| 346 | + self.dump_string(x.co_filename) |
| 347 | + self.dump_string(x.co_name) |
| 348 | + self.w_long(x.co_firstlineno) |
| 349 | + self.dump_string(x.co_lnotab) |
| 350 | + return |
| 351 | + |
| 352 | + dispatch[Code15] = dump_code15 |
| 353 | + |
318 | 354 | def dump_code2(self, x) -> None: |
319 | 355 | # Careful here: many Python 2 code objects are strings, |
320 | 356 | # but Python 3 marshaling, by default, will dump strings as |
@@ -1103,11 +1139,15 @@ def dumps( |
1103 | 1139 | buf = [] |
1104 | 1140 | for b in buffer: |
1105 | 1141 | if isinstance(b, str) and PYTHON3: |
1106 | | - try: |
1107 | | - s2b = bytes(ord(b[j]) for j in range(len(b))) |
1108 | | - except ValueError: |
1109 | | - s2b = b.encode("utf-8") |
1110 | | - buf.append(s2b) |
| 1142 | + if python_version < (2, 0): |
| 1143 | + # Python 1.x has no notion of Unicode. It uses strings. |
| 1144 | + buf.append(b) |
| 1145 | + else: |
| 1146 | + try: |
| 1147 | + s2b = bytes(ord(b[j]) for j in range(len(b))) |
| 1148 | + except ValueError: |
| 1149 | + s2b = b.encode("utf-8") |
| 1150 | + buf.append(s2b) |
1111 | 1151 | elif isinstance(b, bytearray): |
1112 | 1152 | buf.append(str(b)) |
1113 | 1153 | else: |
|
0 commit comments