Skip to content

Commit 2689301

Browse files
authored
gh-106320: Remove private _PyDict functions (#108449)
Move private functions to the internal C API (pycore_dict.h): * _PyDictView_Intersect() * _PyDictView_New() * _PyDict_ContainsId() * _PyDict_DelItemId() * _PyDict_DelItem_KnownHash() * _PyDict_GetItemIdWithError() * _PyDict_GetItem_KnownHash() * _PyDict_HasSplitTable() * _PyDict_NewPresized() * _PyDict_Next() * _PyDict_Pop() * _PyDict_SetItemId() * _PyDict_SetItem_KnownHash() * _PyDict_SizeOf() No longer export most of these functions. Move also the _PyDictViewObject structure to the internal C API. Move dict_getitem_knownhash() function from _testcapi to the _testinternalcapi extension. Update test_capi.test_dict for this change.
1 parent c3d580b commit 2689301

File tree

12 files changed

+76
-57
lines changed

12 files changed

+76
-57
lines changed

Include/cpython/dictobject.h

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,8 @@ typedef struct {
3232
PyDictValues *ma_values;
3333
} PyDictObject;
3434

35-
PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key,
36-
Py_hash_t hash);
37-
PyAPI_FUNC(PyObject *) _PyDict_GetItemIdWithError(PyObject *dp,
38-
_Py_Identifier *key);
3935
PyAPI_FUNC(PyObject *) PyDict_SetDefault(
4036
PyObject *mp, PyObject *key, PyObject *defaultobj);
41-
PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key,
42-
PyObject *item, Py_hash_t hash);
43-
PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key,
44-
Py_hash_t hash);
45-
46-
PyAPI_FUNC(int) _PyDict_Next(
47-
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash);
4837

4938
/* Get the number of items of a dictionary. */
5039
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
@@ -56,26 +45,7 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
5645
#define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op))
5746

5847
PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key);
59-
PyAPI_FUNC(int) _PyDict_ContainsId(PyObject *, _Py_Identifier *);
60-
61-
PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
62-
PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *);
63-
PyAPI_FUNC(PyObject *) _PyDict_Pop(PyObject *, PyObject *, PyObject *);
64-
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)
65-
66-
PyAPI_FUNC(int) _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item);
67-
68-
PyAPI_FUNC(int) _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key);
69-
70-
/* _PyDictView */
71-
72-
typedef struct {
73-
PyObject_HEAD
74-
PyDictObject *dv_dict;
75-
} _PyDictViewObject;
7648

77-
PyAPI_FUNC(PyObject *) _PyDictView_New(PyObject *, PyTypeObject *);
78-
PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other);
7949

8050
/* Dictionary watchers */
8151

Include/internal/pycore_dict.h

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,45 @@ extern "C" {
1414
// Unsafe flavor of PyDict_GetItemWithError(): no error checking
1515
extern PyObject* _PyDict_GetItemWithError(PyObject *dp, PyObject *key);
1616

17-
extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t);
18-
1917
extern int _PyDict_DelItemIf(PyObject *mp, PyObject *key,
2018
int (*predicate)(PyObject *value));
2119

20+
// "KnownHash" variants
21+
// Export for '_testinternalcapi' shared extension
22+
PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key,
23+
Py_hash_t hash);
24+
// Export for '_asyncio' shared extension
25+
PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key,
26+
PyObject *item, Py_hash_t hash);
27+
// Export for '_asyncio' shared extension
28+
PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key,
29+
Py_hash_t hash);
30+
extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t);
31+
32+
// "Id" variants
33+
extern PyObject* _PyDict_GetItemIdWithError(PyObject *dp,
34+
_Py_Identifier *key);
35+
extern int _PyDict_ContainsId(PyObject *, _Py_Identifier *);
36+
extern int _PyDict_SetItemId(PyObject *dp, _Py_Identifier *key, PyObject *item);
37+
extern int _PyDict_DelItemId(PyObject *mp, _Py_Identifier *key);
38+
39+
extern int _PyDict_Next(
40+
PyObject *mp, Py_ssize_t *pos, PyObject **key, PyObject **value, Py_hash_t *hash);
41+
2242
extern int _PyDict_HasOnlyStringKeys(PyObject *mp);
2343

