Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1037ca5

Browse filesBrowse files
authored
bpo-45850: Implement deep-freeze on Windows (#29648)
Implement changes to build with deep-frozen modules on Windows. Note that we now require Python 3.10 as the "bootstrap" or "host" Python. This causes a modest startup speed (around 7%) on Windows.
1 parent 4d6c0c0 commit 1037ca5
Copy full SHA for 1037ca5

9 files changed

+500-24Lines changed: 500 additions & 24 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file
+2Lines changed: 2 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Implement changes to build with deep-frozen modules on Windows.
2+
Note that we now require Python 3.10 as the "bootstrap" or "host" Python.
Collapse file

‎PCbuild/_freeze_module.vcxproj‎

Copy file name to clipboardExpand all lines: PCbuild/_freeze_module.vcxproj
+55-3Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,119 +236,171 @@
236236
<ModName>importlib._bootstrap</ModName>
237237
<IntFile>$(IntDir)importlib._bootstrap.g.h</IntFile>
238238
<OutFile>$(PySourcePath)Python\frozen_modules\importlib._bootstrap.h</OutFile>
239+
<DeepIntFile>$(IntDir)importlib._bootstrap.g.c</DeepIntFile>
240+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.importlib._bootstrap.c</DeepOutFile>
239241
</None>
240242
<None Include="..\Lib\importlib\_bootstrap_external.py">
241243
<ModName>importlib._bootstrap_external</ModName>
242244
<IntFile>$(IntDir)importlib._bootstrap_external.g.h</IntFile>
243245
<OutFile>$(PySourcePath)Python\frozen_modules\importlib._bootstrap_external.h</OutFile>
246+
<DeepIntFile>$(IntDir)importlib._bootstrap_external.g.c</DeepIntFile>
247+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.importlib._bootstrap_external.c</DeepOutFile>
244248
</None>
245249
<None Include="..\Lib\zipimport.py">
246250
<ModName>zipimport</ModName>
247251
<IntFile>$(IntDir)zipimport.g.h</IntFile>
248252
<OutFile>$(PySourcePath)Python\frozen_modules\zipimport.h</OutFile>
253+
<DeepIntFile>$(IntDir)zipimport.g.c</DeepIntFile>
254+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.zipimport.c</DeepOutFile>
249255
</None>
250256
<None Include="..\Lib\abc.py">
251257
<ModName>abc</ModName>
252258
<IntFile>$(IntDir)abc.g.h</IntFile>
253259
<OutFile>$(PySourcePath)Python\frozen_modules\abc.h</OutFile>
260+
<DeepIntFile>$(IntDir)abc.g.c</DeepIntFile>
261+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.abc.c</DeepOutFile>
254262
</None>
255263
<None Include="..\Lib\codecs.py">
256264
<ModName>codecs</ModName>
257265
<IntFile>$(IntDir)codecs.g.h</IntFile>
258266
<OutFile>$(PySourcePath)Python\frozen_modules\codecs.h</OutFile>
267+
<DeepIntFile>$(IntDir)codecs.g.c</DeepIntFile>
268+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.codecs.c</DeepOutFile>
259269
</None>
260270
<None Include="..\Lib\io.py">
261271
<ModName>io</ModName>
262272
<IntFile>$(IntDir)io.g.h</IntFile>
263273
<OutFile>$(PySourcePath)Python\frozen_modules\io.h</OutFile>
274+
<DeepIntFile>$(IntDir)io.g.c</DeepIntFile>
275+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.io.c</DeepOutFile>
264276
</None>
265277
<None Include="..\Lib\_collections_abc.py">
266278
<ModName>_collections_abc</ModName>
267279
<IntFile>$(IntDir)_collections_abc.g.h</IntFile>
268280
<OutFile>$(PySourcePath)Python\frozen_modules\_collections_abc.h</OutFile>
281+
<DeepIntFile>$(IntDir)_collections_abc.g.c</DeepIntFile>
282+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df._collections_abc.c</DeepOutFile>
269283
</None>
270284
<None Include="..\Lib\_sitebuiltins.py">
271285
<ModName>_sitebuiltins</ModName>
272286
<IntFile>$(IntDir)_sitebuiltins.g.h</IntFile>
273287
<OutFile>$(PySourcePath)Python\frozen_modules\_sitebuiltins.h</OutFile>
288+
<DeepIntFile>$(IntDir)_sitebuiltins.g.c</DeepIntFile>
289+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df._sitebuiltins.c</DeepOutFile>
274290
</None>
275291
<None Include="..\Lib\genericpath.py">
276292
<ModName>genericpath</ModName>
277293
<IntFile>$(IntDir)genericpath.g.h</IntFile>
278294
<OutFile>$(PySourcePath)Python\frozen_modules\genericpath.h</OutFile>
295+
<DeepIntFile>$(IntDir)genericpath.g.c</DeepIntFile>
296+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.genericpath.c</DeepOutFile>
279297
</None>
280298
<None Include="..\Lib\ntpath.py">
281299
<ModName>ntpath</ModName>
282300
<IntFile>$(IntDir)ntpath.g.h</IntFile>
283301
<OutFile>$(PySourcePath)Python\frozen_modules\ntpath.h</OutFile>
302+
<DeepIntFile>$(IntDir)ntpath.g.c</DeepIntFile>
303+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.ntpath.c</DeepOutFile>
284304
</None>
285305
<None Include="..\Lib\posixpath.py">
286306
<ModName>posixpath</ModName>
287307
<IntFile>$(IntDir)posixpath.g.h</IntFile>
288308
<OutFile>$(PySourcePath)Python\frozen_modules\posixpath.h</OutFile>
309+
<DeepIntFile>$(IntDir)posixpath.g.c</DeepIntFile>
310+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.posixpath.c</DeepOutFile>
289311
</None>
290312
<None Include="..\Lib\os.py">
291313
<ModName>os</ModName>
292314
<IntFile>$(IntDir)os.g.h</IntFile>
293315
<OutFile>$(PySourcePath)Python\frozen_modules\os.h</OutFile>
316+
<DeepIntFile>$(IntDir)os.g.c</DeepIntFile>
317+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.os.c</DeepOutFile>
294318
</None>
295319
<None Include="..\Lib\site.py">
296320
<ModName>site</ModName>
297321
<IntFile>$(IntDir)site.g.h</IntFile>
298322
<OutFile>$(PySourcePath)Python\frozen_modules\site.h</OutFile>
323+
<DeepIntFile>$(IntDir)site.g.c</DeepIntFile>
324+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.site.c</DeepOutFile>
299325
</None>
300326
<None Include="..\Lib\stat.py">
301327
<ModName>stat</ModName>
302328
<IntFile>$(IntDir)stat.g.h</IntFile>
303329
<OutFile>$(PySourcePath)Python\frozen_modules\stat.h</OutFile>
330+
<DeepIntFile>$(IntDir)stat.g.c</DeepIntFile>
331+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.stat.c</DeepOutFile>
304332
</None>
305333
<None Include="..\Lib\__hello__.py">
306334
<ModName>__hello__</ModName>
307335
<IntFile>$(IntDir)__hello__.g.h</IntFile>
308336
<OutFile>$(PySourcePath)Python\frozen_modules\__hello__.h</OutFile>
337+
<DeepIntFile>$(IntDir)__hello__.g.c</DeepIntFile>
338+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.__hello__.c</DeepOutFile>
309339
</None>
310340
<None Include="..\Lib\__phello__\__init__.py">
311341
<ModName>__phello__</ModName>
312342
<IntFile>$(IntDir)__phello__.g.h</IntFile>
313343
<OutFile>$(PySourcePath)Python\frozen_modules\__phello__.h</OutFile>
344+
<DeepIntFile>$(IntDir)__phello__.g.c</DeepIntFile>
345+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.__phello__.c</DeepOutFile>
314346
</None>
315347
<None Include="..\Lib\__phello__\ham\__init__.py">
316348
<ModName>__phello__.ham</ModName>
317349
<IntFile>$(IntDir)__phello__.ham.g.h</IntFile>
318350
<OutFile>$(PySourcePath)Python\frozen_modules\__phello__.ham.h</OutFile>
351+
<DeepIntFile>$(IntDir)__phello__.ham.g.c</DeepIntFile>
352+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.__phello__.ham.c</DeepOutFile>
319353
</None>
320354
<None Include="..\Lib\__phello__\ham\eggs.py">
321355
<ModName>__phello__.ham.eggs</ModName>
322356
<IntFile>$(IntDir)__phello__.ham.eggs.g.h</IntFile>
323357
<OutFile>$(PySourcePath)Python\frozen_modules\__phello__.ham.eggs.h</OutFile>
358+
<DeepIntFile>$(IntDir)__phello__.ham.eggs.g.c</DeepIntFile>
359+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.__phello__.ham.eggs.c</DeepOutFile>
324360
</None>
325361
<None Include="..\Lib\__phello__\spam.py">
326362
<ModName>__phello__.spam</ModName>
327363
<IntFile>$(IntDir)__phello__.spam.g.h</IntFile>
328364
<OutFile>$(PySourcePath)Python\frozen_modules\__phello__.spam.h</OutFile>
365+
<DeepIntFile>$(IntDir)__phello__.spam.g.c</DeepIntFile>
366+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.__phello__.spam.c</DeepOutFile>
329367
</None>
330368
<None Include="..\Tools\freeze\flag.py">
331369
<ModName>frozen_only</ModName>
332370
<IntFile>$(IntDir)frozen_only.g.h</IntFile>
333371
<OutFile>$(PySourcePath)Python\frozen_modules\frozen_only.h</OutFile>
372+
<DeepIntFile>$(IntDir)frozen_only.g.c</DeepIntFile>
373+
<DeepOutFile>$(PySourcePath)Python\deepfreeze\df.frozen_only.c</DeepOutFile>
334374
</None>
335375
<!-- END frozen modules -->
336376
</ItemGroup>
337377
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
338378
<ImportGroup Label="ExtensionTargets">
339379
</ImportGroup>
340380
<Target Name="_RebuildFrozen" AfterTargets="AfterBuild" Condition="$(Configuration) != 'PGUpdate'">
341-
<Exec Command='"$(TargetPath)" "%(None.ModName)" "%(None.FullPath)" "%(None.IntFile)"' />
381+
<Exec Command='"$(TargetPath)" "%(None.ModName)" "%(None.FullPath)" "%(None.DeepIntFile)"' />
342382

343-
<Copy SourceFiles="%(None.IntFile)"
383+
<Copy SourceFiles="%(None.DeepIntFile)"
344384
DestinationFiles="%(None.OutFile)"
345-
Condition="!Exists(%(None.OutFile)) or (Exists(%(None.IntFile)) and '$([System.IO.File]::ReadAllText(%(None.OutFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))' != '$([System.IO.File]::ReadAllText(%(None.IntFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))')">
385+
Condition="!Exists(%(None.OutFile)) or (Exists(%(None.DeepIntFile)) and '$([System.IO.File]::ReadAllText(%(None.OutFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))' != '$([System.IO.File]::ReadAllText(%(None.DeepIntFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))')">
346386
<Output TaskParameter="CopiedFiles" ItemName="_Updated" />
347387
</Copy>
348388

349389
<Message Text="Updated files: @(_Updated->'%(Filename)%(Extension)',', ')"
350390
Condition="'@(_Updated)' != ''" Importance="high" />
351391
</Target>
392+
<Target Name="_RebuildDeepFrozen" AfterTargets="_RebuildFrozen" Condition="$(Configuration) != 'PGUpdate'">
393+
<Exec Command='$(PythonForBuild) "$(PySourcePath)Tools\scripts\deepfreeze.py" "%(None.OutFile)" "-m" "%(None.ModName)" -o "%(None.IntFile)"' />
394+
395+
<Copy SourceFiles="%(None.IntFile)"
396+
DestinationFiles="%(None.DeepOutFile)"
397+
Condition="!Exists(%(None.DeepOutFile)) or (Exists(%(None.IntFile)) and '$([System.IO.File]::ReadAllText(%(None.DeepOutFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))' != '$([System.IO.File]::ReadAllText(%(None.IntFile)).Replace(`&#x0D;&#x0A;`, `&#x0A;`))')">
398+
<Output TaskParameter="CopiedFiles" ItemName="_DeepUpdated" />
399+
</Copy>
400+
401+
<Message Text="Updated files: @(_DeepUpdated->'%(Filename)%(Extension)',', ')"
402+
Condition="'@(_DeepUpdated)' != ''" Importance="high" />
403+
</Target>
352404
<Target Name="_CleanFrozen" BeforeTargets="CoreClean" Condition="$(Configuration) != 'PGUpdate'">
353405
<ItemGroup>
354406
<Clean Include="%(None.IntFile)" />
Collapse file

‎PCbuild/find_python.bat‎

Copy file name to clipboardExpand all lines: PCbuild/find_python.bat
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
@if "%_Py_EXTERNALS_DIR%"=="" (set _Py_EXTERNALS_DIR=%~dp0\..\externals)
3232

3333
@rem If we have Python in externals, use that one
34-
@if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found in externals directory) & goto :found
34+
@if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" ("%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul) && (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") && (set _Py_Python_Source=found in externals directory) && goto :found || rmdir /Q /S "%_Py_EXTERNALS_DIR%\pythonx86"
3535

3636
@rem If HOST_PYTHON is recent enough, use that
37-
@if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 8)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found
37+
@if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 10)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found
3838

3939
@rem If py.exe finds a recent enough version, use that one
40-
@for %%p in (3.9 3.8) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found
40+
@for %%p in (3.10) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found
4141

4242
@if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%"
4343
@set _Py_NUGET=%NUGET%
Collapse file

‎PCbuild/pythoncore.vcxproj‎

Copy file name to clipboardExpand all lines: PCbuild/pythoncore.vcxproj
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,30 @@
502502
<ClCompile Include="..\Python\thread.c" />
503503
<ClCompile Include="..\Python\traceback.c" />
504504
</ItemGroup>
505+
<ItemGroup>
506+
<!-- BEGIN deepfreeze -->
507+
<ClCompile Include="..\Python\deepfreeze\df.importlib._bootstrap.c" />
508+
<ClCompile Include="..\Python\deepfreeze\df.importlib._bootstrap_external.c" />
509+
<ClCompile Include="..\Python\deepfreeze\df.zipimport.c" />
510+
<ClCompile Include="..\Python\deepfreeze\df.abc.c" />
511+
<ClCompile Include="..\Python\deepfreeze\df.codecs.c" />
512+
<ClCompile Include="..\Python\deepfreeze\df.io.c" />
513+
<ClCompile Include="..\Python\deepfreeze\df._collections_abc.c" />
514+
<ClCompile Include="..\Python\deepfreeze\df._sitebuiltins.c" />
515+
<ClCompile Include="..\Python\deepfreeze\df.genericpath.c" />
516+
<ClCompile Include="..\Python\deepfreeze\df.ntpath.c" />
517+
<ClCompile Include="..\Python\deepfreeze\df.posixpath.c" />
518+
<ClCompile Include="..\Python\deepfreeze\df.os.c" />
519+
<ClCompile Include="..\Python\deepfreeze\df.site.c" />
520+
<ClCompile Include="..\Python\deepfreeze\df.stat.c" />
521+
<ClCompile Include="..\Python\deepfreeze\df.__hello__.c" />
522+
<ClCompile Include="..\Python\deepfreeze\df.__phello__.c" />
523+
<ClCompile Include="..\Python\deepfreeze\df.__phello__.ham.c" />
524+
<ClCompile Include="..\Python\deepfreeze\df.__phello__.ham.eggs.c" />
525+
<ClCompile Include="..\Python\deepfreeze\df.__phello__.spam.c" />
526+
<ClCompile Include="..\Python\deepfreeze\df.frozen_only.c" />
527+
<!-- END deepfreeze -->
528+
</ItemGroup>
505529
<ItemGroup Condition="$(IncludeExternals)">
506530
<ClCompile Include="..\Modules\zlibmodule.c" />
507531
<ClCompile Include="$(zlibDir)\adler32.c" />
Collapse file

