Repository: Parquery/icontract

Issue:
include decorator definition in ViolationError description
Consider this module (defined in ictb.py):
```
from icontract import require, ensure

@require(lambda x: x > 0)
def frobulate(x: int) -> int:
    return x
```
Which I use 

```
$ python -c "import ictb; ictb.frobulate(-1)"                                                                                      (tge) 
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/james/Src/icontract/icontract/_checkers.py", line 291, in wrapper
    raise violation_err  # pylint: disable=raising-bad-type
  File "/home/james/Src/icontract/icontract/_checkers.py", line 285, in wrapper
    _assert_precondition(contract=contract, resolved_kwargs=resolved_kwargs)
  File "/home/james/Src/icontract/icontract/_checkers.py", line 112, in _assert_precondition
    raise ViolationError(msg)
icontract.errors.ViolationError: x > 0: x was -1
```

This is pretty good as far as it goes, but I'm always frustrated that there is no link to the source definition of frobulate with its associated requirements.  The cognitive load of finding the requirement is a little bit irritating.

I think we can do better.  In eg `require.__init__`, I can get the require definition site:

        tb = traceback.format_list(traceback.extract_stack(limit=2)[:1])[0]
        description = "\nDefined at ...\n{}".format(tb)

Giving 

```
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/james/Src/icontract/icontract/_checkers.py", line 291, in wrapper
    raise violation_err  # pylint: disable=raising-bad-type
  File "/home/james/Src/icontract/icontract/_checkers.py", line 285, in wrapper
    _assert_precondition(contract=contract, resolved_kwargs=resolved_kwargs)
  File "/home/james/Src/icontract/icontract/_checkers.py", line 112, in _assert_precondition
    raise ViolationError(msg)
icontract.errors.ViolationError: 
Defined at ...
  File "/home/james/Src/time_gym/ictb.py", line 3, in <module>
    @require(lambda x: x > 0)
: x > 0: x was -1
```

What do you think? 

Discussion:

Patch:
diff --git a/README.rst b/README.rst
index 4cee487..17e1bbe 100644
--- a/README.rst
+++ b/README.rst
@@ -84,7 +84,8 @@ If you want to customize the error, see Section "Custom Errors".
     >>> some_func(x=1)
     Traceback (most recent call last):
       ...
-    icontract.errors.ViolationError: x > 3: x was 1
+    icontract.errors.ViolationError: File <doctest README.rst[1]>, line 1 in <module>:
+    x > 3: x was 1
 
     # Pre-condition violation with a description
     >>> @icontract.require(lambda x: x > 3, "x must not be small")
@@ -94,7 +95,8 @@ If you want to customize the error, see Section "Custom Errors".
     >>> some_func(x=1)
     Traceback (most recent call last):
       ...
-    icontract.errors.ViolationError: x must not be small: x > 3: x was 1
+    icontract.errors.ViolationError: File <doctest README.rst[4]>, line 1 in <module>:
+    x must not be small: x > 3: x was 1
 
     # Pre-condition violation with more complex values
     >>> class B:
@@ -123,7 +125,8 @@ If you want to customize the error, see Section "Custom Errors".
     >>> some_func(an_a)
     Traceback (most recent call last):
       ...
-    icontract.errors.ViolationError: a.b.x + a.b.y() > SOME_GLOBAL_VAR:
+    icontract.errors.ViolationError: File <doctest README.rst[9]>, line 1 in <module>:
+    a.b.x + a.b.y() > SOME_GLOBAL_VAR:
     SOME_GLOBAL_VAR was 13
     a was instance of A
     a.b was instance of B
@@ -138,7 +141,8 @@ If you want to customize the error, see Section "Custom Errors".
     >>> some_func(x=10)
     Traceback (most recent call last):
       ...
-    icontract.errors.ViolationError: result > x:
+    icontract.errors.ViolationError: File <doctest README.rst[12]>, line 1 in <module>:
+    result > x:
     result was 5
     x was 10
 
@@ -292,7 +296,8 @@ Here is an example that uses snapshots to check that a value was appended to the
     >>> some_func(lst=[1, 2], value=3)
     Traceback (most recent call last):
         ...
-    icontract.errors.ViolationError: lst == OLD.lst + [value]:
+    icontract.errors.ViolationError: File <doctest README.rst[28]>, line 2 in <module>:
+    lst == OLD.lst + [value]:
     OLD was a bunch of OLD values
     OLD.lst was [1, 2]
     lst was [1, 2, 3, 1984]
@@ -314,7 +319,8 @@ The following example shows how you can name the snapshot:
     >>> some_func(lst=[1, 2], value=3)
     Traceback (most recent call last):
         ...
-    icontract.errors.ViolationError: len(lst) == OLD.len_lst + 1:
+    icontract.errors.ViolationError: File <doctest README.rst[32]>, line 2 in <module>:
+    len(lst) == OLD.len_lst + 1:
     OLD was a bunch of OLD values
     OLD.len_lst was 2
     len(lst) was 4
