some minimal pkcs7 and pkcs12 tests, and minor adjustments to their part of OpenSSL.crypto module initialization; change NetscapeSPKI to be a type that can be instantiated, and add a very minimal amount of testing for it
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index 49e0b16..89091cc 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -515,37 +515,6 @@
 }
 
 
-static char crypto_NetscapeSPKI_doc[] = "\n\
-The factory function inserted in the module dictionary to create NetscapeSPKI\n\
-objects\n\
-\n\
-@param enc: Base64 encoded NetscapeSPKI object.\n\
-@type enc: C{str}\n\
-@return: The NetscapeSPKI object\n\
-";
-
-static PyObject *
-crypto_NetscapeSPKI(PyObject *spam, PyObject *args)
-{
-    char *enc = NULL;
-    int enc_len = -1;
-    NETSCAPE_SPKI *spki;
-
-    if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
-        return NULL;
-
-    if (enc_len >= 0)
-        spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
-    else
-        spki = NETSCAPE_SPKI_new();
-    if (spki == NULL)
-    {
-        exception_from_error_queue();
-        return NULL;
-    }
-    return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
-}
-
 static char crypto_X509_verify_cert_error_string_doc[] = "\n\
 Get X509 verify certificate error string.\n\
 \n\
@@ -577,8 +546,6 @@
     { "dump_certificate_request", (PyCFunction)crypto_dump_certificate_request, METH_VARARGS, crypto_dump_certificate_request_doc },
     { "load_pkcs7_data", (PyCFunction)crypto_load_pkcs7_data, METH_VARARGS, crypto_load_pkcs7_data_doc },
     { "load_pkcs12", (PyCFunction)crypto_load_pkcs12, METH_VARARGS, crypto_load_pkcs12_doc },
-    /* Factory functions */
-    { "NetscapeSPKI", (PyCFunction)crypto_NetscapeSPKI, METH_VARARGS, crypto_NetscapeSPKI_doc },
     { "X509_verify_cert_error_string", (PyCFunction)crypto_X509_verify_cert_error_string, METH_VARARGS, crypto_X509_verify_cert_error_string_doc },
     { NULL, NULL }
 };
@@ -712,11 +679,11 @@
         goto error;
     if (!init_crypto_x509extension(module))
         goto error;
-    if (!init_crypto_pkcs7(dict))
+    if (!init_crypto_pkcs7(module))
         goto error;
-    if (!init_crypto_pkcs12(dict))
+    if (!init_crypto_pkcs12(module))
         goto error;
-    if (!init_crypto_netscape_spki(dict))
+    if (!init_crypto_netscape_spki(module))
         goto error;
 
 error:
diff --git a/src/crypto/netscape_spki.c b/src/crypto/netscape_spki.c
index a0796cb..d4255f0 100644
--- a/src/crypto/netscape_spki.c
+++ b/src/crypto/netscape_spki.c
@@ -33,6 +33,37 @@
     return self;
 }
 
+
+static char crypto_NetscapeSPKI_doc[] = "\n\
+NetscapeSPKI([enc]) -> NetscapeSPKI instance\n\
+\n\
+@param enc: Base64 encoded NetscapeSPKI object.\n\
+@type enc: C{str}\n\
+@return: The NetscapeSPKI object\n\
+";
+
+static PyObject *
+crypto_NetscapeSPKI_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
+    char *enc = NULL;
+    int enc_len = -1;
+    NETSCAPE_SPKI *spki;
+
+    if (!PyArg_ParseTuple(args, "|s#:NetscapeSPKI", &enc, &enc_len))
+        return NULL;
+
+    if (enc_len >= 0)
+        spki = NETSCAPE_SPKI_b64_decode(enc, enc_len);
+    else
+        spki = NETSCAPE_SPKI_new();
+    if (spki == NULL)
+    {
+        exception_from_error_queue();
+        return NULL;
+    }
+    return (PyObject *)crypto_NetscapeSPKI_New(spki, 1);
+}
+
+
 /*
  * Deallocate the memory used by the NetscapeSPKI object
  *
@@ -224,21 +255,53 @@
     NULL, /* as_number */
     NULL, /* as_sequence */
     NULL, /* as_mapping */
