bpo-36876: Fix the C analyzer tool. (GH-22841)

The original tool wasn't working right and it was simpler to create a new one, partially re-using some of the old code. At this point the tool runs properly on the master. (Try: ./python Tools/c-analyzer/c-analyzer.py analyze.)  It take ~40 seconds on my machine to analyze the full CPython code base.

Note that we'll need to iron out some OS-specific stuff (e.g. preprocessor). We're okay though since this tool isn't used yet in our workflow. We will also need to verify the analysis results in detail before activating the check in CI, though I'm pretty sure it's close.

https://bugs.python.org/issue36876
This commit is contained in:
Eric Snow 2020-10-22 18:42:51 -06:00 committed by GitHub
parent ec388cfb4e
commit 345cd37abe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 8868 additions and 10539 deletions

View file

@ -0,0 +1,64 @@
import contextlib
import os.path
def resolve(source, filename):
if _looks_like_filename(source):
return _resolve_filename(source, filename)
if isinstance(source, str):
source = source.splitlines()
# At this point "source" is not a str.
if not filename:
filename = None
elif not isinstance(filename, str):
raise TypeError(f'filename should be str (or None), got {filename!r}')
else:
filename, _ = _resolve_filename(filename)
return source, filename
@contextlib.contextmanager
def good_file(filename, alt=None):
if not _looks_like_filename(filename):
raise ValueError(f'expected a filename, got {filename}')
filename, _ = _resolve_filename(filename, alt)
try:
yield filename
except Exception:
if not os.path.exists(filename):
raise FileNotFoundError(f'file not found: {filename}')
raise # re-raise
def _looks_like_filename(value):
if not isinstance(value, str):
return False
return value.endswith(('.c', '.h'))
def _resolve_filename(filename, alt=None):
if os.path.isabs(filename):
...
# raise NotImplementedError
else:
filename = os.path.join('.', filename)
if not alt:
alt = filename
elif os.path.abspath(filename) == os.path.abspath(alt):
alt = filename
else:
raise ValueError(f'mismatch: {filename} != {alt}')
return filename, alt
@contextlib.contextmanager
def opened(source, filename=None):
source, filename = resolve(source, filename)
if isinstance(source, str):
with open(source) as srcfile:
yield srcfile, filename
else:
yield source, filename