@@ -392,7 +398,8 @@ The following example shows an abstract parent class and a child class that inhe
         >>> some_b.func(y=0)
         Traceback (most recent call last):
             ...
-        icontract.errors.ViolationError: result < y:
+        icontract.errors.ViolationError: File <doctest README.rst[36]>, line 7 in A:
+        result < y:
         result was 1
         y was 0
 
@@ -445,7 +452,8 @@ The following example shows how preconditions are weakened:
         >>> b.func(x=5)
         Traceback (most recent call last):
             ...
-        icontract.errors.ViolationError: x % 3 == 0: x was 5
+        icontract.errors.ViolationError: File <doctest README.rst[45]>, line 2 in B:
+        x % 3 == 0: x was 5
 
 The example below illustrates how snaphots are inherited:
 
@@ -469,7 +477,8 @@ The example below illustrates how snaphots are inherited:
         >>> b.func(lst=[1, 2], value=3)
         Traceback (most recent call last):
             ...
-        icontract.errors.ViolationError: len(lst) == len(OLD.lst) + 1:
+        icontract.errors.ViolationError: File <doctest README.rst[50]>, line 4 in A:
+        len(lst) == len(OLD.lst) + 1:
         OLD was a bunch of OLD values
         OLD.lst was [1, 2]
         len(OLD.lst) was 2
@@ -567,7 +576,8 @@ Here is an example of the error given as an exception class:
     >>> some_func(x=0)
     Traceback (most recent call last):
         ...
-    ValueError: x > 0: x was 0
+    ValueError: File <doctest README.rst[56]>, line 1 in <module>:
+    x > 0: x was 0
 
 Here is an example of the error given as a callable:
 
diff --git a/icontract/_decorators.py b/icontract/_decorators.py
index 62b005c..f4cb5dc 100644
--- a/icontract/_decorators.py
+++ b/icontract/_decorators.py
@@ -53,7 +53,14 @@ class require:  # pylint: disable=invalid-name
         if not enabled:
             return
 
-        self._contract = Contract(condition=condition, description=description, a_repr=a_repr, error=error)
+        location = None  # type: Optional[str]
+        tb_stack = traceback.extract_stack(limit=2)[:1]
+        if len(tb_stack) > 0:
+            frame = tb_stack[0]
+            location = 'File {}, line {} in {}'.format(frame.filename, frame.lineno, frame.name)
+
+        self._contract = Contract(
+            condition=condition, description=description, a_repr=a_repr, error=error, location=location)
 
     def __call__(self, func: CallableT) -> CallableT:
         """
@@ -130,7 +137,13 @@ class snapshot:  # pylint: disable=invalid-name
 
         # Resolve the snapshot only if enabled so that no overhead is incurred
         if enabled:
-            self._snapshot = Snapshot(capture=capture, name=name)
+            location = None  # type: Optional[str]
+            tb_stack = traceback.extract_stack(limit=2)[:1]
+            if len(tb_stack) > 0:
+                frame = tb_stack[0]
+                location = 'File {}, line {} in {}'.format(frame.filename, frame.lineno, frame.name)
+
+            self._snapshot = Snapshot(capture=capture, name=name, location=location)
 
     def __call__(self, func: CallableT) -> CallableT:
         """
@@ -214,7 +227,14 @@ class ensure:  # pylint: disable=invalid-name
         if not enabled:
             return
 
-        self._contract = Contract(condition=condition, description=description, a_repr=a_repr, error=error)
+        location = None  # type: Optional[str]
+        tb_stack = traceback.extract_stack(limit=2)[:1]
+        if len(tb_stack) > 0:
+            frame = tb_stack[0]
+            location = 'File {}, line {} in {}'.format(frame.filename, frame.lineno, frame.name)
+
+        self._contract = Contract(
+            condition=condition, description=description, a_repr=a_repr, error=error, location=location)
 
     def __call__(self, func: CallableT) -> CallableT:
         """
diff --git a/icontract/_types.py b/icontract/_types.py
index 43b4f3f..c6e80d0 100644
--- a/icontract/_types.py
+++ b/icontract/_types.py
@@ -56,7 +56,7 @@ class Contract:
 class Snapshot:
     """Define a snapshot of an argument *prior* to the function invocation that is later supplied to a postcondition."""
 
-    def __init__(self, capture: Callable[..., Any], name: Optional[str] = None) -> None:
+    def __init__(self, capture: Callable[..., Any], name: Optional[str] = None, location: Optional[str] = None) -> None:
         """
         Initialize.
 
@@ -65,6 +65,7 @@ class Snapshot:
             of the original function)
 
         :param name: name of the captured variable in OLD that is passed to postconditions
