Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersDeepcopy.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
7// This file is included from another C file, help IDEs to still parse it on
8// its own.
9#ifdef __IDE_ONLY__
10#include "nuitka/prelude.h"
11#endif
12
13#if PYTHON_VERSION >= 0x390
14typedef struct {
15 PyObject_HEAD PyObject *origin;
16 PyObject *args;
17 PyObject *parameters;
18} GenericAliasObject;
19#endif
20
21typedef PyObject *(*copy_func)(PyThreadState *tstate, PyObject *);
22
23static PyObject *DEEP_COPY_ITEM(PyThreadState *tstate, PyObject *value, PyTypeObject **type, copy_func *copy_function);
24
25PyObject *DEEP_COPY_LIST(PyThreadState *tstate, PyObject *value) {
26 assert(PyList_CheckExact(value));
27
28 Py_ssize_t n = PyList_GET_SIZE(value);
29 PyObject *result = MAKE_LIST_EMPTY(tstate, n);
30
31 PyTypeObject *type = NULL;
32 copy_func copy_function = NULL;
33
34 for (Py_ssize_t i = 0; i < n; i++) {
35 PyObject *item = PyList_GET_ITEM(value, i);
36 if (i == 0) {
37 PyList_SET_ITEM(result, i, DEEP_COPY_ITEM(tstate, item, &type, &copy_function));
38 } else {
39 PyObject *new_item;
40
41 if (likely(type == Py_TYPE(item))) {
42 if (copy_function) {
43 new_item = copy_function(tstate, item);
44 } else {
45 new_item = item;
46 Py_INCREF(item);
47 }
48 } else {
49 new_item = DEEP_COPY_ITEM(tstate, item, &type, &copy_function);
50 }
51
52 PyList_SET_ITEM(result, i, new_item);
53 }
54 }
55
56 return result;
57}
58
59PyObject *DEEP_COPY_TUPLE(PyThreadState *tstate, PyObject *value) {
60 assert(PyTuple_CheckExact(value));
61
62 Py_ssize_t n = PyTuple_GET_SIZE(value);
63
64 PyObject *result = MAKE_TUPLE_EMPTY_VAR(tstate, n);
65
66 for (Py_ssize_t i = 0; i < n; i++) {
67 PyTuple_SET_ITEM(result, i, DEEP_COPY(tstate, PyTuple_GET_ITEM(value, i)));
68 }
69
70 return result;
71}
72
73static PyObject *_DEEP_COPY_SET(PyObject *value) {
74 // Sets cannot contain non-hashable types, so these all must be immutable,
75 // but the set itself might be changed, so we need to copy it.
76 return PySet_New(value);
77}
78
79PyObject *DEEP_COPY_SET(PyThreadState *tstate, PyObject *value) { return _DEEP_COPY_SET(value); }
80
81#if PYTHON_VERSION >= 0x390
82PyObject *DEEP_COPY_GENERICALIAS(PyThreadState *tstate, PyObject *value) {
83 assert(Py_TYPE(value) == &Py_GenericAliasType);
84
85 GenericAliasObject *generic_alias = (GenericAliasObject *)value;
86
87 PyObject *args = DEEP_COPY(tstate, generic_alias->args);
88 PyObject *origin = DEEP_COPY(tstate, generic_alias->origin);
89
90 if (generic_alias->args == args && generic_alias->origin == origin) {
91 Py_INCREF(value);
92 return value;
93 } else {
94 return Py_GenericAlias(origin, args);
95 }
96}
97#endif
98
99static PyObject *_deep_copy_dispatch = NULL;
100static PyObject *_deep_noop = NULL;
101
102static PyObject *Nuitka_CapsuleNew(void *pointer) {
103#if PYTHON_VERSION < 0x300
104 return PyCObject_FromVoidPtr(pointer, NULL);
105#else
106 return PyCapsule_New(pointer, "", NULL);
107#endif
108}
109
110#if PYTHON_VERSION >= 0x300
111typedef struct {
112 PyObject_HEAD void *pointer;
113 const char *name;
114 void *context;
115 PyCapsule_Destructor destructor;
116} Nuitka_PyCapsule;
117
118#define Nuitka_CapsuleGetPointer(capsule) (((Nuitka_PyCapsule *)(capsule))->pointer)
119
120#else
121#define Nuitka_CapsuleGetPointer(capsule) (PyCObject_AsVoidPtr(capsule))
122#endif
123
124#if PYTHON_VERSION >= 0x3a0
125PyTypeObject *Nuitka_PyUnion_Type;
126#endif
127
128static PyObject *_makeDeepCopyFunctionCapsule(copy_func func) { return Nuitka_CapsuleNew((void *)func); }
129
130static void _initDeepCopy(void) {
131 _deep_copy_dispatch = PyDict_New();
132 _deep_noop = Py_None;
133
134 CHECK_OBJECT(_deep_noop);
135
136 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyDict_Type, _makeDeepCopyFunctionCapsule(DEEP_COPY_DICT));
137 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyList_Type, _makeDeepCopyFunctionCapsule(DEEP_COPY_LIST));
138 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyTuple_Type, _makeDeepCopyFunctionCapsule(DEEP_COPY_TUPLE));
139 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PySet_Type, _makeDeepCopyFunctionCapsule(DEEP_COPY_SET));
140 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyByteArray_Type, _makeDeepCopyFunctionCapsule(BYTEARRAY_COPY));
141
142#if PYTHON_VERSION >= 0x390
143 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&Py_GenericAliasType,
144 _makeDeepCopyFunctionCapsule(DEEP_COPY_GENERICALIAS));
145#endif
146
147#if PYTHON_VERSION >= 0x3a0
148 {
149 PyThreadState *tstate = PyThreadState_GET();
150
151 PyObject *args[2] = {(PyObject *)&PyFloat_Type, (PyObject *)&PyTuple_Type};
152 PyObject *args_tuple = MAKE_TUPLE(tstate, args, 2);
153 PyObject *union_value = MAKE_UNION_TYPE(args_tuple);
154
155 Nuitka_PyUnion_Type = Py_TYPE(union_value);
156
157 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Nuitka_PyUnion_Type, _deep_noop);
158
159 Py_DECREF(union_value);
160 Py_DECREF(args_tuple);
161 }
162
163#endif
164
165#if PYTHON_VERSION < 0x300
166 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyString_Type, _deep_noop);
167 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyInt_Type, _deep_noop);
168#else
169 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyBytes_Type, _deep_noop);
170#endif
171 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyUnicode_Type, _deep_noop);
172 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyLong_Type, _deep_noop);
173 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_None), _deep_noop);
174 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyBool_Type, _deep_noop);
175 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyFloat_Type, _deep_noop);
176 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyRange_Type, _deep_noop);
177 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyType_Type, _deep_noop);
178 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PySlice_Type, _deep_noop);
179 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyComplex_Type, _deep_noop);
180 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyCFunction_Type, _deep_noop);
181 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_Ellipsis), _deep_noop);
182 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)Py_TYPE(Py_NotImplemented), _deep_noop);
183
184 // Sets can be changed, but not a frozenset.
185 PyDict_SetItem(_deep_copy_dispatch, (PyObject *)&PyFrozenSet_Type, _deep_noop);
186}
187
188static PyObject *DEEP_COPY_ITEM(PyThreadState *tstate, PyObject *value, PyTypeObject **type, copy_func *copy_function) {
189 *type = Py_TYPE(value);
190
191 PyObject *dispatcher = DICT_GET_ITEM0(tstate, _deep_copy_dispatch, (PyObject *)*type);
192
193 if (unlikely(dispatcher == NULL)) {
194 NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type");
195 }
196
197 if (dispatcher == Py_None) {
198 *copy_function = NULL;
199
200 Py_INCREF(value);
201 return value;
202 } else {
203 *copy_function = (copy_func)(Nuitka_CapsuleGetPointer(dispatcher));
204 return (*copy_function)(tstate, value);
205 }
206}
207
208PyObject *DEEP_COPY(PyThreadState *tstate, PyObject *value) {
209#if 1
210 PyObject *dispatcher = DICT_GET_ITEM0(tstate, _deep_copy_dispatch, (PyObject *)Py_TYPE(value));
211
212 if (unlikely(dispatcher == NULL)) {
213 NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type");
214 }
215
216 if (dispatcher == Py_None) {
217 Py_INCREF(value);
218 return value;
219 } else {
220 copy_func copy_function = (copy_func)(Nuitka_CapsuleGetPointer(dispatcher));
221 return copy_function(tstate, value);
222 }
223
224#else
225
226 if (PyDict_CheckExact(value)) {
227 return DEEP_COPY_DICT(value);
228 } else if (PyList_CheckExact(value)) {
229 return DEEP_COPY_LIST(value);
230 } else if (PyTuple_CheckExact(value)) {
231 return DEEP_COPY_TUPLE(value);
232 } else if (PySet_CheckExact(value)) {
233 return DEEP_COPY_SET(value);
234 } else if (PyFrozenSet_CheckExact(value)) {
235 // Sets cannot contain non-hashable types, so they must be immutable and
236 // the frozenset itself is immutable.
237 return value;
238 } else if (
239#if PYTHON_VERSION < 0x300
240 PyString_Check(value) ||
241#endif
242 PyUnicode_Check(value) ||
243#if PYTHON_VERSION < 0x300
244 PyInt_CheckExact(value) ||
245#endif
246 PyLong_CheckExact(value) || value == Py_None || PyBool_Check(value) || PyFloat_CheckExact(value) ||
247 PyBytes_CheckExact(value) || PyRange_Check(value) || PyType_Check(value) || PySlice_Check(value) ||
248 PyComplex_CheckExact(value) || PyCFunction_Check(value) || value == Py_Ellipsis || value == Py_NotImplemented) {
249 Py_INCREF(value);
250 return value;
251 } else if (PyByteArray_CheckExact(value)) {
252 // TODO: Could make an exception for zero size.
253 return PyByteArray_FromObject(value);
254#if PYTHON_VERSION >= 0x390
255 } else if (Py_TYPE(value) == &Py_GenericAliasType) {
256 GenericAliasObject *generic_alias = (GenericAliasObject *)value;
257
258 PyObject *args = DEEP_COPY(generic_alias->args);
259 PyObject *origin = DEEP_COPY(generic_alias->origin);
260
261 if (generic_alias->args == args && generic_alias->origin == origin) {
262 Py_INCREF(value);
263 return value;
264 } else {
265 return Py_GenericAlias(origin, args);
266 }
267#endif
268 } else {
269 NUITKA_CANNOT_GET_HERE("DEEP_COPY encountered unknown type");
270 }
271#endif
272}
273
274#ifndef __NUITKA_NO_ASSERT__
275
276static Py_hash_t DEEP_HASH_INIT(PyThreadState *tstate, PyObject *value) {
277 // To avoid warnings about reduced sizes, we put an intermediate value
278 // that is size_t.
279 size_t value2 = (size_t)value;
280 Py_hash_t result = (Py_hash_t)(value2);
281
282 if (Py_TYPE(value) != &PyType_Type) {
283 result ^= DEEP_HASH(tstate, (PyObject *)Py_TYPE(value));
284 }
285
286 return result;
287}
288
289static void DEEP_HASH_BLOB(Py_hash_t *hash, char const *s, Py_ssize_t size) {
290 while (size > 0) {
291 *hash = (1000003 * (*hash)) ^ (Py_hash_t)(*s++);
292 size--;
293 }
294}
295
296static void DEEP_HASH_CSTR(Py_hash_t *hash, char const *s) { DEEP_HASH_BLOB(hash, s, strlen(s)); }
297
298// Hash function that actually verifies things done to the bit level. Can be
299// used to detect corruption.
300Py_hash_t DEEP_HASH(PyThreadState *tstate, PyObject *value) {
301 assert(value != NULL);
302
303 if (PyType_Check(value)) {
304 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
305
306 DEEP_HASH_CSTR(&result, ((PyTypeObject *)value)->tp_name);
307 return result;
308 } else if (PyDict_Check(value)) {
309 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
310
311 Py_ssize_t pos = 0;
312 PyObject *key, *dict_value;
313
314 while (Nuitka_DictNext(value, &pos, &key, &dict_value)) {
315 if (key != NULL && value != NULL) {
316 result ^= DEEP_HASH(tstate, key);
317 result ^= DEEP_HASH(tstate, dict_value);
318 }
319 }
320
321 return result;
322 } else if (PyTuple_Check(value)) {
323 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
324
325 Py_ssize_t n = PyTuple_GET_SIZE(value);
326
327 for (Py_ssize_t i = 0; i < n; i++) {
328 result ^= DEEP_HASH(tstate, PyTuple_GET_ITEM(value, i));
329 }
330
331 return result;
332 } else if (PyList_CheckExact(value)) {
333 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
334
335 Py_ssize_t n = PyList_GET_SIZE(value);
336
337 for (Py_ssize_t i = 0; i < n; i++) {
338 result ^= DEEP_HASH(tstate, PyList_GET_ITEM(value, i));
339 }
340
341 return result;
342 } else if (PySet_Check(value) || PyFrozenSet_Check(value)) {
343 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
344
345 PyObject *iterator = PyObject_GetIter(value);
346 CHECK_OBJECT(iterator);
347
348 while (true) {
349 PyObject *item = PyIter_Next(iterator);
350 if (!item)
351 break;
352
353 CHECK_OBJECT(item);
354
355 result ^= DEEP_HASH(tstate, item);
356
357 Py_DECREF(item);
358 }
359
360 Py_DECREF(iterator);
361
362 return result;
363 } else if (PyLong_Check(value)) {
364 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
365
366 struct Nuitka_ExceptionPreservationItem saved_exception_state;
367
368 FETCH_ERROR_OCCURRED_STATE_UNTRACED(tstate, &saved_exception_state);
369
370 // Use string to hash the long value, which relies on that to not
371 // use the object address.
372 PyObject *str = PyObject_Str(value);
373 result ^= DEEP_HASH(tstate, str);
374 Py_DECREF(str);
375
376 RESTORE_ERROR_OCCURRED_STATE_UNTRACED(tstate, &saved_exception_state);
377
378 return result;
379 } else if (PyUnicode_Check(value)) {
380 Py_hash_t result = DEEP_HASH(tstate, (PyObject *)Py_TYPE(value));
381
382 struct Nuitka_ExceptionPreservationItem saved_exception_state;
383
384 FETCH_ERROR_OCCURRED_STATE_UNTRACED(tstate, &saved_exception_state);
385
386#if PYTHON_VERSION >= 0x300
387 char const *s = (char const *)PyUnicode_DATA(value);
388 Py_ssize_t size = PyUnicode_GET_LENGTH(value) * PyUnicode_KIND(value);
389
390 DEEP_HASH_BLOB(&result, s, size);
391#else
392 PyObject *str = PyUnicode_AsUTF8String(value);
393
394 if (str) {
395 result ^= DEEP_HASH(tstate, str);
396 }
397
398 Py_DECREF(str);
399#endif
400 RESTORE_ERROR_OCCURRED_STATE_UNTRACED(tstate, &saved_exception_state);
401
402 return result;
403 }
404#if PYTHON_VERSION < 0x300
405 else if (PyString_Check(value)) {
406 Py_hash_t result = DEEP_HASH(tstate, (PyObject *)Py_TYPE(value));
407
408 Py_ssize_t size;
409 char *s;
410
411 int res = PyString_AsStringAndSize(value, &s, &size);
412 assert(res != -1);
413
414 DEEP_HASH_BLOB(&result, s, size);
415
416 return result;
417 }
418#else
419 else if (PyBytes_Check(value)) {
420 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
421
422 Py_ssize_t size;
423 char *s;
424
425 int res = PyBytes_AsStringAndSize(value, &s, &size);
426 assert(res != -1);
427
428 DEEP_HASH_BLOB(&result, s, size);
429
430 return result;
431 }
432#endif
433 else if (PyByteArray_Check(value)) {
434 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
435
436 Py_ssize_t size = PyByteArray_Size(value);
437 assert(size >= 0);
438
439 char *s = PyByteArray_AsString(value);
440
441 DEEP_HASH_BLOB(&result, s, size);
442
443 return result;
444 } else if (value == Py_None || value == Py_Ellipsis || value == Py_NotImplemented) {
445 return DEEP_HASH_INIT(tstate, value);
446 } else if (PyComplex_Check(value)) {
447 Py_complex c = PyComplex_AsCComplex(value);
448
449 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
450
451 Py_ssize_t size = sizeof(c);
452 char *s = (char *)&c;
453
454 DEEP_HASH_BLOB(&result, s, size);
455
456 return result;
457 } else if (PyFloat_Check(value)) {
458 double f = PyFloat_AsDouble(value);
459
460 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
461
462 Py_ssize_t size = sizeof(f);
463 char *s = (char *)&f;
464
465 DEEP_HASH_BLOB(&result, s, size);
466
467 return result;
468 } else if (
469#if PYTHON_VERSION < 0x300
470 PyInt_Check(value) ||
471#endif
472 PyBool_Check(value) || PyRange_Check(value) || PySlice_Check(value) || PyCFunction_Check(value)) {
473 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
474
475#if 0
476 printf("Too simple deep hash: %s\n", Py_TYPE(value)->tp_name);
477#endif
478
479 return result;
480#if PYTHON_VERSION >= 0x390
481 } else if (Py_TYPE(value) == &Py_GenericAliasType) {
482 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
483
484 GenericAliasObject *generic_alias = (GenericAliasObject *)value;
485
486 result ^= DEEP_HASH(tstate, generic_alias->args);
487 result ^= DEEP_HASH(tstate, generic_alias->origin);
488
489 return result;
490#endif
491#if PYTHON_VERSION >= 0x3a0
492 } else if (Py_TYPE(value) == Nuitka_PyUnion_Type) {
493 Py_hash_t result = DEEP_HASH_INIT(tstate, value);
494
495 result ^= DEEP_HASH(tstate, LOOKUP_ATTRIBUTE(tstate, value, const_str_plain___args__));
496
497 return result;
498#endif
499 } else if (PyCode_Check(value)) {
500 return DEEP_HASH_INIT(tstate, value);
501 } else {
502 NUITKA_CANNOT_GET_HERE("Unknown type hashed");
503
504 return -1;
505 }
506}
507#endif
508
509// Note: Not recursion safe, cannot do this everywhere.
510void CHECK_OBJECT_DEEP(PyObject *value) {
511 CHECK_OBJECT(value);
512
513 if (PyTuple_Check(value)) {
514 for (Py_ssize_t i = 0, size = PyTuple_GET_SIZE(value); i < size; i++) {
515 PyObject *element = PyTuple_GET_ITEM(value, i);
516
517 CHECK_OBJECT_DEEP(element);
518 }
519 } else if (PyList_CheckExact(value)) {
520 for (Py_ssize_t i = 0, size = PyList_GET_SIZE(value); i < size; i++) {
521 PyObject *element = PyList_GET_ITEM(value, i);
522
523 CHECK_OBJECT_DEEP(element);
524 }
525 } else if (PyDict_Check(value)) {
526 Py_ssize_t pos = 0;
527 PyObject *dict_key, *dict_value;
528
529 while (Nuitka_DictNext(value, &pos, &dict_key, &dict_value)) {
530 CHECK_OBJECT_DEEP(dict_key);
531 CHECK_OBJECT_DEEP(dict_value);
532 }
533 }
534}
535
536void CHECK_OBJECTS_DEEP(PyObject *const *values, Py_ssize_t size) {
537 for (Py_ssize_t i = 0; i < size; i++) {
538 CHECK_OBJECT_DEEP(values[i]);
539 }
540}
541
542static PyObject *_DEEP_COPY_LIST_GUIDED(PyThreadState *tstate, PyObject *value, char const **guide);
543static PyObject *_DEEP_COPY_TUPLE_GUIDED(PyThreadState *tstate, PyObject *value, char const **guide);
544
545static PyObject *_DEEP_COPY_ELEMENT_GUIDED(PyThreadState *tstate, PyObject *value, char const **guide) {
546 char code = **guide;
547 *guide += 1;
548
549 switch (code) {
550 case 'i':
551 Py_INCREF(value);
552 return value;
553 case 'L':
554 return _DEEP_COPY_LIST_GUIDED(tstate, value, guide);
555 case 'l':
556 return LIST_COPY(tstate, value);
557 case 'T':
558 return _DEEP_COPY_TUPLE_GUIDED(tstate, value, guide);
559 case 't':
560 return TUPLE_COPY(tstate, value);
561 case 'D':
562 return DEEP_COPY_DICT(tstate, value);
563 case 'd':
564 return DICT_COPY(tstate, value);
565 case 'S':
566 return DEEP_COPY_SET(tstate, value);
567 case 'B':
568 return BYTEARRAY_COPY(tstate, value);
569 case '?':
570 return DEEP_COPY(tstate, value);
571 default:
572 NUITKA_CANNOT_GET_HERE("Illegal type guide");
573 abort();
574 }
575}
576
577static PyObject *_DEEP_COPY_LIST_GUIDED(PyThreadState *tstate, PyObject *value, char const **guide) {
578 assert(PyList_CheckExact(value));
579
580 Py_ssize_t size = PyList_GET_SIZE(value);
581
582 PyObject *result = MAKE_LIST_EMPTY(tstate, size);
583
584 for (Py_ssize_t i = 0; i < size; i++) {
585 PyObject *item = _DEEP_COPY_ELEMENT_GUIDED(tstate, PyList_GET_ITEM(value, i), guide);
586
587 PyList_SET_ITEM(result, i, item);
588 }
589
590 return result;
591}
592
593static PyObject *_DEEP_COPY_TUPLE_GUIDED(PyThreadState *tstate, PyObject *value, char const **guide) {
594 assert(PyTuple_CheckExact(value));
595
596 Py_ssize_t size = PyTuple_GET_SIZE(value);
597
598 // We cannot have size 0, so this is safe.
599 assert(size > 0);
600 PyObject *result = MAKE_TUPLE_EMPTY(tstate, size);
601
602 for (Py_ssize_t i = 0; i < size; i++) {
603 PyObject *item = _DEEP_COPY_ELEMENT_GUIDED(tstate, PyTuple_GET_ITEM(value, i), guide);
604
605 PyTuple_SET_ITEM(result, i, item);
606 }
607
608 return result;
609}
610
611PyObject *DEEP_COPY_LIST_GUIDED(PyThreadState *tstate, PyObject *value, char const *guide) {
612 PyObject *result = _DEEP_COPY_LIST_GUIDED(tstate, value, &guide);
613 assert(*guide == 0);
614 return result;
615}
616
617PyObject *DEEP_COPY_TUPLE_GUIDED(PyThreadState *tstate, PyObject *value, char const *guide) {
618 PyObject *result = _DEEP_COPY_TUPLE_GUIDED(tstate, value, &guide);
619 assert(*guide == 0);
620 return result;
621}
622
623// Part of "Nuitka", an optimizing Python compiler that is compatible and
624// integrates with CPython, but also works on its own.
625//
626// Licensed under the Apache License, Version 2.0 (the "License");
627// you may not use this file except in compliance with the License.
628// You may obtain a copy of the License at
629//
630// http://www.apache.org/licenses/LICENSE-2.0
631//
632// Unless required by applicable law or agreed to in writing, software
633// distributed under the License is distributed on an "AS IS" BASIS,
634// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
635// See the License for the specific language governing permissions and
636// limitations under the License.
Definition exceptions.h:712