[poky] [PATCH] bbvars.py: add a script to look for undocumented variables

Saul Wold saul.wold at intel.com
Wed Jan 12 21:52:19 PST 2011


On 01/11/2011 03:38 PM, Darren Hart wrote:
> bbvars.py will compare recipes in meta directories with documentation files
> and report on variables that don't appear to be documented. It reports the
> number of times a variable is used as well as any doctags present in the
> documentation config file.
>
> The output of this is intended to aid in determining where documentation may
> be lacking, but it is not perfect, and does generate some false positives. An
> experienced eye and careful attention to count and doctag should be applied to
> the results.
>
> $ ./bbvars.py -d ../../documentation/poky-ref-manual/poky-ref-manual.html -m ../../meta -t ../../meta/conf/documentation.conf -T  | head -n 10
> Found 1413 undocumented bb variables (out of 1578):
> VARIABLE                              COUNT DOCTAG
> ===================================================
> BUILD_ARCH                            4     The name of the building architecture. E.g. i686.
> BUILD_CC_ARCH                         2     FIXME
> BUILD_PREFIX                          4     FIXME
> BUILD_SYS                             13    FIXME
> BUILD_VENDOR                          2     FIXME
> CACHE                                 1     The directory holding the cache of the metadata.
> COMPATIBLE_HOST                       19    A regular expression which matches the HOST_SYS names supported by the package/file. Failure to match will cause the file to be skipped by the parser.
>
> Pull URL: git://git.pokylinux.org/poky-contrib.git
>    Branch: dvhart/scripts
>    Browse: http://git.pokylinux.org/cgit.cgi/poky-contrib/log/?h=dvhart/scripts
>
> Signed-off-by: Darren Hart<dvhart at linux.intel.com>
> CC: Richard Purdie<richard.purdie at linuxfoundation.org>
> ---
>   scripts/contrib/bbvars.py |  186 +++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 186 insertions(+), 0 deletions(-)
>   create mode 100755 scripts/contrib/bbvars.py
>
> diff --git a/scripts/contrib/bbvars.py b/scripts/contrib/bbvars.py
> new file mode 100755
> index 0000000..0896d64
> --- /dev/null
> +++ b/scripts/contrib/bbvars.py
> @@ -0,0 +1,186 @@
> +#!/usr/bin/env python
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 2 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +#
> +# Copyright (C) Darren Hart<dvhart at linux.intel.com>, 2010
> +
> +
> +import sys
> +import getopt
> +import os
> +import os.path
> +import re
> +
> +def usage():
> +    print 'Usage: %s -d FILENAME [-d FILENAME]* -m METADIR [-m MATADIR]*' % os.path.basename(sys.argv[0])
> +    print '  -d FILENAME         documentation file to search'
> +    print '  -h, --help          display this help and exit'
> +    print '  -m METADIR          meta directory to search for recipes'
> +    print '  -t FILENAME         documentation config file (for doc tags)'
> +    print '  -T                  Only display variables with doc tags (requires -t)'
> +
> +def recipe_bbvars(recipe):
> +    ''' Return a unique set of every bbvar encountered in the recipe '''
> +    prog = re.compile("[A-Z_]+")
> +    vset = set()
> +    try:
> +        r = open(recipe)
> +    except IOError as (errno, strerror):
> +        print 'WARNING: Failed to open recipe ', recipe
> +        print strerror
> +
> +    for line in r:
> +        # Strip any comments from the line
> +        line = line.rsplit('#')[0]
> +        vset = vset.union(set(prog.findall(line)))
> +    r.close()
> +
> +    bbvars = {}
> +    for v in vset:
> +        bbvars[v] = 1
> +
> +    return bbvars
> +
> +def collect_bbvars(metadir):
> +    ''' Walk the metadir and collect the bbvars from each recipe found '''
> +    bbvars = {}
> +    for root,dirs,files in os.walk(metadir):
> +        for name in files:
> +            if name.find(".bb")>= 0:
> +                for key in recipe_bbvars(os.path.join(root,name)).iterkeys():
> +                    if bbvars.has_key(key):
> +                        bbvars[key] = bbvars[key] + 1
> +                    else:
> +                        bbvars[key] = 1
> +    return bbvars
> +
> +def bbvar_is_documented(var, docfiles):
> +    prog = re.compile(".*($|[^A-Z_])%s([^A-Z_]|$)" % (var))
> +    for doc in docfiles:
> +        try:
> +            f = open(doc)
> +        except IOError as (errno, strerror):
> +            print 'WARNING: Failed to open doc ', doc
> +            print strerror
> +        for line in f:
> +            if prog.match(line):
> +                return True
> +        f.close()
> +    return False
> +
> +def bbvar_doctag(var, docconf):
> +    prog = re.compile('^%s\[doc\] *= *"(.*)"' % (var))
> +    if docconf == "":
> +        return "?"
> +
> +    try:
> +        f = open(docconf)
> +    except IOError as (errno, strerror):
> +        return strerror
> +
> +    for line in f:
> +        m = prog.search(line)
> +        if m:
> +            return m.group(1)
> +
> +    f.close()
> +    return ""
> +
> +def main():
> +    docfiles = []
> +    metadirs = []
> +    bbvars = {}
> +    undocumented = []
> +    docconf = ""
> +    onlydoctags = False
> +
> +    # Collect and validate input
> +    try:
> +        opts, args = getopt.getopt(sys.argv[1:], "d:hm:t:T", ["help"])
> +    except getopt.GetoptError, err:
> +        print '%s' % str(err)
> +        usage()
> +        sys.exit(2)
> +
> +    for o, a in opts:
> +        if o in ('-h', '--help'):
> +            usage()
> +            sys.exit(0)
> +        elif o == '-d':
> +            if os.path.isfile(a):
> +                docfiles.append(a)
> +            else:
> +                print 'ERROR: documentation file %s is not a regular file' % (a)
> +                sys.exit(3)
> +        elif o == '-m':
> +            if os.path.isdir(a):
> +                metadirs.append(a)
> +            else:
> +                print 'ERROR: meta directory %s is not a directory' % (a)
> +                sys.exit(4)
> +        elif o == "-t":
> +            if os.path.isfile(a):
> +                docconf = a
> +        elif o == "-T":
> +            onlydoctags = True
> +        else:
> +            assert False, "unhandled option"
> +
> +    if len(docfiles) == 0:
> +        print 'ERROR: no docfile specified'
> +        usage()
> +        sys.exit(5)
> +
> +    if len(metadirs) == 0:
> +        print 'ERROR: no metadir specified'
> +        usage()
> +        sys.exit(6)
> +
> +    if onlydoctags and docconf == "":
> +        print 'ERROR: no docconf specified'
> +        usage()
> +        sys.exit(7)
> +
> +    # Collect all the variable names from the recipes in the metadirs
> +    for m in metadirs:
> +        for key,cnt in collect_bbvars(m).iteritems():
> +            if bbvars.has_key(key):
> +                bbvars[key] = bbvars[key] + cnt
> +            else:
> +                bbvars[key] = cnt
> +
> +    # Check each var for documentation
> +    varlen = 0
> +    for v in bbvars.iterkeys():
> +        if len(v)>  varlen:
> +            varlen = len(v)
> +        if not bbvar_is_documented(v, docfiles):
> +            undocumented.append(v)
> +    undocumented.sort()
> +    varlen = varlen + 1
> +
> +    # Report all undocumented variables
> +    print 'Found %d undocumented bb variables (out of %d):' % (len(undocumented), len(bbvars))
> +    header = '%s%s%s' % (str("VARIABLE").ljust(varlen), str("COUNT").ljust(6), str("DOCTAG").ljust(7))
> +    print header
> +    print str("").ljust(len(header), '=')
> +    for v in undocumented:
> +        doctag = bbvar_doctag(v, docconf)
> +        if not onlydoctags or not doctag == "":
> +            print '%s%s%s' % (v.ljust(varlen), str(bbvars[v]).ljust(6), doctag)
> +
> +
> +if __name__ == "__main__":
> +    main()
Pulled into Master

Thanks
	Sau!




More information about the poky mailing list