depyo 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ class PycDisassembler
17
17
  if (opCode.HasConstant) {
18
18
  argValue = opCode.Constant;
19
19
  } else if (opCode.HasName || opCode.HasLocal || opCode.HasFree) {
20
- argValue = opCode.Name;
20
+ argValue = opCode.Name || opCode.LocalName || opCode.FreeName;
21
21
  } else if (opCode.HasJumpRelative) {
22
22
  argValue = opCode.Argument;
23
23
  } else if (opCode.HasCompare) {
package/lib/PycReader.js CHANGED
@@ -93,14 +93,29 @@ const MagicToVersion = {
93
93
  0x0A0D0D33: {major: 3, minor: 6, IsUnicode: true, opcode: require('./bytecode/python_3_6')},
94
94
  0x0A0D0D41: {major: 3, minor: 7, IsUnicode: true, opcode: require('./bytecode/python_3_7')},
95
95
  0x0A0D0D42: {major: 3, minor: 7, IsUnicode: true, opcode: require('./bytecode/python_3_7')},
96
- 0x0A0D0D49: {major: 3, minor: 8, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
96
+ // Python 3.8a1 (3400) and 3.8a2 (3401) predate PEP 570 — no posonly field in marshal.
97
+ 0x0A0D0D48: {major: 3, minor: 8, preReleaseMarshal: true, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
98
+ 0x0A0D0D49: {major: 3, minor: 8, preReleaseMarshal: true, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
99
+ // 3.8a3 (3410) and later include posonly.
100
+ 0x0A0D0D52: {major: 3, minor: 8, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
101
+ 0x0A0D0D53: {major: 3, minor: 8, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
102
+ 0x0A0D0D54: {major: 3, minor: 8, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
97
103
  0x0A0D0D55: {major: 3, minor: 8, IsUnicode: true, opcode: require('./bytecode/python_3_8')},
98
104
  0x0A0D0D61: {major: 3, minor: 9, IsUnicode: true, opcode: require('./bytecode/python_3_9')},
99
105
  0x0A0D0D6F: {major: 3, minor: 10, IsUnicode: true, opcode: require('./bytecode/python_3_10')},
100
106
  0x0A0D0DA7: {major: 3, minor: 11, IsUnicode: true, opcode: require('./bytecode/python_3_11')},
101
107
  0x0A0D0DCB: {major: 3, minor: 12, IsUnicode: true, opcode: require('./bytecode/python_3_12')},
102
108
  0x0A0D0DF3: {major: 3, minor: 13, IsUnicode: true, opcode: require('./bytecode/python_3_13')},
103
- 0x0A0D0E2B: {major: 3, minor: 14, IsUnicode: true, opcode: require('./bytecode/python_3_14')}
109
+ 0x0A0D0E2B: {major: 3, minor: 14, IsUnicode: true, opcode: require('./bytecode/python_3_14')},
110
+ 0x0A0D0E4F: {major: 3, minor: 15, IsUnicode: true, opcode: require('./bytecode/python_3_15')},
111
+
112
+ // PyPy magics (shares opcode tables with matching CPython release).
113
+ // PyPy adds a handful of custom opcodes — unknowns degrade decode rather than fail.
114
+ 0x0A0DF30A: {major: 2, minor: 7, IsUnicode: true, opcode: require('./bytecode/python_2_7'), pypy: true},
115
+ 0x0A0D0030: {major: 3, minor: 2, IsUnicode: true, opcode: require('./bytecode/python_3_2'), pypy: true},
116
+ 0x0A0D0070: {major: 3, minor: 5, IsUnicode: true, opcode: require('./bytecode/python_3_5'), pypy: true},
117
+ 0x0A0D00A0: {major: 3, minor: 6, IsUnicode: true, opcode: require('./bytecode/python_3_6'), pypy: true},
118
+ 0x0A0D00F0: {major: 3, minor: 7, IsUnicode: true, opcode: require('./bytecode/python_3_7'), pypy: true}
104
119
  };
105
120
 
106
121
  const VersionAliases = {
@@ -109,6 +124,9 @@ const VersionAliases = {
109
124
 
110
125
  const VersionToInfo = {};
111
126
  for (const [magic, info] of Object.entries(MagicToVersion)) {
127
+ if (info.pypy) {
128
+ continue;
129
+ }
112
130
  const key = `${info.major}.${info.minor}`;
113
131
  const existing = VersionToInfo[key];
114
132
  const candidate = {...info, magic: Number(magic)};
@@ -626,7 +644,8 @@ class PycReader
626
644
  }
627
645
  codeObject.ArgCount = argCount;
628
646
 
629
- codeObject.PosOnlyArgCount = this.versionCompare(3, 8) >= 0 ? this.m_rdr.readUInt32() : 0;
647
+ const hasPosOnly = this.versionCompare(3, 8) >= 0 && !this.m_version?.preReleaseMarshal;
648
+ codeObject.PosOnlyArgCount = hasPosOnly ? this.m_rdr.readUInt32() : 0;
630
649
  codeObject.KWOnlyArgCount = this.versionCompare(3, 0) >= 0 ? this.m_rdr.readUInt32() : 0;
631
650
 
632
651
  codeObject.NumLocals = 0;
@@ -48,6 +48,31 @@ class PythonObject {
48
48
 
49
49
  // TODO: Refactor to use Symbol.toPrimitive() and Object.valueOf()
50
50
 
51
+ toReprString() {
52
+ if (this.ClassName === "Py_String" || this.ClassName === "Py_Unicode") {
53
+ let raw = this.Value;
54
+ if (raw == null || raw.length === 0) return '""';
55
+ raw = raw.toString();
56
+ let escaped = raw
57
+ .replace(/\\/g, '\\\\')
58
+ .replace(/\n/g, '\\n')
59
+ .replace(/\r/g, '\\r')
60
+ .replace(/\t/g, '\\t')
61
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, c =>
62
+ '\\x' + c.charCodeAt(0).toString(16).padStart(2, '0'));
63
+ let quote = '"';
64
+ if (escaped.includes('"')) {
65
+ if (!escaped.includes("'")) {
66
+ quote = "'";
67
+ } else {
68
+ escaped = escaped.replace(/"/g, '\\"');
69
+ }
70
+ }
71
+ return quote + escaped + quote;
72
+ }
73
+ return this.toString();
74
+ }
75
+
51
76
  toString()
52
77
  {
53
78
  switch(this.ClassName) {
@@ -74,8 +99,16 @@ class PythonObject {
74
99
  case "Py_Interned":
75
100
  return this.Value !== null ? this.Value.toString() : "0";
76
101
 
77
- case "Py_Float":
78
- return this.Value !== null ? `${this.Value}${Number.isInteger(this.Value) ? ".0" : ""}` : "0.0";
102
+ case "Py_Float": {
103
+ if (this.Value === null) return "0.0";
104
+ let s = `${this.Value}`;
105
+ // Python rejects `1e+300.0`; only append `.0` when the
106
+ // printed form is pure digits (optional sign).
107
+ if (/^-?\d+$/.test(s)) {
108
+ s += ".0";
109
+ }
110
+ return s;
111
+ }
79
112
 
80
113
  case "Py_VeryLong":
81
114
  if (this.Value) {
@@ -123,10 +156,11 @@ class PythonObject {
123
156
  let res = "(";
124
157
  if (this.Value) {
125
158
  for (let obj of this.Value) {
159
+ const part = obj instanceof PythonObject ? obj.toReprString() : String(obj);
126
160
  if (res != "(") {
127
- res += ", " + obj;
161
+ res += ", " + part;
128
162
  } else {
129
- res += obj;
163
+ res += part;
130
164
  }
131
165
  }
132
166
  res += ")";
@@ -144,8 +178,10 @@ class PythonObject {
144
178
  for (let pair of this.Value) {
145
179
  if (res != "(") {
146
180
  res += ", ";
147
- }
148
- res += pair.key + ": " + pair.value;
181
+ }
182
+ const kPart = pair.key instanceof PythonObject ? pair.key.toReprString() : String(pair.key);
183
+ const vPart = pair.value instanceof PythonObject ? pair.value.toReprString() : String(pair.value);
184
+ res += kPart + ": " + vPart;
149
185
  }
150
186
  res += ")";
151
187
  return res;