diff --git a/CHANGES.rst b/CHANGES.rst
index 32b7510..b976f79 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,9 @@ Changes
 Unreleased
 ----------
 
+- Fixed the transaction manager ``attempts`` method. It didn't stop
+  repeating when there wasn't an error.
+
 - Corrected ITransaction by removing beforeCommitHook (which is no longer
   implemented) and removing 'self' from two methods.
 
diff --git a/buildout.cfg b/buildout.cfg
index fe65737..0fd0713 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = py
+parts = py sphinx
 
 [test]
 recipe = zc.recipe.testrunner
@@ -10,3 +10,10 @@ eggs = transaction [test]
 recipe = zc.recipe.egg
 eggs = ${test:eggs}
 interpreter = py
+
+[sphinx]
+recipe = zc.recipe.egg
+eggs =
+  transaction
+  sphinx
+  repoze.sphinx.autointerface
diff --git a/docs/convenience.rst b/docs/convenience.rst
index cb1c1ff..bfc3cc3 100644
--- a/docs/convenience.rst
+++ b/docs/convenience.rst
@@ -125,7 +125,7 @@ Of course, other errors are propagated directly:
     >>> for attempt in transaction.manager.attempts():
     ...     with attempt:
     ...         ntry += 1
-    ...         if ntry == 3:
+    ...         if ntry % 3:
     ...             raise ValueError(ntry)
     Traceback (most recent call last):
     ...
@@ -135,6 +135,7 @@ We can use the default transaction manager:
 
 .. doctest::
 
+    >>> ntry = 0
     >>> for attempt in transaction.attempts():
     ...     with attempt as t:
     ...         t.note('test')
@@ -143,9 +144,9 @@ We can use the default transaction manager:
     ...         dm['ntry'] = ntry
     ...         if ntry % 3:
     ...             raise Retry(ntry)
-    3 3
-    3 4
-    3 5
+    3 0
+    3 1
+    3 2
 
 Sometimes, a data manager doesn't raise exceptions directly, but
 wraps other other systems that raise exceptions outside of it's
@@ -172,9 +173,9 @@ attempted again.
     ...         dm2['ntry'] = ntry
     ...         if ntry % 3:
     ...             raise ValueError('we really should retry this')
-    6 0
-    6 1
-    6 2
+    3 0
+    3 1
+    3 2
 
     >>> dm2['ntry']
     3
diff --git a/transaction/_manager.py b/transaction/_manager.py
index 8f642ba..b4bfbe3 100644
--- a/transaction/_manager.py
+++ b/transaction/_manager.py
@@ -144,7 +144,10 @@ class TransactionManager(object):
         while number:
             number -= 1
             if number:
-                yield Attempt(self)
+                attempt = Attempt(self)
+                yield attempt
+                if attempt.success:
+                    break
             else:
                 yield self
 
@@ -167,6 +170,8 @@ class ThreadTransactionManager(TransactionManager, threading.local):
 
 class Attempt(object):
 
+    success = False
+
     def __init__(self, manager):
         self.manager = manager
 
@@ -186,5 +191,7 @@ class Attempt(object):
                 self.manager.commit()
             except:
                 return self._retry_or_raise(*sys.exc_info())
+            else:
+                self.success = True
         else:
             return self._retry_or_raise(t, v, tb)

diff --git a/transaction/tests/test__manager.py b/transaction/tests/test__manager.py
index 8db9ca4..8ec9a04 100644
--- a/transaction/tests/test__manager.py
+++ b/transaction/tests/test__manager.py
@@ -236,6 +236,16 @@ class TransactionManagerTests(unittest.TestCase):
         self.assertEqual(len(found), 1)
         self.assertTrue(found[0] is tm)
 
+    def test_attempts_stop_on_success(self):
+        tm = self._makeOne()
+
+        i = 0
+        for attempt in tm.attempts():
+            with attempt:
+                i += 1
+
+        self.assertEqual(i, 1)
+
     def test_attempts_w_default_count(self):
         from transaction._manager import Attempt
         tm = self._makeOne()

Attemps are retried on successful run
I'm not sure if this is a bug or intended behavior. But the attempts function does work as described in the example code in the [documents](http://transaction.readthedocs.io/en/latest/convenience.html#retries):

```
for i in range(3):
    try:
       with transaction.manager:
           ... some something ...
    except SomeTransientException:
       contine
    else:
       break
```

Instead it works as:

