task: metadata: install: pip install -e .[dev]
patch: diff --git a/CHANGES.rst b/CHANGES.rst
index c9272ea..69afaec 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,10 @@
 4.4.3 (unreleased)
 ------------------
 
-- Nothing changed yet.
+- Fix the repr of the persistent objects to include the module name
+  when using the C extension. This matches the pure-Python behaviour
+  and the behaviour prior to 4.4.0. See `issue 92
+  <https://github.com/zopefoundation/persistent/issues/92>`_.
 
 
 4.4.2 (2018-08-28)
diff --git a/persistent/cPersistence.c b/persistent/cPersistence.c
index 9e0f3ae..5e78cdc 100644
--- a/persistent/cPersistence.c
+++ b/persistent/cPersistence.c
@@ -1423,6 +1423,8 @@ Per_repr(cPersistentObject *self)
     PyObject *prepr = NULL;
     PyObject *prepr_exc_str = NULL;
 
+    PyObject *module = NULL;
+    PyObject *name = NULL;
     PyObject *oid_str = NULL;
     PyObject *jar_str = NULL;
     PyObject *result = NULL;
@@ -1454,15 +1456,32 @@ Per_repr(cPersistentObject *self)
     if (!jar_str)
         goto cleanup;
 
-    result = PyUnicode_FromFormat("<%s object at %p%S%S%S>",
-                                  Py_TYPE(self)->tp_name, self,
-                                  oid_str, jar_str, prepr_exc_str);
+    module = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "__module__");
+    name = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "__name__");
+
+    if (!module || !name) {
+        /*
+          Some error retrieving __module__ or __name__. Ignore it, use the
+          C data.
+        */
+        PyErr_Clear();
+        result = PyUnicode_FromFormat("<%s object at %p%S%S%S>",
+                                      Py_TYPE(self)->tp_name, self,
+                                      oid_str, jar_str, prepr_exc_str);
+    }
+    else {
+        result = PyUnicode_FromFormat("<%S.%S object at %p%S%S%S>",
+                                      module, name, self,
+                                      oid_str, jar_str, prepr_exc_str);
+    }
 
 cleanup:
     Py_XDECREF(prepr);
     Py_XDECREF(prepr_exc_str);
     Py_XDECREF(oid_str);
     Py_XDECREF(jar_str);
+    Py_XDECREF(name);
+    Py_XDECREF(module);
 
     return result;
 }
diff --git a/persistent/persistence.py b/persistent/persistence.py
index 8d72ce1..8af2b8a 100644
--- a/persistent/persistence.py
+++ b/persistent/persistence.py
@@ -585,7 +585,9 @@ class Persistent(object):
                 jar_str = ' in %r' % (e,)
 
         return '<%s.%s object at 0x%x%s%s%s>' % (
-            type(self).__module__, type(self).__name__, id(self),
+            # Match the C name for this exact class
+            type(self).__module__ if type(self) is not Persistent else 'persistent',
+            type(self).__name__, id(self),
             oid_str, jar_str, p_repr_str
         )
 

problem_statement: Type name varies in the repr() depending on the presence of the C extension
This manifests in breakage of [BTrees tests](https://travis-ci.org/zopefoundation/BTrees/jobs/415400906) when the C extensions are used (they pass when the pure-Python extensions are available). 

This is a somewhat common problem. There's a [python-dev thread](https://mail.python.org/pipermail/python-dev/2018-September/155150.html) and [bpo-issue](https://bugs.python.org/issue34595) about this. In particular, in the issue, and one of the [PRs that fixes it](https://github.com/python/cpython/pull/9122/) it's pointed out that getting the correct qualified name in a C type can be complex depending on things like `Py_TPFLAGS_HEAPTYPE` (and that's just on Python 3, I don't know if there's an equivalent of `ht_qualname` on Python 2).

Is this a bug here that we should fix, or should downstream consumers be prepared to deal with the difference? In one of my own downstream projects I dealt with the difference. But BTrees already deals with the difference in its own code to produce equivalent reprs in Python as we *used* to get from C.  (See https://github.com/zopefoundation/BTrees/issues/94)
repo: zopefoundation/persistent
test_cmd: pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
test_patch: diff --git a/persistent/tests/test_persistence.py b/persistent/tests/test_persistence.py
index 9ded7e2..7b502dc 100644
--- a/persistent/tests/test_persistence.py
+++ b/persistent/tests/test_persistence.py
@@ -1698,9 +1698,6 @@ class _Persistent_Base(object):
         self.assertEqual(candidate.set_by_new, 1)
 
     def _normalize_repr(self, r):
-        # Pure-python vs C
-        r = r.replace('persistent.persistence.Persistent', 'persistent.Persistent')
-        r = r.replace("persistent.tests.test_persistence.", '')
         # addresses
         r = re.sub(r'0x[0-9a-fA-F]*', '0xdeadbeef', r)
         # Python 3.7 removed the trailing , in exception reprs
@@ -1842,14 +1839,14 @@ class _Persistent_Base(object):
         result = self._normalized_repr(p)
         self.assertEqual(
             result,
-            "<P object at 0xdeadbeef"
+            "<persistent.tests.test_persistence.P object at 0xdeadbeef"
             " _p_repr Exception('_p_repr failed')>")
 
         p._p_oid = b'12345678'
         result = self._normalized_repr(p)
         self.assertEqual(
             result,
-            "<P object at 0xdeadbeef oid b'12345678'"
+            "<persistent.tests.test_persistence.P object at 0xdeadbeef oid b'12345678'"
             " _p_repr Exception('_p_repr failed')>")
 
         class Jar(object):
@@ -1860,7 +1857,7 @@ class _Persistent_Base(object):
         result = self._normalized_repr(p)
         self.assertEqual(
             result,
-            "<P object at 0xdeadbeef oid b'12345678'"
+            "<persistent.tests.test_persistence.P object at 0xdeadbeef oid b'12345678'"
             " in <SomeJar> _p_repr Exception('_p_repr failed')>")
 
     def test__p_repr_in_instance_ignored(self):
@@ -1869,7 +1866,8 @@ class _Persistent_Base(object):
         p = P()
         p._p_repr = lambda: "Instance"
         result = self._normalized_repr(p)
-        self.assertEqual(result, '<P object at 0xdeadbeef>')
+        self.assertEqual(result,
+                         '<persistent.tests.test_persistence.P object at 0xdeadbeef>')
 
     def test__p_repr_baseexception(self):
         class P(self._getTargetClass()):