Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,15 @@ ctypes
(Contributed by Bénédikt Tran in :gh:`133866`.)


glob
----

* Removed the undocumented :func:`!glob.glob0` and :func:`!glob.glob1`
functions, which have been deprecated since Python 3.13. Use
:func:`glob.glob` and pass a directory to its *root_dir* argument instead.
(Contributed by Barney Gale in :gh:`137466`.)


http.server
-----------

Expand Down
15 changes: 0 additions & 15 deletions Lib/glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,6 @@ def _glob0(dirname, basename, dir_fd, dironly, include_hidden=False):
return [basename]
return []

_deprecated_function_message = (
"{name} is deprecated and will be removed in Python {remove}. Use "
"glob.glob and pass a directory to its root_dir argument instead."
)

def glob0(dirname, pattern):
import warnings
warnings._deprecated("glob.glob0", _deprecated_function_message, remove=(3, 15))
return _glob0(dirname, pattern, None, False)

def glob1(dirname, pattern):
import warnings
warnings._deprecated("glob.glob1", _deprecated_function_message, remove=(3, 15))
return _glob1(dirname, pattern, None, False)

# This helper function recursively yields relative pathnames inside a literal
# directory.

Expand Down
3 changes: 3 additions & 0 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2723,6 +2723,9 @@ def makelink_with_filter(self, tarinfo, targetpath,
return
else:
if os.path.exists(tarinfo._link_target):
if os.path.lexists(targetpath):
# Avoid FileExistsError on following os.link.
os.unlink(targetpath)
os.link(tarinfo._link_target, targetpath)
return
except symlink_exception:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3293,7 +3293,7 @@ def test_code_page_name(self):
codecs.code_page_encode, 932, '\xff')
self.assertRaisesRegex(UnicodeDecodeError, 'cp932',
codecs.code_page_decode, 932, b'\x81\x00', 'strict', True)
self.assertRaisesRegex(UnicodeDecodeError, 'CP_UTF8',
self.assertRaisesRegex(UnicodeDecodeError, 'cp65001',
codecs.code_page_decode, self.CP_UTF8, b'\xff', 'strict', True)

def check_decode(self, cp, tests):
Expand Down
31 changes: 0 additions & 31 deletions Lib/test/test_glob.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import shutil
import sys
import unittest
import warnings

from test.support import is_wasi, Py_DEBUG
from test.support.os_helper import (TESTFN, skip_unless_symlink,
Expand Down Expand Up @@ -393,36 +392,6 @@ def test_glob_many_open_files(self):
for it in iters:
self.assertEqual(next(it), p)

def test_glob0(self):
with self.assertWarns(DeprecationWarning):
glob.glob0(self.tempdir, 'a')

with warnings.catch_warnings():
warnings.simplefilter('ignore')
eq = self.assertSequencesEqual_noorder
eq(glob.glob0(self.tempdir, 'a'), ['a'])
eq(glob.glob0(self.tempdir, '.bb'), ['.bb'])
eq(glob.glob0(self.tempdir, '.b*'), [])
eq(glob.glob0(self.tempdir, 'b'), [])
eq(glob.glob0(self.tempdir, '?'), [])
eq(glob.glob0(self.tempdir, '*a'), [])
eq(glob.glob0(self.tempdir, 'a*'), [])

def test_glob1(self):
with self.assertWarns(DeprecationWarning):
glob.glob1(self.tempdir, 'a')

with warnings.catch_warnings():
warnings.simplefilter('ignore')
eq = self.assertSequencesEqual_noorder
eq(glob.glob1(self.tempdir, 'a'), ['a'])
eq(glob.glob1(self.tempdir, '.bb'), ['.bb'])
eq(glob.glob1(self.tempdir, '.b*'), ['.bb'])
eq(glob.glob1(self.tempdir, 'b'), [])
eq(glob.glob1(self.tempdir, '?'), ['a'])
eq(glob.glob1(self.tempdir, '*a'), ['a', 'aaa'])
eq(glob.glob1(self.tempdir, 'a*'), ['a', 'aaa', 'aab'])

def test_translate_matching(self):
match = re.compile(glob.translate('*')).match
self.assertIsNotNone(match('foo'))
Expand Down
51 changes: 51 additions & 0 deletions Lib/test/test_tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,57 @@ def test_next_on_empty_tarfile(self):
with tarfile.open(fileobj=fd, mode="r") as tf:
self.assertEqual(tf.next(), None)

def _setup_symlink_to_target(self, temp_dirpath):
target_filepath = os.path.join(temp_dirpath, "target")
ustar_dirpath = os.path.join(temp_dirpath, "ustar")
hardlink_filepath = os.path.join(ustar_dirpath, "lnktype")
with open(target_filepath, "wb") as f:
f.write(b"target")
os.makedirs(ustar_dirpath)
os.symlink(target_filepath, hardlink_filepath)
return target_filepath, hardlink_filepath

def _assert_on_file_content(self, filepath, digest):
with open(filepath, "rb") as f:
data = f.read()
self.assertEqual(sha256sum(data), digest)

@unittest.skipUnless(
hasattr(os, "link"), "Missing hardlink implementation"
)
@os_helper.skip_unless_symlink
def test_extract_hardlink_on_symlink(self):
"""
This test verifies that extracting a hardlink will not follow an
existing symlink after a FileExistsError on os.link.
"""
with os_helper.temp_dir() as DIR:
target_filepath, hardlink_filepath = self._setup_symlink_to_target(DIR)
with tarfile.open(tarname, encoding="iso8859-1") as tar:
tar.extract("ustar/regtype", DIR, filter="data")
tar.extract("ustar/lnktype", DIR, filter="data")
self._assert_on_file_content(target_filepath, sha256sum(b"target"))
self._assert_on_file_content(hardlink_filepath, sha256_regtype)

@unittest.skipUnless(
hasattr(os, "link"), "Missing hardlink implementation"
)
@os_helper.skip_unless_symlink
def test_extractall_hardlink_on_symlink(self):
"""
This test verifies that extracting a hardlink will not follow an
existing symlink after a FileExistsError on os.link.
"""
with os_helper.temp_dir() as DIR:
target_filepath, hardlink_filepath = self._setup_symlink_to_target(DIR)
with tarfile.open(tarname, encoding="iso8859-1") as tar:
tar.extractall(
DIR, members=["ustar/regtype", "ustar/lnktype"], filter="data",
)
self._assert_on_file_content(target_filepath, sha256sum(b"target"))
self._assert_on_file_content(hardlink_filepath, sha256_regtype)


class MiscReadTest(MiscReadTestBase, unittest.TestCase):
test_fail_comp = None

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix name of the Python encoding in Unicode errors of the code page codec:
use "cp65000" and "cp65001" instead of "CP_UTF7" and "CP_UTF8" which are not
valid Python code names. Patch by Victor Stinner.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:func:`tarfile.TarFile.extractall` and :func:`tarfile.TarFile.extract` now
overwrite symlinks when extracting hardlinks.
(Contributed by Alexander Enrique Urieles Nieto in :gh:`75989`.)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Remove undocumented :func:`!glob.glob0` and :func:`!glob.glob1` functions,
which have been deprecated since Python 3.13. Use :func:`glob.glob` and pass
a directory to its *root_dir* argument instead.
4 changes: 0 additions & 4 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -7684,10 +7684,6 @@ code_page_name(UINT code_page, PyObject **obj)
*obj = NULL;
if (code_page == CP_ACP)
return "mbcs";
if (code_page == CP_UTF7)
return "CP_UTF7";
if (code_page == CP_UTF8)
return "CP_UTF8";

*obj = PyBytes_FromFormat("cp%u", code_page);
if (*obj == NULL)
Expand Down
45 changes: 29 additions & 16 deletions Programs/_freeze_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,40 @@ static const char header[] =
static void
runtime_init(void)
{
PyConfig config;
PyConfig_InitIsolatedConfig(&config);

config.site_import = 0;
PyInitConfig *config = PyInitConfig_Create();
if (config == NULL) {
printf("memory allocation failed\n");
exit(1);
}

PyStatus status;
status = PyConfig_SetString(&config, &config.program_name,
L"./_freeze_module");
if (PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Py_ExitStatusException(status);
if (PyInitConfig_SetInt(config, "site_import", 0) < 0) {
goto error;
}
if (PyInitConfig_SetStr(config, "program_name", "./_freeze_module") < 0) {
goto error;
}

/* Don't install importlib, since it could execute outdated bytecode. */
config._install_importlib = 0;
config._init_main = 0;
if (PyInitConfig_SetInt(config, "_install_importlib", 0) < 0) {
goto error;
}
if (PyInitConfig_SetInt(config, "_init_main", 0) < 0) {
goto error;
}

if (Py_InitializeFromInitConfig(config) < 0) {
goto error;
}
PyInitConfig_Free(config);
return;

status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
error:
{
const char *err_msg;
(void)PyInitConfig_GetError(config, &err_msg);
printf("Python init error: %s\n", err_msg);
PyInitConfig_Free(config);
exit(1);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Python/codecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ get_standard_encoding_impl(const char *encoding, int *bytelength)
}
}
}
else if (strcmp(encoding, "CP_UTF8") == 0) {
else if (strcmp(encoding, "cp65001") == 0) {
*bytelength = 3;
return ENC_UTF8;
}
Expand Down
17 changes: 8 additions & 9 deletions Python/frozenmain.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* Python interpreter main program for frozen scripts */

#include "Python.h"
#include "pycore_pystate.h" // _Py_GetConfig()
#include "pycore_runtime.h" // _PyRuntime_Initialize()
#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain()

#ifdef HAVE_UNISTD_H
# include <unistd.h> // isatty()
Expand All @@ -20,19 +19,14 @@ extern int PyInitFrozenExtensions(void);
int
Py_FrozenMain(int argc, char **argv)
{
PyStatus status = _PyRuntime_Initialize();
if (PyStatus_Exception(status)) {
Py_ExitStatusException(status);
}

PyConfig config;
PyConfig_InitPythonConfig(&config);
// Suppress errors from getpath.c
config.pathconfig_warnings = 0;
// Don't parse command line options like -E
config.parse_argv = 0;

status = PyConfig_SetBytesArgv(&config, argc, argv);
PyStatus status = PyConfig_SetBytesArgv(&config, argc, argv);
if (PyStatus_Exception(status)) {
PyConfig_Clear(&config);
Py_ExitStatusException(status);
Expand Down Expand Up @@ -64,7 +58,12 @@ Py_FrozenMain(int argc, char **argv)
PyWinFreeze_ExeInit();
#endif

if (_Py_GetConfig()->verbose) {
int verbose;
if (PyConfig_GetInt("verbose", &verbose) < 0) {
verbose = 0;
PyErr_Clear();
}
if (verbose) {
fprintf(stderr, "Python %s\n%s\n",
Py_GetVersion(), Py_GetCopyright());
}
Expand Down
Loading