Skip to content

Commit 9a4a6d9

Browse files
committed
Merge branch 'main' into frozendict_capi_doc
2 parents 0119335 + 0c29f83 commit 9a4a6d9

File tree

10 files changed

+106
-51
lines changed

10 files changed

+106
-51
lines changed

.github/actionlint.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
self-hosted-runner:
2-
# Pending https://github.com/rhysd/actionlint/pull/615
3-
labels: ["windows-2025-vs2026"]
4-
51
config-variables: null
62

73
paths:

.github/zizmor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Configuration for the zizmor static analysis tool, run via prek in CI
2-
# https://woodruffw.github.io/zizmor/configuration/
2+
# https://docs.zizmor.sh/configuration/
33
rules:
44
dangerous-triggers:
55
ignore:

.pre-commit-config.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.15.0
3+
rev: a27a2e47c7751b639d2b5badf0ef6ff11fee893f # frozen: v0.15.4
44
hooks:
55
- id: ruff-check
66
name: Run Ruff (lint) on Apple/
@@ -60,20 +60,20 @@ repos:
6060
files: ^Tools/wasm/
6161

6262
- repo: https://github.com/psf/black-pre-commit-mirror
63-
rev: 26.1.0
63+
rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0
6464
hooks:
6565
- id: black
6666
name: Run Black on Tools/jit/
6767
files: ^Tools/jit/
6868

6969
- repo: https://github.com/Lucas-C/pre-commit-hooks
70-
rev: v1.5.6
70+
rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6
7171
hooks:
7272
- id: remove-tabs
7373
types: [python]
7474

7575
- repo: https://github.com/pre-commit/pre-commit-hooks
76-
rev: v6.0.0
76+
rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
7777
hooks:
7878
- id: check-case-conflict
7979
- id: check-merge-conflict
@@ -91,24 +91,24 @@ repos:
9191
files: '^\.github/CODEOWNERS|\.(gram)$'
9292

9393
- repo: https://github.com/python-jsonschema/check-jsonschema
94-
rev: 0.36.1
94+
rev: 9f48a48aa91a6040d749ad68ec70907d907a5a7f # frozen: 0.37.0
9595
hooks:
9696
- id: check-dependabot
9797
- id: check-github-workflows
9898
- id: check-readthedocs
9999

100100
- repo: https://github.com/rhysd/actionlint
101-
rev: v1.7.10
101+
rev: 393031adb9afb225ee52ae2ccd7a5af5525e03e8 # frozen: v1.7.11
102102
hooks:
103103
- id: actionlint
104104

105-
- repo: https://github.com/woodruffw/zizmor-pre-commit
106-
rev: v1.22.0
105+
- repo: https://github.com/zizmorcore/zizmor-pre-commit
106+
rev: b546b77c44c466a54a42af5499dcc0dcc1a3193f # frozen: v1.22.0
107107
hooks:
108108
- id: zizmor
109109

110110
- repo: https://github.com/sphinx-contrib/sphinx-lint
111-
rev: v1.0.2
111+
rev: c883505f64b59c3c5c9375191e4ad9f98e727ccd # frozen: v1.0.2
112112
hooks:
113113
- id: sphinx-lint
114114
args: [--enable=default-role]

Lib/test/test_capi/test_dict.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,21 +97,13 @@ def test_dictproxy_new(self):
9797
def test_dict_copy(self):
9898
# Test PyDict_Copy()
9999
copy = _testlimitedcapi.dict_copy
100-
for dict_type in ANYDICT_TYPES:
100+
for dict_type in DICT_TYPES:
101101
dct = dict_type({1: 2})
102102
dct_copy = copy(dct)
103-
if dict_type == frozendict:
104-
expected_type = frozendict
105-
self.assertIs(dct_copy, dct)
106-
else:
107-
if issubclass(dict_type, frozendict):
108-
expected_type = frozendict
109-
else:
110-
expected_type = dict
111-
self.assertIs(type(dct_copy), expected_type)
112-
self.assertEqual(dct_copy, dct)
103+
self.assertIs(type(dct_copy), dict)
104+
self.assertEqual(dct_copy, dct)
113105

114-
for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES:
106+
for test_type in NOT_DICT_TYPES + OTHER_TYPES:
115107
self.assertRaises(SystemError, copy, test_type())
116108
self.assertRaises(SystemError, copy, NULL)
117109

