Get the one-line summary out of a module file.
(filename, cache={})
| 412 | return None |
| 413 | |
| 414 | def synopsis(filename, cache={}): |
| 415 | """Get the one-line summary out of a module file.""" |
| 416 | mtime = os.stat(filename).st_mtime |
| 417 | lastupdate, result = cache.get(filename, (None, None)) |
| 418 | if lastupdate is None or lastupdate < mtime: |
| 419 | # Look for binary suffixes first, falling back to source. |
| 420 | if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)): |
| 421 | loader_cls = importlib.machinery.SourcelessFileLoader |
| 422 | elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)): |
| 423 | loader_cls = importlib.machinery.ExtensionFileLoader |
| 424 | else: |
| 425 | loader_cls = None |
| 426 | # Now handle the choice. |
| 427 | if loader_cls is None: |
| 428 | # Must be a source file. |
| 429 | try: |
| 430 | file = tokenize.open(filename) |
| 431 | except OSError: |
| 432 | # module can't be opened, so skip it |
| 433 | return None |
| 434 | # text modules can be directly examined |
| 435 | with file: |
| 436 | result = source_synopsis(file) |
| 437 | else: |
| 438 | # Must be a binary module, which has to be imported. |
| 439 | loader = loader_cls('__temp__', filename) |
| 440 | # XXX We probably don't need to pass in the loader here. |
| 441 | spec = importlib.util.spec_from_file_location('__temp__', filename, |
| 442 | loader=loader) |
| 443 | try: |
| 444 | module = importlib._bootstrap._load(spec) |
| 445 | except: |
| 446 | return None |
| 447 | del sys.modules['__temp__'] |
| 448 | result = module.__doc__.splitlines()[0] if module.__doc__ else None |
| 449 | # Cache the result. |
| 450 | cache[filename] = (mtime, result) |
| 451 | return result |
| 452 | |
| 453 | class ErrorDuringImport(Exception): |
| 454 | """Errors that occurred while trying to import something to document it.""" |
nothing calls this directly
no test coverage detected