From 597b1d6e39039066ce51e4c02d74ed6545ffccdf Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Mon, 8 Aug 2016 16:03:02 -0400 Subject: Refactor into a package; Add RELIC 1.0.5 --- .gitignore | 6 +++ .gitmodules | 3 ++ LICENSE.txt | 22 ++++++++ MANIFEST.in | 1 + README.md | 0 relic | 1 + setup.py | 32 ++++++++++++ verhawk/__init__.py | 3 ++ verhawk/cli/__init__.py | 0 verhawk/cli/verhawk.py | 61 ++++++++++++++++++++++ verhawk/constants.py | 4 ++ verhawk/scanner.py | 81 +++++++++++++++++++++++++++++ versionscanner.py | 132 ------------------------------------------------ 13 files changed, 214 insertions(+), 132 deletions(-) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 LICENSE.txt create mode 100644 MANIFEST.in create mode 100644 README.md create mode 160000 relic create mode 100644 setup.py create mode 100644 verhawk/__init__.py create mode 100644 verhawk/cli/__init__.py create mode 100644 verhawk/cli/verhawk.py create mode 100644 verhawk/constants.py create mode 100644 verhawk/scanner.py delete mode 100755 versionscanner.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f520061 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +RELIC-INFO +*/version.py +build/ +dist/ +*.EGG-INFO +__pycache__ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6d623ae --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "relic"] + path = relic + url = https://github.com/jhunkeler/relic.git diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..49de2ea --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2016, AURA +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..db2348e --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include RELIC-INFO diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/relic b/relic new file mode 160000 index 0000000..68d21ce --- /dev/null +++ b/relic @@ -0,0 +1 @@ +Subproject commit 68d21cefd75c5fadb19ad6e4515a49208fac49d0 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..f791f1c --- /dev/null +++ b/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup, find_packages +import sys +sys.path.insert(1, 'relic') + +import relic.release + +NAME = 'verhawk' +version = relic.release.get_info() +relic.release.write_template(version, NAME) + +setup( + name=NAME, + version=version.pep386, + author='Joseph Hunkeler', + author_email='jhunk@stsci.edu', + description='Extract version data from Python [sub]packages/modules', + url='https://github.com/spacetelescope/verhawk', + license='BSD', + classifiers = [ + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules', + ], + packages=find_packages(), + package_data={'': ['README.md', 'LICENSE.txt']}, + entry_points={ + 'console_scripts': [ + 'verhawk = verhawk.cli.verhawk:main' + ] + }, +) 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 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()) + + diff --git a/versionscanner.py b/versionscanner.py deleted file mode 100755 index 404c14a..0000000 --- a/versionscanner.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function -import json -import os -import pkgutil -import sys - - -STDERR, STDOUT = sys.stderr, sys.stdout - - -class VersionScanner(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 = 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()) - - -if __name__ == '__main__': - import argparse - import importlib - - - parser = argparse.ArgumentParser() - parser.add_argument('parent_package') - 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() - - try: - with open(os.devnull, 'w') as devnull: - sys.stdout = devnull - parent_package = importlib.import_module(args.parent_package) - - sys.stdout = STDOUT - except ImportError as e: - print(e, file=sys.stderr) - exit(1) - - scanner = VersionScanner(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)) - -- cgit