Lib/test/test_dict.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,11 +1848,19 @@ def test_merge(self):
18481848
frozendict({'x': 1, 'y': 2}))
18491849
self.assertEqual(frozendict(x=1, y=2) | frozendict(y=5),
18501850
frozendict({'x': 1, 'y': 5}))
1851+
self.assertEqual(FrozenDict(x=1, y=2) | FrozenDict(y=5),
1852+
frozendict({'x': 1, 'y': 5}))
1853+
18511854
fd = frozendict(x=1, y=2)
18521855
self.assertIs(fd | frozendict(), fd)
18531856
self.assertIs(fd | {}, fd)
18541857
self.assertIs(frozendict() | fd, fd)
18551858

1859+
fd = FrozenDict(x=1, y=2)
1860+
self.assertEqual(fd | frozendict(), fd)
1861+
self.assertEqual(fd | {}, fd)
1862+
self.assertEqual(frozendict() | fd, fd)
1863+
18561864
def test_update(self):
18571865
# test "a |= b" operator
18581866
d = frozendict(x=1)
@@ -1863,6 +1871,11 @@ def test_update(self):
18631871
self.assertEqual(d, frozendict({'x': 1, 'y': 2}))
18641872
self.assertEqual(copy, frozendict({'x': 1}))
18651873

1874+
def test_items_xor(self):
1875+
# test "a ^ b" operator on items views
1876+
res = frozendict(a=1, b=2).items() ^ frozendict(b=2, c=3).items()
1877+
self.assertEqual(res, {('a', 1), ('c', 3)})
1878+
18661879
def test_repr(self):
18671880
d = frozendict()
18681881
self.assertEqual(repr(d), "frozendict()")

