Calmcode - ruff: unsafe fixes

Unsafe Fixes

1 2 3 4 5

Let's have a look at our script again.

def fibonachi(s1, s2, n):
    result = [s1 , s2]
    for i in range(n):
        s1, s2 = s2, s1 + s2
        result.append(s2)
    return result 

if __name__ == "__main__":
    print(fibonachi(1, 1, 10))

For good measure, this is our ruff config:

[lint]
select = ["ALL"]
ignore = ["D211", "D213"]

Now when we run ruff ...

ruff check script.py

... we see that ruff is able to try and make a fix, but requires setting an extra --unsafe-fixes flag. Notice this last line in the output:

[*] 1 fixable with the `--fix` option (2 hidden fixes can be enabled with the `--unsafe-fixes` option).

Before we saw that ruff was able to make an easy fix without any problem. But that involved removing a line that was importing a library that wasn't being used. That's an easy thing to fix because there are no consequences. In this case though, there is a subtle consequence.

Docs again

Once again it can be great to check in on the Ruff documentation pages, pages like this one give a very clear overview of why a rule exists and also how it might reason about introducing a fix. Even if it is a potentially unsafe one.

Making the fix

Let's see what ruff does when we allow it to make an unsafe fix in this case.

ruff check --fix --unsafe-fixes demo.py

Here's what the demo.py file will look like now:

def fibonachi(s1, s2, n):
    result = [s1 , s2]
    for _i in range(n):
        s1, s2 = s2, s1 + s2
        result.append(s2)
    return result

if __name__ == "__main__":
    pass

In this case the i variable in the for loop got turned into _i. That doesn't cause any harm in this case, but it could if the script was a little bit different. The same could be said about removing the print statement.

You may be fine 99% of the time if you run --unsafe-fixes, but that 1% of the time can cause a subtle bug that generates a ton of headackes.