‎Python/frozen.c‎

Copy file name to clipboardExpand all lines: Python/frozen.c
-5Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,7 @@
6161
#include "frozen_modules/frozen_only.h"
6262
/* End includes */
6363

64-
#ifdef MS_WINDOWS
65-
/* Deepfreeze isn't supported on Windows yet. */
66-
#define GET_CODE(name) NULL
67-
#else
6864
#define GET_CODE(name) _Py_get_##name##_toplevel
69-
#endif
7065

7166
/* Start extern declarations */
7267
extern PyObject *_Py_get_importlib__bootstrap_toplevel(void);
Collapse file

‎Tools/scripts/deepfreeze.py‎

Copy file name to clipboardExpand all lines: Tools/scripts/deepfreeze.py
+46-12Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import argparse
2+
import ast
23
import builtins
34
import collections
45
import contextlib
56
import os
6-
import sys
7+
import re
78
import time
89
import types
910
import typing
1011

12+
import umarshal
13+
1114
verbose = False
1215

1316

@@ -55,7 +58,8 @@ def get_localsplus_counts(code: types.CodeType,
5558
nplaincellvars += 1
5659
elif kind & CO_FAST_FREE:
5760
nfreevars += 1
58-
assert nlocals == len(code.co_varnames) == code.co_nlocals
61+
assert nlocals == len(code.co_varnames) == code.co_nlocals, \
62+
(nlocals, len(code.co_varnames), code.co_nlocals)
5963
assert ncellvars == len(code.co_cellvars)
6064
assert nfreevars == len(code.co_freevars)
6165
assert len(names) == nlocals + nplaincellvars + nfreevars
@@ -274,14 +278,7 @@ def generate_tuple(self, name: str, t: tuple[object, ...]) -> str:
274278
self.write(item + ",")
275279
return f"& {name}._object.ob_base.ob_base"
276280

277-
def generate_int(self, name: str, i: int) -> str:
278-
maxint = sys.maxsize
279-
if maxint == 2**31 - 1:
280-
digit = 2**15
281-
elif maxint == 2**63 - 1:
282-
digit = 2**30
283-
else:
284-
assert False, f"What int size is this system?!? {maxint=}"
281+
def _generate_int_for_bits(self, name: str, i: int, digit: int) -> None:
285282
sign = -1 if i < 0 else 0 if i == 0 else +1
286283
i = abs(i)
287284
digits: list[int] = []
@@ -298,6 +295,20 @@ def generate_int(self, name: str, i: int) -> str:
298295
if digits:
299296
ds = ", ".join(map(str, digits))
300297
self.write(f".ob_digit = {{ {ds} }},")
298+
299+
def generate_int(self, name: str, i: int) -> str:
300+
if abs(i) < 2**15:
301+
self._generate_int_for_bits(name, i, 2**15)
302+
else:
303+
connective = "if"
304+
for bits_in_digit in 15, 30:
305+
self.write(f"#{connective} PYLONG_BITS_IN_DIGIT == {bits_in_digit}")
306+
self._generate_int_for_bits(name, i, 2**bits_in_digit)
307+
connective = "elif"
308+
self.write("#else")
309+
self.write('#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"')
310+
self.write("#endif")
311+
# If neither clause applies, it won't compile
301312
return f"& {name}.ob_base.ob_base"
302313

303314
def generate_float(self, name: str, x: float) -> str:
@@ -326,7 +337,7 @@ def generate(self, name: str, obj: object) -> str:
326337
return self.cache[key]
327338
self.misses += 1
328339
match obj:
329-
case types.CodeType() as code:
340+
case types.CodeType() | umarshal.Code() as code:
330341
val = self.generate_code(name, code)
331342
case tuple(t):
332343
val = self.generate_tuple(name, t)
@@ -367,8 +378,31 @@ def generate(self, name: str, obj: object) -> str:
367378
}
368379
"""
369380

381+
FROZEN_COMMENT = "/* Auto-generated by Programs/_freeze_module.c */"
382+
383+
FROZEN_DATA_LINE = r"\s*(\d+,\s*)+\s*"
384+
385+
386+
def is_frozen_header(source: str) -> bool:
387+
return source.startswith(FROZEN_COMMENT)
388+
389+
390+
def decode_frozen_data(source: str) -> types.CodeType:
391+
lines = source.splitlines()
392+
while lines and re.match(FROZEN_DATA_LINE, lines[0]) is None:
393+
del lines[0]
394+
while lines and re.match(FROZEN_DATA_LINE, lines[-1]) is None:
395+
del lines[-1]
396+
values: tuple[int, ...] = ast.literal_eval("".join(lines))
397+
data = bytes(values)
398+
return umarshal.loads(data)
399+
400+
370401
def generate(source: str, filename: str, modname: str, file: typing.TextIO) -> None:
371-
code = compile(source, filename, "exec")
402+
if is_frozen_header(source):
403+
code = decode_frozen_data(source)
404+
else:
405+
code = compile(source, filename, "exec")
372406
printer = Printer(file)
373407
printer.generate("toplevel", code)
374408
printer.write("")

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.