ยปCore Development>Code coverage>Modules/_freeze_importlib.c

Python code coverage for Modules/_freeze_importlib.c

#countcontent
1n/a/* This is built as a stand-alone executable by the Makefile, and helps turn
2n/a Lib/importlib/_bootstrap.py into a frozen module in Python/importlib.h
3n/a*/
4n/a
5n/a#include <Python.h>
6n/a#include <marshal.h>
7n/a
8n/a#include <stdio.h>
9n/a#include <sys/types.h>
10n/a#include <sys/stat.h>
11n/a#ifndef MS_WINDOWS
12n/a#include <unistd.h>
13n/a#endif
14n/a
15n/a
16n/a/* To avoid a circular dependency on frozen.o, we create our own structure
17n/a of frozen modules instead, left deliberately blank so as to avoid
18n/a unintentional import of a stale version of _frozen_importlib. */
19n/a
20n/aconst static struct _frozen _PyImport_FrozenModules[] = {
21n/a {0, 0, 0} /* sentinel */
22n/a};
23n/a
24n/a#ifndef MS_WINDOWS
25n/a/* On Windows, this links with the regular pythonXY.dll, so this variable comes
26n/a from frozen.obj. In the Makefile, frozen.o is not linked into this executable,
27n/a so we define the variable here. */
28n/aconst struct _frozen *PyImport_FrozenModules;
29n/a#endif
30n/a
31n/aconst char header[] = "/* Auto-generated by Modules/_freeze_importlib.c */";
32n/a
33n/aint
34n/amain(int argc, char *argv[])
35n/a{
36n/a char *inpath, *outpath;
37n/a FILE *infile = NULL, *outfile = NULL;
38n/a struct stat st;
39n/a size_t text_size, data_size, n;
40n/a char *text = NULL;
41n/a unsigned char *data;
42n/a PyObject *code = NULL, *marshalled = NULL;
43n/a
44n/a PyImport_FrozenModules = _PyImport_FrozenModules;
45n/a
46n/a if (argc != 3) {
47n/a fprintf(stderr, "need to specify input and output paths\n");
48n/a return 2;
49n/a }
50n/a inpath = argv[1];
51n/a outpath = argv[2];
52n/a infile = fopen(inpath, "rb");
53n/a if (infile == NULL) {
54n/a fprintf(stderr, "cannot open '%s' for reading\n", inpath);
55n/a goto error;
56n/a }
57n/a if (fstat(fileno(infile), &st)) {
58n/a fprintf(stderr, "cannot fstat '%s'\n", inpath);
59n/a goto error;
60n/a }
61n/a text_size = st.st_size;
62n/a text = (char *) malloc(text_size + 1);
63n/a if (text == NULL) {
64n/a fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size);
65n/a goto error;
66n/a }
67n/a n = fread(text, 1, text_size, infile);
68n/a fclose(infile);
69n/a infile = NULL;
70n/a if (n < text_size) {
71n/a fprintf(stderr, "read too short: got %ld instead of %ld bytes\n",
72n/a (long) n, (long) text_size);
73n/a goto error;
74n/a }
75n/a text[text_size] = '\0';
76n/a
77n/a Py_NoUserSiteDirectory++;
78n/a Py_NoSiteFlag++;
79n/a Py_IgnoreEnvironmentFlag++;
80n/a
81n/a Py_SetProgramName(L"./_freeze_importlib");
82n/a /* Don't install importlib, since it could execute outdated bytecode. */
83n/a _Py_InitializeEx_Private(1, 0);
84n/a
85n/a code = Py_CompileStringExFlags(text, "<frozen importlib._bootstrap>",
86n/a Py_file_input, NULL, 0);
87n/a if (code == NULL)
88n/a goto error;
89n/a free(text);
90n/a text = NULL;
91n/a
92n/a marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
93n/a Py_CLEAR(code);
94n/a if (marshalled == NULL)
95n/a goto error;
96n/a
97n/a assert(PyBytes_CheckExact(marshalled));
98n/a data = (unsigned char *) PyBytes_AS_STRING(marshalled);
99n/a data_size = PyBytes_GET_SIZE(marshalled);
100n/a
101n/a /* Open the file in text mode. The hg checkout should be using the eol extension,
102n/a which in turn should cause the EOL style match the C library's text mode */
103n/a outfile = fopen(outpath, "w");
104n/a if (outfile == NULL) {
105n/a fprintf(stderr, "cannot open '%s' for writing\n", outpath);
106n/a goto error;
107n/a }
108n/a fprintf(outfile, "%s\n", header);
109n/a fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n");
110n/a for (n = 0; n < data_size; n += 16) {
111n/a size_t i, end = Py_MIN(n + 16, data_size);
112n/a fprintf(outfile, " ");
113n/a for (i = n; i < end; i++) {
114n/a fprintf(outfile, "%d,", (unsigned int) data[i]);
115n/a }
116n/a fprintf(outfile, "\n");
117n/a }
118n/a fprintf(outfile, "};\n");
119n/a
120n/a Py_CLEAR(marshalled);
121n/a
122n/a Py_Finalize();
123n/a if (outfile) {
124n/a if (ferror(outfile)) {
125n/a fprintf(stderr, "error when writing to '%s'\n", outpath);
126n/a goto error;
127n/a }
128n/a fclose(outfile);
129n/a }
130n/a return 0;
131n/a
132n/aerror:
133n/a PyErr_Print();
134n/a Py_Finalize();
135n/a if (infile)
136n/a fclose(infile);
137n/a if (outfile)
138n/a fclose(outfile);
139n/a if (text)
140n/a free(text);
141n/a if (marshalled)
142n/a Py_DECREF(marshalled);
143n/a return 1;
144n/a}