Skip to content

Commit

Permalink
Pyling code improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
RogerSelwyn committed Feb 11, 2022
1 parent 1e95e1d commit 4e5f2f7
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 102 deletions.
57 changes: 39 additions & 18 deletions custom_components/o365/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,27 @@
from homeassistant.helpers.network import get_url
from O365 import Account, FileSystemTokenBackend

from .const import (AUTH_CALLBACK_NAME, AUTH_CALLBACK_PATH,
AUTH_CALLBACK_PATH_ALT, CONF_ALT_CONFIG, CONF_CALENDARS,
CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_EMAIL_SENSORS,
CONF_QUERY_SENSORS, CONF_TRACK_NEW, CONFIG_SCHEMA,
CONFIGURATOR_DESCRIPTION, CONFIGURATOR_LINK_NAME,
CONFIGURATOR_SUBMIT_CAPTION, DEFAULT_CACHE_PATH,
DEFAULT_NAME, DOMAIN, SCOPE, TOKEN_FILENAME)
from .const import (
AUTH_CALLBACK_NAME,
AUTH_CALLBACK_PATH,
AUTH_CALLBACK_PATH_ALT,
CONF_ALT_CONFIG,
CONF_CALENDARS,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_EMAIL_SENSORS,
CONF_QUERY_SENSORS,
CONF_TRACK_NEW,
CONFIG_SCHEMA,
CONFIGURATOR_DESCRIPTION,
CONFIGURATOR_LINK_NAME,
CONFIGURATOR_SUBMIT_CAPTION,
DEFAULT_CACHE_PATH,
DEFAULT_NAME,
DOMAIN,
SCOPE,
TOKEN_FILENAME,
)
from .utils import build_config_file_path, validate_permissions

_LOGGER = logging.getLogger(__name__)
Expand All @@ -34,7 +48,9 @@ async def async_setup(hass, config):
else:
callback_url = f"{get_url(hass, prefer_external=True)}{AUTH_CALLBACK_PATH}"
token_path = build_config_file_path(hass, DEFAULT_CACHE_PATH)
token_backend = FileSystemTokenBackend(token_path=token_path, token_filename=TOKEN_FILENAME)
token_backend = FileSystemTokenBackend(
token_path=token_path, token_filename=TOKEN_FILENAME
)

account = Account(credentials, token_backend=token_backend, timezone="UTC")
is_authenticated = account.is_authenticated
Expand All @@ -43,11 +59,12 @@ async def async_setup(hass, config):
do_setup(hass, conf, account)
else:
url, state = account.con.get_authorization_url(
requested_scopes=SCOPE,
redirect_uri=callback_url
requested_scopes=SCOPE, redirect_uri=callback_url
)
_LOGGER.info("no token; requesting authorization")
callback_view = O365AuthCallbackView(conf, None, account, state, callback_url, hass)
callback_view = O365AuthCallbackView(
conf, None, account, state, callback_url, hass
)
hass.http.register_view(callback_view)
if alt_config:
request_configuration_alt(hass, url, callback_view)
Expand Down Expand Up @@ -77,9 +94,15 @@ def do_setup(hass, config, account):
CONF_QUERY_SENSORS: config.get(CONF_QUERY_SENSORS, []),
CONF_TRACK_NEW: config.get(CONF_TRACK_NEW, True),
}
hass.async_create_task(discovery.async_load_platform(hass, "calendar", DOMAIN, {}, config))
hass.async_create_task(discovery.async_load_platform(hass, "notify", DOMAIN, {}, config))
hass.async_create_task(discovery.async_load_platform(hass, "sensor", DOMAIN, {}, config))
hass.async_create_task(
discovery.async_load_platform(hass, "calendar", DOMAIN, {}, config)
)
hass.async_create_task(
discovery.async_load_platform(hass, "notify", DOMAIN, {}, config)
)
hass.async_create_task(
discovery.async_load_platform(hass, "sensor", DOMAIN, {}, config)
)


