Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ea59dbf

Browse files
committed
Issue #13959: Re-implement imp.cache_from_source() in Lib/imp.py.
1 parent ed672d6 commit ea59dbf

4 files changed

Lines changed: 2985 additions & 2999 deletions

File tree

Lib/imp.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@
1010
load_dynamic, get_frozen_object, is_frozen_package,
1111
init_builtin, init_frozen, is_builtin, is_frozen,
1212
_fix_co_filename)
13-
# Can (probably) move to importlib
14-
from _imp import (get_tag, get_suffixes, cache_from_source,
15-
source_from_cache)
1613
# Could move out of _imp, but not worth the code
1714
from _imp import get_magic
15+
# Can (probably) move to importlib
16+
from _imp import (get_tag, get_suffixes, source_from_cache)
1817
# Should be re-implemented here (and mostly deprecated)
1918
from _imp import (find_module, NullImporter,
2019
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
2120
PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
2221
PY_CODERESOURCE, IMP_HOOK)
2322

2423
from importlib._bootstrap import _new_module as new_module
24+
from importlib._bootstrap import _cache_from_source as cache_from_source
2525

2626
from importlib import _bootstrap
2727
import os

Lib/importlib/_bootstrap.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,31 @@ def _new_module(name):
178178

179179
# Finder/loader utility code ##################################################
180180