Lib/test/test_venv.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
import os.path
1212
import pathlib
1313
import re
14+
import shlex
1415
import shutil
1516
import subprocess
1617
import sys
1718
import sysconfig
1819
import tempfile
19-
import shlex
2020
from test.support import (captured_stdout, captured_stderr,
2121
skip_if_broken_multiprocessing_synchronize, verbose,
2222
requires_subprocess, is_android, is_apple_mobile,
@@ -373,6 +373,16 @@ def create_contents(self, paths, filename):
373373
with open(fn, 'wb') as f:
374374
f.write(b'Still here?')
375375

376+
@unittest.skipUnless(hasattr(os, 'listxattr'), 'test requires os.listxattr')
377+
def test_install_scripts_selinux(self):
378+
"""
379+
gh-145417: Test that install_scripts does not copy SELinux context
380+
when copying scripts.
381+
"""
382+
with patch('os.listxattr') as listxattr_mock:
383+
venv.create(self.env_dir)
384+
listxattr_mock.assert_not_called()
385+
376386
def test_overwrite_existing(self):
377387
"""
378388
Test creating environment in an existing directory.

Lib/venv/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ def skip_file(f):
581581
'may be binary: %s', srcfile, e)
582582
continue
583583
if new_data == data:
584-
shutil.copy2(srcfile, dstfile)
584+
shutil.copy(srcfile, dstfile)
585585
else:
586586
with open(dstfile, 'wb') as f:
587587
f.write(new_data)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:mod:`venv`: Prevent incorrect preservation of SELinux context
2+
when copying the ``Activate.ps1`` script. The script inherited
3+
the SELinux security context of the system template directory,
4+
rather than the destination project directory.

Objects/clinic/dictobject.c.h

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/dictobject.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,9 @@ static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override);
146146

147147
/*[clinic input]
148148
class dict "PyDictObject *" "&PyDict_Type"
149+
class frozendict "PyFrozenDictObject *" "&PyFrozenDict_Type"
149150
[clinic start generated code]*/
150-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
151+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5dfa93bac68e7c54]*/
151152

152153

153154
/*
@@ -2406,7 +2407,7 @@ dict_unhashable_type(PyObject *op, PyObject *key)
24062407
}
24072408

24082409
const char *errmsg;
2409-
if (PyObject_IsInstance(op, (PyObject*)&PyFrozenDict_Type)) {
2410+
if (PyFrozenDict_Check(op)) {
24102411
errmsg = "cannot use '%T' as a frozendict key (%S)";
24112412
}
24122413
else {
@@ -4384,35 +4385,37 @@ copy_lock_held(PyObject *o, int as_frozendict)
43844385
return NULL;
43854386
}
43864387

4387-
// Similar to PyDict_Copy(), but copy also frozendict.
4388-
static PyObject *
4389-
_PyDict_Copy(PyObject *o)
4388+
PyObject *
4389+
PyDict_Copy(PyObject *o)
43904390
{
4391-
assert(PyAnyDict_Check(o));
4391+
if (o == NULL || !PyDict_Check(o)) {
4392+
PyErr_BadInternalCall();
4393+
return NULL;
4394+
}
43924395

43934396
PyObject *res;
43944397
Py_BEGIN_CRITICAL_SECTION(o);
4395-
res = copy_lock_held(o, PyFrozenDict_Check(o));
4398+
res = copy_lock_held(o, 0);
43964399
Py_END_CRITICAL_SECTION();
43974400
return res;
43984401
}
43994402

4400-
PyObject *
4401-
PyDict_Copy(PyObject *o)
4403+
// Similar to PyDict_Copy(), but return a frozendict if the argument
4404+
// is a frozendict.
4405+
static PyObject *
4406+
anydict_copy(PyObject *o)
44024407
{
4403-
if (o == NULL || !PyAnyDict_Check(o)) {
4404-
PyErr_BadInternalCall();
4405-
return NULL;
4406-
}
4407-
4408-
if (PyFrozenDict_CheckExact(o)) {
4409-
return Py_NewRef(o);
4410-
}
4408+
assert(PyAnyDict_Check(o));
44114409

4412-
return _PyDict_Copy(o);
4410+
PyObject *res;
4411+
Py_BEGIN_CRITICAL_SECTION(o);
4412+
res = copy_lock_held(o, PyFrozenDict_Check(o));
4413+
Py_END_CRITICAL_SECTION();
4414+
return res;
44134415
}
44144416

4415-
// Similar to PyDict_Copy(), but return a dict if the argument is a frozendict.
4417+
// Similar to PyDict_Copy(), but accept also frozendict:
4418+
// convert frozendict to a new dict.
44164419
PyObject*
44174420
_PyDict_CopyAsDict(PyObject *o)
44184421
{
@@ -4969,7 +4972,7 @@ dict_or(PyObject *self, PyObject *other)
49694972
if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) {
49704973
Py_RETURN_NOTIMPLEMENTED;
49714974
}
4972-
PyObject *new = _PyDict_Copy(self);
4975+
PyObject *new = anydict_copy(self);
49734976
if (new == NULL) {
49744977
return NULL;
49754978
}
@@ -6523,7 +6526,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2)
65236526
ASSERT_DICT_LOCKED(d1);
65246527
ASSERT_DICT_LOCKED(d2);
65256528

6526-
PyObject *temp_dict = copy_lock_held(d1, PyFrozenDict_Check(d1));
6529+
PyObject *temp_dict = copy_lock_held(d1, 0);
65276530
if (temp_dict == NULL) {
65286531
return NULL;
65296532
}
@@ -8057,7 +8060,7 @@ static PyMethodDef frozendict_methods[] = {
80578060
DICT_ITEMS_METHODDEF
80588061
DICT_VALUES_METHODDEF
80598062
DICT_FROMKEYS_METHODDEF
8060-
DICT_COPY_METHODDEF
8063+
FROZENDICT_COPY_METHODDEF
80618064
DICT___REVERSED___METHODDEF
80628065
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
80638066
{"__getnewargs__", frozendict_getnewargs, METH_NOARGS},
@@ -8182,6 +8185,25 @@ PyFrozenDict_New(PyObject *iterable)
81828185
}
81838186
}
81848187

8188+
/*[clinic input]
8189+
frozendict.copy
8190+
8191+
Return a shallow copy of the frozendict.
8192+
[clinic start generated code]*/
8193+
8194+
static PyObject *
8195+
frozendict_copy_impl(PyFrozenDictObject *self)
8196+
/*[clinic end generated code: output=e580fd91d9fc2cf7 input=35f6abeaa08fd4bc]*/
8197+
{
8198+
assert(PyFrozenDict_Check(self));
8199+
8200+
if (PyFrozenDict_CheckExact(self)) {
8201+
return Py_NewRef(self);
8202+
}
8203+
8204+
return anydict_copy((PyObject*)self);
8205+
}
8206+
81858207

81868208
PyTypeObject PyFrozenDict_Type = {
81878209
PyVarObject_HEAD_INIT(&PyType_Type, 0)

0 commit comments

Comments
 (0)