Merge pull request #289 from rmkraus/pip_updates
Update dependency installs and prepare for pip deployment
This commit is contained in:
commit
5aa8814a67
59 changed files with 359 additions and 306 deletions
|
@ -3,7 +3,7 @@ language: python
|
|||
python:
|
||||
- "3.4"
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install -r requirements_all.txt
|
||||
- pip install flake8 pylint coveralls
|
||||
script:
|
||||
- flake8 homeassistant --exclude bower_components,external
|
||||
|
|
|
@ -4,12 +4,11 @@ from __future__ import print_function
|
|||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import subprocess
|
||||
import importlib
|
||||
|
||||
DEPENDENCIES = ['requests>=2.0', 'pyyaml>=3.11', 'pytz>=2015.2']
|
||||
IS_VIRTUAL = (getattr(sys, 'base_prefix', sys.prefix) != sys.prefix or
|
||||
hasattr(sys, 'real_prefix'))
|
||||
from homeassistant import bootstrap
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||
|
||||
|
||||
def validate_python():
|
||||
|
@ -18,7 +17,7 @@ def validate_python():
|
|||
|
||||
if major < 3 or (major == 3 and minor < 4):
|
||||
print("Home Assistant requires atleast Python 3.4")
|
||||
sys.exit()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ensure_pip():
|
||||
|
@ -28,85 +27,43 @@ def ensure_pip():
|
|||
print("Home Assistant requires 'pip' to be installed.")
|
||||
print("Please install pip: "
|
||||
"https://pip.pypa.io/en/latest/installing.html")
|
||||
sys.exit()
|
||||
|
||||
|
||||
# Copy of homeassistant.util.package because we can't import yet
|
||||
def install_package(package):
|
||||
"""Install a package on PyPi. Accepts pip compatible package strings.
|
||||
Return boolean if install successfull."""
|
||||
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
||||
if not IS_VIRTUAL:
|
||||
args.append('--user')
|
||||
try:
|
||||
return 0 == subprocess.call(args)
|
||||
except subprocess.SubprocessError:
|
||||
return False
|
||||
|
||||
|
||||
def validate_dependencies():
|
||||
""" Validate all dependencies that HA uses. """
|
||||
ensure_pip()
|
||||
|
||||
print("Validating dependencies...")
|
||||
import_fail = False
|
||||
|
||||
for requirement in DEPENDENCIES:
|
||||
if not install_package(requirement):
|
||||
import_fail = True
|
||||
print('Fatal Error: Unable to install dependency', requirement)
|
||||
|
||||
if import_fail:
|
||||
print(("Install dependencies by running: "
|
||||
"python3 -m pip install -r requirements.txt"))
|
||||
sys.exit()
|
||||
|
||||
|
||||
def ensure_path_and_load_bootstrap():
|
||||
""" Ensure sys load path is correct and load Home Assistant bootstrap. """
|
||||
try:
|
||||
from homeassistant import bootstrap
|
||||
|
||||
except ImportError:
|
||||
# This is to add support to load Home Assistant using
|
||||
# `python3 homeassistant` instead of `python3 -m homeassistant`
|
||||
|
||||
# Insert the parent directory of this file into the module search path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
from homeassistant import bootstrap
|
||||
|
||||
return bootstrap
|
||||
|
||||
|
||||
def validate_git_submodules():
|
||||
""" Validate the git submodules are cloned. """
|
||||
try:
|
||||
# pylint: disable=no-name-in-module, unused-variable
|
||||
from homeassistant.external.noop import WORKING # noqa
|
||||
except ImportError:
|
||||
print("Repository submodules have not been initialized")
|
||||
print("Please run: git submodule update --init --recursive")
|
||||
sys.exit()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ensure_config_path(config_dir):
|
||||
""" Gets the path to the configuration file.
|
||||
Creates one if it not exists. """
|
||||
|
||||
lib_dir = os.path.join(config_dir, 'lib')
|
||||
|
||||
# Test if configuration directory exists
|
||||
if not os.path.isdir(config_dir):
|
||||
print(('Fatal Error: Unable to find specified configuration '
|
||||
'directory {} ').format(config_dir))
|
||||
sys.exit()
|
||||
if config_dir != config_util.get_default_config_dir():
|
||||
print(('Fatal Error: Specified configuration directory does '
|
||||
'not exist {} ').format(config_dir))
|
||||
sys.exit(1)
|
||||
|
||||
import homeassistant.config as config_util
|
||||
try:
|
||||
os.mkdir(config_dir)
|
||||
except OSError:
|
||||
print(('Fatal Error: Unable to create default configuration '
|
||||
'directory {} ').format(config_dir))
|
||||
sys.exit(1)
|
||||
|
||||
# Test if library directory exists
|
||||
if not os.path.isdir(lib_dir):
|
||||
try:
|
||||
os.mkdir(lib_dir)
|
||||
except OSError:
|
||||
print(('Fatal Error: Unable to create library '
|
||||
'directory {} ').format(lib_dir))
|
||||
sys.exit(1)
|
||||
|
||||
config_path = config_util.ensure_config_exists(config_dir)
|
||||
|
||||
if config_path is None:
|
||||
print('Error getting configuration path')
|
||||
sys.exit()
|
||||
sys.exit(1)
|
||||
|
||||
return config_path
|
||||
|
||||
|
@ -117,7 +74,7 @@ def get_arguments():
|
|||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
metavar='path_to_config_dir',
|
||||
default="config",
|
||||
default=config_util.get_default_config_dir(),
|
||||
help="Directory that contains the Home Assistant configuration")
|
||||
parser.add_argument(
|
||||
'--demo-mode',
|
||||
|
@ -134,14 +91,6 @@ def get_arguments():
|
|||
def main():
|
||||
""" Starts Home Assistant. """
|
||||
validate_python()
|
||||
validate_dependencies()
|
||||
|
||||
# Windows needs this to pick up new modules
|
||||
importlib.invalidate_caches()
|
||||
|
||||
bootstrap = ensure_path_and_load_bootstrap()
|
||||
|
||||
validate_git_submodules()
|
||||
|
||||
args = get_arguments()
|
||||
|
||||
|
@ -149,18 +98,14 @@ def main():
|
|||
config_path = ensure_config_path(config_dir)
|
||||
|
||||
if args.demo_mode:
|
||||
from homeassistant.components import frontend, demo
|
||||
|
||||
hass = bootstrap.from_config_dict({
|
||||
frontend.DOMAIN: {},
|
||||
demo.DOMAIN: {}
|
||||
})
|
||||
'frontend': {},
|
||||
'demo': {}
|
||||
}, config_dir=config_dir)
|
||||
else:
|
||||
hass = bootstrap.from_config_file(config_path)
|
||||
|
||||
if args.open_ui:
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_START
|
||||
|
||||
def open_browser(event):
|
||||
""" Open the webinterface in a browser. """
|
||||
if hass.config.api is not None:
|
||||
|
|
|
@ -10,6 +10,7 @@ start by calling homeassistant.start_home_assistant(bus)
|
|||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from collections import defaultdict
|
||||
|
||||
|
@ -61,13 +62,13 @@ def setup_component(hass, domain, config=None):
|
|||
return True
|
||||
|
||||
|
||||
def _handle_requirements(component, name):
|
||||
def _handle_requirements(hass, component, name):
|
||||
""" Installs requirements for component. """
|
||||
if not hasattr(component, 'REQUIREMENTS'):
|
||||
return True
|
||||
|
||||
for req in component.REQUIREMENTS:
|
||||
if not pkg_util.install_package(req):
|
||||
if not pkg_util.install_package(req, target=hass.config.path('lib')):
|
||||
_LOGGER.error('Not initializing %s because could not install '
|
||||
'dependency %s', name, req)
|
||||
return False
|
||||
|
@ -88,7 +89,7 @@ def _setup_component(hass, domain, config):
|
|||
domain, ", ".join(missing_deps))
|
||||
return False
|
||||
|
||||
if not _handle_requirements(component, domain):
|
||||
if not _handle_requirements(hass, component, domain):
|
||||
return False
|
||||
|
||||
try:
|
||||
|
@ -138,14 +139,19 @@ def prepare_setup_platform(hass, config, domain, platform_name):
|
|||
component)
|
||||
return None
|
||||
|
||||
if not _handle_requirements(platform, platform_path):
|
||||
if not _handle_requirements(hass, platform, platform_path):
|
||||
return None
|
||||
|
||||
return platform
|
||||
|
||||
|
||||
def mount_local_lib_path(config_dir):
|
||||
""" Add local library to Python Path """
|
||||
sys.path.insert(0, os.path.join(config_dir, 'lib'))
|
||||
|
||||
|
||||
# pylint: disable=too-many-branches, too-many-statements
|
||||
def from_config_dict(config, hass=None):
|
||||
def from_config_dict(config, hass=None, config_dir=None):
|
||||
"""
|
||||
Tries to configure Home Assistant from a config dict.
|
||||
|
||||
|
@ -153,6 +159,10 @@ def from_config_dict(config, hass=None):
|
|||
"""
|
||||
if hass is None:
|
||||
hass = core.HomeAssistant()
|
||||
if config_dir is not None:
|
||||
config_dir = os.path.abspath(config_dir)
|
||||
hass.config.config_dir = config_dir
|
||||
mount_local_lib_path(config_dir)
|
||||
|
||||
process_ha_core_config(hass, config.get(core.DOMAIN, {}))
|
||||
|
||||
|
@ -195,7 +205,9 @@ def from_config_file(config_path, hass=None):
|
|||
hass = core.HomeAssistant()
|
||||
|
||||
# Set config dir to directory holding config file
|
||||
hass.config.config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||
config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||
hass.config.config_dir = config_dir
|
||||
mount_local_lib_path(config_dir)
|
||||
|
||||
config_dict = config_util.load_config_file(config_path)
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ from homeassistant.components.device_tracker import DOMAIN
|
|||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['pynetgear>=0.3']
|
||||
REQUIREMENTS = ['pynetgear==0.3']
|
||||
|
||||
|
||||
def get_scanner(hass, config):
|
||||
|
|
|
@ -26,8 +26,12 @@ from collections import namedtuple
|
|||
import subprocess
|
||||
import re
|
||||
|
||||
from libnmap.process import NmapProcess
|
||||
from libnmap.parser import NmapParser, NmapParserException
|
||||
try:
|
||||
from libnmap.process import NmapProcess
|
||||
from libnmap.parser import NmapParser, NmapParserException
|
||||
LIB_LOADED = True
|
||||
except ImportError:
|
||||
LIB_LOADED = False
|
||||
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.const import CONF_HOSTS
|
||||
|
@ -43,7 +47,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
# interval in minutes to exclude devices from a scan while they are home
|
||||
CONF_HOME_INTERVAL = "home_interval"
|
||||
|
||||
REQUIREMENTS = ['python-libnmap>=0.6.3']
|
||||
REQUIREMENTS = ['python-libnmap==0.6.1']
|
||||
|
||||
|
||||
def get_scanner(hass, config):
|
||||
|
@ -52,6 +56,10 @@ def get_scanner(hass, config):
|
|||
_LOGGER):
|
||||
return None
|
||||
|
||||
if not LIB_LOADED:
|
||||
_LOGGER.error("Error while importing dependency python-libnmap.")
|
||||
return False
|
||||
|
||||
scanner = NmapDeviceScanner(config[DOMAIN])
|
||||
|
||||
return scanner if scanner.success_init else None
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.const import (
|
|||
|
||||
DOMAIN = "discovery"
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['netdisco>=0.3']
|
||||
REQUIREMENTS = ['netdisco==0.3']
|
||||
|
||||
SCAN_INTERVAL = 300 # seconds
|
||||
|
||||
|
|
0
homeassistant/components/frontend/www_static/__init__.py
Normal file
0
homeassistant/components/frontend/www_static/__init__.py
Normal file
|
@ -21,7 +21,7 @@ from homeassistant.const import (
|
|||
|
||||
DOMAIN = "isy994"
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['PyISY>=1.0.5']
|
||||
REQUIREMENTS = ['PyISY==1.0.5']
|
||||
DISCOVER_LIGHTS = "isy994.lights"
|
||||
DISCOVER_SWITCHES = "isy994.switches"
|
||||
DISCOVER_SENSORS = "isy994.sensors"
|
||||
|
|
|
@ -14,7 +14,7 @@ from homeassistant.const import (
|
|||
|
||||
DOMAIN = "keyboard"
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['pyuserinput>=0.1.9']
|
||||
REQUIREMENTS = ['pyuserinput==0.1.9']
|
||||
|
||||
|
||||
def volume_up(hass):
|
||||
|
|
|
@ -16,7 +16,7 @@ from homeassistant.components.light import (
|
|||
ATTR_FLASH, FLASH_LONG, FLASH_SHORT, ATTR_EFFECT,
|
||||
EFFECT_COLORLOOP)
|
||||
|
||||
REQUIREMENTS = ['phue>=0.8']
|
||||
REQUIREMENTS = ['phue==0.8']
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100)
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from homeassistant.components.light import (Light, ATTR_BRIGHTNESS,
|
|||
from homeassistant.util.color import color_RGB_to_xy
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['ledcontroller>=1.0.7']
|
||||
REQUIREMENTS = ['ledcontroller==1.0.7']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
|
|
|
@ -9,7 +9,7 @@ from homeassistant.components.light import Light, ATTR_BRIGHTNESS
|
|||
from homeassistant.const import ATTR_FRIENDLY_NAME
|
||||
import tellcore.constants as tellcore_constants
|
||||
|
||||
REQUIREMENTS = ['tellcore-py>=1.0.4']
|
||||
REQUIREMENTS = ['tellcore-py==1.0.4']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
|
|
|
@ -9,8 +9,8 @@ from homeassistant.components.light import ATTR_BRIGHTNESS
|
|||
from homeassistant.components.wink import WinkToggleDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/master.zip'
|
||||
'#pywink>=0.1']
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' +
|
||||
'c2b700e8ca866159566ecf5e644d9c297f69f257.zip']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.components.media_player import (
|
|||
SUPPORT_PREVIOUS_TRACK, SUPPORT_NEXT_TRACK,
|
||||
MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, MEDIA_TYPE_VIDEO)
|
||||
|
||||
REQUIREMENTS = ['pychromecast>=0.6.10']
|
||||
REQUIREMENTS = ['pychromecast==0.6.10']
|
||||
CONF_IGNORE_CEC = 'ignore_cec'
|
||||
CAST_SPLASH = 'https://home-assistant.io/images/cast/splash.png'
|
||||
SUPPORT_CAST = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
|
||||
|
|
|
@ -48,7 +48,7 @@ except ImportError:
|
|||
jsonrpc_requests = None
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['jsonrpc-requests>=0.1']
|
||||
REQUIREMENTS = ['jsonrpc-requests==0.1']
|
||||
|
||||
SUPPORT_KODI = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \
|
||||
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_SEEK
|
||||
|
|
|
@ -48,7 +48,7 @@ from homeassistant.components.media_player import (
|
|||
MEDIA_TYPE_MUSIC)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['python-mpd2>=0.5.4']
|
||||
REQUIREMENTS = ['python-mpd2==0.5.4']
|
||||
|
||||
SUPPORT_MPD = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_TURN_OFF | \
|
||||
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK
|
||||
|
|
|
@ -38,8 +38,8 @@ from homeassistant.const import (EVENT_HOMEASSISTANT_START,
|
|||
DOMAIN = "modbus"
|
||||
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['https://github.com/bashwork/pymodbus/archive/python3.zip'
|
||||
'#pymodbus>=1.2.0']
|
||||
REQUIREMENTS = ['https://github.com/bashwork/pymodbus/archive/' +
|
||||
'd7fc4f1cc975631e0a9011390e8017f64b612661.zip']
|
||||
|
||||
# Type of network
|
||||
MEDIUM = "type"
|
||||
|
|
|
@ -46,7 +46,7 @@ The keep alive in seconds for this client. Default is 60.
|
|||
import logging
|
||||
import socket
|
||||
|
||||
from homeassistant.core import HomeAssistantError
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.const import (
|
||||
|
@ -66,7 +66,7 @@ SERVICE_PUBLISH = 'publish'
|
|||
EVENT_MQTT_MESSAGE_RECEIVED = 'MQTT_MESSAGE_RECEIVED'
|
||||
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['paho-mqtt>=1.1']
|
||||
REQUIREMENTS = ['paho-mqtt==1.1']
|
||||
|
||||
CONF_BROKER = 'broker'
|
||||
CONF_PORT = 'port'
|
||||
|
|
|
@ -28,7 +28,7 @@ from homeassistant.components.notify import (
|
|||
from homeassistant.const import CONF_API_KEY
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['pushbullet.py>=0.7.1']
|
||||
REQUIREMENTS = ['pushbullet.py==0.7.1']
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
|
|
|
@ -42,7 +42,7 @@ from homeassistant.components.notify import (
|
|||
DOMAIN, ATTR_TITLE, BaseNotificationService)
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
|
||||
REQUIREMENTS = ['python-pushover>=0.2']
|
||||
REQUIREMENTS = ['python-pushover==0.2']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ from homeassistant.components.notify import (
|
|||
DOMAIN, BaseNotificationService)
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
|
||||
REQUIREMENTS = ['slacker>=0.6.8']
|
||||
REQUIREMENTS = ['slacker==0.6.8']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ from homeassistant.helpers import validate_config
|
|||
from homeassistant.components.notify import (
|
||||
DOMAIN, ATTR_TITLE, BaseNotificationService)
|
||||
|
||||
REQUIREMENTS = ['sleekxmpp>=1.3.1', 'dnspython3>=1.12.0']
|
||||
REQUIREMENTS = ['sleekxmpp==1.3.1', 'dnspython3==1.12.0']
|
||||
|
||||
|
||||
def get_service(hass, config):
|
||||
|
|
|
@ -71,7 +71,7 @@ from homeassistant.util import Throttle
|
|||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
|
||||
REQUIREMENTS = ['blockchain>=1.1.2']
|
||||
REQUIREMENTS = ['blockchain==1.1.2']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
OPTION_TYPES = {
|
||||
'wallet': ['Wallet balance', 'BTC'],
|
||||
|
|
|
@ -44,7 +44,8 @@ from homeassistant.const import TEMP_FAHRENHEIT
|
|||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
# update this requirement to upstream as soon as it supports python3
|
||||
REQUIREMENTS = ['git+git://github.com/mala-zaba/Adafruit_Python_DHT']
|
||||
REQUIREMENTS = ['http://github.com/mala-zaba/Adafruit_Python_DHT/archive/' +
|
||||
'4101340de8d2457dd194bca1e8d11cbfc237e919.zip']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
SENSOR_TYPES = {
|
||||
'temperature': ['Temperature', ''],
|
||||
|
|
|
@ -49,7 +49,7 @@ Details for the API : https://developer.forecast.io/docs/v2
|
|||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
REQUIREMENTS = ['python-forecastio>=1.3.3']
|
||||
REQUIREMENTS = ['python-forecastio==1.3.3']
|
||||
|
||||
try:
|
||||
import forecastio
|
||||
|
|
|
@ -36,8 +36,8 @@ ATTR_NODE_ID = "node_id"
|
|||
ATTR_CHILD_ID = "child_id"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['https://github.com/theolind/pymysensors/archive/master.zip'
|
||||
'#egg=pymysensors-0.1']
|
||||
REQUIREMENTS = ['https://github.com/theolind/pymysensors/archive/' +
|
||||
'35b87d880147a34107da0d40cb815d75e6cb4af7.zip']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
|
|
@ -48,7 +48,7 @@ from homeassistant.util import Throttle
|
|||
from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS, TEMP_FAHRENHEIT)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
REQUIREMENTS = ['pyowm>=2.2.1']
|
||||
REQUIREMENTS = ['pyowm==2.2.1']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
SENSOR_TYPES = {
|
||||
'weather': ['Condition', ''],
|
||||
|
|
|
@ -26,8 +26,8 @@ from collections import OrderedDict
|
|||
from homeassistant.const import (TEMP_CELCIUS)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
REQUIREMENTS = ['https://github.com/Danielhiversen/pyRFXtrx/archive/master.zip'
|
||||
'#RFXtrx>=0.15']
|
||||
REQUIREMENTS = ['https://github.com/Danielhiversen/pyRFXtrx/archive/' +
|
||||
'ec7a1aaddf8270db6e5da1c13d58c1547effd7cf.zip']
|
||||
|
||||
DATA_TYPES = OrderedDict([
|
||||
('Temperature', TEMP_CELCIUS),
|
||||
|
|
|
@ -53,7 +53,7 @@ DEFAULT_VALUE_HIGH = "HIGH"
|
|||
DEFAULT_VALUE_LOW = "LOW"
|
||||
DEFAULT_BOUNCETIME = 50
|
||||
|
||||
REQUIREMENTS = ['RPi.GPIO>=0.5.11']
|
||||
REQUIREMENTS = ['RPi.GPIO==0.5.11']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ import homeassistant.util.dt as dt_util
|
|||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.const import STATE_ON, STATE_OFF
|
||||
|
||||
REQUIREMENTS = ['psutil>=3.0.0']
|
||||
REQUIREMENTS = ['psutil==3.0.0']
|
||||
SENSOR_TYPES = {
|
||||
'disk_use_percent': ['Disk Use', '%'],
|
||||
'disk_use': ['Disk Use', 'GiB'],
|
||||
|
|
|
@ -35,7 +35,7 @@ import homeassistant.util as util
|
|||
|
||||
DatatypeDescription = namedtuple("DatatypeDescription", ['name', 'unit'])
|
||||
|
||||
REQUIREMENTS = ['tellcore-py>=1.0.4']
|
||||
REQUIREMENTS = ['tellcore-py==1.0.4']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -18,7 +18,8 @@ from homeassistant.const import CONF_NAME, DEVICE_DEFAULT_NAME
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
REQUIREMENTS = ['https://github.com/rkabadi/temper-python/archive/master.zip']
|
||||
REQUIREMENTS = ['https://github.com/rkabadi/temper-python/archive/' +
|
||||
'3dbdaf2d87b8db9a3cd6e5585fc704537dd2d09b.zip']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -67,7 +67,7 @@ from transmissionrpc.error import TransmissionError
|
|||
|
||||
import logging
|
||||
|
||||
REQUIREMENTS = ['transmissionrpc>=0.11']
|
||||
REQUIREMENTS = ['transmissionrpc==0.11']
|
||||
SENSOR_TYPES = {
|
||||
'current_status': ['Status', ''],
|
||||
'download_speed': ['Down Speed', 'MB/s'],
|
||||
|
|
|
@ -8,8 +8,8 @@ import logging
|
|||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN, STATE_OPEN, STATE_CLOSED
|
||||
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/master.zip'
|
||||
'#pywink>=0.1']
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' +
|
||||
'c2b700e8ca866159566ecf5e644d9c297f69f257.zip']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
|
|
@ -31,7 +31,7 @@ from homeassistant.helpers.entity import Entity
|
|||
from homeassistant.components.scheduler import ServiceEventListener
|
||||
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['astral>=0.8.1']
|
||||
REQUIREMENTS = ['astral==0.8.1']
|
||||
DOMAIN = "sun"
|
||||
ENTITY_ID = "sun.sun"
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD,\
|
|||
DEFAULT_USERNAME = 'admin'
|
||||
DEFAULT_PASSWORD = '1234'
|
||||
DEVICE_DEFAULT_NAME = 'Edimax Smart Plug'
|
||||
REQUIREMENTS = ['https://github.com/rkabadi/pyedimax/archive/master.zip']
|
||||
REQUIREMENTS = ['https://github.com/rkabadi/pyedimax/archive/' +
|
||||
'365301ce3ff26129a7910c501ead09ea625f3700.zip']
|
||||
|
||||
# setup logger
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
|
|
@ -49,7 +49,7 @@ except ImportError:
|
|||
hikvision.api = None
|
||||
|
||||
_LOGGING = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['hikvision>=0.4']
|
||||
REQUIREMENTS = ['hikvision==0.4']
|
||||
# pylint: disable=too-many-arguments
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ from homeassistant.const import (DEVICE_DEFAULT_NAME,
|
|||
|
||||
DEFAULT_INVERT_LOGIC = False
|
||||
|
||||
REQUIREMENTS = ['RPi.GPIO>=0.5.11']
|
||||
REQUIREMENTS = ['RPi.GPIO==0.5.11']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import tellcore.constants as tellcore_constants
|
|||
|
||||
SINGAL_REPETITIONS = 1
|
||||
|
||||
REQUIREMENTS = ['tellcore-py>=1.0.4']
|
||||
REQUIREMENTS = ['tellcore-py==1.0.4']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -48,7 +48,7 @@ from transmissionrpc.error import TransmissionError
|
|||
import logging
|
||||
|
||||
_LOGGING = logging.getLogger(__name__)
|
||||
REQUIREMENTS = ['transmissionrpc>=0.11']
|
||||
REQUIREMENTS = ['transmissionrpc==0.11']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -8,7 +8,7 @@ import logging
|
|||
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
|
||||
REQUIREMENTS = ['pywemo>=0.2']
|
||||
REQUIREMENTS = ['pywemo==0.2']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -9,8 +9,8 @@ import logging
|
|||
from homeassistant.components.wink import WinkToggleDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/master.zip'
|
||||
'#pywink>=0.1']
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' +
|
||||
'c2b700e8ca866159566ecf5e644d9c297f69f257.zip']
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
|
|
@ -6,7 +6,7 @@ import logging
|
|||
from homeassistant.components.thermostat import ThermostatDevice
|
||||
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS)
|
||||
|
||||
REQUIREMENTS = ['python-nest>=2.4.0']
|
||||
REQUIREMENTS = ['python-nest==2.4.0']
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
|
|
@ -61,7 +61,8 @@ DISCOVER_SWITCHES = 'verisure.switches'
|
|||
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = [
|
||||
'https://github.com/persandstrom/python-verisure/archive/master.zip'
|
||||
'https://github.com/persandstrom/python-verisure/archive/' +
|
||||
'9873c4527f01b1ba1f72ae60f7f35854390d59be.zip'
|
||||
]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
|
|
@ -16,8 +16,8 @@ from homeassistant.const import (
|
|||
|
||||
DOMAIN = "wink"
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/master.zip'
|
||||
'#pywink>=0.1']
|
||||
REQUIREMENTS = ['https://github.com/balloob/python-wink/archive/' +
|
||||
'c2b700e8ca866159566ecf5e644d9c297f69f257.zip']
|
||||
|
||||
DISCOVER_LIGHTS = "wink.lights"
|
||||
DISCOVER_SWITCHES = "wink.switches"
|
||||
|
|
|
@ -12,7 +12,7 @@ from homeassistant.const import (
|
|||
|
||||
DOMAIN = "zwave"
|
||||
DEPENDENCIES = []
|
||||
REQUIREMENTS = ['pydispatcher>=2.0.5']
|
||||
REQUIREMENTS = ['pydispatcher==2.0.5']
|
||||
|
||||
CONF_USB_STICK_PATH = "usb_path"
|
||||
DEFAULT_CONF_USB_STICK_PATH = "/zwaveusbstick"
|
||||
|
|
|
@ -7,7 +7,7 @@ Module to help with parsing and generating configuration files.
|
|||
import logging
|
||||
import os
|
||||
|
||||
from homeassistant.core import HomeAssistantError
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.const import (
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME,
|
||||
CONF_TIME_ZONE)
|
||||
|
@ -16,6 +16,7 @@ import homeassistant.util.location as loc_util
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
YAML_CONFIG_FILE = 'configuration.yaml'
|
||||
CONFIG_DIR_NAME = '.homeassistant'
|
||||
|
||||
DEFAULT_CONFIG = (
|
||||
# Tuples (attribute, default, auto detect property, description)
|
||||
|
@ -39,6 +40,13 @@ DEFAULT_COMPONENTS = {
|
|||
}
|
||||
|
||||
|
||||
def get_default_config_dir():
|
||||
""" Put together the default configuration directory based on OS. """
|
||||
data_dir = os.getenv('APPDATA') if os.name == "nt" \
|
||||
else os.path.expanduser('~')
|
||||
return os.path.join(data_dir, CONFIG_DIR_NAME)
|
||||
|
||||
|
||||
def ensure_config_exists(config_dir, detect_location=True):
|
||||
""" Ensures a config file exists in given config dir.
|
||||
Creating a default one if needed.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
""" Constants used by Home Assistant components. """
|
||||
|
||||
__version__ = "0.7.0"
|
||||
|
||||
# Can be used to specify a catch all when registering state or event listeners.
|
||||
MATCH_ALL = '*'
|
||||
|
||||
|
|
|
@ -21,9 +21,12 @@ from homeassistant.const import (
|
|||
EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL,
|
||||
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED,
|
||||
TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_FRIENDLY_NAME)
|
||||
from homeassistant.exceptions import (
|
||||
HomeAssistantError, InvalidEntityFormatError)
|
||||
import homeassistant.util as util
|
||||
import homeassistant.util.dt as date_util
|
||||
import homeassistant.helpers.temperature as temp_helper
|
||||
from homeassistant.config import get_default_config_dir
|
||||
|
||||
DOMAIN = "homeassistant"
|
||||
|
||||
|
@ -660,7 +663,7 @@ class Config(object):
|
|||
self.api = None
|
||||
|
||||
# Directory that holds the configuration
|
||||
self.config_dir = os.path.join(os.getcwd(), 'config')
|
||||
self.config_dir = get_default_config_dir()
|
||||
|
||||
def path(self, *path):
|
||||
""" Returns path to the file within the config dir. """
|
||||
|
@ -695,21 +698,6 @@ class Config(object):
|
|||
}
|
||||
|
||||
|
||||
class HomeAssistantError(Exception):
|
||||
""" General Home Assistant exception occured. """
|
||||
pass
|
||||
|
||||
|
||||
class InvalidEntityFormatError(HomeAssistantError):
|
||||
""" When an invalid formatted entity is encountered. """
|
||||
pass
|
||||
|
||||
|
||||
class NoEntitySpecifiedError(HomeAssistantError):
|
||||
""" When no entity is specified. """
|
||||
pass
|
||||
|
||||
|
||||
def create_timer(hass, interval=TIMER_INTERVAL):
|
||||
""" Creates a timer. Timer will start on HOMEASSISTANT_START. """
|
||||
# We want to be able to fire every time a minute starts (seconds=0).
|
||||
|
|
16
homeassistant/exceptions.py
Normal file
16
homeassistant/exceptions.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
""" Exceptions used by Home Assistant """
|
||||
|
||||
|
||||
class HomeAssistantError(Exception):
|
||||
""" General Home Assistant exception occured. """
|
||||
pass
|
||||
|
||||
|
||||
class InvalidEntityFormatError(HomeAssistantError):
|
||||
""" When an invalid formatted entity is encountered. """
|
||||
pass
|
||||
|
||||
|
||||
class NoEntitySpecifiedError(HomeAssistantError):
|
||||
""" When no entity is specified. """
|
||||
pass
|
|
@ -7,7 +7,7 @@ Provides ABC for entities in HA.
|
|||
|
||||
from collections import defaultdict
|
||||
|
||||
from homeassistant.core import NoEntitySpecifiedError
|
||||
from homeassistant.exceptions import NoEntitySpecifiedError
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, ATTR_HIDDEN,
|
||||
|
|
|
@ -18,6 +18,7 @@ import urllib.parse
|
|||
import requests
|
||||
|
||||
import homeassistant.core as ha
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.bootstrap as bootstrap
|
||||
|
||||
from homeassistant.const import (
|
||||
|
@ -84,12 +85,12 @@ class API(object):
|
|||
|
||||
except requests.exceptions.ConnectionError:
|
||||
_LOGGER.exception("Error connecting to server")
|
||||
raise ha.HomeAssistantError("Error connecting to server")
|
||||
raise HomeAssistantError("Error connecting to server")
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
error = "Timeout when talking to {}".format(self.host)
|
||||
_LOGGER.exception(error)
|
||||
raise ha.HomeAssistantError(error)
|
||||
raise HomeAssistantError(error)
|
||||
|
||||
def __repr__(self):
|
||||
return "API({}, {}, {})".format(
|
||||
|
@ -102,7 +103,7 @@ class HomeAssistant(ha.HomeAssistant):
|
|||
|
||||
def __init__(self, remote_api, local_api=None):
|
||||
if not remote_api.validate_api():
|
||||
raise ha.HomeAssistantError(
|
||||
raise HomeAssistantError(
|
||||
"Remote API at {}:{} not valid: {}".format(
|
||||
remote_api.host, remote_api.port, remote_api.status))
|
||||
|
||||
|
@ -121,7 +122,7 @@ class HomeAssistant(ha.HomeAssistant):
|
|||
# Ensure a local API exists to connect with remote
|
||||
if self.config.api is None:
|
||||
if not bootstrap.setup_component(self, 'api'):
|
||||
raise ha.HomeAssistantError(
|
||||
raise HomeAssistantError(
|
||||
'Unable to setup local API to receive events')
|
||||
|
||||
ha.create_timer(self)
|
||||
|
@ -132,7 +133,7 @@ class HomeAssistant(ha.HomeAssistant):
|
|||
# Setup that events from remote_api get forwarded to local_api
|
||||
# Do this after we fire START, otherwise HTTP is not started
|
||||
if not connect_remote_events(self.remote_api, self.config.api):
|
||||
raise ha.HomeAssistantError((
|
||||
raise HomeAssistantError((
|
||||
'Could not setup event forwarding from api {} to '
|
||||
'local api {}').format(self.remote_api, self.config.api))
|
||||
|
||||
|
@ -293,7 +294,7 @@ def validate_api(api):
|
|||
else:
|
||||
return APIStatus.UNKNOWN
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
return APIStatus.CANNOT_CONNECT
|
||||
|
||||
|
||||
|
@ -318,7 +319,7 @@ def connect_remote_events(from_api, to_api):
|
|||
|
||||
return False
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error setting up event forwarding")
|
||||
return False
|
||||
|
||||
|
@ -342,7 +343,7 @@ def disconnect_remote_events(from_api, to_api):
|
|||
|
||||
return False
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error removing an event forwarder")
|
||||
return False
|
||||
|
||||
|
@ -354,7 +355,7 @@ def get_event_listeners(api):
|
|||
|
||||
return req.json() if req.status_code == 200 else {}
|
||||
|
||||
except (ha.HomeAssistantError, ValueError):
|
||||
except (HomeAssistantError, ValueError):
|
||||
# ValueError if req.json() can't parse the json
|
||||
_LOGGER.exception("Unexpected result retrieving event listeners")
|
||||
|
||||
|
@ -371,7 +372,7 @@ def fire_event(api, event_type, data=None):
|
|||
_LOGGER.error("Error firing event: %d - %d",
|
||||
req.status_code, req.text)
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error firing event")
|
||||
|
||||
|
||||
|
@ -387,7 +388,7 @@ def get_state(api, entity_id):
|
|||
return ha.State.from_dict(req.json()) \
|
||||
if req.status_code == 200 else None
|
||||
|
||||
except (ha.HomeAssistantError, ValueError):
|
||||
except (HomeAssistantError, ValueError):
|
||||
# ValueError if req.json() can't parse the json
|
||||
_LOGGER.exception("Error fetching state")
|
||||
|
||||
|
@ -404,7 +405,7 @@ def get_states(api):
|
|||
return [ha.State.from_dict(item) for
|
||||
item in req.json()]
|
||||
|
||||
except (ha.HomeAssistantError, ValueError, AttributeError):
|
||||
except (HomeAssistantError, ValueError, AttributeError):
|
||||
# ValueError if req.json() can't parse the json
|
||||
_LOGGER.exception("Error fetching states")
|
||||
|
||||
|
@ -434,7 +435,7 @@ def set_state(api, entity_id, new_state, attributes=None):
|
|||
else:
|
||||
return True
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error setting state")
|
||||
|
||||
return False
|
||||
|
@ -457,7 +458,7 @@ def get_services(api):
|
|||
|
||||
return req.json() if req.status_code == 200 else {}
|
||||
|
||||
except (ha.HomeAssistantError, ValueError):
|
||||
except (HomeAssistantError, ValueError):
|
||||
# ValueError if req.json() can't parse the json
|
||||
_LOGGER.exception("Got unexpected services result")
|
||||
|
||||
|
@ -475,5 +476,5 @@ def call_service(api, domain, service, service_data=None):
|
|||
_LOGGER.error("Error calling service: %d - %s",
|
||||
req.status_code, req.text)
|
||||
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
_LOGGER.exception("Error calling service")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Helpers to install PyPi packages."""
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
@ -8,15 +9,15 @@ from . import environment as env
|
|||
INSTALL_USER = not env.is_virtual()
|
||||
|
||||
|
||||
def install_package(package, upgrade=False, user=INSTALL_USER):
|
||||
def install_package(package, upgrade=False, target=None):
|
||||
"""Install a package on PyPi. Accepts pip compatible package strings.
|
||||
Return boolean if install successfull."""
|
||||
# Not using 'import pip; pip.main([])' because it breaks the logger
|
||||
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
||||
if upgrade:
|
||||
args.append('--upgrade')
|
||||
if user:
|
||||
args.append('--user')
|
||||
if target:
|
||||
args += ['--target', os.path.abspath(target)]
|
||||
try:
|
||||
return 0 == subprocess.call(args)
|
||||
except subprocess.SubprocessError:
|
||||
|
|
2
pylintrc
2
pylintrc
|
@ -1,5 +1,5 @@
|
|||
[MASTER]
|
||||
ignore=external
|
||||
ignore=external,setup.py
|
||||
reports=no
|
||||
|
||||
# Reasons disabled:
|
||||
|
|
123
requirements.txt
123
requirements.txt
|
@ -1,119 +1,4 @@
|
|||
# Required for Home Assistant core
|
||||
requests>=2.0
|
||||
pyyaml>=3.11
|
||||
pytz>=2015.2
|
||||
|
||||
# Optional, needed for specific components
|
||||
|
||||
# Sun (sun)
|
||||
astral>=0.8.1
|
||||
|
||||
# Philips Hue library (lights.hue)
|
||||
phue>=0.8
|
||||
|
||||
# Limitlessled/Easybulb/Milight library (lights.limitlessled)
|
||||
ledcontroller>=1.0.7
|
||||
|
||||
# Chromecast bindings (media_player.cast)
|
||||
pychromecast>=0.6.10
|
||||
|
||||
# Keyboard (keyboard)
|
||||
pyuserinput>=0.1.9
|
||||
|
||||
# Tellstick bindings (*.tellstick)
|
||||
tellcore-py>=1.0.4
|
||||
|
||||
# Nmap bindings (device_tracker.nmap)
|
||||
python-libnmap>=0.6.3
|
||||
|
||||
# PushBullet bindings (notify.pushbullet)
|
||||
pushbullet.py>=0.7.1
|
||||
|
||||
# Nest Thermostat bindings (thermostat.nest)
|
||||
python-nest>=2.4.0
|
||||
|
||||
# Z-Wave (*.zwave)
|
||||
pydispatcher>=2.0.5
|
||||
|
||||
# ISY994 bindings (*.isy994)
|
||||
PyISY>=1.0.5
|
||||
|
||||
# PSutil (sensor.systemmonitor)
|
||||
psutil>=3.0.0
|
||||
|
||||
# Pushover bindings (notify.pushover)
|
||||
python-pushover>=0.2
|
||||
|
||||
# Transmission Torrent Client (*.transmission)
|
||||
transmissionrpc>=0.11
|
||||
|
||||
# OpenWeatherMap Web API (sensor.openweathermap)
|
||||
pyowm>=2.2.1
|
||||
|
||||
# XMPP Bindings (notify.xmpp)
|
||||
sleekxmpp>=1.3.1
|
||||
dnspython3>=1.12.0
|
||||
|
||||
# Blockchain (sensor.bitcoin)
|
||||
blockchain>=1.1.2
|
||||
|
||||
# MPD Bindings (media_player.mpd)
|
||||
python-mpd2>=0.5.4
|
||||
|
||||
# Hikvision (switch.hikvisioncam)
|
||||
hikvision>=0.4
|
||||
|
||||
# console log coloring
|
||||
colorlog>=2.6.0
|
||||
|
||||
# JSON-RPC interface (media_player.kodi)
|
||||
jsonrpc-requests>=0.1
|
||||
|
||||
# Forecast.io Bindings (sensor.forecast)
|
||||
python-forecastio>=1.3.3
|
||||
|
||||
# Firmata Bindings (*.arduino)
|
||||
PyMata==2.07a
|
||||
|
||||
# Rfxtrx sensor (sensor.rfxtrx)
|
||||
https://github.com/Danielhiversen/pyRFXtrx/archive/master.zip
|
||||
|
||||
# Mysensors
|
||||
https://github.com/theolind/pymysensors/archive/master.zip#egg=pymysensors-0.1
|
||||
|
||||
# Netgear (device_tracker.netgear)
|
||||
pynetgear>=0.3
|
||||
|
||||
# Netdisco (discovery)
|
||||
netdisco>=0.3
|
||||
|
||||
# Wemo (switch.wemo)
|
||||
pywemo>=0.2
|
||||
|
||||
# Wink (*.wink)
|
||||
https://github.com/balloob/python-wink/archive/master.zip#pywink>=0.1
|
||||
|
||||
# Slack notifier (notify.slack)
|
||||
slacker>=0.6.8
|
||||
|
||||
# Temper sensors (sensor.temper)
|
||||
https://github.com/rkabadi/temper-python/archive/master.zip
|
||||
|
||||
# PyEdimax
|
||||
https://github.com/rkabadi/pyedimax/archive/master.zip
|
||||
|
||||
# RPI-GPIO platform (*.rpi_gpio)
|
||||
RPi.GPIO >=0.5.11
|
||||
|
||||
# Adafruit temperature/humidity sensor
|
||||
# uncomment on a Raspberry Pi / Beaglebone
|
||||
#git+git://github.com/mala-zaba/Adafruit_Python_DHT
|
||||
|
||||
# PAHO MQTT Binding (mqtt)
|
||||
paho-mqtt>=1.1
|
||||
|
||||
# PyModbus (modbus)
|
||||
https://github.com/bashwork/pymodbus/archive/python3.zip#pymodbus>=1.2.0
|
||||
|
||||
# Verisure (verisure)
|
||||
https://github.com/persandstrom/python-verisure/archive/master.zip
|
||||
requests>=2,<3
|
||||
pyyaml>=3.11,<4
|
||||
pytz>=2015.4
|
||||
pip>=7.0.0
|
||||
|
|
121
requirements_all.txt
Normal file
121
requirements_all.txt
Normal file
|
@ -0,0 +1,121 @@
|
|||
# Required for Home Assistant core
|
||||
requests>=2,<3
|
||||
pyyaml>=3.11,<4
|
||||
pytz>=2015.4
|
||||
pip>=7.0.0
|
||||
|
||||
# Optional, needed for specific components
|
||||
|
||||
# Sun (sun)
|
||||
astral==0.8.1
|
||||
|
||||
# Philips Hue library (lights.hue)
|
||||
phue==0.8
|
||||
|
||||
# Limitlessled/Easybulb/Milight library (lights.limitlessled)
|
||||
ledcontroller==1.0.7
|
||||
|
||||
# Chromecast bindings (media_player.cast)
|
||||
pychromecast==0.6.10
|
||||
|
||||
# Keyboard (keyboard)
|
||||
pyuserinput==0.1.9
|
||||
|
||||
# Tellstick bindings (*.tellstick)
|
||||
tellcore-py==1.0.4
|
||||
|
||||
# Nmap bindings (device_tracker.nmap)
|
||||
python-libnmap==0.6.3
|
||||
|
||||
# PushBullet bindings (notify.pushbullet)
|
||||
pushbullet.py==0.7.1
|
||||
|
||||
# Nest Thermostat bindings (thermostat.nest)
|
||||
python-nest==2.4.0
|
||||
|
||||
# Z-Wave (*.zwave)
|
||||
pydispatcher==2.0.5
|
||||
|
||||
# ISY994 bindings (*.isy994)
|
||||
PyISY==1.0.5
|
||||
|
||||
# PSutil (sensor.systemmonitor)
|
||||
psutil==3.0.0
|
||||
|
||||
# Pushover bindings (notify.pushover)
|
||||
python-pushover==0.2
|
||||
|
||||
# Transmission Torrent Client (*.transmission)
|
||||
transmissionrpc==0.11
|
||||
|
||||
# OpenWeatherMap Web API (sensor.openweathermap)
|
||||
pyowm==2.2.1
|
||||
|
||||
# XMPP Bindings (notify.xmpp)
|
||||
sleekxmpp==1.3.1
|
||||
dnspython3==1.12.0
|
||||
|
||||
# Blockchain (sensor.bitcoin)
|
||||
blockchain==1.1.2
|
||||
|
||||
# MPD Bindings (media_player.mpd)
|
||||
python-mpd2==0.5.4
|
||||
|
||||
# Hikvision (switch.hikvisioncam)
|
||||
hikvision==0.4
|
||||
|
||||
# console log coloring
|
||||
colorlog==2.6.0
|
||||
|
||||
# JSON-RPC interface (media_player.kodi)
|
||||
jsonrpc-requests==0.1
|
||||
|
||||
# Forecast.io Bindings (sensor.forecast)
|
||||
python-forecastio==1.3.3
|
||||
|
||||
# Firmata Bindings (*.arduino)
|
||||
PyMata==2.07a
|
||||
|
||||
# Rfxtrx sensor (sensor.rfxtrx)
|
||||
https://github.com/Danielhiversen/pyRFXtrx/archive/ec7a1aaddf8270db6e5da1c13d58c1547effd7cf.zip
|
||||
|
||||
# Mysensors
|
||||
https://github.com/theolind/pymysensors/archive/35b87d880147a34107da0d40cb815d75e6cb4af7.zip
|
||||
|
||||
# Netgear (device_tracker.netgear)
|
||||
pynetgear==0.3
|
||||
|
||||
# Netdisco (discovery)
|
||||
netdisco==0.3
|
||||
|
||||
# Wemo (switch.wemo)
|
||||
pywemo==0.2
|
||||
|
||||
# Wink (*.wink)
|
||||
https://github.com/balloob/python-wink/archive/c2b700e8ca866159566ecf5e644d9c297f69f257.zip
|
||||
|
||||
# Slack notifier (notify.slack)
|
||||
slacker==0.6.8
|
||||
|
||||
# Temper sensors (sensor.temper)
|
||||
https://github.com/rkabadi/temper-python/archive/3dbdaf2d87b8db9a3cd6e5585fc704537dd2d09b.zip
|
||||
|
||||
# PyEdimax
|
||||
https://github.com/rkabadi/pyedimax/archive/365301ce3ff26129a7910c501ead09ea625f3700.zip
|
||||
|
||||
# RPI-GPIO platform (*.rpi_gpio)
|
||||
# Uncomment for Raspberry Pi
|
||||
# RPi.GPIO ==0.5.11
|
||||
|
||||
# Adafruit temperature/humidity sensor
|
||||
# uncomment on a Raspberry Pi / Beaglebone
|
||||
# http://github.com/mala-zaba/Adafruit_Python_DHT/archive/4101340de8d2457dd194bca1e8d11cbfc237e919.zip
|
||||
|
||||
# PAHO MQTT Binding (mqtt)
|
||||
paho-mqtt==1.1
|
||||
|
||||
# PyModbus (modbus)
|
||||
https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b612661.zip
|
||||
|
||||
# Verisure (verisure)
|
||||
https://github.com/persandstrom/python-verisure/archive/9873c4527f01b1ba1f72ae60f7f35854390d59be.zip
|
53
setup.py
Executable file
53
setup.py
Executable file
|
@ -0,0 +1,53 @@
|
|||
import os
|
||||
import re
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
PACKAGE_NAME = 'homeassistant'
|
||||
HERE = os.path.abspath(os.path.dirname(__file__))
|
||||
with open(os.path.join(HERE, PACKAGE_NAME, 'const.py')) as fp:
|
||||
VERSION = re.search("__version__ = ['\"]([^']+)['\"]\n", fp.read()).group(1)
|
||||
DOWNLOAD_URL = \
|
||||
'https://github.com/balloob/home-assistant/tarball/{}'.format(VERSION)
|
||||
|
||||
PACKAGES = find_packages() + \
|
||||
['homeassistant.external', 'homeassistant.external.noop',
|
||||
'homeassistant.external.nzbclients', 'homeassistant.external.vera']
|
||||
|
||||
PACKAGE_DATA = \
|
||||
{'homeassistant.components.frontend': ['index.html.template'],
|
||||
'homeassistant.components.frontend.www_static': ['*.*'],
|
||||
'homeassistant.components.frontend.www_static.images': ['*.*']}
|
||||
|
||||
REQUIRES = \
|
||||
[line.strip() for line in open('requirements.txt', 'r')]
|
||||
|
||||
setup(
|
||||
name=PACKAGE_NAME,
|
||||
version=VERSION,
|
||||
license='MIT License',
|
||||
url='https://home-assistant.io/',
|
||||
download_url=DOWNLOAD_URL,
|
||||
author='Paulus Schoutsen',
|
||||
author_email='paulus@paulusschoutsen.nl',
|
||||
description='Open-source home automation platform running on Python 3.',
|
||||
packages=PACKAGES,
|
||||
include_package_data=True,
|
||||
package_data=PACKAGE_DATA,
|
||||
zip_safe=False,
|
||||
platforms='any',
|
||||
install_requires=REQUIRES,
|
||||
keywords=['home', 'automation'],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'hass = homeassistant.__main__:main'
|
||||
]
|
||||
},
|
||||
classifiers=[
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Topic :: Home Automation'
|
||||
]
|
||||
)
|
|
@ -16,6 +16,8 @@ from datetime import datetime
|
|||
import pytz
|
||||
|
||||
import homeassistant.core as ha
|
||||
from homeassistant.exceptions import (
|
||||
HomeAssistantError, InvalidEntityFormatError)
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.event import track_state_change
|
||||
from homeassistant.const import (
|
||||
|
@ -41,7 +43,7 @@ class TestHomeAssistant(unittest.TestCase):
|
|||
""" Stop down stuff we started. """
|
||||
try:
|
||||
self.hass.stop()
|
||||
except ha.HomeAssistantError:
|
||||
except HomeAssistantError:
|
||||
# Already stopped after the block till stopped test
|
||||
pass
|
||||
|
||||
|
@ -250,7 +252,7 @@ class TestState(unittest.TestCase):
|
|||
def test_init(self):
|
||||
""" Test state.init """
|
||||
self.assertRaises(
|
||||
ha.InvalidEntityFormatError, ha.State,
|
||||
InvalidEntityFormatError, ha.State,
|
||||
'invalid_entity_format', 'test_state')
|
||||
|
||||
def test_domain(self):
|
||||
|
@ -489,18 +491,24 @@ class TestConfig(unittest.TestCase):
|
|||
|
||||
def test_config_dir_set_correct(self):
|
||||
""" Test config dir set correct. """
|
||||
self.assertEqual(os.path.join(os.getcwd(), "config"),
|
||||
data_dir = os.getenv('APPDATA') if os.name == "nt" \
|
||||
else os.path.expanduser('~')
|
||||
self.assertEqual(os.path.join(data_dir, ".homeassistant"),
|
||||
self.config.config_dir)
|
||||
|
||||
def test_path_with_file(self):
|
||||
""" Test get_config_path method. """
|
||||
self.assertEqual(os.path.join(os.getcwd(), "config", "test.conf"),
|
||||
data_dir = os.getenv('APPDATA') if os.name == "nt" \
|
||||
else os.path.expanduser('~')
|
||||
self.assertEqual(os.path.join(data_dir, ".homeassistant", "test.conf"),
|
||||
self.config.path("test.conf"))
|
||||
|
||||
def test_path_with_dir_and_file(self):
|
||||
""" Test get_config_path method. """
|
||||
data_dir = os.getenv('APPDATA') if os.name == "nt" \
|
||||
else os.path.expanduser('~')
|
||||
self.assertEqual(
|
||||
os.path.join(os.getcwd(), "config", "dir", "test.conf"),
|
||||
os.path.join(data_dir, ".homeassistant", "dir", "test.conf"),
|
||||
self.config.path("dir", "test.conf"))
|
||||
|
||||
def test_temperature_not_convert_if_no_preference(self):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue