Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V1.1.3 #45

Merged
merged 4 commits into from
Nov 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "ludeeus/integration_blueprint",
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"postCreateCommand": "scripts/setup",
"forwardPorts": [
8123
],
"portsAttributes": {
"8123": {
"label": "Home Assistant",
"onAutoForward": "notify"
}
},
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"github.vscode-pull-request-github",
"ms-python.python",
"ms-python.vscode-pylance",
"ryanluker.vscode-coverage-gutters"
],
"settings": {
"files.eol": "\n",
"editor.tabSize": 4,
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.formatOnType": false,
"files.trimTrailingWhitespace": true,
"python.analysis.typeCheckingMode": "basic",
"python.analysis.autoImportCompletions": true,
"python.defaultInterpreterPath": "/usr/local/bin/python",
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
}
},
"remoteUser": "vscode",
"features": {}
}
7 changes: 0 additions & 7 deletions .devcontainer/configuration.yaml

This file was deleted.

30 changes: 0 additions & 30 deletions .devcontainer/devcontainer.json

This file was deleted.

19 changes: 18 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
__pycache__
# artifacts
__pycache__
.pytest*
*.egg-info
*/build/*
*/dist/*


# misc
.coverage
.vscode
coverage.xml
.ruff_cache


# Home Assistant configuration
config/*
!config/configuration.yaml
26 changes: 26 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The contents of this file is based on https://github.com/home-assistant/core/blob/dev/pyproject.toml

target-version = "py312"

[lint]
select = [
"ALL",
]

ignore = [
"ANN101", # Missing type annotation for `self` in method
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed
"D203", # no-blank-line-before-class (incompatible with formatter)
"D212", # multi-line-summary-first-line (incompatible with formatter)
"COM812", # incompatible with formatter
"ISC001", # incompatible with formatter
]

[lint.flake8-pytest-style]
fixture-parentheses = false

[lint.pyupgrade]
keep-runtime-typing = true

[lint.mccabe]
max-complexity = 25
22 changes: 2 additions & 20 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,9 @@
"version": "2.0.0",
"tasks": [
{
"label": "Run Home Assistant on port 9123",
"label": "Run Home Assistant on port 8123",
"type": "shell",
"command": "container start",
"problemMatcher": []
},
{
"label": "Run Home Assistant configuration against /config",
"type": "shell",
"command": "container check",
"problemMatcher": []
},
{
"label": "Upgrade Home Assistant to latest dev",
"type": "shell",
"command": "container install",
"problemMatcher": []
},
{
"label": "Install a spesific version of Home Assistant",
"type": "shell",
"command": "container set-version",
"command": "scripts/develop",
"problemMatcher": []
}
]
Expand Down
12 changes: 12 additions & 0 deletions config/configuration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# https://www.home-assistant.io/integrations/default_config/
default_config:

# https://www.home-assistant.io/integrations/homeassistant/
homeassistant:
debug: true

# https://www.home-assistant.io/integrations/logger/
logger:
default: info
logs:
custom_components.integration_blueprint: debug
7 changes: 4 additions & 3 deletions custom_components/eskom_loadshedding/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
For more details about this integration, please refer to
https://github.com/swartjean/ha-eskom-loadshedding
"""

import asyncio
from datetime import timedelta
import logging
from datetime import timedelta

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
Expand All @@ -16,8 +17,8 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import (
CONF_SCAN_PERIOD,
CONF_API_KEY,
CONF_SCAN_PERIOD,
DEFAULT_SCAN_PERIOD,
DOMAIN,
PLATFORMS,
Expand Down Expand Up @@ -57,7 +58,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):

hass.data[DOMAIN][entry.entry_id] = coordinator

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

if not entry.update_listeners:
entry.add_update_listener(async_reload_entry)
Expand Down
23 changes: 13 additions & 10 deletions custom_components/eskom_loadshedding/calendar.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
"""Sensor platform for Eskom Loadshedding Interface."""
from datetime import datetime, timedelta

import re
from datetime import datetime, timedelta

from homeassistant.components.calendar import CalendarEntity, CalendarEvent
from homeassistant.core import callback

from .const import (
DEFAULT_CALENDAR_SCAN_PERIOD,
DOMAIN,
LOCAL_EVENTS_ID,
LOCAL_EVENTS_NAME,
LOCAL_SCHEDULE_ID,
LOCAL_SCHEDULE_NAME,
DEFAULT_CALENDAR_SCAN_PERIOD,
)
from .entity import EskomEntity

Expand Down Expand Up @@ -62,7 +63,8 @@ def name(self):

@property
def should_poll(self) -> bool:
"""Enable polling for the entity.
"""
Enable polling for the entity.

The coordinator is used to query the API, but polling is used to update
the entity state more frequently.
Expand Down Expand Up @@ -112,11 +114,11 @@ async def async_get_events(
)
for event in events
]
else:
return []
return []

async def async_update(self) -> None:
"""Disable update behavior.
"""
Disable update behavior.
Event updates are performed through the coordinator callback.
This is simply used to evaluate the entity state
"""
Expand Down Expand Up @@ -145,7 +147,8 @@ def name(self):

@property
def should_poll(self) -> bool:
"""Enable polling for the entity.
"""
Enable polling for the entity.

The coordinator is used to query the API, but polling is used to update
the entity state more frequently.
Expand Down Expand Up @@ -215,11 +218,11 @@ async def async_get_events(
)

return calendar_events
else:
return []
return []

async def async_update(self) -> None:
"""Disable update behavior.
"""
Disable update behavior.
Event updates are performed through the coordinator callback.
This is simply used to evaluate the entity state
"""
20 changes: 8 additions & 12 deletions custom_components/eskom_loadshedding/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""Adds config flow for the Eskom Loadshedding Interface."""

from collections import OrderedDict

import voluptuous as vol
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant.helpers.selector import selector
import voluptuous as vol

from .const import ( # pylint: disable=unused-import
CONF_SCAN_PERIOD,
CONF_API_KEY,
CONF_SCAN_PERIOD,
DEFAULT_SCAN_PERIOD,
DOMAIN,
MIN_SCAN_PERIOD,
Expand Down Expand Up @@ -41,8 +42,7 @@ async def async_step_user(self, user_input=None):
# Proceed to the next configuration step
return await self.async_step_area_search()

else:
self._errors["base"] = "auth"
self._errors["base"] = "auth"

return await self._show_user_config_form(user_input)

Expand Down Expand Up @@ -91,8 +91,7 @@ async def async_step_area_selection(self, user_input=None):
CONF_API_KEY: self.api_key,
},
)
else:
self._errors["base"] = "no_area_selection"
self._errors["base"] = "no_area_selection"

# Reformat the areas as label/value pairs for the selector
area_options = [
Expand Down Expand Up @@ -146,8 +145,7 @@ async def validate_key(self, api_key: str) -> bool:
data = await interface.async_query_api("/api_allowance")
if "error" in data:
return False
else:
return True
return True
except Exception: # pylint: disable=broad-except
pass
return False
Expand Down Expand Up @@ -187,8 +185,7 @@ async def async_step_user(self, user_input=None):
# Update all options
self.options.update(user_input)
return await self._update_options()
else:
self._errors["base"] = "auth"
self._errors["base"] = "auth"

data_schema = OrderedDict()
data_schema[
Expand Down Expand Up @@ -226,8 +223,7 @@ async def validate_key(self, api_key: str) -> bool:

if "error" in data:
return False
else:
return True
return True
except Exception: # pylint: disable=broad-except
pass
return False
3 changes: 2 additions & 1 deletion custom_components/eskom_loadshedding/const.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""Constants for eskom loadshedding interface"""

# Base component constants
NAME = "Eskom Loadshedding Interface"
DEVICE_NAME = "Loadshedding"
DOMAIN = "eskom_loadshedding"
DOMAIN_DATA = f"{DOMAIN}_data"
VERSION = "1.1.2"
VERSION = "1.1.3"

ISSUE_URL = "https://github.com/swartjean/ha-eskom-loadshedding/issues"

Expand Down
1 change: 1 addition & 0 deletions custom_components/eskom_loadshedding/entity.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""EskomEntity class"""

from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DEVICE_NAME, DOMAIN, VERSION
Expand Down
7 changes: 4 additions & 3 deletions custom_components/eskom_loadshedding/eskom_interface.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import logging
import socket

Expand All @@ -25,14 +24,16 @@ def __init__(
}

async def async_query_api(self, endpoint: str, payload: dict = None):
"""Queries a given endpoint on the EskomSePush API with the specified payload
"""
Queries a given endpoint on the EskomSePush API with the specified payload

Args:
endpoint (string): The endpoint of the EskomSePush API
payload (dict, optional): The parameters to apply to the query. Defaults to None.

Returns:
The response object from the request

"""
query_url = self.base_url + endpoint
try:
Expand All @@ -52,7 +53,7 @@ async def async_query_api(self, endpoint: str, payload: dict = None):
# Re-raise the ClientResponseError to allow checking for valid headers during config
# These will be caught by the DataUpdateCoordinator
raise
except asyncio.TimeoutError as exception:
except TimeoutError as exception:
_LOGGER.error(
"Timeout fetching information from %s: %s",
query_url,
Expand Down
Loading
Loading