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

Add a Local To-do component #102627

Merged
merged 21 commits into from
Oct 25, 2023
Merged

Conversation

allenporter
Copy link
Contributor

@allenporter allenporter commented Oct 24, 2023

Proposed change

Add a local todo component based on rfc5545. This is similar to shopping list, but supports multiple entities, and stores the local data in ics format. This shares the same underlying library as local calendar that writes .ics files.

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
  • I have followed the perfect PR recommendations
  • 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.

To help with the load of incoming pull requests:

Comment on lines +20 to +24
async def async_load(self) -> str:
"""Load the calendar from disk."""
async with self._lock:
return await self._hass.async_add_executor_job(self._load)

Copy link
Contributor

Choose a reason for hiding this comment

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

We could use a decorator for this and async_store proxy functions

Copy link
Contributor Author

@allenporter allenporter Oct 24, 2023

Choose a reason for hiding this comment

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

Can you elaborate? I'm not familiar with the pattern you are referring to.

I the idea that i'd introduce a new decorator or that there is an existing one that I can use?

Copy link
Member

Choose a reason for hiding this comment

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

I think we can address this in a follow up, when we know more.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry for the delay, but somehow I missed your notification.
I have meant to introduce a new decorator for

async with self._lock:
    return await self._hass.async_add_executor_job(func)

Where func is either load or save.

The motivation was only the reduce duplicate code but no hurry for this small change :)

@home-assistant home-assistant bot marked this pull request as draft October 24, 2023 08:12
@home-assistant
Copy link

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

"""Convert a HomeAssistant TodoItem to an ical Todo."""
try:
return Todo.parse_obj(dataclasses.asdict(item, dict_factory=_todo_dict_factory))
except ValidationError as err:
Copy link
Member

Choose a reason for hiding this comment

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

This looks like the library isn't abstracted properly in this interface. I don't think the library user should know that the library uses pydantic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK -- we'll want to update local calendar as well then. Aside: i chose a different error to raise there given it was about input validation based on different review standards. But here, i'm not sure that the user can actually make this happen given format validation happening upstream on the input so its not expected

Just to be clear though: The way ical uses pydantic is not just an accidental leakage of an internal underlying detail -- the entirely library is built to intentionally make you use data objects that are pydantic data classes (e.g. Event and the examples https://allenporter.github.io/ical/ical.html#quickstart) are directly using the pydantic constructors and helpers as convenience methods rather than having multiple layers of wrapping. (The objects being used here are a BaseModel)

When designing the ical library pydantic didn't seem like it was going to randomly introduce an upgrade nightmare of changes given it was recommended by core team members as a defacto data serialization library, but lesson learned.

The smallest possible change is to add method with the same signature as parse_obj throws an ical specific exception. Larger changes could be changing the base objects to no longer by pydantic objects.

Happy to have any library design advice here given that context.

Copy link
Member

Choose a reason for hiding this comment

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

I think it's enough to replicate the method and throw an ical specific exception instead of a pydantic exception.

It's not a problem to return BaseModel objects to the user as the user doesn't need to care about the base class. It's just a typed object with attributes as far as the user needs to know.

Copy link
Member

Choose a reason for hiding this comment

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

I don't see any pydantic specific interfaces or mentions in the linked library docs. That looks good.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, sounds good. Let me fix this in a future library update, if that is alright with you, and i'll update local calendar too.

Copy link
Member

Choose a reason for hiding this comment

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

Good!

break
if found_item is None:
raise HomeAssistantError(
f"Item '{uid}' not found in todo list {self.entity_id}"
Copy link
Member

Choose a reason for hiding this comment

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

Is this an api error or a user error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently this is only called by the websocket so it would indicate the frontend is referencing a stale item (out of sync somehow with core?). If this were exposed as a service, it could mean the user is referencing an object that doesn't exist like racing with a delete, or it could mean a a typo/template error.

Let me know if another exception is more appropriate.

Copy link
Member

Choose a reason for hiding this comment

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

Let's keep it like this for now. If it would be a service the current convention is to raise ValueError for bad user input.

@allenporter allenporter marked this pull request as ready for review October 24, 2023 15:59
@MartinHjelmare MartinHjelmare self-assigned this Oct 25, 2023
@MartinHjelmare MartinHjelmare removed their assignment Oct 25, 2023
@MartinHjelmare MartinHjelmare dismissed edenhaus’s stale review October 25, 2023 11:20

Remaining comment can be addressed in a follow up

@MartinHjelmare MartinHjelmare merged commit 476e867 into home-assistant:dev Oct 25, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Oct 26, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants