core/script/gen_requirements_all.py

144 lines
3.6 KiB
Python
Raw Normal View History

2015-11-17 08:18:42 +00:00
#!/usr/bin/env python3
2016-03-09 10:15:04 +00:00
"""Generate an updated requirements_all.txt."""
2015-11-17 08:18:42 +00:00
import importlib
import os
import pkgutil
import re
2015-12-18 07:51:34 +00:00
import sys
2015-11-17 08:18:42 +00:00
COMMENT_REQUIREMENTS = (
'RPi.GPIO',
2016-05-12 05:56:05 +00:00
'rpi-rf',
'Adafruit_Python_DHT',
2016-01-29 05:37:08 +00:00
'fritzconnection',
'pybluez',
'bluepy',
'python-lirc',
'gattlib',
'pyuserinput',
'evdev',
'pycups',
)
IGNORE_PACKAGES = (
'homeassistant.components.recorder.models',
)
2015-11-17 08:18:42 +00:00
def explore_module(package, explore_children):
2016-03-09 10:15:04 +00:00
"""Explore the modules."""
2015-11-17 08:18:42 +00:00
module = importlib.import_module(package)
found = []
if not hasattr(module, '__path__'):
return found
for _, name, _ in pkgutil.iter_modules(module.__path__, package + '.'):
2015-11-17 08:18:42 +00:00
found.append(name)
if explore_children:
found.extend(explore_module(name, False))
return found
def core_requirements():
2016-03-09 10:15:04 +00:00
"""Gather core requirements out of setup.py."""
2015-11-17 08:18:42 +00:00
with open('setup.py') as inp:
reqs_raw = re.search(
r'REQUIRES = \[(.*?)\]', inp.read(), re.S).group(1)
return re.findall(r"'(.*?)'", reqs_raw)
def comment_requirement(req):
2016-03-09 10:15:04 +00:00
"""Some requirements don't install on all systems."""
return any(ign in req for ign in COMMENT_REQUIREMENTS)
2015-11-25 22:31:04 +00:00
def gather_modules():
2016-03-09 10:15:04 +00:00
"""Collect the information and construct the output."""
2016-02-01 07:52:42 +00:00
reqs = {}
2015-11-17 08:18:42 +00:00
errors = []
2015-11-25 22:31:04 +00:00
output = []
for package in sorted(explore_module('homeassistant.components', True) +
explore_module('homeassistant.scripts', True)):
2015-11-17 08:18:42 +00:00
try:
module = importlib.import_module(package)
except ImportError:
if package not in IGNORE_PACKAGES:
errors.append(package)
2015-11-17 08:18:42 +00:00
continue
if not getattr(module, 'REQUIREMENTS', None):
continue
for req in module.REQUIREMENTS:
reqs.setdefault(req, []).append(package)
2016-02-01 07:52:42 +00:00
for key in reqs:
reqs[key] = sorted(reqs[key],
key=lambda name: (len(name.split('.')), name))
2015-11-17 08:18:42 +00:00
if errors:
2015-12-18 07:51:34 +00:00
print("******* ERROR")
print("Errors while importing: ", ', '.join(errors))
print("Make sure you import 3rd party libraries inside methods.")
return None
2015-11-17 08:18:42 +00:00
2015-11-25 22:31:04 +00:00
output.append('# Home Assistant core')
output.append('\n')
output.append('\n'.join(core_requirements()))
output.append('\n')
2016-02-01 07:52:42 +00:00
for pkg, requirements in sorted(reqs.items(), key=lambda item: item[0]):
2015-11-17 08:18:42 +00:00
for req in sorted(requirements,
key=lambda name: (len(name.split('.')), name)):
2015-11-25 22:31:04 +00:00
output.append('\n# {}'.format(req))
if comment_requirement(pkg):
2015-11-25 22:31:04 +00:00
output.append('\n# {}\n'.format(pkg))
else:
2015-11-25 22:31:04 +00:00
output.append('\n{}\n'.format(pkg))
return ''.join(output)
def write_file(data):
2016-03-09 10:15:04 +00:00
"""Write the modules to the requirements_all.txt."""
2015-11-25 22:31:04 +00:00
with open('requirements_all.txt', 'w+') as req_file:
req_file.write(data)
2015-12-18 07:51:34 +00:00
def validate_file(data):
2016-03-09 10:15:04 +00:00
"""Validate if requirements_all.txt is up to date."""
2015-12-18 07:51:34 +00:00
with open('requirements_all.txt', 'r') as req_file:
return data == ''.join(req_file)
2015-11-25 22:31:04 +00:00
def main():
2016-03-09 10:15:04 +00:00
"""Main section of the script."""
2015-11-25 22:31:04 +00:00
if not os.path.isfile('requirements_all.txt'):
print('Run this from HA root dir')
return
2015-11-25 22:31:04 +00:00
data = gather_modules()
if data is None:
2015-12-18 07:51:34 +00:00
sys.exit(1)
if sys.argv[-1] == 'validate':
if validate_file(data):
sys.exit(0)
print("******* ERROR")
print("requirements_all.txt is not up to date")
print("Please run script/gen_requirements_all.py")
sys.exit(1)
write_file(data)
2015-11-17 08:18:42 +00:00
2016-11-19 05:47:59 +00:00
2015-11-17 08:18:42 +00:00
if __name__ == '__main__':
main()