pebble/tools/tool_check.py
2025-01-27 11:38:16 -08:00

135 lines
4.2 KiB
Python

# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import sh
import subprocess
import sys
from pkg_resources import parse_version
from waflib import Logs
REQUIREMENTS_OSX = 'requirements-osx.txt'
REQUIREMENTS_BREW = 'requirements-brew.txt'
VERSION_REGEX = r"^(?P<package>.*)(?P<comparator>==|<=|>=|<|>)(?P<version>.*)"
VERSION_PATTERN = re.compile(VERSION_REGEX)
def tool_check():
if sys.platform.startswith('linux'):
Logs.pprint('RED', 'Linux requirements-linux.txt checking not implemented. Sorry.')
return
Logs.pprint('CYAN', 'Checking %s' % REQUIREMENTS_OSX)
with open(REQUIREMENTS_OSX) as file:
osx_req_list = text_to_req_list(file.read())
pip_installed_text = sh.pip('freeze')
pip_installed_dict = installed_list_to_dict(text_to_req_list(pip_installed_text))
for req in osx_req_list:
check_requirement(req, pip_installed_dict)
Logs.pprint('CYAN', 'Checking %s' % REQUIREMENTS_BREW)
with open(REQUIREMENTS_BREW) as file:
brew_req_text = file.read()
brew_req_list = text_to_req_list(brew_req_text)
brew_installed_text = subprocess.check_output(['brew', 'list'])
brew_installed_dict = installed_list_to_dict(text_to_req_list(brew_installed_text))
for req in brew_req_list:
check_requirement(req, brew_installed_dict)
def installed_list_to_dict(list):
d = {}
for l in list:
d[l[0]] = l[2]
return d
def text_to_req_list(req_list_text):
req_list = []
for raw_line in req_list_text.splitlines():
# Recursively handle -r includes
if raw_line.startswith('-r '):
with open(raw_line[3:]) as file:
req_list.extend(text_to_req_list(file.read()))
continue
# Remove whitespace, comments, & --extra-index-url
line = raw_line.replace(" ", "")
if len(line) < 2 or line.startswith('#') or line.startswith('--'):
continue
match = VERSION_PATTERN.match(line)
if not match:
# Assume no version info
req_list.append((line, None, None))
continue
if match.group('package').endswith(','):
# Muliple requirements
match2 = VERSION_PATTERN.match(match.group('package').strip(','))
if not match2:
Logs.pprint('RED', 'Don\'t understand line \'%s\'' % raw_line)
continue
req_list.append((match2.group('package'), match2.group('comparator'),
match2.group('version')))
req_list.append((match2.group('package'), match.group('comparator'),
match.group('version')))
else:
req_list.append((match.group('package'), match.group('comparator'),
match.group('version')))
return req_list
def check_requirement(req, installed):
if req[0] not in installed:
Logs.pprint('RED', 'Package \'%s\' not installed' % req[0])
return
if not req[1]:
# No version/comparison
return
version = parse_version(installed[req[0]])
success = True
if req[1] == '==':
success = version == parse_version(req[2])
elif req[1] == '<=':
success = version <= parse_version(req[2])
elif req[1] == '>=':
success = version >= parse_version(req[2])
elif req[1] == '<':
success = version < parse_version(req[2])
elif req[1] == '>':
success = version > parse_version(req[2])
else:
Logs.pprint('RED', 'Don\'t understand comparison \'%s\'' % req[1])
if not success:
Logs.pprint('RED', 'Package \'%s\' installed = %s, needed %s %s ' %
(req[0], version, req[1], req[2]))
# vim:filetype=python