def finish_update(self, ctx, exc_info=None):
        if not self.in_update_block:
            raise RuntimeError('Artifact is not open for updates.')
        ctx.pop()
        self.in_update_block = False
        self.updated = True

        # If there was no error, we memoize the dependencies like normal
        # and then commit our transaction.
        if exc_info is None:
            self._memorize_dependencies(
                ctx.referenced_dependencies,
                ctx.referenced_virtual_dependencies.values())
            self._commit()
            return

        # If an error happened we roll back all changes and record the
        # stacktrace in two locations: we record it on the context so
        # that a called can respond to our failure, and we also persist
        # it so that the dev server can render it out later.
        self._rollback()

        # This is a special form of dependency memorization where we do
        # not prune old dependencies and we just append new ones and we
        # use a new database connection that immediately commits.
        self._memorize_dependencies(
            ctx.referenced_dependencies,
            ctx.referenced_virtual_dependencies.values(),
            for_failure=True)

        ctx.exc_info = exc_info
        self.build_state.notify_failure(self, exc_info)
Verify that the iterModules API will only return top-level modules and
dataset/ETHPy150Open lektor/lektor/lektor/builder.py/Artifact.finish_update--crossover with--dataset/ETHPy150Open nlloyd/SubliminalCollaborator/libs/twisted/test/test_modules.py/BasicTests.test_onlyTopModules