@@ -286,6 +286,43 @@ PyObject *_Dtool_Return(PyObject *value) {
286
286
}
287
287
288
288
#if PY_VERSION_HEX < 0x03040000
289
+ /* *
290
+ * This function converts an int value to the appropriate enum instance.
291
+ */
292
+ PyObject *Dtool_EnumType_New (PyTypeObject *subtype, PyObject *args, PyObject *kwds) {
293
+ PyObject *arg;
294
+ if (!Dtool_ExtractArg (&arg, args, kwds, " value" )) {
295
+ return PyErr_Format (PyExc_TypeError,
296
+ " %s() missing 1 required argument: 'value'" ,
297
+ subtype->tp_name );
298
+ }
299
+
300
+ if (Py_TYPE (arg) == subtype) {
301
+ Py_INCREF (arg);
302
+ return arg;
303
+ }
304
+
305
+ PyObject *value2member = PyDict_GetItemString (subtype->tp_dict , " _value2member_map_" );
306
+ nassertr_always (value2member != nullptr , nullptr );
307
+
308
+ PyObject *member = PyDict_GetItem (value2member, arg);
309
+ if (member != nullptr ) {
310
+ Py_INCREF (member);
311
+ return member;
312
+ }
313
+
314
+ PyObject *repr = PyObject_Repr (arg);
315
+ PyErr_Format (PyExc_ValueError, " %s is not a valid %s" ,
316
+ #if PY_MAJOR_VERSION >= 3
317
+ PyUnicode_AS_STRING (repr),
318
+ #else
319
+ PyString_AS_STRING (repr),
320
+ #endif
321
+ subtype->tp_name );
322
+ Py_DECREF (repr);
323
+ return nullptr ;
324
+ }
325
+
289
326
static PyObject *Dtool_EnumType_Str (PyObject *self) {
290
327
PyObject *name = PyObject_GetAttrString (self, " name" );
291
328
#if PY_MAJOR_VERSION >= 3
@@ -337,18 +374,21 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha
337
374
static PyObject *name_sunder_str;
338
375
static PyObject *value_str;
339
376
static PyObject *value_sunder_str;
377
+ static PyObject *value2member_map_sunder_str;
340
378
// Emulate something vaguely like the enum module.
341
379
if (enum_class == nullptr ) {
342
380
#if PY_MAJOR_VERSION >= 3
343
381
name_str = PyUnicode_InternFromString (" name" );
344
382
value_str = PyUnicode_InternFromString (" value" );
345
383
name_sunder_str = PyUnicode_InternFromString (" _name_" );
346
384
value_sunder_str = PyUnicode_InternFromString (" _value_" );
385
+ value2member_map_sunder_str = PyUnicode_InternFromString (" _value2member_map_" );
347
386
#else
348
387
name_str = PyString_InternFromString (" name" );
349
388
value_str = PyString_InternFromString (" value" );
350
389
name_sunder_str = PyString_InternFromString (" _name_" );
351
390
value_sunder_str = PyString_InternFromString (" _value_" );
391
+ value2member_map_sunder_str = PyString_InternFromString (" _value2member_map_" );
352
392
#endif
353
393
PyObject *name_value_tuple = PyTuple_New (4 );
354
394
PyTuple_SET_ITEM (name_value_tuple, 0 , name_str);
@@ -365,27 +405,39 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha
365
405
enum_class = PyObject_CallFunction ((PyObject *)&PyType_Type, (char *)" s()N" , " Enum" , slots_dict);
366
406
nassertr (enum_class != nullptr , nullptr );
367
407
}
368
- PyObject *result = PyObject_CallFunction ((PyObject *)&PyType_Type, (char *)" s(O)N" , name, enum_class, PyDict_New ());
408
+
409
+ // Create a subclass of this generic Enum class we just created.
410
+ PyObject *value2member = PyDict_New ();
411
+ PyObject *dict = PyDict_New ();
412
+ PyDict_SetItem (dict, value2member_map_sunder_str, value2member);
413
+ PyObject *result = PyObject_CallFunction ((PyObject *)&PyType_Type, (char *)" s(O)N" , name, enum_class, dict);
369
414
nassertr (result != nullptr , nullptr );
370
415
416
+ ((PyTypeObject *)result)->tp_new = Dtool_EnumType_New;
371
417
((PyTypeObject *)result)->tp_str = Dtool_EnumType_Str;
372
418
((PyTypeObject *)result)->tp_repr = Dtool_EnumType_Repr;
373
419
374
- // Copy the names as instances of the above to the class dict.
420
+ PyObject *empty_tuple = PyTuple_New (0 );
421
+
422
+ // Copy the names as instances of the above to the class dict, and create a
423
+ // reverse mapping in the _value2member_map_ dict.
375
424
Py_ssize_t size = PyTuple_GET_SIZE (names);
376
425
for (Py_ssize_t i = 0 ; i < size; ++i) {
377
426
PyObject *item = PyTuple_GET_ITEM (names, i);
378
427
PyObject *name = PyTuple_GET_ITEM (item, 0 );
379
428
PyObject *value = PyTuple_GET_ITEM (item, 1 );
380
- PyObject *member = _PyObject_CallNoArg ( result);
429
+ PyObject *member = PyType_GenericNew ((PyTypeObject *) result, empty_tuple, nullptr );
381
430
PyObject_SetAttr (member, name_str, name);
382
431
PyObject_SetAttr (member, name_sunder_str, name);
383
432
PyObject_SetAttr (member, value_str, value);
384
433
PyObject_SetAttr (member, value_sunder_str, value);
385
434
PyObject_SetAttr (result, name, member);
435
+ PyDict_SetItem (value2member, value, member);
386
436
Py_DECREF (member);
387
437
}
388
438
Py_DECREF (names);
439
+ Py_DECREF (value2member);
440
+ Py_DECREF (empty_tuple);
389
441
#endif
390
442
391
443
if (module != nullptr ) {
0 commit comments