| 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 |