Skip to content

Commit

Permalink
Add Python 3.9 to the build matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
jacebrowning committed Nov 17, 2020
1 parent be8c72e commit 7ab00d4
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 47 deletions.
2 changes: 2 additions & 0 deletions .appveyor.yml
Expand Up @@ -6,6 +6,8 @@ environment:
PYTHON_MINOR: 7
- PYTHON_MAJOR: 3
PYTHON_MINOR: 8
- PYTHON_MAJOR: 3
PYTHON_MINOR: 9

cache:
- .venv -> poetry.lock
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -4,6 +4,7 @@ language: python
python:
- 3.7
- 3.8
- 3.9

cache:
pip: true
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -51,7 +51,7 @@ $(DEPENDENCIES): poetry.lock

ifndef CI
poetry.lock: pyproject.toml
poetry lock
poetry lock --no-update
@ touch $@
endif

Expand Down
135 changes: 89 additions & 46 deletions bin/verchew
Expand Up @@ -38,27 +38,28 @@ from collections import OrderedDict
from subprocess import PIPE, STDOUT, Popen


try:
import configparser # Python 3
except ImportError:
import ConfigParser as configparser # Python 2
PY2 = sys.version_info[0] == 2

__version__ = '1.6.2'
if PY2:
import ConfigParser as configparser
from urllib import urlretrieve
else:
import configparser
from urllib.request import urlretrieve

PY2 = sys.version_info[0] == 2
__version__ = '3.1.1'

SCRIPT_URL = (
"https://raw.githubusercontent.com/jacebrowning/verchew/main/verchew/script.py"
)

CONFIG_FILENAMES = [
'verchew.ini',
'.verchew.ini',
'.verchewrc',
'.verchew',
]
CONFIG_FILENAMES = ['verchew.ini', '.verchew.ini', '.verchewrc', '.verchew']