+        :param location: indicate where the snapshot was defined (*e.g.*, path and line number)
 
         """
         self.capture = capture
@@ -88,3 +89,5 @@ class Snapshot:
             self.arg = args[0]
         else:
             assert len(args) == 0, "There can be at most one argument to a snapshot capture, but got: {}".format(args)
+
+        self.location = location


Test patch:
diff --git a/tests/test_inheritance_invariant.py b/tests/test_inheritance_invariant.py
index 8be4a44..7085849 100644
--- a/tests/test_inheritance_invariant.py
+++ b/tests/test_inheritance_invariant.py
@@ -71,7 +71,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was instance of B\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_violated_in_child(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -102,7 +102,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was instance of B\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_additional_invariant_violated_in_childs_init(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -127,7 +127,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 100:\n"
                          "self was instance of B\n"
-                         "self.x was 10", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was 10", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_method_violates_in_child(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -156,7 +156,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 100:\n"
                          "self was instance of B\n"
-                         "self.x was 10", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was 10", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_triple_inheritance(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -188,7 +188,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was instance of C\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_abstract_method(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -220,7 +220,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was instance of B\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestProperty(unittest.TestCase):
@@ -250,7 +250,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_setter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -281,7 +282,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_deleter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -312,7 +314,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_invariant_on_getter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -340,7 +343,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_invariant_on_setter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -371,7 +375,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_invariant_on_deleter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -402,7 +407,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 if __name__ == '__main__':
diff --git a/tests/test_inheritance_postcondition.py b/tests/test_inheritance_postcondition.py
index 32f0130..af714eb 100644
--- a/tests/test_inheritance_postcondition.py
+++ b/tests/test_inheritance_postcondition.py
@@ -89,7 +89,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result < 100: result was 1000",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_with_modified_implementation(self):
         class A(icontract.DBC):
@@ -110,7 +110,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result < 100: result was 10000",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_ensure_then_violated_in_base(self):
         class A(icontract.DBC):
@@ -132,7 +132,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("result % 2 == 0: result was 3", str(icontract_violation_error))
+        self.assertEqual("result % 2 == 0: result was 3",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_ensure_then_violated_in_child(self):
         class A(icontract.DBC):
@@ -155,7 +156,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result % 3 == 0: result was 2",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_abstract_method(self):
         class A(icontract.DBC):
@@ -177,7 +178,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result < 100: result was 1000",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_that_base_postconditions_apply_to_init_if_not_defined(self):
         class A(icontract.DBC):
@@ -200,7 +201,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.x >= 0:\n'
                          'self was B\n'
-                         'self.x was -1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.x was -1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_that_base_postconditions_dont_apply_to_init_if_overridden(self):
         class A(icontract.DBC):
@@ -229,7 +230,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.x < 0:\n'
                          'self was B\n'
-                         'self.x was 0', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.x was 0', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestPropertyOK(unittest.TestCase):
@@ -295,7 +296,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_setter(self):
         class SomeBase(icontract.DBC):
@@ -330,7 +332,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_deleter(self):
         class SomeBase(icontract.DBC):
@@ -365,7 +368,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_setter_strengthened(self):
         class SomeBase(icontract.DBC):
@@ -400,7 +404,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
diff --git a/tests/test_inheritance_precondition.py b/tests/test_inheritance_precondition.py
index de39889..0ecb19f 100644
--- a/tests/test_inheritance_precondition.py
+++ b/tests/test_inheritance_precondition.py
@@ -64,7 +64,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 100: x was 1000", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 100: x was 1000",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inherited_with_implementation(self):
         class A(icontract.DBC):
@@ -84,7 +85,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 100: x was 1000", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 100: x was 1000",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_require_else(self):
         class A(icontract.DBC):
@@ -106,7 +108,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x % 3 == 0: x was 5", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x % 3 == 0: x was 5",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_triple_inheritance_wo_implementation(self):
         class A(icontract.DBC):
@@ -128,7 +131,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 100: x was 1000", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 100: x was 1000",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_triple_inheritance_with_implementation(self):
         class A(icontract.DBC):
@@ -151,7 +155,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 100: x was 1000", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 100: x was 1000",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_triple_inheritance_with_require_else(self):
         class A(icontract.DBC):
@@ -178,7 +183,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x % 5 == 0: x was 7", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x % 5 == 0: x was 7",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_abstract_method(self):
         class A(icontract.DBC):
@@ -199,7 +205,7 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x > 0: x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x > 0: x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_that_base_preconditions_apply_to_init_if_not_defined(self):
         class A(icontract.DBC):
@@ -217,7 +223,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x >= 0: x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x >= 0: x was -1", tests.violation_error.wo_mandatory_location(
+            str(icontract_violation_error)))
 
     def test_that_base_preconditions_dont_apply_to_init_if_overridden(self):
         class A(icontract.DBC):
@@ -241,7 +248,7 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 0: x was 0", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 0: x was 0", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestPropertyOK(unittest.TestCase):
@@ -307,7 +314,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_setter(self):
         class SomeBase(icontract.DBC):
@@ -337,8 +345,8 @@ class TestPropertyViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual('value > 0: value was 0', tests.violation_error.lstrip_location(
-            str(icontract_violation_error)))
+        self.assertEqual('value > 0: value was 0',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_deleter(self):
         class SomeBase(icontract.DBC):
@@ -373,7 +381,8 @@ class TestPropertyViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
diff --git a/tests/test_inheritance_snapshot.py b/tests/test_inheritance_snapshot.py
index b3f3cd0..90b8157 100644
--- a/tests/test_inheritance_snapshot.py
+++ b/tests/test_inheritance_snapshot.py
@@ -6,6 +6,8 @@ from typing import Optional, List  # pylint: disable=unused-import
 
 import icontract
 
+import tests.violation_error
+
 
 class TestOK(unittest.TestCase):
     def test_with_no_override(self):
@@ -55,7 +57,7 @@ class TestViolation(unittest.TestCase):
                          'OLD.lst was []\n'
                          'self was B\n'
                          'self.lst was [2, 1984]\n'
-                         'val was 2', str(icontract_violation_error))
+                         'val was 2', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_inherited_snapshot(self):
         class A(icontract.DBC):
@@ -90,7 +92,8 @@ class TestViolation(unittest.TestCase):
                          'OLD.len_lst was 0\n'
                          'len(self.lst) was 2\n'
                          'self was B\n'
-                         'self.lst was [2, 1984]', str(icontract_violation_error))
+                         'self.lst was [2, 1984]',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestPropertyOK(unittest.TestCase):
@@ -182,7 +185,7 @@ class TestPropertyViolation(unittest.TestCase):
                          'OLD was a bunch of OLD values\n'
                          'OLD.gets was 0\n'
                          'self was SomeClass\n'
-                         'self.gets was 0', str(icontract_violation_error))
+                         'self.gets was 0', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
         # setter fails
         icontract_violation_error = None
@@ -196,7 +199,7 @@ class TestPropertyViolation(unittest.TestCase):
                          'OLD was a bunch of OLD values\n'
                          'OLD.sets was 0\n'
                          'self was SomeClass\n'
-                         'self.sets was 0', str(icontract_violation_error))
+                         'self.sets was 0', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
         # deleter fails
         icontract_violation_error = None
@@ -210,7 +213,7 @@ class TestPropertyViolation(unittest.TestCase):
                          'OLD was a bunch of OLD values\n'
                          'OLD.dels was 0\n'
                          'self was SomeClass\n'
-                         'self.dels was 0', str(icontract_violation_error))
+                         'self.dels was 0', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
diff --git a/tests/test_invariant.py b/tests/test_invariant.py
index 22cc9f2..bdfdc9d 100644
--- a/tests/test_invariant.py
+++ b/tests/test_invariant.py
@@ -167,7 +167,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.x > 0:\n'
                          'self was some instance\n'
-                         'self.x was 0', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.x was 0', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inv_as_precondition(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -192,7 +192,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_method(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -216,7 +216,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_magic_method(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -240,7 +240,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_multiple_invs_first_violated(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -261,7 +261,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_multiple_invs_last_violated(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -282,7 +282,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x < 10:\n"
                          "self was some instance\n"
-                         "self.x was 100", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was 100", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inv_violated_after_pre(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -305,7 +305,7 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("y > 0: y was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("y > 0: y was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
         icontract_violation_error = None  # type: Optional[icontract.ViolationError]
         try:
@@ -317,7 +317,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inv_ok_but_post_violated(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -342,7 +342,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result > 0: result was -1",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inv_violated_but_post_ok(self):
         @icontract.invariant(lambda self: self.x > 0)
@@ -368,7 +368,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("self.x > 0:\n"
                          "self was some instance\n"
-                         "self.x was -1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.x was -1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_inv_with_empty_arguments(self):
         z = 42
@@ -384,7 +384,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("z != 42: z was 42", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("z != 42: z was 42", tests.violation_error.wo_mandatory_location(
+            str(icontract_violation_error)))
 
 
 class TestProperty(unittest.TestCase):
@@ -413,7 +414,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_property_setter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -443,7 +445,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_property_deleter(self):
         @icontract.invariant(lambda self: not self.toggled)
@@ -473,7 +476,8 @@ class TestProperty(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not self.toggled:\n'
                          'self was SomeClass\n'
-                         'self.toggled was True', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.toggled was True',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestError(unittest.TestCase):
@@ -496,7 +500,7 @@ class TestError(unittest.TestCase):
         self.assertIsInstance(value_error, ValueError)
         self.assertEqual('self.x > 0:\n'
                          'self was A\n'
-                         'self.x was 0', tests.violation_error.lstrip_location(str(value_error)))
+                         'self.x was 0', tests.violation_error.wo_mandatory_location(str(value_error)))
 
     def test_as_function(self):
         @icontract.invariant(
diff --git a/tests/test_postcondition.py b/tests/test_postcondition.py
index 9489a0d..d8d21a6 100644
--- a/tests/test_postcondition.py
+++ b/tests/test_postcondition.py
@@ -38,7 +38,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result > x:\n"
                          "result was -4\n"
-                         "x was 1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "x was 1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_description(self):
         @icontract.ensure(lambda result, x: result > x, "expected summation")
@@ -54,7 +54,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("expected summation: result > x:\n"
                          "result was -4\n"
-                         "x was 1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "x was 1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_stacked_decorators(self):
         def mydecorator(f):
@@ -85,7 +85,7 @@ class TestViolation(unittest.TestCase):
         self.assertEqual("y > result + another_var:\n"
                          "another_var was 2\n"
                          "result was 100\n"
-                         "y was 10", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "y was 10", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_default_values_outer(self):
         @icontract.ensure(lambda result, c: result % c == 0)
@@ -103,7 +103,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result % c == 0:\n"
                          "c was 2\n"
-                         "result was 13", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "result was 13", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
         # Check the inner post condition
         icontract_violation_error = None  # type: Optional[icontract.ViolationError]
@@ -115,7 +115,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result < b:\n"
                          "b was 21\n"
-                         "result was 36", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "result was 36", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_only_result(self):
         @icontract.ensure(lambda result: result > 3)
@@ -130,7 +130,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("result > 3: result was 0",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestError(unittest.TestCase):
@@ -147,7 +147,7 @@ class TestError(unittest.TestCase):
 
         self.assertIsNotNone(value_error)
         self.assertIsInstance(value_error, ValueError)
-        self.assertEqual('result > 0: result was 0', str(value_error))
+        self.assertEqual('result > 0: result was 0', tests.violation_error.wo_mandatory_location(str(value_error)))
 
     def test_as_function(self):
         @icontract.ensure(lambda result: result > 0, error=lambda result: ValueError("result must be positive."))
@@ -231,7 +231,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('result != 0: result was 0',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_postcondition_in_class_method(self):
         class SomeClass:
@@ -251,7 +251,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('result != 0: result was 0',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_postcondition_in_abstract_static_method(self):
         class SomeAbstract(icontract.DBC):
@@ -276,7 +276,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('result != 0: result was 0',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_postcondition_in_abstract_class_method(self):
         class Abstract(icontract.DBC):
@@ -302,7 +302,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('result != 0: result was 0',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_getter(self):
         class SomeClass:
@@ -324,7 +324,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('result > 0: result was -1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_setter(self):
         class SomeClass:
@@ -351,7 +351,8 @@ class TestInClass(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.some_prop > 0:\n'
                          'self was SomeClass\n'
-                         'self.some_prop was 0', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.some_prop was 0',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_deleter(self):
         class SomeClass:
@@ -380,7 +381,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.some_prop > 0:\nself was SomeClass\nself.some_prop was -1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
@@ -442,4 +443,5 @@ class TestInvalid(unittest.TestCase):
 
         self.assertIsNotNone(type_error)
         self.assertEqual("The argument(s) of the postcondition error have not been set: ['z']. "
-                         "Does the original function define them? Did you supply them in the call?", str(type_error))
+                         "Does the original function define them? Did you supply them in the call?",
+                         tests.violation_error.wo_mandatory_location(str(type_error)))
diff --git a/tests/test_precondition.py b/tests/test_precondition.py
index 60218bd..c7223d5 100644
--- a/tests/test_precondition.py
+++ b/tests/test_precondition.py
@@ -37,7 +37,7 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x > 3: x was 1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x > 3: x was 1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_description(self):
         @icontract.require(lambda x: x > 3, "x must not be small")
@@ -52,7 +52,7 @@ class TestViolation(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("x must not be small: x > 3: x was 1",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_condition_as_function(self):
         def some_condition(x: int):
@@ -69,8 +69,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("some_condition: x was 1", tests.violation_error.lstrip_location(
-            str(icontract_violation_error)))
+        self.assertEqual("some_condition: x was 1",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_pathlib(self):
         @icontract.require(lambda path: path.exists())
@@ -86,8 +86,8 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("path.exists():\n"
                          "path was PosixPath('/doesnt/exist/test_contract')\n"
-                         "path.exists() was False", tests.violation_error.lstrip_location(
-                             str(icontract_violation_error)))
+                         "path.exists() was False",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_multiple_comparators(self):
         @icontract.require(lambda x: 0 < x < 3)
@@ -101,7 +101,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("0 < x < 3: x was 10", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("0 < x < 3: x was 10",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_stacked_decorators(self):
         def mydecorator(f):
@@ -131,7 +132,7 @@ class TestViolation(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("x > another_var:\n"
                          "another_var was 0\n"
-                         "x was 0", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "x was 0", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_default_values(self):
         @icontract.require(lambda a: a < 10)
@@ -147,7 +148,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("c < 10: c was 22", str(icontract_violation_error))
+        self.assertEqual("c < 10: c was 22", tests.violation_error.wo_mandatory_location(
+            str(icontract_violation_error)))
 
         icontract_violation_error = None  # type: Optional[icontract.ViolationError]
         try:
@@ -156,7 +158,8 @@ class TestViolation(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("b < 10: b was 21", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("b < 10: b was 21", tests.violation_error.wo_mandatory_location(
+            str(icontract_violation_error)))
 
 
 class TestBenchmark(unittest.TestCase):
@@ -220,7 +223,7 @@ class TestError(unittest.TestCase):
 
         self.assertIsNotNone(value_error)
         self.assertIsInstance(value_error, ValueError)
-        self.assertEqual('x > 0: x was 0', str(value_error))
+        self.assertEqual('x > 0: x was 0', tests.violation_error.wo_mandatory_location(str(value_error)))
 
     def test_as_function(self):
         @icontract.require(lambda x: x > 0, error=lambda x: ValueError("x non-negative"))
@@ -328,7 +331,7 @@ class TestInClass(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x > 3: x was 1", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x > 3: x was 1", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
         # Test method with self
         icontract_violation_error = None  # type: Optional[icontract.ViolationError]
@@ -340,7 +343,7 @@ class TestInClass(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.y > 10:\n'
                          'self was A\n'
-                         'self.y was 5', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'self.y was 5', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_getter(self):
         class SomeClass:
@@ -366,8 +369,8 @@ class TestInClass(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self._some_prop > 0:\n'
                          'self was SomeClass\n'
-                         'self._some_prop was -1', tests.violation_error.lstrip_location(
-                             str(icontract_violation_error)))
+                         'self._some_prop was -1',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_setter(self):
         class SomeClass:
@@ -389,8 +392,8 @@ class TestInClass(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual('value > 0: value was -1', tests.violation_error.lstrip_location(
-            str(icontract_violation_error)))
+        self.assertEqual('value > 0: value was -1',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_deleter(self):
         class SomeClass:
@@ -419,7 +422,7 @@ class TestInClass(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('self.some_prop > 0:\nself was SomeClass\nself.some_prop was -1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
@@ -451,7 +454,8 @@ class TestInvalid(unittest.TestCase):
 
         self.assertIsNotNone(type_error)
         self.assertEqual("The argument(s) of the precondition error have not been set: ['z']. "
-                         "Does the original function define them? Did you supply them in the call?", str(type_error))
+                         "Does the original function define them? Did you supply them in the call?",
+                         tests.violation_error.wo_mandatory_location(str(type_error)))
 
 
 if __name__ == '__main__':
diff --git a/tests/test_represent.py b/tests/test_represent.py
index bfd1af6..e651b71 100644
--- a/tests/test_represent.py
+++ b/tests/test_represent.py
@@ -24,7 +24,8 @@ class TestReprValues(unittest.TestCase):
             icontract_violation_error = err
 
         self.assertIsNotNone(icontract_violation_error)
-        self.assertEqual("x < 5: x was 100", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+        self.assertEqual("x < 5: x was 100", tests.violation_error.wo_mandatory_location(
+            str(icontract_violation_error)))
 
     def test_str(self):
         @icontract.require(lambda x: x != "oi")
@@ -39,7 +40,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("""x != "oi": x was 'oi'""",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_bytes(self):
         @icontract.require(lambda x: x != b"oi")
@@ -54,7 +55,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("""x != b"oi": x was b'oi'""",
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_bool(self):
         @icontract.require(lambda x: x is not False)
@@ -69,7 +70,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x is not False: x was False',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_list(self):
         y = 1
@@ -88,7 +89,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual('sum([1, y, x]) == 1:\n'
                          'sum([1, y, x]) was 5\n'
                          'x was 3\n'
-                         'y was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'y was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_tuple(self):
         y = 1
@@ -107,7 +108,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual('sum((1, y, x)) == 1:\n'
                          'sum((1, y, x)) was 5\n'
                          'x was 3\n'
-                         'y was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'y was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_set(self):
         y = 2
@@ -126,7 +127,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual('sum({1, y, x}) == 1:\n'
                          'sum({1, y, x}) was 6\n'
                          'x was 3\n'
-                         'y was 2', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'y was 2', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_dict(self):
         y = "someKey"
@@ -145,7 +146,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual("len({y: 3, x: 8}) == 6:\n"
                          "len({y: 3, x: 8}) was 2\n"
                          "x was 'oi'\n"
-                         "y was 'someKey'", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "y was 'someKey'", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_unary_op(self):
         @icontract.require(lambda x: not -x + 10 > 3)
@@ -160,7 +161,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('not -x + 10 > 3: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_binary_op(self):
         @icontract.require(lambda x: -x + x - x * x / x // x**x % x > 3)
@@ -175,7 +176,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('-x + x - x * x / x // x**x % x > 3: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_binary_op_bit(self):
         @icontract.require(lambda x: ~(x << x | x & x ^ x) >> x > x)
@@ -190,7 +191,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('~(x << x | x & x ^ x) >> x > x: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_bool_op_single(self):
         # pylint: disable=chained-comparison
@@ -206,7 +207,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x > 3 and x < 10: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_bool_op_multiple(self):
         # pylint: disable=chained-comparison
@@ -222,7 +223,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x > 3 and x < 10 and x % 2 == 0: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_compare(self):
         # pylint: disable=chained-comparison
@@ -243,7 +244,7 @@ class TestReprValues(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('0 < x < 3 and x > 10 and x != 7 and x >= 10 and x <= 11 and x is not None and\n'
                          '              x in [1, 2, 3] and x not in [1, 2, 3]: x was 1',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_call(self):
         def y() -> int:
@@ -262,7 +263,7 @@ class TestReprValues(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x < y():\n'
                          'x was 1\n'
-                         'y() was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'y() was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_if_exp_body(self):
         y = 5
@@ -280,7 +281,7 @@ class TestReprValues(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x < (x**2 if y == 5 else x**3):\n'
                          'x was 1\n'
-                         'y was 5', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'y was 5', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_if_exp_orelse(self):
         y = 5
@@ -297,7 +298,7 @@ class TestReprValues(unittest.TestCase):
 
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x < (x**2 if y != 5 else x**3):\nx was 1\ny was 5',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_attr(self):
         class A:
@@ -323,7 +324,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual('x > a.y:\n'
                          'a was A()\n'
                          'a.y was 3\n'
-                         'x was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'x was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_index(self):
         lst = [1, 2, 3]
@@ -341,7 +342,7 @@ class TestReprValues(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('x > lst[1]:\n'
                          'lst was [1, 2, 3]\n'
-                         'x was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'x was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_slice(self):
         lst = [1, 2, 3]
@@ -360,7 +361,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual('x > sum(lst[1:2:1]):\n'
                          'lst was [1, 2, 3]\n'
                          'sum(lst[1:2:1]) was 2\n'
-                         'x was 1', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'x was 1', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_lambda(self):
         @icontract.require(lambda x: x > (lambda y: y + 4).__call__(y=7))
@@ -390,7 +391,7 @@ class TestReprValues(unittest.TestCase):
         self.assertEqual("all(single_res[1].is_absolute() for single_res in result):\n"
                          "all(single_res[1].is_absolute() for single_res in result) was False\n"
                          "result was [(PosixPath('/home/file1'), PosixPath('home/file2'))]",
-                         str(icontract_violation_error))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_generator_expression_multiple_for(self):
         lst = [[1, 2], [3]]
@@ -413,7 +414,8 @@ class TestReprValues(unittest.TestCase):
 
         self.assertEqual('all(item == x for sublst in lst for item in sublst):\n'
                          'all(item == x for sublst in lst for item in sublst) was False\n'
-                         'lst was [[1, 2], [3]]', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'lst was [[1, 2], [3]]',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_list_comprehension(self):
         lst = [1, 2, 3]
@@ -431,7 +433,8 @@ class TestReprValues(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual('[item < x for item in lst if item % x == 0] == []:\n'
                          '[item < x for item in lst if item % x == 0] was [False]\n'
-                         'lst was [1, 2, 3]', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'lst was [1, 2, 3]', tests.violation_error.wo_mandatory_location(
+                             str(icontract_violation_error)))
 
     def test_set_comprehension(self):
         lst = [1, 2, 3]
@@ -451,7 +454,7 @@ class TestReprValues(unittest.TestCase):
                          'len({item < x for item in lst if item % x == 0}) was 1\n'
                          'lst was [1, 2, 3]\n'
                          '{item < x for item in lst if item % x == 0} was {False}',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_dict_comprehension(self):
         @icontract.require(lambda x: len({i: i**2 for i in range(x)}) == 0)
@@ -470,7 +473,7 @@ class TestReprValues(unittest.TestCase):
                          'range(x) was range(0, 2)\n'
                          'x was 2\n'
                          '{i: i**2 for i in range(x)} was {0: 0, 1: 1}',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestConditionAsText(unittest.TestCase):
@@ -491,7 +494,7 @@ class TestConditionAsText(unittest.TestCase):
             violation_err = err
 
         self.assertIsNotNone(violation_err)
-        self.assertEqual("x > 3: x was 0", str(violation_err))
+        self.assertEqual("x > 3: x was 0", tests.violation_error.wo_mandatory_location(str(violation_err)))
 
     def test_condition_on_next_line(self):
         # yapf: disable
@@ -509,7 +512,7 @@ class TestConditionAsText(unittest.TestCase):
             violation_err = err
 
         self.assertIsNotNone(violation_err)
-        self.assertEqual("x > 3: x was 0", str(violation_err))
+        self.assertEqual("x > 3: x was 0", tests.violation_error.wo_mandatory_location(str(violation_err)))
 
     def test_condition_on_multiple_lines(self):
         # yapf: disable
@@ -530,7 +533,7 @@ class TestConditionAsText(unittest.TestCase):
             violation_err = err
 
         self.assertIsNotNone(violation_err)
-        self.assertEqual('x\n    >\n    3: x was 0', str(violation_err))
+        self.assertEqual('x\n    >\n    3: x was 0', tests.violation_error.wo_mandatory_location(str(violation_err)))
 
     def test_with_multiple_lambdas_on_a_line(self):
         # pylint: disable=unnecessary-lambda
@@ -584,7 +587,8 @@ class TestRepr(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("len(x) < 10:\n"
                          "len(x) was 10000\n"
-                         "x was [0, 1, 2, ...]", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "x was [0, 1, 2, ...]",
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestClass(unittest.TestCase):
@@ -622,7 +626,7 @@ class TestClass(unittest.TestCase):
         self.assertEqual("self.b.x > 0:\n"
                          "self was A()\n"
                          "self.b was B(x=0)\n"
-                         "self.b.x was 0", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "self.b.x was 0", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_nested_method(self):
         z = 10
@@ -675,7 +679,7 @@ class TestClass(unittest.TestCase):
                          "self.b.c(x=0) was C(x=0)\n"
                          "self.b.c(x=0).x() was 0\n"
                          "str(gt_zero(self.b.c(x=0).x() + 12.2 * z)) was 'True'\n"
-                         "z was 10", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "z was 10", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestClosures(unittest.TestCase):
@@ -697,7 +701,7 @@ class TestClosures(unittest.TestCase):
         self.assertEqual("x < y + z:\n"
                          "x was 100\n"
                          "y was 4\n"
-                         "z was 5", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "z was 5", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_global(self):
         @icontract.require(lambda x: x < SOME_GLOBAL_CONSTANT)
@@ -713,7 +717,7 @@ class TestClosures(unittest.TestCase):
         self.assertIsNotNone(icontract_violation_error)
         self.assertEqual("x < SOME_GLOBAL_CONSTANT:\n"
                          "SOME_GLOBAL_CONSTANT was 10\n"
-                         "x was 100", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "x was 100", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_closure_and_global(self):
         y = 4
@@ -732,7 +736,7 @@ class TestClosures(unittest.TestCase):
         self.assertEqual("x < y + SOME_GLOBAL_CONSTANT:\n"
                          "SOME_GLOBAL_CONSTANT was 10\n"
                          "x was 100\n"
-                         "y was 4", tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         "y was 4", tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class MockArray:
@@ -791,7 +795,7 @@ class TestWithNumpyMock(unittest.TestCase):
         self.assertEqual('(arr > 0).all():\n'
                          '(arr > 0).all() was False\n'
                          'arr was MockArray([-3, 3])',
-                         tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_that_multiple_comparators_fail(self) -> None:
         """
diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py
index 7f7c653..140ebb1 100644
--- a/tests/test_snapshot.py
+++ b/tests/test_snapshot.py
@@ -60,7 +60,7 @@ class TestViolation(unittest.TestCase):
                          'OLD was a bunch of OLD values\n'
                          'OLD.lst was [1]\n'
                          'lst was [1, 2, 1984]\n'
-                         'val was 2', tests.violation_error.lstrip_location(str(icontract_violation_error)))
+                         'val was 2', tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
     def test_with_custom_name(self):
         @icontract.snapshot(lambda lst: len(lst), name="len_lst")
@@ -80,7 +80,8 @@ class TestViolation(unittest.TestCase):
                          'OLD was a bunch of OLD values\n'
                          'OLD.len_lst was 1\n'
                          'len(lst) was 3\n'
-                         'lst was [1, 2, 1984]', str(icontract_violation_error))
+                         'lst was [1, 2, 1984]',
+                         tests.violation_error.wo_mandatory_location(str(icontract_violation_error)))
 
 
 class TestInvalid(unittest.TestCase):
diff --git a/tests/violation_error.py b/tests/violation_error.py
index 73442ab..67244a6 100644
--- a/tests/violation_error.py
+++ b/tests/violation_error.py
@@ -2,15 +2,27 @@
 """Manipulate the text of the violation error."""
 import re
 
+_LOCATION_RE = re.compile(r'\AFile [^\n]+, line [0-9]+ in [a-zA-Z_0-9]+:\n(.*)\Z', flags=re.MULTILINE | re.DOTALL)
 
-def lstrip_location(text: str) -> str:
+
+def wo_mandatory_location(text: str) -> str:
     r"""
     Strip the location of the contract from the text of the violation error.
 
     :param text: text of the violation error
     :return: text without the location prefix
+    :raise AssertionError: if the location is not present in the text of the violation error.
+
+    >>> wo_mandatory_location(text='File /some/file.py, line 233 in some_module:\nsome\ntext')
+    'some\ntext'
 
-    >>> lstrip_location(text='File /some/file.py, line 233 in some_module:\\nsome text')
-    'some text'
+    >>> wo_mandatory_location(text='a text')
+    Traceback (most recent call last):
+    ...
+    AssertionError: Expected the text to match \AFile [^\n]+, line [0-9]+ in [a-zA-Z_0-9]+:\n(.*)\Z, but got: 'a text'
     """
-    return re.sub(r'^File .+, line [0-9]+ in [a-zA-Z_0-9]+:\n', '', text, flags=re.MULTILINE)
+    mtch = _LOCATION_RE.match(text)
+    if not mtch:
+        raise AssertionError("Expected the text to match {}, but got: {!r}".format(_LOCATION_RE.pattern, text))
+
+    return mtch.group(1)