def request_configuration(hass, url, callback_view):
Expand Down Expand Up @@ -144,7 +167,7 @@ async def get(self, request):
self.account.con.request_token,
url,
state=self.state,
redirect_uri=self.callback
redirect_uri=self.callback,
)
)
domain_data = self._hass.data[DOMAIN]
Expand All @@ -163,9 +186,7 @@ def alt_callback(self, data):
url = [v for k, v in data.items()][0]

result = self.account.con.request_token(
url,
state=self.state,
redirect_uri=AUTH_CALLBACK_PATH_ALT
url, state=self.state, redirect_uri=AUTH_CALLBACK_PATH_ALT
)
if not result:
self.configurator.notify_errors(
Expand Down
104 changes: 76 additions & 28 deletions custom_components/o365/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,52 @@
from datetime import datetime, timedelta
from operator import attrgetter, itemgetter

from homeassistant.components.calendar import (CalendarEventDevice,
calculate_offset,
is_offset_reached)
from homeassistant.components.calendar import (
CalendarEventDevice,
calculate_offset,
is_offset_reached,
)
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.util import Throttle, dt

from .const import (CALENDAR_ENTITY_ID_FORMAT, CALENDAR_SERVICE_CREATE_SCHEMA,
CALENDAR_SERVICE_MODIFY_SCHEMA,
CALENDAR_SERVICE_REMOVE_SCHEMA,
CALENDAR_SERVICE_RESPOND_SCHEMA, CONF_DEVICE_ID,
CONF_ENTITIES, CONF_HOURS_BACKWARD_TO_GET,
CONF_HOURS_FORWARD_TO_GET, CONF_MAX_RESULTS, CONF_NAME,
CONF_SEARCH, CONF_TRACK, CONF_TRACK_NEW, DEFAULT_OFFSET,
DOMAIN, MIN_TIME_BETWEEN_UPDATES, YAML_CALENDARS)
from .utils import (add_call_data_to_event, build_config_file_path, clean_html,
format_event_data, load_calendars, update_calendar_file)
from .const import (
CALENDAR_ENTITY_ID_FORMAT,
CALENDAR_SERVICE_CREATE_SCHEMA,
CALENDAR_SERVICE_MODIFY_SCHEMA,
CALENDAR_SERVICE_REMOVE_SCHEMA,
CALENDAR_SERVICE_RESPOND_SCHEMA,
CONF_DEVICE_ID,
CONF_ENTITIES,
CONF_HOURS_BACKWARD_TO_GET,
CONF_HOURS_FORWARD_TO_GET,
CONF_MAX_RESULTS,
CONF_NAME,
CONF_SEARCH,
CONF_TRACK,
CONF_TRACK_NEW,
DEFAULT_OFFSET,
DOMAIN,
MIN_TIME_BETWEEN_UPDATES,
YAML_CALENDARS,
)
from .utils import (
add_call_data_to_event,
build_config_file_path,
clean_html,
format_event_data,
load_calendars,
update_calendar_file,
)

_LOGGER = logging.getLogger(__name__)


def setup_platform(hass, config, add_devices, discovery_info=None):
def setup_platform(
hass, config, add_devices, discovery_info=None
): # pylint: disable=unused-argument
"""Set up the O365 platform."""
if discovery_info is None:
return
return None

account = hass.data[DOMAIN]["account"]
track_new = hass.data[DOMAIN][CONF_TRACK_NEW]
Expand All @@ -45,16 +67,28 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
for entity in calendar.get(CONF_ENTITIES):
if not entity[CONF_TRACK]:
continue
entity_id = generate_entity_id(CALENDAR_ENTITY_ID_FORMAT, entity.get(CONF_DEVICE_ID), hass=hass)
entity_id = generate_entity_id(
CALENDAR_ENTITY_ID_FORMAT, entity.get(CONF_DEVICE_ID), hass=hass
)
cal = O365CalendarEventDevice(hass, account, cal_id, entity, entity_id)
devices.append(cal)
add_devices(devices, True)

hass.services.register(DOMAIN, "modify_calendar_event", calendar_services.modify_calendar_event)
hass.services.register(DOMAIN, "create_calendar_event", calendar_services.create_calendar_event)
hass.services.register(DOMAIN, "remove_calendar_event", calendar_services.remove_calendar_event)
hass.services.register(DOMAIN, "respond_calendar_event", calendar_services.respond_calendar_event)
hass.services.register(DOMAIN, "scan_for_calendars", calendar_services.scan_for_calendars)
hass.services.register(
DOMAIN, "modify_calendar_event", calendar_services.modify_calendar_event
)
hass.services.register(
DOMAIN, "create_calendar_event", calendar_services.create_calendar_event
)
hass.services.register(
DOMAIN, "remove_calendar_event", calendar_services.remove_calendar_event
)
hass.services.register(
DOMAIN, "respond_calendar_event", calendar_services.respond_calendar_event
)
hass.services.register(
DOMAIN, "scan_for_calendars", calendar_services.scan_for_calendars
)

return True

Expand Down Expand Up @@ -89,7 +123,9 @@ def extra_state_attributes(self):
"""Device state property."""
if self._event:
return {
"all_day": self._event.get("all_day", False) if self.data.event is not None else False,
"all_day": self._event.get("all_day", False)
if self.data.event is not None
else False,
"offset_reached": self._offset_reached,
"data": self._data_attribute,
}
Expand Down Expand Up @@ -126,7 +162,9 @@ async def async_update(self):
datetime.now() + timedelta(hours=self.end_offset),
)
)
self._data_attribute = [format_event_data(x, self.data.calendar.calendar_id) for x in events]
self._data_attribute = [
format_event_data(x, self.data.calendar.calendar_id) for x in events
]
self._data_attribute.sort(key=itemgetter("start"))
self._event = event

