Get the one-line summary out of a module file.
(filename, cache={})
| 347 | return None |
| 348 | |
| 349 | def synopsis(filename, cache={}): |
| 350 | """Get the one-line summary out of a module file.""" |
| 351 | mtime = os.stat(filename).st_mtime |
| 352 | lastupdate, result = cache.get(filename, (None, None)) |
| 353 | if lastupdate is None or lastupdate < mtime: |
| 354 | # Look for binary suffixes first, falling back to source. |
| 355 | if filename.endswith(tuple(importlib.machinery.BYTECODE_SUFFIXES)): |
| 356 | loader_cls = importlib.machinery.SourcelessFileLoader |
| 357 | elif filename.endswith(tuple(importlib.machinery.EXTENSION_SUFFIXES)): |
| 358 | loader_cls = importlib.machinery.ExtensionFileLoader |
| 359 | else: |
| 360 | loader_cls = None |
| 361 | # Now handle the choice. |
| 362 | if loader_cls is None: |
| 363 | # Must be a source file. |
| 364 | try: |
| 365 | file = tokenize.open(filename) |
| 366 | except OSError: |
| 367 | # module can't be opened, so skip it |
| 368 | return None |
| 369 | # text modules can be directly examined |
| 370 | with file: |
| 371 | result = source_synopsis(file) |
| 372 | else: |
| 373 | # Must be a binary module, which has to be imported. |
| 374 | loader = loader_cls('__temp__', filename) |
| 375 | # XXX We probably don't need to pass in the loader here. |
| 376 | spec = importlib.util.spec_from_file_location('__temp__', filename, |
| 377 | loader=loader) |
| 378 | try: |
| 379 | module = importlib._bootstrap._load(spec) |
| 380 | except: |
| 381 | return None |
| 382 | del sys.modules['__temp__'] |
| 383 | result = module.__doc__.splitlines()[0] if module.__doc__ else None |
| 384 | # Cache the result. |
| 385 | cache[filename] = (mtime, result) |
| 386 | return result |
| 387 | |
| 388 | class ErrorDuringImport(Exception): |
| 389 | """Errors that occurred while trying to import something to document it.""" |
nothing calls this directly
no test coverage detected
searching dependent graphs…