-    NULL  /* hash */
+    NULL,  /* hash */
+    NULL, /* call */
+    NULL, /* str */
+    NULL, /* getattro */
+    NULL, /* setattro */
+    NULL, /* as_buffer */
+    Py_TPFLAGS_DEFAULT,
+    crypto_NetscapeSPKI_doc, /* doc */
+    NULL, /* traverse */
+    NULL, /* clear */
+    NULL, /* tp_richcompare */
+    0, /* tp_weaklistoffset */
+    NULL, /* tp_iter */
+    NULL, /* tp_iternext */
+    crypto_NetscapeSPKI_methods, /* tp_methods */
+    NULL, /* tp_members */
+    NULL, /* tp_getset */
+    NULL, /* tp_base */
+    NULL, /* tp_dict */
+    NULL, /* tp_descr_get */
+    NULL, /* tp_descr_set */
+    0, /* tp_dictoffset */
+    NULL, /* tp_init */
+    NULL, /* tp_alloc */
+    crypto_NetscapeSPKI_new, /* tp_new */
 };
 
 
 /*
  * Initialize the X509Name part of the crypto module
  *
- * Arguments: dict - The crypto module dictionary
+ * Arguments: module - The crypto module
  * Returns:   None
  */
 int
-init_crypto_netscape_spki(PyObject *dict)
-{
-    crypto_NetscapeSPKI_Type.ob_type = &PyType_Type;
-    Py_INCREF(&crypto_NetscapeSPKI_Type);
-    PyDict_SetItemString(dict, "NetscapeSPKIType", (PyObject *)&crypto_NetscapeSPKI_Type);
+init_crypto_netscape_spki(PyObject *module) {
+    if (PyType_Ready(&crypto_NetscapeSPKI_Type) < 0) {
+        return 0;
+    }
+
+    if (PyModule_AddObject(module, "NetscapeSPKI", (PyObject *)&crypto_NetscapeSPKI_Type) != 0) {
+        return 0;
+    }
+
+    if (PyModule_AddObject(module, "NetscapeSPKIType", (PyObject *)&crypto_NetscapeSPKI_Type) != 0) {
+        return 0;
+    }
+
     return 1;
 }
diff --git a/src/crypto/pkcs12.c b/src/crypto/pkcs12.c
index 3fa39aa..71ebcdd 100644
--- a/src/crypto/pkcs12.c
+++ b/src/crypto/pkcs12.c
@@ -253,15 +253,19 @@
 /*
  * Initialize the PKCS12 part of the crypto sub module
  *
- * Arguments: dict - The crypto module dictionary
+ * Arguments: module - The crypto module
  * Returns:   None
  */
 int
-init_crypto_pkcs12(PyObject *dict)
-{
-    crypto_PKCS12_Type.ob_type = &PyType_Type;
-    Py_INCREF(&crypto_PKCS12_Type);
-    PyDict_SetItemString(dict, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type);
+init_crypto_pkcs12(PyObject *module) {
+    if (PyType_Ready(&crypto_PKCS12_Type) < 0) {
+        return 0;
+    }
+
+    if (PyModule_AddObject(module, "PKCS12Type", (PyObject *)&crypto_PKCS12_Type) != 0) {
+        return 0;
+    }
+
     return 1;
 }
 
diff --git a/src/crypto/pkcs7.c b/src/crypto/pkcs7.c
index 4ff0b6b..1cb0813 100644
--- a/src/crypto/pkcs7.c
+++ b/src/crypto/pkcs7.c
@@ -197,15 +197,19 @@
 /*
  * Initialize the PKCS7 part of the crypto sub module
  *
- * Arguments: dict - The crypto module dictionary
+ * Arguments: module - The crypto module
  * Returns:   None
  */
 int
-init_crypto_pkcs7(PyObject *dict)
-{
-    crypto_PKCS7_Type.ob_type = &PyType_Type;
-    Py_INCREF(&crypto_PKCS7_Type);
-    PyDict_SetItemString(dict, "PKCS7Type", (PyObject *)&crypto_PKCS7_Type);
+init_crypto_pkcs7(PyObject *module) {
+    if (PyType_Ready(&crypto_PKCS7_Type) < 0) {
+        return 0;
+    }
+
+    if (PyModule_AddObject(module, "PKCS7Type", (PyObject *)&crypto_PKCS7_Type) != 0) {
+        return 0;
+    }
+
     return 1;
 }
 
diff --git a/test/test_crypto.py b/test/test_crypto.py
index 87e9048..d83218b 100644
--- a/test/test_crypto.py
+++ b/test/test_crypto.py
@@ -15,6 +15,9 @@
 from OpenSSL.crypto import FILETYPE_PEM, FILETYPE_ASN1, FILETYPE_TEXT
 from OpenSSL.crypto import dump_certificate, load_certificate_request
 from OpenSSL.crypto import dump_certificate_request, dump_privatekey
+from OpenSSL.crypto import PKCS7Type, load_pkcs7_data
+from OpenSSL.crypto import PKCS12Type, load_pkcs12
+from OpenSSL.crypto import NetscapeSPKI, NetscapeSPKIType
 
 
 cleartextCertificatePEM = """-----BEGIN CERTIFICATE-----
@@ -88,6 +91,85 @@
 """
 encryptedPrivateKeyPEMPassphrase = "foobar"
 
+# Some PKCS12 data, base64 encoded.  The data itself was constructed using the
+# openssl command line:
+#
+#    openssl pkcs12 -export -in s.pem -out o.p12 -inkey s.pem -certfile s.pem
+#
+# With s.pem containing a private key and certificate.  The contents of the
+# generated file, o.p12, were then base64 encoded to produce this value.
+pkcs12Data = """\
+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
+""".decode('base64')
+
+# Some PKCS#7 stuff.  Generated with the openssl command line:
+#
+#    openssl crl2pkcs7 -inform pem -outform pem -certfile s.pem -nocrl
+#
+# with a certificate and key (but the key should be irrelevant) in s.pem
+pkcs7Data = """\
+-----BEGIN PKCS7-----
+MIIDNwYJKoZIhvcNAQcCoIIDKDCCAyQCAQExADALBgkqhkiG9w0BBwGgggMKMIID
+BjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzERMA8G
+A1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQDExtN
+MkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5ncHNA
+cG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzELMAkG
+A1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhvc3Qx
+HTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEBBQAD
+SwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh5kwI
+zOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQCMAAw
+LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
+A1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7hyNp
+65w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoTCE0y
+Q3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlwdG8g
+Q2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3QxLmNv
+bYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6BoJu
+VwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++7QGG
+/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JEWUQ9
+Ho4EzbYCOaEAMQA=
+-----END PKCS7-----
+"""
+
 
 class _Python23TestCaseHelper:
     # Python 2.3 compatibility.
@@ -814,5 +896,37 @@
         self.assertEqual(loadedKey.bits(), key.bits())
 
 
+    def test_load_pkcs7_data(self):
+        """
+        L{load_pkcs7_data} accepts a PKCS#7 string and returns an instance of
+        L{PKCS7Type}.
+        """
+        pkcs7 = load_pkcs7_data(FILETYPE_PEM, pkcs7Data)
+        self.assertTrue(isinstance(pkcs7, PKCS7Type))
+
+
+    def test_load_pkcs12(self):
+        """
+        L{load_pkcs12} accepts a PKCS#12 string and returns an instance of
+        L{PKCS12Type}.
+        """
+        pkcs12 = load_pkcs12(pkcs12Data)
+        self.assertTrue(isinstance(pkcs12, PKCS12Type))
+
+
+
+class NetscapeSPKITests(TestCase):
+    """
+    Tests for L{OpenSSL.crypto.NetscapeSPKI}.
+    """
+    def test_construction(self):
+        """
+        L{NetscapeSPKI} returns an instance of L{NetscapeSPKIType}.
+        """
+        nspki = NetscapeSPKI()
+        self.assertTrue(isinstance(nspki, NetscapeSPKIType))
+
+
+
 if __name__ == '__main__':
     main()