Как создать новый словарь, не меняя старый?
rows = self.rows
НО! В тоже время изменяется из self.rows, который является другим списком.
Не является. Твой оператор просто присвоил переменной rows ссылку на тот же самый список, что и self.rows.
Это легко проверить оператором is или сравнением id():
print(rows is self.rows, id(rows) == id(self.rows))  # True True
Более того, если ты только скопируешь сам список:
rows = self.rows.copy()
То всё ещё поймаешь проблемы, так как скопируются ссылки на элементы, а не их значения:
print(rows is self.rows, id(rows) == id(self.rows))  # False False
print(rows[0] is self.rows[0], id(rows[0]) == id(self.rows[0]))  # True True
Тебе нужно сделать глубокую копию (deepcopy). Это можно сделать вручную, так как у тебя всего два уровня вложенности (список-словарь):
rows = [rowdict.copy() for rowdict in self.rows]
Для более глубоких уровней есть функция copy.deepcopy(), но у неё есть свои подводные камни. Цитата:
Two problems often exist with deep copy operations that don’t exist with shallow copy operations:
    Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
    Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.

Так происходит, потому что присвоение значения переменной rows = self.rows не является дублированием исходного массива. Нужно использовать deepcopy().