Expand Down Expand Up @@ -160,11 +198,17 @@ def o365_get_events(self, start_date, end_date):
query.chain("and").on_attribute("end").less_equal(end_date)
if self.search is not None:
query.chain("and").on_attribute("subject").contains(self.search)
return self.calendar.get_events(limit=self.limit, query=query, include_recurring=True)
return self.calendar.get_events(
limit=self.limit, query=query, include_recurring=True
)

async def async_get_events(self, hass, start_date, end_date):
"""Get the via async."""
vevent_list = list(await hass.async_add_executor_job(self.o365_get_events, start_date, end_date))
vevent_list = list(
await hass.async_add_executor_job(
self.o365_get_events, start_date, end_date
)
)
vevent_list.sort(key=attrgetter("start"))
event_list = []
for event in vevent_list:
Expand Down Expand Up @@ -217,7 +261,9 @@ def is_all_day(vevent):
@staticmethod
def is_over(vevent):
"""Is it over."""
return dt.now() >= O365CalendarData.to_datetime(O365CalendarData.get_end_date(vevent))
return dt.now() >= O365CalendarData.to_datetime(
O365CalendarData.get_end_date(vevent)
)

@staticmethod
def get_hass_date(obj, is_all_day):
Expand Down Expand Up @@ -303,12 +349,14 @@ def respond_calendar_event(self, call):
event.accept_event(event_data.get("message"), send_response=send_response)

elif response.lower() == "tentative":
event.accept_event(event_data.get("message"), tentatively=True, send_response=send_response)
event.accept_event(
event_data.get("message"), tentatively=True, send_response=send_response
)

elif response.lower() == "decline":
event.decline_event(event_data.get("message"), send_response=send_response)

def scan_for_calendars(self, call):
def scan_for_calendars(self, call): # pylint: disable=unused-argument
"""Scan for new calendars."""
calendars = self.schedule.list_calendars()
for calendar in calendars:
Expand Down
30 changes: 20 additions & 10 deletions custom_components/o365/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant.components.notify import (ATTR_DATA, ATTR_MESSAGE,
ATTR_TARGET, ATTR_TITLE)
from homeassistant.components.notify import (
ATTR_DATA,
ATTR_MESSAGE,
ATTR_TARGET,
ATTR_TITLE,
)
from homeassistant.config import get_default_config_dir
from homeassistant.const import CONF_NAME
from O365.calendar import AttendeeType, EventSensitivity, EventShowAs
from O365.calendar import AttendeeType # pylint: disable=no-name-in-module
from O365.calendar import EventSensitivity # pylint: disable=no-name-in-module
from O365.calendar import EventShowAs # pylint: disable=no-name-in-module