2444
extern void _PyDict_MaybeUntrack(PyObject *mp);
2545

46+
extern PyObject* _PyDict_NewPresized(Py_ssize_t minused);
47+
48+
// Export for '_ctypes' shared extension
49+
PyAPI_FUNC(Py_ssize_t) _PyDict_SizeOf(PyDictObject *);
50+
51+
// Export for '_socket' shared extension (Windows remove_unusable_flags())
52+
PyAPI_FUNC(PyObject*) _PyDict_Pop(PyObject *, PyObject *, PyObject *);
53+
54+
#define _PyDict_HasSplitTable(d) ((d)->ma_values != NULL)
55+
2656
/* Like PyDict_Merge, but override can be 0, 1 or 2. If override is 0,
2757
the first occurrence of a key wins, if override is 1, the last occurrence
2858
of a key wins, if override is 2, a KeyError with conflicting key as
@@ -32,6 +62,18 @@ extern int _PyDict_MergeEx(PyObject *mp, PyObject *other, int override);
3262

3363
extern void _PyDict_DebugMallocStats(FILE *out);
3464

65+
66+
/* _PyDictView */
67+
68+
typedef struct {
69+
PyObject_HEAD
70+
PyDictObject *dv_dict;
71+
} _PyDictViewObject;
72+
73+
extern PyObject* _PyDictView_New(PyObject *, PyTypeObject *);
74+
extern PyObject* _PyDictView_Intersect(PyObject* self, PyObject *other);
75+
76+
3577
/* runtime lifecycle */
3678

3779
extern void _PyDict_Fini(PyInterpreterState *interp);

Lib/test/test_dict.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,8 +1582,8 @@ class CAPITest(unittest.TestCase):
15821582
# Test _PyDict_GetItem_KnownHash()
15831583
@support.cpython_only
15841584
def test_getitem_knownhash(self):
1585-
_testcapi = import_helper.import_module('_testcapi')
1586-
dict_getitem_knownhash = _testcapi.dict_getitem_knownhash
1585+
_testinternalcapi = import_helper.import_module('_testinternalcapi')
1586+
dict_getitem_knownhash = _testinternalcapi.dict_getitem_knownhash
15871587

15881588
d = {'x': 1, 'y': 2, 'z': 3}
15891589
self.assertEqual(dict_getitem_knownhash(d, 'x', hash('x')), 1)

Modules/_asynciomodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#endif
44

55
#include "Python.h"
6+
#include "pycore_dict.h" // _PyDict_GetItem_KnownHash()
67
#include "pycore_moduleobject.h" // _PyModule_GetState()
78
#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
89
#include "pycore_pylifecycle.h" // _Py_IsInterpreterFinalizing()

Modules/_collectionsmodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "Python.h"
22
#include "pycore_call.h" // _PyObject_CallNoArgs()
3+
#include "pycore_dict.h" // _PyDict_GetItem_KnownHash()
34
#include "pycore_long.h" // _PyLong_GetZero()
45
#include "pycore_moduleobject.h" // _PyModule_GetState()
56
#include "pycore_typeobject.h" // _PyType_GetModuleState()

Modules/_ctypes/stgdict.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#endif
1010

1111
#include "pycore_call.h" // _PyObject_CallNoArgs()
12+
#include "pycore_dict.h" // _PyDict_SizeOf()
1213
#include <ffi.h>
1314
#ifdef MS_WIN32
1415
# include <malloc.h>

Modules/_sre/sre.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ static const char copyright[] =
3939
" SRE 2.2.2 Copyright (c) 1997-2002 by Secret Labs AB ";
4040

4141
#include "Python.h"
42+
#include "pycore_dict.h" // _PyDict_Next()
4243
#include "pycore_long.h" // _PyLong_GetZero()
4344
#include "pycore_moduleobject.h" // _PyModule_GetState()
4445

Modules/_testcapimodule.c

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -271,26 +271,6 @@ test_dict_iteration(PyObject* self, PyObject *Py_UNUSED(ignored))
271271
Py_RETURN_NONE;
272272
}
273273

