modern annotation
We used to have to do this:
from typing import List
But in a modern interpreter like 3.11 we prefer to just say
def main(args: list[str]) -> int:
(Note the lowercase "l".)
Anyway, thank you for the helpful annotations.
cracking argv
You're doing it the hard way.
if argc != 2 and argc != 3:
Recommend you let typer
sweat the details for you.
Plus, it will offer --help to the hapless shell user.
stat()
result = subprocess.run(f"stat {args[1]} --printf=%s", shell=True, capture_output=True)
You're definitely doing it the hard way.
First, use Path:
from pathlib import Path
...
file = Path(args[1])
Now you're set up to ask questions like whether file.exists().
And most importantly, you can assign
size = file.stat().st_size
ULP
It's not obvious to me that this always triggers when you want it to:
elif delta == 100:
We did a FP divide, and a multiply to obtain that.
Oh, wait!
Not just any divide -- we only care about equality, and unity, FTW.
Yes, this triggers when you want it to.
I was going to suggest elif old == new:, but this computes the same thing.
However, in general, after certain FP operations such as divide,
plan on obtaining a result which is \$\pm \epsilon\$
from what you thought you should be getting.
So you might phrase it elif abs(delta - 100) < epsilon:,
for some small \$\epsilon\$, maybe 1e-9.
Or as @Greedo observes, better still to use isclose(), which defaults to (approximately) defaults to that setting. The relative tolerance is usually what makes the most sense.
docstring
return 0
return 3
The four different statuses are very nice.
But please give main() a """docstring"""
which mentions what they mean.