Skip to content

Commit

Permalink
23.09 (#412)
Browse files Browse the repository at this point in the history
  • Loading branch information
spacemanspiff2007 authored Sep 12, 2023
1 parent ab962ef commit 979b80a
Show file tree
Hide file tree
Showing 207 changed files with 4,682 additions and 2,618 deletions.
5 changes: 4 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ exclude =
tests/conftest.py,

# the interfaces will throw unused imports
src/HABApp/openhab/interface.py,
src/HABApp/openhab/connection_handler/*,
src/HABApp/openhab/interface_sync.py,
src/HABApp/openhab/interface_async.py,
src/HABApp/mqtt/interface_sync.py,
src/HABApp/mqtt/interface_async.py,
src/HABApp/rule/interfaces/http_interface.py,
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ repos:


- repo: https://github.com/PyCQA/flake8
rev: '6.0.0'
rev: '6.1.0'
hooks:
- id: flake8
# additional_dependencies:
Expand All @@ -35,7 +35,7 @@ repos:


- repo: https://github.com/asottile/pyupgrade
rev: v3.3.1
rev: v3.10.1
hooks:
- id: pyupgrade
args: ["--py38-plus"]
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10 as buildimage
FROM python:3.11 as buildimage

COPY . /tmp/app_install

Expand All @@ -7,7 +7,7 @@ RUN set -eux; \
cd /tmp/app_install; \
pip wheel --wheel-dir=/root/wheels .

FROM python:3.10
FROM python:3.11

COPY --from=buildimage /root/wheels /root/wheels
COPY container/entrypoint.sh /entrypoint.sh
Expand Down
14 changes: 7 additions & 7 deletions docs/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -175,20 +175,20 @@ Finally, define the HABApp functions to indirectly invoke the actions:
def play_local_audio_file(sink_name: str, file_location: str):
""" Plays a local audio file on the given audio sink. """
HABApp.openhab.interface.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface.send_command(ACTION_AUDIO_LOCAL_FILE_LOCATION_ITEM_NAME, file_location)
HABApp.openhab.interface_sync.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface_sync.send_command(ACTION_AUDIO_LOCAL_FILE_LOCATION_ITEM_NAME, file_location)
def play_stream_url(sink_name: str, url: str):
""" Plays a stream URL on the given audio sink. """
HABApp.openhab.interface.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface.send_command(ACTION_AUDIO_STREAM_URL_ITEM_NAME, url)
HABApp.openhab.interface_sync.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface_sync.send_command(ACTION_AUDIO_STREAM_URL_ITEM_NAME, url)
def play_text_to_speech_message(sink_name: str, tts: str):
""" Plays a text to speech message on the given audio sink. """
HABApp.openhab.interface.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface.send_command(ACTION_TEXT_TO_SPEECH_MESSAGE_ITEM_NAME, tts)
HABApp.openhab.interface_sync.send_command(ACTION_AUDIO_SINK_ITEM_NAME, sink_name)
HABApp.openhab.interface_sync.send_command(ACTION_TEXT_TO_SPEECH_MESSAGE_ITEM_NAME, tts)
Mocking openHAB items and events for tests
Expand All @@ -215,7 +215,7 @@ Add an openHAB mock item to the item registry
item = SwitchItem('my_switch', 'ON')
HABApp.core.Items.add_item(item)

Remove the mock item from the registry
Remove the mock item from the registry:

.. exec_code::
:hide_output:
Expand Down
16 changes: 8 additions & 8 deletions docs/class_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,63 +33,63 @@ Scheduler
OneTimeJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.OneTimeJob
.. autoclass:: eascheduler.scheduler_view.OneTimeJob
:members:
:inherited-members:
:member-order: groupwise

CountdownJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.CountdownJob
.. autoclass:: eascheduler.scheduler_view.CountdownJob
:members:
:inherited-members:
:member-order: groupwise

ReoccurringJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.ReoccurringJob
.. autoclass:: eascheduler.scheduler_view.ReoccurringJob
:members:
:inherited-members:
:member-order: groupwise

DayOfWeekJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.DayOfWeekJob
.. autoclass:: eascheduler.scheduler_view.DayOfWeekJob
:members:
:inherited-members:
:member-order: groupwise

DawnJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.DawnJob
.. autoclass:: eascheduler.scheduler_view.DawnJob
:members:
:inherited-members:
:member-order: groupwise

SunriseJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.SunriseJob
.. autoclass:: eascheduler.scheduler_view.SunriseJob
:members:
:inherited-members:
:member-order: groupwise

SunsetJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.SunsetJob
.. autoclass:: eascheduler.scheduler_view.SunsetJob
:members:
:inherited-members:
:member-order: groupwise

DuskJob
""""""""""""""""""""""""""""""""""""""

.. autoclass:: eascheduler.jobs.DuskJob
.. autoclass:: eascheduler.scheduler_view.DuskJob
:members:
:inherited-members:
:member-order: groupwise
56 changes: 48 additions & 8 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,41 @@
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config

# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import logging
import os
import re
import sys

import sphinx
from docutils.nodes import Text, Node
from sphinx.addnodes import desc_signature

IS_RTD_BUILD = os.environ.get('READTHEDOCS', '-').lower() == 'true'
IS_CI = os.environ.get('CI', '-') == 'true'

# required for autodoc

# https://www.sphinx-doc.org/en/master/extdev/logging.html
sphinx_logger = sphinx.util.logging.getLogger('post')
logger_lvl = logging.DEBUG if IS_RTD_BUILD or IS_CI else logging.INFO # set level to DEBUG for CI


def log(msg: str):
sphinx_logger.log(logger_lvl, f'[POST] {msg:s}')


# -- Path setup --------------------------------------------------------------

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
sys.path.insert(0, os.path.join(os.path.abspath('..'), 'src'))

# -- Project information -----------------------------------------------------

project = 'HABApp'
copyright = '2022, spacemanspiff2007'
copyright = '2023, spacemanspiff2007'
author = 'spacemanspiff2007'

# The short X.Y version
Expand Down Expand Up @@ -248,6 +264,8 @@
regex_path = re.compile(r"^\w+Path\('([^']+)'\)")
assert regex_path.search('WindowsPath(\'lib\')').group(1) == 'lib'

regex_item = re.compile(r'(class \w+Item)\(.+\)')

# nicer type values
TYPE_REPLACEMENTS = {
'_MissingType.MISSING': '<MISSING>',
Expand All @@ -274,9 +292,16 @@ def replace_node_contents(node: Node):

replacement = TYPE_REPLACEMENTS.get(node_text)

# https://www.sphinx-doc.org/en/master/extdev/nodes.html
if isinstance(node, desc_signature) and node.attributes.get('fullname', '').endswith('Item'):
log(f'Removing constructor signature of {", ".join(node.attributes["ids"])}')
assert len(node.children) == 3
signature_node = node.children[2]
signature_node.children = []

# Replace default value
# WindowsPath('config') -> 'config'
if node_text.endswith(')') and (m := regex_path.search(node_text)) is not None:
if replacement is None and node_text.endswith(')') and (m := regex_path.search(node_text)) is not None:
replacement = f"'{m.group(1)}'"

# # Type hints
Expand Down Expand Up @@ -305,3 +330,18 @@ def transform_desc(app, domain, objtype: str, contentnode):

def setup(app):
app.connect('object-description-transform', transform_desc)


# -- Options for intersphinx -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html
if IS_RTD_BUILD:
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None)
}


# Don't show warnings for missing python references since these are created via intersphinx during the RTD build
if not IS_RTD_BUILD:
nitpick_ignore_regex.append(
(re.compile(r'py:data|py:class'), re.compile(r'typing\..+'))
)
3 changes: 3 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ Example
# Useful for testing rules from another machine.
It's possible to use environment variables and files (e.g. docker secrets) in the configuration.
See `the easyconfig documentation <https://easyconfig.readthedocs.io>`_ for the exact syntax and examples.


Configuration Reference
======================================
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ Example Dockerfile installing scipy, pandas and numpy libraries:
# Install required build dependencies (Optional)
apt-get update; \
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
build-essentials; \
build-essential; \
# Prepare python packages
pip3 wheel \
--wheel-dir=/root/wheels \
Expand Down
45 changes: 44 additions & 1 deletion docs/interface_openhab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ It can be enabled through the gui in ``settings`` -> ``API Security`` -> ``Allow
openHAB item types
**************************************

.. |oh_item_desc_name| replace:: Item name
.. |oh_item_desc_value| replace:: Current item value (or state in openHAB wording)
.. |oh_item_desc_label| replace:: Item label or ``None`` if not configured
.. |oh_item_desc_tags| replace:: Item tags
.. |oh_item_desc_group| replace:: The groups the item is in
.. |oh_item_desc_metadata| replace:: Item metadata


Description and example
======================================
Items that are created from openHAB inherit all from :class:`~HABApp.openHAB.items.OpenhabItem` and
Expand Down Expand Up @@ -233,7 +241,7 @@ or through an ``OpenhabItem``.

Function parameters
======================================
.. automodule:: HABApp.openhab.interface
.. automodule:: HABApp.openhab.interface_sync
:members:
:imported-members:

Expand Down Expand Up @@ -466,6 +474,41 @@ ItemCommandEventFilter
:inherited-members:
:member-order: groupwise

**************************************
Transformations
**************************************

From openHAB 4 on it's possible to use the existing transformations in HABApp.
Transformations are loaded every time when HABApp connects to openHAB.
OpenHAB does not issue an event when the transformations change so in order for HABApp to
pick up the changes either HABApp or openHAB has to be restarted.
Available transformations are logged on connect.

map
======================================
The `map transformation <https://www.openhab.org/addons/transformations/map/>`_ is returned as a dict.
If the map transformation is defined with a default the default is used accordingly.

Example:

.. exec_code::
hide_output

# ------------ hide: start ------------
from HABApp.openhab.transformations._map.registry import MAP_REGISTRY
MAP_REGISTRY.objs['test.map'] = {'test_key': 'test_value'}, None
MAP_REGISTRY.objs['numbers.map'] = {1: 'test number meaning'}, None

# ------------ hide: stop -------------
from HABApp.openhab import transformations

TEST_MAP = transformations.map['test.map'] # load the transformation, can be used anywhere
print(TEST_MAP['test_key']) # It's a normal dict with keys as str and values as str

# if all keys or values are numbers they are automatically casted to an int
NUMBERS = transformations.map['numbers.map']
print(NUMBERS[1]) # Note that the key is an int


**************************************
Textual thing configuration
Expand Down
8 changes: 4 additions & 4 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Packages required to build the documentation
sphinx == 6.2.1
sphinx-autodoc-typehints == 1.23.0
sphinx_rtd_theme == 1.2.0
sphinx == 7.2.5
sphinx-autodoc-typehints == 1.24.0
sphinx_rtd_theme == 1.3.0
sphinx-exec-code == 0.10
autodoc_pydantic == 1.8.0
autodoc_pydantic == 2.0.1
sphinx-copybutton == 0.5.2
4 changes: 2 additions & 2 deletions docs/util.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ The lights will only turn on after 4 and before 8 and two movement sensors are u
from datetime import time

from HABApp import Rule
from HABApp.core.events import ValueChangeEvent
from HABApp.core.events import ValueChangeEventFilter
from HABApp.openhab.items import SwitchItem, NumberItem
from HABApp.util import EventListenerGroup

Expand All @@ -216,7 +216,7 @@ The lights will only turn on after 4 and before 8 and two movement sensors are u

# use a list of items which will be subscribed with the same callback and event
self.listeners = EventListenerGroup().add_listener(
[self.sensor_move_1, self.sensor_move_2], self.sensor_changed, ValueChangeEvent)
[self.sensor_move_1, self.sensor_move_2], self.sensor_changed, ValueChangeEventFilter())

self.run.on_every_day(time(4), self.listen_sensors)
self.run.on_every_day(time(8), self.sensors_cancel)
Expand Down
16 changes: 14 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/habapp)

![PyPI](https://img.shields.io/pypi/v/HABapp)
[![Downloads](https://pepy.tech/badge/habapp/month)](https://pepy.tech/project/habapp)
[![Downloads](https://static.pepy.tech/badge/habapp/month)](https://pepy.tech/project/habapp)
![Docker Image Version (latest by date)](https://img.shields.io/docker/v/spacemanspiff2007/habapp?label=docker)
![Docker Pulls](https://img.shields.io/docker/pulls/spacemanspiff2007/habapp)


_Easy automation with MQTT and/or openHAB_


Expand Down Expand Up @@ -128,6 +127,19 @@ MyOpenhabRule()
```

# Changelog
#### 23.09.0 (2023-XX-XX)
- Switched version number scheme to CalVer (Calendar Versioning): ``YEAR.MONTH.COUNTER``
- Fail fast when a value instead of a callback is passed to the event listener / scheduler
- Completely removed types and type hints from traceback
- Completely reworked connection logic for openHAB and mqtt
- Added support for transformations
- Updated dependencies:
- Improved performance
- Support for docker secrets and environment variables in the config file
- Support sending scheduler datetimes to an item
- Search in the docs finally works again
- Updated dependencies

#### 1.1.2 (2023-06-19)
- Re-added `ItemStateEventFilter`
- Improved parsing of `DateTime` values
Expand Down
Loading

0 comments on commit 979b80a

Please sign in to comment.