diff options
Diffstat (limited to 'verhawk')
| -rw-r--r-- | verhawk/__init__.py | 3 | ||||
| -rw-r--r-- | verhawk/cli/__init__.py | 0 | ||||
| -rw-r--r-- | verhawk/cli/verhawk.py | 61 | ||||
| -rw-r--r-- | verhawk/constants.py | 4 | ||||
| -rw-r--r-- | verhawk/scanner.py | 81 | 
5 files changed, 149 insertions, 0 deletions
diff --git a/verhawk/__init__.py b/verhawk/__init__.py new file mode 100644 index 0000000..30eb98f --- /dev/null +++ b/verhawk/__init__.py @@ -0,0 +1,3 @@ +from . import scanner +from .version import * + diff --git a/verhawk/cli/__init__.py b/verhawk/cli/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/verhawk/cli/__init__.py diff --git a/verhawk/cli/verhawk.py b/verhawk/cli/verhawk.py new file mode 100644 index 0000000..bf69dab --- /dev/null +++ b/verhawk/cli/verhawk.py @@ -0,0 +1,61 @@ +import argparse +import importlib +import os +import sys +import verhawk.scanner +import verhawk.constants as constants + + +def main(): +    parser = argparse.ArgumentParser() +    parser.add_argument('parent_package') +    parser.add_argument('-V', '--version', +        action='store_true', +        help='Display version information'), +    parser.add_argument('-e', '--exclude', +        action='append', +        default=[], +        help='Ignore sub-[package|module] by name.') +    parser.add_argument('-v', '--verbose', +        action='store_true', +        help='Show packages without version data.') +    parser.add_argument('-j', '--json', +        action='store_true', +        help='Emit JSON to stdout') +    parser.add_argument('-p', '--packages-only', +        action='store_true', +        help='Ignore non-packages (i.e modules)') +    parser.add_argument('-r', '--recursive', +        action='store_true', +        help='Descend into package looking for additional version data.') + +    args = parser.parse_args() + +    if args.version: +        print(verhawk.version.__version_long__) +        exit(0) + +    try: +        with open(os.devnull, 'w') as devnull: +            sys.stdout = devnull +            parent_package = importlib.import_module(args.parent_package) + +        sys.stdout = constants.STDOUT +    except ImportError as e: +        print(e, file=sys.stderr) +        exit(1) + +    scanner = verhawk.scanner.Scanner(parent_package, args.exclude, +                                     args.recursive, args.packages_only) + +    if args.json: +        print(scanner.as_json()) +    else: +        for pkg, version in sorted(scanner): +            if not args.verbose and version is None: +                continue + +            print('{0}={1}'.format(pkg, version)) + +if __name__ == '__main__': +    main() diff --git a/verhawk/constants.py b/verhawk/constants.py new file mode 100644 index 0000000..f9dff6c --- /dev/null +++ b/verhawk/constants.py @@ -0,0 +1,4 @@ +import sys + + +STDERR, STDOUT = sys.stderr, sys.stdout diff --git a/verhawk/scanner.py b/verhawk/scanner.py new file mode 100644 index 0000000..41b6ecd --- /dev/null +++ b/verhawk/scanner.py @@ -0,0 +1,81 @@ +from __future__ import print_function +import json +import os +import pkgutil +import sys +from . import constants + + +class Scanner(object): +    def __init__(self, package, exclusions=[], recursive=False, packages_only=False): +        self.package = package +        self.prefix = self.package.__name__ + '.' +        self.exclusions = exclusions +        self.versions = dict() +        self.recursive = recursive +        self.packages_only = packages_only +        self.scan() + +    def __iter__(self): +        for k, v in self.versions.items(): +            yield k, v + +    def scan(self): +        try: +            module = self.package +            modname = module.__name__ + +            try: +                self.versions[modname] = module.__version__ or module.version or module._version +            except AttributeError: +                self.versions[modname] = None +        except ImportError as e: +            print('ImportError({0}): {1}'.format(modname, e), file=sys.stderr) + +        if self.recursive: +            try: +                for importer, modname, ispkg in pkgutil.iter_modules(self.package.__path__, self.prefix): +                    excluded = False +                    for ex in self.exclusions: +                        ex = self.prefix + ex +                        if modname == ex: +                            excluded = True +                            break + +                    if excluded: +                        continue + +                    if self.packages_only and not ispkg: +                        continue + +                    try: +                        module = None +                        with open(os.devnull, 'w') as devnull: +                            sys.stdout = devnull +                            module = importer.find_module(modname).load_module(modname) + +                        sys.stdout = constants.STDOUT + +                        try: +                            self.versions[modname] = module.__version__ or module.version or module._version +                        except AttributeError: +                            self.versions[modname] = None + +                    except ImportError as e: +                        print('ImportError({0}): {1}'.format(modname, e), file=sys.stderr) + +            except AttributeError: +                # has no sub-packages or sub-modules, so ignore +                pass +            except TypeError: +                # has strange requirements at import-time, so ignore +                pass + +    def as_json(self): +        return json.dumps(self.versions, sort_keys=True) + + +    def as_zip(self): +        return zip(self.versions.keys(), self.versions.values()) + +  | 
