I got inspired by this answer in order to elaborate mine.
So, i'll use inspect and re modules alongside with a decorator in order to check if run method is called or not:
import re
import inspect
def check_run_is_called(func):
    def wrapper(*args, **kwargs):
        # Here the interesting part
        # We're searching if the string `.run()` exists in the code context
        run_exist = re.search(r'\.run\(.*?\)', inspect.stack()[-1].code_context[0])
        if not run_exist:
            raise Exception('Run must be called !')
        f = func(*args, **kwargs)
        return f
    return wrapper
class TestClass():
    @check_run_is_called
    def method1(self, arg):
        print(arg)
        return self
    @check_run_is_called
    def method2(self, arg):
        print(arg)
        return self
    @check_run_is_called
    def method3(self, arg):
        print(arg)
        return self
    def run(self):
        print('Run')
# test
if __name__ == '__main__':
    app = TestClass()
    app.method1('method1').method2('method2').method3('method3').run()
Output:
method1
method2
method3
Run
Otherwise, if we call the method chain without including run method:
app.method1('method1').method2('method2').method3('method3')
We'll get an Exception:
Exception: Run must be called !
Besides of this, you can also create a combination of chains like this example:
app.method1('method1').run()
# method1
# Run
app.method1('method1').method2('method2').run()
# method1
# method2
# Run
app.method2('method2').method3('method3').method1('method1').run()
# method2
# method3
# method1
# Run