SAMPLE_CONFIG = """
[Python]
cli = python
versions = Python 3.5 | Python 3.6
version = Python 3.5 || Python 3.6
[Legacy Python]
Expand All @@ -81,16 +82,16 @@ optional = true

STYLE = {
"~": "✔",
"*": "⭑",
"?": "⚠",
"?": "▴",
"x": "✘",
"#": "䷉",
}

COLOR = {
"x": "\033[91m", # red
"~": "\033[92m", # green
"?": "\033[93m", # yellow
"*": "\033[94m", # cyan
"x": "\033[91m", # red
"#": "\033[96m", # cyan
None: "\033[0m", # reset
}

Expand All @@ -110,6 +111,10 @@ def main():
log.debug("PWD: %s", os.getenv('PWD'))
log.debug("PATH: %s", os.getenv('PATH'))

if args.vendor:
vendor_script(args.vendor)
sys.exit(0)

path = find_config(args.root, generate=args.init)
config = parse_config(path)

Expand All @@ -118,22 +123,37 @@ def main():


def parse_args():
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(description="System dependency version checker.",)

version = "%(prog)s v" + __version__
parser.add_argument('--version', action='version', version=version)
parser.add_argument('-r', '--root', metavar='PATH',
help="specify a custom project root directory")
parser.add_argument('--init', action='store_true',
help="generate a sample configuration file")
parser.add_argument('--exit-code', action='store_true',
help="return a non-zero exit code on failure")

group = parser.add_mutually_exclusive_group()
group.add_argument('-v', '--verbose', action='count', default=0,
help="enable verbose logging")
group.add_argument('-q', '--quiet', action='store_true',
help="suppress all output on success")
parser.add_argument(
'--version', action='version', version=version,
)
parser.add_argument(
'-r', '--root', metavar='PATH', help="specify a custom project root directory"
)
parser.add_argument(
'--exit-code',
action='store_true',
help="return a non-zero exit code on failure",
)

group_logging = parser.add_mutually_exclusive_group()
group_logging.add_argument(
'-v', '--verbose', action='count', default=0, help="enable verbose logging"
)
group_logging.add_argument(
'-q', '--quiet', action='store_true', help="suppress all output on success"
)

group_commands = parser.add_argument_group('commands')
group_commands.add_argument(
'--init', action='store_true', help="generate a sample configuration file"
)

group_commands.add_argument(
'--vendor', metavar='PATH', help="download the program for offline use"
)

args = parser.parse_args()

Expand All @@ -151,6 +171,20 @@ def configure_logging(count=0):
logging.basicConfig(level=level, format="%(levelname)s: %(message)s")


def vendor_script(path):
root = os.path.abspath(os.path.join(path, os.pardir))
if not os.path.isdir(root):
log.info("Creating directory %s", root)
os.makedirs(root)

log.info("Downloading %s to %s", SCRIPT_URL, path)
urlretrieve(SCRIPT_URL, path)

log.debug("Making %s executable", path)
mode = os.stat(path).st_mode
os.chmod(path, mode | 0o111)


def find_config(root=None, filenames=None, generate=False):
root = root or os.getcwd()
filenames = filenames or CONFIG_FILENAMES
Expand Down Expand Up @@ -186,7 +220,7 @@ def generate_config(root=None, filenames=None):


def parse_config(path):
data = OrderedDict()
data = OrderedDict() # type: ignore

log.info("Parsing config file: %s", path)
config = configparser.ConfigParser()
Expand All @@ -198,9 +232,9 @@ def parse_config(path):
data[section][name] = value

for name in data:
versions = data[name].get('versions', data[name].pop('version', ""))
data[name]['versions'] = versions
data[name]['patterns'] = [v.strip() for v in versions.split('|')]
version = data[name].get('version') or ""
data[name]['version'] = version
data[name]['patterns'] = [v.strip() for v in version.split('||')]

return data

Expand All @@ -214,23 +248,28 @@ def check_dependencies(config):

for pattern in settings['patterns']:
if match_version(pattern, output):
show(_("~") + " MATCHED: {0}".format(pattern))
show(_("~") + " MATCHED: {0}".format(pattern or "<anything>"))
success.append(_("~"))
break
else:
if settings.get('optional'):
show(_("?") + " EXPECTED: {0}".format(settings['versions']))
show(_("?") + " EXPECTED (OPTIONAL): {0}".format(settings['version']))
success.append(_("?"))
else:
if QUIET:
print("Unmatched {0} version: {1}".format(
name,
settings['versions'],
))
show(_("x") + " EXPECTED: {0}".format(settings['versions']))
if "not found" in output:
actual = "Not found"
else:
actual = output.split('\n')[0].strip('.')
expected = settings['version'] or "<anything>"
print("{0}: {1}, EXPECTED: {2}".format(name, actual, expected))
show(
_("x")
+ " EXPECTED: {0}".format(settings['version'] or "<anything>")
)
success.append(_("x"))
if settings.get('message'):
show(_("*") + " MESSAGE: {0}".format(settings['message']))
show(_("#") + " MESSAGE: {0}".format(settings['message']))

show("Results: " + " ".join(success), head=True)

Expand All @@ -247,12 +286,16 @@ def get_version(program, argument=None):

show("$ {0}".format(" ".join(args)))
output = call(args)
show(output.splitlines()[0] if output else "<nothing>")
lines = output.splitlines()
show(lines[0] if lines else "<nothing>")

return output


def match_version(pattern, output):
if "not found" in output.split('\n')[0]:
return False

regex = pattern.replace('.', r'\.') + r'(\b|/)'

log.debug("Matching %s: %s", regex, output)
Expand Down Expand Up @@ -289,7 +332,7 @@ def show(text, start='', end='\n', head=False):
if log.getEffectiveLevel() < logging.WARNING:
log.info(text)
else:
formatted = (start + text + end)
formatted = start + text + end
if PY2:
formatted = formatted.encode('utf-8')
sys.stdout.write(formatted)
Expand All @@ -303,7 +346,7 @@ def _(word, is_tty=None, supports_utf8=None, supports_ansi=None):
if is_tty is None:
is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
if supports_utf8 is None:
supports_utf8 = sys.stdout.encoding == 'UTF-8'
supports_utf8 = str(sys.stdout.encoding).lower() == 'utf-8'
if supports_ansi is None:
supports_ansi = sys.platform != 'win32' or 'ANSICON' in os.environ

Expand Down
1 change: 1 addition & 0 deletions gitman/tests/conftest.py
Expand Up @@ -17,6 +17,7 @@
def pytest_configure(config):
terminal = config.pluginmanager.getplugin('terminal')
terminal.TerminalReporter.showfspath = False
log.init()
log.silence('gitman.shell', allow_info=True)
log.silence('datafiles', allow_warning=True)

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Expand Up @@ -32,6 +32,7 @@ classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Topic :: Software Development",
"Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Version Control",
Expand Down

0 comments on commit 7ab00d4

Please sign in to comment.