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
|
2018-03-08 23:28:49 +00:00
|
|
|
import fnmatch
|
2015-11-17 08:18:42 +00:00
|
|
|
|
2016-07-02 18:22:51 +00:00
|
|
|
COMMENT_REQUIREMENTS = (
|
2018-07-30 14:15:13 +00:00
|
|
|
'Adafruit-DHT',
|
2017-01-12 16:31:30 +00:00
|
|
|
'Adafruit_BBIO',
|
2019-02-26 22:50:48 +00:00
|
|
|
'avion',
|
2017-04-04 21:57:19 +00:00
|
|
|
'beacontools',
|
2019-02-26 22:50:48 +00:00
|
|
|
'blinkt',
|
2016-04-20 04:00:56 +00:00
|
|
|
'bluepy',
|
2019-02-26 22:50:48 +00:00
|
|
|
'bme680',
|
|
|
|
'credstash',
|
2017-05-04 14:03:50 +00:00
|
|
|
'decora',
|
2017-06-21 15:24:39 +00:00
|
|
|
'envirophat',
|
2019-02-26 22:50:48 +00:00
|
|
|
'evdev',
|
|
|
|
'face_recognition',
|
|
|
|
'fritzconnection',
|
2017-10-13 06:57:45 +00:00
|
|
|
'i2csense',
|
2019-02-26 22:50:48 +00:00
|
|
|
'opencv-python',
|
2018-08-22 22:21:46 +00:00
|
|
|
'py_noaa',
|
2019-02-26 22:50:48 +00:00
|
|
|
'pybluez',
|
|
|
|
'pycups',
|
|
|
|
'PySwitchbot',
|
|
|
|
'pySwitchmate',
|
|
|
|
'python-eq3bt',
|
|
|
|
'python-lirc',
|
|
|
|
'pyuserinput',
|
|
|
|
'raspihats',
|
|
|
|
'rpi-rf',
|
|
|
|
'RPi.GPIO',
|
|
|
|
'smbus-cffi',
|
2016-07-02 18:22:51 +00:00
|
|
|
)
|
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
TEST_REQUIREMENTS = (
|
2019-01-28 23:35:39 +00:00
|
|
|
'aioambient',
|
2017-05-07 05:37:31 +00:00
|
|
|
'aioautomatic',
|
2017-09-12 16:47:04 +00:00
|
|
|
'aiohttp_cors',
|
2018-03-04 05:28:04 +00:00
|
|
|
'aiohue',
|
2018-10-16 08:35:35 +00:00
|
|
|
'aiounifi',
|
2017-05-07 05:37:31 +00:00
|
|
|
'apns2',
|
2017-12-10 16:44:28 +00:00
|
|
|
'caldav',
|
2017-10-26 16:49:17 +00:00
|
|
|
'coinmarketcap',
|
2017-10-18 14:21:46 +00:00
|
|
|
'defusedxml',
|
2017-09-12 16:47:04 +00:00
|
|
|
'dsmr_parser',
|
2019-01-22 08:16:35 +00:00
|
|
|
'eebrightbox',
|
2019-01-11 02:20:35 +00:00
|
|
|
'emulated_roku',
|
2018-11-30 08:06:59 +00:00
|
|
|
'enturclient',
|
2017-09-12 16:47:04 +00:00
|
|
|
'ephem',
|
|
|
|
'evohomeclient',
|
2019-02-12 09:30:09 +00:00
|
|
|
'feedparser-homeassistant',
|
2018-03-16 02:50:58 +00:00
|
|
|
'foobot_async',
|
2018-09-21 19:15:57 +00:00
|
|
|
'geojson_client',
|
2018-10-02 08:20:51 +00:00
|
|
|
'georss_client',
|
2018-11-06 13:27:52 +00:00
|
|
|
'gTTS-token',
|
|
|
|
'ha-ffmpeg',
|
2018-08-24 08:39:35 +00:00
|
|
|
'hangups',
|
2018-02-19 22:46:22 +00:00
|
|
|
'HAP-python',
|
2017-09-24 06:12:38 +00:00
|
|
|
'haversine',
|
2017-05-07 05:37:31 +00:00
|
|
|
'hbmqtt',
|
2018-09-17 20:43:31 +00:00
|
|
|
'hdate',
|
2017-09-12 16:47:04 +00:00
|
|
|
'holidays',
|
2017-10-25 02:36:27 +00:00
|
|
|
'home-assistant-frontend',
|
2019-01-27 11:34:49 +00:00
|
|
|
'homekit',
|
2018-07-06 21:05:34 +00:00
|
|
|
'homematicip',
|
2017-09-12 16:47:04 +00:00
|
|
|
'influxdb',
|
2018-12-03 06:25:54 +00:00
|
|
|
'jsonpath',
|
2017-09-12 16:47:04 +00:00
|
|
|
'libpurecoollink',
|
|
|
|
'libsoundtouch',
|
2018-11-06 13:27:52 +00:00
|
|
|
'luftdaten',
|
2018-12-20 10:33:47 +00:00
|
|
|
'mbddns',
|
2017-05-07 05:37:31 +00:00
|
|
|
'mficlient',
|
2017-10-25 15:33:17 +00:00
|
|
|
'numpy',
|
2017-10-09 03:49:51 +00:00
|
|
|
'paho-mqtt',
|
2017-09-12 16:47:04 +00:00
|
|
|
'pexpect',
|
|
|
|
'pilight',
|
2017-05-07 05:37:31 +00:00
|
|
|
'pmsensor',
|
2017-09-12 16:47:04 +00:00
|
|
|
'prometheus_client',
|
2018-01-24 20:06:35 +00:00
|
|
|
'pushbullet.py',
|
2017-12-08 09:40:45 +00:00
|
|
|
'py-canary',
|
2018-04-19 09:35:38 +00:00
|
|
|
'pyblackbird',
|
2018-03-30 07:34:26 +00:00
|
|
|
'pydeconz',
|
2017-10-09 03:49:51 +00:00
|
|
|
'pydispatcher',
|
2018-10-12 07:36:52 +00:00
|
|
|
'pyhomematic',
|
2017-09-12 16:47:04 +00:00
|
|
|
'pylitejet',
|
2017-12-22 09:26:34 +00:00
|
|
|
'pymonoprice',
|
2017-10-09 03:49:51 +00:00
|
|
|
'pynx584',
|
2018-09-04 07:22:44 +00:00
|
|
|
'pyopenuv',
|
2018-08-26 20:38:52 +00:00
|
|
|
'pyotp',
|
2019-02-17 20:41:55 +00:00
|
|
|
'pyps4-homeassistant',
|
2019-01-31 01:31:59 +00:00
|
|
|
'pysmartapp',
|
|
|
|
'pysmartthings',
|
2018-09-20 21:50:11 +00:00
|
|
|
'pysonos',
|
2018-04-08 19:59:19 +00:00
|
|
|
'pyqwikswitch',
|
2018-08-10 17:35:09 +00:00
|
|
|
'PyRMVtransport',
|
2018-10-11 07:44:17 +00:00
|
|
|
'PyTransportNSW',
|
2018-09-24 08:10:10 +00:00
|
|
|
'pyspcwebgw',
|
2017-10-09 03:49:51 +00:00
|
|
|
'python-forecastio',
|
2018-06-13 15:14:52 +00:00
|
|
|
'python-nest',
|
Add Awair sensor platform (#18570)
* Awair Sensor Platform
This commit adds a sensor platform for Awair devices, by accessing
their beta API. Awair heavily rate-limits this API, so we throttle
updates based on the number of devices found. We also allow for the
user to bypass API device listing entirely, because the device list
endpoint is limited to only 6 calls per day. A crashing or restarting
server would quickly hit that limit.
This sensor platform uses the python_awair library (also written
as part of this PR), which is available for async usage.
* Disable pylint warning for broad try/catch
It's true that this is generally not a great idea, but we really don't
want to crash here. If we can't set up the platform, logging it and
continuing is the right answer.
* Add space to satisfy the linter
* Awair platform PR feedback
- Bump python_awair to 0.0.2, which has support for more granular exceptions
- Ensure we have python_awair available in test
- Raise PlatformNotReady if we can't set up Awair
- Make the 'Awair score' its own sensor, rather than exposing it other ways
- Set the platform up as polling, and set a sensible default
- Pass in throttling parameters to the underlying data class, rather
than use hacky global variable access to dynamically set the interval
- Switch to dict access for required variables
- Use pytest coroutines, set up components via async_setup_component,
and test/modify/assert in generally better ways
- Commit test data as fixtures
* Awair PR feedback, volume 2
- Don't force updates in test, instead modify time itself and let
homeassistant update things "normally".
- Remove unneeded polling attribute
- Rename timestamp attribute to 'last_api_update', to better reflect
that it is the timestamp of the last time the Awair API servers
received data from this device.
- Use that attribute to flag the component as unavailable when data
is stale. My own Awair device periodically goes offline and it really
hardly indicates that at all.
- Dynamically set fixture timestamps to the test run utcnow() value,
so that we don't have to worry about ancient timestamps in tests
blowing up down the line.
- Don't assert on entities directly, for the most part. Find desired
attributes in ... the attributes dict.
* Patch an instance of utcnow I overlooked
* Switch to using a context manager for timestream modification
Honestly, it's just a lot easier to keep track of patches. Moreover,
the ones I seem to have missed are now caught, and tests seem to
consistently pass.
Also, switch test_throttle_async_update to manipulating time more
explicitly.
* Missing blank line, thank you hound
* Fix pydocstyle error
I very much need to set up a script to do this quickly w/o tox, because
running flake8 is not enough!
* PR feedback
* PR feedback
2018-11-25 08:01:19 +00:00
|
|
|
'python_awair',
|
2018-10-25 20:15:20 +00:00
|
|
|
'pytradfri\\[async\\]',
|
2017-06-17 18:09:27 +00:00
|
|
|
'pyunifi',
|
2018-04-12 22:22:52 +00:00
|
|
|
'pyupnp-async',
|
2017-09-12 16:47:04 +00:00
|
|
|
'pywebpush',
|
Add support for automatic discovery of TP-Link switches, bulbs and dimmers (#18091)
* {switch,light}.tplink: use deviceid as unique id, fetch name from the device during initialization
* raise PlatformNotReady when no device is available
* Use mac instead of deviceid
* remove name option as obsolete
* Add support for configuration flow / integration
Allows activating automatic discovery of supported devices from the configuration
* Fix linting, update requirements_all.txt
* start cleaning up tplink component based on feedback
* add device info, improve config handling
* Allow overriding detected devices via configuration file
* Update requirements.txt
* Remove debug logging
* make hound happy
* Avoid I/O during init and simplify the code, remove remains of leds_on
* Fix issues based on feedback, use consistent quotation marks for device info
* add async_setup_platform emiting a deprecation warning
* Avoid blocking the I/O, check for None on features
* handle some Martin's comments, schema-validation is still missing
* use async_create_task instead of async_add_job, let core validate the schema
* simplify configuration handling by storing the configuration data separately from initialized instances
* add default values to schema, make hound happy
* with defaults set by schema, simplify the checks. add async_unload_entry
* Use constant for data structure access
* REWORD add a short note about async_unload_entry
* handle feedback from Martin, config_data is checked against Noneness
* use pop to remove the domain on unload
* First steps to add tests for the new tplink component
* embed platforms under the component directory
* Fix tests by mocking the pyhs100 internals
* Fix linting
* Test against multiple instances of devices, tidy up
* (hopefully) final linting round
* Add pyHS100 to test requirements
* log always the warnings occured during an update to make them easy to see
* revert back the warning behavior (requirement for silver level in IQS)
* Unload only when an entry is being loaded and add tests for that
Thanks @MartinHjelmare for pointing this out!
* Fix linting
* Bump the upstream lib, fixes most prominently the HSV setting on bulbs
* Test unloading for all platforms, clear the data storage instead of popping it out, making it possible to reconfigure after removal without restarting hass first
* Use class variables instead of instance variables for bulb states, required for HS220
* Use new-style format string
* Fix indenting, uppercase the mock constant
* Run black on test_init, hopefully that will finally fix the weird formatting (pycharm, pylint and hound seems to have different opinions...)
2019-02-21 19:29:07 +00:00
|
|
|
'pyHS100',
|
2018-11-14 20:23:49 +00:00
|
|
|
'regenmaschine',
|
2017-09-12 16:47:04 +00:00
|
|
|
'restrictedpython',
|
|
|
|
'rflink',
|
|
|
|
'ring_doorbell',
|
|
|
|
'rxv',
|
2018-10-12 17:07:47 +00:00
|
|
|
'simplisafe-python',
|
2017-09-12 16:47:04 +00:00
|
|
|
'sleepyq',
|
2018-10-08 21:54:55 +00:00
|
|
|
'smhi-pkg',
|
2017-09-12 16:47:04 +00:00
|
|
|
'somecomfort',
|
|
|
|
'sqlalchemy',
|
2018-11-08 18:19:30 +00:00
|
|
|
'srpenergy',
|
2017-09-12 16:47:04 +00:00
|
|
|
'statsd',
|
2019-02-26 18:18:09 +00:00
|
|
|
'toonapilib',
|
2017-09-12 16:47:04 +00:00
|
|
|
'uvcclient',
|
2018-12-03 06:25:54 +00:00
|
|
|
'vsure',
|
2017-09-12 16:47:04 +00:00
|
|
|
'warrant',
|
2017-11-01 10:15:24 +00:00
|
|
|
'pythonwhois',
|
2017-11-05 13:10:14 +00:00
|
|
|
'wakeonlan',
|
2018-10-04 21:34:04 +00:00
|
|
|
'vultr',
|
|
|
|
'YesssSMS',
|
2018-10-17 14:31:06 +00:00
|
|
|
'ruamel.yaml',
|
2019-02-20 15:34:59 +00:00
|
|
|
'zigpy-homeassistant',
|
|
|
|
'bellows-homeassistant',
|
2017-05-07 05:37:31 +00:00
|
|
|
)
|
|
|
|
|
2016-07-02 18:22:51 +00:00
|
|
|
IGNORE_PACKAGES = (
|
|
|
|
'homeassistant.components.recorder.models',
|
2018-08-24 08:39:35 +00:00
|
|
|
'homeassistant.components.homekit.*',
|
|
|
|
'homeassistant.components.hangouts.hangups_utils'
|
2016-07-02 18:22:51 +00:00
|
|
|
)
|
2015-11-17 08:28:22 +00:00
|
|
|
|
2017-01-21 23:31:10 +00:00
|
|
|
IGNORE_PIN = ('colorlog>2.1,<3', 'keyring>=9.3,<10.0', 'urllib3')
|
|
|
|
|
2017-03-12 19:08:49 +00:00
|
|
|
IGNORE_REQ = (
|
|
|
|
'colorama<=1', # Windows only requirement in check_config
|
|
|
|
)
|
|
|
|
|
2018-09-15 11:27:37 +00:00
|
|
|
URL_PIN = ('https://developers.home-assistant.io/docs/'
|
|
|
|
'creating_platform_code_review.html#1-requirements')
|
2017-01-22 16:34:00 +00:00
|
|
|
|
2015-11-17 08:18:42 +00:00
|
|
|
|
2017-03-22 15:50:54 +00:00
|
|
|
CONSTRAINT_PATH = os.path.join(os.path.dirname(__file__),
|
|
|
|
'../homeassistant/package_constraints.txt')
|
2017-08-05 06:06:10 +00:00
|
|
|
CONSTRAINT_BASE = """
|
2018-08-28 10:49:50 +00:00
|
|
|
pycryptodome>=3.6.6
|
|
|
|
|
2018-02-20 07:10:44 +00:00
|
|
|
# Breaks Python 3.6 and is not needed for our supported Python versions
|
2017-08-05 06:06:10 +00:00
|
|
|
enum34==1000000000.0.0
|
2018-02-27 09:58:45 +00:00
|
|
|
|
|
|
|
# This is a old unmaintained library and is replaced with pycryptodome
|
|
|
|
pycrypto==1000000000.0.0
|
2018-11-16 13:28:39 +00:00
|
|
|
|
|
|
|
# Contains code to modify Home Assistant to work around our rules
|
|
|
|
python-systemair-savecair==1000000000.0.0
|
2019-02-26 20:33:40 +00:00
|
|
|
|
|
|
|
# Newer version causes pylint to take forever
|
|
|
|
# https://github.com/timothycrosley/isort/issues/848
|
|
|
|
isort==4.3.4
|
2017-08-05 06:06:10 +00:00
|
|
|
"""
|
2017-03-22 15:50:54 +00:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2016-08-23 04:42:05 +00:00
|
|
|
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)
|
|
|
|
|
|
|
|
|
2015-11-17 08:28:22 +00:00
|
|
|
def comment_requirement(req):
|
2018-08-24 08:28:43 +00:00
|
|
|
"""Comment out requirement. Some don't install on all systems."""
|
2015-11-17 08:28:22 +00:00
|
|
|
return any(ign in req for ign in COMMENT_REQUIREMENTS)
|
|
|
|
|
|
|
|
|
2015-11-25 22:31:04 +00:00
|
|
|
def gather_modules():
|
2017-05-07 05:37:31 +00:00
|
|
|
"""Collect the information."""
|
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
|
|
|
|
2018-08-22 07:52:34 +00:00
|
|
|
for package in sorted(
|
|
|
|
explore_module('homeassistant.components', True) +
|
|
|
|
explore_module('homeassistant.scripts', True) +
|
|
|
|
explore_module('homeassistant.auth', True)):
|
2015-11-17 08:18:42 +00:00
|
|
|
try:
|
|
|
|
module = importlib.import_module(package)
|
|
|
|
except ImportError:
|
2018-03-08 23:28:49 +00:00
|
|
|
for pattern in IGNORE_PACKAGES:
|
|
|
|
if fnmatch.fnmatch(package, pattern):
|
|
|
|
break
|
|
|
|
else:
|
2016-07-02 18:22:51 +00:00
|
|
|
errors.append(package)
|
2015-11-17 08:18:42 +00:00
|
|
|
continue
|
|
|
|
|
|
|
|
if not getattr(module, 'REQUIREMENTS', None):
|
|
|
|
continue
|
|
|
|
|
|
|
|
for req in module.REQUIREMENTS:
|
2017-03-12 19:08:49 +00:00
|
|
|
if req in IGNORE_REQ:
|
|
|
|
continue
|
2018-12-19 13:21:40 +00:00
|
|
|
if '://' in req and 'pyharmony' not in req:
|
2018-07-18 10:16:27 +00:00
|
|
|
errors.append(
|
|
|
|
"{}[Only pypi dependencies are allowed: {}]".format(
|
|
|
|
package, req))
|
2017-01-21 23:31:10 +00:00
|
|
|
if req.partition('==')[1] == '' and req not in IGNORE_PIN:
|
2017-01-22 16:34:00 +00:00
|
|
|
errors.append(
|
|
|
|
"{}[Please pin requirement {}, see {}]".format(
|
|
|
|
package, req, URL_PIN))
|
2015-11-17 08:18:42 +00:00
|
|
|
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.")
|
2015-11-29 21:55:46 +00:00
|
|
|
return None
|
2015-11-17 08:18:42 +00:00
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
return reqs
|
|
|
|
|
|
|
|
|
|
|
|
def generate_requirements_list(reqs):
|
|
|
|
"""Generate a pip file based on requirements."""
|
|
|
|
output = []
|
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))
|
2015-11-17 08:28:22 +00:00
|
|
|
|
|
|
|
if comment_requirement(pkg):
|
2015-11-25 22:31:04 +00:00
|
|
|
output.append('\n# {}\n'.format(pkg))
|
2015-11-17 08:28:22 +00:00
|
|
|
else:
|
2015-11-25 22:31:04 +00:00
|
|
|
output.append('\n{}\n'.format(pkg))
|
2017-05-07 05:37:31 +00:00
|
|
|
return ''.join(output)
|
|
|
|
|
|
|
|
|
|
|
|
def requirements_all_output(reqs):
|
|
|
|
"""Generate output for requirements_all."""
|
|
|
|
output = []
|
|
|
|
output.append('# Home Assistant core')
|
|
|
|
output.append('\n')
|
|
|
|
output.append('\n'.join(core_requirements()))
|
|
|
|
output.append('\n')
|
|
|
|
output.append(generate_requirements_list(reqs))
|
|
|
|
|
|
|
|
return ''.join(output)
|
|
|
|
|
|
|
|
|
|
|
|
def requirements_test_output(reqs):
|
|
|
|
"""Generate output for test_requirements."""
|
|
|
|
output = []
|
|
|
|
output.append('# Home Assistant test')
|
|
|
|
output.append('\n')
|
2017-10-09 03:49:51 +00:00
|
|
|
with open('requirements_test.txt') as test_file:
|
|
|
|
output.append(test_file.read())
|
2017-05-07 05:37:31 +00:00
|
|
|
output.append('\n')
|
|
|
|
filtered = {key: value for key, value in reqs.items()
|
2017-10-09 03:49:51 +00:00
|
|
|
if any(
|
|
|
|
re.search(r'(^|#){}($|[=><])'.format(ign),
|
|
|
|
key) is not None for ign in TEST_REQUIREMENTS)}
|
2017-05-07 05:37:31 +00:00
|
|
|
output.append(generate_requirements_list(filtered))
|
2015-11-25 22:31:04 +00:00
|
|
|
|
|
|
|
return ''.join(output)
|
|
|
|
|
|
|
|
|
2017-03-22 15:50:54 +00:00
|
|
|
def gather_constraints():
|
|
|
|
"""Construct output for constraint file."""
|
|
|
|
return '\n'.join(core_requirements() + [''])
|
|
|
|
|
|
|
|
|
|
|
|
def write_requirements_file(data):
|
2016-03-09 10:15:04 +00:00
|
|
|
"""Write the modules to the requirements_all.txt."""
|
2017-03-12 19:08:49 +00:00
|
|
|
with open('requirements_all.txt', 'w+', newline="\n") as req_file:
|
2015-11-25 22:31:04 +00:00
|
|
|
req_file.write(data)
|
|
|
|
|
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
def write_test_requirements_file(data):
|
2018-07-18 10:16:27 +00:00
|
|
|
"""Write the modules to the requirements_test_all.txt."""
|
2017-05-07 05:37:31 +00:00
|
|
|
with open('requirements_test_all.txt', 'w+', newline="\n") as req_file:
|
|
|
|
req_file.write(data)
|
|
|
|
|
|
|
|
|
2017-03-22 15:50:54 +00:00
|
|
|
def write_constraints_file(data):
|
|
|
|
"""Write constraints to a file."""
|
|
|
|
with open(CONSTRAINT_PATH, 'w+', newline="\n") as req_file:
|
2017-08-05 06:06:10 +00:00
|
|
|
req_file.write(data + CONSTRAINT_BASE)
|
2017-03-22 15:50:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
def validate_requirements_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:
|
2017-08-05 06:06:10 +00:00
|
|
|
return data == req_file.read()
|
2015-12-18 07:51:34 +00:00
|
|
|
|
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
def validate_requirements_test_file(data):
|
2018-07-18 10:16:27 +00:00
|
|
|
"""Validate if requirements_test_all.txt is up to date."""
|
2017-05-07 05:37:31 +00:00
|
|
|
with open('requirements_test_all.txt', 'r') as req_file:
|
2017-08-05 06:06:10 +00:00
|
|
|
return data == req_file.read()
|
2017-05-07 05:37:31 +00:00
|
|
|
|
|
|
|
|
2017-03-22 15:50:54 +00:00
|
|
|
def validate_constraints_file(data):
|
|
|
|
"""Validate if constraints is up to date."""
|
|
|
|
with open(CONSTRAINT_PATH, 'r') as req_file:
|
2017-08-05 06:06:10 +00:00
|
|
|
return data + CONSTRAINT_BASE == req_file.read()
|
2017-03-22 15:50:54 +00:00
|
|
|
|
|
|
|
|
2018-03-09 20:27:39 +00:00
|
|
|
def main(validate):
|
2018-08-24 08:28:43 +00:00
|
|
|
"""Run 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')
|
2018-03-09 20:27:39 +00:00
|
|
|
return 1
|
2015-11-29 21:55:46 +00:00
|
|
|
|
2015-11-25 22:31:04 +00:00
|
|
|
data = gather_modules()
|
|
|
|
|
2015-11-29 21:55:46 +00:00
|
|
|
if data is None:
|
2018-03-09 20:27:39 +00:00
|
|
|
return 1
|
2015-12-18 07:51:34 +00:00
|
|
|
|
2017-03-22 15:50:54 +00:00
|
|
|
constraints = gather_constraints()
|
2015-11-29 21:55:46 +00:00
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
reqs_file = requirements_all_output(data)
|
|
|
|
reqs_test_file = requirements_test_output(data)
|
|
|
|
|
2018-03-09 20:27:39 +00:00
|
|
|
if validate:
|
2017-05-07 05:37:31 +00:00
|
|
|
errors = []
|
|
|
|
if not validate_requirements_file(reqs_file):
|
|
|
|
errors.append("requirements_all.txt is not up to date")
|
|
|
|
|
|
|
|
if not validate_requirements_test_file(reqs_test_file):
|
|
|
|
errors.append("requirements_test_all.txt is not up to date")
|
2017-03-22 15:50:54 +00:00
|
|
|
|
|
|
|
if not validate_constraints_file(constraints):
|
2017-05-07 05:37:31 +00:00
|
|
|
errors.append(
|
|
|
|
"home-assistant/package_constraints.txt is not up to date")
|
|
|
|
|
|
|
|
if errors:
|
2017-03-22 15:50:54 +00:00
|
|
|
print("******* ERROR")
|
2017-05-07 05:37:31 +00:00
|
|
|
print('\n'.join(errors))
|
2017-03-22 15:50:54 +00:00
|
|
|
print("Please run script/gen_requirements_all.py")
|
2018-03-09 20:27:39 +00:00
|
|
|
return 1
|
2017-03-22 15:50:54 +00:00
|
|
|
|
2018-03-09 20:27:39 +00:00
|
|
|
return 0
|
2017-03-22 15:50:54 +00:00
|
|
|
|
2017-05-07 05:37:31 +00:00
|
|
|
write_requirements_file(reqs_file)
|
|
|
|
write_test_requirements_file(reqs_test_file)
|
2017-03-22 15:50:54 +00:00
|
|
|
write_constraints_file(constraints)
|
2018-03-09 20:27:39 +00:00
|
|
|
return 0
|
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__':
|
2018-03-09 20:27:39 +00:00
|
|
|
_VAL = sys.argv[-1] == 'validate'
|
|
|
|
sys.exit(main(_VAL))
|