Skip to content

Commit

Permalink
Add pre-commit configuration (#33)
Browse files Browse the repository at this point in the history
* add hassfest

* add recorder dependency

* fix manifest

* add pre-commit

* add pre-commit

* format the source code

* format the source code

---------

Co-authored-by: Konstantin Deev <konstantinde@zillowgroup.com>
  • Loading branch information
kdeyev and Konstantin Deev authored Aug 19, 2023
1 parent 38feefd commit 68f75e1
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 69 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/hassfest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Validate with hassfest

on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'

jobs:
validate:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v3"
- uses: "home-assistant/actions/hassfest@master"
15 changes: 15 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: pre-commit

on:
push:
pull_request:
schedule:
- cron: '0 0 * * *'

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v3
- uses: pre-commit/action@v3.0.0
24 changes: 24 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: trailing-whitespace
- id: end-of-file-fixer
- id: mixed-line-ending
args: ["--fix=lf"]
# - repo: https://github.com/astral-sh/ruff-pre-commit
# rev: v0.0.284
# hooks:
# - id: ruff
# args: ["--fix"]

- repo: https://github.com/psf/black
rev: 23.7.0
hooks:
- id: black

- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Add `https://github.com/kdeyev/eyeonwater` as Repository and select the "Integra

2. Add EyeOnWater integration following [HACS instructions](https://github.com/hacs/integration)

Follow the configuration dialog:
Follow the configuration dialog:
- Choose EyeOnWater hostname (choose eyeonwater.com unless you are in Canada).
- Choose the measurement system you prefer to use. "Imperial" will create a water sensor counting gallons, "Metric" will create a water sensor counting cubic meters.
- Use your username and password, which you use to log in on eyeonwater.com
Expand Down
19 changes: 12 additions & 7 deletions custom_components/eyeonwater/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
try:
await eye_on_water_data.client.authenticate()
except EyeOnWaterAuthError:
_LOGGER.error("Username or password was not accepted")
_LOGGER.exception("Username or password was not accepted")
return False
except asyncio.TimeoutError as error:
raise ConfigEntryNotReady from error

# Fetch actual meter_info for all meters
try:
await eye_on_water_data.setup()
await eye_on_water_data.read_meters()
except Exception as e:
_LOGGER.error(f"Reading meters failed: {e}")
raise e
message = f"Reading meters failed: {e}"
_LOGGER.exception(message)
raise

try:
await eye_on_water_data.import_historical_data(days_to_load=30)
except Exception as e:
_LOGGER.error(f"Loading historical data failed: {e}")

message = f"Loading historical data failed: {e}"
_LOGGER.exception(message)

for meter in eye_on_water_data.meters:
_LOGGER.debug(meter.meter_uuid, meter.meter_id, meter.meter_info)
Expand All @@ -67,7 +69,10 @@ async def async_update_data():
update_method=async_update_data,
update_interval=SCAN_INTERVAL,
request_refresh_debouncer=debounce.Debouncer(
hass, _LOGGER, cooldown=DEBOUNCE_COOLDOWN, immediate=True
hass,
_LOGGER,
cooldown=DEBOUNCE_COOLDOWN,
immediate=True,
),
)

Expand All @@ -77,7 +82,7 @@ async def async_update_data():
DATA_SMART_METER: eye_on_water_data,
}

watch_task = asyncio.create_task(coordinator.async_refresh())
asyncio.create_task(coordinator.async_refresh())
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

return True
Expand Down
1 change: 1 addition & 0 deletions custom_components/eyeonwater/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
),
]


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the EyeOnWater sensors."""
coordinator = hass.data[DOMAIN][config_entry.entry_id][DATA_COORDINATOR]
Expand Down
14 changes: 7 additions & 7 deletions custom_components/eyeonwater/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Config flow for EyeOnWater integration."""
import asyncio
import contextlib
import logging
from typing import Any

Expand All @@ -24,12 +23,13 @@
{
vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
}
},
)


def create_account_from_config(
hass: core.HomeAssistant, data: dict[str, Any]
hass: core.HomeAssistant,
data: dict[str, Any],
) -> Account:
"""Create account login from config."""
CountryCode = hass.config.country
Expand All @@ -43,13 +43,12 @@ def create_account_from_config(
username = data[CONF_USERNAME]
password = data[CONF_PASSWORD]

account = Account(
return Account(
eow_hostname=eow_hostname,
username=username,
password=password,
metric_measurement_system=metric_measurement_system,
)
return account


async def validate_input(hass: core.HomeAssistant, data):
Expand Down Expand Up @@ -79,7 +78,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):

async def async_step_user(self, user_input=None):
"""Handle the initial step."""

errors = {}
if user_input is not None:
try:
Expand All @@ -100,7 +98,9 @@ async def async_step_user(self, user_input=None):
return self.async_create_entry(title=info["title"], data=user_input)

return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors
step_id="user",
data_schema=DATA_SCHEMA,
errors=errors,
)


Expand Down
38 changes: 22 additions & 16 deletions custom_components/eyeonwater/coordinator.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
"""EyeOnWater coordinator."""
import logging
import datetime
from typing import List
import logging

from homeassistant.components.recorder.models import StatisticData, StatisticMetaData
from homeassistant.components.recorder.statistics import async_import_statistics
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.update_coordinator import UpdateFailed
from homeassistant.components.recorder.models import StatisticData, StatisticMetaData
from homeassistant.components.recorder.statistics import async_import_statistics

from .const import WATER_METER_NAME

from .config_flow import create_account_from_config
from .eow import (
Account,
Client,
Meter,
EyeOnWaterAPIError,
EyeOnWaterAuthError,
EyeOnWaterResponseIsEmpty,
Meter,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -58,7 +55,6 @@ async def read_meters(self):

async def import_historical_data(self, days_to_load: int = 2):
"""Import historical data for today and past N days."""

for meter in self.meters:
statistics = await self.get_historical_data(meter, days_to_load)

Expand All @@ -77,12 +73,16 @@ async def import_historical_data(self, days_to_load: int = 2):
async_import_statistics(self.hass, metadata, statistics)

async def get_historical_data(
self, meter: Meter, days_to_load: int = 2
) -> List[StatisticData]:
self,
meter: Meter,
days_to_load: int = 2,
) -> list[StatisticData]:
"""Retrieve historical data for today and past N days."""

today = datetime.datetime.now().replace(
hour=0, minute=0, second=0, microsecond=0
hour=0,
minute=0,
second=0,
microsecond=0,
)

date_list = [today - datetime.timedelta(days=x) for x in range(0, days_to_load)]
Expand All @@ -92,16 +92,22 @@ async def get_historical_data(
else:
units = meter.native_unit_of_measurement.upper()

_LOGGER.info(
f"adding historical statistics for {meter.meter_id} on {date_list} with units {units}"
message = (
f"adding historical statistics for {meter.meter_id} on {date_list} with units {units}",
)
_LOGGER.info(message)

statistics = []

for date in date_list:
_LOGGER.debug(
f"requesting historical statistics for {meter.meter_id} on {date} with units {units}",
)
try:
data = await meter.get_historical_data(
date=date, units=units, client=self.client
date=date,
units=units,
client=self.client,
)
except EyeOnWaterResponseIsEmpty:
# Suppress this exception. It's valid situation when data was not reported by EOW for the requested day
Expand All @@ -116,7 +122,7 @@ async def get_historical_data(
StatisticData(
start=row["start"],
sum=row["sum"],
)
),
)

return statistics
Loading

0 comments on commit 68f75e1

Please sign in to comment.