181+
PYCACHE = '__pycache__'
182+
183+
DEBUG_BYTECODE_SUFFIX = '.pyc'
184+
OPT_BYTECODE_SUFFIX = '.pyo'
185+
BYTECODE_SUFFIX = DEBUG_BYTECODE_SUFFIX if __debug__ else OPT_BYTECODE_SUFFIX
186+
187+
def _cache_from_source(path, debug_override=None):
188+
"""Given the path to a .py file, return the path to its .pyc/.pyo file.
189+
190+
The .py file does not need to exist; this simply returns the path to the
191+
.pyc/.pyo file calculated as if the .py file were imported. The extension
192+
will be .pyc unless __debug__ is not defined, then it will be .pyo.
193+
194+
If debug_override is not None, then it must be a boolean and is taken as
195+
the value of __debug__ instead.
196+
197+
"""
198+
debug = __debug__ if debug_override is None else debug_override
199+
suffix = DEBUG_BYTECODE_SUFFIX if debug else OPT_BYTECODE_SUFFIX
200+
head, tail = _path_split(path)
201+
base_filename, sep, _ = tail.partition('.')
202+
filename = '{}{}{}{}'.format(base_filename, sep, _imp.get_tag(), suffix)
203+
return _path_join(head, PYCACHE, filename)
204+
205+
181206
def verbose_message(message, *args):
182207
"""Print the message to stderr if -v/PYTHONVERBOSE is turned on."""
183208
if sys.flags.verbose:
@@ -452,7 +477,7 @@ def _load_module(self, module, *, sourceless=False):
452477
code_object = self.get_code(name)
453478
module.__file__ = self.get_filename(name)
454479
if not sourceless:
455-
module.__cached__ = _imp.cache_from_source(module.__file__)
480+
module.__cached__ = _cache_from_source(module.__file__)
456481
else:
457482
module.__cached__ = module.__file__
458483
module.__package__ = name
@@ -515,7 +540,7 @@ def get_code(self, fullname):
515540
516541
"""
517542
source_path = self.get_filename(fullname)
518-
bytecode_path = _imp.cache_from_source(source_path)
543+
bytecode_path = _cache_from_source(source_path)
519544
source_mtime = None
520545
if bytecode_path is not None:
521546
try:
@@ -554,9 +579,6 @@ def get_code(self, fullname):
554579
verbose_message('code object from {}', source_path)
555580
if (not sys.dont_write_bytecode and bytecode_path is not None and
556581
source_mtime is not None):
557-
# If e.g. Jython ever implements imp.cache_from_source to have
558-
# their own cached file format, this block of code will most likely
559-
# throw an exception.
560582
data = bytearray(_MAGIC_NUMBER)
561583
data.extend(_w_long(source_mtime))
562584
data.extend(_w_long(len(source_bytes)))

Python/import.c

Lines changed: 0 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,6 @@ remove_module(PyObject *name)
783783

784784
static PyObject * get_sourcefile(PyObject *filename);
785785
static PyObject *make_source_pathname(PyObject *pathname);
786-
static PyObject* make_compiled_pathname(PyObject *pathname, int debug);
787786

788787
/* Execute a code object in a module and return the module object
789788
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
@@ -924,71 +923,6 @@ rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end)
924923
return found;
925924
}
926925

927-
/* Given a pathname for a Python source file, fill a buffer with the
928-
pathname for the corresponding compiled file. Return the pathname
929-
for the compiled file, or NULL if there's no space in the buffer.
930-
Doesn't set an exception.
931-
932-
foo.py -> __pycache__/foo.<tag>.pyc
933-
934-
pathstr is assumed to be "ready".
935-
*/
936-
937-
static PyObject*
938-
make_compiled_pathname(PyObject *pathstr, int debug)
939-
{
940-
PyObject *result;
941-
Py_ssize_t fname, ext, len, i, pos, taglen;
942-
Py_ssize_t pycache_len = sizeof(CACHEDIR) - 1;
943-
int kind;
944-
void *data;
945-
Py_UCS4 lastsep;
946-
947-
/* Compute the output string size. */
948-
len = PyUnicode_GET_LENGTH(pathstr);
949-
/* If there is no separator, this returns -1, so
950-
fname will be 0. */
951-
fname = rightmost_sep_obj(pathstr, 0, len) + 1;
952-
/* Windows: re-use the last separator character (/ or \\) when
953-
appending the __pycache__ path. */
954-
if (fname > 0)
955-
lastsep = PyUnicode_READ_CHAR(pathstr, fname -1);
956-
else
957-
lastsep = SEP;
958-
ext = fname - 1;
959-
for(i = fname; i < len; i++)
960-
if (PyUnicode_READ_CHAR(pathstr, i) == '.')
961-
ext = i + 1;
962-
if (ext < fname)
963-
/* No dot in filename; use entire filename */
964-
ext = len;
965-
966-
/* result = pathstr[:fname] + "__pycache__" + SEP +
967-
pathstr[fname:ext] + tag + ".py[co]" */
968-
taglen = strlen(pyc_tag);
969-
result = PyUnicode_New(ext + pycache_len + 1 + taglen + 4,
970-
PyUnicode_MAX_CHAR_VALUE(pathstr));
971-
if (!result)
972-
return NULL;
973-
kind = PyUnicode_KIND(result);
974-
data = PyUnicode_DATA(result);
975-
PyUnicode_CopyCharacters(result, 0, pathstr, 0, fname);
976-
pos = fname;
977-
for (i = 0; i < pycache_len; i++)
978-
PyUnicode_WRITE(kind, data, pos++, CACHEDIR[i]);
979-
PyUnicode_WRITE(kind, data, pos++, lastsep);
980-
PyUnicode_CopyCharacters(result, pos, pathstr,
981-
fname, ext - fname);
982-
pos += ext - fname;
983-
for (i = 0; pyc_tag[i]; i++)
984-
PyUnicode_WRITE(kind, data, pos++, pyc_tag[i]);
985-
PyUnicode_WRITE(kind, data, pos++, '.');
986-
PyUnicode_WRITE(kind, data, pos++, 'p');
987-
PyUnicode_WRITE(kind, data, pos++, 'y');
988-
PyUnicode_WRITE(kind, data, pos++, debug ? 'c' : 'o');
989-
return result;
990-
}
991-
992926

993927
/* Given a pathname to a Python byte compiled file, return the path to the
994928
source file, if the path matches the PEP 3147 format. This does not check
@@ -2991,49 +2925,6 @@ PyDoc_STRVAR(doc_reload,
29912925
\n\
29922926
Reload the module. The module must have been successfully imported before.");
29932927

2994-
static PyObject *
2995-
imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws)
2996-
{
2997-
static char *kwlist[] = {"path", "debug_override", NULL};
2998-
2999-
PyObject *pathname, *cpathname;
3000-
PyObject *debug_override = NULL;
3001-
int debug = !Py_OptimizeFlag;
3002-
3003-
if (!PyArg_ParseTupleAndKeywords(
3004-
args, kws, "O&|O", kwlist,
3005-
PyUnicode_FSDecoder, &pathname, &debug_override))
3006-
return NULL;
3007-
3008-
if (debug_override != NULL &&
3009-
(debug = PyObject_IsTrue(debug_override)) < 0) {
3010-
Py_DECREF(pathname);
3011-
return NULL;
3012-
}
3013-
3014-
if (PyUnicode_READY(pathname) < 0)
3015-
return NULL;
3016-
3017-
cpathname = make_compiled_pathname(pathname, debug);
3018-
Py_DECREF(pathname);
3019-
3020-
if (cpathname == NULL) {
3021-
PyErr_Format(PyExc_SystemError, "path buffer too short");
3022-
return NULL;
3023-
}
3024-
return cpathname;
3025-
}
3026-
3027-
PyDoc_STRVAR(doc_cache_from_source,
3028-
"cache_from_source(path, [debug_override]) -> path\n\
3029-
Given the path to a .py file, return the path to its .pyc/.pyo file.\n\
3030-
\n\
3031-
The .py file does not need to exist; this simply returns the path to the\n\
3032-
.pyc/.pyo file calculated as if the .py file were imported. The extension\n\
3033-
will be .pyc unless __debug__ is not defined, then it will be .pyo.\n\
3034-
\n\
3035-
If debug_override is not None, then it must be a boolean and is taken as\n\
3036-
the value of __debug__ instead.");
30372928

30382929
static PyObject *
30392930
imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws)
@@ -3116,8 +3007,6 @@ static PyMethodDef imp_methods[] = {
31163007
{"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock},
31173008
{"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock},
31183009
{"reload", imp_reload, METH_O, doc_reload},
3119-
{"cache_from_source", (PyCFunction)imp_cache_from_source,
3120-
METH_VARARGS | METH_KEYWORDS, doc_cache_from_source},
31213010
{"source_from_cache", (PyCFunction)imp_source_from_cache,
31223011
METH_VARARGS | METH_KEYWORDS, doc_source_from_cache},
31233012
/* The rest are obsolete */

0 commit comments

Comments
 (0)