```
for i in range(3):
    try:
       with transaction.manager:
           ... some something ...
    except SomeTransientException:
       contine
```

A successful attempt will just try again, as shown in the following:

```
import transaction.tests.savepointsample
import transaction

dm = transaction.tests.savepointsample.SampleSavepointDataManager()
with transaction.manager:
    dm['ntry'] = 0
ntry = 0

import transaction.interfaces
class Retry(transaction.interfaces.TransientError):
    pass

for attempt in transaction.manager.attempts(6):
    with attempt as t:
        t.note('test')
        print("%s %s" % (dm['ntry'], ntry))
        ntry += 1
        dm['ntry'] = ntry
        if ntry % 3:
            raise Retry(ntry)
print('current ntry: %s' % dm['ntry'])
```

The result:

```
0 0
0 1
0 2
3 3
3 4
3 5
current ntry 6
```

While if the documentation is to be believed I'd expect a result as follows:

```
0 0
0 1
0 2
current ntry 3
```

Thus my question is really what is correct, the documentation or the implementation?

transaction/tests/test__manager.py::TransactionManagerTests::test_attempts_stop_on_success
transaction/tests/test__manager.py::TransactionManagerTests::test__retryable_w_multiple transaction/tests/test__manager.py::TransactionManagerTests::test__retryable_w_normal_exception_no_resources transaction/tests/test__manager.py::TransactionManagerTests::test__retryable_w_normal_exception_w_resource_voting_yes transaction/tests/test__manager.py::TransactionManagerTests::test__retryable_w_transient_error transaction/tests/test__manager.py::TransactionManagerTests::test__retryable_w_transient_subclass transaction/tests/test__manager.py::TransactionManagerTests::test_abort_normal transaction/tests/test__manager.py::TransactionManagerTests::test_abort_w_broken_jar transaction/tests/test__manager.py::TransactionManagerTests::test_abort_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_abort_w_nonsub_jar transaction/tests/test__manager.py::TransactionManagerTests::test_as_context_manager_w_error transaction/tests/test__manager.py::TransactionManagerTests::test_as_context_manager_wo_error transaction/tests/test__manager.py::TransactionManagerTests::test_attempts_w_default_count transaction/tests/test__manager.py::TransactionManagerTests::test_attempts_w_invalid_count transaction/tests/test__manager.py::TransactionManagerTests::test_attempts_w_valid_count transaction/tests/test__manager.py::TransactionManagerTests::test_begin_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_begin_wo_existing_txn_w_synchs transaction/tests/test__manager.py::TransactionManagerTests::test_begin_wo_existing_txn_wo_synchs transaction/tests/test__manager.py::TransactionManagerTests::test_clearSynchs transaction/tests/test__manager.py::TransactionManagerTests::test_commit_normal transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_broken_jar_commit transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_broken_jar_tpc_abort_tpc_vote transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_broken_jar_tpc_begin transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_broken_jar_tpc_vote transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_commit_w_nonsub_jar transaction/tests/test__manager.py::TransactionManagerTests::test_ctor transaction/tests/test__manager.py::TransactionManagerTests::test_doom transaction/tests/test__manager.py::TransactionManagerTests::test_free_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_free_w_other_txn transaction/tests/test__manager.py::TransactionManagerTests::test_get_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_get_wo_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_isDoomed_w_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_isDoomed_wo_existing_txn transaction/tests/test__manager.py::TransactionManagerTests::test_notify_transaction_late_comers transaction/tests/test__manager.py::TransactionManagerTests::test_registerSynch transaction/tests/test__manager.py::TransactionManagerTests::test_savepoint_default transaction/tests/test__manager.py::TransactionManagerTests::test_savepoint_explicit transaction/tests/test__manager.py::TransactionManagerTests::test_unregisterSynch transaction/tests/test__manager.py::AttemptTests::test___enter__ transaction/tests/test__manager.py::AttemptTests::test___exit__no_exc_abort_exception_after_nonretryable_commit_exc transaction/tests/test__manager.py::AttemptTests::test___exit__no_exc_no_commit_exception transaction/tests/test__manager.py::AttemptTests::test___exit__no_exc_nonretryable_commit_exception transaction/tests/test__manager.py::AttemptTests::test___exit__no_exc_retryable_commit_exception transaction/tests/test__manager.py::AttemptTests::test___exit__with_exception_value_nonretryable transaction/tests/test__manager.py::AttemptTests::test___exit__with_exception_value_retryable transaction/tests/test__manager.py::test_suite