Browse Source

more review comments:
- use constancts from cpp where applicable (instead of hardcoded values)
- removed obsolete comments
- added missing comments with some explanations
- factored out common code in the creation of static classes and types


git-svn-id: svn://bind10.isc.org/svn/bind10/experiments/python-binding@2243 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
02ce015385

+ 0 - 10
src/lib/dns/python/message_python.cc

@@ -116,8 +116,6 @@ static PyTypeObject messageflag_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -342,8 +340,6 @@ static PyTypeObject opcode_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -747,8 +743,6 @@ static PyTypeObject rcode_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -1162,8 +1156,6 @@ static PyTypeObject section_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -1500,8 +1492,6 @@ static PyTypeObject message_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };

+ 1 - 2
src/lib/dns/python/messagerenderer_python.cc

@@ -111,8 +111,6 @@ static PyTypeObject messagerenderer_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -129,6 +127,7 @@ MessageRenderer_destroy(s_MessageRenderer* self) {
     delete self->messagerenderer;
     delete self->outputbuffer;
     self->messagerenderer = NULL;
+    self->outputbuffer = NULL;
     Py_TYPE(self)->tp_free(self);
 }
 

+ 43 - 33
src/lib/dns/python/name_python.cc

@@ -118,8 +118,6 @@ static PyTypeObject name_comparison_result_type = {
     NULL,                                     // tp_cache
     NULL,                                     // tp_subclasses
     NULL,                                     // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                                     // tp_del
     0                                         // tp_version_tag
 };
@@ -178,7 +176,7 @@ static PyObject* Name_getLength(s_Name* self);
 static PyObject* Name_compare(s_Name* self, PyObject* args);
 static PyObject* Name_equals(s_Name* self, PyObject* args);
 
-static PyObject* Name_richcmp(s_Name* n1, s_Name* n2, int op);
+static PyObject* Name_richcmp(s_Name* self, s_Name* other, int op);
 static PyObject* Name_split(s_Name* self, PyObject* args);
 static PyObject* Name_reverse(s_Name* self);
 static PyObject* Name_concatenate(s_Name* self, PyObject* args);
