Используйте отрицательный lookghead для соответствия всем запятым, которые не находятся внутри скобки. Разделение входной строки в соответствии с согласованными запятыми даст вам желаемый результат.
,\s*(?![^()]*\))
>>> import re
>>> s = "Water, Titanium Dioxide (CI 77897), Black 2 (CI 77266), Iron Oxides (CI 77491, 77492, 77499), Ultramarines (CI 77007)"
>>> re.split(r',\s*(?![^()]*\))', s)
['Water', 'Titanium Dioxide (CI 77897)', 'Black 2 (CI 77266)', 'Iron Oxides (CI 77491, 77492, 77499)', 'Ultramarines (CI 77007)']
Вам нужно пометить cur_step как глобальный внутри вашей функции (а также снаружи, для правильного обозначения кода).
Функция может без проблем использовать переменную из родительской области видимости, если в области действия функции нет присваивания. Если где-то есть присваивание (даже если оно в блоке if), то функция интерпретируется как локальная; это верно даже до того момента, когда происходит его назначение.
Чтобы правильно воспринимать переменную, которая назначается в некоторой точке внутри функции, как глобальную, необходимо явно указать это внутри функции, используя global cur_step
.