274-
static PyObject*
275-
dict_getitem_knownhash(PyObject *self, PyObject *args)
276-
{
277-
PyObject *mp, *key, *result;
278-
Py_ssize_t hash;
279-
280-
if (!PyArg_ParseTuple(args, "OOn:dict_getitem_knownhash",
281-
&mp, &key, &hash)) {
282-
return NULL;
283-
}
284-
285-
result = _PyDict_GetItem_KnownHash(mp, key, (Py_hash_t)hash);
286-
if (result == NULL && !PyErr_Occurred()) {
287-
_PyErr_SetKeyError(key);
288-
return NULL;
289-
}
290-
291-
return Py_XNewRef(result);
292-
}
293-
294274
/* Issue #4701: Check that PyObject_Hash implicitly calls
295275
* PyType_Ready if it hasn't already been called
296276
*/
@@ -3353,7 +3333,6 @@ static PyMethodDef TestMethods[] = {
33533333
{"test_sizeof_c_types", test_sizeof_c_types, METH_NOARGS},
33543334
{"test_list_api", test_list_api, METH_NOARGS},
33553335
{"test_dict_iteration", test_dict_iteration, METH_NOARGS},
3356-
{"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},
33573336
{"test_lazy_hash_inheritance", test_lazy_hash_inheritance,METH_NOARGS},
33583337
{"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS},
33593338
{"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS},

Modules/_testinternalcapi.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,27 @@ new_hamt(PyObject *self, PyObject *args)
15721572
}
15731573

15741574

1575+
static PyObject*
1576+
dict_getitem_knownhash(PyObject *self, PyObject *args)
1577+
{
1578+
PyObject *mp, *key, *result;
1579+
Py_ssize_t hash;
1580+
1581+
if (!PyArg_ParseTuple(args, "OOn:dict_getitem_knownhash",
1582+
&mp, &key, &hash)) {
1583+
return NULL;
1584+
}
1585+
1586+
result = _PyDict_GetItem_KnownHash(mp, key, (Py_hash_t)hash);
1587+
if (result == NULL && !PyErr_Occurred()) {
1588+
_PyErr_SetKeyError(key);
1589+
return NULL;
1590+
}
1591+
1592+
return Py_XNewRef(result);
1593+
}
1594+
1595+
15751596
static PyMethodDef module_functions[] = {
15761597
{"get_configs", get_configs, METH_NOARGS},
15771598
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -1637,6 +1658,7 @@ static PyMethodDef module_functions[] = {
16371658
{"pymem_getallocatorsname", test_pymem_getallocatorsname, METH_NOARGS},
16381659
{"get_object_dict_values", get_object_dict_values, METH_O},
16391660
{"hamt", new_hamt, METH_NOARGS},
1661+
{"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS},
16401662
{NULL, NULL} /* sentinel */
16411663
};
16421664

Modules/_threadmodule.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44

55
#include "Python.h"
66
#include "pycore_ceval.h" // _PyEval_MakePendingCalls()
7+
#include "pycore_dict.h" // _PyDict_Pop()
78
#include "pycore_interp.h" // _PyInterpreterState.threads.count
89
#include "pycore_moduleobject.h" // _PyModule_GetState()
910
#include "pycore_pylifecycle.h"
1011
#include "pycore_pystate.h" // _PyThreadState_SetCurrent()
1112
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
12-
#include <stddef.h> // offsetof()
13-
1413

14+
#include <stddef.h> // offsetof()
1515
#ifdef HAVE_SIGNAL_H
1616
# include <signal.h> // SIGINT
1717
#endif

Modules/socketmodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ Local naming conventions:
106106
#endif
107107

108108
#include "Python.h"
109+
#include "pycore_dict.h" // _PyDict_Pop()
109110
#include "pycore_fileutils.h" // _Py_set_inheritable()
110111
#include "pycore_moduleobject.h" // _PyModule_GetState
111112

Python/import.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* Module definition and import implementation */
22

33
#include "Python.h"
4+
#include "pycore_dict.h" // _PyDict_Pop()
45
#include "pycore_hashtable.h" // _Py_hashtable_new_full()
56
#include "pycore_import.h" // _PyImport_BootstrapImp()
67
#include "pycore_initconfig.h" // _PyStatus_OK()

0 commit comments

Comments
 (0)