@@ -283,7 +281,10 @@ Name_init(s_Name* self, PyObject* args) {
     const char* s;
     PyObject* downcase = Py_False;
 
-    // fromText
+    // Depending on the arguments in *args, we decide which of the
+    // constructors is meant. If the first argument is of type string,
+    // we use the string-based constructor. If it is a bytes object,
+    // we use the wire-based one.
     if (PyArg_ParseTuple(args, "s|O!", &s, &PyBool_Type, &downcase)) {
         try {
             const std::string n(s);
@@ -326,7 +327,8 @@ Name_init(s_Name* self, PyObject* args) {
     Py_ssize_t len;
     unsigned int position = 0;
 
-    // fromWire
+    // It was not a string (see comment above), so try bytes, and
+    // create with buffer object
     if (PyArg_ParseTuple(args, "O|IO!", &bytes_obj, &position,
                          &PyBool_Type, &downcase) &&
                          PyObject_AsCharBuffer(bytes_obj, &bytes, &len) != -1) {
@@ -396,6 +398,8 @@ Name_toText(s_Name* self) {
 static PyObject*
 Name_str(PyObject* self) {
     // Simply call the to_text method we already defined
+    // str() is not defined in the c++ version, only to_text
+    // and we already have a wrapper for that one.
     return PyObject_CallMethod(self,
                                const_cast<char*>("to_text"),
                                const_cast<char*>(""));
@@ -409,13 +413,13 @@ Name_toWire(s_Name* self, PyObject* args) {
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
         
-        OutputBuffer buffer(255);
+        OutputBuffer buffer(Name::MAX_WIRE);
         self->name->toWire(buffer);
-        PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
-        PyObject* result = PySequence_InPlaceConcat(bytes_o, n);
+        PyObject* name_bytes = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
+        PyObject* result = PySequence_InPlaceConcat(bytes_o, name_bytes);
         // We need to release the object we temporarily created here
         // to prevent memory leak
-        Py_DECREF(n);
+        Py_DECREF(name_bytes);
         return result;
     } else if (PyArg_ParseTuple(args, "O!", &messagerenderer_type, (PyObject**) &mr)) {
         self->name->toWire(*mr->messagerenderer);
@@ -440,10 +444,6 @@ Name_compare(s_Name* self, PyObject* args) {
     if (ret != NULL) {
         ret->ncr = new NameComparisonResult(
             self->name->compare(*other->name));
-        if (ret->ncr == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
     }
     return static_cast<PyObject*>(ret);
 }
@@ -501,37 +501,44 @@ Name_split(s_Name* self, PyObject* args) {
 }
 #include <iostream>
 
+//
+// richcmp defines the ==, !=, >, <, >= and <= operators in python
+// It is translated to a function that gets 3 arguments, an object,
+// an object to compare to, and an operator.
+//
 static PyObject* 
-Name_richcmp(s_Name* n1, s_Name* n2, int op) {
+Name_richcmp(s_Name* self, s_Name* other, int op) {
     bool c;
 
     // Check for null and if the types match. If different type,
     // simply return False
-    if (!n2 || (n1->ob_type != n2->ob_type)) {
+    if (!other || (self->ob_type != other->ob_type)) {
         Py_RETURN_FALSE;
     }
 
     switch (op) {
     case Py_LT:
-        c = *n1->name < *n2->name;
+        c = *self->name < *other->name;
         break;
     case Py_LE:
-        c = *n1->name <= *n2->name;
+        c = *self->name <= *other->name;
         break;
     case Py_EQ:
-        c = *n1->name == *n2->name;
+        c = *self->name == *other->name;
         break;
     case Py_NE:
-        c = *n1->name != *n2->name;
+        c = *self->name != *other->name;
         break;
     case Py_GT:
-        c = *n1->name > *n2->name;
+        c = *self->name > *other->name;
         break;
     case Py_GE:
-        c = *n1->name >= *n2->name;
+        c = *self->name >= *other->name;
         break;
     default:
-        assert(0);              // XXX: should trigger an exception
+        PyErr_SetString(PyExc_IndexError,
+                        "Unhandled rich comparison operator");
+        return NULL;
     }
     if (c) {
         Py_RETURN_TRUE;
@@ -567,10 +574,6 @@ Name_concatenate(s_Name* self, PyObject* args) {
             ret->name = new Name(self->name->concatenate(*other->name));
         } catch (isc::dns::TooLongName tln) {
             PyErr_SetString(po_TooLongName, tln.what());
-            ret->name = NULL;
-        }
-        if (ret->name == NULL) {
-            Py_DECREF(ret);
             return NULL;
         }
     }
@@ -602,7 +605,9 @@ initModulePart_Name(PyObject* mod) {
     // We initialize the static description object with PyType_Ready(),
     // then add it to the module
 
+    //
     // NameComparisonResult
+    //
     if (PyType_Ready(&name_comparison_result_type) < 0) {
         return false;
     }
@@ -610,14 +615,18 @@ initModulePart_Name(PyObject* mod) {
 
     // Add the enums to the module
     po_NameRelation = Py_BuildValue("{i:s,i:s,i:s,i:s}",
-                                    0, "SUPERDOMAIN",
-                                    1, "SUBDOMAIN",
-                                    2, "EQUAL",
-                                    3, "COMMONANCESTOR");
+                                    NameComparisonResult::SUPERDOMAIN, "SUPERDOMAIN",
+                                    NameComparisonResult::SUBDOMAIN, "SUBDOMAIN",
+                                    NameComparisonResult::EQUAL, "EQUAL",
+                                    NameComparisonResult::COMMONANCESTOR, "COMMONANCESTOR");
     addClassVariable(name_comparison_result_type, "NameRelation", po_NameRelation);
 
     PyModule_AddObject(mod, "NameComparisonResult",
                        reinterpret_cast<PyObject*>(&name_comparison_result_type));
+
+    //
+    // Name
+    //
     
     if (PyType_Ready(&name_type) < 0) {
         return false;
@@ -638,6 +647,10 @@ initModulePart_Name(PyObject* mod) {
     Py_INCREF(po_ROOT_NAME);
     addClassVariable(name_type, "ROOT_NAME", po_ROOT_NAME);
 
+    PyModule_AddObject(mod, "Name",
+                       reinterpret_cast<PyObject*>(&name_type));
+    
+
     // Add the exceptions to the module
     po_EmptyLabel = PyErr_NewException("libdns_python.EmptyLabel", NULL, NULL);
     PyModule_AddObject(mod, "EmptyLabel", po_EmptyLabel);
@@ -665,8 +678,5 @@ initModulePart_Name(PyObject* mod) {
     po_DNSMessageFORMERR = PyErr_NewException("libdns_python.DNSMessageFORMERR", NULL, NULL);
     PyModule_AddObject(mod, "DNSMessageFORMERR", po_DNSMessageFORMERR);
 
-    PyModule_AddObject(mod, "Name",
-                       reinterpret_cast<PyObject*>(&name_type));
-    
     return true;
 }

+ 0 - 2
src/lib/dns/python/question_python.cc

@@ -121,8 +121,6 @@ static PyTypeObject question_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };

+ 0 - 2
src/lib/dns/python/rdata_python.cc

@@ -130,8 +130,6 @@ static PyTypeObject rdata_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };

+ 16 - 45
src/lib/dns/python/rrclass_python.cc

@@ -147,8 +147,6 @@ static PyTypeObject rrclass_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -288,7 +286,9 @@ RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) {
             *self->rrclass == *other->rrclass;
         break;
     default:
-        assert(0);              // XXX: should trigger an exception
+        PyErr_SetString(PyExc_IndexError,
+                        "Unhandled rich comparison operator");
+        return NULL;
     }
     if (c)
         Py_RETURN_TRUE;
@@ -296,64 +296,35 @@ RRClass_richcmp(s_RRClass* self, s_RRClass* other, int op) {
         Py_RETURN_FALSE;
 }
 
-static PyObject* RRClass_IN(s_RRClass *self UNUSED_PARAM) {
+//
+// Common function for RRClass_IN/CH/etc.
+//
+static PyObject* RRClass_createStatic(RRClass stc) {
     s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
     if (ret != NULL) {
-        ret->rrclass = new RRClass(RRClass::IN());
-        if (ret->rrclass == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
+        ret->rrclass = new RRClass(stc);
     }
     return static_cast<PyObject*>(ret);
 }
 
+static PyObject* RRClass_IN(s_RRClass *self UNUSED_PARAM) {
+    return RRClass_createStatic(RRClass::IN());
+}
+
 static PyObject* RRClass_CH(s_RRClass *self UNUSED_PARAM) {
-    s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
-    if (ret != NULL) {
-        ret->rrclass = new RRClass(RRClass::CH());
-        if (ret->rrclass == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRClass_createStatic(RRClass::CH());
 }
 
 static PyObject* RRClass_HS(s_RRClass *self UNUSED_PARAM) {
-    s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
-    if (ret != NULL) {
-        ret->rrclass = new RRClass(RRClass::HS());
-        if (ret->rrclass == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRClass_createStatic(RRClass::HS());
 }
 
 static PyObject* RRClass_NONE(s_RRClass *self UNUSED_PARAM) {
-    s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
-    if (ret != NULL) {
-        ret->rrclass = new RRClass(RRClass::NONE());
-        if (ret->rrclass == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRClass_createStatic(RRClass::NONE());
 }
 
 static PyObject* RRClass_ANY(s_RRClass *self UNUSED_PARAM) {
-    s_RRClass* ret = PyObject_New(s_RRClass, &rrclass_type);
-    if (ret != NULL) {
-        ret->rrclass = new RRClass(RRClass::ANY());
-        if (ret->rrclass == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRClass_createStatic(RRClass::ANY());
 }
 // end of RRClass
 

+ 0 - 2
src/lib/dns/python/rrset_python.cc

@@ -147,8 +147,6 @@ static PyTypeObject rrset_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };

+ 2 - 4
src/lib/dns/python/rrttl_python.cc

@@ -136,8 +136,6 @@ static PyTypeObject rrttl_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -147,7 +145,7 @@ RRTTL_init(s_RRTTL* self, PyObject* args) {
     const char* s;
     unsigned long i;
     PyObject* bytes = NULL;
-    // The constructor argument can be a string ("IN"), an integer (1),
+    // The constructor argument can be a string ("1234"), an integer (1),
     // or a sequence of numbers between 0 and 255 (wire code)
 
     // Note that PyArg_ParseType can set PyError, and we need to clear
@@ -224,7 +222,7 @@ RRTTL_toWire(s_RRTTL* self, PyObject* args) {
     if (PyArg_ParseTuple(args, "O", &bytes) && PySequence_Check(bytes)) {
         PyObject* bytes_o = bytes;
         
-        OutputBuffer buffer(2);
+        OutputBuffer buffer(4);
         self->rrttl->toWire(buffer);
         PyObject* n = PyBytes_FromStringAndSize((const char*) buffer.getData(), buffer.getLength());
         PyObject* result = PySequence_InPlaceConcat(bytes_o, n);

+ 32 - 173
src/lib/dns/python/rrtype_python.cc

@@ -196,8 +196,6 @@ static PyTypeObject rrtype_type = {
     NULL,                               // tp_cache
     NULL,                               // tp_subclasses
     NULL,                               // tp_weaklist
-    // Note: not sure if the following are correct.  Added them just to
-    // make the compiler happy.
     NULL,                               // tp_del
     0                                   // tp_version_tag
 };
@@ -344,7 +342,9 @@ RRType_richcmp(s_RRType* self, s_RRType* other, int op) {
             *self->rrtype == *other->rrtype;
         break;
     default:
-        assert(0);              // XXX: should trigger an exception
+        PyErr_SetString(PyExc_IndexError,
+                        "Unhandled rich comparison operator");
+        return NULL;
     }
     if (c)
         Py_RETURN_TRUE;
@@ -352,251 +352,110 @@ RRType_richcmp(s_RRType* self, s_RRType* other, int op) {
         Py_RETURN_FALSE;
 }
 
-static PyObject*
-RRType_NSEC3PARAM(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
+//
+// Common function for RRType_A/NS/etc.
+//
+static PyObject* RRType_createStatic(RRType stc) {
+    s_RRType* ret = PyObject_New(s_RRType, &rrclass_type);
     if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::NSEC3PARAM());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
+        ret->rrtype = new RRType(stc);
     }
     return static_cast<PyObject*>(ret);
 }
 
 static PyObject*
+RRType_NSEC3PARAM(s_RRType *self UNUSED_PARAM) {
+    return RRType_createStatic(RRType::NSEC3PARAM());
+}
+
+static PyObject*
 RRType_DNAME(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::DNAME());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::DNAME());
 }
 
 static PyObject*
 RRType_PTR(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::PTR());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::PTR());
 }
 
 static PyObject*
 RRType_MX(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::MX());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::MX());
 }
 
 static PyObject*
 RRType_DNSKEY(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::DNSKEY());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::DNSKEY());
 }
 
 static PyObject*
 RRType_TXT(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::TXT());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::TXT());
 }
 
 static PyObject*
 RRType_RRSIG(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::RRSIG());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::RRSIG());
 }
 
 static PyObject*
 RRType_NSEC(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::NSEC());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::NSEC());
 }
 
 static PyObject*
 RRType_AAAA(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::AAAA());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::AAAA());
 }
 
 static PyObject*
 RRType_DS(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::DS());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::DS());
 }
 
 static PyObject*
 RRType_OPT(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::OPT());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::OPT());
 }
 
 static PyObject*
 RRType_A(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::A());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::A());
 }
 
 static PyObject*
 RRType_NS(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::NS());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::NS());
 }
 
 static PyObject*
 RRType_CNAME(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::CNAME());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::CNAME());
 }
 
 static PyObject*
 RRType_SOA(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::SOA());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::SOA());
 }
 
 static PyObject*
 RRType_NSEC3(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::NSEC3());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::NSEC3());
 }
 
 static PyObject*
 RRType_IXFR(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::IXFR());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::IXFR());
 }
 
 static PyObject*
 RRType_AXFR(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::AXFR());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::AXFR());
 }
 
 static PyObject*
 RRType_ANY(s_RRType *self UNUSED_PARAM) {
-    s_RRType* ret = PyObject_New(s_RRType, &rrtype_type);
-    if (ret != NULL) {
-        ret->rrtype = new RRType(RRType::ANY());
-        if (ret->rrtype == NULL) {
-            Py_DECREF(ret);
-            return NULL;
-        }
-    }
-    return static_cast<PyObject*>(ret);
+    return RRType_createStatic(RRType::ANY());
 }