Staging
v0.5.1
https://github.com/python/cpython
Revision a3c2c5f15ba5b4ad6fb86b3320d0464f1c502fd2 authored by Miss Islington (bot) on 20 February 2020, 18:37:23 UTC, committed by GitHub on 20 February 2020, 18:37:23 UTC
(cherry picked from commit 1246d892038a693304549f8574e6c2784b91589a)

Co-authored-by: Stefan Krah <skrah@bytereef.org>

Co-authored-by: Stefan Krah <skrah@bytereef.org>
1 parent 2574910
Raw File
Tip revision: a3c2c5f15ba5b4ad6fb86b3320d0464f1c502fd2 authored by Miss Islington (bot) on 20 February 2020, 18:37:23 UTC
Use the new recommended number of repetitions in the refleak tests. (GH-18569) (#18575)
Tip revision: a3c2c5f
smelly.py
#!/usr/bin/env python
# Script checking that all symbols exported by libpython start with Py or _Py

import subprocess
import sys
import sysconfig


def get_exported_symbols():
    LIBRARY = sysconfig.get_config_var('LIBRARY')
    if not LIBRARY:
        raise Exception("failed to get LIBRARY")

    args = ('nm', '-p', LIBRARY)
    print("+ %s" % ' '.join(args))
    proc = subprocess.run(args, stdout=subprocess.PIPE, universal_newlines=True)
    if proc.returncode:
        sys.stdout.write(proc.stdout)
        sys.exit(proc.returncode)

    stdout = proc.stdout.rstrip()
    if not stdout:
        raise Exception("command output is empty")
    return stdout


def get_smelly_symbols(stdout):
    symbols = []
    ignored_symtypes = set()
    for line in stdout.splitlines():
        # Split line '0000000000001b80 D PyTextIOWrapper_Type'
        if not line:
            continue

        parts = line.split(maxsplit=2)
        if len(parts) < 3:
            continue

        symtype = parts[1].strip()
        # Ignore private symbols.
        #
        # If lowercase, the symbol is usually local; if uppercase, the symbol
        # is global (external).  There are however a few lowercase symbols that
        # are shown for special global symbols ("u", "v" and "w").
        if symtype.islower() and symtype not in "uvw":
            ignored_symtypes.add(symtype)
            continue

        symbol = parts[-1]
        if symbol.startswith(('Py', '_Py')):
            continue
        symbol = '%s (type: %s)' % (symbol, symtype)
        symbols.append(symbol)

    if ignored_symtypes:
        print("Ignored symbol types: %s" % ', '.join(sorted(ignored_symtypes)))
        print()
    return symbols


def main():
    nm_output = get_exported_symbols()
    symbols = get_smelly_symbols(nm_output)

    if not symbols:
        print("OK: no smelly symbol found")
        sys.exit(0)

    symbols.sort()
    for symbol in symbols:
        print("Smelly symbol: %s" % symbol)
    print()
    print("ERROR: Found %s smelly symbols!" % len(symbols))
    sys.exit(1)


if __name__ == "__main__":
    main()
back to top