Merge pull request #1081 from haberman/fix-py3

Fixes for Python 3.
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index c39f7b8..516662e 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -395,7 +395,12 @@
     return NULL;
   }
 
+#if PY_MAJOR_VERSION >= 3
+  ScopedPyObjectPtr obj(PyType_GenericAlloc(
+        reinterpret_cast<PyTypeObject *>(ScalarMapContainer_Type), 0));
+#else
   ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0));
+#endif
   if (obj.get() == NULL) {
     return PyErr_Format(PyExc_RuntimeError,
                         "Could not allocate new container.");
@@ -510,12 +515,6 @@
   Py_TYPE(_self)->tp_free(_self);
 }
 
-static PyMappingMethods ScalarMapMappingMethods = {
-  MapReflectionFriend::Length,             // mp_length
-  MapReflectionFriend::ScalarMapGetItem,   // mp_subscript
-  MapReflectionFriend::ScalarMapSetItem,   // mp_ass_subscript
-};
-
 static PyMethodDef ScalarMapMethods[] = {
   { "__contains__", MapReflectionFriend::Contains, METH_O,
     "Tests whether a key is a member of the map." },
@@ -532,44 +531,71 @@
   {NULL, NULL},
 };
 
-PyTypeObject ScalarMapContainer_Type = {
-  PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  FULL_MODULE_NAME ".ScalarMapContainer",  //  tp_name
-  sizeof(MapContainer),                //  tp_basicsize
-  0,                                   //  tp_itemsize
-  ScalarMapDealloc,                    //  tp_dealloc
-  0,                                   //  tp_print
-  0,                                   //  tp_getattr
-  0,                                   //  tp_setattr
-  0,                                   //  tp_compare
-  0,                                   //  tp_repr
-  0,                                   //  tp_as_number
-  0,                                   //  tp_as_sequence
-  &ScalarMapMappingMethods,            //  tp_as_mapping
-  0,                                   //  tp_hash
-  0,                                   //  tp_call
-  0,                                   //  tp_str
-  0,                                   //  tp_getattro
-  0,                                   //  tp_setattro
-  0,                                   //  tp_as_buffer
-  Py_TPFLAGS_DEFAULT,                  //  tp_flags
-  "A scalar map container",            //  tp_doc
-  0,                                   //  tp_traverse
-  0,                                   //  tp_clear
-  0,                                   //  tp_richcompare
-  0,                                   //  tp_weaklistoffset
-  MapReflectionFriend::GetIterator,    //  tp_iter
-  0,                                   //  tp_iternext
-  ScalarMapMethods,                    //  tp_methods
-  0,                                   //  tp_members
-  0,                                   //  tp_getset
-  0,                                   //  tp_base
-  0,                                   //  tp_dict
-  0,                                   //  tp_descr_get
-  0,                                   //  tp_descr_set
-  0,                                   //  tp_dictoffset
-  0,                                   //  tp_init
-};
+#if PY_MAJOR_VERSION >= 3
+  static PyType_Slot ScalarMapContainer_Type_slots[] = {
+      {Py_tp_dealloc, (void *)ScalarMapDealloc},
+      {Py_mp_length, (void *)MapReflectionFriend::Length},
+      {Py_mp_subscript, (void *)MapReflectionFriend::ScalarMapGetItem},
+      {Py_mp_ass_subscript, (void *)MapReflectionFriend::ScalarMapSetItem},
+      {Py_tp_methods, (void *)ScalarMapMethods},
+      {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
+      {0, 0},
+  };
+
+  PyType_Spec ScalarMapContainer_Type_spec = {
+      FULL_MODULE_NAME ".ScalarMapContainer",
+      sizeof(MapContainer),
+      0,
+      Py_TPFLAGS_DEFAULT,
+      ScalarMapContainer_Type_slots
+  };
+  PyObject *ScalarMapContainer_Type;
+#else
+  static PyMappingMethods ScalarMapMappingMethods = {
+    MapReflectionFriend::Length,             // mp_length
+    MapReflectionFriend::ScalarMapGetItem,   // mp_subscript
+    MapReflectionFriend::ScalarMapSetItem,   // mp_ass_subscript
+  };
+
+  PyTypeObject ScalarMapContainer_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    FULL_MODULE_NAME ".ScalarMapContainer",  //  tp_name
+    sizeof(MapContainer),                //  tp_basicsize
+    0,                                   //  tp_itemsize
+    ScalarMapDealloc,                    //  tp_dealloc
+    0,                                   //  tp_print
+    0,                                   //  tp_getattr
+    0,                                   //  tp_setattr
+    0,                                   //  tp_compare
+    0,                                   //  tp_repr
+    0,                                   //  tp_as_number
+    0,                                   //  tp_as_sequence
+    &ScalarMapMappingMethods,            //  tp_as_mapping
+    0,                                   //  tp_hash
+    0,                                   //  tp_call
+    0,                                   //  tp_str
+    0,                                   //  tp_getattro
+    0,                                   //  tp_setattro
+    0,                                   //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                  //  tp_flags
+    "A scalar map container",            //  tp_doc
+    0,                                   //  tp_traverse
+    0,                                   //  tp_clear
+    0,                                   //  tp_richcompare
+    0,                                   //  tp_weaklistoffset
+    MapReflectionFriend::GetIterator,    //  tp_iter
+    0,                                   //  tp_iternext
+    ScalarMapMethods,                    //  tp_methods
+    0,                                   //  tp_members
+    0,                                   //  tp_getset
+    0,                                   //  tp_base
+    0,                                   //  tp_dict
+    0,                                   //  tp_descr_get
+    0,                                   //  tp_descr_set
+    0,                                   //  tp_dictoffset
+    0,                                   //  tp_init
+  };
+#endif
 
 
 // MessageMap //////////////////////////////////////////////////////////////////
