pschanely / CrossHair

An analysis tool for Python that blurs the line between testing and type systems.
Other
1.03k stars 49 forks source link

SideEffect detection too strict ? #163

Closed PiotrZakrzewski closed 2 years ago

PiotrZakrzewski commented 2 years ago

Is your feature request related to a problem? Please describe. I would like to use Crosshair with bigger more complex code-bases which import variety of modules, including those marked as having side effects. e.g. uuid from stdlib following file

import uuid

def fun(a:int) -> int:
    return a + 1

when checked with crosshair check returns

  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/site-packages/crosshair/auditwall.py", line 32, in reject
    raise SideEffectDetected(
crosshair.auditwall.SideEffectDetected: A "subprocess.Popen" operation was detected. CrossHair should not be run on code with side effects

Describe the solution you'd like Allow to disable the audit check with a flag? Provide some way to mock out the side-effects?

pschanely commented 2 years ago

Oh golly, yes, uuid should certainly be usable. Thank you for the report!

I suspect this is platform or environment dependent (it doesn't immediately reproduce on my mac). Can you tell me a little more about your setup? Is there anything more in the stack trace?

Stuff like this happens often enough that a command line flag might not be a bad idea (though perhaps then fewer people will tell me when it's not working?!)

PiotrZakrzewski commented 2 years ago

full traceback

▶ crosshair check cross_test.py 
Could not import your code:

Traceback (most recent call last):
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/site-packages/crosshair/util.py", line 374, in load_file
    return import_module(module_name)
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/site-packages/crosshair/util.py", line 342, in import_module
    result_module = importlib.import_module(module_name)
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 843, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/tmp/cross_test.py", line 1, in <module>
    import uuid
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/uuid.py", line 60, in <module>
    _platform_system = platform.system()
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/platform.py", line 892, in system
    return uname().system
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/platform.py", line 858, in uname
    processor = _syscmd_uname('-p', '')
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/platform.py", line 614, in _syscmd_uname
    output = subprocess.check_output(('uname', option),
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/subprocess.py", line 415, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/subprocess.py", line 493, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/subprocess.py", line 858, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/subprocess.py", line 1582, in _execute_child
    sys.audit("subprocess.Popen", executable, args, cwd, env)
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/site-packages/crosshair/auditwall.py", line 110, in audithook
    handler(event, args)
  File "/home/piotrzakrzewski/.pyenv/versions/3.8.11/lib/python3.8/site-packages/crosshair/auditwall.py", line 32, in reject
    raise SideEffectDetected(
crosshair.auditwall.SideEffectDetected: A "subprocess.Popen" operation was detected. CrossHair should not be run on code with side effects

PoP OS (equivalent to Ubuntu 18.04) 18.04 Python 3.8.11

pschanely commented 2 years ago

Thanks! I've just merged a fix in 0a9df84b3889f5d7ac9f5cd32a412478ff74fe31 and published v0.0.24 including it! In addition to this case, I covered the standard library modules I could easily find that might try to (safely) Popen. Hopefully it covers your exact case, as I could only locally confirm with ~similar cases. Kindly re-open if it doesn't work for you!

I should have also mentioned that it is indeed possible to mock out side effects via a plugin (docs; example for the random module). Not an ideal solution though, and I certainly want to make the standard library work reasonably well out-of-the-box.

Finally, I hope to hear how it goes in gitter chat, more issues, or more general feedback in discussions. I know that filing github issues is "real work", but it's critically important to the project. Thank you for helping!