mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00

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
64 lines
1.7 KiB
Python
64 lines
1.7 KiB
Python
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
|