@@ -613,7 +639,12 @@
     return NULL;
   }
 
+#if PY_MAJOR_VERSION >= 3
+  PyObject* obj = PyType_GenericAlloc(
+        reinterpret_cast<PyTypeObject *>(MessageMapContainer_Type), 0);
+#else
   PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0);
+#endif
   if (obj == NULL) {
     return PyErr_Format(PyExc_RuntimeError,
                         "Could not allocate new container.");
@@ -735,12 +766,6 @@
   Py_TYPE(_self)->tp_free(_self);
 }
 
-static PyMappingMethods MessageMapMappingMethods = {
-  MapReflectionFriend::Length,              // mp_length
-  MapReflectionFriend::MessageMapGetItem,   // mp_subscript
-  MapReflectionFriend::MessageMapSetItem,   // mp_ass_subscript
-};
-
 static PyMethodDef MessageMapMethods[] = {
   { "__contains__", (PyCFunction)MapReflectionFriend::Contains, METH_O,
     "Tests whether the map contains this element."},
@@ -759,44 +784,72 @@
   {NULL, NULL},
 };
 
-PyTypeObject MessageMapContainer_Type = {
-  PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  FULL_MODULE_NAME ".MessageMapContainer",  //  tp_name
-  sizeof(MessageMapContainer),         //  tp_basicsize
-  0,                                   //  tp_itemsize
-  MessageMapDealloc,                   //  tp_dealloc
-  0,                                   //  tp_print
-  0,                                   //  tp_getattr
-  0,                                   //  tp_setattr
-  0,                                   //  tp_compare
-  0,                                   //  tp_repr
-  0,                                   //  tp_as_number
-  0,                                   //  tp_as_sequence
-  &MessageMapMappingMethods,           //  tp_as_mapping
-  0,                                   //  tp_hash
-  0,                                   //  tp_call
-  0,                                   //  tp_str
-  0,                                   //  tp_getattro
-  0,                                   //  tp_setattro
-  0,                                   //  tp_as_buffer
-  Py_TPFLAGS_DEFAULT,                  //  tp_flags
-  "A map container for message",       //  tp_doc
-  0,                                   //  tp_traverse
-  0,                                   //  tp_clear
-  0,                                   //  tp_richcompare
-  0,                                   //  tp_weaklistoffset
-  MapReflectionFriend::GetIterator,    //  tp_iter
-  0,                                   //  tp_iternext
-  MessageMapMethods,                   //  tp_methods
-  0,                                   //  tp_members
-  0,                                   //  tp_getset
-  0,                                   //  tp_base
-  0,                                   //  tp_dict
-  0,                                   //  tp_descr_get
-  0,                                   //  tp_descr_set
-  0,                                   //  tp_dictoffset
-  0,                                   //  tp_init
-};
+#if PY_MAJOR_VERSION >= 3
+  static PyType_Slot MessageMapContainer_Type_slots[] = {
+      {Py_tp_dealloc, (void *)MessageMapDealloc},
+      {Py_mp_length, (void *)MapReflectionFriend::Length},
+      {Py_mp_subscript, (void *)MapReflectionFriend::MessageMapGetItem},
+      {Py_mp_ass_subscript, (void *)MapReflectionFriend::MessageMapSetItem},
+      {Py_tp_methods, (void *)MessageMapMethods},
+      {Py_tp_iter, (void *)MapReflectionFriend::GetIterator},
+      {0, 0}
+  };
+
+  PyType_Spec MessageMapContainer_Type_spec = {
+      FULL_MODULE_NAME ".MessageMapContainer",
+      sizeof(MapContainer),
+      0,
+      Py_TPFLAGS_DEFAULT,
+      MessageMapContainer_Type_slots
+  };
+
+  PyObject *MessageMapContainer_Type;
+#else
+  static PyMappingMethods MessageMapMappingMethods = {
+    MapReflectionFriend::Length,              // mp_length
+    MapReflectionFriend::MessageMapGetItem,   // mp_subscript
+    MapReflectionFriend::MessageMapSetItem,   // mp_ass_subscript
+  };
+
+  PyTypeObject MessageMapContainer_Type = {
+    PyVarObject_HEAD_INIT(&PyType_Type, 0)
+    FULL_MODULE_NAME ".MessageMapContainer",  //  tp_name
+    sizeof(MessageMapContainer),         //  tp_basicsize
+    0,                                   //  tp_itemsize
+    MessageMapDealloc,                   //  tp_dealloc
+    0,                                   //  tp_print
+    0,                                   //  tp_getattr
+    0,                                   //  tp_setattr
+    0,                                   //  tp_compare
+    0,                                   //  tp_repr
+    0,                                   //  tp_as_number
+    0,                                   //  tp_as_sequence
+    &MessageMapMappingMethods,           //  tp_as_mapping
+    0,                                   //  tp_hash
+    0,                                   //  tp_call
+    0,                                   //  tp_str
+    0,                                   //  tp_getattro
+    0,                                   //  tp_setattro
+    0,                                   //  tp_as_buffer
+    Py_TPFLAGS_DEFAULT,                  //  tp_flags
+    "A map container for message",       //  tp_doc
+    0,                                   //  tp_traverse
+    0,                                   //  tp_clear
+    0,                                   //  tp_richcompare
+    0,                                   //  tp_weaklistoffset
+    MapReflectionFriend::GetIterator,    //  tp_iter
+    0,                                   //  tp_iternext
+    MessageMapMethods,                   //  tp_methods
+    0,                                   //  tp_members
+    0,                                   //  tp_getset
+    0,                                   //  tp_base
+    0,                                   //  tp_dict
+    0,                                   //  tp_descr_get
+    0,                                   //  tp_descr_set
+    0,                                   //  tp_dictoffset
+    0,                                   //  tp_init
+  };
+#endif
 
 // MapIterator /////////////////////////////////////////////////////////////////
 
diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h
index 2de6118..ddf94be 100644
--- a/python/google/protobuf/pyext/map_container.h
+++ b/python/google/protobuf/pyext/map_container.h
@@ -111,8 +111,16 @@
   PyObject* message_dict;
 };
 
-extern PyTypeObject ScalarMapContainer_Type;
-extern PyTypeObject MessageMapContainer_Type;
+#if PY_MAJOR_VERSION >= 3
+  extern PyObject *MessageMapContainer_Type;
+  extern PyType_Spec MessageMapContainer_Type_spec;
+  extern PyObject *ScalarMapContainer_Type;
+  extern PyType_Spec ScalarMapContainer_Type_spec;
+#else
+  extern PyTypeObject MessageMapContainer_Type;
+  extern PyTypeObject ScalarMapContainer_Type;
+#endif
+
 extern PyTypeObject MapIterator_Type;  // Both map types use the same iterator.
 
 // Builds a MapContainer object, from a parent message and a
diff --git a/python/setup.py b/python/setup.py
index 2a5513b..1223775 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -162,7 +162,7 @@
     extra_compile_args = ['-Wno-write-strings', '-Wno-invalid-offsetof']
     test_conformance.target = 'test_python_cpp'
 
-    if "clang" in os.popen('$CC --version').read():
+    if "clang" in os.popen('$CC --version 2> /dev/null').read():
       extra_compile_args.append('-Wno-shorten-64-to-32')
 
     if warnings_as_errors in sys.argv: