@@ -1212,182 +1212,6 @@ def visitModule(self, mod):
1212
1212
return result;
1213
1213
}
1214
1214
1215
- /*
1216
- * Perform the following validations:
1217
- *
1218
- * - All keyword arguments are known 'fields' or 'attributes'.
1219
- * - No field or attribute would be left unfilled after copy.replace().
1220
- *
1221
- * On success, this returns 1. Otherwise, set a TypeError
1222
- * exception and returns -1 (no exception is set if some
1223
- * other internal errors occur).
1224
- *
1225
- * Parameters
1226
- *
1227
- * self The AST node instance.
1228
- * dict The AST node instance dictionary (self.__dict__).
1229
- * fields The list of fields (self._fields).
1230
- * attributes The list of attributes (self._attributes).
1231
- * kwargs Keyword arguments passed to ast_type_replace().
1232
- *
1233
- * The 'dict', 'fields', 'attributes' and 'kwargs' arguments can be NULL.
1234
- *
1235
- * Note: this function can be removed in 3.15 since the verification
1236
- * will be done inside the constructor.
1237
- */
1238
- static inline int
1239
- ast_type_replace_check(PyObject *self,
1240
- PyObject *dict,
1241
- PyObject *fields,
1242
- PyObject *attributes,
1243
- PyObject *kwargs)
1244
- {
1245
- // While it is possible to make some fast paths that would avoid
1246
- // allocating objects on the stack, this would cost us readability.
1247
- // For instance, if 'fields' and 'attributes' are both empty, and
1248
- // 'kwargs' is not empty, we could raise a TypeError immediately.
1249
- PyObject *expecting = PySet_New(fields);
1250
- if (expecting == NULL) {
1251
- return -1;
1252
- }
1253
- if (attributes) {
1254
- if (_PySet_Update(expecting, attributes) < 0) {
1255
- Py_DECREF(expecting);
1256
- return -1;
1257
- }
1258
- }
1259
- // Any keyword argument that is neither a field nor attribute is rejected.
1260
- // We first need to check whether a keyword argument is accepted or not.
1261
- // If all keyword arguments are accepted, we compute the required fields
1262
- // and attributes. A field or attribute is not needed if:
1263
- //
1264
- // 1) it is given in 'kwargs', or
1265
- // 2) it already exists on 'self'.
1266
- if (kwargs) {
1267
- Py_ssize_t pos = 0;
1268
- PyObject *key, *value;
1269
- while (PyDict_Next(kwargs, &pos, &key, &value)) {
1270
- int rc = PySet_Discard(expecting, key);
1271
- if (rc < 0) {
1272
- Py_DECREF(expecting);
1273
- return -1;
1274
- }
1275
- if (rc == 0) {
1276
- PyErr_Format(PyExc_TypeError,
1277
- "%.400s.__replace__ got an unexpected keyword "
1278
- "argument '%U'.", Py_TYPE(self)->tp_name, key);
1279
- Py_DECREF(expecting);
1280
- return -1;
1281
- }
1282
- }
1283
- }
1284
- // check that the remaining fields or attributes would be filled
1285
- if (dict) {
1286
- Py_ssize_t pos = 0;
1287
- PyObject *key, *value;
1288
- while (PyDict_Next(dict, &pos, &key, &value)) {
1289
- // Mark fields or attributes that are found on the instance
1290
- // as non-mandatory. If they are not given in 'kwargs', they
1291
- // will be shallow-coied; otherwise, they would be replaced
1292
- // (not in this function).
1293
- if (PySet_Discard(expecting, key) < 0) {
1294
- Py_DECREF(expecting);
1295
- return -1;
1296
- }
1297
- }
1298
- if (attributes) {
1299
- // Some attributes may or may not be present at runtime.
1300
- // In particular, now that we checked whether 'kwargs'
1301
- // is correct or not, we allow any attribute to be missing.
1302
- //
1303
- // Note that fields must still be entirely determined when
1304
- // calling the constructor later.
1305
- PyObject *unused = PyObject_CallMethodOneArg(expecting,
1306
- &_Py_ID(difference_update),
1307
- attributes);
1308
- if (unused == NULL) {
1309
- Py_DECREF(expecting);
1310
- return -1;
1311
- }
1312
- Py_DECREF(unused);
1313
- }
1314
- }
1315
-
1316
- // Discard fields from 'expecting' that default to None
1317
- PyObject *field_types = NULL;
1318
- if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self),
1319
- &_Py_ID(_field_types),
1320
- &field_types) < 0)
1321
- {
1322
- Py_DECREF(expecting);
1323
- return -1;
1324
- }
1325
- if (field_types != NULL) {
1326
- Py_ssize_t pos = 0;
1327
- PyObject *field_name, *field_type;
1328
- while (PyDict_Next(field_types, &pos, &field_name, &field_type)) {
1329
- if (_PyUnion_Check(field_type)) {
1330
- // optional field
1331
- if (PySet_Discard(expecting, field_name) < 0) {
1332
- Py_DECREF(expecting);
1333
- Py_DECREF(field_types);
1334
- return -1;
1335
- }
1336
- }
1337
- }
1338
- Py_DECREF(field_types);
1339
- }
1340
-
1341
- // Now 'expecting' contains the fields or attributes
1342
- // that would not be filled inside ast_type_replace().
1343
- Py_ssize_t m = PySet_GET_SIZE(expecting);
1344
- if (m > 0) {
1345
- PyObject *names = PyList_New(m);
1346
- if (names == NULL) {
1347
- Py_DECREF(expecting);
1348
- return -1;
1349
- }
1350
- Py_ssize_t i = 0, pos = 0;
1351
- PyObject *item;
1352
- Py_hash_t hash;
1353
- while (_PySet_NextEntry(expecting, &pos, &item, &hash)) {
1354
- PyObject *name = PyObject_Repr(item);
1355
- if (name == NULL) {
1356
- Py_DECREF(expecting);
1357
- Py_DECREF(names);
1358
- return -1;
1359
- }
1360
- // steal the reference 'name'
1361
- PyList_SET_ITEM(names, i++, name);
1362
- }
1363
- Py_DECREF(expecting);
1364
- if (PyList_Sort(names) < 0) {
1365
- Py_DECREF(names);
1366
- return -1;
1367
- }
1368
- PyObject *sep = PyUnicode_FromString(", ");
1369
- if (sep == NULL) {
1370
- Py_DECREF(names);
1371
- return -1;
1372
- }
1373
- PyObject *str_names = PyUnicode_Join(sep, names);
1374
- Py_DECREF(sep);
1375
- Py_DECREF(names);
1376
- if (str_names == NULL) {
1377
- return -1;
1378
- }
1379
- PyErr_Format(PyExc_TypeError,
1380
- "%.400s.__replace__ missing %ld keyword argument%s: %U.",
1381
- Py_TYPE(self)->tp_name, m, m == 1 ? "" : "s", str_names);
1382
- Py_DECREF(str_names);
1383
- return -1;
1384
- }
1385
- else {
1386
- Py_DECREF(expecting);
1387
- return 1;
1388
- }
1389
- }
1390
-
1391
1215
/*
1392
1216
* Python equivalent:
1393
1217
*
@@ -1477,9 +1301,6 @@ def visitModule(self, mod):
1477
1301
if (PyObject_GetOptionalAttr(self, state->__dict__, &dict) < 0) {
1478
1302
goto cleanup;
1479
1303
}
1480
- if (ast_type_replace_check(self, dict, fields, attributes, kwargs) < 0) {
1481
- goto cleanup;
1482
- }
1483
1304
empty_tuple = PyTuple_New(0);
1484
1305
if (empty_tuple == NULL) {
1485
1306
goto cleanup;
0 commit comments