class EventResponse(Enum):
"""Event response."""

Accept = "accept"
Tentative = "tentative"
Decline = "decline"
Accept = "accept" # pylint: disable=invalid-name
Tentative = "tentative" # pylint: disable=invalid-name
Decline = "decline" # pylint: disable=invalid-name


ATTR_ATTACHMENTS = "attachments"
Expand Down Expand Up @@ -51,7 +57,7 @@ class EventResponse(Enum):
CONF_CALENDAR_NAME = "calendar_name"
CONF_CALENDARS = "calendars"
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
CONF_CLIENT_SECRET = "client_secret" # nosec
CONF_DEVICE_ID = "device_id"
CONF_EMAIL_SENSORS = "email_sensor"
CONF_IGNORE_AVAILABILITY = "ignore_availability"
Expand All @@ -75,12 +81,14 @@ class EventResponse(Enum):
CONF_SUBJECT_IS = "subject_is"
CONF_TRACK_NEW = "track_new_calendar"
CONFIG_BASE_DIR = get_default_config_dir()
CONFIGURATOR_DESCRIPTION = "To link your O365 account, click the link, login, and authorize:"
CONFIGURATOR_DESCRIPTION = (
"To link your O365 account, click the link, login, and authorize:"
)
CONFIGURATOR_LINK_NAME = "Link O365 account"
CONFIGURATOR_SUBMIT_CAPTION = "I authorized successfully"
DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
DEFAULT_CACHE_PATH = ".O365-token-cache"
TOKEN_FILENAME = "o365.token"
TOKEN_FILENAME = "o365.token" # nosec
DEFAULT_HOURS_BACKWARD_TO_GET = 0
DEFAULT_HOURS_FORWARD_TO_GET = 24
DEFAULT_NAME = "O365"
Expand Down Expand Up @@ -243,7 +251,9 @@ class EventResponse(Enum):
CALENDAR_DEVICE_SCHEMA = vol.Schema(
{
vol.Required(CONF_CAL_ID): cv.string,
vol.Required(CONF_ENTITIES, None): vol.All(cv.ensure_list, [SINGLE_CALSEARCH_CONFIG]),
vol.Required(CONF_ENTITIES, None): vol.All(
cv.ensure_list, [SINGLE_CALSEARCH_CONFIG]
),
},
extra=vol.ALLOW_EXTRA,
)
28 changes: 15 additions & 13 deletions custom_components/o365/notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
_LOGGER = logging.getLogger(__name__)


async def async_get_service(hass, config, discovery_info=None):
async def async_get_service(
hass, config, discovery_info=None
): # pylint: disable=unused-argument
"""Get the service."""
if discovery_info is None:
return
Expand Down Expand Up @@ -72,7 +74,7 @@ def send_message(self, message="", **kwargs):
if isinstance(photos, str):
photos = [photos]

m = account.new_message()
new_message = account.new_message()
if is_html or photos:
message = f"""
<html>
Expand All @@ -83,8 +85,8 @@ def send_message(self, message="", **kwargs):
message += f'<br><img src="{photo}">'
else:
photo = get_ha_filepath(photo)
m.attachments.add(photo)
att = m.attachments[-1]
new_message.attachments.add(photo)
att = new_message.attachments[-1]
att.is_inline = True
att.content_id = "1"
message += f'<br><img src="cid:{1}">'
Expand All @@ -93,16 +95,16 @@ def send_message(self, message="", **kwargs):
attachments = [get_ha_filepath(x) for x in attachments]
if attachments and zip_attachments:
z_file = zip_files(attachments, zip_name)
m.attachments.add(z_file)
new_message.attachments.add(z_file)
cleanup_files.append(z_file)

else:
for attachment in attachments:
m.attachments.add(attachment)

m.to.add(target)
m.subject = title
m.body = message
m.send()
for x in cleanup_files:
os.remove(x)
new_message.attachments.add(attachment)

new_message.to.add(target)
new_message.subject = title
new_message.body = message
new_message.send()
for filename in cleanup_files:
os.remove(filename)
Loading

0 comments on commit 4e5f2f7

Please sign in to comment.