diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc88817..7905ac8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -153,6 +153,7 @@ jobs: container: ubuntu:24.04 os: ubuntu-latest install: clang-18 + lint: yes - toolset: clang compiler: clang++-19 cxxstd: "11,14,17,20,2b" @@ -197,6 +198,17 @@ jobs: - uses: actions/checkout@v4 + - name: Install lint pre-reqs + if: ${{ matrix.lint == 'yes' }} + run: | + set -xe + apt-get install -y black + - name: Python formatter + if: ${{ matrix.lint == 'yes' }} + run: | + set -xe + black depinst/depinst.py + - name: Install packages if: matrix.install run: | diff --git a/depinst/depinst.py b/depinst/depinst.py index 6dfba36..bed90c4 100644 --- a/depinst/depinst.py +++ b/depinst/depinst.py @@ -18,186 +18,188 @@ verbose = 0 -def vprint( level, *args ): + +def vprint(level, *args): if verbose >= level: - print( *args ) + print(*args) -def is_module( m, gm ): +def is_module(m, gm): - return ( 'libs/' + m ) in gm + return ("libs/" + m) in gm -def module_for_header( h, x, gm ): +def module_for_header(h, x, gm): if h in x: - return x[ h ] + return x[h] else: # boost/function.hpp - m = re.match( 'boost/([^\\./]*)\\.h[a-z]*$', h ) + m = re.match("boost/([^\\./]*)\\.h[a-z]*$", h) - if m and is_module( m.group( 1 ), gm ): + if m and is_module(m.group(1), gm): - return m.group( 1 ) + return m.group(1) # boost/numeric/conversion.hpp - m = re.match( 'boost/([^/]*/[^\\./]*)\\.h[a-z]*$', h ) + m = re.match("boost/([^/]*/[^\\./]*)\\.h[a-z]*$", h) - if m and is_module( m.group( 1 ), gm ): + if m and is_module(m.group(1), gm): - return m.group( 1 ) + return m.group(1) # boost/numeric/conversion/header.hpp - m = re.match( 'boost/([^/]*/[^/]*)/', h ) + m = re.match("boost/([^/]*/[^/]*)/", h) - if m and is_module( m.group( 1 ), gm ): + if m and is_module(m.group(1), gm): - return m.group( 1 ) + return m.group(1) # boost/function/header.hpp - m = re.match( 'boost/([^/]*)/', h ) + m = re.match("boost/([^/]*)/", h) - if m and is_module( m.group( 1 ), gm ): + if m and is_module(m.group(1), gm): - return m.group( 1 ) + return m.group(1) - vprint( 0, 'Cannot determine module for header', h ) + vprint(0, "Cannot determine module for header", h) return None -def scan_header_dependencies( f, x, gm, deps ): +def scan_header_dependencies(f, x, gm, deps): for line in f: - m = re.match( '[ \t]*#[ \t]*include[ \t]*["<](boost/[^">]*)[">]', line ) + m = re.match('[ \t]*#[ \t]*include[ \t]*["<](boost/[^">]*)[">]', line) if m: - h = m.group( 1 ) + h = m.group(1) - mod = module_for_header( h, x, gm ) + mod = module_for_header(h, x, gm) if mod: if not mod in deps: - vprint( 1, 'Adding dependency', mod ) - deps[ mod ] = 0 + vprint(1, "Adding dependency", mod) + deps[mod] = 0 -def scan_directory( d, x, gm, deps ): +def scan_directory(d, x, gm, deps): - vprint( 1, 'Scanning directory', d ) + vprint(1, "Scanning directory", d) - if os.name == 'nt' and sys.version_info[0] < 3: - d = unicode( d ) + if os.name == "nt" and sys.version_info[0] < 3: + d = unicode(d) - for root, dirs, files in os.walk( d ): + for root, dirs, files in os.walk(d): for file in files: - fn = os.path.join( root, file ) + fn = os.path.join(root, file) - vprint( 2, 'Scanning file', fn ) + vprint(2, "Scanning file", fn) if sys.version_info[0] < 3: - with open( fn, 'r' ) as f: - scan_header_dependencies( f, x, gm, deps ) + with open(fn, "r") as f: + scan_header_dependencies(f, x, gm, deps) else: - with open( fn, 'r', encoding='latin-1' ) as f: - scan_header_dependencies( f, x, gm, deps ) + with open(fn, "r", encoding="latin-1") as f: + scan_header_dependencies(f, x, gm, deps) -def scan_module_dependencies( m, x, gm, deps, dirs ): +def scan_module_dependencies(m, x, gm, deps, dirs): - vprint( 1, 'Scanning module', m ) + vprint(1, "Scanning module", m) for dir in dirs: - scan_directory( os.path.join( 'libs', m, dir ), x, gm, deps ) + scan_directory(os.path.join("libs", m, dir), x, gm, deps) def read_exceptions(): # exceptions.txt is the output of "boostdep --list-exceptions" - vprint( 1, 'Reading exceptions.txt' ) + vprint(1, "Reading exceptions.txt") x = {} module = None - with open( os.path.join( os.path.dirname( sys.argv[0] ), 'exceptions.txt' ), 'r' ) as f: + with open(os.path.join(os.path.dirname(sys.argv[0]), "exceptions.txt"), "r") as f: for line in f: line = line.rstrip() - m = re.match( '(.*):$', line ) + m = re.match("(.*):$", line) if m: - module = m.group( 1 ).replace( '~', '/' ) + module = m.group(1).replace("~", "/") else: header = line.lstrip() - x[ header ] = module + x[header] = module return x def read_gitmodules(): - vprint( 1, 'Reading .gitmodules' ) + vprint(1, "Reading .gitmodules") gm = [] - with open( '.gitmodules', 'r' ) as f: + with open(".gitmodules", "r") as f: for line in f: line = line.strip() - m = re.match( 'path[ \t]*=[ \t]*(.*)$', line ) + m = re.match("path[ \t]*=[ \t]*(.*)$", line) if m: - gm.append( m.group( 1 ) ) + gm.append(m.group(1)) return gm -def install_modules( modules, git_args ): - if len( modules ) == 0: +def install_modules(modules, git_args): + + if len(modules) == 0: return - vprint( 0, 'Installing:', ', '.join(modules) ) + vprint(0, "Installing:", ", ".join(modules)) - modules = [ 'libs/' + m for m in modules ] + modules = ["libs/" + m for m in modules] - command = 'git submodule' + command = "git submodule" if verbose <= 0: - command += ' -q' + command += " -q" - command += ' update --init ' + git_args + ' ' + ' '.join( modules ) + command += " update --init " + git_args + " " + " ".join(modules) - vprint( 1, 'Executing:', command ) - r = os.system( command ); + vprint(1, "Executing:", command) + r = os.system(command) if r != 0: - raise Exception( "The command '%s' failed with exit code %d" % (command, r) ) + raise Exception("The command '%s' failed with exit code %d" % (command, r)) -def install_module_dependencies( deps, x, gm, git_args ): +def install_module_dependencies(deps, x, gm, git_args): modules = [] @@ -205,78 +207,121 @@ def install_module_dependencies( deps, x, gm, git_args ): if not i: - modules += [ m ] - deps[ m ] = 1 # mark as installed + modules += [m] + deps[m] = 1 # mark as installed - if len( modules ) == 0: + if len(modules) == 0: return 0 - install_modules( modules, git_args ) + install_modules(modules, git_args) for m in modules: - scan_module_dependencies( m, x, gm, deps, [ 'include', 'src' ] ) - - return len( modules ) - - -if( __name__ == "__main__" ): - - parser = argparse.ArgumentParser( description='Installs the dependencies needed to test a Boost library.' ) - - parser.add_argument( '-v', '--verbose', help='enable verbose output', action='count', default=0 ) - parser.add_argument( '-q', '--quiet', help='quiet output (opposite of -v)', action='count', default=0 ) - parser.add_argument( '-X', '--exclude', help="exclude a default subdirectory ('include', 'src', or 'test') from scan; can be repeated", metavar='DIR', action='append', default=[] ) - parser.add_argument( '-N', '--ignore', help="exclude top-level dependency even when found in scan; can be repeated", metavar='LIB', action='append', default=[] ) - parser.add_argument( '-I', '--include', help="additional subdirectory to scan; can be repeated", metavar='DIR', action='append', default=[] ) - parser.add_argument( '-g', '--git_args', help="additional arguments to `git submodule update`", default='', action='store' ) - parser.add_argument( '-u', '--update', help='update before scanning', action='store_true' ) - parser.add_argument( 'library', help="name of library to scan ('libs/' will be prepended)" ) + scan_module_dependencies(m, x, gm, deps, ["include", "src"]) + + return len(modules) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser( + description="Installs the dependencies needed to test a Boost library." + ) + + parser.add_argument( + "-v", "--verbose", help="enable verbose output", action="count", default=0 + ) + parser.add_argument( + "-q", "--quiet", help="quiet output (opposite of -v)", action="count", default=0 + ) + parser.add_argument( + "-X", + "--exclude", + help="exclude a default subdirectory ('include', 'src', or 'test') from scan; can be repeated", + metavar="DIR", + action="append", + default=[], + ) + parser.add_argument( + "-N", + "--ignore", + help="exclude top-level dependency even when found in scan; can be repeated", + metavar="LIB", + action="append", + default=[], + ) + parser.add_argument( + "-I", + "--include", + help="additional subdirectory to scan; can be repeated", + metavar="DIR", + action="append", + default=[], + ) + parser.add_argument( + "-g", + "--git_args", + help="additional arguments to `git submodule update`", + default="", + action="store", + ) + parser.add_argument( + "-u", "--update", help="update before scanning", action="store_true" + ) + parser.add_argument( + "library", help="name of library to scan ('libs/' will be prepended)" + ) args = parser.parse_args() verbose = args.verbose - args.quiet - vprint( 2, '-X:', args.exclude ) - vprint( 2, '-I:', args.include ) - vprint( 2, '-N:', args.ignore ) + vprint(2, "-X:", args.exclude) + vprint(2, "-I:", args.include) + vprint(2, "-N:", args.ignore) x = read_exceptions() - vprint( 2, 'Exceptions:', x ) + vprint(2, "Exceptions:", x) gm = read_gitmodules() - vprint( 2, '.gitmodules:', gm ) + vprint(2, ".gitmodules:", gm) - essentials = [ 'config', 'headers', '../tools/boost_install', '../tools/build', '../tools/cmake' ] + essentials = [ + "config", + "headers", + "../tools/boost_install", + "../tools/build", + "../tools/cmake", + ] - essentials = [ e for e in essentials if os.path.exists( 'libs/' + e ) ] + essentials = [e for e in essentials if os.path.exists("libs/" + e)] if args.update: - essentials.append( args.library ) + essentials.append(args.library) - install_modules( essentials, args.git_args ) + install_modules(essentials, args.git_args) m = args.library - deps = { m : 1 } + deps = {m: 1} - dirs = [ 'include', 'src', 'test' ] + dirs = ["include", "src", "test"] for dir in args.exclude: - dirs.remove( dir ) + dirs.remove(dir) for dir in args.include: - dirs.append( dir ) + dirs.append(dir) - vprint( 1, 'Directories to scan:', *dirs ) + vprint(1, "Directories to scan:", *dirs) - scan_module_dependencies( m, x, gm, deps, dirs ) + scan_module_dependencies(m, x, gm, deps, dirs) for dep in args.ignore: if dep in deps: - vprint( 1, 'Ignoring dependency', dep ) + vprint(1, "Ignoring dependency", dep) del deps[dep] - vprint( 2, 'Dependencies:', deps ) + vprint(2, "Dependencies:", deps) - while install_module_dependencies( deps, x, gm, args.git_args ): + while install_module_dependencies(deps, x, gm, args.git_args): pass