@@ -12,270 +12,24 @@ DialectCspEnumMeta::DialectCspEnumMeta( PyTypeObjectPtr pyType, const std::strin
1212 CspEnumMeta ( name, def ),
1313 m_pyType ( pyType )
1414{
15- m_isPyIntEnum = PyType_IsSubtype ( pyType.get (), CspTypeFactory::instance ().intEnumPyType () );
16- }
17-
18- /*
19- MetaClass Madness NOTES!!! -- see PyStruct.cpp for note, same idea
20- */
21-
22- static PyObject * PyCspEnumMeta_new ( PyTypeObject *subtype, PyObject *args, PyObject *kwds )
23- {
24- CSP_BEGIN_METHOD ;
25-
26- PyObject * pyname;
27- PyObject * bases;
28- PyObject * dict;
29- if ( !PyArg_ParseTuple ( args, " UO!O!" ,
30- &pyname,
31- &PyTuple_Type, &bases,
32- &PyDict_Type, &dict ) )
33- CSP_THROW ( PythonPassthrough, " " );
34-
35- // subtype is python defined CspEnumMeta class
36- PyCspEnumMeta * pymeta = ( PyCspEnumMeta * ) PyType_Type.tp_new ( subtype, args, kwds );
37-
38- // Note that we call ctor without parents so as not to 0-init the base POD PyTypeObject class after its been initialized
39- new ( pymeta ) PyCspEnumMeta;
40-
41- // this would be the CspEnum class on python side, it doesnt create any metadata for itself
42- if ( pymeta -> ht_type.tp_base == &PyCspEnum::PyType )
43- return ( PyObject * ) pymeta;
44-
45- std::string name = PyUnicode_AsUTF8 ( pyname );
46-
47- PyObject * metadata = PyDict_GetItemString ( dict, " __metadata__" );
48- if ( !metadata )
49- CSP_THROW ( KeyError, " CspEnumMeta missing __metadata__" );
50-
51- CspEnumMeta::ValueDef def;
52-
53- {
54- PyObject *key, *value;
55- Py_ssize_t pos = 0 ;
56- while ( PyDict_Next ( metadata, &pos, &key, &value ) )
57- {
58- const char * keystr = PyUnicode_AsUTF8 ( key );
59- if ( !keystr )
60- CSP_THROW ( PythonPassthrough, " " );
61-
62- if ( !PyLong_Check ( value ) )
63- CSP_THROW ( TypeError, " csp.Enum key " << keystr << " expected an integer got " << PyObjectPtr::incref ( value ) );
64-
65- def[ keystr ] = fromPython<int64_t >( value );
66- }
67- }
68-
69- // back reference to the csp enum type that will be accessible on the csp enum -> meta()
70- // intentionally dont incref here to break the circular dep of type -> shared_ptr on CspEnumMeta
71- PyTypeObjectPtr typePtr = PyTypeObjectPtr::own ( ( PyTypeObject * ) pymeta );
72- auto enumMeta = std::make_shared<DialectCspEnumMeta>( typePtr, name, def );
73-
74- pymeta -> enumMeta = enumMeta;
75-
7615 // pre-create instances
77- pymeta -> enumsByName = PyObjectPtr::own ( PyDict_New () );
78- pymeta -> enumsByValue = PyObjectPtr::own ( PyDict_New () );
16+ m_enumsByName = PyObjectPtr::own ( PyDict_New () );
7917
80- for ( auto & [ key, value ] : def )
18+ PyObjectPtr iter = PyObjectPtr::check ( PyObject_GetIter ( ( PyObject * ) pyType.get () ) );
19+ PyObjectPtr member;
20+ while ( member = PyObjectPtr::own ( PyIter_Next ( iter.get () ) ) )
8121 {
82- PyCspEnum * enum_ = ( PyCspEnum * ) ( (PyTypeObject * ) pymeta ) -> tp_alloc ( (PyTypeObject * ) pymeta, 0 );
22+ PyObjectPtr name = PyObjectPtr::check ( PyObject_GetAttrString ( member. get (), " name " ) );
8323
84- new ( enum_ ) PyCspEnum ( enumMeta -> create ( value ) );
85- enum_ -> enumName = PyObjectPtr::own ( toPython ( key ) );
86- enum_ -> enumValue = PyObjectPtr::own ( toPython<int64_t >( value ) );
24+ if ( !PyLong_Check ( member.get () ) )
25+ CSP_THROW ( TypeError, " enum key " << name << " expected an integer got " << member );
26+
27+ int64_t value = fromPython<int64_t >( member.get () );
28+ m_enumsByCValue[ value ] = member;
8729
88- pymeta -> enumsByCValue[ value ] = PyObjectPtr::incref ( enum_ );
89-
90- if ( PyDict_SetItem ( pymeta -> enumsByName.get (), enum_ -> enumName.get (), enum_ ) < 0 )
91- CSP_THROW ( PythonPassthrough, " " );
92-
93- if ( PyDict_SetItem ( pymeta -> enumsByValue.get (), enum_ -> enumValue.get (), enum_ ) < 0 )
94- CSP_THROW ( PythonPassthrough, " " );
95-
96- // We also have to update the items in the actual type's dict so FooEnum.A is a PyCspEnum!
97- if ( PyDict_SetItem ( ( ( PyTypeObject * ) pymeta ) -> tp_dict, enum_ -> enumName.get (), enum_ ) < 0 )
30+ if ( PyDict_SetItem ( m_enumsByName.get (), name.get (), member.get () ) < 0 )
9831 CSP_THROW ( PythonPassthrough, " " );
9932 }
100-
101- return ( PyObject * ) pymeta;
102- CSP_RETURN_NULL ;
103- }
104-
105- PyObject * PyCspEnumMeta::toPyEnum ( CspEnum e ) const
106- {
107- auto it = enumsByCValue.find ( e.value () );
108- if ( it == enumsByCValue.end () )
109- return nullptr ;
110-
111- PyObject * rv = it -> second.get ();
112- Py_INCREF ( rv );
113- return rv;
114- }
115-
116- void PyCspEnumMeta_dealloc ( PyCspEnumMeta * m )
117- {
118- CspTypeFactory::instance ().removeCachedType ( reinterpret_cast <PyTypeObject*>( m ) );
119- m -> ~PyCspEnumMeta ();
120- PyCspEnumMeta::PyType.tp_free ( m );
121- }
122-
123- PyObject * PyCspEnumMeta_subscript ( PyCspEnumMeta * self, PyObject * key )
124- {
125- CSP_BEGIN_METHOD ;
126-
127- PyObject * obj = PyDict_GetItem ( self -> enumsByName.get (), key );
128-
129- if ( !obj )
130- CSP_THROW ( ValueError, PyObjectPtr::incref ( key ) << " is not a valid name on csp.enum type " << ( ( PyTypeObject * ) self ) -> tp_name );
131-
132- Py_INCREF ( obj );
133- return obj;
134- CSP_RETURN_NULL ;
135- }
136-
137-
138- static PyMappingMethods PyCspEnumMeta_MappingMethods = {
139- 0 , /* mp_length */
140- (binaryfunc) PyCspEnumMeta_subscript, /* mp_subscript */
141- };
142-
143- PyTypeObject PyCspEnumMeta::PyType = {
144- PyVarObject_HEAD_INIT (nullptr , 0 )
145- " _cspimpl.PyCspEnumMeta" , /* tp_name */
146- sizeof (PyCspEnumMeta), /* tp_basicsize */
147- 0 , /* tp_itemsize */
148- (destructor) PyCspEnumMeta_dealloc, /* tp_dealloc */
149- 0 , /* tp_print */
150- 0 , /* tp_getattr */
151- 0 , /* tp_setattr */
152- 0 , /* tp_reserved */
153- 0 , /* tp_repr */
154- 0 , /* tp_as_number */
155- 0 , /* tp_as_sequence */
156- &PyCspEnumMeta_MappingMethods, /* tp_as_mapping */
157- 0 , /* tp_hash */
158- 0 , /* tp_call */
159- 0 , /* tp_str */
160- 0 , /* tp_getattro */
161- 0 , /* tp_setattro */
162- 0 , /* tp_as_buffer */
163- Py_TPFLAGS_DEFAULT |
164- Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */
165- " csp enum metaclass" , /* tp_doc */
166- 0 , /* tp_traverse */
167- 0 , /* tp_clear */
168- 0 , /* tp_richcompare */
169- 0 , /* tp_weaklistoffset */
170- 0 , /* tp_iter */
171- 0 , /* tp_iternext */
172- 0 , /* tp_methods */
173- 0 , /* tp_members */
174- 0 , /* tp_getset */
175- &PyType_Type, /* tp_base */
176- 0 , /* tp_dict */
177- 0 , /* tp_descr_get */
178- 0 , /* tp_descr_set */
179- 0 , /* tp_dictoffset */
180- 0 , /* tp_init*/
181- 0 , /* tp_alloc */
182- (newfunc) PyCspEnumMeta_new,/* tp_new */
183- PyObject_GC_Del, /* tp_free */
184- };
185-
186-
187- // PyCspEnum
188- void PyCspEnum_dealloc ( PyCspEnum * self )
189- {
190- self -> ~PyCspEnum ();
191- PyCspEnum::PyType.tp_free ( self );
192- }
193-
194- PyObject * PyCspEnum_new ( PyTypeObject * type, PyObject *args, PyObject *kwds )
195- {
196- CSP_BEGIN_METHOD ;
197-
198- PyObject * pyvalue;
199- if ( !PyArg_ParseTuple ( args, " O" , &pyvalue ) )
200- CSP_THROW ( PythonPassthrough, " " );
201-
202- auto pymeta = (PyCspEnumMeta * ) type;
203- PyObject * obj = nullptr ;
204- if ( PyLong_Check ( pyvalue ) )
205- obj = PyDict_GetItem ( pymeta -> enumsByValue.get (), pyvalue );
206- else if ( PyUnicode_Check ( pyvalue ) )
207- obj = PyDict_GetItem ( pymeta -> enumsByName.get (), pyvalue );
208-
209- if ( !obj )
210- CSP_THROW ( ValueError, PyObjectPtr::incref ( pyvalue ) << " is not a valid value on csp.enum type " << type -> tp_name );
211-
212- Py_INCREF ( obj );
213- return obj;
214- CSP_RETURN_NULL ;
21533}
21634
217- PyObject * PyCspEnum_name ( PyCspEnum * self, void * )
218- {
219- Py_INCREF ( self -> enumName.get () );
220- return self -> enumName.get ();
221- }
222-
223- PyObject * PyCspEnum_value ( PyCspEnum * self, void * )
224- {
225- Py_INCREF ( self -> enumValue.get () );
226- return self -> enumValue.get ();
227- }
228-
229- static PyGetSetDef PyCspEnum_getset[] = {
230- { ( char * ) " name" , (getter) PyCspEnum_name, 0 , ( char * ) " string name of the enum instance" , 0 },
231- { ( char * ) " value" , (getter) PyCspEnum_value, 0 , ( char * ) " long value of the enum instance" , 0 },
232- { NULL }
233- };
234-
235- PyTypeObject PyCspEnum::PyType = {
236- PyVarObject_HEAD_INIT (nullptr , 0 )
237- " _cspimpl.PyCspEnum" , /* tp_name */
238- sizeof (PyCspEnum), /* tp_basicsize */
239- 0 , /* tp_itemsize */
240- (destructor) PyCspEnum_dealloc, /* tp_dealloc */
241- 0 , /* tp_print */
242- 0 , /* tp_getattr */
243- 0 , /* tp_setattr */
244- 0 , /* tp_reserved */
245- 0 , /* tp_repr */
246- 0 , /* tp_as_number */
247- 0 , /* tp_as_sequence */
248- 0 , /* tp_as_mapping */
249- 0 , /* tp_hash */
250- 0 , /* tp_call */
251- 0 , /* tp_str */
252- 0 , /* tp_getattro */
253- 0 , /* tp_setattro */
254- 0 , /* tp_as_buffer */
255- Py_TPFLAGS_DEFAULT |
256- Py_TPFLAGS_BASETYPE, /* tp_flags */
257- " csp enum" , /* tp_doc */
258- 0 , /* tp_traverse */
259- 0 , /* tp_clear */
260- 0 , /* tp_richcompare */
261- 0 , /* tp_weaklistoffset */
262- 0 , /* tp_iter */
263- 0 , /* tp_iternext */
264- 0 , /* tp_methods */
265- 0 , /* tp_members */
266- PyCspEnum_getset, /* tp_getset */
267- 0 , /* tp_base */
268- 0 , /* tp_dict */
269- 0 , /* tp_descr_get */
270- 0 , /* tp_descr_set */
271- 0 , /* tp_dictoffset */
272- 0 , /* tp_init */
273- 0 , /* tp_alloc */
274- (newfunc) PyCspEnum_new, /* tp_new */
275- 0 , /* tp_free */
276- };
277-
278- REGISTER_TYPE_INIT ( &PyCspEnumMeta::PyType, " PyCspEnumMeta" )
279- REGISTER_TYPE_INIT ( &PyCspEnum::PyType, " PyCspEnum" )
280-
28135}
0 commit comments