pyodbc uses '?' instead of '%s' as parameter placeholder.
SQL identifiers (consequently table names, columns) can contain special characters if surrounded by brackets '[...]'
Replace only those placeholders:'%, %%, %s, %d etc.' which are not surrounded by brackets.
This is not complete solution, there may be problems with string literals in SQL etc. , if non string placeholder is found (example:%d) there should be error raised.
pyodbc uses '?' instead of '%s' as parameter placeholder. SQL identifiers (consequently table names, columns) can contain special characters if surrounded by brackets '[...]' Replace only those placeholders:'%, %%, %s, %d etc.' which are not surrounded by brackets.
This is not complete solution, there may be problems with string literals in SQL etc. , if non string placeholder is found (example:%d) there should be error raised.
Test: input:
''', test,%ss, [Company$Item].[Percentile %], [Company$Item],%s, [bfbfdb%vbddfb], %, %% [[%]], [%'''
result:''', test,?s, [Company$Item].[Percentile %], [Company$Item],?, [bfbfdb%vbddfb], ?, ? [[%]], [%'''