Generate requirements_* from manifests (#22718)
## Description: Generate requirements_* from manifests (if present). If not, fallback to the current approach of reading `REQUIREMENTS` from the module attribute. I disabled exploring the children of the `homeassistant.components.*` packages since that will just add a dependency (from the manifest) due to each of the python files in the package. Just having one for the top level package should be sufficient. **Related issue (if applicable):** relates to #22700 ## Checklist: - [x] The code change is tested and works locally. - [x] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass** - [x] There is no commented out code in this PR. [ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L14 [ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L23 Co-authored-by: Jason Hu <awaregit@gmail.com>
This commit is contained in:
parent
6c5f0b7434
commit
d15eedc0fb
4 changed files with 515 additions and 524 deletions
File diff suppressed because it is too large
Load diff
|
@ -26,19 +26,19 @@ HAP-python==2.4.2
|
|||
# homeassistant.components.owntracks
|
||||
PyNaCl==1.3.0
|
||||
|
||||
# homeassistant.components.rmvtransport.sensor
|
||||
# homeassistant.components.rmvtransport
|
||||
PyRMVtransport==0.1.3
|
||||
|
||||
# homeassistant.components.transport_nsw.sensor
|
||||
# homeassistant.components.transport_nsw
|
||||
PyTransportNSW==0.1.1
|
||||
|
||||
# homeassistant.components.yessssms.notify
|
||||
# homeassistant.components.yessssms
|
||||
YesssSMS==0.2.3
|
||||
|
||||
# homeassistant.components.ambient_station
|
||||
aioambient==0.2.0
|
||||
aioambient==0.1.3
|
||||
|
||||
# homeassistant.components.automatic.device_tracker
|
||||
# homeassistant.components.automatic
|
||||
aioautomatic==0.6.5
|
||||
|
||||
# homeassistant.components.aws
|
||||
|
@ -54,7 +54,7 @@ aiohue==1.9.1
|
|||
# homeassistant.components.unifi
|
||||
aiounifi==4
|
||||
|
||||
# homeassistant.components.apns.notify
|
||||
# homeassistant.components.apns
|
||||
apns2==0.3.0
|
||||
|
||||
# homeassistant.components.stream
|
||||
|
@ -66,49 +66,49 @@ axis==19
|
|||
# homeassistant.components.zha
|
||||
bellows-homeassistant==0.7.2
|
||||
|
||||
# homeassistant.components.caldav.calendar
|
||||
# homeassistant.components.caldav
|
||||
caldav==0.5.0
|
||||
|
||||
# homeassistant.components.coinmarketcap.sensor
|
||||
# homeassistant.components.coinmarketcap
|
||||
coinmarketcap==5.0.3
|
||||
|
||||
# homeassistant.components.ihc
|
||||
# homeassistant.components.namecheapdns
|
||||
# homeassistant.components.ohmconnect.sensor
|
||||
# homeassistant.components.upc_connect.device_tracker
|
||||
# homeassistant.components.ohmconnect
|
||||
# homeassistant.components.upc_connect
|
||||
defusedxml==0.5.0
|
||||
|
||||
# homeassistant.components.dsmr.sensor
|
||||
# homeassistant.components.dsmr
|
||||
dsmr_parser==0.12
|
||||
|
||||
# homeassistant.components.ee_brightbox.device_tracker
|
||||
# homeassistant.components.ee_brightbox
|
||||
eebrightbox==0.0.4
|
||||
|
||||
# homeassistant.components.emulated_roku
|
||||
emulated_roku==0.1.8
|
||||
|
||||
# homeassistant.components.season.sensor
|
||||
# homeassistant.components.season
|
||||
ephem==3.7.6.0
|
||||
|
||||
# homeassistant.components.evohome
|
||||
# homeassistant.components.honeywell.climate
|
||||
# homeassistant.components.honeywell
|
||||
evohomeclient==0.3.2
|
||||
|
||||
# homeassistant.components.feedreader
|
||||
feedparser-homeassistant==5.2.2.dev1
|
||||
|
||||
# homeassistant.components.foobot.sensor
|
||||
# homeassistant.components.foobot
|
||||
foobot_async==0.3.1
|
||||
|
||||
# homeassistant.components.google.tts
|
||||
# homeassistant.components.google
|
||||
gTTS-token==1.1.3
|
||||
|
||||
# homeassistant.components.geo_json_events.geo_location
|
||||
# homeassistant.components.nsw_rural_fire_service_feed.geo_location
|
||||
# homeassistant.components.usgs_earthquakes_feed.geo_location
|
||||
# homeassistant.components.geo_json_events
|
||||
# homeassistant.components.nsw_rural_fire_service_feed
|
||||
# homeassistant.components.usgs_earthquakes_feed
|
||||
geojson_client==0.3
|
||||
|
||||
# homeassistant.components.geo_rss_events.sensor
|
||||
# homeassistant.components.geo_rss_events
|
||||
georss_generic_client==0.2
|
||||
|
||||
# homeassistant.components.ffmpeg
|
||||
|
@ -120,13 +120,13 @@ hangups==0.4.6
|
|||
# homeassistant.components.cloud
|
||||
hass-nabucasa==0.11
|
||||
|
||||
# homeassistant.components.mqtt.server
|
||||
# homeassistant.components.mqtt
|
||||
hbmqtt==0.9.4
|
||||
|
||||
# homeassistant.components.jewish_calendar.sensor
|
||||
# homeassistant.components.jewish_calendar
|
||||
hdate==0.8.7
|
||||
|
||||
# homeassistant.components.workday.binary_sensor
|
||||
# homeassistant.components.workday
|
||||
holidays==0.9.10
|
||||
|
||||
# homeassistant.components.frontend
|
||||
|
@ -139,7 +139,6 @@ homekit[IP]==0.13.0
|
|||
homematicip==0.10.6
|
||||
|
||||
# homeassistant.components.influxdb
|
||||
# homeassistant.components.influxdb.sensor
|
||||
influxdb==5.2.0
|
||||
|
||||
# homeassistant.components.verisure
|
||||
|
@ -148,7 +147,7 @@ jsonpath==0.75
|
|||
# homeassistant.components.dyson
|
||||
libpurecool==0.5.0
|
||||
|
||||
# homeassistant.components.soundtouch.media_player
|
||||
# homeassistant.components.soundtouch
|
||||
libsoundtouch==0.7.2
|
||||
|
||||
# homeassistant.components.luftdaten
|
||||
|
@ -157,38 +156,36 @@ luftdaten==0.3.4
|
|||
# homeassistant.components.mythicbeastsdns
|
||||
mbddns==0.1.2
|
||||
|
||||
# homeassistant.components.mfi.sensor
|
||||
# homeassistant.components.mfi.switch
|
||||
# homeassistant.components.mfi
|
||||
mficlient==0.3.0
|
||||
|
||||
# homeassistant.components.opencv.image_processing
|
||||
# homeassistant.components.pollen.sensor
|
||||
# homeassistant.components.tensorflow.image_processing
|
||||
# homeassistant.components.trend.binary_sensor
|
||||
# homeassistant.components.opencv
|
||||
# homeassistant.components.pollen
|
||||
# homeassistant.components.tensorflow
|
||||
# homeassistant.components.trend
|
||||
numpy==1.16.2
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
# homeassistant.components.shiftr
|
||||
paho-mqtt==1.4.0
|
||||
|
||||
# homeassistant.components.aruba.device_tracker
|
||||
# homeassistant.components.cisco_ios.device_tracker
|
||||
# homeassistant.components.pandora.media_player
|
||||
# homeassistant.components.unifi_direct.device_tracker
|
||||
# homeassistant.components.aruba
|
||||
# homeassistant.components.cisco_ios
|
||||
# homeassistant.components.pandora
|
||||
# homeassistant.components.unifi_direct
|
||||
pexpect==4.6.0
|
||||
|
||||
# homeassistant.components.pilight
|
||||
pilight==0.1.1
|
||||
|
||||
# homeassistant.components.mhz19.sensor
|
||||
# homeassistant.components.serial_pm.sensor
|
||||
# homeassistant.components.mhz19
|
||||
# homeassistant.components.serial_pm
|
||||
pmsensor==0.4
|
||||
|
||||
# homeassistant.components.prometheus
|
||||
prometheus_client==0.2.0
|
||||
|
||||
# homeassistant.components.pushbullet.notify
|
||||
# homeassistant.components.pushbullet.sensor
|
||||
# homeassistant.components.pushbullet
|
||||
pushbullet.py==0.11.0
|
||||
|
||||
# homeassistant.components.canary
|
||||
|
@ -197,7 +194,7 @@ py-canary==0.5.0
|
|||
# homeassistant.components.tplink
|
||||
pyHS100==0.3.4
|
||||
|
||||
# homeassistant.components.blackbird.media_player
|
||||
# homeassistant.components.blackbird
|
||||
pyblackbird==0.5
|
||||
|
||||
# homeassistant.components.deconz
|
||||
|
@ -215,11 +212,10 @@ pyhomematic==0.1.58
|
|||
# homeassistant.components.litejet
|
||||
pylitejet==0.1
|
||||
|
||||
# homeassistant.components.monoprice.media_player
|
||||
# homeassistant.components.monoprice
|
||||
pymonoprice==0.3
|
||||
|
||||
# homeassistant.components.nx584.alarm_control_panel
|
||||
# homeassistant.components.nx584.binary_sensor
|
||||
# homeassistant.components.nx584
|
||||
pynx584==0.4
|
||||
|
||||
# homeassistant.components.openuv
|
||||
|
@ -227,7 +223,7 @@ pyopenuv==1.0.9
|
|||
|
||||
# homeassistant.auth.mfa_modules.notify
|
||||
# homeassistant.auth.mfa_modules.totp
|
||||
# homeassistant.components.otp.sensor
|
||||
# homeassistant.components.otp
|
||||
pyotp==2.2.6
|
||||
|
||||
# homeassistant.components.ps4
|
||||
|
@ -248,24 +244,23 @@ pysonos==0.0.8
|
|||
# homeassistant.components.spc
|
||||
pyspcwebgw==0.4.0
|
||||
|
||||
# homeassistant.components.darksky.sensor
|
||||
# homeassistant.components.darksky.weather
|
||||
# homeassistant.components.darksky
|
||||
python-forecastio==1.4.0
|
||||
|
||||
# homeassistant.components.nest
|
||||
python-nest==4.1.0
|
||||
|
||||
# homeassistant.components.awair.sensor
|
||||
# homeassistant.components.awair
|
||||
python_awair==0.0.3
|
||||
|
||||
# homeassistant.components.tradfri
|
||||
pytradfri[async]==6.0.1
|
||||
|
||||
# homeassistant.components.unifi.device_tracker
|
||||
# homeassistant.components.unifi
|
||||
pyunifi==2.16
|
||||
|
||||
# homeassistant.components.html5.notify
|
||||
pywebpush==1.9.2
|
||||
# homeassistant.components.html5
|
||||
pywebpush==1.6.0
|
||||
|
||||
# homeassistant.components.rainmachine
|
||||
regenmaschine==1.4.0
|
||||
|
@ -279,7 +274,7 @@ rflink==0.0.37
|
|||
# homeassistant.components.ring
|
||||
ring_doorbell==0.2.3
|
||||
|
||||
# homeassistant.components.yamaha.media_player
|
||||
# homeassistant.components.yamaha
|
||||
rxv==0.6.0
|
||||
|
||||
# homeassistant.components.simplisafe
|
||||
|
@ -291,14 +286,14 @@ sleepyq==0.6
|
|||
# homeassistant.components.smhi
|
||||
smhi-pkg==1.0.10
|
||||
|
||||
# homeassistant.components.honeywell.climate
|
||||
# homeassistant.components.honeywell
|
||||
somecomfort==0.5.2
|
||||
|
||||
# homeassistant.components.recorder
|
||||
# homeassistant.components.sql.sensor
|
||||
# homeassistant.components.sql
|
||||
sqlalchemy==1.3.0
|
||||
|
||||
# homeassistant.components.srp_energy.sensor
|
||||
# homeassistant.components.srp_energy
|
||||
srpenergy==1.0.6
|
||||
|
||||
# homeassistant.components.statsd
|
||||
|
@ -307,7 +302,7 @@ statsd==3.2.1
|
|||
# homeassistant.components.toon
|
||||
toonapilib==3.2.2
|
||||
|
||||
# homeassistant.components.uvc.camera
|
||||
# homeassistant.components.uvc
|
||||
uvcclient==0.11.0
|
||||
|
||||
# homeassistant.components.verisure
|
||||
|
@ -316,10 +311,9 @@ vsure==1.5.2
|
|||
# homeassistant.components.vultr
|
||||
vultr==0.1.2
|
||||
|
||||
# homeassistant.components.panasonic_viera
|
||||
# homeassistant.components.samsungtv
|
||||
# homeassistant.components.wake_on_lan
|
||||
# homeassistant.components.panasonic_viera.media_player
|
||||
# homeassistant.components.samsungtv.media_player
|
||||
# homeassistant.components.wake_on_lan.switch
|
||||
wakeonlan==1.1.6
|
||||
|
||||
# homeassistant.components.zha
|
||||
|
|
|
@ -7,6 +7,8 @@ import pkgutil
|
|||
import re
|
||||
import sys
|
||||
|
||||
from script.manifest.requirements import gather_requirements_from_manifests
|
||||
|
||||
COMMENT_REQUIREMENTS = (
|
||||
'Adafruit-DHT',
|
||||
'Adafruit_BBIO',
|
||||
|
@ -213,36 +215,8 @@ def gather_modules():
|
|||
|
||||
errors = []
|
||||
|
||||
for package in sorted(
|
||||
explore_module('homeassistant.components', True) +
|
||||
explore_module('homeassistant.scripts', True) +
|
||||
explore_module('homeassistant.auth', True)):
|
||||
try:
|
||||
module = importlib.import_module(package)
|
||||
except ImportError as err:
|
||||
for pattern in IGNORE_PACKAGES:
|
||||
if fnmatch.fnmatch(package, pattern):
|
||||
break
|
||||
else:
|
||||
print("{}: {}".format(package.replace('.', '/') + '.py', err))
|
||||
errors.append(package)
|
||||
continue
|
||||
|
||||
if not getattr(module, 'REQUIREMENTS', None):
|
||||
continue
|
||||
|
||||
for req in module.REQUIREMENTS:
|
||||
if req in IGNORE_REQ:
|
||||
continue
|
||||
if '://' in req and 'pyharmony' not in req:
|
||||
errors.append(
|
||||
"{}[Only pypi dependencies are allowed: {}]".format(
|
||||
package, req))
|
||||
if req.partition('==')[1] == '' and req not in IGNORE_PIN:
|
||||
errors.append(
|
||||
"{}[Please pin requirement {}, see {}]".format(
|
||||
package, req, URL_PIN))
|
||||
reqs.setdefault(req, []).append(package)
|
||||
gather_requirements_from_manifests(process_requirements, errors, reqs)
|
||||
gather_requirements_from_modules(errors, reqs)
|
||||
|
||||
for key in reqs:
|
||||
reqs[key] = sorted(reqs[key],
|
||||
|
@ -257,12 +231,47 @@ def gather_modules():
|
|||
return reqs
|
||||
|
||||
|
||||
def gather_requirements_from_modules(errors, reqs):
|
||||
"""Collect the requirements from the modules directly."""
|
||||
for package in sorted(
|
||||
explore_module('homeassistant.scripts', True) +
|
||||
explore_module('homeassistant.auth', True)):
|
||||
try:
|
||||
module = importlib.import_module(package)
|
||||
except ImportError as err:
|
||||
for pattern in IGNORE_PACKAGES:
|
||||
if fnmatch.fnmatch(package, pattern):
|
||||
break
|
||||
else:
|
||||
print("{}: {}".format(package.replace('.', '/') + '.py', err))
|
||||
errors.append(package)
|
||||
continue
|
||||
|
||||
if getattr(module, 'REQUIREMENTS', None):
|
||||
process_requirements(errors, module.REQUIREMENTS, package, reqs)
|
||||
|
||||
|
||||
def process_requirements(errors, module_requirements, package, reqs):
|
||||
"""Process all of the requirements."""
|
||||
for req in module_requirements:
|
||||
if req in IGNORE_REQ:
|
||||
continue
|
||||
if '://' in req:
|
||||
errors.append(
|
||||
"{}[Only pypi dependencies are allowed: {}]".format(
|
||||
package, req))
|
||||
if req.partition('==')[1] == '' and req not in IGNORE_PIN:
|
||||
errors.append(
|
||||
"{}[Please pin requirement {}, see {}]".format(
|
||||
package, req, URL_PIN))
|
||||
reqs.setdefault(req, []).append(package)
|
||||
|
||||
|
||||
def generate_requirements_list(reqs):
|
||||
"""Generate a pip file based on requirements."""
|
||||
output = []
|
||||
for pkg, requirements in sorted(reqs.items(), key=lambda item: item[0]):
|
||||
for req in sorted(requirements,
|
||||
key=lambda name: (len(name.split('.')), name)):
|
||||
for req in sorted(requirements):
|
||||
output.append('\n# {}'.format(req))
|
||||
|
||||
if comment_requirement(pkg):
|
||||
|
|
22
script/manifest/requirements.py
Normal file
22
script/manifest/requirements.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
"""Helpers to gather requirements from manifests."""
|
||||
from .manifest_helper import iter_manifests
|
||||
|
||||
|
||||
def gather_requirements_from_manifests(process_requirements, errors, reqs):
|
||||
"""Gather all of the requirements from manifests."""
|
||||
for manifest in iter_manifests():
|
||||
assert manifest['domain']
|
||||
|
||||
if manifest.get('requirements') is None:
|
||||
errors.append(
|
||||
'The manifest for component {} is invalid. Please run'
|
||||
'script/manifest/validate.py'.format(manifest['domain'])
|
||||
)
|
||||
continue
|
||||
|
||||
process_requirements(
|
||||
errors,
|
||||
manifest['requirements'],
|
||||
'homeassistant.components.{}'.format(manifest['domain']),
|
||||
reqs
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue