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

Resolve traceback error when using variables in template triggers #77287

Merged
merged 5 commits into from Sep 29, 2022

Conversation

ehendrix23
Copy link
Contributor

Proposed change

Fix traceback error NoneType can't be used in await expression when using variables in template triggers.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

To help with the load of incoming pull requests:

@probot-home-assistant
Copy link

Hey there @PhracturedBlue, @tetienne, @home-assistant/core, mind taking a look at this pull request as it has been labeled with an integration (template) you are listed as a code owner for? Thanks!
(message by CodeOwnersMention)

@MartinHjelmare MartinHjelmare added this to Needs review in Dev Aug 27, 2022
@ehendrix23
Copy link
Contributor Author

Just doing a quick check on status. I have not seen these errors occur at all within my installation after implementing this fix and everything has been working fine related to it.

@frenck frenck added the smash Indicator this PR is close to finish for merging or closing label Sep 26, 2022
@emontnemery
Copy link
Contributor

emontnemery commented Sep 28, 2022

The problem is caused by a regression introduced by #68275
While this PR hides the problem in the template integration, the same problem exists also in websocket_api etc.

Instead of this, we should fix the _trigger_action_wrapper which was introduced by https://github.com/home-assistant/core/pull/68275 to handle either regular functions or coroutine functions, following this pattern:

def catch_log_exception(
func: Callable[..., Any], format_err: Callable[..., Any]
) -> Callable[..., None] | Callable[..., Coroutine[Any, Any, None]]:
"""Decorate a function func to catch and log exceptions.
If func is a coroutine function, a coroutine function will be returned.
If func is a callback, a callback will be returned.
"""
# Check for partials to properly determine if coroutine function
check_func = func
while isinstance(check_func, partial):
check_func = check_func.func
wrapper_func: Callable[..., None] | Callable[..., Coroutine[Any, Any, None]]
if asyncio.iscoroutinefunction(check_func):
async_func = cast(Callable[..., Coroutine[Any, Any, None]], func)
@wraps(async_func)
async def async_wrapper(*args: Any) -> None:
"""Catch and log exception."""
try:
await async_func(*args)
except Exception: # pylint: disable=broad-except
log_exception(format_err, *args)
wrapper_func = async_wrapper
else:
@wraps(func)
def wrapper(*args: Any) -> None:
"""Catch and log exception."""
try:
func(*args)
except Exception: # pylint: disable=broad-except
log_exception(format_err, *args)
if is_callback(check_func):
wrapper = callback(wrapper)
wrapper_func = wrapper
return wrapper_func

@ehendrix23
Copy link
Contributor Author

I've reverted the change I initially did within the template and updated _trigger_action_wrapper instead using the example provided.
Ran test on everything under components/template and everything under helpers/test_trigger without issues.
Updated my local copy for home assistant and no errors, also no errors as reported originally.

Let me know if these changes look good or further updates required. :-)

@emontnemery emontnemery added this to the 2022.10.0 milestone Sep 29, 2022
@emontnemery
Copy link
Contributor

emontnemery commented Sep 29, 2022

Thanks @ehendrix23 !

Unfortunately, the more complicated solution I linked to is needed to avoid returning a coroutine function when wrapping a regular function. I updated the PR accordingly + added a test.

It would be helpful if you can verify this also solves your problem.

Comment on lines +118 to +121
# Check for partials to properly determine if coroutine function
check_func = action
while isinstance(check_func, functools.partial):
check_func = check_func.func
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed if you use inspect.iscoroutinefunction

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's not needed for inspect.iscoroutinefunction, it's needed for is_callback.
If we teach is_callback about unwinding partials we can indeed drop it, that's for another PR though.

Dev automation moved this from Needs review to Reviewer approved Sep 29, 2022
@ehendrix23
Copy link
Contributor Author

Thanks. I didn't think the more complex one was required but I guess I was wrong. :-)

Tested on my local instance and issue is not occurring. So looks like this is working.

Saw the comment from balloob. And you acknowledging but not sure if anything further is required as it looks like there was a force push but I don't see any difference in that section. :-)

@emontnemery
Copy link
Contributor

emontnemery commented Sep 29, 2022

@ehendrix23 right, I first implemented @balloob's suggestion, then I realized we need the unwinding also for is_partial so I reverted it. Sorry about the force push, I should have done a revert commit instead.

@balloob balloob merged commit ba6a81c into home-assistant:dev Sep 29, 2022
Dev automation moved this from Reviewer approved to Done Sep 29, 2022
balloob pushed a commit that referenced this pull request Sep 29, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Sep 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bugfix cherry-picked cla-signed integration: template small-pr PRs with less than 30 lines. smash Indicator this PR is close to finish for merging or closing
Projects
Dev
  
Done
Development

Successfully merging this pull request may close these issues.

Errors while using trigger variables with trigger-based template entities.
6 participants